liveBook · Manning

What you will learn in Software Design for Python Programmers

Principles and patterns

by Ronald Mak

Chapter by chapter

Chapter 1: The path to well-designed software

1.1 What is software design? · 1.2 What you will learn from this book · 1.3 The benefits of good software design · 1.4 A few design examples · 1.4.1 Leaking changes · 1.4.2 Code that’s too complex · 1.4.3 Inflexible code · 1.4.4 Surprise! · 1.4.5 Common architecture problems · 1.5 Make sure we’re going to build the right application; then, build it right · 1.6 Good design doesn’t come easily · 1.7 Change and complexity are the enemies of good design · 1.8 Design with object-oriented programming concepts · 1.9 What about AI-generated code? · 1.10 Summary

What you learn in chapter 1 →

Chapter 2: Iterate to achieve good design

2.1 Good application design requires an iterative process · 2.2 Don’t let changes leak out · 2.3 Iterate to achieve good design · 2.3.1 Iteration 1: Initial cohesive classes · 2.3.2 Iteration 2: Encapsulation, delegation, and loose coupling · 2.3.3 Iteration 3: More kinds of books and their attributes · 2.3.4 Iteration 4: A better design after backtracking · 2.4 Summary

What you learn in chapter 2 →

Chapter 3: Get requirements to build the right application

3.1 The overture to application design · 3.2 Functional requirements: What must the application do? · 3.3 Nonfunctional requirements: Constraints on the application · 3.4 How to get requirements · 3.4.1 A short requirements case study · 3.4.2 Stated and implied requirements · 3.5 Unified Modeling Language diagrams for creating and documenting design · 3.6 Use cases provide context for the requirements · 3.6.1 UML use case diagram · 3.6.2 Use case description · 3.7 The functional specification and software validation · 3.8 Where do classes come from? · 3.8.1 Textual analysis: Nouns can become classes · 3.8.2 Textual analysis: Verbs can become methods · 3.9 Summary

What you learn in chapter 3 →

Chapter 4: Good class design to build the application right

4.1 When do we do application design? · 4.2 Two important goals for good class design · 4.2.1 Cohesion and the Single Responsibility Principle · 4.2.2 Loose coupling and the Principle of Least Knowledge · 4.3 UML class diagrams to document class design · 4.3.1 Dependency: The most basic relationship · 4.3.2 Aggregation and composition: Objects that contain other objects · 4.3.3 Generalization: Superclasses and their subclasses · 4.3.4 Abstract classes and interfaces: What subclasses must implement · 4.4 UML state diagram: How an object changes state · 4.5 UML sequence diagram: How objects interact [optional] · 4.6 The design specification and software verification · 4.7 Summary

What you learn in chapter 4 →

Chapter 5: Hide class implementations

5.1 The Principle of Least Knowledge and hidden implementations · 5.2 Public getter and setter methods access hidden implementation selectively · 5.3 Class Date: A case study of implementation hiding · 5.3.1 Iteration 1: Date arithmetic with loops · 5.3.2 Iteration 2: Julian day numbers simplify date arithmetic · 5.3.3 Iteration 3: A hybrid approach with lazy evaluation · 5.4 Public setter methods carefully modify hidden implementation · 5.5 Beware of dangerous setter methods · 5.6 Rules from the Law of Demeter support the Principle of Least Knowledge · 5.7 But is the implementation really hidden? · 5.8 The Open-Closed Principle supports code stability · 5.9 Summary

What you learn in chapter 5 →

Chapter 6: Don’t surprise your users

6.1 No surprises and the Principle of Least Astonishment · 6.1.1 Off-by-one errors · 6.1.2 Misnamed functions can mislead their callers · 6.2 Poor performance is an unwelcome surprise · 6.2.1 Bad design can cause unexpected performance problems · 6.2.2 Performance surprises of lists, tuples, and arrays · 6.3 Programming by contract helps eliminate surprises [optional] · 6.3.1 Programming a circular buffer by contract · 6.3.2 Precondition: What must be true before calling a method or function · 6.3.3 Postcondition: What must be true after returning from a function · 6.3.4 Class invariant: What must remain true of object states · 6.4 Summary

What you learn in chapter 6 →

Chapter 7: Design subclasses right

7.1 When to override and when to overload methods · 7.1.1 Override superclass methods to get subclass behavior · 7.1.2 Type hints and method overriding · 7.1.3 Overload methods that have similar or equivalent behaviors · 7.1.4 Overloading with multimethod and type hints · 7.2 The Liskov Substitution Principle and proper subclasses · 7.3 Choosing the is-a and has-a relationships · 7.3.1 Using is-a · 7.3.2 Using is-a with multiple inheritance · 7.3.3 Using has-a · 7.4 Use a factory function with the Code to the Interface Principle · 7.5 Programming by contract with subclasses [optional] · 7.6 Summary

What you learn in chapter 7 →

Chapter 8: The Template Method and Strategy Design Patterns

8.1 The Template Method Design Pattern defines the steps of an algorithm · 8.1.1 Desired design features · 8.1.2 Before using the Template Method Design Pattern · 8.1.3 After using the Template Method Design Pattern · 8.1.4 Template Method’s generic model · 8.2 The Strategy Design Pattern encapsulates algorithms · 8.2.1 Desired design features · 8.2.2 Before using the Strategy Design Pattern · 8.2.3 After using the Strategy Design Pattern · 8.2.4 Strategy’s generic model · 8.3 Choosing between Template Method and Strategy · 8.4 Summary

What you learn in chapter 8 →

Chapter 9: The Factory Method and Abstract Factory Design Patterns

9.1 The Factory Method Design Pattern lets subclasses create objects · 9.1.1 Desired design features · 9.1.2 Before using Factory Method · 9.1.3 After using Factory Method · 9.1.4 Factory Method’s generic model · 9.2 The Abstract Factory Design Pattern creates families of objects · 9.2.1 Before using Abstract Factory · 9.2.2 After using Abstract Factory · 9.2.3 Abstract Factory’s generic model · 9.3 Choosing between Factory Method and Abstract Factory · 9.4 Summary

What you learn in chapter 9 →

Chapter 10: The Adapter and Façade Design Patterns

10.1 The Adapter Design Pattern integrates code · 10.1.1 Desired design features · 10.1.2 Before using Adapter · 10.1.3 After using Adapter · 10.1.4 Adapter’s generic model · 10.1.5 An alternative Adapter model · 10.2 The Façade Design Pattern hides a subsystem of interfaces · 10.2.1 Desired design features · 10.2.2 Before using Façade · 10.2.3 After using Façade · 10.2.4 Façade’s generic model · 10.3 Choosing between Adapter and Façade · 10.4 Summary

What you learn in chapter 10 →

Chapter 11: The Iterator and Visitor Design Patterns

11.1 The Iterator Design Pattern: One algorithm operates on different sequential data collections · 11.1.1 Desired design features · 11.1.2 Before using Iterator · 11.1.3 After using Iterator · 11.1.4 Iterator’s generic model · 11.2 The Visitor Design Pattern: Different algorithms operate on a single data collection · 11.2.1 Desired design features · 11.2.2 Before using Visitor · 11.2.3 After using Visitor · 11.2.4 Visitor’s generic model · 11.3 Choosing between Iterator and Visitor · 11.4 Summary

What you learn in chapter 11 →

Chapter 12: The Observer Design Pattern

12.1 The Observer Design Pattern: Publish data for multiple subscribers · 12.1.1 Desired design features · 12.1.2 Before using Observer · 12.1.3 After using Observer · 12.1.4 The Observer’s generic model · 12.2 Summary

What you learn in chapter 12 →

Chapter 13: The State Design Pattern

13.1 The State Design Pattern models state transitions · 13.1.1 Desired design features · 13.1.2 Before using State · 13.1.3 After using State · 13.1.4 State’s generic model · 13.2 Choosing between State and Visitor · 13.3 Summary

What you learn in chapter 13 →

Chapter 14: The Singleton, Composite, and Decorator Design Patterns

14.1 The Singleton Design Pattern ensures that a class has only one object · 14.1.1 Desired design features · 14.1.2 Before using Singleton · 14.1.3 After using Singleton · 14.1.4 Singleton’s generic model · 14.2 The Composite Design Pattern: Treat individual and composite objects uniformly · 14.2.1 Desired design features · 14.2.2 Before using Composite · 14.2.3 After using Composite · 14.2.4 Composite’s generic model · 14.3 The Decorator Design Pattern: Dynamically add object responsibilities · 14.3.1 Desired design features · 14.3.2 Before using Decorator · 14.3.3 After using Decorator · 14.3.4 Decorator’s generic model · 14.4 Summary

What you learn in chapter 14 →

Chapter 15: Designing solutions with recursion and backtracking

15.1 Recursion compared to the for loop · 15.2 Finding the largest value in a list by recursion · 15.3 Reversing a list with recursion · 15.4 Solving the Towers of Hanoi puzzle by recursion · 15.5 Recursive algorithms for a binary search tree · 15.5.1 Inserting into a BST with recursion · 15.5.2 Printing a BST with recursion · 15.6 Quicksorting a list with recursion · 15.6.1 Quicksort in action · 15.6.2 Partitioning a list into sublists · 15.6.3 Quicksort implementation · 15.7 The Fibonacci sequence and a recursion disaster · 15.8 Dynamic backtracking increases the power of recursion · 15.9 Solving the eight queens puzzle with recursion and backtracking · 15.10 Solving Sudoku puzzles with recursion and backtracking · 15.11 Summary

What you learn in chapter 15 →

Chapter 16: Designing multithreaded programs

16.1 How do things happen simultaneously? · 16.2 A mutex enforces mutual exclusion · 16.2.1 Protect the integrity of a shared printing resource · 16.3 A semaphore accepts multiple threads · 16.3.1 The classic reader–writer problem · 16.4 Condition objects synchronize threads · 16.4.1 How condition objects synchronize threads · 16.4.2 The classic producer–consumer problem · 16.5 A final note on multithreading · 16.6 Summary

What you learn in chapter 16 →

Concepts explained in this book

These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.