Design by Committee

Who's driving?

Can a team of experienced, empowered developers successfully design the architecture of a product? Sure.

Can a team of experienced, empowered developers successfully design the architecture of a product without a unified vision of how the architecture should be structured to accomplish its purpose? Probably not.

Can a team of experienced, empowered developers successfully design the architecture of a product while staying within the bounds of their role as developers? Absolutely not.

A lot of ink, both physical and virtual, has been spilled arguing over the utility of architecture and architects. A common misunderstanding among the anti-architect faction is that an application is the sum of its parts. This is particularly prevalent with those espousing the view that if the team does the “simplest thing that could possibly work”, the architecture will just emerge. To be honest, an architecture will emerge from this method. Whether that architecture is coherent, performant, scalable, secure, etc. is quite another matter.

In order to have an informed opinion on whether or not a particular role is need, it is necessary to understand the nature of that role. For example, while the ability to code is a critical qualification for both application and solution architects, it is not the sole qualification. While architects are concerned with the structure of the code, that structure is a means to meet the needs of a customer, not the end in itself.

The purpose of an architect is to understand the needs of the stakeholders and meld his/her knowledge of code, platform (OS, database and web server, etc.), and environment (machines and network) into a cohesive whole that accomplishes the mission. This means the architect’s focus must be on the product as whole, not just a particular project or release and also not on just one aspect (code) of the product. The evolution of both code and platform (hardware, supporting software, and network) needs to be managed across the lifecycle of the product in order for it to remain useful.

For smaller products and teams, it may well be possible for the team to undertake the tasks listed above in addition to their duties as developers. As the scale of the product grows, however, dealing with multiple levels of abstraction and achieving timely consensus across multiple feature teams becomes problematic. At this point, coordination and specialization becomes more important. The architect role then becomes responsible for collaboratively developing and maintaining a unified high-level vision, providing sufficient guidance to keep the product coherent as it evolves while avoiding the trap of Big Design Up Front.

Whether the role is fulfilled by an individual or multiple individuals or the entire team as whole is less important than whether the role is handled effectively. Both “Whiteboard Architecture” and the classic “Big Ball of Mud” need to be avoided.

Faster Horses – Henry Ford and Customer Development

A faster horse

(originally posted on CitizenTekk)

Henry (“Any customer can have a car painted any color that he wants so long as it is black”) Ford was not an advocate of customer development. Although there’s no evidence that he actually said “If I had asked people what they wanted, they would have said faster horses”, it’s definitely congruent with other statements he did make. Henry was also persistent; it took a 75% drop in market share before he finally bowed to the market and brought out a successor to the Model T. All of which makes it very hard to understand why some like to trot out this saying as an excuse to go with their own vision rather than listen to their customers. The most ironic thing of all, is that, regardless of its provenance, this snarky little saying explains the source of the success Ford enjoyed and almost threw away.

Had Ford actually conducted market research, it’s very likely he would have found that people wanted horses that were faster, horses that wouldn’t bury the streets under nine feet of manure, horses that required less care and maintenance, etc. While it’s true that a naive response to these requirements would have led someone down the wrong path, the right path is shining through for anyone who cares to look. Re-read them, replacing “horses” with “transportation” and it becomes clear.

Meeting a need involves two architectures: the architecture of the problem and the architecture of the solution. In this context, requirements, as the architecture of the problem, are design decisions. In “Contexts and Challenges: Toward the Architecture of the Problem”, Charlie Alfred identified two key concepts:

  • Contexts – a set of stakeholders sharing similar goals and concerns.
  • Challenges – obstacles to delivering desired value.

He observes that:

These two concepts, in turn, lead to three important considerations. First, because value (unlike benefit) is subjective, challenges, priorities, risks and tradeoffs are inherently contextual, and the architect must treat context as a first-class concern. Second, the priority of challenges within a context needs to drive architectural decision making. Addressing the highest priority challenges first improves the quality tradeoffs and increases degrees of freedom. Third, while different contexts may pose similar challenges, frequently, the priorities of challenges varies among contexts. Tradeoffs between challenges in a context are often subordinate to tradeoffs between similar challenges across contexts.

Adequately understanding the problem space is a critical first step. People frequently express their wants and needs in terms of solutions rather than problems: “I want a car” rather than “I need transportation”. By the same token, without an appreciation of the constraints that one requirement might introduce, they may well offer up a list of features difficult and/or expensive to meet: “comfortably seat six plus four cubic feet of cargo space and get sixty miles per gallon”. With multiple groups of stakeholders, this sort of conflict is virtually assured. Jumping to the architecture of the solution without adequately addressing the architecture of the problem will lead to wasted effort due to these unresolved conflicts.

Jeff Atwood, in “Listen to Your Community, But Don’t Let Them Tell You What to Do” puts it perfectly: “Community feedback is great, but it should never be used as a crutch, a substitute for thinking deeply about what you’re building and why”. If you’re blindly taking requests without analysis, you’re not providing value. At the extreme end, Patrick Stahler’s advice in “Great value propositions: Not everybody needs to love you” applies: “a great business model is all about what you do and what you do not do”. Not all conflicts can (or should) be resolved: “if you focus on all customer segments, you have no focus”. In attempting to please all, you could easily wind up pleasing none.

Listening to customers in order to understand the problem space does not simplify the architecture of the solution. It does, however, make it much more likely that the solution actually meets the needs of the target market. Ford was luck that his vision resonated with the market at that time. His initial success fooled him into trusting that vision above the needs of his customers and cost him dearly before he relented. As strategies go, luck doesn’t have a good long-term track record.

Mixed Signals and Messed-Up Metrics, maybe?

Dentistry has made me a liar.

One of my tasks each morning is to make sure my youngest son brushes his teeth. Someone, somewhere decided that two minutes of tooth brushing will ensure optimal oral hygiene, which target has been transmitted by our dentist to our very bright, but very literal six year-old. Every morning when he has thoroughly brushed and I give him the go-ahead to rinse, he asks “Dad, was that two minutes?”, to which I reply “yes, yes it was”, regardless of how long it took. I’m a horrible person, yes, but trying to explain the nuances to him at this age would be a pain on par with trimming my nails with a chainsaw – the lie works out better for all involved.

My daily moral dilemma has a very common source – metrics are frequently signals of a condition, rather than the condition itself. When you cannot use a direct measure (e.g. number of widgets per hour), it’s usual to substitute a proxy that indicates the desired condition (at least that’s the plan). A simplistic choice, however, will lead to metrics that fail to hold true. Two minutes spent brushing well should yield very good results, however, inadequate brushing, no matter how long you spend doing it, will always be inadequate. This is a prime example of what Seth Godin termed “…measuring what’s easy to measure as opposed to what’s important”.

Examples of these types of measures in software development are well-known:

  • Lines of Code: Rather than productivity, this just measure typing. Given two methods equal in every other way, would the longer one be better?
  • Bug Counts: Not all bugs are created equal. One substantive bug can outweigh thousands of cosmetic ones.
  • Velocity/Turn Time: Features and (again) bugs are not created equal. Complexity, both business and technical, as well as clarity of the problem, tend to be have more impact on time to complete than effort expended or size.

As John Sonmez noted in “We Can’t Measure Anything in Software Development”: “We can track the numbers, but we can’t draw any good conclusions from them.”

There are a number of reasons these measures are unreliable. First, is the tenuous ties between the measures and what they hope to represent as noted above. Second, is the phenomenon known as Goodhart’s law: “When a measure becomes a target, it ceases to be a good measure”. In essence, when people know that a certain number is wanted/expected, the system will be gamed to achieve that number. Most importantly, however, is that value is the desired result, not effort. In manufacturing, more widgets per hour means greater profits (assuming sufficient demand). For software development, excess production can likely yield excess risk.

None of this is to suggest that metrics, including those above, are useless. What is important, however, is not the number, but what the number signals (particularly when metrics are combined). Increasing lines of code over time coupled with increasing bug counts and/or decreasing velocity may signal increased complexity/technical debt in your codebase, allowing you to investigate before things reach critical mass. Capturing the numbers to use as an early warning mechanism will likely bear much more fruit than using them as a management tool, where they likely become just a lie we tell ourselves and others.