Don’t use abbreviations while naming variables

A few months ago, Technogise had conducted a Code Retreat session for engineering graduates. I was one of the volunteers for this activity.

We asked students to solve a simple problem.

We asked them to write a program which calculates the final price of product items in a shopping cart, when the initial price of each item, the category in which each item falls, their quantity and the GST (goods & services tax) slab applicable to each category was given.

Going through the code for some of the students led me to write this post.

Please read the code below:


using System;
using System.Collections.Generic;
using System.Linq;
namespace Assignment
{
internal class Program
{
private static Dictionary<string, int> CGR = new Dictionary<string, int>();
private static Dictionary<string, string> iCat = new Dictionary<string, string>();
private static void Main(string[] args)
{
CGR.Add("Food-grains", 0);
CGR.Add("Furniture", 5);
CGR.Add("Electronics", 18);
CGR.Add("Cosmetics", 28);
iCat.Add("Rice", "Food-grains");
iCat.Add("Wheat", "Food-grains");
iCat.Add("Sofa", "Furniture");
iCat.Add("Chairs", "Furniture");
iCat.Add("TV", "Electronics");
iCat.Add("Mobile", "Electronics");
iCat.Add("Shampoo", "Cosmetics");
iCat.Add("Perfume", "Cosmetics");
Console.WriteLine("Welcome to NMart store");
Console.WriteLine("***************************");
Console.Write("Enter name of item: ");
string iName = Console.ReadLine();
Console.Write("Enter quantity of item: ");
int iQnt = int.Parse(Console.ReadLine());
Console.Write("Enter rate per product item: ");
int iRate = int.Parse(Console.ReadLine());
string cName = "";
foreach (var cat in iCat)
{
if (cat.Key == iName)
{
cName = cat.Value;
break;
}
}
int cPercentage = 0;
foreach (var c in CGR)
{
if (c.Key == cName)
{
cPercentage = c.Value;
break;
}
}
double fPrice = iQnt * (iRate + iRate * cPercentage / 100.0);
string output = "*******************************************\n" +
"Billing Details for " + iName + ":\n" +
"*******************************************\n" +
"Quantity: " + iQnt +
"\nPrice per unit: " + iRate +
"\nFinal rate: " + fPrice;
Console.WriteLine(output);
Console.WriteLine("\n*********************************\n");
}
}
}

Were you able to understand the code? After a few minutes of repeated reading, you could.

It’s difficult to know the meaning of the variables like CGR, iCat, iName, iQnt, cPercentage, fPrice and so on?

It creates a complicated mapping in your brain. You need to scroll up and down to understand the intention of everything, isn’t it?

Now let’s see the same code after giving little better names.


using System;
using System.Collections.Generic;
namespace NMart.Billing
{
internal class NMartStore
{
private static Dictionary<string, int> CategoryGstRatesInPercentage = new Dictionary<string, int>();
private static Dictionary<string, string> ItemsInCategory = new Dictionary<string, string>();
private static void Main()
{
CategoryGstRatesInPercentage.Add("Food-grains", 0);
CategoryGstRatesInPercentage.Add("Furniture", 5);
CategoryGstRatesInPercentage.Add("Electronics", 18);
CategoryGstRatesInPercentage.Add("Cosmetics", 28);
ItemsInCategory.Add("Rice", "Food-grains");
ItemsInCategory.Add("Wheat", "Food-grains");
ItemsInCategory.Add("Sofa", "Furniture");
ItemsInCategory.Add("Chairs", "Furniture");
ItemsInCategory.Add("TV", "Electronics");
ItemsInCategory.Add("Mobile", "Electronics");
ItemsInCategory.Add("Shampoo", "Cosmetics");
ItemsInCategory.Add("Perfume", "Cosmetics");
Console.WriteLine("Welcome to NMart store");
Console.WriteLine("***************************");
Console.Write("Enter name of item: ");
string itemName = Console.ReadLine();
Console.Write("Enter quantity of item: ");
int itemQuantity = int.Parse(Console.ReadLine());
Console.Write("Enter rate per product item: ");
int ratePerUnitItem = int.Parse(Console.ReadLine());
string categoryName = "";
foreach (var item in ItemsInCategory)
{
if (item.Key == itemName)
{
categoryName = item.Value;
break;
}
}
int gstPercentageForItem = 0;
foreach (var categoryGstRate in CategoryGstRatesInPercentage)
{
if (categoryGstRate.Key == categoryName)
{
gstPercentageForItem = categoryGstRate.Value;
break;
}
}
double finalPrice = itemQuantity * (ratePerUnitItem + ratePerUnitItem * gstPercentageForItem / 100.0);
string output = "*******************************************\n" +
"Billing Details for " + itemName + ":\n" +
"*******************************************\n" +
"Quantity: " + itemQuantity +
"\nPrice per unit: " + ratePerUnitItem +
"\nFinal rate: " + finalPrice;
Console.WriteLine(output);
Console.WriteLine("\n*********************************\n");
}
}
}

Do you see how simple it becomes as soon as you write meaningful names?itemName, itemQuantity, ratePerUnitItem, gstPercentageForItem, finalPrice and so on. Now the variables are conveying their intent, better than the first snippet? (I agree I could use a better data structure or use LINQ. However, I am simulating what students had written. They used different programming languages too. This code is for demo purpose.)

Now, you don’t need to scroll up and down to understand the intention of the variables. This is an impact of giving meaningful names to variables.

Don’t use abbreviations for variable names

Hence, we should spend little more time on giving meaningful names to variables (same thing is applicable to the class, namespace, methods, and so on) so that when you or maintenance developer revisits your code to fix a bug or add a feature, she/he could do it very easily. It should be flawless. Avoid using abbreviations while giving names to variables throughout the project. It would be a nightmare to maintain such code.

Dattatray Kale

Creating reliable “Objects”

Let’s start of with a piece of code.

We have a Main( ) method, which creates an object of a Circle class, sets the radius and then calculates the area of the circle. Let’s have a look at the circle class. It has a simple implementation to calculate the area of circle.

The above code looks simple and it works. Are there any flaws in it? Let’s examine.

What if the consumer of the Circle class, does not set the radius correctly? For example, like this,

circle.Radius = Convert.ToInt32("abc");

The call to CalculateArea( ) would fail, because the input cannot be parsed into an integer. By design, the Circle class  is allowing other classes to control the Radius property. The consuming classes, may set unacceptable values for the Radius property. This leads to unpredictable results from the CalculateArea( ) method. We can do a validation check for the Radius property either in it’s setter or the CalculateArea( ) method. That would work. Perhaps that is a natural approach we adopt most of the time.

But let us for a moment take a step back and think more in terms of object orientation. Imagine someone asks you to draw a circle on a piece of paper. Your obvious question would be, “Sure, how big or small do you want it?”. In other words, in order to “construct” a circle, you would need the information about it’s radius.

One more important aspect in this example, is that a Circle is immutable. Once we create circle with a certain radius, we cannot change it. Making the setter for Radius property as public allows the consuming classes to alter it, even after it has been created (Hmm, not good.)

It is therefore always a good idea to create objects in a robust way, when they are being constructed. The radius property is integral to the Circle class and it is the responsibility of Circle class to manage it. The clients just need to provide the details while creating the objects. If the client code provides incorrect information while constructing the object, the class can choose not to go further with its creation, thereby protecting its integrity.

Below would be the correct implementation of Circle class.
The above example was a simple one. We just had one property to deal with. But in reality, we need to deal with classes which have a lot of properties and really complex methods. Ensuring correct values in all properties throughout the lifetime of an object can be a very tedious task. This leads to many potential bugs. It is impossible to predict the ways in which the consumers of the classes would consume them. This leads to responsibilities scattered all over the place and classes that are strongly dependent on each other.

In addition, once we make a property as public, it is very difficult to make it private again, because by the time you realize that you need to do that, there may be a number of places, it has already been consumed and used in different ways.

As a thumb rule, try to restrict the access to all the properties in the class when you write it for the first time. This will allows you to encapsulate the class properties and the code to manage them inside the class itself. If you need to make any property as protected, internal or public, think and try to find for a strong need and justification for doing so.

 

Fail as early as possible

The inspiration behind this blog post is, of course, the Clean code book.

Sometimes, people choose to use unnecessary deep conditionals.

They choose to return error/exception from else part of the deeply nested conditionals. It hampers the readability.

We will consider the use case of register user which requires three mandatory fields: Name, Email, and Password. (Let’s keep it simple.)

Let me walk you through a code that was created to showcase the problem of deep nesting. This was a part of the method “RegisterUser” that accept user object.

RegisterUser(User user) routine and User has Name, Email and Password fields.

This code snippet creates a little-complicated decision matrix in your head, especially for the Else part.

When User’s Name is NOT empty && User’s email is NOT empty && User’s password is NOT empty then store user and also send a notification for that user.

Whereas Else part was more complicated and may read like:

  • When User’s name is empty then throw an exception for the name is required.
  • When User’s name is NOT empty but user’s email is empty then throw an exception for the email is required.
  • When User’s name is NOT empty and the user’s email is NOT empty but the user’s password is empty then throw an exception for the password is required.

To make it simple, use guard clause to fail early or fail fast. All if clause in below snippet is guard clause.

Now, this one reads like

  • Throw exception for the name as soon as the user’s name is empty.
  • Throw exception for the email as soon as the user’s email is empty.
  • Throw exception for the password as soon as the user’s password is empty.
  • Otherwise, store user and send a notification to the user.

Thus, the fail-fast/fail early would make the code simpler.

Guard clause in such scenarios helps us to improve understandability.

The end result:

Do not catch “Generic exceptions types”

(Below scenario may be hypothetical, but for explanation purpose, let’s consider it happens…….)

Imagine you are using a service for achieving some task, for example, let’s say, you are buying something on an online shopping portal.

It so happens that while surfing for products, the site crashes. You contact the support and they tell you it was a “SYSTEM ERROR” and they will get it fixed. Such things happens and it’s ok for you. You move on.

After a few days, you are trying to purchase something on this website and while checking out, the site crashes in the 3rd party payment gateway. This time you are a little annoyed and you contact the support again and tell them your story. The support tells you it was a “SYSTEM ERROR” and they will get it fixed. You move on, since you cannot do anything about it besides trying again.

Time passes by and after a few days you successfully place an order with this site. You are excited about your product, it’s a new gift for your spouse. But this time the product goes to a different warehouse in a different city and the product does not reach you. You again contact the customer care, and they tell you again that it was a “SYSTEM ERROR” and they will get it fixed. This time you get furious. How could it be a “SYSTEM ERROR” every time something goes wrong? You want more details about the problem, you want to hear more about what went wrong. After all, you have invested your time, money and effort in this activity.

This is exactly how the consumer of our library would feel if we return them a generic exception type, every time something goes wrong.

The consumer of the code code expects more details to either fix the problem or get the problem fixed. Standard libraries such as .NET, precisely describe about each exception that can be expected from the calling code. If your API has business logic and you want to enforce certain things (for example validation), you can return your own exception types (by deriving from base) and communicate the same to the consumer of the API. In this way the consumer knows what to expect when and take necessary actions.

Exceptions should be handled on case-to-case basis. Catching generic exceptions is a code smell and has to be strictly avoided. They indicate negligence to detail. Microsoft does not recommend suppressing this rule. More details can be found on MSDN here.

Repeating yourself? Wait! You could avoid the repetition.

In software development, there is this term Don’t repeat yourself. There are many posts which talk about it and terms like DRY, DRYness, WET, “write everything twice”, “we enjoy typing” or “waste everyone’s time”, and so on.

When you are repeating yourself, it’s a clue, an opportunity for you to do something about this repetition.

I’ll walk you through some of the examples.

As a developer, the first thing I was doing every morning was open the visual studio, get the latest code from TFS, build the dependencies (dependent projects), copy dll’s to the shared folder and build the main web project. I was doing this action daily in the morning. I saw I could have automated the process.

It was a clue! I created a bat file. The bat file was doing the above repetitive actions for me as soon as I start my computer.

In your case, it could be something else. It could get latest code from git, docker up, build containers and so on. Are you repeating yourself?

Whenever you see you are copying and pasting the bunch of HTML and CSS code to display a notification message. Just stop there! think about reusable HTML components, extract it and use it everywhere. Write once and use everywhere.

Whenever you see you are repeating the code to download CSV on multiple pages, then think about extracting it to a class, CsvContentGenerator? CsvDownloader?

Whenever you see you are repeating inline calculation?

 
if((totalStudentInClass - studentPresentInClass)>0){
    var message = "There are {totalStudentInClass - studentPresentInClass} absent students in the class";
}

Consider extracting it to a method or a variable.


var absentStudentsCount = totalStudentInClass - studentPresentInClass; 
if(absentStudentsCount>0){
   var message = "There are {absentStudentsCount} absent students in the class";
}

Whenever you see you are copying an email sending code from one project to another, consider writing a shared library.

Whenever you see you are repeatedly writing the validation messages in translation files. Consider writing the generic message in translation file and fill specific field name at runtime.

Check the support for it in your translation framework.


"EmailIsRequired": "Email is required".
"UsernameIsRequired": "Username is required".
"NameIsRequired": "Name is required".

// Instead of repeating, create generic message and 
// fill template-placeholder %{fieldName} with actual field name.
"FieldIsRequired": "%{fieldName} is required"

Whenever you see you are creating padding and margin styles and your app.css is growing.
Consider writing SCSS helpers, https://gist.github.com/jacurtis/30da4bf9a6c9b9b5cc0aebac512ca7c9.

Whenever you see you are writing repetitive if/switch case to decide and create a specific instance of a class. Consider using abstract factory pattern which decides and create the specific instance of a class for you.

We don’t know everything. It’s okay.

Whenever you see you are repeating something, I want you to stop there, think about it, there will be a clean solution. This could save your future time and code could be more maintainable.

In the software development field, patterns, practices, refactoring techniques and many more other techniques are already there to avoid repetition, use it.

You must be using the combination of key Ctrl+C, Ctrl+V million times a day. Next time when you press this combination, I want you to think about avoiding the repetition and ask yourself. Oh! wait! Can I do something about it? Can I automate this? Can I extract this logic to the method, classes, reusable CSS, js components, library and so on?

Is it time to re-name “Human resources” department?

Few weeks ago, I received an email from a recruiter. The title of the email went like, “Need immediate .NET resources who can join in Blah Blah.. time”. The email kind of triggered many thoughts in my mind. Am I really a “resource”? Is that only what I stand for? If I put in all efforts in my team and company’s success, will I still be a resource for the company? and so on…

We have been hearing this word “Human resources” for a very long time now. One of the companies I worked for hired college students from a campus in huge numbers. Once these graduates would join the company, there was a separate department named “Resource management group” who would look into how to harness these resources for company business. I was one of those graduate resource. For a very long time, I had the kind of feeling which you would have on seeing a huge farm of humans in the movie Matrix. In this movie, the machines would harness these humans for their survival.

It’s a common term in traditional program management to address, people, computers, cubicles everything as resources.  “Is the project delayed? Ok, no problem, put 10 more resources and complete it quickly.” We may have heard or even been a part of such conversations.

But, are we really resources? I’m not. I’m not a machine or a chair or a white board. I’m human. I have feelings, thoughts, ideas, knowledge. I get motivated, I get happy, I get sad, I have ups and I have downs. I don’t just type code. I create things, that help others, makes their life easy, things that make difference.

A company is not made by how fascinating offices they have, or how many computers they have. The most important asset for a company is its people, without it’s people, there would be nothing. Many successful companies originated in someone’s basement.

Google has moved away from the word “Human resources”. They call it “People operations”. And we all know the efforts Google takes in taking care of it’s people. And we also know the care it’s people take in keeping Google such a successful company.

I believe people in any company deserve more respect, not just for the work they do, but also because we’re humans. The culture of mutual respect, drives ownership and belongingness. These values can drive any company to great heights.

Introduce explaining variable

While doing pair programming with developers, I have experienced that some of them are hesitant to introduce the explaining variable. They worry more about other devs thinking about that extra variable.

Will it be redundant to have an extra variable? Well, let’s see:

Before

In the above code snippet (…even though it’s a simple one), checking file size against an arbitrary number does not convey any business rule clearly. You can’t predict easily about the meaning of ‘10000000’ or size whether it is in Bits, Byte, KB, MB or something else. One who visits this snippet needs to spend some time to figure out the intent.

Well, let’s introduce explaining variable and see if it helps.

Better way:

I know, I have increased the line of code here. However, don’t you think the introduction of explaining variable made it expressive and understandable?

Now it reads like:

When file size exceeds maximum allowed size (10000000 Bytes!), then just exit!

Another example:

Before

PHP code doing some matching on phone.

It’s really difficult for me when I read it the first time.

Better way:

Divided into multiple parts so that it could express itself very easily.

Now at least, you know that there is a regular expression for valid phone number pattern. It is used to determine if the phone number is valid or not and take appropriate action.

Introduce the explaining variable to convey your intent. This is one of the ways to express yourself via code.


What is “Google time”?

Software engineering and product development are different from other streams of business (manufacturing, for instance). Things are more predictable in manufacturing, specifically in the execution phase. But it is no so at any stage in product development, where you get to know the next challenge only once you solve the current one.

What has this to do with “Google time”? Many of us might be aware that employers give some time every week to their employees to work on anything they like. Most of the employees during this time spend time on their own learning or working on their own side projects. Many of the in-house tools and even products are born out of this activity.

But the main intention behind giving such “do-Whatever-you-Wanna-do” time to the employees in my opinion is not to churn out such side projects. The main reason and science of this lies in the “Queuing theory”. Less.works explain in great detail how the utilization levels affect the flow of value through the system. I will attempt to summarize it and put it in a context.

Imagine you have a highway and the vehicles are moving through with ease. Let’s say the traffic increases, vehicles gradually start taking more time to get through.

Each new vehicle coming on the highway gets added to the “Queue” and the time to get that vehicle through then is, can you guess?? As may predict it is linear, but it is not. It grows exponentially, until a certain point when you cant get anything out of the system, which means the response time goes to “Infinity” (mathematically). Such a curve is called M/M/1/∞ curve.

So the thumb rule is, when your size of inputs to the queue are random and when the time taken to process each input is random, then the system response can never be linear, it follows the curve we just described. This theory applies to many scenarios including server utilization for production systems and…… yes, you guessed it right, it applies to a developer’s day to day life as well.

How? as we know that in software development, we can never accurately predict the time it will take us to complete a task. We can only guess based on our experience. Each task gets done one after the other, in variable amount of time.

So let’s say that you, as a developer, is given a task each day of the week. There are 5 tasks you need to complete in this week.

On Monday, you are excited and start working on task A. However, it takes some more time in the end to test and deploy the functionality. You therefore, utilize some of the time on Tuesday to finish task A.

But wait, you already need to complete task B by Tuesday day end. Without wasting any time you get to work on Task B. Task B turns out to be tough one to crack, after you start working on it, you realize that you need some more technical help within the team to proceed. It turns out that you finish Task B on Wednesday.

On Thursday, you already have 2 tasks (C and D) in your plate. You start to feel the pressure now, and you are already thinking about multiple things at a time. On Thursday, your manager calls for a team meeting to discuss teams performance in last quarter, you lose half a day in the meeting (not to mention the context switch that comes along with it). You work on Task C, by sitting late in office and try to complete it.

When you arrive on Friday, you already have 3 tasks assigned to you which you need to complete by EOD. You realize that it is unrealistic for you to achieve it. This is exactly the breaking point, mentioned in the “Queuing theory”. Beyond this point of time, no matter how many tasks you keeping adding to “Your Queue”, they will take (mathematically) infinite amount of time to process.

I’m sure this has happened with most of us at some point of time in our careers. Linearity calculations do not work in software development. So how do we solve this problem? Well, that is precisely why good companies give their employees, some time to take control of their queues. Moving fast, compromises quality and increases technical debt. Most of the time, good employee’s, will utilize this Google time to either finish their pending work or to reduce the technical debt they introduced, when they had to finish things quickly.

There may be times when developers finish work quickly than estimated and may spend this time, learning or work on something else. Either way, it benefits the company, but as we just saw, these are the extra benefits. The main intention from management’s perspective is to induce the “Flow”, so that value get’s out of the system at a consistent pace.

Writing test for translation files

In the past, I had worked on different websites and app that support localization.  The user on these sites can work with the language of their choice and translations were provided on UI elements for selected languages.

When working with translation files for multiple languages, I found that there were instances when developers added translation text for English but forget to add translation text for languages other than English. That was a problem when a user chooses to work with a language other than English (He/she was provided with misleading text).

Secondly, there were issues due to duplicate translation keys provided by developers. It leads to incorrect translation due to overwriting (Misleading!).

I learned that adding the test for verifying these rules will help developers to identify the problems before pushing changes to production.

The simple react application is hosted on github: https://github.com/way2datta/translation-demo.

This sample app has support for English and Hindi language. The app has tests for verifying the translation files.

When the translation keys are present in the all translation files. The test runner display everything is well.

When I add translations in one language file and forgot to add it to another language file, tests start yelling at me.

Thus, the tests for translation files can help the developer to identify the issues related to translation files in development phase itself.

https://blog.beingcraftsman.com/datta/

Encapsulation


Encapsulation is the process of putting data and code (that operates on data) together in a single unit, which, acts as a protective wrapper for data and code. Access to the data is provided via controlled access (public interface).

Consider an example of a simple wristwatch.

Abstraction means to provide the simplest view of a complex concept (showing only the necessary part). So, in this case, it displays only time.

Encapsulation means not only provide the simplest view of complex concept (Abstraction!) but also hide and protect internal implementation. The end user cannot see how time is being calculated; what gives energy to the wristwatch; how the internal circuits are structured and so on…

The glass and plastic body forms a protective wrapper (Encapsulation) which hides the internal implementation details (hiding the complexity) and shows the current time (…only relevant part, Abstraction!).

Encapsulation gives access to modify the data via the controlled public interface. In this case, it’s a push button which is used to change/set the time.

From this example, it is clear that the two concepts are related. Without proper encapsulation, there would be no abstraction. Encapsulation not only helps a code achieve abstraction (shows only relevant functionality) but goes one step further and hides everything else, which is irrelevant to the user.

In essence, Encapsulation picks up where abstraction leaves off. In code, you will either have both abstraction and encapsulation, or you will have neither.

https://blog.beingcraftsman.com/datta/