Posts tagged ‘Architecture’

Exploring the Design Space

In Choosing a Software Design Strategy I proposed that your understanding of the design space will determine what design strategies are appropriate for your project. That is, how much you know about the problem domain and solution space will determine how much design work is appropriate for your project. Rather than fussing over dogma, the power is clearly in your hands. If you feel uncomfortable with what you are capable of designing, then you need to further explore the design space! Otherwise, you are free to design in a way that is appropriate to your understanding of the system and a way that makes sense to your team be it Big Design Up Front or a more minimalistic design approach.

Personally I’m a visual person so having a graphical representation which shows how to think about what I know about the design space is extremely helpful to me. In this graphical representation, there is a real boundary which will eventually prevent me from exploring the infinitely large design space. This boundary is formed by things like time, budget, and schedule as well as thought stuff such as your team’s training or overall knowledge and the existence of research or even existing technologies. For example, once I was involved with a project that required large amounts of data to be transferred from Australia to the United States in real-time with an aggressive deadline, on the order of tens of milliseconds. Crunching the numbers, we quickly realized that this was completely impossible with the existing telecommunications infrastructure. In fact, the only technology we could find which might promise this kind of performance was entangled quantum particles which are only today becoming a reality…sort of. The solution boundary in this case severely limited our ability to find a viable design. Sometimes you can move these real boundaries, for example by increasing the budget and schedule or hiring a consultant, but any system you design will come from your understanding of the area in the highlighted space shown below.

The Rational Design Space

Another interesting thing about this representation is that it’s actually parametric. The X and Y axes will tell you what you know, but your understanding of the problem you aim to solve and the solution you are using to solve it will change over time. It’s also possible that you might not start at (0, 0) in every case. And the way you learn about the design is going to be different every time, rarely (if ever) taking the direct, efficient route to enlightenment. As time goes on, as you learn more about the problem and solution, you’ll create a parametric curve, the shape of which will give you a pretty good idea of where your knowledge gaps might be. And thinking about design in this way exposes some interesting things about what you know, and what you might need to learn in order to make a satisficing design.

Design Knowledge over Time

So if you have a design curve that starts off almost horizontal, it means that you know a lot about the problem but don’t know very much about solutions. Teams with lots of specific domain knowledge might face a curve like this. Most of the projects I did with the US Navy started with a curve that looked like this. The problems the Navy was trying to solve were well understood and the teams were initially made up of veteran subject matter experts. One of my jobs then was to help understand how to solve these well understood problems using more recent advances in hardware and software.

A curve which starts off steep presents the exact opposite case. Here the team has plenty of knowledge about possible solutions but knows very little about the problem. This is the case with most software development teams. We’re experts in building software and in most cases, when someone comes to us with a problem they want a software solution. The team’s main focus will be on understanding requirements and then applying their software engineering knowledge in creating a solution. A great example of this scenario is web development shops who specialize in creating web applications for clients. For these teams, every solution will involve some kind of 3-tiered system, probably using one of a handful of languages the team is an expert in. Now it’s just a matter of understanding the problem so they can iron out the specifics of the solution.

Design space - knowledge discovery opportunities

Most of the time your team is going to have a pretty good mix of knowledge, and as you work to complete the project you’ll embark on a circuitous journey through the design space, eventually coming to a point where you’ll feel comfortable moving forward with design and full scale development.

Your team will have some base knowledge at the start of the project. From there you’ll start to explore requirements which might lead you to thinking of certain solutions. Of course any solution will involve trade-offs which will expose new problems to consider so it’s back to the client to talk about the positives and negatives of one solution over another (quality attribute scenarios work great in this situation). As you explore these new problems, you’ll gain new knowledge which will then help you learn even more about the solution. Throughout this journey you might create prototypes, architecture descriptions, sketches, or code stubs. Each of these things will serve as a communication aide for your team and clients and give you tangible evidence of your understanding of the design space.

Exploring the design space - knowns and unknowns

The ultimate goal of this line of thinking is to figure out a better way to understand how to effectively explore the design space so you can more effectively reach a point when you have enough knowledge to be able to move forward with implementation. At some point, you’ll feel comfortable with what you know and create an appropriately detailed design. Or maybe you’ll just jump right into implementation. Exploration might take a few minutes or several weeks, all depending on what you already know about the problem and potential solutions, not to mention the size of the design space that needs exploring (more space implies more complexity and bigger systems). You might leave large swaths of the design space unexplored when you create your design or move onto implementation or you might explore everything fully. Regardless of your knowledge, it is important to realize that the amount of detail you use in your design and when you do that design work – the design strategy you choose – is an independent matter but your knowledge will limit your design capabilities.

The awesome part about thinking about design in this way is that even though you’ve moved on to a different phase of your project’s lifecycle, your knowledge and understanding of the design space will not cease. You’ll continue to learn more about the problem and solution with each step of implementation until the project ends. And by the end you will have the most complete understanding of the problem and solution yet. Of course, this will also be the time when this understanding is least helpful to you since the project is over! The essential key then is to apply methods which help you to quickly and efficiently understand when enough is enough so you can create useful plans, organize your team, and begin implementation with confidence that you will succeed.

Choosing a Software Design Strategy

I was reading an article from the Joel on Software archives and was struck by this quote from The Project Aardvark Spec:

I can’t tell you how strongly I believe in Big Design Up Front, which the proponents of Extreme Programming consider anathema. I have consistently saved time and made better products by using BDUF and I’m proud to use it, no matter what the XP fanatics claim. They’re just wrong on this point and I can’t be any clearer than that.

When thinking about design there are two extremes pivoting around how much up front design work needs to be done before you start writing code. Proponents of up front design point out, as Joel has in the quote above, that making changes in the design is a lot cheaper in a 20 page design document than a partially or fully implemented system. With a solid plan you stand a better chance of not painting yourself into a corner and avoid having to make expensive design changes in the code later. Opponents of BDUF worry greatly about analysis paralysis, which can severely delay a team’s ability to provide working software to the client. Codified in this thinking are the assumptions that clients don’t really know what they want until they see it and that only by getting working software in the hands of users can we understand whether a proposed solution is a good enough solution. To these folks, writing a design document is wasted effort because they don’t know what they want and they believe to their core that things are going to change anyway.

Both of these perspectives are correct. Both of these perspectives are also wrong. Since everyone loses when thinking in extremes and ultimatums, let’s figure out what is really going on.

Choosing a Software Design Approach: Theory

Building software falls into an interesting case of problems known as wicked problems. This means basically that there are many possible solutions and that no solution is really “right” or “wrong” only “better” or “worse” given your current understanding of the problem. Further each problem is essentially unique, there isn’t an explicit stopping rule, and as the designer you will be held liable for consequences of your solution.

With this in mind, in thinking about software design there are two variables which will determine how you go about designing a solution.

  • How well do you understand the problem domain?
  • How well do you understand the solution space?

In the software world, understanding the problem domain means thinking about technical constraints, functional requirements, quality attributes, and business constraints. Understanding constraints is critically important since these will define some of the boundaries of the solution space. Functional requirements deal with what the system will do while quality attributes deal with how a system should behave when performing certain functions. Finally business constraints are things the customer simply requires of a solution usually for business reasons (a common example is a budget or delivery date).

The solution space is a multi-dimensional landscape filled with nearly limitless possibilities. As the designer it is your job to figure out how to navigate this space in search of a solution to a problem. Your current understanding of the problem limits your ability to see solutions and often the fitness of a solution can only be understood in reference to another possible solution. I imagine the solution space as a mountain range and my job as the designer is to find the “best” mountain for my client. Of course some mountains might block my view from others which means I may have to climb a peak just to see a better solution. This implies that my understanding of the problem dictates my understanding of potential solutions and that my understanding of the solution will yield further insights into the problem. This is one reason why it is often helpful to get working software in front of users quickly.

Graphical depiction showing how a team's knowledge of the soultion space and problem domain will be bounded by constraints prevent fully rational designs.

When designing something we have a natural tendency to prefer making rational design decisions where, after careful examination of all information we choose the best or optimized solution. To make a rational choice requires not only that we know everything about the problem domain but also everything about every possible solution to the problem. Both business constraints, by constraining time or money, and shortcomings in the human brain limit on our ability to seek this knowledge creating a boundary around which a solution must be found. And it is in this world of bounded rationality that we must find a solution for our customer’s problem. Searching for a solution then is not as much a matter of optimization (finding the “absolute best”) as it is a matter of satisficing, finding the best solution with the information currently available. To complicate matters further, an individual’s understanding of the problem domain and solution space is relative to that individual’s experience and capabilities, the size of the problem, and the complexity of the solution.

When designing software it’s natural to want to move as far up the knowledge curve, get as close to making a rational, optimal design, as possible. This tendency stems from our instinctual preference to avoid loss [1]. In other words, designers assume that an optimal solution exists and so are predetermined to reject less than optimal solutions.

Choosing a Software Design Approach: Application

In the software design world there are four basic types of design strategies.

  • Planned Design: All design is completed before beginning implementation. Often referred to as Big Design Up Front by detractors and associated with waterfall lifecycles. The essential assumption is that you can fully design a system before beginning construction.
  • Minimally Planned Design: Some design is completed before beginning implementation. Sometimes referred to as Little Design Up Front. In using this strategy you acknowledge that some change is likely to occur but still want to avoid painting yourself into the obvious corners.
  • Evolutionary Design: The design of the system grows as the system is implemented , but growth is deliberate and controlled by experienced engineers and proven engineering practices such as reference designs and refactoring. At least some requirements are usually specified in the beginning but it is not expected to be exhaustive.
  • Emergent Design: The design of the system is allowed to occur organically as the system is implemented without specific intentions.

Graphical representation showing when specific design strategies are applicable based on design stabilty and the amount of desired planning

The design strategies appropriate for your team to choose is going to be determined by the amount of risk remaining in the bounded knowledge graph. Less risk implies that you anticipate less change (or at least that you feel you can deal with the change reasonably) and the more options you will have in choosing a design strategy. Choosing a design strategy then is a matter of deciding the degree to which your team would like to plan within the determined appropriate strategies. The amount of planning will depends on your team’s preferences and experience, or can be driven by customers’ business needs. From a theory perspective, the amount of planning appropriate to the project is directly proportional to how much you know about the problem domain and the solution space. In other words, the less you know about a problem and the fuzzier the solution seems to you, the less capable you will be in making planned designs. As designers we run into problems in our designs when we are wrong about what we think we know about the problem domain or solution space. Unfortunately as eternal optimists, software engineers get these things wrong often.

Don’t feel comfortable with the design strategies appropriate for your project? Remember that the appropriateness of a design strategy is based on your current understanding of the solution space and problem domain. Therefore, to make more design strategies available to your team you must learn more about the solution space and problem domain. I find that examining the project risks is the best way to determine what you think you know about the problem domain and solution space. Understanding the engineering risks your project faces also serves as a blueprint for moving along the knowledge curve. For example, if your team feels that they don’t know enough about the problem based on the identified and prioritized risks, you can increase your knowledge about the problem domain. On the same token, if the team feels there is a lot of risk concerning the solution space you can explore different designs, run experiments, or create prototypes for your users to try. Another option other than looking at risk is to use a design process such as Architecture Centric Design Methodology (ACDM). ACDM is a staged design process that encourages teams to explore the design space through experiments by addressing issues in proposed designs. ACDM strongly focuses on quality attributes and will nudge your team toward a planned design strategy but the process can be adjusted to use a different design strategy, if that is something your team strongly desires, by adjusting the go/no-go criteria between stages.

Remember too that you learn more about the problem and solution as you implement the system. So by the end of the project there will be no risk, you’ll know everything about the system you can, and you’ll have all the information necessary for a great (and practically useless) planned design.

The Project Aardvark Design Approach

Let’s apply this information to Project Aardvark and figure out why Joel is such a strong supporter of BDUF at Fog Creek Software. Project Aardvark, like most other software systems developed at Fog Creek, is a developer tool. This means that the folks developing the system are also going to be at least one of the groups of end users. We can assume based on Fog Creek’s hiring strategies that the developers are pretty smart. Further, Aardvark falls into a class of problems which has been well studied meaning there are examples available for study and some folks at Fog Creek may have even implemented similar (but not identical) systems or subsystems.

Determining what design strategies are approporate for Project Aardvark based on knowledge concerning the design.

The implication is that the Project Aardvark problem domain is well understood and the solution space doesn’t need much exploration because Joel doesn’t perceive much risk in the solution. Since Joel has a firm grasp on the problem domain and since he feels confident about the solution space, he doesn’t anticipate much change in the design throughout development. Based on the information Joel has available about the project relative to his knowledge and experience with the problem domain and solution space, a planned design strategy is appropriate for this project. Joel could use other approaches further down the application curve too, but since Joel has relevant experience with planned design, the design probably won’t be that big (in fact it was less than 20 pages), and the Fog Creek team is used to following planned designs, planned design is probably a good fit for Project Aardvark.

One last note. Bounded rationality implies that the planned approach to design may not always be possible. There is a limit based on the size of the problem domain, solution space, and business constraints (especially time and resources available) that may prohibit you from effectively using Big Design Up Front. In other words, it may not always be possible to be high enough on the knowledge curve for a planned approach to make sense. Opponents of BDUF will tell you that most software falls into this category. In the case of Project Aardvark, the system was relatively small and Joel ensured that he had plenty of resources and time for exploring the solution space. It is critically important to understand where the boundaries that might prevent you from rational design are. Since we prefer rational optimization over decision making with less information, failing to recognize these boundaries will result in analysis paralysis.

By understanding some of the theory behind design decision making it’s easier to know where in the spectrum of possible design strategies your project belongs. Examining a project’s engineering risks is a relatively simple and repeatable way to determine where you are on the knowledge curve for a project. Now it’s possible to move your team up the knowledge curve, as necessary, to reach a point where you feel comfortable with the risks your project faces. You move along this curve by addressing the project’s risks through prototyping, research, experiments, evaluating proposed designs, and interacting with the customer. You could also use a specific design process such as ACDM. It is important to recognize that by moving up the knowledge curve you are necessarily moving your team closer to being able to use a planned design strategy. Your location on the knowledge curve will determine which design strategies you can use but you still need to determine which makes the most sense for your team and the project. Finally, these curves are relative and the scale is going to change from project to project and team to team. I think the principles behind the curves are more important than the curves themselves and you shouldn’t take the curves literally as a mathematical function.

Further Reading

End Notes

[1] This also explains why humans behave the way we do in free market economies, gambling, and other similar situations. I am attempting to apply information I learned watching this TED Talk on monkey economics and irrational decision making by Laurie Santos.

Improvisational Architecture

If you were to go to two improvisational jazz performances, even two concerts by the same band, you’d hear different music at each show. The thrill of experiencing something unique, as it is created, without any kind of real plan or rehearsal, is both exciting and entertaining. Sometimes the music is so spectacular you feel like you’re witnessing a miracle. Other times the group can’t seem to get it together and the show is one long, painful indulgence in artistic expression. No matter the outcome, what you hear during that performance will never be experienced again.

Music has always served as a great metaphor for thinking about software development. At XP2010 during one of the most original key notes I’ve ever seen, Bjørn Halterhaug and John Pål Inderberg, professors of musicology and improvisation respectively, from the University of Technology and Science in Trondheim, Norway and both veteran jazz musicians, discussed, through music and words how they approach improvisational jazz, the mechanics for making it work, and the general implications on collaboration among artists. It’s tempting to romanticize improvisational jazz as a truly spontaneous creation but this isn’t exactly how it works in reality. For any improvisational jazz band to be successful its members must exhibit seven key characteristics.

  1. Provocative Competence Interrupting Habit Patterns
  2. Embracing Errors as a Source of Learning
  3. Minimum Structures that allow Maximum Flexibility
  4. Distributed Task: Continual Negotiation toward Dynamic Synchronisation
  5. Reliance of Retrospective Sense Making as Form
  6. Hanging out: Membership in Communities of Practice
  7. Alternating between Soloing and Supporting

I propose that these seven characteristics apply directly to how teams who espouse emergent design should approach software architecture.

XP2010 Keynote: Bjørn Alterhaug and John Pål Inderberg improvising jazz music on stage.

Music and Design

Experienced musicians have an attenuated ear which enables them to hear music in ways that novices can’t. Drawing on a well-developed playbook of clichés, an expert in the standup bass for example can not only follow the minimally, well-defined structure of a song but also weave pleasing bass licks into the musical ramblings of his band mates, adjusting his actions based on the paths his band mates choose with appropriate responsiveness as the song develops. Part of it is musical maturity, a taste or style developed over years of playing, part of it is also trust both in himself as a musician but also in the rest of the group, that they too will not overreact to mistakes and are also able to follow a musical flow as it develops.

Well-defined but minimalist structure. Contrast this with the music played by a symphony which is also well-defined but has explicit and detailed structure.

When I hear this I immediately think of architecture as seen through the lens of agile software processes which advocate strongly for emergent design. Agile software development processes and agile culture in general strongly encourages teams to become improvisational architects. Create a minimalist, well-defined design of the system and then allow the developers to evolve the system, creating the design as they develop, playing off the code written by their fellow teammates as the system emerges. The romantic view of this is appealing to some: “Let’s go have a code jammin’ session, you dig?” But the results of an emergent design can be just as varied as improvisational jazz bands; some designs are elegant and spectacular successes, some designs are flaming piles of disaster, most turn out somewhere in between – usually good enough for customers who aren’t paying too much and who expected a somewhat unpredictable but functionally adequate outcome.

So if you enjoy the thrill of experiencing once-in-a-lifetime moments of creation, the outcome of which can never be predicted or known ahead of time, then emergent design is probably right up your alley. As demonstrated by the near exclusive emphasis on code and shipping, many agile developers fancy themselves as code jammin’, improvisational architects.

The exact opposite of emergent design, of course, is the easy to hate (and rightly so) enemy of creating things that actually work, Big Design Up Front, where a heavy cost is levied against a project in the beginning without producing any usable code whatsoever. Sticking with the music metaphor, the well-defined, explicit, and detailed structures of a symphony might take a composer months or even years to create. But in exchange for this planning you get a piece of music that is guaranteed to be executed (for all intents and purposes) in a nearly identical way in every performance in which it is played. I am not saying you should use a Big Design Up Front approach, in reality, even Mozart tried out music and made incremental deliveries to his sponsors as he wrote.

While certainly a degree of improvisation happens when we develop software, customers paying for software usually expect more predictability in the outcome. So, while it might be ok to spend 30 bucks for a fun first date with a girl at a jazz club – if only for the experience of it – when I pay 100 bucks a ticket to see the symphony play Mozarts’s Requiem, I would be more than a little disappointed, angry, and confused if the first chair violinist “felt a groove” in the middle of the second movement and began jamming. The greater the cost of a project, the more highly valued predictability in it will be.

Who can be an Improvisational Architect?

Mozart was a true genius, a master of composition. To play Mozart, you need to be well practiced but you don’t need to have his level of genius. On the other hand, most members of a great improvisational jazz group must be experienced musicians – experienced in composition as well as technical playing ability. Even then, a great group will usually avoid disaster but occasionally it will still happen because of the nature of improvisation.

In my experience, teams that plan to allow their designs to emerge do an ok job of providing the minimal structure that is essential for evolving a design. But only a few developers have the necessary experience and background to truly improvise a design. The implication? Most teams are terrible at improvising architecture because they have neither a solid enough understanding of the core fundamentals for software architecture nor the experience with using architectural design to reason about a system.

I believe that most of the seven characteristics of improvisation are deeply ingrained in agile culture, but agile teams often fail to fully embrace all seven characteristics of improvisation when designing a software system. A team without the experience, who doesn’t understand design cliché’s (architectural styles and patterns) will have an unpredictable outcome when allowing the design of a system to emerge as the system is developed. This is something the agile community must work to resolve.

Bonus

Cory Foy was thinking ahead and had the foresight to record video of the performance/keynote.  It comes in 6 parts.

Ingvald Skaug was also inspired by this talk and wrote an interesting essay which explains kanban as agile jazz. Check it out for a process perspective on the idea of “minimal structure for maximum flexibility.” If you believe Conway’s Law, then it isn’t coincidence that we would apply the characteristics of improvisation in jazz to both process and design.

Exploring Archetypes of Architects

During a brainstorming session in a recent OOPSLA workshop I participated in we were discussing what qualities make for a “good” architect in an agile world. I jotted down this list during the discussion based on the group brain dump. Some archetypes are “good” while others are “bad” but I don’t think any of them necessarily describe the perfect architect. When you’re designing software, what kind of architect are you? What kind do you prefer to work with?

The Megalomaniac Architect: “You will implement the system as I have designed it because I am the most important person on this team, the project will fail without me, and I am the only one smart enough to know everything that needs to be known!”

The Benevolent Dictator: “Implement the system precisely as I have designed it and I will make your work easier.” [via Dennis Mancl]

The “Everything’s a Nail!” Architect: All problems can be solved by a single tool, idea, or way of thinking. He’s got a hammer…and everything he sees is a nail.

The Diva: “I’m the architect of this system! Are you questioning my ability to design? If you’re not going to appreciate my talents, maybe I’ll just go to another team.”

The Magician: Excellent at high level abstraction, vague on how the design actually achieves architectural drivers.

The Over-Accommodating Architect: “You want that change? No problem.” There are no trade-offs to consider when making architectural decisions.

The Chess Master: To achieve victory, it is simply a matter of being able to see enough moves ahead. Every element in the architecture can be strategically placed in a perfect position to checkmate your opponent: requirements changes.

The PowerPoint Architect: “Architecture is just pretty pictures!”

The Ninja: Infiltrates a project from the outside, crafts an amazing design, then disappears into the shadows before anyone realizes he’s gone. Ninjas do not suffer fools and their designs are technically correct, thorough, and beyond your ability to comprehend.

The Navigator: Creates a map (with legend) and uses it to plot a course through implementation, testing, and deployment.

The Movie Producer: Leads the team indirectly by providing technical design support. [via George Fairbanks]

The Coach: Teaches the team about architectural practices and concepts as well as the design.

The Puppeteer: Able to manipulate multiple levels of abstraction simultaneously to design the architecture, the Puppeteer effortlessly manages the various threads influencing the design (commonly known as architectural drivers).

The Seasoned Veteran: He’s tried a lot of things and is pretty good at all of them including programming, design, processes, and management. Thanks to his experience, having walked 10,000 miles, he understands the role of architecture across the lifecycle, has seen many different situations, and is an excellent technical practitioner. [via Bill Opdyke]

The Long-Bearded Wise Man: A little philosophical but always willing to share an enlightened thought that will help resolve whatever concerns are ailing the project, though somewhat indirectly.

The Team Captain: A bona fide member of the team, playing on the field with everyone else, leading the team from the field.

The Design Evangelist: Excited about the architectural drivers and architecture to the point of near fanaticism. His enthusiasm for architecture and the system’s design is infectious and helps maintain conceptual integrity of the system.

The Student: Takes time to learn about the problem domain and the customer’s needs to the greatest extent possible so that he understands and solves the right problems. [via Gail Harris]

What other archetypes have you worked with? Which archetypes do you think might combine to make the perfect software architect?