Clear Code
  • Introduction
    • About This Book
    • Timeline
    • Software Killers
    • Billion Dollar Mistakes
    • Clear Code Overview
    • Clear Code Rules
  • Data Processing
    • Separate Data Collection And Processing
    • Create Data Models
    • Separate Use Cases
    • Data Should Be Immutable
  • Examples
    • Separate Use Cases With Data Model
  • Maintenance Cost
    • Consider the Maintenance Cost
    • The Software Exists In Time
    • Don't Feed the Monsters
  • OOP
    • Separate Data And Procedures
    • Do Not Use Inheritance
    • When To Avoid Inheritance?
    • What Is The Problem With Abstract Frameworks?
  • VARIOUS
    • The Real Single Responsibility Principle
    • The problem with Clean Code's name
    • How To Handle Warnings
    • Do Not Create Constant Collection Classes
  • Externals
    • Links
    • Quotes
    • Funny
  • Technology
    • Git Tutorials
  • Clean Code
    • Clean Code Introduction
      • Origin & Overview
      • Advanced
      • Typical Issues
    • Clean Code Outline
      • Why Clean Code?
      • Clean Code
      • Clean Code Approaches
      • Specification & Design
      • Duplication
      • Refinement & Refactoring
      • Conventions
      • Names
      • Types
      • Methods
      • Nulls and Validity Checks
      • Comments
      • Dead Code
      • Error Handling
      • Classes
      • Code Formatting
      • Unit Tests
      • Special Cases
      • Object Oriented Programming
      • General Code Smells
    • Clean Code Links
    • Clean Code TOC
    • Effective Java TOC
Powered by GitBook
On this page
  • Separate everything
  • Simplest solution by default
  • Avoid indirection
  • Decrease branching
  • Decrease dependencies
  • Focus on business logic

Was this helpful?

  1. Introduction

Clear Code Rules

2023.01.30 DRAFT

Last updated 1 year ago

Was this helpful?

Separate steps
  • Split the algorithms into separate steps that can be done one by one.

  • Design the intermediate data to be created by the steps and used by the next ones.

  • Create sequences of steps. That is the easiest to be understood by the human mind.

  • .

Separate features

Separate features

  • Implement different features and use cases in different parts of the code.

  • Avoid common code above different features.

  • Avoid implementing use cases with a common code and then branching them from there.

  • As early as possible.

  • Never join use cases again, once they are separated.

Separate data and procedures

  • For data processing always design the data first.

  • Model the business results with the data. That's why it is called a 'data model'.

  • Create separate data loaders/collectors and data processors.

  • In Java implement equals(), hashcode() and toString() of data classes.

    • It will help the testing and debugging.

  • Avoid using Maps in data models. They will make the data 'unfinished'.

Create code units with

  • a well-defined and immutable (or effectively immutable) input data model,

  • and a well-defined and immutable (or effectively immutable) output data model.

  • Avoid additional data collection during data processing.

Test code units with input/output data.

  • Create input data.

  • Create expected output.

  • Simply test their equality.

Separate method types

Dispatcher method

  • One branching

  • Redirecting method outputs to method inputs.

Implementation method

  • Implements one thing.

  • Usually returns a result.

Strive to create only these two method types.

  • Break long methods into multiple methods until you reach it.

Separate constants

Don't collect constants at the top of the class.

Put constants in the class that is responsible for it by business logic.

Collect constant value sets into enums.

Separate business code and technical code

Hide technical details behind business logic.

Don't pollute business functionality with technical details or the other way around.

Don't mix technical implementations with business logic implementations.

  • Don't extend generic technical classes (e.g., Collections) to create a business-specific implementation.

Always name variables after their business meaning.

  • Avoid technical names.

  • E.g., don't call a map 'map' a result 'result' etc.

Organize code by SRP
  • Every part of the code should implement only one part of the business logic. (The original SRP.)

  • Every part of the business logic should be implemented by one part of the code.

  • A 'part' of the code can be any level, like a method, class, package, module, etc.

Apply high cohesion

  • Put together what belongs together.

    • Methods or classes that call each other.

  • Method and class implementation are simply code blocks that hold elements together.

  • Create inner classes to group a few methods within a larger class.

  • A package is also a bracket that holds classes together

  • Minimize the interface to a group of procedural codes.

    • One public method for one class.

    • One public class for one package.

Treat classes as code units

  • closed

  • finished

  • final

  • tested

Consider maintenance costs when choosing a solutions.

Directly call subroutines

No internal ad hoc frameworks

No pets - they will become monsters

No fancy solutions

No tricky solutions

Quit OOP

Don't use inheritance. Overriding is forbidden.

Use composition.

Use classes to simply organize code into components.

Use your programming language as a structured language.

  • Write procedures and call them directly.

No frameworks over frameworks

Use them as it is

Avoid design patterns

No Builder

No visitor

Use complex solutions only if really necessary

Design and document them.

Avoid indirection

Preference

No indirection

Interface

Lambda

Subclass

Avoid passing lambdas to methods

Minimize to 'attributes'

Avoid call-back classes

Avoid child classes

Don't pass Maps as parameters

Use them where you create them

Don't use Maps in data models

Minimize callbacks

Callbacks are code injection

Callbacks are branching

Callbacks are parallels

Callbacks are "frameworks"

Image with callback: parallels

Separate use cases

As early as possible

In data models

Never join separated use cases

Organize ifs properly

Use guardian pattern

Decrease indentation

Don't indent the main payload of the method

Consider the cyclomatic complexity of an entire implementation of a feature or use case, not only of one method.

Create sequences

Image with sequences

Image with callback

Image with common code

Image with branching

Branchings are parallels

Write common code that is really common

Put related static information into enums.

  • Once you have the enums, you can get the related information without branching.

  • Don't use it to reach procedural code. I.e. don't use it for functions, lambdas, method references. They need a different solution.

Decrease dependencies

Make everything final / immutable

or effectively final / immutable

Data should be final / immutable

Avoid side effect programming

Mutables cannot be used as keys.

Classes should be final

But because of the mocking framework they cannot be

Investigate #xx

Organize code by SRP

Treat classes as code units

closed

finished / final

tested

minimize interfaces

Access the one functionality through one way (one method)

high cohesion

low coupling

everything should do only one thing

method

class

package

module

Don't increase visibility

Minimize interfaces

  • Access the one functionality through one way (one method)

  • low coupling

Fully understand the business requirement before coding

Don't start with the coding.

  • Put aside your programming language.

  • Put aside your implementation ideas.

  • Don't code until you don't understand the specification perfectly.

Don't skip the design.

  • Create examples if necessary.

  • Create graphs or UML-s if necessary.

  • Identify use cases.

Refine the specification into code

Refine the specification into a pseudo-code.

  • This is a language-independent implementation of the business logic.

  • This is the actual program programmers should write!

Implement the pseudo-code in your programming language.

  • Names in the program should be the same as in the pseudo-code.

  • Implement the steps of the pseudo-code in the real code.

  • E.g., the call hierarchy of the methods should be the pseudo-code.

Chose the most simple and straightforward implementation.

  • Usually, this consists only of simple method calls.

  • The methods are simply grouped into components (procedural classes).

Organize code by business logic

Implement one feature under one package or module.

Name components and variables by their business meaning.

  • Name them by actions, functions, use cases, etc.

  • Avoid technical names.

  • Reading the names in the code should show the business logic.

  • Names are important.

Always provide business code with names

Extract implementations of the business logic into methods and components with proper names.

Don't inline business implementation into other code.

Implement one business functionality only once.

Avoid code repetition.

Separate business code and technical code

See above, under Separate everything.

In one case you can use method references: for data attributes. ()

Single Responsibility Principle
Separate data collection and data processing
Separate use cases
Already in data models.
Separate data and procedures
Create data models
Don't collect constants in a class or interface.
Because they are actually not procedures.
Separate everything
Simplest solution by default
Decrease branching
Focus on business logic