Design boot camp

I attended a three-day Construx Design Boot Camp August 5-7 at the Construx Bellevue, Washington headquarters.  The instructor was Matt Peloquin.  It was great.  Even though for the past few years I’ve been reading and trying to really improve the quality of what I produce, there were many concepts and perspectives I had not considered.  Good stuff!

Following are some of the highlights from my notes.


“The art of design is balancing tradeoffs”

Design doc artifacts: think lean – “What’s really needed?”

Potential purposes of design artifacts:

  • a simplified view that supports decisionmaking
  • a communication tool
  • help to future maintainers – why were things done this way?

Balance: keeping things lean with making sure there is enough understanding

In most cases, the things that are easy – the explicit knowledge – aren’t really the most valuable.  Think about what really needs to be captured.


Consider breaking the link between the exploratory design doc and the “as built” design doc. “What’s the least we can write down to effectively support our ongoing maintenance needs?”

To adopt a lean perspective, drive the level of detail in the design based on risk.  (Safe areas, less detail; risky areas, more detail.)  Unless we are intentional about this, though, since the risky areas tend be areas where more is unknown, we tend to write less about those areas and concentrate on the areas we know — exactly the opposite of a risk management approach!

Conceptual information is valuable!  Put it in the design.

Most diagrams are better if done at a conceptual level…

…so make sure you leave out some details

…and don’t forget to bend/break the rules!

Big, long design documents don’t tend to get read

Tribal knowledge: decide how much is reasonable based on risk

“The path to a high-quality design is not deterministic.  Experience, creativity, and artistry are required.”

We need to get good at sensing where the system will need to be flexible

Essential vs. accidental complexity

Trying to design everything up front can be wasteful, because what you learn along the way could obsolete decisions made earlier; BUT on the other hand, there are some things that would be prohibitively expensive to add later and need to be thought of from the beginning.  Think about the economics: which areas wll be cheaper to pre-optimize than to retrofit

Lean design – it’s about being intelligent about where to invest our time

As a designer don’t ‘adopt a paradigm’ — rather master as many paradigms as possible, so you have different ways and tools to approach and solve a problem

“Design to tools”: basing the design on what the tool does well

Local vs. global complexity: Decomposition decreases local complexity (methods/classes are simpler) but increases global complexity (more methods and classes in the system) – the increase in global complexity is often worth it, but should be kept in mind

Making design a team activity (including testers/QA)

Very few requirements problems are technical problems.  (They’re mostly people problems.)

The “-ilities” (Flexibility, maintainability, supportability, scalability, security, etc.)

ISO 9126 Quality Model

Maintainability is one “ility” that can be one of the best bangs for the buck

Economic benefit of automated tests over several years relative to manual regression testing — immense!  Put price tags on it.

Big idea: “ilities” often conflict: there is no such thing as the “best” design because it depends what your priorities are.

Consider the “ilities” early

Performance: Ask “What part of the system needs to be fast?”

“Ground truth” — the importance of making sure you’re tracking with reality

Talk about money, not beauty and elegance, when addressing management

A good designer

  • won’t master all technologies
  • but will be aware of what is available
  • and will master what is most useful in their domain

The group exercises and interaction with the people from different companies were very helpful as well.

I hoped that this training would be different from some of the onsite training I’ve experienced, which has seemed to have a tendency to address the lowest common denominator and has ended up being unfortunately largely a waste of the company’s time and money, at least from a perspective of “how much would  it have hurt us if we hadn’t done this training?”  I hoped this training would be different, and I was not disappointed.  Taking a systems perspective on design alternatives and design process alternatives is a big deal, and I think some of the concepts from this seminar have changed the way I will approach design.

Thanks, Matt!  And thanks again, Construx!

StartupSvcFactory: why go to the bother?

In a previous post I had said we had

…changed our can’t-mock-dis Startup service from a plain ol’ Singleton…to an Abstract Factory so that…we can now mock out the Startup service and its application-context-creatin’ slowness when we want to.

But some muddled thinking had snuck in on my part: New Ben notes that you don’t need a factory to mock an interface.  Why didn’t we just make the StartupSvc class an interface and mock that interface?  Why go to the bother of creating a StartupSvcFactory as well?

Here’s the proof:

  1. Assume that a factory is not needed
  2. StartupSvc is a class, and getStartupSvc() is a static method on it
  3. You can’t have a static method on an interface (a rule of the Java language), and a factory is not needed (by assumption, #1), so we’ll make getStartupSvc() an instance method of StartupSvc.
  4. To call getStartupSvc() as an instance method, you must already have an instance of a StartupSvc on which to call it, BUT because StartupSvc is a singleton, the only way to get an instance in the first place is by calling getStartupSvc().  When getStartupSvc() as an instance method, there is no way to call it.

∴ a factory is needed.

The factory then takes care of managing the singleton-ness of the StartupSvc and holds the static StartupSvc reference.

How does this help mockability?  Client code then holds a reference to a StartupSvcFactory (interface) and is injected with a StartupSvcFactoryImpl whose getStartupSvc() instance method returns a real StartupSvcImpl — but unit tests inject a mock StartupSvcFactory and can then simulate different behaviors coming from the StartupSvc that are difficult to reproduce, or just slower, with the real thing.