No one writes clean code from the get go, our first attempt is always to make the code run and heavily biassed towards code production speed than code quality. Many developers skip the cleaning step because it takes about same amount of time it took to write the code.
As a developer, there are two parts to your job
- Communicate with computers
- Communicate with peers
Getting the code run (communicate with computers) is only half of the job, and it is the least important. You must write code that is maintainable by someone else(communicate with peers) .
The only way to go fast is to go well.
Clean code is a piece of code which make up a function that does one thing well. How do you define or measure one thing? Objectively speaking, you know you have a clean code if you cannot extract out another meaningful function from it.
Clean code is simple and direct, reads like well written prose.
Clean code looks like written by someone who cares.
Clean code is when each routine you read is exactly as you expect, and there are no surprises.
Function names should be verbs, because functions carry out actions.
Function should take no more than 3 arguments, because the number of ways to place the arguments increases factorially. For large number of arguments, make an object or use other data structures. Don’t pass boolean into functions in most cases, because it means the function must have an if statement in the function body, better to have two separate functions and call the corresponding one in each case. For a group of functions that manipulates a common set of variables, use a class.
As aside to function inputs, outputs out of context can be distracting too. If returning error, prefer exceptions to returning error codes.
The First Rule of Functions:
Function bodies should be small, which means they should do one thing. Continuously extract logics from them until you can't anymore. You will end up with a semantic tree of functions with function names, packages and modules.
Every line of a function should be at the same level of abstraction. It is like journalism, level of details increases as you read on and each title is self explanatory. It allows readers to exit early and only read parts that are interesting to them. Bad code means readers have to understand and read each and every single line of code without choice.
Avoid switch statements, it is fragile and not easily adaptable. There are two associated drawbacks:
One should be able to extend the behaviour of a module without modifying it, which is not possible with switch statements. Creating base classes instead would solve such problem.
Open-Closed Principle (one of SOLID principle): a module should be open for extension but closed for modification.
Switch statements act as a dependency magnet, makes it difficult to independently compile and deploy programs e.g. jar file is a runtime linking loader, so you can independently deploy parts of program like the GUI which constantly changes (Isolate GUI from business rules and database).
Use explanatory variables where appropriate to explain context/content.
Don't repeat yourself - DRY principle.
There are two types of functions:
- command functions have side effects, change state of the system
- query functions have no side effects, simply return values
Side effect functions come in pairs (e.g. new-delete, open-close), pairs of functions must be called in the right order, so contain the pair within the same function make more sense to avoid memory leaks (usually such function will return void). Garbage collection makes it easy to forget free allocated memories.
By convention, you should aim for command and query separation.
Every algorithm can be written out of sequence, iteration, selection(if-else), so then algorithm can be proven correct (No goto statements in Java)
However, programming is not the exact equivalent to math theorems, we write tests to prove the software is not incorrect instead of proving it to be correct.
credit @Clean Code Uncle Bob Lesson 1