Domain
Software Design
A systematic learning path for software design — from clean code to architecture, testing, and quality culture. Covers code quality, TDD, DDD, distributed system design, and DevOps/quality organization.
The Terrain of This Field
The terrain of software design can be read as a single ascending path: it begins at "readable code" under your feet, rises through the habits that preserve quality (refactoring and test-driven development), and continues up to the highlands of "architecture" that overlook the whole system.
The first continent is the realm of "code quality" — variable names, functions, and responsibilities at the micro scale. Beyond it spread the hills of "testing and refactoring" for growing code without breaking it, and further on rise the mountain ranges of "clean architecture" and "domain-driven design," where you design the direction of dependencies and the boundaries between modules.
Deeper still lie the plateaus of "scale and operations" — distributed systems, data-intensive design, and DevOps/quality organizations. The key to surveying this field is recognizing that the scale of concerns connects continuously, from the micro (code) to the macro (organization and operations).
Follow the arrows to read in order / solid = required, dashed = recommended
Share this map
Grouping
Difficulty
Difficulty
Dependencies
Computing layout...
Books in this domain
23 books
Head First Design Patterns
Eric Freeman, Elisabeth Robson
The Art of Readable Code
Dustin Boswell, Trevor Foucher
Building Microservices
Sam Newman
Clean Architecture
Robert C. Martin
Clean Code
Robert C. Martin
Designing Distributed Systems
Patterns and Paradigms for Scalable, Reliable Services
Brendan Burns
Effective Software Testing
A developer's guide
Maurício Aniche
Fundamentals of Software Architecture, 2nd Edition
Mark Richards, Neal Ford
Generative AI for Software Development
Sergio Pereira
Learning Domain-Driven Design
Vlad Khononov
The Pragmatic Programmer
David Thomas, Andrew Hunt
Responsible Software Engineering
Daniel Barrett, Google Engineering
Unit Testing Principles, Practices, and Patterns
Vladimir Khorikov
Building Evolutionary Architectures
Neal Ford, Rebecca Parsons, Patrick Kua
Building Secure and Reliable Systems
Best Practices for Designing, Implementing, and Maintaining Systems
Heather Adkins, Betsy Beyer, Paul Blankinship, Piotr Lewandowski, Ana Oprea, Adam Stubblefield
Designing Data-Intensive Applications
Martin Kleppmann
Domain-Driven Design: Tackling Complexity in the Heart of Software
Eric Evans
Leading Quality
Ronald Cummings-John, Owais Peer
Monolith to Microservices
Sam Newman
A Philosophy of Software Design, 2nd Edition
John Ousterhout
Property-Based Testing with PropEr, Erlang, and Elixir
Fred Hebert
Software Architecture: The Hard Parts
Neal Ford, Mark Richards, Pramod Sadalage, Zhamak Dehghani
Software Engineering at Google
Titus Winters, Tom Manshreck, Hyrum Wright
Dependencies
Reason: Grasp the idea of splitting the frontend into independent parts, and you notice it shares the same roots as backend microservices. Building Microservices provides the server-side framework of boundaries, autonomous deployment, and alignment with organization, letting you understand the principles of decomposition from both sides.
Reason: Once quality at the function and class level is second nature, the next step is to design the direction of dependencies and boundaries across the whole system. Clean Architecture provides the principle of pushing details outward and keeping business rules at the core.
- 03Clean ArchitectureFundamentals of Software Architecture, 2nd EditionRecommended / アーキテクチャ原則から体系的学習へ
Reason: After gaining an intuition for the ideal shape from Clean Architecture, you formalize architectural characteristics and trade-offs into a shared vocabulary. This book elevates design judgment from personal instinct to a discipline you can reason about.
Reason: Once you can control the direction of dependencies, the next question becomes where to draw the boundaries. Domain-Driven Design derives bounded contexts from the language of the business, giving architectural decomposition real meaning.
- 05Fundamentals of Software Architecture, 2nd EditionBuilding MicroservicesRecommended / アーキテクチャ基礎から分散設計へ
Reason: Once you have a vocabulary of architectural characteristics and trade-offs, you apply that judgment to the concrete case of distributed systems. Microservices demand a design that deliberately breaks coupling in exchange for independent deployment and autonomy.
- 06Fundamentals of Software Architecture, 2nd EditionSoftware Architecture: The Hard PartsRecommended / 基礎から実践的な設計判断へ
Reason: After grasping the fundamental characteristics, you advance to trade-off analysis in the hard parts that have no single right answer—service granularity, data ownership, distributed transactions. The same authors show not the answer but how to decide.
- 07Fundamentals of Software Architecture, 2nd EditionBuilding Evolutionary ArchitecturesRecommended / 基礎から進化的アーキテクチャへ
Reason: After learning static architectural decisions, you widen your view to designs that keep adapting to change. You gain the idea of using fitness functions to continuously verify architectural characteristics, making evolution measurable.
- 08Learning Domain-Driven DesignDomain-Driven Design: Tackling Complexity in the Heart of SoftwareRecommended / DDD入門から原典へ
Reason: After mapping the strategic and tactical landscape with an introductory text, you verify the origin and precise definitions of the concepts in the source. Evans' DDD grounds the ubiquitous language and model-driven design, forming the foundation for applied judgment.
Reason: Once you understand microservice principles, you advance to realistic strategies for migrating from an existing monolith. Most successes peel services off a monolith incrementally, so you also learn when not to distribute from the start.
Reason: Once you split services, the next hard problem becomes the distribution, consistency, and reliability of data. DDIA systematically provides the foundational theory and trade-offs of distributed data systems—replication, partitioning, and transactions.
Reason: Once you have the principles of dependencies and boundaries, you descend to the universal question beneath them: how to contain complexity. Ousterhout systematizes complexity management through the lens of deep modules and information hiding.
- 12Unit Testing Principles, Practices, and PatternsEffective Software TestingRecommended / テスト原則から設計技法へ
Reason: After grasping the qualities of good tests—protection against regressions, resistance to refactoring, fast feedback—you raise the question of what to test with systematic techniques like boundary analysis, equivalence partitioning, and structural testing. Case selection moves from intuition to engineering.
- 13Effective Software TestingProperty-Based Testing with PropEr, Erlang, and ElixirRecommended / テスト設計技法から不変条件検証へ
Reason: Once example-based testing techniques are in hand, you advance to property-based testing, which generates inputs broadly and verifies invariants. You let the machine find counterexamples a human would miss and expose gaps in the spec.
Reason: After understanding the engineering practices of large organizations, you advance to a leadership view that raises quality from individual effort to a culture the organization cultivates. Quality becomes a strategic concern of management.
- 15Building Evolutionary ArchitecturesSoftware Architecture: The Hard PartsRecommended / 進化的設計から分散の難所へ
Reason: Once you have the idea of guiding evolution with fitness functions, you advance to concrete analysis of the hard parts of distributed architecture—granularity, data ownership, and communication trade-offs—from the same authors.
- 16A Philosophy of Software Design, 2nd EditionDomain-Driven Design: Tackling Complexity in the Heart of SoftwareRelated / 複雑性管理からDDDへ
Reason: Once you have universal principles for containing complexity, you apply them specifically to the complexity of the domain. DDD tames the essential complexity inherent in the business through a model and a ubiquitous language.
- 17Clean CodeDomain-Driven Design: Tackling Complexity in the Heart of SoftwareRecommended / コード品質からドメインモデリングへ
Reason: Once you have quality standards at the code level, you point that expressiveness toward the language of the domain. Meaningful names become a ubiquitous language that bridges business and code, making the model speakable in code.
Reason: The principles of dependency direction and boundaries apply directly to designing service boundaries. You connect them to concrete decisions that map bounded responsibilities onto independently deployable units.
Reason: After grasping the basics of readability such as naming and function decomposition, you move on to binding them into principles of why. Clean Code connects individual techniques into a coherent system of craftsmanship and design principles.
Reason: Once you have the concrete techniques of readability such as naming and formatting, you widen your view to the professional philosophy that runs through daily decisions—DRY, orthogonality, and a stance toward change. The Pragmatic Programmer binds individual techniques into an attitude of why.
Reason: After adopting the pragmatic mindset of keeping code healthy, you ground those attitudes in concrete quality standards at the function and class level. Clean Code systematizes what good code is through principles and worked examples.
- 22Software Architecture: The Hard PartsDesigning Data-Intensive ApplicationsRecommended / 難しい設計判断から分散データシステムへ
Reason: When the hard parts of distributed architecture force decisions about decomposing data, you descend to the underlying theory of distributed data. The principles of consistency, replication, and storage engines become the grounds for your design decisions.
- 23Software Engineering at GoogleGenerative AI for Software DevelopmentRecommended / Googleの開発実践からAI駆動開発へ
Reason: After understanding the engineering practices of large organizations, you view how generative AI changes the flow of development with the same discipline. AI is a tool that pays off only on a foundation of review, testing, and design judgment.
Reason: Once you have the pragmatic mindset—sharpen your tools, own your judgment—you take in generative AI as a new tool. The ability to verify AI output rather than trust it blindly is the very craftsmanship of the AI era.
- 25Generative AI for Software DevelopmentResponsible Software EngineeringRecommended / AI活用の実践から責任ある設計へ
Reason: Once you can bring AI into development, you advance to the question of responsibility—the impact that power has on society. You take a view that weaves correctness, bias, and accountability of outputs into design from the start.
Reason: Once you can build security and reliability into a system's design, you extend that reach to responsibility toward users and society. Technical robustness becomes the foundation for fulfilling ethical and social responsibility.
Explore next
Connected fields