Good/Bad Comments and Code Formatting: #CleanCode P3

How "Comments" can make your code Clean and Messy. Proper comments and Code Formatting makes a developer's life easier. How? Check out this blog...

Previously we have Covered! 🗺👨🏽‍💻

Hello guys 🙋🏽‍♂️, I'm back with another #CleanCode✨ series. This is Part 3. If you have missed previous blogs, please also go through🧐 them after this. Previously we have covered:

  1. What is Clean Code? Why do we require and should follow such practices?🦾 How helpful it will be for developers and other program managers.

  2. Several pitfalls🤮 are where most of the mess we create is, how should we incorporate #CleanCode in our coding lifestyle? Difference between CleanCode and QuickCode.

  3. Naming Conventions for variables, functions and Class objects. 🤷🏽‍♂️How should we name them? How does the naming of them matter the most in the developer's world? Why should we have to be consistent with the naming practices?

Roll of Comments in Developer's life?🤓

Famed MIT professor Hal Abelson said: “Programs must be written for people to read and only incidentally for machines to execute.”

Generally, we comment to make the code relatable and subjective. We describe them and add properties and functions which help us to predict the behavior.🙄 We find some programs harder to understand than others, and we look to comments to help us make sense of them. Different languages have different conventions to make placing comments on code.👨🏽‍💻 For Eg.,

LanguageComment sign
HTML<!-- Comment -->
Markdown<!-- Comment -->
Slim/ Comment or /!Comment
Pug//- or //
Haml-# Comment or /Comment
CSS/* Comment */
PostCSS/* Comment */
Sass// or /* */
SCSS// or /* */
LESS// or /* */
Stylus// or /* */
Javascript//Comment or /*Comment */
TypeScript//Comment or /* Comment*/
LiveScript#Comment or /* Comment */
CoffeeScript# or ### Comment ###

To find out the shortcut for the comment expressions, on VS Code:

Menu --> Preferences --> Keyboard Shortcuts --> search for Comments

👦🏽Comments? For Beginners and Professionals

When I started coding, my code lines had more comments than my codes.🥺 I used to write everything I hear from the instructor. Every word and every instruction. However, it helped me a lot in understanding codes and processes. But it was too many comments.😥 I used to take 30+ mins to finish the 5-6min class video. That is why It took 90 days to finish my first coding tutorial course of 45 days.😫

I’ve also heard of instructors requiring students to comment on every line of code.👨🏽‍💻 While this may be a reasonable policy for extreme beginners, such comments are like training wheels and should be removed when bicycling🚴🏽‍♂️ with the big kids.🧑🏽 Comments that add no information have negative value because they:

  • add visual clutter

  • take time to write and read

  • can become out-of-date

    Policies requiring comments for every line of code have been rightly ridiculed on Reddit:

      // create a for loop // <-- comment 
      for // start for loop 
      ( // round bracket 
          // newline 
      int // type for declaration 
      i // name for declaration 
      = // assignment operator for declaration 
      0 // start value for i
    

    So mostly, comments are considered redundant in codes. Typically we should avoid it✋🏽. An experienced programmer should understand the code with its structure and functions.👨🏽‍💻

Bad Comments: How to avoid them?🤷🏽‍♂️

Comments should be adding value or describing an original logic, not translating syntax. It also does not duplicate👩🏻‍🤝‍🧑🏼 what is written in the code. We have learned in the previous blog, proper naming of functions and variables can solve most of the developer's problems and heavy commenting is one of them.

// Acts as an adapter, connecting models to various database engines(SQL, mongoDb etc)
class Database {
    private dbDriver: any; // the database engine to which we connect

    loadDatabseDriver(driver: string) {
        if(driver === 'sql') {
            this.dbDriver = sqlDriver;
                // connect to sql driver if 'driver' is set to sql
        } else {
                // otherwise, connect to MongoDb
            this.dbDriver = mongoDbDriver;
        }
    }
    connect() {
    this.dbDriver.connect(); // this may fail and throw error
    }

Since comments like this can be avoided by practice and by using proper names. Such comments also show different negative sides of the developer, like lack of basic code clarity and confidence, careless approach to coding and code maintainability.

The code could be written like this:

class Database {
    private dbEngine: any; 

    loadDatabseDriver(driver: string) {
        if(driver === 'sql') {
            this.dbEngine = sqlDriver;                
        } else {                
            this.dbEngine = mongoDbDriver;
        }
    }
    connect() {
        try(
        this.dbEngine.connect();
        ) catch(error) {
            alert(error);
        }
    }
}

Types Of Bad Comments:😖

  1. Redundant Info giving comments

  2. Dividers and Block Markers

     /**
     *************************************
     *  Global Variables
     ************************************
      */
    
     let count = 0;
     let slides = 0;
    
     // ***************************
     // Classes 
     //***************************
     // Act as adapter, connecting models to various database engines (SQL, mongoDb etc)
     class Database {
         private dbDriver: any; // the database engine to which we connect
         .....
    
  3. Misleading Comments

inserData(data: any) {
    this.dbEngine.insert(data);  // update data of user
}

The road to hell is paved with good intentions*.* The author can put an inaccurate comment for all the right reasons, yet that would cost a poor programmer an expensive debugging session. Here it inserts data of the user in the database, but comments instruct about updating data. This should be avoided. Comments should dispel confusion, not cause it.

Comment-Out Codes which are not relevant anymore. Commenting while development is useful but Comment-out before committing it for production is the must-do operation.

Good Comments:

Those comments which should get a proper place in the codes are as follows:

  1. Legal disclaimers and Information (should be placed on the top of the file).

  2. Explanations that can't be replaced by good naming like regular expressions,

     //accepts [text]@[text].[text], i.e, it simply requires an "@" and a dot
     const emailRegex = /\S+@\S+\.\S+/;
    
  3. Comments containing Warnings, like any API will work only available in the JS running in the browser.

     // only works in browser environment
     localStorage.setItem('user', 'dummy@dummy.com');
    
  4. A #todo note during development. However, it should be removed after working on that #todo. So it is just a temporary comment which should not to pushed🙈 to production.

     findUserById(id: string) {
     // *Todo*: require id param from model
     }
     //  oR
     // TODO(hal): We are making the decimal separator be a period, 
     // regardless of the locale of the phone. We need to think about 
     // how to allow comma as decimal separator, which will require 
     // updating number parsing and other places that transform numbers 
     // to strings, such as FormatAsDecimal
    
  5. Documentations📓 and references of code:

  6. Add comments when fixing bugs 🎃

      // NOTE: At least in Firefox 2, if the user drags outside of the browser window,
       // mouse-move (and even mouse-down) events will not be received until
       // the user drags back inside the window. A workaround for this issue
       // exists in the implementation for onMouseLeave().
       @Override
       public void onMouseMove(Widget sender, int x, int y) { .. }
    

    Some mandatory comments might not be that useful after all. Comments should not be just clutter. The general perception and convention instruct not to comment on the production-ready codes.

How does Code Formatting🤿 help in #CleanCode?

Code formatting is crucial and considered equal in terms of the importance of Clean-code. It enhances readability and helps in code maintenance. Formatting rules although differ between languages.🎭 There are language-specific conventions and guidelines for code formatting. These are often referred to as 'style guides', simply search for a ''Python style guide'' or any other language style guide you want.

Code Formatting is of two types:

  1. Vertical Formatting: where we format the code from top to bottom. It includes spacing between the line of codes, grouping of codes, and placement of functions and variables etc.

  2. Horizontal Formatting: where we format the code line by line. We ensure indentations, space between code, variables in expressions and syntax, and maintain proper line width.

How to format the code?🤷🏽‍♂️

  1. The code should be smooth🏄🏽‍♂️ in its layout. From top to bottom, we must avoid too many jumps🏃🏽‍♂️ like, function/method initialization and execution should be placed near each other to avoid jumps.

  2. Ordering of the codes also should be considered before placing functions and methods away from their execution,

  3. If the code file turns huge, consider splitting multiple concepts of similar type into small files. Refactoring♻ of code comes here very handy. For, e.g. it is a rule of thumb that one class should be contained in a single file, i.e. one class per file.

  4. We should follow MVC (Model-View-Controller) pattern for formatting the code in multiple files. It will make the code cleaner and more readable, especially in big projects.

  5. In a file, we should give proper spacing to different concepts or areas of code. A single blank line makes the code more readable. IDEs now come with code formatting extensions, for eg, in VSCode, it is "Prettier" which auto format the code.

     start();
     function next() {
         console.log('next');
         last();
     }
     function start() {
         console.log('start');
         next();
     }
     function last() {
         console.log('last');
     }
    

    This will execute without any error because JS kept open all the functions defined during its execution. But this syntax does not execute in Python.

     # won't work if we execute start() here, as it have not initialized the function yet.
     # start()
    
     def start():
         print('start')
         next();
    
     # won't work because it uses next() method which is not initialized yet.
     # start()
    
     def next():
         print('next');
         last();
    
     def last():
         print('last');
    
     start();  # now it would work
    

For Horizontal Formatting, lines of code should be readable without scrolling right or left, hence code expressions should be short and properly indented. Python🐍 requires technical indentations to define the scopes, but in other languages, it would be better to use proper indentation. Break long statements into multiple shorter ones and avoid unreadable long names.

Using extensions and including simple formatting practices in codes will make the code more readable and maintainable. We can tweak the default formatting of the extensions to our liking, but extensions like Prettier are very handy and quick for trivial tasks. For, e.g.,

const navBarProps = {name:["John Doe", null],
displayMode: ["dark", "light"],timezone: ["ET", "CT", "MT", "PT"],
};

function allCombinations(obj) {let combos=[{}];
for(const[key, values] of Object.entries(obj)) {combos = combos.flatMap((combo) =>
values.map((value) => ({ ...combo, [key]: value })));}return combos;}

console.log(allCombinations(navBarProps));

Prettier can change it into this:👇🏻👇🏾

const navBarProps = {
  name: ["John Doe", null],
  displayMode: ["dark", "light"],
  timezone: ["ET", "CT", "MT", "PT"],
};

function allCombinations(obj) {
  let combos = [{}];
  for (const [key, values] of Object.entries(obj)) {
    combos = combos.flatMap((combo) =>
      values.map((value) => ({ ...combo, [key]: value }))
    );
  }
  return combos;
}

console.log(allCombinations(navBarProps));

Important

This article is not an invitation to ditch comments. Comments are powerful tools, just use them wisely and invest in their quality, Also never forget that refactoring the code is key.

What would be in the next blog?🦥

In the next blog, we'll talk specifically about the "Functions", major pitfalls💩 where we mess in different ways, like initializing, naming, setting arguments, parameters and indentations, especially technical indentations. 😣

Functions are the executives of our code, their proper and efficient execution can change the game all around. Frameworks and libraries are built on creating such functions to make the developer's life easier.🕺🏽💃🏽

So We'll talk about:

  • how to write clean functions,

  • how to give them parameters and arguments, and how we can be clean there.

  • structured functions body, its length, abstraction levels, and how can we split the function into multiple functions to make it cleaner and enhance readability.

So, I'll see you in the next blog. Adios 🤹🏽‍♂️