Andy Crouch - Code, Technology & Obfuscation ...

Readable Code Part 3 - Code Asset Naming

Photo: Markus Spiske - Unsplash

This third post on code readability is about code asset naming. This includes variables, objects and function/method naming. There are many different views on this subject and it can be contentious. But, I will outline the reasons for the rules I follow as I go through the article.

The first thing that I want to highlight is that all languages have style guidelines. .Net has C# Coding Conventions and the F# style guide. Python has PEP 8. The Elixir community went so far as to take their style guide and enforce it with a build task. If your stack doesn’t have one then the community most certainly will have defined one. Find the one applicable for your language, read it and stick to it. Define its usage in your project documentation. If need be, automated its application with supporting tools. Issues like name casing and tabs vs spaces will be governed on your languages style guide. The following set of recommendations are to be used with the applicable style guide.

The most important thing is that you make your code asset names as obvious as possible. There is never a reason to use a single letter/symbol variable name for variables:

double d = 10.;
int i = 5;

What is d? What significance does it have in the method or function it is used in. There is no way to know the answers until you read through more of the surrounding code. Remember from previous posts that we want the code to be read like prose. So having to search for the meaning of d will break your ability to read the code fluidly.

(Actually, there is a single reason to use such a naming convention and that is when implementing mathematical/scientific notation. However, you should limit it to a single class or namespace and not use notation as domain specific variable names.)

You also do not want to use a name that requires you to use a comment to explain it:

int height = 21; // Height in Centimetres 

string name = "Bob"; // The managers first name

So, how should you name your variables and objects? Simple, in a clear way that reveals what the purpose is or what it is referencing:

int heightInCentimeters = 21;
string managersFirstName = "Bob";

You should not worry about longer variable names as they provide clarity. We are not working with limited memory and clarity beats brevity. Intellisense is available in all editors and resolutions are much higher these days on screens as well. While from habit I tend to stick to 100 characters per line that stems from the start of my career. On the opposite end of the same spectrum, do not make your variable names overly long either:

int anIndexCounterUsedToTrackTheNumberOfEmployeesInAList = 0;

This is not useful and can be reduced to the following while still providing the required clarity:

int employeeListIndexCounter = 0;

For most of the languages I have worked with, there is almost no reason to add a language type *fix to a name. With strongly typed languages especially, you add no value with:

bool isLoadedBool = false;
bool boolIsLoaded = false;

Over:

bool isLoaded = false;

While dynamic languages imply their type from the assigned data there is still no reason for the *fix. What if the following:

intDivisor = 10

Became:

intDivisor = 10.57654

By changing the data assigned you have now made the variable name invalid. This nicely brings me onto the next naming issue I have seen a lot, lying naming. Never name an asset in a way which misleads, confuses or plain lies to the reader over its intention. If you have a collection of objects call it a collection:

var results = _someObject.GetResults(calcInputs);

Could be redefined as the following to clarify its purpose:

var resultsCollection = _someObject.GetResultsCollectionFrom(calcInputs);

If you change an object or variable’s purpose then change the variable name to reflect it.

// Changed the method call to return a List<Results>

var resultsList = _someObject.GetResultsListFrom(calcInputs);

Across your objects, you should try and adopt a consistent naming approach. This is confusing and inconsistent:

_someObject.Remove(item); 
_someOtherObject.Delete(thing);
_aThirdObject.Bin(record);

Would be better as:

_someObject.Delete(item);
_someOtherObject.Delete(item);
_aThirdObject.Delete(item);

I’ve found that by using strong parameter naming you can massively improve readability.

var employeeId = 100;
var employee = db.Employees.FilterBy(employeeId); // public void FilterBy(int employeeId)


// Update data

employee.Name = "Fred Smith";
employee.Age = "55";

db.Employees.Save(employee); // public void Save(Employee employee)

db.Employees.Delete(employee); // public void Delete(Employee employee)

As you can see above, this code becomes extremely easy to read. Once a developer has worked on the code base for a short while they will become quicker due to the predictability of the method or function naming. This shows the lack of need to include the Type in the naming. The following doesn’t really offer any benefit:

db.Employee.FilterByEmployeeId(employeeId);

I see a lot of naming like the above. It slows the ability to read the code down due to duplication. In most cases Verb(parameter) is almost always good enough. In fact, it can be quite a nice feature of some languages when implementing fluent API’s:

var employee = new Employee().Add(name).Add(age).Add(employeeAddress);

Adding solution and domain naming conventions tend to result in specific naming patterns becoming obvious. The Clean Code community suggest that you can mix in solution and pattern related suffixes to your naming conventions. Including the full design pattern name is akin to including a type suffix. But, adding a clear identifier can be helpful in understanding the code dependencies and responsibilities, such as:

var managerFactory = new ManagerFactory();
var manager = managerFactory.CreateNewManager();

What you do not want to do is confuse mixing in access modifiers such as the following:

// Should be called EmployeeFactory as the fact it is an abstract class is obvious from the access modifier

public abstract class AbstractEmployeeFactory
{
}

public  class ManagerFactory : AbstractEmployeeFactory
{
}

var abstractEmployeeFactory = new ManagerFactory(); 

We should be mindful when naming objects and methods/functions of the languages namespace functionality. The namespace should be seen as a container in which your naming makes complete sense. As an example, taking the above code you would not expect to find a method that is destructive. A Factories namespace should only contain objects with methods that result in the creation of objects.

The last thing worth remembering is that your reputation is based on your code. So with that in mind, it is always best to leave the humour to team events and one on one conversations.

var result = employeeRepository.Kill(employee); // No

var result = messageRepository.Post(letter); // No

var omgHowOld = employee.CalculatePensionAgeFor(employee); // No

Just like insulting, rude or humorous comments, git blame will point to you. As you get older you will appreciate the impact on the way you are viewed.

So those are my thoughts on naming. They come from reading a great deal on the subject and real-life experience. Again, the purpose of this series is to instil that readable code is instrumental to the success of any project. By adopting clean, clear and consistent naming conventions you will reduce the development effort of your project. It will ease the onboarding of your growing team. It will also improve your velocity and simplify business as usual changes.

If you have any opinions around code asset naming or the points made here then please contact me via twitter or email.