Clean Code – A challenge becoming harder to tackle

5 minutes to read read

Clean Code is something which seems so simple by names and most of the times something which is ignored and forgiven by most programmers of all ages, but it is one of the most important characteristic of maintainable code. You may be a top shot programmer highly skilled in structures and algos, but if it is not clean, it may end up as junk. Clean code is something which wraps all (yes all) the aspects of modern programming such as various Design patterns, principles etc. But yet, a lot of people forget (or rather ignore). Lets try to understand what it is, and why is it important. For the most part of the code I shall refer c# in this post, but this applies in general to any language, as its a paradigm to general coding practices not specific to any language.
Disclaimer: Also, this post may get a little longer and may seem a bit boring, but i would highly recommend reading it. Also, most of the content is what i learned by experience, suggestions and/or comments are welcome.

Brief summary of programmers life

I am in programming for about 15 years, initially as a freelancer, and for about last 10 years, working full time. Have been involved in code reviews and refactoring at multiple levels for about last 6 years or so. Also, i have been following several open source projects and also contributing in my part time. Basically in this post, some of the common issues I found across platforms are highlighted along with why are they important.

Let’s break the shackles. First and foremost the important thing.

Testable

Is your latest ground breaking code testable using unit-tests? This is a question you should ask yourself whenever committing anything. There are a lot of cases such as urgent deliveries, lack or processes or knowledge, limitation from framework and others that can reduce testability of your code. Consider the following code segments.

[ApiController]
[Route("/api/v1/locations/{location}/")]
class UntestableCodeApiController
{
    [HttpPost("launcher")]
    public bool FireRocket(double destinationLat, double destinationLong, bool useInfraRed = false)
    {
        var location = RouteData.Values["location"].ToString();
        var rocketLauncher = new CrazyRocketInterface("");
        Debug.WriteLine($"Lat: {destinationLat}");
        Debug.WriteLine($"Lat: {destinationLong}");
        Debug.WriteLine($"use infrared: {useInfraRed}");
        Debug.WriteLine($"Firing");
        var result = rocketLauncher.GetRocketResult();
        return result;
    }
   
}

There are two issues which can prevent writing unit tests to the above code. Firstly, RouteData (an static) is used to get location value, secondly CrazyRocketInterface instance is locally created. Apparently, all the classes other then one being tested should be mocked to test behaviors which will not happen.

The solution to this is using the abstractions (or read as interfaces for simpler term) and injecting them using DI.

Code Comments

XML Comments

If your code is shared across projects, or called outside, comments are required as it tells the outside world about your rocket breaking code, what it does, what it takes and what it returns.

Consider the following code.

public class RocketLauncher
{
    private string _rocketName;
    private string _launchCode;
    private CrazyRocketInterface _rocketInterface;

    public RocketLauncher(string rocketName, string launchCode)
    {
        _rocketName = rocketName;
        _launchCode = launchCode;
        _rocketInterface = new CrazyRocketInterface(rocketName);
    }

    public bool FireRocket(double destinationLat, double destinationLong, bool useInfraRed = false)
    {
        Debug.WriteLine($"Lat: {destinationLat}");
        Debug.WriteLine($"Lat: {destinationLong}");
        Debug.WriteLine($"use infrared: {useInfraRed}");
        Debug.WriteLine($"Firing");
        var result = _rocketInterface.GetRocketResult();
        return result;
    }

    public class CrazyRocketInterface
    {
        public CrazyRocketInterface(string rocketType)
        {
            
        }
        public bool GetRocketResult()
        {
            return true;
        }
    }
}

Now, lets assume this ground breaking code becomes hit, you publish your code as an api to other users. A few challenges over here, when ever a consume is initializing the code, he never knows what the code does, other then assuming from names. For an consumer the methods look like following.

Consumer accessing a non-commented code.

Lets say your consumers are smart and get variable names correctly, but they cannot make out the return type meaning of second method. It returns bool. But does that mean it is fired successfully, or command is passed successfully, or a lot of things, which can have yes no. All rest to the assumption of user using the code. Lets modify the code to add some xml comments as below.

/// <summary>
/// Initializes instance of Rocket Launcher by rocket name and launch code. 
/// </summary>
/// <param name="rocketName">Name of the rocket</param>
/// <param name="launchCode">Launch code to rocket</param>
public RocketLauncher(string rocketName, string launchCode)
{
    _rocketName = rocketName;
    _launchCode = launchCode;
    _rocketInterface = new CrazyRocketInterface(rocketName);
}

/// <summary>
/// Send the launch command to rocket.
/// </summary>
/// <param name="destinationLat">latitude of target</param>
/// <param name="destinationLong">longitude of target</param>
/// <param name="useInfraRed">should rocket seek Infra red</param>
/// <returns>returns true if command is processed successfully.</returns>
public bool FireRocket(double destinationLat, double destinationLong, bool useInfraRed = false)
{
    Debug.WriteLine($"Lat: {destinationLat}");
    Debug.WriteLine($"Lat: {destinationLong}");
    Debug.WriteLine($"use infrared: {useInfraRed}");
    Debug.WriteLine($"Firing");
    var result = _rocketInterface.GetRocketResult();
    return result;
}

The XML comments are visible when anybody uses or invokes your method. Additionally user can peek in to see more details. Refer to the below screenshot on how does the code looks to user.

XML Comments popping for consumer.

Inline Comments

Inline comments are self-explanatory and probably don’t require any explanation. Whenever you write something important or complex, such as firing a rocket, its always useful to put a single line comment. In most languages just a “//” and comment would work, “/******/” in many other languages.

/// <summary>
/// Send the launch command to rocket.
/// </summary>
/// <param name="destinationLat">latitude of target</param>
/// <param name="destinationLong">longitude of target</param>
/// <param name="useInfraRed">should rocket seek Infra red</param>
/// <returns>returns true if command is processed successfully.</returns>
public bool FireRocket(double destinationLat, double destinationLong, bool useInfraRed = false)
{
    //Write Logs to console
    Debug.WriteLine($"Lat: {destinationLat}");
    Debug.WriteLine($"Lat: {destinationLong}");
    Debug.WriteLine($"use infrared: {useInfraRed}");
    Debug.WriteLine($"Firing");
    //Send command to rocket interface
    var result = _rocketInterface.GetRocketResult();
    return result;
}

Naming

Class Names

Class names should be “Nouns” [fullstop]. Just follow the simple rule and you are good. For instance if your class is firing rocket, class name should not be “FireRocket” but may be “RocketFirer” or “RocketFiringManager” something like that.

Method Names

Method names should always be verbs. Which defines doing certain thing. For instance valid method names could be “InitializeFireSequence” or “FireRocket” or something.

Standard Practices

Some of the standard practices and conventions can be referred from Microsoft.

Thats all for now for this post. I shall try to consolidate some of the other areas such as parameters and arguments, usage of overloads, oops in application, code de-duplication, Cyclometic complexity, lines of code and several others in second part of the post. Keep watching to get updates, and comments are welcome.

Leave a Reply

Your email address will not be published. Required fields are marked *