Clean code – what next?

Welcome in the second part of article about clean code. Last time we talked about importance of naming in programming and idea of small functions. I hope that previous lesson was helpful for you. I am certain that programming with clean code rules is easier and more enjoyable for you ;) Remember:

Good code is like a good joke – is needs no explanation.

Today we are going to talk about two another aspects of clean code. First of them are comments. Use them or not to use them – that is the question.

Good comment, bad comment

Comments are a real double-edged sword. Nothing can be quite so helpful as proper-placed comment. Nothing can be quite so damaging as deprecated comment that preaches untruth and disinformation. Programmers often disagree about comments role – they are pure good or necessary evil? I our case C# is a lot expressive language so we would not need comments very much to express our intent. It is fact that programmers often use comment to do fast makeup for bad code. This solution is like an adhesive tape – fast and easy though only for a moment. Unfortunately bad code even with beautiful makeup is still ugly bad code. Next time against comment confusing code just better clean it! For example:

//Check to see if the player done lethal hit to enemy below 30 hp
if(enemy.healthPoints < 30 && isCritical)  
…

If you will use separate function, your comment becomes unnecessary.

if(enemy.isLethalDamage(isCritical))  
…

In many cases better idea is to create a function that says the same thing as the comment you want to write. However some comments are necessary or favourable.

Good comments

In some situations comments will be very welcome:

  • Legal comments – often copyright and authorship statements are necessary things to put into a coment at the start of each source file. For example:

//Copyright © 2017 by University of Games sp. z o.o. All rights reserved.

  • Informative comments – it is sometimes useful to provide basic information with a comment. It is still better to provide this information by function name but in some case comment is quite good:
//Returns tracked Enemy object
protected abstract Enemy EnemyInstance();  
  • Intent explanation – sometimes comment provides also the intent behind a decision. In following case we see an interesting decision documented by a comment:
//Less value is better, red color cards are better than black
bool CompareCards(Card card1, Card card2){  
…
}
  • Clarification – of course always better is find way to argument or return value be more readable. But sometimes when we use some kind of external libraries that you cannot modify, comment can be very useful.

  • Warning of consequences – sometimes we can warn other programmers about certain consequences. For example:

//Do not use it every frame. Use only if is necessary!
AreaElements[] ScanArea()  
  • //TODO comments - my favourites :) TODO comments mark task should be done but for some reasons we can’t do it at the moment. What is important is regularly remove unused TODO comments
//TODO implement this function after introduce frozen feature
protected Enemy GetFrozedEnemy()  
{
    return null;
}


Bad comments

Unfortunately most comments fall into this category. The worst genres of comments are:

  • Redundant comments – extra comment which not more informative than code. For example:
//Method that return random powerup. Return null value if powerups list is empty
PowerUp GetRandomPowerUp()  
{
    if(powerups.count > 0)
        return powerups[Random.Range(0,powerups.count)];
    return null;
}
  • Misleading comments – not accurate comments which say another thing that they exactly do
  • Noise comments – they are nothing but noise. This comments describe obvious and provide no new information:
//Default constructor
public Weapon()  
{
}

//THX for information bro!
  • Closing brace comments – sometimes programmers will put comment on closing braces as below. This behaviour creates only chaos. IDE tells us which brace is on pair with selected one.
try {  
     …
     while{
           …
     } //while
}//try
catch {  
}//catch
  • Commented-out code – please, don’t do this. Old commented code is like an old dust. Other programmers don’t know if those commented lines of code are important or not. Probably they leave it commented. Next time don’t hesitate and remove unused code. You can always go back to it using source code control systems like git.

Abstraction and encapsulation

In OOP abstraction and encapsulation are going hand in hand, they help accelerate the pace of innovation by allowing software to evolve without being stuck in the trap of version incompatibility. What are the encapsulation and abstraction? Generally speaking:

Abstraction – allows us to represent complex real world in simplest way. It is a process of identifying the essential features and behaviours an object should possess.

Encapsulation – is a process of hiding all the internal details of an object from the outside real world. “Encaplsulation” is like “enclosing” into a “capsule”. It restricts from watching its internal view where abstraction behaviour is implemented.

With this definitions we can talk about why this two things are so important in object-oriented programming. Let’s look at practical example below:

//abstraction – exposing only the relevant behaviour
public interface IShootable  
{
    void Shoot();
}

//encapsulation – hiding things that the rest of the world doesn’t need to see
public class Archer : IShootable  
{
    //exposed information
    public string name {get;set;}

    //exposed but unchangeable information
    public int arrowsAmount {get; private set;}

    //internal i.e hidden object detail. This can be changed freely, the outside world 
    //doesn’t know about it
    private bool CanShoot(()
    {
        return arrowsAmount > 0;
    }

    //implementation of a relevant feature
    public void Shoot()
    {
        if(!CanShoot())
        {
            Debug.LogError(“No arrows!”);
            return;
        }
        LoadArrow();
        Aim();  
        Fire();
        }

        private void LoadArrow() {};
        private void Aim() {};
        private void Fire() {};
}

public class Gunner : IShootable  
{
    //implementation
} 

Any archer can shoot, because it implements IShootable ‘feature’. Having a group of shooters (list) this means that both Archer and Gunner are valid choices.
This means that:

//this method isn’t implemented in Archer or a Gunner class
//it can work with ANY object implementing IShootable
public void ShooterAttackOrder(IShootable shooter)  
{
    shooter.Shot();
} 

So you can have lots of implementors with plenty of properties and methods, but in this scenario what matters is their ability to Shoot. This is abstraction.

Since shooting requires some steps (LoadArrow etc.), these are hidden from the view as they are an internal concern of the class. The Archer has many other public behaviours which can be called by the outside world. But some details will be always hidden because are related to internal working. They’re private and exist only for the object, they are never exposed. This is encapsulation.

Concusion

There is a dirty little secret of code comments: to write good comments you have to be a good writer. Comments aren’t written for the compiler but for other people. Writing good, meaningful comments is hard, like an art of writing the code itself. In most cases if you feel your code is too complex to understand without comments – your code is probably just bad. The earlier you start rewrite it, the less effort is needed to get good results.

Objects expose behaviour and hide data. This makes it easy to add new kinds of objects without changing existing behaviours. Using of abstraction makes life easier. We don’t need to worry about update copypasted code from another class. The best solution is to write code in way where we need change code in only one place to update existing behaviour. I hope that you have enjoyed clean code rules. To learn more about clean code we recommend you excellent book written by Robert C. Martin: “Clean Code: A Handbook of Agile Software Craftmanship”.

I hope it’s useful for you. If you have any comments or questions, please write them here!

Mateusz Olszewski - Lead Programmer



Show Comments