Tuesday, March 31, 2015

Communicating Design Intent by Sharing the Paths not Taken

If you're even remotely a movie buff then you'll probably really enjoy Tony Zhou's "Every Frame a Painting" series.  His analytical, accessible, and entertaining film studies mini-documentaries are wonderful. Each video in the series focuses on one main idea, often something overlooked or perhaps under appreciated by other films studies enthusiasts (analysts? critics?).  This bit of analysis on what makes Jackie Chan's physical comedy so brilliant is... well, itself brilliantly done.

In this episode of Every Frame a Painting, Tony discusses the idea of showing character choice rather than just talking about it, using Snowpiercer as an example:
In nearly every blockbuster you've watched or tell-tale game that you've played, you've seen moments like this: the protagonist has to make a choice and there's no way to reverse it.
Just to be clear, I think moments like these are great and a foundation of good storytelling but I do wish in movies they weren't presented through dialog.  So today I look at one possible alternative.  In fact it's one of the oldest traditions in cinema.  How do you show character choice?  Left or right.  That's it.
In a similar fashion as many blockbuster and video game protagonists software architects regularly encounter complex choices that often can't be easily reversed. Or rather, the architecture we're designing experiences those complex choices (since in this metaphor we're working behind the camera and the architecture is the character on screen). But, unlike blockbusters and video games, software architects don't have the luxury of an audience that can simply watch the architecture evolve with each design decision made.

Even on small teams, generally only a few people at a time are in the room or at the whiteboard when a key decision about the architecture is made.  In some ways it's as if we are asking downstream designers to watch only the last 10 minutes of Snowpiercer and then try to figure out why it's such a big deal for Chris Evan's character, Curtis, to do what he does.  Without the context of these critical decision points that are constantly happening throughout a character's/architecture's journey, the audience/downstream designer loses significant rationale that could help explain a lot.

Are there methods that architects can use to make architectural choice evident?  The answer to this question is certainly, "Yes!"

The Paths Not Taken

While downstream designers can't watch the architecture make a choice on the silver screen (left or right?), we can still make it easier for developers who read our documents to playback the architecture's "character development" more easily.

Sometimes when trying to communicate design intent and rationale, it's more effective to say what you didn't do rather than what you chose to do. The method I'm proposing is pretty simple. Create a list of the architectural decisions you discarded with a brief note for why those decisions were rejected.  With this list in hand, downstream designers have an opportunity to replay critical decision points and can now watch the architecture develop and mature.  Left or right?  What critical moments did this architecture face and what path did it end up taking?

Here's an example from a recent project. The basic problem involves figuring out how to integrate our client software with third-party, cloud-based web services that application developers using our software are starting to employ more frequently. The specifics aren't too important for the example, and I can't really share the specifics anyway.

Path not Taken Why this Path was Rejected
Create a cloud-based "services adapter" to buffer against changes in third-party services.
  • New component that must be maintained by the team. This increases the workload for development, QA, docs, ... everyone.
  • Benefits in features and quality attributes are not required for MVP release
  • Costs significantly outweigh the benefits.

    Release adapter as open source, have customers load it themselves
    • Extra steps to deployment inhibit adoption
    • Open source is great, but unmodified defaults could mean security issues down the road.
    • Worries about training for customers and delivery consultants
    • New component that must be maintained by the team 
    Offer a client library that makes it easier for developers to connect to third party services directly
    • Client library will always be out of date (services are cloud-based with continuous delivery, our software is not)
    • Increased learning curve in that customers must learn both how to use the service and how to use the client library.
    • Documentation overhead - client library must be fully documented.
    • Design overhead, client library becomes a stable API... high risk in getting it right the first time on short schedule.
    • New component, increases workload for team
    No new support for web services integration in the client software
    • Doing nothing does not improve the user experience
    • New patterns and paradigms are emerging that require some kind of help be available to application developers.

    With this background and context, its' pretty easy to see that the design choices we made kept our architecture on a path toward simplicity and tended to favor less code over more code. With this history and context, the list of design decisions that were rejected, it's much easier to understand why the resulting architecture is what it is. You're essentially replaying the architecture's definable moments. Hopefully with this information downstream developers won't scratch their heads when they see what might appear to be an odd outcome for the architecture/character. They can see for themselves the key decisions that led to the architecture/character becoming what it became and in turn internalize a significantly more nuanced appreciation for the architecture/character as a whole.

    Again, the insightful Tony Zhou:
    So, the next time you your character runs into a complex choice, who knows?  Maybe it's actually just a simple matter of: left or right?