#begin

 

But alright, let’s continue with a new section which describes the concept of Orthogonality.
So what again does Orthogonality mean again? It’s one of these words that’s always thrown around in computer science lectures and literature. Well orthogonality in a computer science context means a kinds of independence and decoupling. Two or more things are orthogonal when changes in one do not trigger changes in the other. So for example, in a well designed game, changes to your gameplay do not trigger changes to web requests or database. Same goes for UI, when you change the user interface that won’t trigger changes in your gameplay code. So be weary with using monobehaviours as domain level objects.

So, have you worked on a non-orthogonal system? If you have worked in IT for a while, you probably have. You change something here, and something else totally unrelated explodes. Yes, sounds all too familiar to me.

So what are the benefits of orthogonality. Well first of all they are less complex than non-orthogonal systems since orthogonality eliminates the effects between unrelated things. A nice quote here in the book says the following; “in a non-orthogonal system, so a system which is highly interdependent, there is no such things as an local fix”, for a bug for example. Let that sink in for a minute because this is a really important concept in computer science.

So, having explained this, you probably see how an orthogonal system has many benefits. But let’s take a look at what these benefits are and discuss them.

So first of all, when a system is orthogonal, you will gain some productivity. Changes you do to a system, whether it’s a bug fix or a new feature, are localized. This means that not just development time is reduced, but also testing and maybe even compiling and deployment. Another reason why your productivity might increase is that since changes are localized in a specific area, you can get away with only small changes instead of a large change in many files in the case of a non-orthogonal system.

Orthogonal system also promote and allow for reuse of components. If components have well-defined responsibilities and are loosely coupled you can reuse them in different contexts as well.
This is very, very useful. It’s a really important concept in the context of computer science. Prof. Ousterhout also talks about this in his book A Philosophy of Software Design. We discussed this to great lengths, so go back to some of the previous blogs if you want to hear a deep dive into all of this stuff.

An orthogonal system will also bring the benefit of reducing risk in software development. But how you might ask? Well since orthogonal systems are loosely coupled and as we talked about just a minute ago, changes are localized to certain parts of the code, or components, bugs or faults are as well. And in the book the authors have something funny to say about this so I will quote that directly: “If a module is sick, it is less likely to spread the symptoms around the rest of the system. It is also easier to slice it out and transplant in something new and healthy”. Isn’t that a funny analogy? And it’s totally right. If bugs and faults are localized in some component you can really quickly make a fix for them in a single spot, or simply replace the entire component with something that does work.

I will give you guys and gals a nice example of something we ran into in our Unity application just a couple of months ago. So for an app we are developing we needed some form of efficient data storage. So we set out and implement a local Sqlite data base that will be created by the client on windows, mac, android and iOS devices. This all worked perfectly fine until our database started to grow and queries took a long time. Also considering the fact that we do some multi-threading, we ran into issues with transactions. All the code for database access is isolated in dedicated components which simply expose functions that return domain level objects. So SQL tables, rows and columns never leak to the outside. Remember Prof. Ousterhout’s concepts of information leakage and hiding here by the way.

But the database was growing large and queries started to take a long time. We solved this issue by simply ripping the entire database out, and replacing it with a NoSQL solution. We choose LiteDB, which is a document database, similar to MongoDB. This means we did not have to do complicated joins etc. since we now could simply dump a JSON object in there which kept all the references in tact. For us, this was a nice solution, it might not be for you. For example, the database just kept local copies of things that were available from our backend anyway. So deleting it did not impact production clients, or customers. But if there was other data in there that was only used locally, there could have been major consequences. But we were in this unique position to just replace it altogether.

I think this is a very nice example of how orthogonality helps creating flexible systems. We did not want to dive into boring SQL query optimizations and simply ripped out the entire database and replaced it. This is how orthogonal systems are supposed to work.

This also makes systems less fragile. Again, since functionality including bugs and faults are localized you can simply make a change in a local area to fix things. Another benefit of this is that, these loosely coupled components are easily tested. I will sound like a broken record but, since things a loosely coupled you can easily mock things out or inject testable dependencies into your orthogonal system. As we have discussed in great length in many blogs here, testing is of great importance to software design and development. Tests allow you to go faster, not slower… as the common belief still is.

Other benefits of orthogonal systems are related to project teams. I think that some of you might have experienced this, so let me explain. If you work in some company with multiple project or product teams you might have noticed that some teams are able to create features quickly while other teams are struggling to get out of each others way. This is an orthogonality issue. I’ll quote the book now since they explain it nicely: “When teams are organized with lots of overlap, members are confused about responsibilities. Every change needs a meeting of the entire team, because anyone of them might be affected”. This is what we call Conway’s Law; The structure or software design will reflect the organizational structure. So if you work in a large company, it is very useful to split teams according to known components. I will remind you that components might be total vertical slices, so from front-end, to business logic, to database. Jeff Bezos’ famous memo said that teams should not be larger than one you can feed with two pizza’s. And such a team maintains the front-end code, the business logic and the database.

This is another example how a massively distributed company organization and culture reflects the software design and architecture, so Conway’s law. I recently finished reading the book I was talking about in a previous blog in this series called Modern Software Development by Dave Farley. I fondly remember a quote from that book about micro services and it goes something like this: Micro services are for scaling the organization, not the system per-see. You could achieve similar scalability with other architectures. But let’s get back to the book, I don’t want to drift off too far.

Next up the talk about some implications of orthogonal systems. However I think we have discussed this already. They talk about how orthogonal systems are created by organizing decoupled components in some modular way. This feels like common sense to me but I think that it is still often a problem in Unity3D. Ask yourself, how much business logic do you actually write in your classes that inherit from monobehaviour or VisualElement. I bet it’s a lot. So, changing your UI i.e. gameobjects or components impacts your business logic. So this is a non-orthogonal system.

People often tell me Ruben, stop whining, we are Unity3D devs, we choose Unity3D for a reason and thus we will accept our dependence on Unity3D. But, that’s not the point. The point is you are mixing responsibilities of your UI and Business logic. If your code breaks just because you decide to organize your prefab slightly different, that’s bad. Note that I said, your code, and not your game because, changing the structure of prefabs might definitely break your game, without breaking your code. Like, if you add colliders on things you did not have before.

So to battle non-orthogonality the authors provide us with three tips. First of all keep your code decoupled… duhh. Write independent modular components that do not depend on other components when they do not have to. Make sure these components don’t leak information and hide their internals. As Uncle Bob and Prof. Ousterhout also said, don’t expose the innards of a module through it’s public interface. Always make use of DTO objects. Just make sure those DTO objects don’t impact your performance. If you are generating 100’s if not 1000’s of DTO objects in update loops of your components that will slow down your game. So search for a different solution in that case. The authors specifically mention the Law of Demeter again. Remember that law? It’s the law that says that you should only talk to your direct references, and not to strangers i.e. references of references. So do not call Player.Weapon.Fire. But make some function like Player.Attack() which attacks with the selected weapon, whatever that might be. This way you encapsulate the behaviour and you adhere to the Law of Demeter.

The next tip David and Andrew give is that you should avoid global data. Every time your code references global data, you couple your code to it and share that data. This includes your singletons as well! This is exactly why there’s so much hate against singletons. Sharing this data can be a really big problem once you start to add multi-threading into the mix or when you need to split your code in dll’s or packages. They mention Singletons specifically in the book as well with the following warning: “Be careful with singletons – they can also lead to unnecessary linkage”. And remember, this book is from 1999. So singletons being a cause of problems has been known for a while. I don’t want to say never, ever use them, they can be very useful, but use them with caution.

And the third and last tip they give in regard to maintain orthogonality of your system is to avoid similar functions. Yes, we already spend a lot of time talking about duplication and the DRY principle. I just want to repeat quickly that duplicated code is often a symptom of structural problems and you should refactor when you see it.

Ok, so the last sub sections related to orthogonality mention testing and documentation. We’ve talked about how orthogonal systems are easier to test since you can test components in isolation and are able to inject testable dependencies like mocks. As with duplication and the DRY principle, I wont explain orthogonality in testing again since we already did. If you do want some more information about that, search for blogs that explain testing in the context of Clean Code and A Philosophy of Software Design on this site. We’ve talked extensively about the topic of testing.

Then about documentation. They did not mention it until now, but it seems kind of obvious doesn’t it. If you have an orthogonal system, you have well defined components that are modular. It seems pretty straightforward that writing documentation for these components is fairly “easy” since you can focus on one topic. You don’t need to talk about dependencies or inter dependencies much, because they don’t exist. There might be some publicly exposed interfaces other components should inherit, but these will not impact the documentation of the component you are describing. So if you find yourself documenting all kinds of references and dependencies, that could be a sign of a non-orthogonal system. That is a really nice observation I think.

But I think that’s enough for today.

De balle!

#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!