Clean Code

Basic principles based on the book – Clean Code Robert – C. Martin

Introduction

Some time ago I read the book „Clean Code” by Robert C. Martin. I approached it with curiosity, but I have to admit, as it’s usually the case with technical books, that it was not a piece of cake. A lot of code to analyze slows down reading a bit, and focusing on Java also means that not all aspects of the book are universal.

So I thought that I could summarize the most important aspects common to different programming languages and create a small introduction to clean code.

I think it will be a good introduction for junior programmers and some revision for a bit more advanced ones.

Clean code

What is Clean Code? In my opinion, clean code is like a good book, everyone who reads it will know what is going on.

The problem with bad code is that we often don’t focus on code quality because time is running out. Because we’ll fix it later. Because we need to add something to the current code and we don’t want to mess with it too much, so we’re adding more bad code.

This is where further problems arise. Bugs that are hard to identify, code that takes a long time to understand, etc.

Unfortunately, sometimes (often) even the author can’t decrypt their own bad code after some time:-)

“It’s not enough to write working code. Working code is often badly written. Programmers who are satisfied only with working code are unprofessional.„


Therefore, in the following points, I will try to explain a bit the basic concepts  of the book. Of course, I also encourage you to read the book.

Names

Names should reflect intentions and be descriptive

A wrong name for a function, variable, or even class is often a problem. The name of the function should indicate what it is for and what to expect after its execution. Variable names should indicate what information they hold.

“Don’t be afraid to write long names. A long descriptive name is better than a short enigmatic one.„


Create clear differences

Avoid giving similar names to functions / methods / classes.

  • getAccount()
  • getAccounts()
  • getAccountList()
  • getAccountInfo()

What function should we use? How do they differ?

  • moneyAmount = money ??
  • accountData = account ??

Names that can be pronounced

It’s just easier  to work with names that are easy to pronounce and remember. When talking about code, it will be easier if you can pronounce the name of a variable / function.

The discussion about the first code will be more problematic than about  the second one below.

Names of classes and functions

Class names should be nouns or noun phrases e.g.:

  • Customer,
  • Account

Function names should be verbs or verbal expressions:

  • getAccount,
  • save,
  • postPayment

One word per concept

One specific word for one abstract concept should be used.

It can be confusing to use the names fetch, retrieve, get for similar methods in different classes.

Functions

They should be as short as possible

It has been assumed that the maximum size of the function should not exceed 20 lines of code.

One function should contain a maximum of 2 indents, if / else / while blocks and similar are considered as indents. They should be single-line, so they should contain a function call.

They should do only one thing

“Functions should perform one operation. They should  do it right and they should  do only that.„


Reading the code from top to bottom – „Top down rule”

For convenience, we want to read the code from top to bottom. That’s why after each function there should be another one at the next level of abstraction.

Avoiding side effects

This is, of course, related to naming functions. Let’s take such a function as an example:

We expect the above function will check the password, but a session initialization is  an unexpected side effect here.

Therefore, to avoid a side effect, the name of the function should be changed to e.g. checkPasswordAndInitializeSession.

Function arguments

Ideally, functions should take up to 2 arguments, maximum 3. When more is needed, they should be passed as an object. The boolean argument should also be avoided, as it indicates that the function is likely to do more than one thing.

Using exceptions instead of error codes

It is probably rare, but it sometimes happens: error codes are returned from functions. This should be avoided and exceptions should be thrown. Problem with error code is that it must be handled immediately.

With try-catch blocks, error processing can be separated from the correct code execution path.

Also note that functions that contain a try-catch block should do nothing but handle errors.

Comments

„Clean code does not require comments.”


Often code could function without any comment, but sometimes developers prefer to add an explanation comment rather than „code” it, e.g.:

And it can be also done in such a way:

There are, of course, „good” comments, including:

  • Legal Comments
  • Informative comments
  • Comments of intentions
  • TODO Comments
  • Consequence Warnings
  • Enhancement
  • Javadoc /… doc comments in public API

I don’t want to focus on describing them, I encourage you to read the book.

Tests

The basic rule in writing tests is that tests should be written along with the code. As the code changes, the tests should also be updated.

Here are some additional rules:

Clean tests

„What makes the tests clean? Three elements: legibility, legibility, legibility.„


One assertion per test

Sometimes it seems obvious to make more than one assertion in a test. However, there is a programming school that says that there should be one assertion per test.1

This has some advantages, because in the case of a failed test, it is easier to find the error. For example, a fairly simple test:

A fairly simple test can be made into 3 smaller ones, which may seem redundant, but with more tests and appropriate names it is easier to spot possible problems.

One concept per test

It is important give each test function a single concept . We shouldn’t write long test functions which test one thing after another. It is also related to the principle described in the previous point:  after separating tests they are both clearer and easier to understand.

F.I.R.S.T rules

Clean  tests shall follow five  F.I.R.S.T rulet:

  • Fast – tests should work fast
  • Independent  – tests should not depend on each other. They should  work individually and in a chosen order.
  • Repeatable – tests should be repeatable in every  environment: developer, production, on a laptop…
  • Self-validating – should  give clear information: success / fail
  • Timely – tests should be timely written , i.e. immediately before the tested production code is created.

In my opinion, these are the most important basic rules of writing good, readable, clean code. There are of course more detailed rules and recommendations, if you would like to know more  you’d better read the book.            

1https://www.artima.com/weblogs/viewpost.jsp?thread=35578

Written by
Bogusław Marcinków

No items found.