Skip to content
Go back

The Art of Writing Clean Code - Rule of Thumb for Software Engineers

Table of Contents

Open Table of Contents

TL; DR

include your voice in every section
- A decision: one explicit trade-off you made.
    
- A metric: p95 latency, error rate, or cost.
    
- An artifact: ADR/test/diagram you’d link.
    
- A drill: a tiny 5–10 min exercise for readers.

Motivation

When I had started out as a software engineer 10 years back, I remember reading that code should be clean, concise and maintainable. I tried to read multiple blogs to form an opinion, but at the end what helped was learning the painful way. Face an issue, deep dive and root cause it, find the best way to resolve the issue and then save it in my memory palace so that I don’t forget it (lol jk…being the lazy person that I am, the true process I followed was to keep forgetting and re-learning).

This blog post, I felt, would be a good way for me to document it so that it would useful for future me as well as any people who might face similar issues and thus feel the need for a checklist of sorts to ensure they are writing code which would cause them (and their team members) the least probability of waking up late at night in order to douse fires in their codebase, when they least expect it.

Trigger

Like before any code release, our team was heads down in the development cycle, working hard to ship the features before our User Acceptance Testing that was going to happen the next week. I received a Code Review from a junior developer on the team. The code changes he had made were simple enough, an API which would read from the Database and service the request made from the frontend, but what bugged me was one value which was being inserted into the table column called MetricType. In order to confirm what the use of that column value was, I checked the codebase and found it was used for insertions into the database only, no business logic depended on it. I dug deeper, in case there might be functionality which is not straightforward. I checked the cron jobs, our team’s documentation, as well as the database triggers to see if other table columns might be dependent on it, still nothing. Frustrating right?

How many times has it so happened, that the service you own has tech debt, that the documentation is not that great because you might have prioritized velocity to get features out faster? In the above scenario, in case the method was documented correctly, it would have been easier figuring out the functionality thus saving me the time I had to spend looking around. Which brings me to the main point this blog is all about.

Writing clean code should be about reducing the mental load on the next reader.

Just imagine, you write some code. 3 months later, you are trying to fix a bug in the codebase. You stare at your screen, soaking in the code, thinking to yourself: “This code could be a lot better. Who is the idiot who wrote this code?”. You check the Git Blame and behold it was your intern. That guy should not have received the return offer! But just in case what if it was you who had written the code?

Always write code as though the person reading it in the future will be someone who has no idea about the codebase at all. You want to make it as easy as you can for them to follow the code. That my friends is what clean code is all about.

Name By Intent

This may sound very basic, but regardless of what you are naming, be it APIs, variables or be it your pet, always name it by intent. What this means is avoid generic names like someStuff(), xx and doggie respectively. Instead the names should depict the what and why of the functionality for example, getDocumentPreSignedURL(), downloadTimeStamp and Scooby Doo (in case you want it to solve cases).

A good rule of thumb question to ask yourself would be:

Is this name going to make sense to a new joinee in 2 years?

Names are in a manner the first line of documentation. If you look at the name and are able to figure out what the API or variable is doing, that is a huge help in setting context and making it easier to understand the code for the reader.

Before:

  Map<String, String> m = get(id);  
  if (m != null && m.containsKey("s")) {
    process(m.get("s"));
  }

After:

  Map<String, String> sessionRepository;
  Optional<UserSession> session = sessionRepository.findById(userId);
  session.ifPresent(this::startLoginFlow);

Methods should be small; single-purpose


Share this post on:

Next Post
My First Post