Clean Code: Write better, simple and cleaner

Sude Kılıç
Koçfinans Tech
Published in
7 min readApr 2, 2021

Some books change the way we code, one of the best examples for me (and probably many developers) is “Clean Code” by Robert C. Martin.

You may think that technical debt should be left but I believe messy code tends to get messier and it becomes hard to clean. Decreasing repetitive codes and preferring understandable/extensible code principles will speed up the decision process. The clean code principles will not only give you personal satisfaction but also your teammates and future self will thank you.

Code is not how you tell the computer what to do; it is how you tell another programmer what you want the computer to do.

In this article, I’ll discuss a few issues that are also addressed in the “Clean Code” Bible. Although most of us have mastered these rules, I wrote this article because I believe it would be good to remember and remind each other from time to time. I hope you enjoy reading!

1. Meaningful Names

There are only two hard things in Computer Science: cache invalidation and naming things.Phil Karlton

You have probably heard of Phil Karlton’s famous phrase. Although it is difficult to find meaningful names, it is one of the most important elements underlying the clean code principles. The name of a variable, function or class should tell why it exists, what it does, and how it is used. If a name requires a comment, the name has not been selected properly.

Let’s look at some examples.

Variable names should have meaning and should be easily pronounceable:

“You should name a variable using the same care with which you name a first-born child.” — Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship

int x = products.size();  -- Wrongint prdctSize = products.size();  -- Wrongint productSize = products.size(); -- Right

Singular and Plural:

List<String> name = Arrays.asList("Sude","Selen","Mert","Kerim");
String name1 = name.get(0); -- Wrong
List<String> names = Arrays.asList("Sude","Selen","Mert","Kerim");
String name = names.get(0); -- Right

Functions should be verbs, classes should be nouns: Use a verb as the first word in the method and use a noun for class. Use camelCase for variables and function names. Classes should start with a capital letter.

function price()  -- Wrongfunction calculatePrice()  -- Rightclass CalculatePrice  -- Wrongclass Price   -- Right

Booleans are “to be are not be”:

boolean nameValid = !StringUtils.isBlank(name);   -- Wrongboolean isNameValid = !StringUtils.isBlank(name); -- Right

Consistency: Chose similar words for similar functions. If you used “get” in one class, do not use “fetch” in another.

2. Testing

If it is not tested, it is broken

Write a lot of tests and make sure you have enough to cover your core business functionality. Writing clean code will automatically make writing unit tests faster and easier.

In addition, there are a few points mentioned in the book.

Dirty tests are worse than no tests!

They will be more difficult to understand and it takes more time to fix it. I don’t think we should stick to the “one assertion per test” rule dogmatically but as the name implies it is “unit” testing.

Good tests should be readable and follow to FIRST rules:

Fast: Tests should be fast enough that you won’t be discouraged from using them.

Independent: Tests should not depend on each other, when needed you should be able to run each test separately.

Repeatable: Tests should be repeatable in any environment without varying results.

Self-Validating: Each test will have a single pass/fail boolean output. It should not be your responsibility to check whether the method’s output is correct every time the test is run.

Timely: Unit tests should be written right before the production code that makes the test pass. This is something you would do if you were doing TDD (Test Driven Development), but it may not be applicable in other cases.

3. Separation of Concerns (Single Responsibility Principle)

The Single Responsibility Principle (SRP) is a computer programming principle that states that every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility.

Basically, keep it simple! Classes and functions should be small and do one thing(one purpose). Surely, if an error occurs, it will be easier to find.

Robert C. Martin in Clean Code provides a parallel definition about this subject:

The Single Responsibility Principle (SRP) states that each software module should have one and only one reason to change.Gather together the things that change for the same reasons. Separate those things that change for different reasons.

It’s critical to divide responsibilities into different functions, classes, and modules because code smells like Fragility and Viscosity can result from misplaced responsibilities. There are multiple techniques to achieve this separation. In this context, the reason for the change and whose responsibility it is are important. Uncle Bob comments on this situation as follows: “The code is not responsible for bug fixes or refactoring. Those things are the responsibility of the programmer, not of the program.”

4. Reusable Codes instead of Duplication

Duplicate code is the root of all evil in software design. When a system is littered with many snippets of indentical, or nearly identical code, it is indicative of sloppiness, carelessness, and sheer unprofessionalism. It is the guilt-edged responsibility of all software developers to root out and eliminate duplication whenever they find it. — Robert C. Martin

Removing code duplications keeps your code clean and allows you to provide faster feature support and new updates. It simplifies the code structure and also improves the code’s maintainability while reducing technical debt over time. It helps to reduce the number of security vulnerabilities.

You can see some of the treatments in the following:

If the same code appears in two or more methods in the same class: Use the Extract Method and call the new method from both locations.

If the same code appears in two subclasses of the same level: Use the Extract Method for both classes and Pull it Up.

If the same code appears in two different classes: If the classes don’t belong to a hierarchy, use Extract Superclass; if creating a superclass is impossible, use Extract Class in one class and use the new component in the other.

Do not hardcode: Instead of hardcoding values define constants or use variables. Using variables will not only make the code more readable, but it will also make it easy to modify if it is being used at multiple places.

Also an important point, have you ever heard of DRY principles?

“It basically aims to reduce the repetition of software patterns by replacing them with abstractions or using data normalization to avoid redundancy.”

Although it is one of the most valuable principles of common development wisdom, it can often be misunderstood. Even if two pieces of code appear to be identical, they may represent different concepts and different abstractions. In such examples, duplication may be a more logical choice.

Duplication is far cheaper than the wrong abstraction – Sandi Metz

5. Design Decisions

The hardest part of design … is keeping features out. — Donald A. Norman

Keep Configurable Data at High Levels: If you have a constant such as a default or configuration value that is known and expected at a high level of abstraction, do not bury it in a low-level function. Expose it as an argument to that low-level function called from the high-level function.

A class should know only its direct dependencies: Follow Law of Demeter.

Use dependency injection: Dependency injection makes it possible to eliminate unnecessary dependencies and makes it easier to reuse in a different context. It reduces dependency carrying and increases testability. Inversion of Control supports the SPR.

Functions should have no side effects.

Prefer to use as few parameters as possible and no flag arguments.

Prefer polymorphism to if/else or switch/case: Switch statements are commonly used because they are the most obvious brute force solution, not because they are the best solution. That is why this heuristic exists to remind us to consider polymorphism before using a switch. In addition, cases, where functions are more unpredictable than types, are uncommon. Therefore, any switch statement should be regarded as suspicious.

6. Code Smells

We all know what code smells means but I still wanted to share its definition on Wikipedia:

“In computer programming, a code smell is any characteristic in the source code of a program that possibly indicates a deeper problem. Code smells are usually not bugs; they are not technically incorrect and do not prevent the program from functioning.”

We all are familiar with the concept and most part of this post is related to or covers this topic. But, since the book specifically mentions it, I wanted to quote a few points here.

Rigidity: The software is difficult to change. A small change causes a cascade of subsequent changes.

Fragility: The software breaks in many places due to a single change.

Immobility: You cannot reuse parts of the code in other projects because of involved risks and high effort.

Opacity: The code is hard to understand.

Thank you for reading, let’s take our corona days as a warning and always pay attention to cleanliness :)

--

--