Refactoring / Code Writing

Refactoring / Code Writing

If you want one of the best books that will help you become a better programmer, try this one: Clean Code: A Handbook of Agile Software Craftsmanship

And you can watch me try to apply some of the principles I got from the book in this video:

Disclaimer, I haven't read all of the book, because it kind of stopped me on the TDD, which is something I don't really do since I was never asked to do this in the first place. Come to think about, last year was the first time I've written any tests for an application, on a project in the forth company I've been working for.

But anyways, here are some rules and quotes I found interesting and which you can follow whenever you want to write new code.

Naming is very important

One difference between a smart programmer and a professional programmer is that the professional understands that clarity is king. Professionals use their powers for good and write code that others can understand.

Whoever is reading your code should feel like he's reading a story and understand what your program is doing by just reading the variable, function, class names.

This means that you should:

Avoid single letter variables, and use intention-reavealing names

ex: forget about var t (or single letter variables in general) and use var time

Use pronounceable names

ex: getClassroomStudents vs getClsStuds

This means that the names are searchable and easy to find in your code

you can still use single letter variables, in for loops, for example `for(let i = 0;...)

Class names should be a noun or noun phrase; also, don't use verbs as names

ex: use Customer, Product, ProductPage; avoid using words like Manager, Processor, Data or Info in the class names

Method names should use verbs and accessors, mutators and predicates should be prefixed with get and set with their value

ex: sendMessage, getName, setName

One word per concept meaning you shouldn't use multiple words describing the same concept

ex: get, fetch, retrieve used for getting data; just pick one and stick with it

Add meaningful context when there can be confusions made;

ex: state might make sense when it's together with city, country, etc. but might be confusing when used alone. You can add the info in a class or object or even prefix them with the word address

Shorter names are better than long one as long as they are clear; don't add gratuitous context

ex: if your app is named Featuring Code App, don't add FCA in front of every class

Functions

The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that.

The reason we write functions is to decompose a larger concept.

Blocks and indenting

The blocks within if/else/while statements should be one line long; This line should probably be a function call with a nice descriptive name.

The functions should not be large enough to hold nested structures and the indent level of a function should not be greater than one or two.

Do One Thing

You can have functions that call other functions and so on, if they serve the main goal of that function. If the function does coupled steps that are one level below the stated name of the function, then the function is doing one thing.

You can tell if your function is doing more than one thing if you can extract other functions from it that with a name that is not merely a restatement of its implementation.

To me, for example, this function is adding an element but doing two different things: creating a div with contend and appending the div

function addElement () {
  // create a new div element
  const newDiv = document.createElement("div");

  // and give it some content
  const newContent = document.createTextNode("Hi there and greetings!");

  // add the text node to the newly created div
  newDiv.appendChild(newContent);

 // add the newly created element and its content into the DOM
 const currentDiv = document.getElementById("div1");
 document.body.insertBefore(newDiv, currentDiv);
}

How I would make addElement do one thing is by renaming it and creating two new functions

function addNewDivWithContentBeforeDiv1() {
    const newDivWithContent = getNewDivWithContent();
    addHtmlElementBeforeDiv1(newDivWithContent);
}

function getNewDivWithContent() {
    const newDiv = document.createElement("div");
    const newContent = document.createTextNode("Hi there and greetings!");

    return newDiv.appendChild(newContent);
}

function addHtmlElementBeforeDiv1(element) {
    const div1Element = document.getElementById("div1");
    document.body.insertBefore(element, div1Element);
}

And before jumping to conclusions, OF COURSE I would have made the functions reusable, by accepting parameters and renaming the functions to addNewDivBeforeIdIdentifiedElement(newDivContent, id) and addElementBeforeIdIdentifiedElement(htmlElement, id)

Sections within Functions

Functions that do one thing cannot be reasonably divided into sections.

Reading Code from Top to Bottom: The Stepdown Rule

The code should read like a top-down narrative. Each function should be followed by those at the net level of abstraction, descending one level of abstraction at a time as we read the code.

The code should read like adding the word "to" in front of a paragraph

*ex: TO add a new div with content before div 1 we get a new div with content and then add the new div before the div 1

TO get a new div with content we create a new div, then create new content and return this new div

TO add a new div before the div 1 element we get the div1 element and then insert the new div before it *

Use Descriptive Names

Don't be afraid of long names. Although(this I got from the online lectures), the broader the scope of the function, the shorter the name (ex: start() or init()) and the more focused the function is, the longer the name.

Verbs and Keywords

Verbs should express the intent of a function. For example write(name) tells us that a thing called name is being written, but writeField(name) tells us that the name is actually a field.

Function Arguments

The ideal number of arguments for a function is none, followed by one, two and three. You can also pass an object if you have multiple arguments.

Don’t Repeat Yourself

Move repeatable code inside functions and call those functions instead.

Comments

Don't comment bad code - rewrite it

You should avoid writing comments all together, because the code should explain itself by the way it is written. Also, comments might become obsolete while the code functionality changes, which creates more confusion for the colleague working on the new code.

Some comments can be good, for example, explaining some abstract methods from some libraries.

Objects

Objects expose expose behaviours and hide data

The Demeter law

Don't talk to strangers. - which means that you should access data only from the direct children of an object and not by talking to children of children;

ex: ob.methodA() - is good, ob.methodA().methodB() or ob.a.b; - is bad

The book has 450+ pages so if you want to get deep into the rules, you can find it here Clean Code: A Handbook of Agile Software Craftsmanship