Introduction
- Writing clean code is very essential is easy to
read,understand and maintain
. It increases quality of a resulting product andfaster resolution of bugs
.
Things to keep in mind
Make it work and then make it right
- Code should be getting better with time
Speed is not the criteria
for a developer- The attitude that we can go fast now and we can deal with the mess later, is bad.
If you are not clean, mess will slow you down within an hour
- Requirements are urgent but architecture is important
- A file size should not exceed 100 lines of code.
Naming
- A variable should be named in
camelCase
, so that it explains clearly what that variable is. - Class should be named as nouns(sometimes as verbs),
- Functions should be named as verb,
- Booleans should be named as a question(is, are, should, has etc.).
Don't be afraid of writing big names
. Its good if it explains what it does clearlyArray - e.g
fruitArr, fruits, fruitNames, fruitList
- Boolean -
prefix(is, has, have, are, should, can)e.g isUserAuthorized, areChanged, hasFruit, shouldFetchData, canDataChange
- Numbers - e.g
minDogs, totalPersons, filteredBoxLength
- Functions -
prefix(get, set, reset, fetch, remove, delete, handle, update, replace, add, insert, hide, do, mutate, trigger) e.g getUser, calculateTotal, fetchData, setInformation, updateDetails, changeAppearance, createMenu, addMonthToDate
,
Functions
- A
function body length should be in the range 1-10 lines
, Shorter the function easier it is to understand. - A function
should do only one thing
. - use of _functionName to indicate its a utility function that is used by other public function. e.g
// myFunction is exposed to client
function myfunction(){
_utilFunc1();
}
function _utilFunc1(){
// do something
}
- Restrict function arguments to 2, if more then pass them as object e.g
<!-- BAD -->
function f1(p1, p2, p3){
/do something
}
<!-- GOOD -->
function f1(paramObj){
// do something
}
f1({p1, p2, p3});
- Similar finctions/concepts should be grouped together ( so that developers wont have to jump up and down)
Most important functions come first
Avoid if-else in a function based on some flag
, rather create 2 separate function, same goes for switch case as well
<!-- Bad -->
function createFile(name, temp) {
if (temp) {
fs.create(`./temp/${name}`);
} else {
fs.create(name);
}
}
Separate Query from modifier : If a function is modifying an object and returning something as well, seprate this function into 2 functions, one for query and other one for modifuying an object.
Function callers and callees should be close
: If a function calls another, keep those functions vertically close in the source file. Ideally, keep the caller right above the callee. We tend to read code from top-to-bottom, like a newspaper. Because of this, make your code read that way.
If-Else
avoid negative conditions
<!-- BAD -->
if(!ispresent){// do something}
<!-- GOOD -->
if(isAbsent){// do something}
Always write linear code
. If You have a group of nested conditionals and it is hard to determine the normal flow of code execution.
<!-- BAD -->
public double getPayAmount() {
double result;
if (isDead){
doSomething1();
}
else {
if (isSeparated){
doSomething2();
}
else {
if (isRetired){
doSomething3();
}
else{
doSomething4();
}
}
}
return result;
}
<!-- GOOD -->
public double getPayAmount() {
if (isDead){
return doSomething1();
}
if (isSeparated){
return doSomething2();
}
if (isRetired){
return doSomething3();
}
return doSomething4();
}
Complex Conditionals
- When a long conditional is used in a If statement, we can extract them into a separate function or a separate const variable
<!-- BAD -->
if (date && date.actual() !== 0 && (date.before(12) || date.after(9)) ) {
return 'Date is correct'
}
<!-- GOOD -->
const isDateValid = date && date.actual() !== 0 && (date.before(12) || date.after(9))
if(isDateValid){
return 'Date is correct'
}
<!-- OR GOOD -->
function isDateValid(){
return date && date.actual() !== 0 && (date.before(12) || date.after(9))
}
if(isDateValid()){
return 'Date is correct'
}
Special Number
Your code uses a number that has a certain meaning to it. name them in SNAKE_CASE
<!-- BAD -->
potentialEnergy(mass: number, height: number): number {
return mass * height * 9.81;
}
<!-- GOOD -->
static const GRAVITATIONAL_CONSTANT = 9.81;
potentialEnergy(mass: number, height: number): number {
return mass * height * GRAVITATIONAL_CONSTANT;
}
Comments
- comments should not explain code;
code should explain itself
- Avoid too much details in comments
- Reveal intent( like rational, why some decisions were made, or why certain algo were used)
To caution the developer of something
- Remove commented code, we can retrieve them in future if needed from version control
Only comment on complex logic or Business logic
Add TODO
, when yun intend to do something in the future. e.g // TODO: ensure error handling is done properly
Javascript clean code tips
- variables decalaration
let a = 1, b = 2;
let [a,b] = [1,2];
let a, b = 2;
- Swapping numbers
let [a,b] = [1, 2];
[a,b] = [b,a]
- let and const : When we know that some declaration should not be changed, we should maximise use of const.
<!-- BAD -->
let myfunction = ()=>{}
<!-- GOOD -->
const myFunction = ()=>{}
Array :
use of map, filter, reduce, forEach, for(let item of fruitList)
Destructuring object :
<!-- BAD -->
const name = employee.name;
const email = employee.email;
const phone = employee.phone;
<!-- GOOD -->
const {name, email, phone} = employee;
- Use of promises and async and await
<!-- BAD -->
function1(function (err, data) {
...
function2(user, function (err, data) {
...
function3(profile, function (err, data) {
...
function4(account, function (err, data) {
....
});
});
});
});
<!-- GOOD -->
function1()
.then(function2)
.then(function3)
.then(function2)
.catch((err) => console.error(err));
<!-- VERY GOOD -->
async function myAsyncFunction() {
try {
const data1= await function1();
const data2= await function2(data1);
const data3= await function3(data2);
return function4(data4);
}
catch (e) {
console.error(err);
}}
- Usageof && :
<!-- BAD -->
if(data){
if(data.person){
result = data.person.name;
}
}
<!-- GOOD -->
result = data && data.person && data.person.name;
- usage of || : Can be used for setting the default value;
<!-- BAD -->
if(!name){
data = 'defaultName';
}
<!-- GOOD -->
data = name || 'defaultName';