Clean Code Cookbook: Recipes to Improve the Design and Quality of your Code

This document was uploaded by one of our users. The uploader already confirmed that they had the permission to publish it. If you are author/publisher or own the copyright of this documents, please report to us by using this DMCA report form.

Simply click on the Download Book button.

Yes, Book downloads on Ebookily are 100% Free.

Sometimes the book is free on Amazon As well, so go ahead and hit "Search on Amazon"

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...
  • Author(s): Maximiliano Contieri
    Publisher: O'Reilly Media
    Year: 2023

    Language: English
    Pages: 428

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