Objects and Data Structures and Error Handling in Clean Code
In this article I will be talking about Chapters 6 and 7 from Robert Martin’s Clean Code book. This practices of clean code will help us developers to polish our programming skills and code quality.
Don’t expose all the implementation of a class
Hiding implementations is about abstractions. A class it’s not all about getters and setters. It exposes abstract interfaces that allow us to manipulate the data without having to know the implementation.
Objects and Data Structures are not the same
Objects hide their data behind abstractions and expose functions that operate on that data. Data structure expose their data and have no meaningful functions.
Procedural Code and Object Oriented Code
It makes it easy to add new functions without changing the existing data structures. Object Oriented code, on the other hand, makes it easy to add new classes without changing existing functions. makes it easy to add new functions without changing the existing data structures. Object Oriented code, on the other hand, makes it easy to add new classes without changing existing functions. Mature programmers know that the idea of everything is an object is a myth and in reality there are some times where you really want and need a simple data structure with procedures.
The Law of Demeter
It says that a module should not know about the innards of the objects it manipulates. This law also states 4 things that a method ‘f’ of a class ‘C’ can do:
- An object created by f
- An object passed as an argument to f
- An object held in an instance variable of C
This concept is used to describe when you call a lot of methods in a single line that each method depend on the result of the other method. It is called this way because it looks like a bunch of coupled train cars and it is not a good practice. A method should not invoke methods on objects that are returned by any of the allowed functions, talk to friends, not strangers.
Watch out for hybrids
Hybrids are the worst of both worlds, they are half object and half data structure but with all the negatives of each. They are hard to add functions and hard to add new data structures. When a hybrid exists is a bad sign in that code, it tells us that it has confusing design.
Data Transfer Objects
They are a class with public variables and no functions. These are used mainly to communicate with databases or parsing messages. They are very useful and they come in many forms. Active Record is one example of a DTO. They area data structures with public variables and have navigational methods like ‘save’ and ‘find’. They typically are direct translations from database tables, or other data sources. DTO’s should live by themselves, because sometimes programmers implement business rule methods in them and it creates a hybrid. That’s a big no no.
Objects and Data Structures, when to use them?
In any given system we will sometimes want the flexibility to add new data types, and so we prefer objects for that part of the system. Other times we will want the flexibility to add new behaviors, and so in that part of the system we prefer data types and procedures.
This topic is crucial in clean code. We all have to do error handling to make a better user experience but also to help us developers. Error handling is really important, but if it obscures logic, something’s wrong.
Return exceptions instead of a return code
In the past error handling was limited and developers returned a code that later will be checked by its code and see what the error was. But this code list is really long and it takes time to remember that a certain code meant. We can now return an exception and the error, this makes it easier for everyone to see the error and know what to do with it.
Don’t just return an exception
When returning an exception you should also provide a context of the error, why it happened, where it happened, source, location, etc. Mention the operation that failed and the type of failure.
They are very useful because you can wrap third-party APIs. This is a really good practice because you can change the API without much penalty, because you minimize the dependencies upon it. Also, you are not tied to a specific API design choice.
Special Case Pattern
When you follow the tips mentioned above, your code will be very good at detecting errors and handling them correctly. No error will escape and it will make it pretty easy to identify anything that comes up, but your code will start to look like a clean unadorned algorithm and sometimes we want to avoid complex code and make it look cleaner and more simple. There’s a way we can do this by using the Special Case Pattern. You create a class or configure an object so that it handles a special case for you.
Never return Null
When we return null we are basically creating work for ourselves because when that breaks and we receive a message telling us that it returned null, we will have no idea what happened. It’s better to return a special case object when something like this happens or also an exception to get an idea of what went wrong.
Never pass Null
Returning null from methods is bad, but passing null into methods is worse, unless you are working with an API that expects this. This is pretty difficult to avoid but it can be done. This will also help you in the long because when something breaks and you in the parameters a null then it means something is not right and you will have fewer careless mistakes.
Clean code ir readable, but it must also be robust
These goals are not conflicting, we can write clean code and also robust if we see error handling as a separate concern, it is basically independent of the main logic.
I hope this helps you to improve your definitions of objects and data structures as well as the error handling which is a big factor in software development and that not many people emphasize it. As always feel free to contact me if you have any doubt!