#begin 

Today we are going to look at the next chapter of the Clean Code book by Robert C. Martin. In the previous blogs of this series we discussed the first 7 chapters of the book. Yeah we have come pretty far already. If you have not read them, don’t forget to check them out as well!

So the next chapter is about how to properly integrate with 3th-party code. I think it is particularly interesting for him to put such a chapter in the book. I mean, when you think about clean code, you often do not consider 3th-party code right? So having a short chapter dedicated to this is really nice. And 3th-party code can be many things like code you get from github, for free, or some API on the web, or some webservice you need to spend your money on, or even code from the team next door. You want to have a clean interface into that code and create as less dependencies on it as you can. With dependencies I mean, source code dependencies. You will always keep the run-time dependencies but you can avoid source code dependencies. And that’s not the only thing of course, you also want to have a nice interface to talk to. I mean if the 3th-party interface is unclear and badly named it will create confusion on your side. So in the next section we will discuss some of the practices how to deal with these kinds of things. Although Uncle bob will not dive too deeply into turning source code dependencies into run-time dependencies in this book. He essentially wrote an entire book about this called: Clean Architecture. But that’s not the subject of this blog so let’s continue with chapter 8, boundaries.

 

Boundaries

So first of all he starts of by saying that you should always build like a facade around a 3h-party package or component. Second, something he does not mention himself, but more an observation on my end, use DTO objects for communication with these api’s if needed. Remember DTO’s? We discussed them a bit earlier and they are specifically designed for this purpose. Another great piece of advise he gives is that you should wrap any specific types that are returned by the 3th-party code into a type of your own or else you end up spreading the dependency of that library or package all throughout your code base.

So what he’s saying here essentially is that you should wrap a 3th-party API in a facade class, and wrap or convert any special types returned by the package into some business object of your own to break that dependency as soon as you can so you do not spread it through your codebase. So I think this is great advise. I always setup some facade class to talk to 3th-party stuff because it is really easy to well, encapsulate it, hide it and maybe at some point replace it. You just change the implementation of that facade class and you’re done. And oh, if you do not know what a facade class is it’s a design pattern which aims to simplify an interface by wrapping it into a single nice object for you to use. If this does not make sense google it for a second. I fondly remember the example given in a book from the Head First series, Head First design patterns. The book describes the facade in a really simple example and that is; a universal remote control which can access your tv, dvd player, sound system and maybe some of stuff as well. So the remote control is a facade to all the other devices. If you know how to operate and work with the facade you don’t need to know all the intricate details of your tv, dvd player and sound system. I always liked this particular example maybe that’s why I still remember it although I read that book many years ago, like 8 to 10 years or so.

So create a facade around 3th-party code to hide implementation details and nicely encapsulate things so they don’t leak into your codebase or confuse the caller of the code.

Next, Uncle bob talks about a subject that sounds really nice on paper, but in practice is difficult, especially in a Unity3D context and that is how to explore 3th-party code by Unit Testing. So what he means is that you can write unit tests agains a 3th-party API to find out what exactly the code does. But I think we all know how difficult and horrible it is to test some random guys code from the AssetStore for example. A lot of the code on the AssetStore is heavily denpendent on the Unity API and thus difficult to test. And you should also consider the fact that a great deal of the code that is available on the AssetStore might not be, well, up to your standards. Trust me, I’ve bought many assets on the store and often have I been disappointed by the overall code quality. Don’t get me wrong, the code often works but if there’s bugs it’s really difficult to work with. And on the other hand, there are also many, really nicely written packages on the AssetStore as well. But I bet, that if you have some experience with buying assets in the store, you probably know of some package that wasn’t worth it and you should have written yourself.

But we were talking about how Uncle bob likes to explore 3th-party code by covering the API with Unit-Tests. The example is the book is a funny one; it’s about “Learning Log4j”. So he has about 2 pages in the book on how he would use unit-tests as a means of exploration. And I’ve tried this approach a couple of times and it works great if the package you are targetting is just code, and no fancy physics based asset package. So, if you have some code that simply does some transformations you can easily explore the code this way and increase your test coverage. But then again, it does not work well with code that does fancy unity things. Because that’s just really difficult to test and I’m not sure it’s worth the effort to find lots of workaround testing hacks to tests certain things.

I remember doing a hobby project where I set out to create a simple 2D game fully Test-Driven. This was my first time of building a game in unity3D in a Test Driven Development workflow, also known as TDD. And if you don’t know what Test Driven Development is, it is a practice where you first write a unit test, and then write some production code and make it work. So you always have a failing test before you actually write any working code. I’m not going to much into details about TDD since it’s a nice subject for another blog. But in my project I also used to run, so called run-time tests which are tests in Unity3d where you can start a scene, do some tests and cleanup the scene. This way you can test some Awake and Start logic for example. I quickly found out that if you use run-time tests you need to find some clever testing hacks to test certain behaviour. I can’t really remember them from the top of my head and if you like I can look into it. So let me know if you think that is interesting and I’ll cover that somewhere else on this blog.

But let’s continue with clean code again. Next Uncle bob still talks about how learning a 3th-party api through unit tests is helpful since you can increase not just your own understanding of the code, also that of your team. And, again, he is right but there are nuances, which we already talked about. He also makes a nice observation that if you cover an API with unit-tests you can really easily upgrade it and make sure it works. Just, do the update and run the tests right? Wouldn’t that be awesome? It’s the perfect world isn’t it. Just hope the asset did not have any breaking changes.. right? So tests that cover 3th-party code might ease migration.

Next he talks about how you can also use these tests to cover what he calls unkown code. And what he means here is that there’s sometimes parts of the code that are pure magic to us. You have a lot of knowledge about the code and the problem you are solving, but at some point, that knowledge might end and drop off the edge. Sometimes what is on the other side of that boundary is unknowable, at least for now. And sometimes you do not even want to look past that boundary because it’s not your problem. A simple example would be the Newtonsoft Json Serializer we often use in Unity3D. It’s a massive, very cool and stable library for Json encoding. This is such a boundary I do not want to dive into and preferably would have remain to be unknown. Just some DLL you throw in your plugins folder and you call it to serialize and deserialize stuff. Well, it works very will in 99% of the cases until you need to do some custom JSON things or make sure the performance it high. Then you need to dive into it and that boundary is no longer unknown. You could write unit test for this but I these particular examples; writing unit tests against custom serialization is easy, since you know the in and output. But writing tests against the second problem, which was about trying to increase the performance is pretty difficult. How are we going to write proper unit-tests that check memory allocations and garbage collection for example? Is that even something we want to unit tests? I don’t think so.

So as I said, there are nuances with just covering 3th-party api’s with unit tests. We did not even cover the fact, that some API’s are cloud based. So are you now going to write unit-tests that run across the network through HTTP requests? What if your internet fails during your CI pipeline, will that cause the pipeline to fail then? I mean, the internet is out, it has nothing to do with the test itself. But then again, if you can cover a 3th-party api with tests easily it might be a really valuable thing to do since you create not just an understanding for yourself, but also for your team. Plus your unit tests might come in handy when migrating the library to a new version. Just upgrade it and run these darn tests again.

Alright, that’s another chapter covered! We just discussed the eight chapter in the book; Boundaries. We talked about how boundaries are an important conceptual separation between code and how to make sure your own code is decoupled from 3th-party code. We also discussed how to explore 3th-party code by means of tests, with all pro’s and con’s. 

So that’s it for the eigth part of this blog. The next blog will cover the ninth chapter of the book called unit tests. If you have any comments about this blog, please leave them in the comment section.

Thanks for reading, and I hope to see you next time too!

#end

01010010 01110101 01100010 01100101 01101110.

Hey, sorry to bother you but you can subscribe to my blog here.

Never miss a blog post!

You have Successfully Subscribed!