a Trace in the Sand

by Ruth Malan

 

 

 

 

February 2018

2/20/18

February Traces

What's a Trace?

A Trace is what I called my journal -- where I write my notes as I explore what it takes to create architecture and be a great architect. You might consider it a warning about my sense of humor and delight in Life's irony and the jokes the Universe plays on us, that a person who helps shapes the field of architecture, predominantly writes in so "disorganized" and emergent a style as a journal. [grin] But it is a format that emphasizes that we are, individually and as a collective, a field, on a learning journey --- many journeys, really. Individually. And across the lot of us.

I need to carve out time to get to Part II of the Visual Architecting keynote slidedeck -- going into more of the architecture modeling and heuristics that guide architecting, and then widening the field of view, to explore what architecture means, when we take another look at what is significant in "architecturally significant decisions." In the meantime, here's Part I (it's also on the Bredemeyer site):

10/3/17

Image: Fearless Girl -- gently persisting in taking people along a path they think they know, and showing them what they haven't been seeing.Part I. Visual Architecting Keynote

Earlier this year, I was awarded the 2017 Linda M. Northrop Software Architecture Award. I encourage you to take a look at the criteria for the award, and join me in thanking everyone who endorsed me, as the nomination and endorsements take considerable work to put together! Work -- and also a generosity of spirit that sees and recognizes another person's contribution.

The award takes place at the annual SATURN conference and I was asked to give a keynote in conjunction with accepting the award. It was an honor -- and a predicament, as I'd decided formal talks are not my forte. I was asked to focus the talk on work that led to the award, which is rather broadly scoped for 30 minutes. Eventually I settled on talking about how we view software architecture and visual architecting. Which resulted in another conference slideset, so at least there's that. My slides are available as a .pdf on SEI's SATURN conference site, and on Slideshare (where you can download the slides; and remember to Like them if you do).

Preamble

How we approach architecture, defines what architecture, in effect, is, at least for our system. That is, no matter what we say architecture is (for), architecture is (an outcome of) what we do. This is a POSIWID (the purpose of a thing is what it does -- Stafford Beer) kind of point, noting that what the thing does, trumps what we may think it is and ought to do.

Still, intentions influence behavior. How we conceive of architecture, influences what we do. If we think software architecture is a set of decisions, say, we're going to try to notice when we're making a decision so we can write it down. If we think architecture is diagrams or maps, we'll direct attention there.

In short, what we do in the name of architecture, shapes what it is; what we think it is, shapes what we do.

At any rate, I wanted to elaborate a richer understanding of what software architecture is, to inform how we advocate approaching the architecture of systems we're design-evolving. So here, after the passage of several months, is more or less the thrust of the talk:

Annotated Keynote Slides

Outline

As a bridge from Bill Pollack's generous introduction and presentation of the award, I of course thanked Dana Bredemeyer for his contribution to the work I was being recognized for, as well as what I was about to present. Anything "Visual Architecting" is very much a "standing on the shoulders of giants" endeavor, and not just Dana's, but every architect (of any title) we have ever worked with.

By way of an outline of the talk, I told the audience the sketch (above) was a fairly accurate visualization of my talk -- I would iterate on, and elaborate, build out, our notion of software architecture. And I wouldn't be complete, in that self-set mission, in a timebox (of 30 minutes, or even, if my 20+ years in software architecture is anything to go by, a lifetime).

Beck

If we go back to 1992, we already see one of the narrative threads that have shaped our conceptualization of, and discourse around, software architecture, architects, and architecting:

“Mr. Beck, what is software architecture?”

“Software architecture?” replied Kent, “well, it is what software architects do.”

“So then, what is an architect?”

“Hum, ‘software architect’ it’s a new pompous title that programmers demand to have on their business cards to justify their sumptuous emoluments.”

[source: What do software architects do? Philippe Kruchten]

Fowler

A (little over a) decade later, in 2003, we have Martin Fowler (in "Who needs an architect?") similarly perplexed, and quoting Ralph Johnson:

“Tell us what is important.” Architecture is about the important stuff. Whatever that is.

Architecture is decisions

Let's sidestep the discomfort we have with someone (else?) doing "the important stuff" and getting "sumptuous emoluments," for a moment anyway, and follow the arc of software architecture to its recurrent destination, namely Grady Booch and

"Architecture represents the significant design decisions that shape a system."

Decisions!

Decisions! We haz template

Decisions?

Michael Nygard's post on Documenting Architecture Decisions presents a useful template. It has echoes of the patterns template used by the Gang of Four, and subsequent, in that it draws attention to the essential elements of Context (presenting forces and demands) and Consequences, not just the Decision itself.

It's a template I and others recommend (though I like to add Alternatives Considered). Still, too much of a good thing sinks itself under its own weight, so an Architecture Decision Record leaves itself begging the question -- which decisions?

Which decisions though

Which decisions?

Architecturally significant decisions! Which are architecturally significant? The architect decides!

Architecture is significant decisions

On what basis? Returning to Grady Booch: "significant is measured by cost of change"

If you think good architecture is expensive, try bad architecture

"Bad architecture is expensive" -- paraphrasing Brian Foote, coauthor of the must-read classic "Big Ball of Mud"

Big ball of mude architecture

The opening sentence to that paper observes that the de-facto standard in software architecture is <drum roll> "the big ball of mud" <badum tish>

[Aside: Joe was in the SATURN audience, having presented earlier, so that was cool.]

Big ball of mud

When you have a "big ball of mud," as Michael Stahl vividly put it "you reach for the banana, and get the entire gorilla."

Now that sketch is an idealization...

tangled

in "real life," the degree of entanglement is more like this... [above]

[Image: from Undoing the harm of layers by Bjørn Bjartnes]

Modularity

By contrast, a modular structure reduces cost of change by (and to the extent that it achieves) isolating change, shielding the rest of the system from cascading change.

In a modular approach, parts of the system that are unstable, due to uncertainty and experimentation to resolve that uncertainty, can be shielded from other, better understood and more stable parts of the system.

Parts can be plugged in, but removed if they don't work out, making for reversibility of decisions that don't pan out. They can be replaced with new or alternative parts, with minimal effect on other parts of the system, enabling responsiveness to emerging requirements or adaptation to different contexts.

Further, it's a mechanism to cope with, and hence harness, complexity. Partitioning the system, reduces how much complexity must be dealt with at once, allowing focus within the parts with reduced demand to attend (within the part) to complexity elsewhere in the system. We give a powerful programmatic affordance a handle with minimal understanding to invoke it, and can selectively ignore (not all the time, but for a time), or may never even need to know (it depends), its internals.

Fowler concedes

So modularity and parts, or components, is key to managing change and associated costs. Returning to Martin Fowler's paper, indeed software architecture is acknowledged to include how the system is divided into components, and how they interact.

 

Perry and Wolf definition of sw architecture

Going back to 1992, when Kent Beck was giving the architecture-architects thing a ¯\_(ツ)_/¯, Perry and Wolf were defining (software) architecture as being concerned with "the selection of architectural elements, their interactions, and the constraints on those elements and their interactions."

[Hopefully those who are excited about Alicia Juarrero's work on constraints (1999), are tingly at the foreshadowing in Perry and Wolf's characterization (1992).]

software architecture is elements and relations

And, indeed, the contemporary go-to reference definition for software architecture (that being the definition in wikipedia which, in this case, derives from that of the Clements et al team from the SEI, which dates back to the mid-90's), is in terms of the high level structures of the system, where those structures comprise software elements and the relations between them.

 

Everything's already been said, but no-one was listening

We're holding these two ideas about architecture in creative suspension -- architecture is decisions about "the important stuff" where important is distinguished by cost of change, and architecture is about the structure of the system, which has something to do with (lowering) the cost of change.

Now we're going to take another pass at our conception of architecture (where how we conceive of architecture is being used in its double sense), and this quote (above) is my permission slip.

Architecture is design

Architecture is design. Not all design, but importantly, architecture is design.

Herbert Simon: We're doing design when

What is design? In The Sciences of the Artificial," Herbert Simon ("ground zero in design discourse" -- Jabe Bloom) notes "Everyone designs who devises courses of action aimed at changing existing situations into preferred ones." This characterization is profound, for all its straightforward simplicity.

We design to get more what we want

Design is what we do, when we want to get more of what we want than we'd get by "just doing it."

How do we design better boxes?

Now, if architecture is design, and architecture is, or at least includes, the shaping structure, the elements and relations -- the boxes and lines -- and design is about creating a better structure, how do we do that?

The tale of the dextrous butcher

As one does, in contemplating life's profound questions, we might turn to the Tao. And in this case, the story of the dextrous butcher. In one translation, the master cook tells us:

“It goes according to natural laws, Striking apart large gaps, Moving toward large openings, Following its natural structure.

“A good cook goes through a knife in a year, Because he cuts. An average cook goes through a knife in a month, Because he hacks.

“I have used this knife for nineteen years. It has butchered thousands of oxen, But the blade is still like it’s newly sharpened.

“The joints have openings, And the knife’s blade has no thickness. Apply this lack of thickness into the openings, And the moving blade swishes through, With room to spare!

“That’s why after nineteen years, The blade is still like it’s newly sharpened.

“Nevertheless, every time I come across joints, I see its tricky parts, I pay attention and use caution, My vision concentrates, My movement slows down.”

Where natural features like rivers and mountains oblige, states have boundaries along them, but software doesn't have natural topology. Or does it?

Design things to be insensitive to outside

The system boundary is an obvious candidate. In the founding classic of system architecture, Eberhardt Rechtin presents heuristics gleaned from his amazing career as a system architect in aerospace, and master teacher of system architects in the seminal program he created at USC. One of these heuristics (is a "turtles all the way down" sort of thing, but applies also at the system level):

"Design things to make their performance as insensitive to the unknown or uncontrollable external influence as practical."

That, for me anyway, has echoes of fort design and Ambrose Bierce' Devil's Dictionary definition of abatis:

"rubbish in front of a fort, to prevent the rubbish outside from molesting the rubbish inside"

Hexagonal architecture

Which visually, and in intent, has echoes of Alistair Cockburn's hexagonal architecture (pattern). Here, adapters at the system boundary, shield the (core) application (code) from interactions with the outside, keeping business logic uncontaminated by the peculiarities of external agents or systems and their states, interactions and interaction paradigms, and keeping business logic from leaching into user, or other system, interface code. Moreover, ports and adapters are a first mechanism of address for cost of change, partitioning the system boundary into plug-and-play access points.

Abstractions

But what about the boundaries within the boundary? These abstractions we use to give our system internal form, must, as Michael Feathers points out, be invented. They are conceits. In every sense of the word, perhaps. At least, when asked about the granularity of microservices, I point to the WELC master going "about so big." Obviously a joke, the joke being on us, the right answer of course being "the right size, and no bigger." Which is not an answer, but where can we look, for a better answer?

Bounded contexts

One place to go, in looking for the natural topology, to find the natural shape to follow in creating internal system boundaries, is the "problem" domain -- that is, the domain(s) being served by the system(s) we're evolve-building. And indeed, we're broadly using bounded contexts in Domain-Driven Design to suggest microservice boundaries. And when we get to the tricky parts, like "customer" or "product" that have potentially overlapping, yet different, meanings in different domains, we slow down, and move more carefully. A customer, after all, experiences themselves to be one person through all touchpoints with "the system," and doesn't want to feel like the system cleaved them brutalistically. So we separate domains, but the architect is noting this point of articulation, this tricky part, where we have to move more carefully.

Components and responsibilities

Another place to go is back to 1989 and Ward Cunningham and Kent Beck's CRC cards, but repurposed for components. We work with components and responsibilities in both directions -- start with a first cut notion of components the system will need, and identify and allocate responsibilities to them; or start with responsibilities evident from what the system needs to do, and factor to find components. Continue to update the responsibilities for each component, as more is learned as the system is explored and built out.

Factor and Refactor

These lists of responsibilities are a powerful and largely overlooked/underused tool in the architect's toolbelt. If the responsibilities don't cohere within an overarching responsibility, or purpose, that should trip the architect's boundary bleed detectors. We may need to refactor responsibilities, and discover new components in the process. We think that "naming things" is the big problem of software development, but "places to put things" is the proximate corollary.

Jan van Til paraphrased a Tom Graves point into a neat contragram:

"The responsibility of architecture is the architecture of responsibility."

We forgive a line for what it doesn't capture, when it does capture so much of the very essence of a thing!

the architect's SCARS

Grady Booch notes that, for all that changes, there are "fundamentals that remain fundamental." I took the liberty of rearranging Grady's fundamentals (identified in his keynote at SATURN 2016 and elsewhere), to create a mnemonic handle: SCARS*. You know, what we get from experience.

Separation of concerns plays a role widely and variously -- we've already talked about separating interactions at the system boundary from the application core, looking to bounded contexts (domains of concern) to suggest abstractions, and separating responsibilities to create crisp and resilient abstractions.

Resilience can be tested by doing thought experiments with anticipated changes -- assessing the impact against the responsibilities of current components, to see how well we're doing in isolating change. And as the system evolves, we can visualize and track changes to see how well our abstractions hold up.

Having identified component responsibilities comes in handy in assessing balance as well as cohesion. It is readily evident if we're conceiving of a "god" component, or even demigods, with aspirations.

As the story goes, to Thoreau's "simplify, simplify," Ralph Waldo Emerson retorted "One "simplify" would have sufficed." Which nicely indicates a key strategy for simplifying -- do less.

Disorder is the most likely thing

Returning to Dijkstra: "we know we have to keep it crisp, disentangled, and simple if we refuse to be crushed by the complexities of our own making."

Having (named!) places to put things, is a nice idea. But code is a matter of mind -- many minds even. Entropy is hard to work against, especially when the effects are hard to notice (until it is hard not to notice).

 

Conway's Law

Conway's Law asserts that the structure of the organization, and the communication paths it facilitates and inhibits, are powerful, even determining, shapers of the system. I paraphrase it thusly: "if the architecture of the system and the architecture of the organization are at odds, the architecture of the organization wins." Recognizing that's a law, like gravity, then, we can play along with it, and use team boundaries to maintain component or microservice boundaries, by lining them up.

But. There is a but. We do have to remain vigilant, lest we get played by the very law we're using to game entropy. The forces we're using to protect and reinforce boundaries, increase inertial forces at the boundary -- it's harder to see when change is needed, and harder to change.

Moreover, given what the communication paths foster and inhibit, we're going to have to put in explicit work, to ensure that we don't get scope creep within the component (microservice, etc.), and to manage duplication (with concomitant inconsistency) across components.

Short-cuts within teams to avoid co-ordination overhead between teams (trying to create sync points in schedules, negotiate differing priorities, etc.), become erosion of cohesion and accommodations within components. Slippery slope to a growing constellation of balls of mud, unless work is put in, not just to maintain order, but to create new order as context and understanding shifts and evolves, and raises new needs, challenges and forces that must be addressed within the system -- the organization and the code.

We need to talk about systems

So far we've been talking about boundaries, and designing crisp and resilient abstractions and keeping them that way. But if we swing by Grady Booch's characterization of software architecture once more, we might notice that while system hasn't been absent in what we've covered so far, it also hasn't been the focus.

Russ Ackoff on systems

Russell Ackoff is one of the pioneers of systems thinking and design. In 1974 he was writing papers with titles like "Systems, Messes, and Interactive Planning" -- how very 2017!

In this roughly 10 minute (starting at 1:12) talk, Russ Ackoff covers and illustrates the key characteristics of systems. Notably,

a system has properties that none of its parts have, on their own. "You can write. Your hand can't write. To see this, imagine your hand is cut off; can it write?" [narrator: gruesome image, but it makes the point]

when we take a system, decompose it into its parts, optimize the parts, and put them back together, we don't even necessarily get a working system. To see this, imagine you have the best automotive engineers in the world pick the best carburettor, the best fuel pump, distributor, and so on. Now ask them to assemble those best parts into a car. Most likely they can't because the parts don't fit, but even if they do, in all likelihood it doesn't work very well.

Parts flying in formation, trying to be an airplane

Returning to Eb Rechtin:

"The only thing added to the parts to make the whole greater than the sum of its parts is the interrelationships among them."

Without interrelationships, we have, as Wim Roelandts put it (back when we were working at HP): "parts flying in formation, trying to be an airplane."

Obvious? Surely. Yet we need to act on this understanding. It is not enough to decompose a system into components or microservices or whatever the chunking du jour, minimizing interdependence, and proceed as if coherent systems will gracefully emerge from independent "two pizza" teams.

Minimalist architecture

So we arrive at another characterization of architecture, one that we owe to Dana Bredemeyer: architecture decisions are those that must be made from a system perspective to achieve system outcomes (capabilities and properties of the system).

A minimalist architecture uses this heuristic to filter for significance. If a decision can be made at local scope (within a microservice, say) without negatively impacting system outcomes, it is made there. Architecture decisions, on the other hand, are those that need to be made across boundaries (the system boundary, or across boundaries within the system), in order to get more the system properties we want, and to build desired system capabilities. They are decisions that enable us to build more than just an aggregation of parts.

We're addressing fit among the parts, and their interaction, to yield a coherent system. And addressing, as we do that, the complexity we've moved to interactions, when we shield and focus attention within the parts, to increase organizational and cognitive tractability.

Structure and behavior

The system takes a different kind of attention: we're reasoning about the interaction among architectural elements to yield capabilities (and related value to stakeholders) with desired properties (impacting user-, operations-, and developer-experience, and impacting system integrity and sustainability), addressing the inherent challenges and tradeoffs that arise as we do so.

Which means that we're exploring behavior, to direct discovery as we're exploring how to build the system, not just its parts. But this impacts how we conceive of and design the parts.

Ask questions

So we're positing structure, and asking "what is this system made of?," but also -- and soon -- exploring behavior, asking "how will this work?" and "how does this approach contribute to or inhibit the desired system properties and yield needed system behaviors?"

Remember to update responsibilities

As we do this, we're going to learn more about the responsibilities of the components or architectural elements. And we need to be disciplined about updating the responsibilities and refactoring components/responsibilities to try out alternative structurings, or to improve the current one.

Visual models are sketch prototypes, they are ways to test ideas cheaply

Design of complex systems is hard -- wickedly hard! And wicked problems take all the cognitive assist we can muster. Tradeoffs must be made because there is interaction -- not just interaction among components to create a capability, but interaction among properties.

We draw diagrams or model (some aspect of the system) to think, alone, and to create a shared thoughtspace where we can think together (and across time) about the form and shape and flow of things, considering how-it-works both before we have code and when the very muchness of the code obfuscates and it is all too much to hold in our head, yet we need to think, explore, reason about interactions, cross-cutting concerns, how things work together, and such. [That long sentence reifies how soon too much becomes cognitively intractable.]

Models help us test our ideas -- in an exploratory way when they are just sketches, and thought experiments, where we "animate" the models in mind and in conversation. Drawing views of our system, helps us notice the relationships between structure and function, to reason about relationships that give rise to and boost or damp properties. We pan across views, or out to wider frames, taking in more of the system and what it does where and how and why (again, because we must make tradeoffs we need to weigh value/import and risk/consequences and side effects).

We sketch-prototype alternatives to try them out in the cheapest medium that fits what we're trying to understand and improve. We seek to probe, to learn, to verify the efficacy of the abstractions we're considering, under multiple simultaneous demands. We evolve the design. We factor and refactor; we reify and elaborate. We test and evolve. We make trade-offs and judgment calls. We bring what we can to bear, to best enable our judgment, given the concerns we're dealing with.

Software is a highly cognitive substance with which to build systems on which people and organizations depend. So. We design-test our way, with different media and mediums to support, enhance, stress and reveal flaws in our thinking.

Along the way -- early, and more as fits the moment -- we're "model storming" "out loud" "in pairs" or small groups. And all that agile stuff. Just in the cheapest medium for the moment, because we need to explore options quick and dirty. Hack them -- with sketches/models, with mockups, with just-enough prototypes. We use diagrams and models to see what we can't, or what is hard to see and reason about, with (just) code. Enough early. And enough along the way so that we course correct when we need to. So that we anticipate enough. Put in infrastructure in good time. Avoid getting coupled to assumptions that cement the project into expectations that are honed for too narrow a customer need/group. And suchness.

Years ago I saw a cartoon where there's an architecture diagram on a door, and everyone is throwing darts at it, and the caption read "at least they're looking at it." I couldn't find the original, so unfortunately I can't give proper attribution and had to redraw it, or at least the gist I remember.

Self-repairing egos

Architecture decisions entail tradeoffs. We try for "and" type solutions, that give us more of more. More of the outcomes we seek, across multiple outcomes. Still, there are tradeoffs -- "[architecting] strives for fit, balance and compromise among the tensions of client needs and resources, technology, and multiple stakeholder interests" (Rechtin and Maier).

Compromises mean not everyone is getting what they want (for themselves, or the stakeholders they see themselves beholden to serving) to the extent they want. Seeing the options and good ideas to resolve (only) the forces from the perspective of (just) a part, may.... lead to questioning design decisions ("throwing darts", in the terms of the cartoon) made from the perspective of the system. It can be hard to see why anyone would give up a good thing at a local level to benefit another part of the system, or to avoid precluding a future strategic option or direction. Sometimes those questions lead to a better resolution. Sometimes they just mean compromise.

Further, complex systems are, well, complex. Many, many! parts, in motion. In dynamic, and changing, contexts (of use, operations, evolutionary development). So there's uncertainty. And ambiguity. And lots of room for imperfect understanding. And mistakes. Will be made. Wrong turns taken. Reversed. Recovered from. We're fallible. So. More darts. Which is humbling -- more so, if we're not humble enough to stay fleet, to try to learn earlier and respond to what we're learning.

All of which means we need to notice what is hard to notice from inside the tunnel of our own vision -- where what we're paying attention to, shapes what we perceive and pay attention to.

Change in perspective us worth

"A change of perspective is worth 80 IQ points" reminds us to take a different vantage point, to see from a different perspective. Consider the system from different points of view; use the lens of various views. This can play out multiple ways, but includes considering the design (structure, dynamics and implications) from the perspective of security, and from the perspective of responsiveness to load spikes, etc.

Another way to get a change of perspective, is to get another person's perspective. Invite peers working on other systems, say, to share what's been learned and seek out opportunities and weaknesses, things we missed. Our team can miss the gorilla, so to speak, when our attention is focused on the design issues of the moment. Fresh perspective, and even just naive questions about what the design means, can nudge an assumption or weakness into view. And merely telling the story, unfolding the narative arc of the architecture to fit this person or audience, then that, gets us to adopt more their point of reference, across more perspectives -- in anticipation, and when we listen, really listen, to their response and questions.

More than one way

Relatedly, Minsky is further pushing us to the discipline of not just accepting our initial understanding, but rather seeking different understandings. These are the significant design decisions, decisions about the important stuff, after all.

"If you 'understand' something in only one way then you scarcely understand it at all. For then, if anything should go wrong, you'll have no other place to go. But if you represent something in multiple ways, then when one of them fails you can switch to another—until you find one that works for you." -- Marvin Minsky

We can understand the system as code, and building up mental models of the structure and "how it works." And we can understand the system (as we envision it, and as we build-evolve it) through sketches or visual models with reasoned arguments, explaining, exploring and defending the design. And we can understand the system through visualization of the system behavior, or through simulation or instrumentation (of prototypes, earlier, and the system in production, soon and then later, as the system is evolved). We can understand the system as perceived by someone new to the system, and as someone comfortable with the mental models we've imbued it with. We can understand the system directly and through the lens of an analogy (or hybrid blend of analogies). Understand it as loss and as gain. As a system we break down into parts, and as a system, or whole.

Weinberg's Rule of Three

Part II.

strucutre and behavior and views

Design across

iterate

 

 

8/16/18

Here's a draft of a post I'm working on, covering heuristics. There's overlap with the above, but as it gets banged into shape, some of the overlap will reduce ... at least, ... there will be proportionately less, because more will be added; I need to decide if the overlap is okay, given the destination it's headed to.

Clue Bucket

Architecture Clues: Heuristics Part i. SCARS

"Design of complex systems is hard -- wickedly hard! It takes all the cognitive assist we can muster." That's how I began my last post, and it focused on modeling. Still, wickedly hard -- what else to do? Sometimes we're stuck and want a clue to get unstuck. Other times we want clues that prompt or guide, or just give reassurance. Here, we will explore a particular kind of clue, namely (architecture) heuristics.

We develop, through direct and indirect experience, "a considerable body of contextual sense" -- that is, "a knowledge of what is reasonable within a given context" (Rechtin, 1991). Engineering heuristics, or rules of thumb, are "statements of common, or contextual, sense that aid in concept development, problem solving, decision making, or judgment"(Rechtin, 1991). They can be descriptive (what is the situation) or prescriptive (what to do about it) (Rechtin, 1991).

"Heuristics offer plausible approaches to solving problems, not infallible ones."—Rebecca Wirfs-Brock

Perry and Wolf defined software architecture as being concerned with "the selection of architectural elements, their interactions, and the constraints on those elements and their interactions" (1992). Some of our contemporary characterizations of software architecture focus on architecture decisions, but design of the organizing structure is still a defining aspect. So, let us dig in on heuristics that have to do with designing the organizing structure and, in particular at this point, key elements or abstractions.

SCARS: heuristics for designing system structure

In talks on software architecture, Grady Booch points [minute 43+] to what he characterizes as "the fundamentals that remain fundamental":

  • clear Separation of Concerns
  • crisp and resilient Abstractions
  • balanced Responsibilities
  • Simplicity

which I resequenced as shown above, to give us the mnemonic, SCARS* (see The Architect's Clue Bucket, slide 16). Which is appropriate, since SCARS are what we get from experience. As Grady Booch put it, we stand on the shoulders and ashes of those that go before, and I take that to include our own, and others', successes and failures, along with the usual building on the knowledge developed by giants in our and other fields.

SCars: Separation of Concerns

Taking the first of those (Separation of Concerns), and to illustrate surfacing and illuminating heuristics, here's a story from the Tao. It is the story of the dextrous butcher. In one translation, the master cook tells us: 

“It goes according to natural laws, Striking apart large gaps, Moving toward large openings, Following its natural structure.
A good cook goes through a knife in a year, Because he cuts. An average cook goes through a knife in a month, Because he hacks.
I have used this knife for nineteen years. It has butchered thousands of oxen, But the blade is still like it’s newly sharpened.
The joints have openings, And the knife’s blade has no thickness. Apply this lack of thickness into the openings, And the moving blade swishes through, With room to spare!
That’s why after nineteen years, The blade is still like it’s newly sharpened.
Nevertheless, every time I come across joints, I see its tricky parts, I pay attention and use caution, My vision concentrates, My movement slows down.”

What do we extract, that helps guide us in architecting? Two heuristics jump out:

  • follow the natural structure
  • when we come to the tricky parts, slow down

This story is used as a teaching story in many and diverse situations. And yet here it is, yielding heuristics for architecting, which is, after all, at least in part about decomposing, in order to compose a coherent system. What is useful to notice here, is that once drawn out, these heuristics may seem obvious -- just common sense! But until they're drawn out, we may not have formed, or be applying, these rules of thumb -- they are not quite so common as we might hope. Or we might challenge the heuristic with: what, in so conceptual a matter as a system formed of thought, written as code, is "natural structure"?

So glad you asked! The system boundary is an obvious candidate: separate interactions at the boundary from the core of the system.

Rebecca Wirfs-Brock has argued that patterns are organized collections of heuristics -- cue Alistair Cockburn's hexagonal architecture pattern. Here, adapters at the system boundary, shield the (core) application (code) from interactions with the outside, keeping business logic uncontaminated by the peculiarities of external agents or systems and their states, interactions and interaction paradigms, and keeping business logic from leaching into user, or other system, interface code. Moreover, ports and adapters are a first mechanism of address for cost of change, partitioning the system boundary into plug-and-play access points.

It's not just a separation of concerns, but an allocation of responsibility. Returning to Rechtin, one of the heuristics he identified in Systems Architecting is:

"Design things to make their performance as insensitive to the unknown or uncontrollable external influence as practical."

Relatedly, Postel’s Law (also called The Robustness Principle) states:

"be conservative in what you do, be liberal in what you accept from others"

I nickname it the "play well with others" principle. At any rate, concerns at the boundary encompass responsibilities to not just plug and play, but to play well. We will return to resilience and robustness at a later point (future post).

But what about the boundaries within the system boundary? These abstractions we use to give our system internal form, must be invented. They are conceits. In every sense of the word, perhaps. 

One place to go, in looking for the natural topology, to find the natural shape to follow in creating internal system boundaries, is the "problem" domain -- that is, the domain(s) being served by the system(s) we're evolve-building. This brings us to bounded contexts and heuristics and guidance in Domain-Driven Design to suggest system and component or microservice boundaries. And to business capabilities in Enterprise Architecture/Business Architecture approaches, that seek to understand the topology, the shape and relatedness, of business capabilities.

Another place to go is back to 1989 and Ward Cunningham and Kent Beck's CRC cards, but repurposed for components, along with a heuristic that takes the form of a neat antimetabole (thanks to Jan van Til's paraphrase of a Tom Graves point):

"The responsibility of architecture is the architecture of responsibility."

Which points us in the direction of identifying responsibilities related to system capabilities and properties, and the arrangement of responsibilities. Separating responsibilities along the lines of concerns. [This is not the only way we use the term "separation of concerns' in software design, of course.]

scArs: crisp and resilient Abstractions

The dual to separation of concerns is a coalescence or cohesion of concerns?

"Things that are cohesive, [..] naturally stick to each other because they are of like kind, or because they fit so well together.[..] the pieces all seem to be related, they seem to belong together, and it would feel somewhat unnatural (it would result in tight coupling!) to pull them apart"—Glenn Vanderburg

That is, not only are we looking for what to pull apart, but what to keep together to form crisp and resilient abstractions.

We use abstraction in different ways -- levels of abstraction, abstractions as elements of code we work with, the activity of abstracting. J. Edsger Dijkstra (The Humble Programmer, 1972) noted:

“The purpose of abstracting is not to be vague, but to create a new semantic level in which one can be absolutely precise.”

Here, we're talking about heuristics for identifying architectural elements (or components, or microservices if those are the architectural elements of the system in question). A crisp abstraction has a clear, unifying purpose or cohesive identity; it has, in effect,

a single responsibility at the level of abstraction of the abstraction.

That is, there is high cohesion among its sub-responsibilities, and all contribute to the element's distinguishing purpose, or single responsibility. A single, if you like, defining job-to-be-done.

This suggests a focus on responsibilities as an avenue to system (de)composition. We identify responsibilities and assign to them components, working in either (and both!) direction: start with a first cut notion of components the system will need, and identify and allocate responsibilities to them; or start with responsibilities evident from what the system needs to do, and factor to find components. A related heuristic takes the form:

"To find the right abstraction, guess. If it exhibits the right properties, stop."Jessica Kerr

We take a guess as a starting point, and improve on it: Run thought experiments (use cases or user stories; focus on one property, then another, etc.) to flush out responsibilities we overlooked in our initial guess. Change perspective, and review the responsibilities and abstractions in the view of, for example, thinking through allocation to the physical system topology, or a system change.. Be disciplined in seeking alternatives -- for example, by emphasizing a different requirement. Do this quickly and cheaply, to get a good enough starting point to build the next increment of code, and iterate on the design. Update the responsibilities lists as we do so.

These lists of responsibilities are a powerful and largely overlooked/underused tool in the architect's toolbelt. If the responsibilities don't cohere within an overarching responsibility, or purpose, that should trip the architect's boundary bleed detectors. We may need to refactor responsibilities, and discover new components in the process. We think that "naming things" is the big problem of software development, but "places to put things" is the proximate corollary.

Be deliberate and deliberate all the things” — Dawn Ahukanna

Heuristics don't take away the need to think, to reason and try things out. They help us identify what to think about, as we do so, and may suggest how to go about it (better). In another of the foundational classics of our field, David Parnas (On the Criteria To Be Used in Decomposing Systems into Modules, 1972) proposes:

"that one begins with a list of difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from the others."

That's two heuristics, and thanks to Robert Martin, the second has primary place in the SOLID set of principles that are a touch of software design, and object-oriented design in particular:

Single Responsibility Principle (SRP): a class should have one and only one reason to change

Stuart Brand, writing about pace or shearing layers in building architecture in How Buildings Learn, observed that different parts of a structure change at different rates (with the building site, and then the structure, being least likely to change, given the cost and difficulty of doing so; and the stuff inside being the most likely to change). This observation gives rise to the heuristic:

keep things that change together, together

Thus, one thing we're seeking to do with a modular structure and crisp abstractions, is to isolate change, shielding, as best we can, the rest of the system from cascading change. We can check how we're doing against the heuristic, by running anticipated changes across the architecture, informally mapping a new use case on the architecture, to see if responsibilities that are missing illuminate a different clustering/factoring an resulting abstractions. We're not trying to build antipactory capabilities we're not sure we'll need. We're simply stress testing the resilience of our abstractions, to see if we've missed a more resilient basis for separating and coalescing responsibilities.

Let's return to Parnas; the other heuristic in his criteria for decomposing (already quoted above) is:

"[begin] with a list of difficult design decisions [..] Each module is then designed to hide such a decision from the others."

As an aside, we also recommend identifying key architectural challenges when we're determining architectural strategy, to think about principles we might craft to help shape our approach to the challenge. And this approach is again useful, when identifying abstractions, or (re)assessing already identified abstractions for goodness.

In a modular approach, parts of the system that are unstable, due to uncertainty and experimentation to resolve that uncertainty, can be shielded from other, better understood and more stable parts of the system. 

Uncertainty is not a license to guess. It is a directive to decouple." — Sandi Metz

Parts can be plugged in, but removed if they don't work out, making for reversibility of decisions that don't pan out. They can be replaced with new or alternative parts, with minimal effect on other parts of the system, enabling responsiveness to emerging requirements or adaptation to different contexts. 

Further, it's a mechanism to cope with, and hence harness, complexity. Partitioning the system, reduces how much complexity must be dealt with at once, allowing focus within the parts with reduced demand to attend (within the part) to complexity elsewhere in the system. We give a powerful programmatic affordance a handle with minimal understanding to invoke it, and can selectively ignore (not all the time, but for a time), or may never even need to know (it depends), its internals.

“There was a wall. It did not look important. It was built of uncut rocks roughly mortared. An adult could look right over it, and even a child could climb it. Where it crossed the roadway, instead of having a gate it degenerated into mere geometry, a line, an idea of boundary. But the idea was real. It was important. For seven generations there had been nothing in the world more important than that wall.
Like all walls it was ambiguous, two-faced. What was inside it and what was outside it depended upon which side of it you were on.”

Ursula K. Le Guin 

“Encapsulation is important, but the reason why it is important is more important. Encapsulation helps us reason about our code.” - Michael Feathers

Resilience to change (caveats apply) is just one dimension to resilience in "crisp and resilient abstractions." Again, more to consider under the topic of resilience. For now:

"All non-trivial abstractions, to some degree, are leaky."—Joel Spolsky

 

scaRs: balanced Responsibilities

What is often the case with something we might call common sense -- even if we mean the contextual sense variety -- is that it looks obvious once noted. And yet it time and again that a system design ends up with a component that has a high center of gravity or something, and attracts way more responsibility than other components (common enough it goes by a name, "god class"). "A single responsibility at the level of abstraction of the abstraction" is a judgment call (or set of judgment calls). One way to check our judgment is the apply the heuristic: consider the distribution of responsibilities for balance.

scarS: Simplicity

The last of the fundamentals organized by the SCARS mnemonic, reminds us to strive to simplify. In response to H.D. Thoreau's "simplify, simplify," Ralph Waldo Emerson reportedly retorted 'One "simplify" would have sufficed.' Eb Rechtin, on the other hand, offers us the heuristic:

"Simplify, simplify, simplify."

Another heuristic (Rechtin, 1991) might illuminate:

"Communicate, communicate, communicate."

That is, we need to simplify, and simplify again, and again, maintaining a discipline of repeatedly simplifying. And we need to communicate the need, and underscore the need, to simplify. Complexity is something we both embrace (we want more than hammers in our toolsets) and eschew (complexity costs -- attention, errors, ..., resources), so we need to harness complexity and reduce accidental, gratuitous, and unnecessary complexity.

"An evolving system increases its complexity unless work is done to reduce it." — Meir Lehman

There's considerable discipline in applying Occam's Razor (also Ockham's razor or Ocham's razor; Latin: lex parsimoniae "law of parsimony"):

Occam's razor is the problem-solving principle that the simplest solution tends to be the right one.

That is, given a solution, it takes discipline and discernment to look for a simple(r) solution. The following Twitter exchange draws a smile, and a nod of recognition:

Chad Fowler: The older I get, the more I realize the biggest problem to solve in tech is to get people to stop making things harder than they have to be.
Michael Feathers: It's not that easy.

Following the spirit of Bill Venner's conversation with Ward Cunningham on "do the simplest thing that could possibly work," we form the heuristic: "do the simplest thing that is good enough."

We're looking to simplify our system design, and if we only consider the system internals, the obvious can be hidden in plain sight -- the simplest way to reduce complexity, is to not add to it:

'focusing is saying "No"' — Steve Jobs

"A primary cause of complexity is that software vendors uncritically adopt almost any feature that users want."- Niklaus Wirth

Or to remove complexity that is no longer servicable:

"old code doesn't die; you have to kill it" — Grady Booch

Of course, to again quote the WELC guy, it's not that easy. One approach is what Martin Fowler calls the StranglerApplication Pattern:

"gradually create a new system around the edges of the old, letting it grow slowly over several years until the old system is strangled"

SCARS, Systems and What's Next

Here we have explored a set of heuristics that are centered around the organizing structure of the system, and in particular identifying "crisp and resilient abstractions." We invite you to add to the set above (and share via twitter, if you like), but also to share other heuristics you find useful in architecting. Part ii will widen the focus to systems, to relations and interactions, to tradeoffs and compromises, etc., and more essence of systems. From there, we widen the scope still further, to systems in context, and more broadly to the various ecosystems the system of interest plays a role in, serves, and relies upon.

And, at some point, we hope to broaden our focus to draw in other kinds of design clues -- analogies, principles and laws, checklists, (more) patterns, etc. I like the more general "clues," because I don't have to think about how to classify

"what, at this extraordinary moment, is the most important thing for me to be thinking about" — Bucky Fuller (via Dana Bredemeyer; this might be a paraphrase)

."The art of being wise is the art of knowing what to overlook." —William James

* I know, I broke the rule that every letter has to be an element, and could make the C or the second S stand for something else, but I wanted to stay true to the source (@Grady_Booch's four "fundamentals that remain fundamental") and just give them a catchy handle :-)

8/16/18

Workshops

Up coming open enrollment Software Architecture Workshops:

- September 17-20, 2018, Rotterdam, The Netherlands. Full, but you can request to be added to the wait list.

- November 12-15, 2018, Chicago/Schaumburg, IL, USA. Early enrollment discount ends soon.

 

Talks

Dana Bredemeyer will give a talk at Luminis in Rotterdam, The Netherlands, on September 18 (event starts at 5:30pm), titled: The Architect’s Clue Bucket. This talk covers a number of design principles, heuristics, tips, guidelines, etc. — clues we can use in architectural design — and places them in the context of architecture work, motivating them by outlining the kinds of challenges the architect addresses. It ends with some suggestions on building up a personal set of design heuristics. Free, but reserve a place.

 

2/16/18

Gratitude: Mentioning my Visual Architecting Keynote Notes

Thanks to Eugene Barker's positive mention, and retweets from the likes of Grady Booch, Brenda Michelson, Amitai Schleier, Romeu Moura, Oliver Baier, Julie Hunt and Vish Persaud, my notes on my Visual Architecting Keynote at SATURN 2017 got an initial buzz of encouraging likes and further retweets. That was followed by "fist bump" mentions from noted reflective practitioners and prominent influencers Jessica Kerr and Jez Humble, which even prompted a read and reply from Alistair Cockburn. So. Pretty cool. Thanks to everyone who helped to advocate or bring attention to this work, through retweets. The mentions are especially meaningful, because they share space in the attention stream with me in a way that is rare in my experience -- so again thank you to Eugene, Jessica and Jez. Thank you also to those who mentioned it in its current form on the Bredemeyer site: Alfonso Adriasola‏, Alexandre Aquiles and Fernando Paris.

Gratitude: Getting Word Out about my Software Architecture Workshop

Thanks to Brenda Michelson, Dana Bredemeyer, Diana Montallion and Amitai Schleier for mentioning my upcoming Software Architecture Workshop, giving it positive exposure to their followers in their own words. Thanks also to those who retweeted my playful mentions (including Cat Swetel and Michael Hill, Coleen Eibling, Tom Graves, Julie Hunt, Grady Booch, Mathias Verraes, Colin Quirke, Richard West, and others) and bearing with my repetition. Gals gotta make a living, and all. I won an award because a number of people from companies around the world wrote about the impact that my/our work in software architecture has had on them and their businesses, and our field. After thousands of archtiects have taken our workshops over the past 20 years, it sucks that it is this hard to get a workshop to critical mass. But aside from being a woman "with considerable experience" (i.e., <cough> not a Millenial), it is also a field that is repeatedly questioned -- even though we have to keep living through the ill-consequences of bad design and design decay.

A huge thank you to those who expressed feedback on the workshop publically:

"It is! most people that join still remember and apply 10+ year later what they learned!" -- Dirk-Jan Swagerman

"We always look forward to Dana coming to Johannesburg, South Africa. The training has been very beneficial to the teams over the last several years at @StandardBankZA" -- Deven Gengan

"great workshop, check it out!" -- Carlo Kuip

Thank you!

Anyone making architecturally — structurally and strategically — significant system design decisions, is architecting! Hope they know what they’re doing! -- 2/12/18

Gratitude: Exposure for "Software Architects: Do We Need 'em" Post

I had to jump up and down and wave my arms without decorum, so to speak, but my first real essay on LinkedIn (taken from a trace and brushed up for wider consumption) ended up with a number of positive comments, quite a good showing on reshares (27), likes (122) and views (1816) as of today (2/20/18). Thanks in particular to Carlo Kuip for encouraging and useful suggestions, and to those who retweeted it, and replied or mentioned it positively (this mention from Andra Sonea shows how to signal boost -- thanks Andra)) on Twitter, giving it the initial boost it needed, to get it some momentum on LinkedIn. I really need to give LinkedIn more attention -- it seems like maybe it's more of a hangout for architects than twitter??? Perhaps the format (more characters) is needed, to have more nuanced interactions on a domain whose relevance and contribution is perpetually ... questioned....??

In case I Neglected to Thank *You*

If I forgot to thank you, it may be that I missed a tweet/mention (I don't get many, but some days my notifications are more busy because I'm caught in a reply stream -- obviously fine, but just so you know I don't intend to be rude!). Anyway, let me know, so I can correct my gratitude lists above!

Follow Recommend

Lastly, I hope you consider following everyone listed above -- it's ample evidence that they are good people, and discerning, clearly! Well, okay, at least it is evidence that they are kind -- you'll give them that much?

And once I...uh... figure out LinkedIn better, I may find that I owe some thanks for support over there too.

 

Keynote Notes, Part II

Getting the notes finished really needs to be my writing focus over the next week or so. So many other things to write!! But. So distracted by a workshop that's still not at critical mass. Is it me? Did I mess up by being human on twitter -- leave the unfriendly confirmed in their low expectations of me? Oh well.

 

 

 

I also write at:

- Trace In the Sand Blog

- Bredemeyer Resources for  Architects

 

Software Architecture Workshop:

- September 17-20, 2018, Rotterdam, The Netherlands.

- November 12-15, 2018, Chicago/Schaumburg, IL, USA

 

 

Journal Archives

- Journal Map

- storylines tubemap by Peter Bakker

 

2018

- Current

 

2017

- December

 

2016

- January
- February
- April
- May
- June


2015

- June
- July
- August
- September
- October
- November
- December

 

2014

- January
- February
- March
- April
- May
- June
- July
- August
- September
- October
- November

 

More Archives

 

 

 

 

 

Architecture astronaut

 

 

 

 


Copyright © 2017 by Ruth Malan
https://www.ruthmalan.com
Page Created: November 3, 2017
Last Modified: August 23, 2018