How to write clean code?

Vignesh Sathiyamurthy
4 min readAug 16, 2022

--

What is clean code? Everyone has a different answer. The following are some of my observations from reading blogs, books and a decade of professional experience.

Naming conventions

  • Don’t use abbreviations.
  • Searchable names are better
  • Avoid using coded names

Class names should be nouns.

public class User() {}public class Company() {}

Function names should be verbs, name should clearly state the action they perform.

public User fetchUserByEmail(String email) {}public void deleteUserById(String id) {}

Variables and arguments should be short and descriptive.

String firstName;String billingStatus;public Subscription updateSubscription(UpdateSubscriptionRequest updateRequest) {}

Constants should be all upper-case

String DATE_FORMAT = "YYYY-MM-DD";
String API_KEY = "XXXXXXXX";

Intention revealing names, code is way to communicate with developers reading it.

public boolean isUserHasPermission() {}public List<User> sortUserByAge() {}

Pick one word per concept is abstract and stick with it.

// bad practice 
public List<User> getUsers() {}
public List<Message> fetchMessages() {}
public List<Contacts> retrieveContacts() {}
// good practice
public List<User> fetchUsers() {}
public List<Message> fetchMessages() {}
public List<Contacts> fetchContacts() {}

Classes

  • Classes should be small and contains small functions that strongly promoted idea of abstracting any and every piece of logic that may even are nominally complex into a separate function of something.
  • Use access levels properly.
  • Keep the utility functions and variables are private except some cases for testing.
  • Expose necessary variables through getter and setter.

Functions

  • Functions should short and do only one thing. If our functions is doing more than one thing, it is perfect moment to extract to another function.
  • Small functions are easy to understand.
  • Pass few arguments as possible, ideally none.
  • Functions should not be longer than 20 lines and mostly less than 10 lines.
  • This means that if statements, for and while loops should be one line long, obviously this line should be calling another function.

Software Engineering Principles

  • DRY - Don’t repeat by yourself
  • Kiss - Keep it simple stupid
  • SOLID Principles

Don’t repeat by yourself

  • A piece of code should not be repeated across the software.
  • Reduce duplicate and increase reusability.
  • Reusability means less code which leads to better maintainability, but remember some reusability can actually increase readability.
  • Opposite of DRY is WET - Write everything twice, We enjoy typing, Waster everyone time.
  • General rule, when you write something thrice, it is time to refactor the logic to a function and reuse.

Keep it simple stupid

  • Keep the code as simple as possible.
  • Avoid unnecessary complexity for better understanding and maintainability.
  • To keep the code simple, break down the problem into small steps or functions.

SOLID Principles

  • Single responsibility principle - One function should do only one thing. If a function does more than one thing, then the function should be split into multiple functions.
  • Open or closed principle - The entity should open for extension, but closed for modification.
  • Liskov substitution or substitution principle - A variable of a given type may be assigned a value of any sub type, and a method with a parameter of a given type may be invoked with an argument of any subtype of the type.
  • Interface segregation - Larger interfaces should be split into smaller ones. By doing so, we can ensure that implementing classes only needs to be concerned about the methods that are interesting to them.
  • Dependency inversion principle - High level modules should not depend upon low level modules. Both should depend abstrctions.

Code formatting

Code formatting is about communication.

  • Functions should be separated by blank lines
  • Concepts that are closely related must be held together vertically.
  • Instance variable declarations should be in one location and most preferably on the top of the class
  • Dependent functions should be vertically close, the caller should be above the Callee
  • Lines should not exceed a maximum 200 characters.
  • Don’t break indentation rule, even in the case of short, if statements or functions

Comments

  • Comments should be used only as an explanation. If we write functions in a descriptive way, we can avoid writing comments at all.
  • Do not write comments for what you are doing, instead write comments why you’re doing.
  • Specify about hacks, workaround and temporary fixes.
  • Don’t write redundant comments, if the code is self explanatory, no need to add comments.
  • TODO & FIXME comments are ok, because the IDE can find them easily before ending the project.

Logging

  • Avoid excess or less logging
  • Avoid printing object
  • Use correct log levels ERROR, WARN, INFO, DEBUG

Exception Handling

Things can go wrong, and when they do, we are responsible for handling and throwing valid responses, user can understand.

  • Do not allow functions to take null parameters, use preconditions.
  • Consider throwing specific exception rather than throwing null.
  • Try not to catch general exceptions, instead catch specific exception and throw an appropriate code and message to the user.
  • In the catch block, log exceptions and throw exception with all useful information. Don’t do anything extra.
  • Finally block to execute clean up code like close connection, file and freeing up threads, etc.

Tests

  • Unit tests should be fast and executed in a short time.
  • Tests should not depend on other tests.
  • One assert per test.
  • Write unit tests to verify function arguments, conditional statements, exceptions and expected results.

Note: In my next posts will explain each topic separately with an example.

--

--