Why good names make a difference

29.11.2020 Reading time: 25min

It's natural for us that when we talk about people we know, we refer to them by their name. In the same way we call things we have by their name and know what to expect when using them. It's just intuitive and much more efficient than having to cope with its details or characteristics each time. Or do you care about how much electric current is involved in making your light bulb shining when switching the light on. Probably not, right? At least as long as it gets brighter in the room. Only when we need to fix the light bulb, we might be interested in those details. Why am I telling this? Because it's equally important when developing software. Let's take a look.

Why naming is important

To me there are two essential reasons why I consider proper naming as a major qualitative criterion.

Managing complexity

As software developer you know that writing programs is usually not an easy task. Programs are interpreted on a technical low-level and it takes quite some knowledge to understand all details. If we think about larger applications which consist of multiple parts connected and working together, possibly managed by a team or multiple teams, it's impossible to keep the full picture with all details in your mind. Like an architect drafting the plan of a house does not care about which compressive strength the concrete used in the building process has, should I not have to go through the details of the merge sort when I want to get a sorted list of users from a database.

Readability

It's no secret that as a software developer you will read more code than you write. With regard to this fact you have to make sure that your code is easy to read and understand for others and for yourself when you come back to it. Names of variables, constants or methods play a key role there. Simply compare the two code snippets below and judge for yourself which one is better to read and understand.

  
    
function func(list) {
  let x;
  list.forEach((item) => {
    if (!x || item.a < x.a) {
      x = item;
    }
  }); 
  return x;
}

  
  
    
function youngestEmployee(employees) {
  let youngest;
  employees.forEach((employee) => {
    if (!youngest || employee.age < youngest.age) {
      youngest = employee
  });
  return youngest;
}

  

Although this was just a simple example, I hope you admit that naming variables and functions properly as shown in the second case pays off.

My ultimate naming checklist

A few years of experience as professional software developer and quite some reading and learning later, I come up with a list of points to consider when choosing names.

Refer to the problem, not the solution

This rule sounds a bit paradox because we want to solve things as developers. Yes, we do but for method or variable names it makes sense to emphasise the "what" instead of the "how". Let's look at an example.

Bad:

  
    
const records = fetchAllRecordsFromMySqlDatabase();

  

Good:

  
    
const users = getAllUsers();

  

The first example uses low-level language we don't want to care as consumer. We want to retrieve all users, no matter if they are stored in a MySql database, a CSV file or in an S3 bucket. By using a domain language as in the second example we know immediately what we can expect when consuming this interface.

Avoid abbreviations

As software developer we not only tend to use a "techy" language when we talk about implementation details but we also like to abbreviate things which are obvious to us in the current context when writing a piece of source code. However, they might not be so well-known for other developers in our team or not even to us when we come back to that code in a few months. Therefore, it's advisable to let aside abbreviations, which are not a best practice standard or agreed on by the whole team. The rule I follow here is "Better longer than not expressive". Let's have a look at some examples.

Bad:

  
    
const empRec = firstEmpRecFromDb();

  

Good:

  
    
const employee = firstEmployeeFromDatabase();

  

At the time of writing the code, it will be clear that you get the first employee record from the database. However, a colleague on your team definitely has to take the time to look inside the function what he is going to get as "empRec". The second code example makes it crystal clear what you can expect when executing it.

Setup naming conventions

Developing software is a creative and complex process and there are usually dozens of ways how to solve certain problems. Naturally the style of writing code will vary in different aspects when multiple persons work on the same project. Up to a certain point I think that's how it should be because every member of your team should have the freedom to find the best way to solve a particular problem from his point of view. However, when the code base grows, it absolutely makes sense to setup certain conventions in order to remove unnecessary obstacles in reading, understanding and maintaining the code. So we agree on a certain layout and formatting, so should we also enforce conventions when it comes to naming. My personal view on naming conventions is to rely on the general naming best practices, like the ones mentioned in this article, as well as recommendations and style guides provided by the programming language or framework you use. Especially mature programming languages and frameworks usually provide you with a rich set of conventions which have following advantages:

  • They are well known and used by a lot of people out there.

  • They can usually be configured easily by the IDE you use.

  • They usually have a rich documentation you can refer to and does not require you to maintain yourself.

  • Since they are a de-facto standard it's one obstacle less for new employees when onboarding them to your team.

However, every software project has its own domain specific things and it usually makes sense to agree on common terminology used throughout your project to ease communication. A typical example can be common abbreviations of your specific domain. In case everyone knows about them, they are a good tool for shorter variable or method names, although I personally don't recommend to exaggerate this just for the sake of short names. If the list of abbreviations becomes too long that you can't remember them anymore this turns into a disadvantage quickly. Hence, an "empRec" like in the code example from the previous section does not outweigh "employeeRecord" in my opinion and I would not setup a naming convention for such general terminologies. Another interesting point could be standardized prefixes. Let's look at an example to make this clearer.

  
    
const employee = getEmployee(id);
const anotherEmployee = findEmployee(anotherId);

  

Do you know what's the difference between those two functions? To be honest, I don't know either without seeing the internals of the two functions. They could even be the same but just written by two different persons with different ideas of terminology. For such things, it would be a big advantage to have a convention stating that a function retrieving a particular record from a data source should be prefixed with "find". Having this rule documented and communicated we would immediately know what to expect when reading the function call.

Provide names better too much than too little

As programs grow, so does the complexity of the whole code base as well. As a consequence, the more important it gets to pay attention to keep a good structure to ease reading and understanding. An essential thing thereby is to prevent your functions from getting longer, more nested and cluttered with complicated expressions. Again another example to illustrate this:

Bad:

  
    
function promoteEmployee(employee) {
  if (employee.age < 30 && employee.enteredCompany < new Date().getDate() - 365 * 5 || employee.finishedProjects > 10) {
    employee.salary += 200;
    employee.save();
  }
}

  

Good:

  
    
function promoteEmployee(employee) {
  if (shouldBePromoted(employee)) {
    employee.salary += 200;
    employee.save();
  }
}

function shouldBePromoted(employee) {
  return employee.age < 30 && employee.enteredCompany < new Date().getDate() - 365 * 5 || employee.finishedProjects > 10;
}

  

I know that this is a simple example and you can rather easily grasp the expressions but still I think it makes a difference to extract the boolean expression into its own function. At the time I read the promoteEmployee , I am most likely just interested in the functionality of promoting an employee (in this case increasing the salary by 200). In which case an employee should be promoted is secondary to me in this situation. Having this part of code encapsulated in its own function hides the complex boolean expression and I don't lose focus. As a rule o thumb I recommend to extract something once too much than too little into a variable, method or constant.

Conclusion

I hope I could outline the importance and power of naming in software development with this article. Although it does not have an immediate impact on whether a program does what it is expected to do, it is inevitable to deal with it when writing code. As a professional software engineer I consider it as an essential skill you need to have in your toolbelt to write not only correct but also readable code which can be maintained and is scalable over a long period. It's definitely a topic where there are usually no black-white decisions and it takes courage to get it right. However, with the checklist outlined in this article I hope it will be a little easier for you in the future.

© 2020 Jürgen Ratzenböck, All rights reserved - Privacy Policy