Tag Archives: design

Resources on Software Design and Patterns

Software design and design patterns are both broad topics where a lot has been written; this is necessarily a sampling.

Other Resources: TDD, Refactoring, CI/CD, BDD

[Disclosure: Note that I may have been involved in some of the materials mentioned below, and I work for Industrial Logic.]




Web Sites

Web Articles

[I welcome further suggestions of resources you’ve found useful, provided they’re something I (or a friend) can review before adding them here.]

Resources on Set-Based Design

yellow woods

“Two roads diverged in a yellow wood,

yet I could travel both.”

—Not Robert Frost


A reading list on set-based design (part of lean product development).


Applied Fluid Technologies. Information on boat design.


Baldwin, Carliss, and Kim Clark. Design Rules, Volume 1: The Power of Modularity. MIT Press, 2000. ISBN 0262024667. Modularity and platforms, from a somewhat economic perspective; not overly focused on software modularity. (No volume 2 yet:(


Kennedy, Michael. Product Development for the Lean Enterprise: Why Toyota’s System is Four Times More Productive and How You Can Implement It. Oaklea Press, 2008. ISBN 1892538180. Business novel, touches on set-based approaches. 


Kennedy, Michael and Kent Harmon. Ready, Set, Dominate: Implement Toyota’s Set-Based Learning for Developing Products, and Nobody Can Catch You. Oaklea Press, 2008. ISBN 1892538407. Second novel, also touches on set-based approaches. 


Morgan, James, and Jeffrey Liker. The Toyota Product Development System. Productivity Press, 2006. ISBN 1-56327-282-2. Overview of lean product development, touches on set-based approaches. 


Poppendieck, Mary and Tom. "Amplify Learning." The importance of communicating constraints (rather than solutions) in set-based development. 


Shook, John. Managing to Learn: Using the A3 Management Process to Solve Problems, Gain Agreement, Mentor, and Lead. Lean Enterprise Institute, 2008. ISBN 1934109207. A3 reports as the heart of lean management.


Sobek II, Durward, Allen Ward, and Jeffrey Liker. “Toyota’s Principles of Set-Based Concurrent Engineering,” Sloan Management Review, Winter, 1998. Basic description and principles of the approach. 


Wake, Bill. “Set-Based Concurrent Engineering.” Overview of several variations of set-based design in software. 


Ward, Allen, Jeffrey Liker, John Cristiano, Durward Sobek II. “The Second Toyota Paradox: How Delaying Decisions Can Make Better Cars Faster,” Sloan Management Review, Spring, 1995. Looks at how set-based concurrent engineering lets Toyota do better than other carmakers. 


Ward, Allen. Lean Product and Process Development. Lean Enterprise Institute, 2007. ISBN 978-1-934109-13-7. Description of knowledge waste, set-based concurrent engineering, and a different view of the PDCA cycle.


This is based on a list originally prepared for Agile 2009 by Bill Wake and Jean Tabaka.

Review: Structured Programming (Dahl, Dijkstra, and Hoare)

Structured Programming Structured Programming, by O.-J. Dahl, E.W. Dijkstra, and C.A.R. Hoare. Academic Press, 1972. 

This year (2012) is the 40th anniversary of this text, but it holds up well. It consists of three essays:

  • "Notes on Structured Programming" by E.W. Dijkstra
  • "Notes on Data Structuring" by C.A.R. Hoare
  • "Hierarchical Program Structures" by O.-J. Dahl and C.A.R. Hoare

If you've been led to think "Structured Programming = No GOTOs", the first essay will change your mind. It's much more a consideration of design in the small than a focus on surface form. 

"Data Structuring" considers how to structure types; Pascal's type structure (remember that?) of records, sets, enumerations etc. clearly embodies some of these ideas. You can see roots of the "object-based" approach (that never seemed to make it to the mainstream in the way object-oriented approaches did). 

The final essay describes mechanisms from SIMULA 67, an early (if not the original) object-oriented programming language. You can see the early consideration of objects and coroutines, classes and subclasses. 

There's definitely a "historical" air to these essays, but they hint at a path almost taken. Modern libraries and the modern rush to deliver let us ignore many ideas about software design, but they don't go away. These articles take a slower, more mathematical path than I've seen anybody apply in practice, but it brings clarity of thought about mapping problems and solutions that I'd like to imitate. 

Review: Applying Domain-Driven Design and Patterns (Nilsson)

Applying Domain-Driven Design and Patterns Applying Domain-Driven Design and Patterns: With Examples in C# and .NET, by Jimmy Nilsson. Addison-Wesley, 2006.

Stir together Eric Evans' Domain-Driven Design with Martin Fowler's Patterns of Enterprise Application Architecture, mix in C# code, and you've got the flavor of this book.

It's not as classic as its antecedents. But it does provide useful examples, relating it from the perspective of someone familiar with database issues, but who now comes at things from the domain-driven perspective.

Some of the tools used have changed, but the basics still hold.

Review – Growing Object-Oriented Software, Guided by Tests

Growing Object-Oriented Software, Guided by Tests, by Steve Freeman and Nat Pryce, ISBN 0-321-50362-7

Freeman and Pryce explain Test-Driven Development through an extended example. (They have a somewhat different perspective than I do, with much heavier use of mock objects. I'm not sure what drives this difference; it may be due to type of application, philosophical reasons, or just something I should learn.) I love the clarity with which they tackle the problem of driving in from all the way outside, and how they don't shy away from dealing with concurrency and persistence. It's high praise for me to say a book deserves further study; this book is one I'll definitely be reading again. 


Review – Structured Design

Structured Design. Edward Yourdon and Larry L. Constantine. Prentice-Hall, 1979.

This was one of the early structured "standard works" that I've only just gotten to for the first time. I'd learned things like coupling and cohesion, afferent and efferent flows, and the concept of factoring, but it's much stronger coming directly from this source. Not everything here is compatible with the way I think about design, but this is one of those books that deserve repeated study.

Set-Based Concurrent Engineering

One of the ideas in lean product development is the notion of set-based concurrent engineering: considering a solution as the intersection of a number of feasible parts, rather than iterating on a bunch of individual "point-based" solutions. This lets several groups work at the same time, as they converge on a solution.

People trying to describe Toyota's product development process seem to have settled on "set-based concurrent engineering" as a term for one key part. They see the approach as set-based because it's built around the idea of finding a solution as the intersection of a set of feasible choices, and it's concurrent because teams are trying to work "all at once," not in a sequential, hand-off style.

Reading the book The Toyota Product Development System has me considering these notions again. You can also see the Poppendiecks' Implementing Lean Software Development for more on this idea.

Twenty Questions

You probably know the game of 20 Questions. Let's try it "point-based":

I'm thinking of something.
Is it animal, vegetable or mineral? Animal.
Is it a schnauzer? No.
Is it a parakeet? No.
Is it a goldfish? No.
Koala? No.
Mini-lop rabbit? No.
Blue-tailed skink? You got it.

Instead, let's use a "set-based" approach:

I'm thinking of something.
Is it animal, vegetable or mineral? Animal.
Is it bigger than a breadbox? No.
Is it a mammal? Yes.
Is it a dog? Yes.
Is it curly-haired? Yes.
Is it a standard poodle? You got it.

The point-based approach proposes a solution, and then iterates by revising to a different point. In real design, there's more feedback than in the first game above, of course. But the point solution is in effect treated as "the right answer." If we find out it's not right, we move to a different point.

A set-based approach takes a different path. Instead of moving to a solution right away, it starts with options open, then narrows in on a solution.

Why might we want to take the set-based approach? Because it lets us:

  • defer decisions until the "last responsible moment," when we have the best information;
  • explore many possible designs at the same time; and
  • converge designs more quickly.

We'll look at three ways that software can use a set-based approach.

1. Consciously explore alternatives

One approach is to identify several alternatives, and spend energy to spike and/or analyze the choices. For example, should we use C++, Java, or C#? Should we use an object database or a relational database? Quicksort or insertion sort or radix sort or …?

In lean product development, they use tradeoff curves to record their findings. (See The Toyota Product Development System for more.) That's inspired me to produce the following diagrams. See the wikipedia article on sorting algorithms for many more algorithms and a fuller discussion.



Comparison-Based Sorting Algorithms

Algorithm O(n) O(n log n) O(n1.5) O(n2) Stable?
Bubblesort B     W yes
Selection sort       BEW no
Insertion sort B     EW yes
Shell sort     W   no
Heap sort   BEW     no
Quicksort   BE   W no
Key: B=best-case, E=expected-case, W=worst-case.
Default choices are italicized.



Here's another view of the same information:

You might make a matrix comparing several choices: (fake values; you're on your own here:)



Persistence Mechanisms
Approach Cost Familiarity Support Performance Risk
Hibernate Low Med Low Med to High Med
Custom layer Med High Med Low to High High
Toplink Med Lo Hi Med to High Med



In each of these cases, we spend time identifying and exploring the alternatives, then strive for a clear, succinct way to present the tradeoffs involved.

These summaries can help you narrow in. For example, we might decide early on that we need sorting. A later decision might highlight that stable sorting is important. This would cut down the number of algorithm options. A later decision might highlight the need for consistent performance, cutting our options even more, until we're to the point where we can choose an algorithm.

This approach, of exploring, recording, and narrowing alternatives, feels closest in spirit to the Toyota product-development approach.

2. Consciously enable alternatives

A second approach is to use modularity: create designs that explicitly enable different alternatives. The book Design Rules, Volume 1: The Power of Modularity, by Baldwin and Clark, explores modularity from a non-software-specific point of view; Design Patterns (Gamma et al.), Pattern-Oriented Software Architecture (Buschmann et al.), and many other pattern and software books consider modularity from a software perspective.

Many examples of modularity are based around the ideas of abstraction and of an interface: two parts make a commitment to how they will "talk" to each other, but no commitment about what happens beyond the interface. Consider these examples:

  • Service-oriented architecture. For example, two systems communicate via SOAP, with no commitment about what technology or tool will be used on either side.
  • Network protocols.
  • Plug-in architecture.
  • Layered architecture.
  • Adapter design pattern.
  • Bridge (driver) design pattern. For example, we commit to using a JDBC driver but don't commit to whether we'll use SQL Server, MySQL, or Oracle.
  • Abstract class.
  • Machine-independent language.

Each of these patterns represents a "move" that is consciously leaving room for a set of alternative designs.

3. Incremental design as not blocking alternatives

Gordon Bell said, "The cheapest, fastest, and most reliable components are those that aren't there." Simple design (in the XP sense) suggests, "Don't add anything until you have a failing test that demonstrates you need it."

Each part you add removes flexibility – it either interferes with what you might have done instead, or it becomes dead weight, dragged along even though nothing needs it. And yet, if we don't add parts, our software doesn't do anything.

For example, you've decided on a persistence approach. You could "build the persistence layer," mapping out all objects from all the tables you already have. This creates a "point-based" solution – this is the way persistence works. It creates a drag, from the effort spent on objects you don't need yet. Each of those objects will have to be tested, refactored, and maintained, against that possible day in the future when all that work may finally pay off.

Instead, an incremental design might commit us a little now, but it leaves to the future the set of all possible ways to implement the objects based on the current structure. If we get an idea for a better approach, unmapped objects are free to use it when it's time to map them. (And if the whole approach becomes rejected, we only pay to change objects that were already needed.) 

I think of a simple design as set-based in this sense: Consider the program we have, doing just enough to support the current set of features. Some aspects of this program are a commitment to a particular design. But there is a set of programs out there – all those programs that extend the current program in a way compatible with the current design. By using "just enough design" – not implementing parts not needed to support functionality, we don't eliminate those programs that would evolve in a different way to support those future parts. By contrast, if we fully elaborate an implementation to support our guesses about future directions, we in effect are betting on a point solution, not a set of possible evolutions.

4. Carry Forward with Multiple Implementations

Kent Beck wrote:

I think there is another strategy that also fits the bill–duplicate implementation. The example that brought this home to me was a client of [someone]’s who reported that they were trying to decide between an HTML interface or a rich client interface. [His] advice was to implement both, keeping them in sync every iteration until it was clear which one was most valuable. The client said that they couldn't stand the idea of wasting all that effort, so they picked early and later regretted it.

This is the kind of strategy that is only possible when you have slack programming capacity, enough so you don't mind applying some to risk reduction.

This approach goes further than the first one – rather than evaluate the alternatives and make a guess, we carry forward on multiple implementations, thus seeing the real impact of our decisions.


There are several different design approaches that yield aspects of a set-based design:

  • exploring alternatives (and recording and using the results of that exploration)
  • designing in mechanisms that support alternative designs
  • committing to the minimal level of current design, to leave room for a variety of future designs
  • carry forward with multiple implementations

By applying these tools, you can help match the level of commitment to your solution to the level of understanding you have in the constraints surrounding it.


Further Reading

[November, 2006. Updated 12-20-2006 with Kent Beck’s fourth strategy. Updated 1/4/2014 to add link to more resources.]

Review – Design Patterns in Java

Design Patterns in Java. Steve Metsker and William C. Wake. Addison-Wesley, 2006. I won’t review my own book, but I will summarize:

This is a workbook-style book, updating Steve’s earlier Design Patterns Java Workbook and Design Patterns in C#. It covers the same 23 patterns as Design Patterns, but adds some different perspective and a number of challenges to help you make sure you understand the patterns. It’s targeted to intermediate programmers, though more advanced programmers who want to brush up on patterns might consider it also. (May, ’06)

Review – Game Design

Game Design – Theory & Practice (2/e), Richard Rouse III. Wordware, 2005.
This book is a somewhat sprawling look at game design. Its focus is on electronic games. It covers “what players want,” gameplay, artificial intelligence, story-telling, and game documentation (with what I found surprisingly heavy emphasis on the latter). Rouse intermingles these chapters with analyses of significant games and interviews with established game designers.

The interviews were the most interesting part. The game theory chapters were OK, but Chris Crawford’s books covers the same ground more thoroughly. The material on design documents could have been greatly compressed – it takes about a third of the book, and I didn’t find it particularly revealing. (Reviewed Dec., ’05)

Review – Refactoring to Patterns

Refactoring to Patterns, Joshua Kerievsky. Addison-Wesley, 2005.
Design patterns and refactoring have been related for a long time. (Consider that Ralph Johnson, one of the co-authors of Design Patterns, was a sponsor of the work that created the original refactoring browser.) Josh has cataloged a number of refactorings that can lead your code to (or toward) any of the best-known design patterns. The code examples are excellent: realistic, interesting, and showing what was added or deleted. I recommend it for anybody who understands the basic concepts of refactoring, and is ready to further develop their design and refactoring skills. (Reviewed Sept., ’05)

Review – Design Rules, Vol. 1: The Power of Modularity

Design Rules, Volume 1: The Power of Modularity, Carliss Y. Baldwin and Kim B. Clark. MIT Press, 2000.
Modularity creates value both at the level of systems and at the level of organizations. Baldwin and Clark describe a number of operators that affect modularity: splitting, substitution, augmentation, excluding, inverting, and porting. These operators have economic consequences on the systems they modify. This is a book that I will study again. (Reviewed Sept., ’05)

Cutting with the Grain: The Rhythms of Design

As a result of Kent Beck’s "Programming Intensive" workshop, Kent, Joseph Leddy, and I created a paper on one small aspect of design.

From the abstract:

One way to make software development more valuable is to spend as much time as possible going "with the grain." Programming languages, personal style, and team dynamics all create some paths in which development flows smoothly. They also create other paths which are bumpy and potholed. This paper describes how you can identify which kind of path you are on and what you can do when you find yourself on a bumpy path.

See http://www.threeriversinstitute.org/Cutting%20with%20the%20Grain.pdf (or cached copy)

[Posted on XPlorations, April, 2005.]

Kent Beck’s “Programming Intensive” Workshop

Kent Beck’s workshop was a chance to spend a few days programming and thinking about programming.

We used "games" as the vehicle. That worked well enough – you can get the feel of a game without having to develop it all the way out. In the evenings, we were on our own to do some writing and exercises in thinking about software.

The first couple days, we focused on creating a crossword puzzle helper. The idea is that you’d populate some parts of a grid, and then the tool would fill in the remaining words. We got far enough into it to show it worked on moderate-sized examples, and to start optimizing.

The next program we worked on was a partially developed tic-tac-toe program. We completed some screen hookup and looked at improving the code. We spent a good bit of time contemplating a couple approaches to part of the problem, and how you’d choose between them.

Finally, we took a stab at something closer in spirit to an arcade game; a relative of the commercial games Pong or Breakout. We got as far as having a paddle and a ball bouncing around. We gave it a twist – you controlled the velocity of the paddle, not its direct position. As primitive as it was, Kent’s children gave it a thumbs up.

The week was good for me. I got to learn some things about Eclipse, I got to learn some things about design. We had a couple stretches where we had the "flow" feeling of losing time in the zone. One of the puzzles I’ve been working through is how to take a thin slice of a system; I had some time to think about that.

Would I recommend it? Yes: I learned a lot, and found it great to spend some "renewal time" with others who just wanted to program.