Abílio Azevedo.

Clean Code

Cover Image for Clean Code
Abílio Azevedo
Abílio Azevedo

Uncle Bob brings us the necessary principles for clean code and encourages the practice of these principles to develop the skill of being a clean code craftsman.

5S Principles:

  • Seiri - Organization (think "Sort") - Knowing where things are.
  • Seiton - Arrangement (think "Systematize") - Code should be where you expect to find it.
  • Seiso - Cleaning (think "Polish") - Refactoring and eliminating comments.
  • Seiketsu - Standardization (think "Standards") - Maintain standards among the development team.
  • Shutsuke - Discipline (think "Self-discipline") - Maintain discipline in adhering to clean code practices.

We always need to maintain and improve our code, making it cleaner. Often, we make the code work and consider it done.

Part I - Principles, Patterns, and Practices for Creating Clean Code

1 - Clean Code

  • Codes represent the details of requirements. Specifying them in detail so that the machine can execute them is programming.
  • Bad code can ruin companies. Maintaining bad code is costly.
  • Don't let yourself be corrupted by managers' deadlines. They defend the deadlines, and you have to defend clean code as a deliverable. Disorganized code will only delay deliveries.
  • Writing clean code is like painting a picture. Most of us can distinguish a well-painted one from a poorly painted one. But not everyone can paint well.
  • Clean code does one thing well, requires attention to detail, and is simple and straightforward. It is readable, understandable, and all information is expressed within the code itself. Code without tests is not clean.
  • Scout Rule: "Leave the campsite cleaner than you found it." Always refactor.

2 - Meaningful Names

Use meaningful names that reveal the purpose of the code. Use searchable names.

3 - Functions

Functions should not have too many parameters. Functions should not have logical parameters that require entering the function and understanding their use.

4 - Comments

"Don't comment bad code, rewrite it." Old comments are harmful as they spread lies.

5 - Formatting

Follow alignment and spacing standards. Avoid excessive indentation layers. Follow a logical order of declarations and function calls.

6 - Objects and Data Structures

"Objects should hide their data and expose operations" - Law of Demeter

7 - Error Handling

Use exceptions instead of returning error codes. Create informative error messages and pass them along with exceptions.

8 - Boundaries

When using code that is out of your control, pay special attention to your investment and ensure that future changes are not too costly. Using a single point of contact with external libraries is a good approach.

9 - Unit Tests

Tests are as important to project health as production code. TDD

  • First Law - Don't write production code until you have a failing unit test.
  • Second Law - Don't write more of a unit test than is sufficient to fail, and not compiling is failing.
  • Third Law - Don't write more production code than is necessary to pass the current failing test. FIRST Tests need to be clean and follow the F.I.R.S.T rules:
  • Fast - Tests should be fast.
  • Independent - Tests should not depend on each other.
  • Repeatable - Tests should be repeatable in any environment.
  • Self-Validating - Tests should have a boolean output.
  • Timely - Tests need to be written in a timely manner.

10 - Classes

Classes should be small and follow the following order:

  • List of variables (Public, Static, Constants, Private).
  • Methods. Apply the Dependency Injection Principle so that classes depend on abstractions rather than concrete details.

11 - Systems

"Complexity kills. It sucks the life out of developers, it makes products difficult to plan, build, and test." - Ray Ozzie, CTO, Microsoft Corporation

Systems are like cities that need to progress through appropriate levels of abstraction and modularity, allowing individuals and "components" to work efficiently, even without understanding the whole.

Software systems should separate the initialization process - creating application objects and "connecting" dependencies - from the runtime logic that comes after initialization.

An architecture can grow gradually if we maintain proper separation of concerns.

An invasive architecture affects agility and overrides domain logic, which, when obfuscated, loses quality as bugs hide more easily and implementation becomes difficult.

12 - Emergence

Four rules of Simple Design by Kent Beck:

  • Pass all tests.
  • Don't repeat yourself.
  • Express the programmer's intent.
  • Minimize the number of classes and methods.

Most of the costs in a software project come from long-term maintenance. The clearer the author makes their code, the less time others will spend understanding it.

13 - Concurrency

Decoupling "what" and "how much" often has a significant impact on the system's structure.

Keep your concurrency-oriented code separate from the rest of the code.

Take data encapsulation seriously; severely limit access to any shared data.

Try to divide data into independent subsystems that can be manipulated by independent threads, possibly on different processors.

Part II - Case Studies with Increasing Complexity

14 - The Grand Redesign in Small Steps

The author presents a case study where he took an application and refactored it to achieve cleaner code. It is not enough to make the program work professionally. We need to refine and clean our code continuously.

15 - Internal Characteristics of the JUnit Framework

The author examines parts of the JUnit framework code and proposes improvements. Scout Rule: Leave the code a little cleaner than you found it.

16 - Refactoring SerialDate

The author presents a class called SerialDate in the JCommon library and proposes improvements.

Part III - Heuristics and Code Smells

17 - Code Smells and Heuristics

  1. Putting code in comments is an abomination. Maybe the code could be clearer so it doesn't need the comment;
  2. Bad names (variable, method, class);
  3. Building a project should be a simple and single operation (EG: yarn build);
  4. Dead code ( "turned off" code) or unnecessary;
  5. Distance from the margin (increased complexity);
  6. Functions should have a small number of parameters;
  7. Output parameters are unexpected;
  8. Boolean parameters are confusing;
  9. Don't be afraid to delete functions that are not used;
  10. DRY (Don't repeat yourself) - Don't duplicate code. Use Template Method pattern and Strategy. Object orientation and structured programming are tactics to organize modules and eliminate duplication;
  11. Base classes should not see anything in their derivatives;
  12. Limit information to help maintain low coupling;
  13. Keep your source files clean, well organized and free of clutter;
  14. In general, it is better to have many functions than to pass code as a parameter to select behavior;
  15. We want the code to be as expressive as possible;
  16. Use descriptive variables, if you can't understand what a function does and need to look at the documentation it's better to refactor;
  17. There is a difference between understanding how the code works and knowing if the algorithm will do the job properly. Not being sure if the algorithm is appropriate is normal. Not being sure what your code does is pure laziness;
  18. The team should not need a document describing their conventions because their codes provide the examples;
  19. Different responsibilities (SRP breach);
  20. Blank line (no pattern);
  21. Magic numbers (that could be constants);
  22. Inadequate exception handling (return -1, unnecessary try/catch);
  23. Unnecessary else (invert the if);
  24. Untyped variable (in languages where typing is mandatory);
  25. Variables declared together;
  26. Variables declared long before their use (eventually groups of variables);

PS: Remember that performance can be affected by clean code.

Did you like?

More posts

Cover Image for The Phychology of Money

The Phychology of Money

Morgan Housel offers valuable insights on financial management and decision-making. The author emphasizes that financial success depends more on behavior than on intelligence or technical knowledge. Housel highlights the importance of long-term vision and resilience in the face of market volatility, encouraging us to focus on sustainability rather than short-term gains.

Cover Image for Bellsant

Bellsant

I've been at the forefront of developing a cutting-edge health and wellness app. Our tech stack combines React Native for cross-platform mobile development with a serverless NodeJS backend, leveraging AWS Lambda for scalability and cost-efficiency.

Abílio Azevedo
Abílio Azevedo

NewsLetter

I will send the content posted here. No Spam =)

Experienced Software Engineer with degree in Electrical Engineering with over 10 years of hands-on expertise in building robust and scalable mobile, web and backend applications across various projects mainly in the fintech sector. Mobile (React Native), Web (React and Next.JS) and Backend (Node.JS, PHP and DJANGO). My goal is to create products that add value to people. - © 2024, Abílio Azevedo