Clean Code Cookbook

Book description

Often, software engineers and architects work with large, complex code bases that they need to scale and maintain. With this cookbook, author Maximiliano Contieri takes you beyond the concept of clean code by showing you how to identify improvement opportunities and their impact on production code. When it comes to reliability and system evolution, these techniques provide benefits that pay off over time.

Using real life examples in JavaScript, PHP, Java, Python, and many other programming languages, this cookbook provides proven recipes to help you scale and maintain large systems. Every section covers fundamental concepts including readability, coupling, testability, and extensibility, as well as code smells—symptoms of a problem that requires special attention—and the recipes to address them.

As you proceed through this book, refactoring recipes and the variety of code smells increase in complexity. You will:

  • Understand the benefits of clean code and learn how to detect code smells
  • Learn refactoring techniques step by step
  • Gain illustrative code examples in several modern programming languages
  • Get a comprehensive catalog of common code smells, their impacts, and possible solutions
  • Use code that's straight to the point, favoring readability and learning

Publisher resources

View/Submit Errata

Table of contents

  1. Foreword
  2. Preface
    1. Who This Book Is For
    2. How This Book Is Organized
    3. What You Need to Use This Book
    4. Access This Book in Digital Format
    5. Conventions Used in This Book
    6. Using Code Examples
    7. O’Reilly Online Learning
    8. How to Contact Us
    9. Acknowledgments
  3. 1. Clean Code
    1. 1.1. What Is a Code Smell?
    2. 1.2. What Is Refactoring?
    3. 1.3. What Is a Recipe?
    4. 1.4. Why Clean Code?
    5. 1.5. Readability, Performance, or Both
    6. 1.6. Software Types
    7. 1.7. Machine-Generated Code
    8. 1.8. Naming Considerations Throughout the Book
    9. 1.9. Design Patterns
    10. 1.10. Programming Language Paradigms
    11. 1.11. Objects Versus Classes
    12. 1.12. Changeability
  4. 2. Setting Up the Axioms
    1. 2.0. Introduction
    2. 2.1. Why Is It a Model?
    3. 2.2. Why Is It Abstract?
    4. 2.3. Why Is It Programmable?
    5. 2.4. Why Is It Partial?
    6. 2.5. Why Is It Explanatory?
    7. 2.6. Why Is It About Reality?
    8. 2.7. Inferring the Rules
    9. 2.8. The One and Only Software Design Principle
  5. 3. Anemic Models
    1. 3.0. Introduction
    2. 3.1. Converting Anemic Objects to Rich Objects
    3. 3.2. Identifying the Essence of Your Objects
    4. 3.3. Removing Setters from Objects
    5. 3.4. Removing Anemic Code Generators
    6. 3.5. Removing Automatic Properties
    7. 3.6. Removing DTOs
    8. 3.7. Completing Empty Constructors
    9. 3.8. Removing Getters
    10. 3.9. Preventing Object Orgy
    11. 3.10. Removing Dynamic Properties
  6. 4. Primitive Obsession
    1. 4.0. Introduction
    2. 4.1. Creating Small Objects
    3. 4.2. Reifying Primitive Data
    4. 4.3. Reifying Associative Arrays
    5. 4.4. Removing String Abuses
    6. 4.5. Reifying Timestamps
    7. 4.6. Reifying Subsets as Objects
    8. 4.7. Reifying String Validations
    9. 4.8. Removing Unnecessary Properties
    10. 4.9. Creating Date Intervals
  7. 5. Mutability
    1. 5.0. Introduction
    2. 5.1. Changing var to const
    3. 5.2. Declaring Variables to Be Variable
    4. 5.3. Forbidding Changes in the Essence
    5. 5.4. Avoiding Mutable const Arrays
    6. 5.5. Removing Lazy Initialization
    7. 5.6. Freezing Mutable Constants
    8. 5.7. Removing Side Effects
    9. 5.8. Preventing Hoisting
  8. 6. Declarative Code
    1. 6.0. Introduction
    2. 6.1. Narrowing Reused Variables
    3. 6.2. Removing Empty Lines
    4. 6.3. Removing Versioned Methods
    5. 6.4. Removing Double Negatives
    6. 6.5. Changing Misplaced Responsibilities
    7. 6.6. Replacing Explicit Iterations
    8. 6.7. Documenting Design Decisions
    9. 6.8. Replacing Magic Numbers with Constants
    10. 6.9. Separating “What” and “How”
    11. 6.10. Documenting Regular Expressions
    12. 6.11. Rewriting Yoda Conditions
    13. 6.12. Removing Comedian Methods
    14. 6.13. Avoiding Callback Hell
    15. 6.14. Generating Good Error Messages
    16. 6.15. Avoiding Magic Corrections
  9. 7. Naming
    1. 7.0. Introduction
    2. 7.1. Expanding Abbreviations
    3. 7.2. Renaming and Breaking Helpers and Utils
    4. 7.3. Renaming MyObjects
    5. 7.4. Renaming Result Variables
    6. 7.5. Renaming Variables Named After Types
    7. 7.6. Renaming Long Names
    8. 7.7. Renaming Abstract Names
    9. 7.8. Correcting Spelling Mistakes
    10. 7.9. Removing Class Names from Attributes
    11. 7.10. Removing the First Letter from Classes and Interfaces
    12. 7.11. Renaming Basic / Do Functions
    13. 7.12. Converting Plural Classes to Singular
    14. 7.13. Removing “Collection” from Names
    15. 7.14. Removing “Impl” Prefix/Suffix from Class Names
    16. 7.15. Renaming Arguments According to Role
    17. 7.16. Removing Redundant Parameter Names
    18. 7.17. Removing Gratuitous Context from Names
    19. 7.18. Avoiding Data Naming
  10. 8. Comments
    1. 8.0. Introduction
    2. 8.1. Removing Commented Code
    3. 8.2. Removing Obsolete Comments
    4. 8.3. Removing Logical Comments
    5. 8.4. Removing Getter Comments
    6. 8.5. Converting Comments to Function Names
    7. 8.6. Removing Comments Inside Methods
    8. 8.7. Replacing Comments with Tests
  11. 9. Standards
    1. 9.0. Introduction
    2. 9.1. Following Code Standards
    3. 9.2. Standardizing Indentations
    4. 9.3. Unifying Case Conventions
    5. 9.4. Writing Code in English
    6. 9.5. Unifying Parameter Order
    7. 9.6. Fixing Broken Windows
  12. 10. Complexity
    1. 10.0. Introduction
    2. 10.1. Removing Repeated Code
    3. 10.2. Removing Settings/Configs and Feature Toggles
    4. 10.3. Changing State as Properties
    5. 10.4. Removing Cleverness from Code
    6. 10.5. Breaking Multiple Promises
    7. 10.6. Breaking Long Chains of Collaborations
    8. 10.7. Extracting a Method to an Object
    9. 10.8. Looking After Array Constructors
    10. 10.9. Removing Poltergeist Objects
  13. 11. Bloaters
    1. 11.0. Introduction
    2. 11.1. Breaking Too Long Methods
    3. 11.2. Reducing Excess Arguments
    4. 11.3. Reducing Excess Variables
    5. 11.4. Removing Excessive Parentheses
    6. 11.5. Removing Excess Methods
    7. 11.6. Breaking Too Many Attributes
    8. 11.7. Reducing Import Lists 
    9. 11.8. Breaking “And” Functions
    10. 11.9. Breaking Fat Interfaces
  14. 12. YAGNI
    1. 12.0. Introduction
    2. 12.1. Removing Dead Code
    3. 12.2. Using Code Instead of Diagrams
    4. 12.3. Refactoring Classes with One Subclass
    5. 12.4. Removing One-Use Interfaces
    6. 12.5. Removing Design Pattern Abuses
    7. 12.6. Replacing Business Collections
  15. 13. Fail Fast
    1. 13.0. Introduction
    2. 13.1. Refactoring Reassignment of Variables
    3. 13.2. Enforcing Preconditions
    4. 13.3. Using Stricter Parameters
    5. 13.4. Removing Default from Switches
    6. 13.5. Avoiding Modifying Collections While Traversing
    7. 13.6. Redefining Hash and Equality
    8. 13.7. Refactoring Without Functional Changes
  16. 14. Ifs
    1. 14.0. Introduction
    2. 14.1. Replacing Accidental Ifs with Polymorphism
    3. 14.2. Renaming Flag Variables for Events
    4. 14.3. Reifying Boolean Variables
    5. 14.4. Replacing Switch/Case/Elseif Statements
    6. 14.5. Replacing Hardcoded If Conditions with Collections
    7. 14.6. Changing Boolean to Short-Circuit Conditions
    8. 14.7. Adding Implicit Else
    9. 14.8. Rewriting Conditional Arrow Code
    10. 14.9. Avoiding Short-Circuit Hacks
    11. 14.10. Rewriting Nested Arrow Code
    12. 14.11. Preventing Return Boolean Values for Condition Checks
    13. 14.12. Changing Comparison Against Booleans
    14. 14.13. Extracting from Long Ternaries
    15. 14.14. Converting Nonpolymorphic Functions to Polymorphic
    16. 14.15. Changing Equal Comparison
    17. 14.16. Reifying Hardcoded Business Conditions
    18. 14.17. Removing Gratuitous Booleans
    19. 14.18. Rewriting Nested Ternaries
  17. 15. Null
    1. 15.0. Introduction
    2. 15.1. Creating Null Objects
    3. 15.2. Removing Optional Chaining
    4. 15.3. Converting Optional Attributes to a Collection
    5. 15.4. Using Real Objects for Null
    6. 15.5. Representing Unknown Locations Without Using Null
  18. 16. Premature Optimization
    1. 16.0. Introduction
    2. 16.1. Avoiding IDs on Objects
    3. 16.2. Removing Premature Optimization
    4. 16.3. Removing Bitwise Premature Optimizations
    5. 16.4. Reducing Overgeneralization
    6. 16.5. Changing Structural Optimizations
    7. 16.6. Removing Anchor Boats
    8. 16.7. Extracting Caches from Domain Objects
    9. 16.8. Removing Callback Events Based on Implementation
    10. 16.9. Removing Queries from Constructors
    11. 16.10. Removing Code from Destructors
  19. 17. Coupling
    1. 17.0. Introduction
    2. 17.1. Making Hidden Assumptions Explicit
    3. 17.2. Replacing Singletons
    4. 17.3. Breaking God Objects
    5. 17.4. Breaking Divergent Change
    6. 17.5. Converting 9999 Special Flag Values to Normal
    7. 17.6. Removing Shotgun Surgery
    8. 17.7. Removing Optional Arguments
    9. 17.8. Preventing Feature Envy
    10. 17.9. Removing the Middleman
    11. 17.10. Moving Default Arguments to the End
    12. 17.11. Avoiding the Ripple Effect
    13. 17.12. Removing Accidental Methods on Business Objects
    14. 17.13. Removing Business Code from the User Interface
    15. 17.14. Changing Coupling to Classes
    16. 17.15. Refactoring Data Clumps
    17. 17.16. Breaking Inappropriate Intimacy
    18. 17.17. Converting Fungible Objects
  20. 18. Globals
    1. 18.0. Introduction
    2. 18.1. Reifying Global Functions
    3. 18.2. Reifying Static Functions
    4. 18.3. Replacing GoTo with Structured Code
    5. 18.4. Removing Global Classes
    6. 18.5. Changing Global Date Creation
  21. 19. Hierarchies
    1. 19.0. Introduction
    2. 19.1. Breaking Deep Inheritance
    3. 19.2. Breaking Yo-Yo Hierarchies
    4. 19.3. Breaking Subclassification for Code Reuse
    5. 19.4. Replacing “is-a” Relationship with Behavior
    6. 19.5. Removing Nested Classes
    7. 19.6. Renaming Isolated Classes
    8. 19.7. Making Concrete Classes Final
    9. 19.8. Defining Class Inheritance Explicitly
    10. 19.9. Migrating Empty Classes
    11. 19.10. Delaying Premature Classification
    12. 19.11. Removing Protected Attributes
    13. 19.12. Completing Empty Implementations
  22. 20. Testing
    1. 20.0. Introduction
    2. 20.1. Testing Private Methods
    3. 20.2. Adding Descriptions to Assertions
    4. 20.3. Migrating assertTrue to Specific Assertions
    5. 20.4. Replacing Mocks with Real Objects
    6. 20.5. Refining Generic Assertions
    7. 20.6. Removing Flaky Tests
    8. 20.7. Changing Float Number Assertions
    9. 20.8. Changing Test Data to Realistic Data
    10. 20.9. Protecting Tests Violating Encapsulation
    11. 20.10. Removing Irrelevant Test Information
    12. 20.11. Adding Coverage for Every Merge Request
    13. 20.12. Rewriting Tests Depending on Dates
    14. 20.13. Learning a New Programming Language
  23. 21. Technical Debt
    1. 21.0. Introduction
    2. 21.1. Removing Production-Dependent Code
    3. 21.2. Removing Defect Trackers
    4. 21.3. Removing Warning/Strict Off
    5. 21.4. Preventing and Removing ToDos and FixMes
  24. 22. Exceptions
    1. 22.0. Introduction
    2. 22.1. Removing Empty Exception Blocks
    3. 22.2. Removing Unnecessary Exceptions
    4. 22.3. Rewriting Exceptions for Expected Cases
    5. 22.4. Rewriting Nested Try/Catches
    6. 22.5. Replacing Return Codes with Exceptions
    7. 22.6. Rewriting Exception Arrow Code
    8. 22.7. Hiding Low-Level Errors from End Users
    9. 22.8. Narrowing Exception Tries
  25. 23. Metaprogramming
    1. 23.0. Introduction
    2. 23.1. Removing Metaprogramming Usage
    3. 23.2. Reifying Anonymous Functions
    4. 23.3. Removing Preprocessors
    5. 23.4. Removing Dynamic Methods
  26. 24. Types
    1. 24.0. Introduction
    2. 24.1. Removing Type Checking
    3. 24.2. Dealing with Truthy Values
    4. 24.3. Changing Float Numbers to Decimals
  27. 25. Security
    1. 25.0. Introduction
    2. 25.1. Sanitizing Inputs
    3. 25.2. Changing Sequential IDs
    4. 25.3. Removing Package Dependencies
    5. 25.4. Replacing Evil Regular Expressions
    6. 25.5. Protecting Object Deserialization
  28. Glossary of Terms
  29. Index
  30. About the Author

Product information

  • Title: Clean Code Cookbook
  • Author(s): Maximiliano Contieri
  • Release date: September 2023
  • Publisher(s): O'Reilly Media, Inc.
  • ISBN: 9781098144722