Use meaningful names in your code

What is in the name?

Naming your variables and methods is not easier than naming your baby, we cannot just pick a name that sounds pretty to the mother. Generally programmers would rate naming methods and variables as tough or at least an important task. I have impression that after the books like “Smalltalk Best Practice Patterns”, Refactoring and Clean Code, we have definitely? come out of the age of names like i, j, fun1 and got a consensus on using meaningful names.

 

What do you mean by meaningful?

We still find us having disagreement on what is meaningful. Kent Beck  put it as “Intent Revealing Method Selector” in “Smalltalk Best Practice Patterns”. For me it all boils down to readability and maintainability. Reading code is all together a different mindset then writing code. While writing code you already know “what” you are trying to achieve and your mind is too occupied in “how” you are going to do it. Where as while reading code, all on your mind is “what” exactly this guy was trying to do.

Lets take an example, say we have a list of promotional product stored in some sort of configuration and then we call an API to get all the products with up-to-date prices. Before we render the products to the user, we refresh our local list with prices from the list we received from server.

var configProducts = Configuration.GetList("PromotionalProducts");
configProducts.forEach((item)=>{
product = products.find((ps) => ps.id === item.id);
item.price = product.price;
item.tax = product.tax;
});

This is just a very simple example, so the reader may not get too much trouble in understanding the logic. But in case of complex code, names like ‘item’ and ‘product’ inherits some level of ambiguity of their i,j predecessors.

Lets try changing some of the variable names and see if it make it any better for the user.

var promotionalProducts = Configuration.GetList("PromotionalProducts");
promotionalProducts.forEach((promotionalProduct)=>{
productWithUpdatedPrice = productsWithUpdatedPrices.find((ps) => ps.id === promotionalProduct.id);
promotionalProduct.price = productWithUpdatedPrice.price;
promotionalProduct.tax = productWithUpdatedPrice.tax;
});

 

With these small modifications, without any real change to the logic, we communicate the intention quite clearly. Now within for-each we can tell that we are updating price of  the product on promotion with updated price. Sometimes in lambda, I see the use of ‘item’ or some other abbreviation (p for product) etc. In those cases it does not lose much readability as long as it is a simple expression and is involving only one entity (list or collection etc.)

 

What vs How:

When reading code, if you know “what”, then it is easier to understand “how” by reading the code but things are not quite the same when it is other way around.

In an another example, say we are writing a method/function to generate a notification to a 3rd party about a product being updated. It is a legacy monolith using one big database with no bounded contexts separation. There is a batch job pooling a multi purpose ‘actions’ table, if it find a new row, it processes it and in this case it sends required notification. So all we need to do is add a new action:

public void UpdateProduct(product){
API.Product.Update(product);
this.API.Action.Add(new Action{
Reason = "Product Updated"
EntityId = product.Id
});
}

 

This method is doing two things, updating product and add a “product updated” action. It will be a good idea to extract the second part into a separate method.

public void UpdateProduct(product){
API.Product.Update(product);
AddProductUpdatedAction(product.id);
}

private void AddProductUpdatedAction(int productId)
{
this.API.Action.Add(new Action{
Reason = "Product Updated"
EntityId = productId
});
}

So there is an API to add new action, we call that and give it an instance of new action. Here author’s real intent is to send a notification,  not adding an action to the table. Adding action to the table is just how it can be done in the system right now and it may change in future. Lets see how we can improve the readability by changing the method name:

public void UpdateProduct(product){
API.Product.Update(product);
SendProducUpdatedNotification(product.id);
}

Now the reader should understand that we want to send a notification. So if in future we refactor the code to change the way we send notifications, whoever is making the change would know where to make the change.

 

When in Rome:

Intention has to be done as per  the context of your system. If your application is an event-driven decoupled microservices handling different bounded contexts. Then your code should just communicate what it is trying to do within the current bounded context, instead of how it expects the other systems to react on the particular event.

Lets try the previous example in an event-driven system, where we have a separate subsystem handling notifications, which listens to the event and react accordingly. In this case the code within the current bounded context will only update the product entity and broadcast an event that product is updated. Sending notification will be done in a different system. In that case we could have done something like this:

public void (product){
API.Product.Update(product);
Bus.Raise(new Event("Product Updated", product.MinimumInfo.ToJson()));
}

So here the real intention is to raise an event and we don’t care what will happen in other systems after that. There can be more  than one system listening to this, but code in this sub system does not need to know that.

 

Again, we can do a huge favour to the application by choosing the meaningful names. It will come quite handy for any future reference or refactoring of the code. I hope you find this post helpful.

One thought on “Use meaningful names in your code

Leave a comment