Guide

Sustainable Code

How to write code that's easy to maintain.

On video

Código Sostenible

Chapter 1

What Is Sustainable Code?

Fundamentals for writing maintainable, long-lasting code

Definition

Code that's easy to maintain, with intuitive design and minimal complexity

  • Intuitive design
  • Minimal essential complexity
  • Good test coverage

Write for Humans

Code should be readable and understandable to other developers

  • Prioritize readability
  • Use descriptive names
  • Document complex decisions

Code Degeneration

How to keep code from deteriorating over time

  • Accidental vs. essential complexity
  • Continuous refactoring
  • Keep the architecture clean

People First

Empathy as a core principle of software development

  • Consider the team
  • Make maintenance easier
  • Reduce cognitive load
Chapter 2

Refactoring

The daily practice of improving existing code

Daily Practice

Refactoring should be part of the everyday workflow

  • Small, constant improvements
  • Don't wait for big rewrites
  • Integrate it into normal development

Readability Improvements

Focus on making code easier to read and understand

  • Rename variables and functions
  • Extract complex methods
  • Simplify expressions

Code Smells

Identify and eliminate problematic patterns in the code

  • Overly long methods
  • Classes with too many responsibilities
  • Duplicated code
  • Excessive comments
Chapter 3

Fundamentals

Basic principles for sustainable code

Design for the Present

Avoid over-engineering and focus on current needs

  • YAGNI (You Aren't Gonna Need It)
  • Simple solutions first
  • Incremental evolution

Concrete Use vs. Reuse

Prioritize specific solutions over premature abstractions

  • Solve the problem at hand
  • Abstract once clear patterns emerge
  • Avoid premature generalization

Rules of Sustainable Code

Four fundamental rules for keeping code high quality

  • 1. Covered by tests
  • 2. The tests are sustainable
  • 3. The abstractions make sense
  • 4. Explicit intent
Chapter 4

Naming Techniques

The art of naming things in code

Traits of Good Names

Properties that names in code should have

  • Easy to pronounce
  • Free of technical jargon
  • Concrete and specific
  • Form natural phrases (is, has)

Avoid Bad Practices

What not to do when naming things

  • No confusing aliases
  • Avoid abbreviations
  • Don't use sequential numbers
  • Avoid generic names

Naming Strategies

Techniques for coming up with effective names

  • Lean on context
  • Use appropriate nouns, verbs, and adjectives
  • Name literal values
  • Rename the next day if needed
Chapter 5

Principle of Least Surprise

The compass of sustainable code

Definition of the Principle

Code should behave the way developers expect

  • Predictable behavior
  • Consistency in the API
  • Follow established conventions

Practical Application

How to apply this principle day to day

  • Methods that do what their name says
  • Parameters in a logical order
  • Expected return values

Avoid Side Effects

Minimize unexpected behavior

  • Pure functions whenever possible
  • Document necessary side effects
  • Separate commands from queries
Chapter 6

Cohesion and Coupling

The north star of software design

High Cohesion

Related elements should stay together

  • Related responsibilities
  • Functions that work together
  • Data and behavior bound together

Low Coupling

Minimize dependencies between modules

  • Law of Demeter
  • Tell, Don't Ask
  • Well-defined interfaces

Connascence

A measure of the strength of dependency between elements

  • Connascence of name
  • Connascence of type
  • Connascence of meaning
  • Connascence of algorithm
Chapter 7

SOLID Principles

Five fundamental principles of object-oriented design

SRP - Single Responsibility Principle

A class should have only one reason to change

  • One responsibility per class
  • Easier maintenance
  • Reduced coupling

OCP - Open-Closed Principle

Open for extension, closed for modification

  • Extensible without modifying existing code
  • Use of abstractions
  • Polymorphism and inheritance

LSP - Liskov Substitution Principle

Derived objects must be substitutable for their base types

  • Well-defined contracts
  • No stronger preconditions
  • No weaker postconditions

ISP - Interface Segregation Principle

Many specific interfaces are better than one general-purpose one

  • Cohesive interfaces
  • Avoid unnecessary dependencies
  • Clients don't depend on methods they don't use

DIP - Dependency Inversion Principle

Depend on abstractions, not on concrete implementations

  • High-level modules don't depend on low-level ones
  • Both depend on abstractions
  • Makes testing and flexibility easier
Chapter 8

Sustainable Implementation

Practical techniques for writing maintainable code

Structure and Formatting

Visual organization of code

  • Consistent indentation
  • Minimize scope as much as possible
  • Guard clauses and symmetry

Composition vs. Inheritance

Prefer composition over inheritance

  • Greater flexibility
  • Less coupling
  • Easier to test

Constructors and Functions

Best practices for methods and constructors

  • Simple constructors
  • Named constructors
  • Separate control flow from logic
  • Prefer pure functions

Parameters and CQS

Managing parameters and separating responsibilities

  • No configuration parameters
  • Reduce arity
  • CQS: Separate Queries and Commands
Chapter 9

Error Management and Prevention

Strategies for robust, resilient code

Preventing Human Error

Design systems that minimize mistakes

  • Understand the language deeply
  • Values, references, objects
  • Comparison (equals, hashCode)
  • Shallow vs. deep copy

Hotspots for Accidents

Areas of code most prone to errors

  • State management
  • Asynchrony and concurrency
  • Resource handling
  • Input validation

Resilient vs. Defensive Code

Strategies for handling unexpected situations

  • Fail fast vs. fail safe
  • Validation at boundaries
  • Graceful recovery

Handling Absence and Errors

Patterns for handling missing values and errors

  • Null Object pattern
  • Optional/Maybe type
  • Either type
  • Notification pattern
  • Try type
Chapter 10

Domain-Specific Types

Expressiveness and cohesion through types

Benefits of Domain-Specific Types

Why create your own domain types

  • Greater expressiveness
  • Better cohesion
  • Fighting Primitive Obsession
  • Compile-time validation

Value Objects vs. Entities

Fundamental differences in design

  • Value Objects: immutable, no identity
  • Entities: mutable, with identity
  • When to use each

Generics and Algebraic Types

Advanced typing tools

  • Generics for reuse
  • Sum types (Union Types)
  • Product types (Record Types)
  • Type composition
Chapter 11

Misunderstood Principles

Debunking outdated programming rules

Historical Context

Why certain rules came about and why they no longer apply

  • Limitations of old hardware
  • Primitive development tools
  • Evolution of languages and paradigms

Outdated Rules

Principles that are no longer relevant or are counterproductive

  • Only one return per function
  • Declare variables at the top
  • Interfaces always decouple
  • Getters and setters for everything

Premature Optimization

Balancing readability and performance

  • Code must be optimal (a myth)
  • Readability first, optimization later
  • Measure before optimizing
  • Comment only what's necessary
Chapter 12

Credits

Book

Based on the book

  • Author: Carlos Blé Jurado
  • Foreword: Javier Ferrer

Summary

Key takeaways

  • Author: Daniel Boggiano

Audio

AI-generated podcast

  • Author: Daniel Boggiano
  • YouTube: