What makes good code (5/7)

João Bertolino
5 min readSep 21, 2020

--

Readability

Now we are finally talking about readability. The first thing that pops up in this subject is the need for a code standard. It means that all programmers in the team should make code in a standardized way, for example, the way they name methods and how you differentiate local variables from member properties and so on. These standards are related to the language that is being used and the preferences of the team. But there is another important aspect of naming that goes beyond standardization.

When reading code, we have expectations of what we should find, and as soon as we meet these expectations, we move to another topic or else we investigate further. When a code has something that should have a particular behavior, but has a different behavior, it becomes hard to identify the problem. For example, we expect to have costless access to properties in an Object. Let us use the example of the photo in our User class. We might have a property user.ProfileImage and we expected that it would return the bytes of the image that is loaded in memory. But the programmer who wrote the code did not want to fetch the data when creating the object, he/she wanted a simple way to retrieve the photo. So, when you call this property it is loading the photo data from a data source. This is a bad decision because loading data should be an asynchronous operation and the programmers that use this code might call this property multiple times assuming this is a costless call. In this case, a more elegant solution would be to have a method user.LoadProfileImage() that returns a reference to an asynchronous operation. In that case, a simple change in name and return value makes all the difference in the understanding of the code without the need of any documentation. You should give descriptive names to all entities in your code. This will make the code more readable and programmers will have a better life quality dealing with it.

Another important topic of readability is comments. Comments are useful only when they are necessary. If we make a parallel with real life, it’s annoying to hear comments of everything or the obvious, comments must bring useful information. There are two kinds of comments: member comments that go to the documentation and comments inside the functions. If you are making a public API it is good to have comments in the public methods so you can have the opportunity to teach new users of your API on how to use it. For the private members, using a descriptive name should be the priority, and a comment should be used only if it has a necessary unintuitive behavior. This may change depending on the code standard or the company that you are working for. They may have a different view, so it’s better to follow their pattern.

Comments inside functions can help to avoid unnecessary refactors. Sometimes the business logic is complicated and other programmers or you in the future might want to refactor that to a simpler solution. It will take an refactor attempt so you can realize the design decision. So, if you place some comments before an awkward but necessary decision, you could save some time and make a more readable code. One important tip to avoid a lot of comments and maintain the expressiveness of your code is to make functions for some chunk of logic and name this function in a way that explains what is happening inside even if this function will not be used anywhere else in your code.

Error handling is an especially important part of good codes. When debugging a code, the more precise error messages your code provides, the faster will be to find the bug. Good code provides error messages consistent with the real problem and it must show the first time that something not expected happens, so you can spot the source of the problem and not a consequence of a previous problem. Sometimes a function receives an unexpected parameter that may cause a problem later, but for convenience you just handle that special case and continue the process, in that case you should at least throw a Warning to tell the programmers that something is wrong but it’s not critical. A silent code or a code that throws generic messages is terrible to debug. When it comes to warning messages, it is important to try to clear the most you can. In big projects you may have hundreds of warning messages thrown and then they will simply be ignored. If you have few, when they appear, they will catch your attention so you can get important feedback. There is a profound relation with real life. It is rare to see people that can be assertive to tell what is going wrong with them. People have a tendency on one hand to keep the problems to themselves or on the other hand to adopt an aggressive posture. In both cases, they will have a hard time getting help from others. Marshall Rosenberg developed a process to help with that called Non-Violent Communication. It reframes how you communicate with people on a fundamental level, just like we expect from a good error message in code.

“Every criticism, judgment, diagnosis, and expression of anger is the tragic expression of an unmet need.”
― Marshall Rosenberg

There is an important topic in Software Engineering that is called Design Patterns. When we know a pattern beforehand, we can relate to this code faster. We all know that for a specific problem we might have many solutions and these solutions differ themselves by the design decisions. Programmers notice, empirically, that some patterns arise when you follow the principles mentioned so far and these patterns have been categorized and studied. It is important to learn all Design Patterns that you can and apply them when needed. This knowledge improves your skill to read and write quality code.

Now we have readable, organized code that works, in the next section we will discuss how to guarantee software quality.

--

--