If you heard concepts like SOLID, you know people like Uncle Bob, or are an expert in architecture, you surely have heard about Clean or clean code.
This philosophy brings together a set of ideas that aim to make the code easier to read, maintain, extend and less error prone.
The original idea came about through the book of the same name written by Robert C. Martin (Uncle Bob), and I wanted to draw some ideas that I think are interesting.
1. Use meaningful names
One of the ideas that closely repeated is that the code must be able to be read like a book. To do so, the names of variables, methods, classes have to be selected carefully to give meaning to what we are trying to “count” in our program.
The names of public structures (classes, functions …) must be specific and clear. However, private may be all we need long and descriptive, so that clearly explain what they do.
2. Make small units of code
Functions or classes that are too long they become almost impossible to understand if you do not study line by line, and that will extend much time understanding.
On the contrary, if they are short and, combined with the previous point, give them a lot of meaning, the reading will be direct.
It is also generally recommended limiting the number of lines of classes and functions, in order to force us to fulfill this point. You want to limit how’s your choice, but as a general rule, 10-20 lines per method and 500 per class can be a good scale.
It is also recommended not to exceed more than one level of nesting. Each of the branches of a if/else for example, should be formed by a single line to call a function.
The idea behind this is that code forks become difficult to follow. If you draw a function, you can give a meaningful name to explain what is done in that way possible.
3. The units of code should do one thing
Closely related to the previous point, if our code structures are too large, it is because they are probably doing more than one thing. It is what is known as the principle of single responsibility, one of the 5 principles SOLID, very present in the ideas of clean code.
Why is it important this point? Focusing on a class for example, if this does several things, sooner or later we will find the following problems:
- This class will be very prone to change: increased the number of reasons for which need to modify this class, and so it is easier to introduce errors and it becomes exceedingly complex.
- We test it costs more: having no well defined what it does, tests and lengthy surely be ineffective. In addition, we will perform change very often when that class is changed.
- The code will grow out of control, and we will be very difficult to add new functionality.
4. The functions should have a limited number of arguments
The parameters add a lot of burden conceptual difficult to read. It is much easier to understand what makes a function without arguments one to which we pass a parameter; because that means that the result will be different depending on the input.
Besides the testing difficult. Imagine the number of possible combinations that exist for a function with four parameters. And to be sure it works in every case, you would need to try them all.
More than three parameters should be well justified, and are best avoided.
An alternative would be to replace all (or some of) those parameters for an object that models the entrance. It does not eliminate complexity, but at least it will be easier to understand what is being done with these arguments, without seeing what the code.
5. Follow the DRY principle: Do not Repeat Yourself
Repeat code is a very dangerous action that will cause us problems sooner or later, and follow this design principle of software will avoid some headaches.
Some of the points that arise when we repeat code are:
- It forces us to test the same thing several times since being in different parts of the program; we will have to validate their performance in all of them.
- When we change something in a block, we have to remember to change the rest. Obviously, the chances are that we forget them.
- Expand the amount of code to maintain, and that’s always a problem.
It would be as easy as removing it to a new class or function, and use it from the places we need.
The problem with this is that sometimes the duplication of code is not as obvious as it might seem, so we have to be vigilant and refactor when we detect these cases.
6. Avoid using comments whenever possible
If you need to add a comment, it is because the code is not self-explanatory, which would contradict the first point.
Whenever you see the need to write a comment, try to rewrite code or name things differently, so that the comment becomes irrelevant.
The problem is that it has some comments similar to those of repeated code problems. Most modify the code but sometimes we forget to do the same with the comments. In addition, the brain is very skilled programmer to ignore, even if they are there.
In any case, there will always be situations in which a comment is much better to leave a complex code or a “hack” without explanation. When working with other libraries, APIs, Frameworks, always arise situations where we need to do something we have to explain in words.
7. Use a single format in your code
Any format, strangely enough, is better than none at all. It will give coherence and structure to the code, and guidelines to be followed by all developers. Some of them we have already mentioned, as the size of the work and classes. Some other things you can agree:
- Vertical Density: the concepts that are related should appear together vertically. You need rules to decide when to leave a blank line and when not.
- Locating components: normally the fields of a class are usually put at the beginning of it. You also have to decide where inner classes or interfaces, in the event that you use ALLOW place.
- The number of characters per line: Normally editors are marked with a vertical line are usually around 120 characters. It is a good rule to follow.
And so on. When you see a conflict in how to define the format of something specific in your computer, it is best to define a rule that everyone does it the same way.
You may also like to read another article on Tiffany-Hines: How to Select the Best Computer Programming Training Course For You
8. Abstracts your data: do not use getter and setters indiscriminately
A common practice in languages like Java is to create an object and immediately self – generate all its getters and setters to access and ability to change your state.
But classes exist precisely to encapsulate our data and that can only be modified from the outside under certain rules that we impose. We are not interested expose the details of our data.
Here it is important to identify whether our class is a simple data structure or an object with behavior . Objects hide their data through abstractions and expose functions to operate with them. By contrast the data structures expose their content but their functions do not perform any relevant transaction.
In this second case, it will make sense to expose all its attributes with getters and setters, or even make them public.
9. You Know the Law of Demeter
The Law of Demeter is a coupling detecting mechanism, and we come to say that our object should not know the innards of other objects with which it interacts. If we want to do something, we must ask directly instead of navigating its structure.
The problem with this type of code is, first, we need to know the class structure to perform an operation that should be direct to the point of code in which we live.
And second, that this code is very likely to change, because that line depends on 3 classes that can be changed at any time.
Normally the solution to the violation of this law usually happens to restructure our code, not only create methods that hide the problem. This will require to identify who is responsible for each of the actions taken and delegate to them you run the task.
10. Throw exceptions instead of returning return codes
Thus, a double effect is achieved:
- On the one hand, you do not have to remember to operate with that error code and decide which path to take, because exceptions will do it for you.
- On the other hand, the logic of “happy way” of error is easily separated, since errors will be handled in their catch respective.
The ideal is to create custom exceptions that give a more semantic meaning to the error at a glance, and provide them with clear and descriptive error messages.
11. Establishes borders
There are many cases in our software in which we have no control over the code that execute, either for example when using third – party libraries or frameworks.
The boundaries allow us to establish boundaries between our code and that code that we do not control, so that we can narrow your interaction with him, and which in turn allows us to seamlessly replace it if necessary.
Borders can also help us in cases where we have to work with code that does not yet exist. We can declare a number of interfaces that implement initially false data that serve as a substitute until the final code is ready.
12. Write tests
There is not much to tell here. The tests help define and validate software functionality you’re implementing.
There is much literature on tests, but a good place to start are the unit tests. Usually the easiest for which to start, and it should represent the highest percentage in terms of quantity. They are quick to implement and validate the details of implementation.
As always, all these ideas have to be researched and used when it makes sense. But if you start to apply them, you will get your code easier to read and maintain.
How many are already being implemented? What are going to start using from now?