Share
Explore

Coding Best Practices: Clean Code, Refactoring and TDD

This article is a compilation of knowledge and common practices that can help developers write better code. These practices can be applied to any programming language, framework or project.
The first section, “Code smell”, shows you what bad code can look like. Bad code may not be the wrong code, but it does show some potential problems in your software.
The second section, “Clean code”, shows you what good code looks like. (according to Uncle Bob).
The third section, “Refactoring”, introduces a techniques that are widely used in software development, an important technique in TDD. Refactoring helps you transform smelly code to clean code.
The final section, “Coding Convention”, gives you some tools and resources about coding convention for each language.

I. Code smell

According to Martin Fowler, “a code smell is a surface indication that usually corresponds to a deeper problem in the system”. Smells are certain structures in the code that indicate violations of fundamental design principles and negatively impact design quality. They are usually not bugs, they indicate weaknesses in the design that may be slowing down development, increasing the risk of bugs or failures in the future.
Detecting code smell is a skill required for all software engineer. Some tools can automatically check for certain kinds of code smell.
This is a short summary of common code smell, according to

Coding smells within classes/methods:

Comments: Do they explain “why” and not “what”? Can you refactor the code so the comments aren’t required?
Long methods.
Long parameters list.
Duplicated code
Conditional complexity
Combinatorial explosion: Lots of code does almost the same thing, but with tiny variations in data or behavior.
Large class.
Type embedded in name: Avoid placing types in method names.
Uncommunicative name: Could you read the method’s name to another developer and have them explain to you what it does
Inconsistent names.
Dead code
Speculative generality: Write code that worry about tomorrow problems that may not exist. .
Oddball solution: There should only be one way of solving the same problem in code.
Temporary field: Watch out for objects that contain a lot of optional or unnecessary fields.

Code smells between two classes:

Not just for OOP, but also for designing modules/structs:
Alternative Classes with Different Interfaces: Two classes are similar on the inside but different on the outside
Primitive Obsession: Don’t use a gaggle of primitive data type variables as a poor man’s substitute for a class. If your data type is sufficiently complex, write a class to represent it.
Data class: Avoid class that passively store data, it should also have methods to operate on that data.
Data clumps: If some kind of data always data hanging around together, maybe it belongs together. Consider rolling the related data up into a larger class.
Refused bequest: Inherit from a class, but never use any of the inherited functionality,
Inappropriate Intimacy: Watch out for classes that spend too much time together, or classes that interface in inappropriate ways. Classes should know as little as possible about each other.
Indecent Exposure: Beware of classes that unnecessarily expose the internals.
Feature envy: Methods that make extensive use of another class may belong in another class.
Lazy class:If a class that isn’t doing enough, can it be collapsed or combined into another class?
Message chains: Watch out for long sequences of method call or temporary variables to get routine data.
Middleman: If a class is delegating all its work, it should be removed. Beware classes that are merely wrappers over other classes or existing functionality in the framework.
Divergent change: If, over time, you make changes to a class that touch completely different parts of the class, it may contain too much unrelated functionality. Consider isolating the parts that changed in another class.
Shotgun surgery: If a change in one class requires cascading changes in several related classes, consider refactoring so that the changes are limited to a single class.
Parallel inheritance hierarchies: If every time you make a subclass of one class, you must also make a subclass of another, consider folding the hierarchy into a single class..
Incomplete library class: We need a method that’s missing from the library, but we’re unwilling or unable to change the library to include the method. The method ends up tacked on to some other class. If you can’t modify the library, consider isolating the method.
Solution Sprawl: If it takes five classes to do anything useful, you might have solution sprawl. Consider simplifying and consolidating your design

Additional resources:

The infamous Refactoring book by Martin Fowler:

II. Clean code

Clean code is code that is easy to understand and easy to change. Clean codes is opposite to the codes that are “smelly”.
0_EyKDdK-R4Qc3Qo94.jpg
© Focus shift / From the book Clean Code by Uncle Bob
These are some guidelines from the famous book “” by Robert C. Martin a.k.a Uncle Bob. You can find a similar resource from “”.
The code can be measured with either “good” or “bad” in the code review or by how many minutes it takes you to talk about it.
The code should be elegant, efficient, readable, simple, without duplications, and well-written.
You should add value to the business with your code.
Naming:
Should be meaningful and clearly indicate it does.
Should be pronounceable, related to the system domain, context
Avoid acronyms and avoid confusing names.
Replace magic numbers with named constants.
Method / Function:
Should be small. (< 20 lines, some believe that it should be < 10 lines)
Should only do one thing.
Small number of parameters: <= 2.
Always return something.
Shouldn’t create side effect.
Comment:
Explain what and why, rather than how.
Refactor the code to remove the comment if necessary. Prefer self-explanatory code to comment.
Comments can be used to express the importance of certain points in the code.
Formatting:
Set a limit of characters per line.
Use spaces between operators, parameters, and commas.
Similar functions should be close.
Declare variables close to their usage.
Class / Struct:
Should be small.
Do one thing.
Small number of instance variables.
Hide internal structure.
Base class should know nothing about their derivatives.
Prefer non-static methods to static methods.
Law of Demeter: one M method of an object O can only consume services of the following types of objects: The object itself, O; the M parameters; any object created or instantiated by M; direct components of O.
Unit test:
Follow the TDDs law:
Don’t create code before you have a failing test.
Don’t create more tests than necessary to fail.
You cannot write more code than enough to pass the test that is failing.
Use the F.I.R.S.T rule for testing:
The test is fast-running.
The tests are independent of other.
The test is repeatable in various environments.
The test is self-validating.
The test is timely.
Keep your test clean.
References:

III. Refactoring

Refactoring is the process of restructuring existing computer code without changing its external behavior. Refactoring improves non-functional attributes of the software.
Refactoring is an important technique in TDD. More about TDD will come in another article.
0_SH9fdMgM6aXglTM-.png

Purpose of refactoring:

Improve readability.
Reduce complexity
Improve maintainability
Create a more expressive internal architecture or object model to improve extensibility.
In short: Transform from bad smell code to clean code

Techniques

There is a list of refactoring techniques that you can quickly read at: . For details description, you can read the Refactoring book by Martin Fowler. The Refactoring to Pattern by Joshua Kerievsky introduces more techniques that are specific for object oriented patterns.

References

by Martin Fowler

IV. Coding Convention

Our team uses various languages, including Javascript, Python, Ruby, Golang. Each language has its own set of recommended conventions. This section will introduce list of conventions for each languages and tools you can use to automatically check for these errors. Although each language has its own convention, they are still follow basic principle of clean code that has been described in the second section.

Javascript

Convention:
Tools:

Ruby

Convention:
Tools:

Python

Convention:
Tools:

Golang

Convention:
Tools:
Tools:
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.