Chapter 20: Attribute-Driven Design – Creating Architecture

0:00 / 0:00
Report an issue

Welcome to Last Minute Lecture.

This free chapter overview is designed to help students review and understand key concepts.

These summaries supplement not replaced the original textbook and may not be redistributed or resold.

For complete coverage, always consult the official text.

Welcome back to the Deep Dive.

You know, architectural design, it often gets described with that quote from Antoine de Saint -Supéry.

Something like, a designer knows perfection isn't when there's nothing left to add, but when there's nothing left to take away.

Right.

That's the ideal, isn't it?

But actually getting there, that process can feel pretty messy, far from perfect.

Today, we're looking at how to make it more manageable.

We're diving into attribute driven design, or ADD.

ODD, okay.

Yeah, it's basically a systematic method.

The goal is to make software architecture repeatable, teachable, and, you know, cost effective.

Less mysterious art, more structured engineering discipline for, well, for everyone else.

I like that framing.

It means architecture isn't just for the lone genus architect, right?

It can be a team sport almost.

Exactly.

So our mission here is to unpack this structured process, ADD version 3 .0 specifically.

We want to trace how those core decisions, the architectural drivers, get transformed step by step into actual concrete architectural structures.

From fuzzy ideas to building blocks.

Precisely.

And ADD organizes this whole activity into rounds, which you can think of as major design phases within your project life cycle.

And each round contains one or more iterations.

So rounds are the big chunks, iterations are the smaller repeated steps inside.

You got it.

And before you even start step one of an iteration, there's a crucial setup,

defining the system's scope and context.

You absolutely have to know what's inside your system, what's outside, and how they talk to each other.

That boundary definition is non -negotiable.

Okay.

Context first.

That makes sense.

So once we have that context, where does the ADD process actually begin?

What's step one?

Step one is all about reviewing the inputs.

Getting a solid foundation.

All right.

Let's unpack that.

What inputs are we talking about here?

What are the absolute must haves before we even sketch out a component?

So step one is reviewing what we call the architectural drivers.

This is pretty comprehensive.

It includes your architecturally significant requirements.

Usually these are your quality attribute scenarios, like performance or security goals.

The ASRs, right?

Exactly.

The ASRs.

Then you've got your primary functional requirements.

Think use cases, user stories, and of course, any hard constraints like needing to use a specific database or follow certain regulations.

Okay.

Requirements, constraints,

seems standard.

But here's a key part of ADD 3 .0.

The drivers must also explicitly include the design purpose for the current round.

The design purpose.

Why is that singled out?

Why does the reason we're designing matter so much to the input?

Because it changes everything.

It changes what you optimize for.

If your purpose this round is just say early cost estimation, you'll focus on high level components and maybe deployment.

But if the purpose is risk mitigation through prototyping a tricky interface, you'll focus intensely on those specific scenarios and interactions.

Ah, I see.

So the why directs the what and how.

Precisely.

And if these inputs, especially the design purpose and the prioritized scenarios are vague or maybe they conflict with each other, well ADD just won't work effectively.

It's kind of a garbage in garbage out situation.

So the architect really needs to take ownership here.

Like verify these inputs are solid before moving on.

Seems like a big responsibility.

It absolutely is.

It requires discipline.

The architect has to verify them, own them.

Once they're reviewed and accepted, these drivers, they don't just disappear.

They become the initial entries in something called the architectural design backlog.

An architectural design backlog.

So it's like a specific to do list just for the architecture work in this round.

Exactly that.

It's the single source of truth for tracking what needs to be designed, what needs to be verified for this entire round.

It keeps things accountable.

Okay, that makes sense.

Turning abstract goals into concrete tasks.

Now you mentioned iterations.

Steps two through seven are the core loop, right?

Repeated over and over.

That's right.

This is the heart of the design process within a round.

So what kicks off an iteration?

How do we decide what to tackle next from that big backlog?

That brings us to step two.

Establish the iteration goal.

You know, that backlog might have dozens of drivers.

You can't tackle them all at once.

So each iteration needs a clear focused goal.

Usually it's about satisfying a small subset of the most important drivers from the backlog.

Like maybe one critical use case and its related performance requirement.

Exactly.

Or maybe a specific security threat you need to mitigate.

You pick a manageable chunk.

Okay, so we have a goal for this specific iteration.

Then step three is choosing what parts of the system to work on.

Correct.

Step three is choose elements to refine.

Based on the drivers you picked for your iteration goal in step two, you identify which existing system elements, maybe modules, components defined earlier, need to be worked on to meet that goal.

And how do we refine them?

Are there specific techniques?

ADD suggests three main ways.

You can use decomposition, which is, you know, top down breaking larger elements into smaller, more manageable pieces.

Or you could use combination, which is kind of the opposite, bottom up, grouping smaller related elements together into a larger one.

Or sometimes it's just improvement.

You're not breaking or combining, just refining the responsibilities or properties of an element that already exists.

Now, if you're starting a totally new project, a Greenfield system, choosing elements seems easy.

You just start with the whole system, right?

Pretty much.

You begin by decomposing the system itself as the top level element.

But what if you're modifying an existing system?

That sounds trickier.

It is.

For existing systems, step three often involves some detective work first.

You need to understand the current as -is architecture, maybe through reverse engineering or documentation review, before you can intelligently decide which elements to refine.

It really determines what piece of the puzzle you're focusing on in this iteration.

Right.

Got to know what you have before you change it.

Okay, so we know our goal for the iteration, and we know which part of the system we're working on.

Now comes step four.

Choosing design concepts.

This feels like the core creative part, maybe the hardest part.

It often is.

Step four is arguably the most critical decision point.

This is where the synthesis happens, as you said.

But design creativity here isn't usually about inventing something brand new from scratch.

It's more about identifying, selecting, combining, and adapting existing solutions.

Existing solutions like what?

Things like architectural patterns, design tactics, maybe established reference architectures, or even off -the -shelf components you can integrate.

The real challenge is navigating that huge space of potential solutions.

Yeah, I can imagine.

There are so many patterns, so many libraries out there.

How do architects even begin to identify candidates without getting lost?

Well, the source material suggests three main ways to find candidates.

First, you can leverage existing best practices, you know, dive into pattern catalogs, books, online resources.

The upside being you tap into proven knowledge.

Exactly.

Proven solutions.

Well, it can be a massive time sink.

You spend ages researching, and you still have to figure out if the documented solution is high quality or even applicable.

You know, there can be bias.

Okay, so research is one way.

What's the second?

I bet this is common.

Oh, definitely.

It's leveraging your own knowledge and experience.

This is often super fast.

You feel confident.

But the big risk here is what's sometimes called the hammer nail problem.

Ah, where every problem looks like a nail because all you have is a hammer.

You got it.

You keep applying the same familiar, maybe outdated solutions just because you know them well, even if they aren't the best fit anymore.

Risky.

And the third way.

Leverage the knowledge of others.

Basically, brainstorming with peers, colleagues, other architects.

Get fresh perspectives, challenge your assumptions.

Good idea.

So once you have a list of potential concepts, how do you choose?

Beyond just gut feeling, I hope.

Definitely beyond gut feeling.

You'd use selection criteria, maybe a simple pros cons table or a SWOT analysis comparing the options against the iteration goal and the overall drivers.

And crucially, you must adhere to the constraints identified back in step one.

Things like approved technologies or license requirements.

And I suppose previous choices can limit current ones, too.

Like picking one pattern might make another incompatible.

Absolutely.

Design decisions create path dependencies.

What you chose in iteration two might restrict your options in iteration five.

What if there's still a lot of uncertainty?

Maybe a new technology or a really tough quality attribute target.

That's where prototyping comes in.

Step four is often where you decide if a prototype is needed.

If the uncertainty or risk is high, building a quick prototype can be invaluable.

The source calls these throwaway prototypes.

Throwaway, meaning you don't intend to ship that code.

Correct.

They're built purely for learning.

To gather data, measure performance, test and integration, reduce that uncertainty, and then you discard the prototype code itself.

OK, that makes sense for risk reduction.

And this ties into something you mentioned earlier, the value of information or VOIAI.

That sounded almost financial.

It kind of is.

It's a fascinating concept to play to architecture because building prototypes, running experiments that cost time and money.

VOIAI is basically a technique to help you decide if that cost is justified.

It's risk management with numbers.

So you're calculating how much it's worth spending to reduce uncertainty.

Pretty much.

VOIAI helps estimate the expected payoff from doing an experiment.

Say you're unsure whether a standard three -tier architecture or a microservices approach will meet your performance goals.

An experiment could tell you, but it costs money.

VOIAI helps quantify the potential benefit of knowing the answer before you commit to one path.

How does it work, roughly?

Well, there are two main calculations.

The expected value of perfect information, EVPI, tells the absolute maximum you should ever be willing to pay for an experiment that gives you a 100 % certain perfect answer.

The theoretical upper limit.

Right.

Then there's the expected value of sample information, EVSI, which is more realistic.

It adjusts that value based on the fact that your prototype or experiment

probably won't give you perfect certainty, just better information.

It helps you justify the cost to stakeholders.

So you can go to management and say, spending X on this prototype now could save us Y down the road by avoiding a bad choice.

That's powerful.

It makes the decision much more rational and defensible.

Okay, makes sense.

So we've chosen our design concepts, maybe built a prototype.

Now step five, instantiating elements and defining interfaces.

This sounds like where the abstract ideas finally become, well, architecture.

This is definitely where the rubber meets the road.

Step five is the instantiation phase.

You take the concepts you selected in step four and you actually create or modify the architectural elements.

And you need to think about how these elements fit into the key architectural structures.

Remind us what those main structure categories are.

Sure.

There are three broad categories architects need to manage.

First, module structures.

This is about how the code is organized, files, classes, namespaces.

It's mostly relevant during development time, how the work is divided up.

Okay, code organization.

Second, component and connector, CNC structures.

This is the runtime view, how the system behaves when it's actually running processes, threads, objects, and how they communicate the connectors like RPC or message queues.

One time behavior, got it.

And third, allocation structures.

This maps the software elements onto the non -software environment.

Things like which software component runs on which server or how development work is allocated to different teams.

Software meeting the real world, basically.

Exactly.

And a single design decision like, say, implementing passive redundancy for high availability can impact multiple structures.

It changes the CNC structure, how components interact at runtime, and the allocation structure needing duplicate hardware.

And how you instantiate depends on what kind of concept you chose back in step four, right?

It's not always the same process.

Correct.

It varies.

If you chose a reference architecture like a standard web app model,

instantiation usually means customizing it, maybe adding a specific integration component or removing a feature you don't need.

Tailoring the template.

Right.

If you chose a pattern like client server,

instantiation means making the generic structure concrete.

You have to decide things like how many servers, what communication protocol, what are the specific responsibilities of the client and server elements.

Filling in the blanks of the pattern.

Yep.

Now, tactics,

those quality attribute achieving techniques, they don't usually prescribe a specific structure themselves.

So you realize a tactic by adapting existing elements, maybe applying a pattern that embodies the tactic or integrating an external component that provides it.

And what about using external components like a library or framework?

That often means creating new elements in your architecture that interact with it.

Maybe inheriting classes if it's a framework or simply configuring it, like setting the number of threads in a pre -built thread pool component.

While we're creating or modifying these elements, I assume standard design principles apply like keeping things cohesive internally.

Absolutely critical.

As you instantiate elements, you must define their responsibilities clearly.

You're aiming for high cohesion within elements that should do one thing well and low coupling between elements, minimizing dependencies.

And you need to define their properties too.

Yes.

Things like configuration parameters, whether an element is stateful or stateless, how it manages resources.

These properties are crucial because they're what you'll analyze later to see if you're meeting your quality attribute goals.

And alongside elements, you must define interfaces.

Okay.

Interfaces.

There are external ones dealing with systems outside our control, right?

Right.

Those are often constraints given to you.

But just as important are the internal interfaces, the connections between the elements you're instantiating within your system.

Why focus on those internal interfaces so early?

Because they define the contracts.

They specify how these newly defined elements are going to collaborate.

In early iterations, the interface definition might be pretty abstract, like UI sends commands to business logic.

Okay.

High level.

But defining it, even abstractly, establishes the boundaries and helps manage dependencies.

Then in later iterations driven by specific use cases or quality attribute scenarios,

you'll refine those interface definitions with much more detailed specific method signatures, data formats, protocols.

It's an incremental process.

Got it.

Establish the connection points early, detail them later.

Now we're nearing the end of the loop.

Step six and seven.

Sketching views, recording decisions and performing analysis.

Sounds like discipline is key here.

Huge discipline needed here.

Step six is sketching views and recording decisions.

You need to capture the structures you've just designed, even if it's just informal sketches initially, maybe whiteboard photos.

These sketches are vital for communication and importantly for analysis in the next step.

So drawing pictures, basically.

Yes.

But crucially, you also need to develop the discipline of immediately writing down the responsibilities of the elements you just drew.

The force suggests using a simple table right alongside your diagram and equally important, recording the design rationale.

You mean why we made these choices.

Exactly.

Why did we choose this pattern over that one?

What trade -offs did we consider?

What assumptions are we making?

Capturing this rationale is fundamental.

Without it, future architects or developers looking at the diagrams only see the what, not the crucial why.

It prevents so much confusion and rework down the line.

Documenting the thought process, not just the result, makes sense.

And then step seven, perform analysis and review.

Right.

You need to analyze the partial design you've created in this iteration against the iteration goal and the relevant drivers.

Does it seem like it will work?

Does it introduce new risks?

And you mentioned earlier getting someone else to review it is valuable.

Immensely valuable.

It's like having separate QA for code.

An architect reviewing another's design brings a fresh perspective, different assumptions.

They can often spot flaws or design bugs that the original designer, being so close to it, might miss.

This review step is critical for risk mitigation.

Okay.

Analysis finds potential problems.

How do we keep track of everything we still need to do and know when we're actually done with the design for this round?

That's where the tracking tools come back in.

Remember the architectural design backlog from step one.

It's not just the initial drivers.

As you go, you add new items, maybe tasks like create prototype for X or explore options for Y or issues found during the analysis in step seven.

So the backlog grows and evolves.

It does.

And to visualize progress, ADD often uses a design Kanban board.

Think simple columns, maybe not yet addressed, partially addressed and completely addressed.

Items from the backlog move across the board as they're worked on and verified.

I can see how that helps visualize where things stand.

So when do we stop iterating?

When is the design done for this round?

The key stopping criterion isn't just emptying the backlog or hitting a date.

It's fundamentally about risk.

Yeah.

You continue iterating until you have high confidence that the most critical, highest priority architectural drivers, the ones representing the biggest risks, if you get them wrong, have been satisfactorily addressed.

They should be in the completely addressed column.

So it's risk -driven completion.

Makes sense.

Okay.

Let's try to recap this deep dive then.

Attribute -driven design, ADD, it's really a systematic way to approach architecture.

It's iterative.

It focuses intensely on the key drivers, quality attributes, functions, constraints, and that design purpose.

Right.

And it methodically guides you from those abstract drivers through analysis and decision -making in steps like four and five to produce concrete architectural structures documented in different views.

With a strong emphasis on documenting not just the structures, but the rationale behind them and using analysis and tracking to manage risk.

And it's worth noting this version, ADD 3 .0, has evolved.

It puts more explicit weight on considering implementation technologies early, on clarifying that design purpose for each round, and making documentation and analysis explicit steps.

This helps it fit better within modern agile development contexts.

Excellent overview.

Okay.

That brings us to our final provocative thought for you, the listener.

We talked about the value of information.

The idea that gaining certainty through experiments has a quantifiable value, but also a cost.

So here's something to think about for your own work.

How much architectural design, how much analysis is just enough?

When does the cost in time and resources of chasing perfect certainty outweigh the benefit of making the best educated decision you can right now and moving forward into implementation?

Where's that balance point for you?

Definitely something to mull over.

Thanks for joining us for this deep dive into attribute -driven design.

We appreciate you tuning in.

We'll catch you next time on the deep dive.

ⓘ This audio and summary are simplified educational interpretations and are not a substitute for the original text.

Chapter SummaryWhat this audio overview covers
Attribute-Driven Design represents a formalized methodology that transforms the unpredictable nature of architectural decision-making into a structured, repeatable process accessible to practitioners at all experience levels. The method centers on architectural drivers—a collection of architecturally significant requirements, functional needs, constraints, and overarching design objectives—that serve as the foundation for all subsequent architectural work. The ADD process organizes work into design rounds comprised of iterative steps that systematically move from driver validation through architectural instantiation to design verification. Each iteration begins with input review, where drivers are examined and prioritized to create a ranked design backlog that reflects organizational and technical priorities. The team then selects which drivers to address in the current cycle and identifies which system elements require refinement, whether through decomposition of existing structures or synthesis of elements into higher-level abstractions. The critical challenge emerges during design concept selection, where architects draw upon established patterns, tactics, reference architectures, and external components to address identified drivers. When uncertainty around emerging technologies or critical quality attribute satisfaction introduces risk, the Value of Information technique provides a quantitative framework for deciding whether exploratory prototypes justify their investment cost. Following concept selection, architects instantiate concrete architectural elements—manifested through module structures, component and connector models, or allocation structures—each with clearly defined responsibilities and specified interfaces that establish contracts for element interaction. Documentation of both architectural views and design rationale during this phase ensures that reasoning behind structural choices remains preserved and communicable. Subsequent analysis, typically conducted through peer review mechanisms, evaluates whether the current iteration has satisfied its goals and advanced progress toward the overall design purpose. Progress tracking using instruments like the Design Kanban Board makes explicit which drivers remain unaddressed, partially resolved, or fully satisfied, informing decisions about proceeding to implementation or continuing architectural refinement. Modern applications of ADD, particularly in version 3.0, incorporate guidance on documentation practices, systematic analysis approaches, and implementation technology selection, enabling the methodology to complement agile development practices and remain relevant across diverse project contexts.

Using this chapter to study? Last Minute Lecture is free and student-run. If it helped, consider supporting the project.

Support LML ♥