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