This is the second post from a series of articles about broadly defined clean code. If you overlooked the first part of the series, which is about comments, then you can find it here.
Whereas in this post, you can read about another factor that influences the quality of dev’s code: naming.
I will give a widely described lists of todos and not todos in terms of the current topic.
Good practices of naming have a significant meaning for clean code. It’s because developers have to name almost everything that is a part of the code. They name packages, classes, variables, functions and so on. As you can see, this is the reason why naming is such an important thing for keeping the code clean. As I mentioned, I prepared two lists. The first one is called “TODOS” and it’s about things that we should do in terms of naming. The second one I called “NOT TODOS” and it’s of course respectively about the things that we shouldn’t do.
As the headline says, you should put emphasis on using names that present all of your intentions. It is not easy to choose an optimal name, but the effort devoted to it pays off in the future. Every developer, who takes a look at the author’s code written in accordance with this principle, will have a much easier task to understand it. The name of your variable, class or method should answer these questions:
If it answers them, there is no need for any additional comments in the code (from a previous post you already know that in general comments are not a good idea).
Let’s assume that you want to name a variable for a distance measured in meters. Don’t call it distance
, meters
or m
and so on. Much better will be distanceInMeters
. It will give you a clear context and intentions that this variable should express. Lack of these values is a big problem.
It’s never a good idea to use the same or similar names for a different purpose. We are not able to see a clear difference between what is hiding below these names. Let’s take names of methods for an example. Is naming two methods getProduct(UUID id)
and getProductInfo(UUID id)
a good idea? Nope, because we don’t know what is this slight difference about. We are forced to check what they are returning and what code is executing inside them. Of course, in this example, we have comfort due to the fact that they are indeed returning something. If not, it would be even harder to note the difference.
Another example is using numbers for variables numbering that have the same name, e.g. product1
, product2
and so on. Although, such names are not misleading, but nevertheless non-informative.
With no doubt, using mental shortcuts or a group of letters, which are not forming any existing word, is a sabotage in terms of clearness of code and in general of the whole development process. Due to that, using the name getModStrNm
for a method instead of getModifiedStreetName
is not a good idea. Just imagine how funny your conversation with another dev would look like if you both had to talk about this method. Not to mention the difficulty of reading and understanding the code which in fact is still a main problem about the unpronounceable words.
In practice, every IDE nowadays offers a search function through a whole project. You can search for classes, methods, variables, etc. by entering strings in the search bar. Therefore, it is another argument for not using single letters as names. Let’s assume that you called a variable with the e
letter. Because of the fact that it is the most-used letter in English, the results list will be huge when it comes to searching for variable e
. By naming variables this way, the developer is making his life much harder.
It is a good practice to declare static variables at the top of classes. Let’s say that we make a static variable named MIN_LETTERS_PER_DAY
equal to 3. Thanks to that it will be easier to find this variable with searching feature. But there is one more reason for this practice - if it turns out that this value should be equal 4 then all you need to do is to change 3 to 4 in one place instead of every place that this value was used.
Methods name should be verbs or verbal nouns like activateAccount
or accountActivation
, period. What is more, methods which are accessors, mutators or predicates should be created on the basis of operated value like getExpirationTimestamp
, setName
and isActive
.
Developers should stick to one and consistent lexicon for the project. Using different names for analogic methods in various classes is not an optimal solution. For example, you shouldn’t use get
, fetch
and retrieve
interchangeably. These names’ meanings are slightly different, so it can cause other developers a doubt in the fact that these methods are doing exactly the same operations. So, as you can see compliance with this rule is really important for the quality of our code because how your code is understandable by others is a huge factor of the final quality.
It is a good practice to use IT terminology everywhere it is possible and reasonable. It’s because of the fact that most likely everyone who will be reading our code is a developer. Whereas everywhere where there is no possibility to use IT terminology, e.g. because there is no such a name for a specific element of code, we should use a name that describes this element well in terms of a business problem that it concerns.
It is common that there is no possibility to name an element in any rational way in terms of giving it enough context. But with help comes a proper naming of these components in which is our element (such as classes or methods). Name them is such a way so that they also could bring some needed information and somehow relieve it from a part of the responsibility of giving a sufficient context. Let’s say you have the class Foo
and it is responsible for something totally different from the method that you want to create in this class. This method will be e.g. making a real phone call using a third party library and it will be named makePhoneCall(String from, String to)
. Despite the fact that the class Foo
shouldn’t have any implemented methods that are not related to it at all, there is a possibility to rename it into make(String from, String to)
thanks to moving it to a newly created class called PhoneCall
. Then class Foo
could just call something like this: PhoneCall.make(“+48123456789”, “+48987654321”)
if this method was a static one of course. By the way, there is one more advantage by doing this - when you have a PhoneCall
class you can divide our method’s body into a few methods to make things more clear and understandable.
In one of the previous pieces of advice, I wrote about giving names that represent a good context. In this one, I want to warn about naming that gives a bad or unclear context. In my opinion, it is even worse than not giving the context at all. Such behavior is misinforming everyone who works with our code and even ourselves. A simple example: let’s say that you have a map that is a collection of some products. Giving this collection a name productsList
is just suggesting that this collection is not a Map, but a List. This was just a simple example, but things might get more serious when you replace a name insert
for a method with save
.
If you are still using prefixes in instance variables names, then you can stop right now. After all, we are all using IDEs which are able to color every element of the code by its type. Thanks to that, prefixes are just useless noise in code that is worth to eliminate. From my observations, I can tell that developers are ignoring these prefixes when it comes to reading such a code, but why making them difficult to live?
When you are writing a code you need to think not just about yourself, but also about the other developers who will or might be reading it. It is extremely important to remember that the code has to be understandable for everyone. So, according to the headline of this paragraph, don’t use any thought shortcuts or any other unclear naming that only you understand. It’s not cool to think that naming user password variable with uP
will be fine because you understand it and you will remember about the meaning of this name later, while everybody else will probably have problems to deduce what is this about.
This is the opposite advice to that about method names. You shouldn’t use verbs in class names. Instead of them, you should use nouns or noun expressions. Also, you shouldn’t use too general names such as Parser
or Generator
. It would be nice to mention in these names what they can parse or generate.
Names should show their meaning well. If you make jokes, then you are darkening it and it is not transparent enough. It’s because when you make jokes, you are using some colloquialisms or a slang which is not always understandable for everyone (mostly only for you or a narrow group of people).
This is analogue to the advice about using one word for a concept, but the opposite way. We should always use one name only for identical operations or meanings. It will be easier to explain on an example. Let’s say that we have a few classes and there is exactly one method in each of them that does the same thing as the rest. It seems obvious that every method should have the same name. Everything is fine, but when we have to make one more class that also has to have such a method implemented and this time this method has to do a slightly different operation, we might have a problem. In this situation, it might occur a temptation of naming this method exactly the same as in other classes. Unfortunately, we would do a pun, if we give up, and we want our code to be as understandable as possible and not difficult to study, right?
In this post, I’ve already written about the necessity of adding a context by properly giving the names for classes and methods. Because of that, you shouldn’t overdo it by adding too much context for elements that are a part of them. It becomes unnecessary because we already know it from the rest of the code. For example, when we have a simple DTO class UserDto
, then we don’t have to use the word user
in every variable name in this class. Nobody will have doubts that the variable id
is the user identifier, because it already results from the context given by the name of UserDto
class.
Personally, not once I came across some cases of breaking the above rules. What is interesting it was mostly when I was working on the Android projects. I think that the reason is that mobile projects are usually much smaller than the backend. It is often that only one person works on mobile app, so he thinks that he doesn’t have to pay so much attention to the purity of the code. Unfortunately, it’s rare that the Android project is developed from the beginning to the end by one company, and thus another developer has to face someone else’s code. I was that another developer more than once. Then I have seen some mixed names for the same elements of code, some jokes and also a lot of dis-informative contexts. These problems are often hard to fix, because they require much time to understand them first and only then you can start with refactoring.
Like in the first post I remind you that the content of this series is based on Robert C. Martin’s Clean Code: A Handbook of Agile Software Craftsmanship book. I hope that in this post I gave you a wide and handy range of advice about naming in programming. The best would be to stick to all of them, but I think the most important thing is to remember that the code we write is not just for us, but for others as well. And with this cool conclusion, we can end this post, but before that, I would like to express my interest in your opinion. So, are there any other good or bad habits you have come across or applying to? I encourage you to think about it and share your thoughts leaving a comment.