The structure of a principle

We had a bit of weather recently, and while waiting for electricity to come back on, I found myself flipping through the pages of The Timeless Way of Building by Christopher Alexander. I was re-reading the chapter about the structure of patterns when something clicked. I realized that patterns and well-learned organizational principles are very similar in structure.

Principles are a big thing in today’s organizations. Most want to have them, yet few get to benefit from them. It is fairly easy to list out a bunch of “things we wish to be true”. But how do I make them actually useful to my team? A sound principle is like a pattern in this regard: it helps navigate a tension that is otherwise difficult to grasp. A principle is only an aspiration if it simply points at the desired destination without doing the hard work of capturing the challenges that will make reaching this destination difficult. Put it differently, if a principle doesn’t wrestle with some tension, it’s probably not a principle.

Borrowing from Alexander’s playbook, my guess is that a sound principle will have this structure: it will begin with the context, describing the situation in a way that is resonant to the team. Then, it will point out the forces that are present within this context — these forces are usually in tension with each other. Then, it will provide guidance (Alexander calls it “configuration”) on how to navigate this tension. Another thing that stood out for me was Alexander’s pursuit to get the name of the pattern right. Similarly, the few words that capture the nature of the principle will become the team’s shorthand, the intuitive handle. It’s worth a bit of extra wordsmithing to make that handle fit like a well-built tool in the team’s collective minds. 

To play with this idea, I decided to use a principle from an org I used to lead. We dubbed it “Treat 1P like 3P.” It was a simple phrase, but it seemed to have been useful: it helped resolve conversations about priorities, serving as a planning and strategy tool. Let’s see if I can retcon that principle into the structure above.

We’ll start with framing the broader context.

Our team ships a developer surface to both internal and external customers. We are at the early stage of our journey, where most of our customers are internal, but we expect the ratio to shift toward external customers over time. The internal customers sit right next to us. We know their workflows and tools. We work at the same company. We  can talk easily to them and partner with them as well as coordinate our plans. The external customers work at other companies, and we often have no easy way to communicate with them. At the start, we only have some guesses about what tools and workflows they might use, but we know for sure they will be different from the custom stack of our internal customers.

Next, we point out the forces that operate within this context. There are two: availability bias and technical debt.

Availability bias. Proximity, familiarity, and general alignment of values creates an incentive toward first-party customers. The path of least resistance leads to shaping our developer surface closely to fit the tools and workflows of internal customers.

Technical debt. Knowing that the internal/external ratio will shift over time, we need to be cognizant that overfitting to the needs of internal customers will incur the cost of painful future migration to a more flexible architecture.

Now that the forces are defined and it’s fairly easy to see how they are in tension, let’s provide guidance on how to navigate that tension.

We recognize that the availability bias is a short-term force, and technical debt is a long-term force. We expect that the short-term force will generally prevail in day-to-day decisions, so we lean a bit toward the long-term force. To do so, we treat our internal customers as if they were a kind of an external customer. We avoid embedding any special knowledge of the internal customer-specific stack. We do research on other potential stacks and ensure that our architecture is flexible enough to support them.

Finally, the handle. Within our team, we called internal customers “1P” and external customers “3P,” so “Treat 1P like 3P” ended up working nicely: it was easy to say and remember while conveying the gist of the guidance.

Looking back, this is not how I structured the principle. Instead, it was just a brief paragraph of words beneath the title. But now that I’ve gone through the exercise, I am noticing something interesting: I want to argue with my past self about the context and the nature of the forces that I was seeing back then. This is probably the most powerful part of structuring principles like that: it allows your team to examine the principle, understand how you arrived at it, and help you make it more sound by presenting their own perspectives. 

Stages of customer-centric maturity

While riffing on customer-centric mindsets and the veering toward first-order effects pattern, my colleagues and I came up with this idea of stages of customer-centric maturity. These stages are modeled after the personal development stages, like the ones in adult development theory. The basic premise is that teams typically progress through these stages as they become more experienced in the trade of developer experience, with each new stage building on the insights of the previous one: the include and transcend type of thing, rather than a wholesale replacement of fundamental premises.

At the zeroth stage of customer-centric maturity, we have the teams who come together to build cool developer tools and other kinds of products. The thought about developers is limited to “if I like it, then others will like it, too” and perhaps some vague notions of “shifting the developer paradigm.” There’s a sense of a rather imperial perspective, with nearly zero investment into understanding customers. These teams tend to build amazing things that nobody needs, though occasionally, they strike gold, perpetuating the “if you build it, they will come” myth.

After accumulating enough scars looking for problems that fit their predetermined solutions, teams tend to graduate to the first stage of customer-centric maturity. The pendulum swings all the way in the other direction. “Make developers happy” is the mantra. Intense focus on developers as customers is at the center of prioritization/investment decisions (aka first-order effects). If the team at this stage is building a UI toolkit, most of the attention will be devoted to ergonomics, faster build cycles, or seamless refactoring. Talking about users who might or might not benefit from developers relying on this UI toolkit is usually met with “well, that’s important, but isn’t it up to developers to do the right thing?” As a result, teams at this stage tend to struggle squeezing diminishing returns out of “faster horses”, unable to break out of the local maxima of developer wishes.

Somewhere around here, the awareness of connection between the first-order effects and the second-order effects may develop, potentially leading the team to the second stage of customer-centric maturity. Teams realize that having satisfied developers isn’t the end goal. Rather, it is the means to improve satisfaction of users: customers who will enjoy (or suffer from) the products made by developers — the second-order effects. Thanks to the constant pull toward the first-order effects (as outlined in the DX pattern), the arrival to this stage may be elusive. However, if the team perseveres, it is rewarded with a much broader perspective that transforms local maximas from inescapable cages to minor bumps along the way.

One of my colleagues had a wise observation that within a large organization that ships developer-facing products, teams might be scattered across the whole spectrum of stages. In such a situation, teams will likely do a lot of talking past each other. For example, if a team operating at the second stage decides that the developer satisfaction metric can dip to accommodate a shift toward better user outcomes, they might encounter strong resistance from the team that’s still at the first stage. To them, such a move will bring back the pain of the scars they earned at the zeroth stage. Perhaps this simple framework could help them understand where their disconnect is coming from?

Framing and solving diverge-converge exercises

There’s this fairly common technique: the diverge-converge exercise. I first heard about it when learning about design thinking, and now recognize it in other places. The gist of it is fairly simple: break down your thinking process into two distinct phases. In the first phase, encourage divergence of ideas to broaden the space of possibilities. In the second phase, study this space to converge on one artifact that best satisfies the intended objective of the exercise.

When working on a decision-making framework, I realized that there are two distinct kinds of this diverge-converge exercise, each with a different goal. I am going to call them “framing” and “solving”. As I implied before, the first one roughly maps into the Complex Cynefin space, and the second one into the Complicated.

The solving diverge-converge exercise is the one that I see described most commonly. Invest a bit of time in the “diverge” phase to generate a rich pool of possible alternatives, then compare them to pick the one that works best in the “converge” phase. A typical engineering doc that’s an outcome of the solving diverge-converge exercise has several alternatives listed with pros and cons, and a discussion followed by a decision to pick one of these alternatives. This kind of diverge-converge exercise is very much about finding the best fit, and it benefits from having a strong fitness function that guides the process of making the pick.

The framing diverge-converge exercise might seem similar, but has an entirely different mindset. Here, the “diverge” phase is meant to collect perspectives that all describe something that’s difficult to see from just one side. When framing, the “converge” phase is no longer about picking the best fit. Instead, it’s the process to see the larger picture, incorporating all perspectives, studying the differences and similarities between them to synthesize a larger perspective. A typical artifact here is a problem statement doc, describing multiple perspectives of the stakeholders and outlining how they relate to — and interact with — each other, along with the outline of the synthesized larger perspective. In the framing diverge-converge exercise, the choices aren’t narrowed down. Instead, they are used to improve the understanding of the space.

When trying to compare the two kinds, the blind men and the elephant parable comes to mind. When applying the solving diverge-converge exercise, the big question will be whether it’s a fan, a snake, a tree, or a wall: we have to pick one. When applying the framing diverge-converge exercise, we might actually see the elephant.

The story of agency

Another kind of story that I’ve encountered in my exploration of coherence narratives is the story of agency. Again, it’s loosely borrowed from the Four Needs Framework and plays a catalytic role similar to that of the story of belonging.

The story of agency is all about going it alone. It’s about striking out on my own, finding our own path, independence, and self-sufficiency. It can also be about perseverance, toughing it out, defending, and standing tall.  The story of agency is deeply woven into American culture, celebrated on July 4, in remembering the Alamo, and oh so many movies with a lone heroic protagonist.

Just like the other catalyst story, the story of agency leans on the structure of another story. Combined with the story of an opportunity, it celebrates uniqueness and breaking with convention as the precious ingredient. Mixed into the story of a threat, it uses the same qualities to draw the bright line between life and death.

Looking at various organizations, I am picking out two distinct patterns. First, the story of agency often plays a role in diminishing coherence. It is the story of break-ups, of abandoning the common goal, of “this is not working out.” Behind every tense conversation, irreconcilable disagreements, and teams deciding not to collaborate lurk stories of agency.

Second, the stories of agency and belonging tend to blend into this curious nested-doll relationship that increases coherence. The story of agency provides the lens to evaluate the external environment, while the story of belonging sets the tone for internal: “we come together to be unique and different from others.” This is also a very common strategy in marketing. Apple’s “Think Different” poster immediately pops to mind when looking for an example of such a nested doll. I buy your product to stand out, while at the same time becoming part of a group.

Through this symbiotic relationship of two stories, organizations and any groups of individuals create boundaries. The story of belonging is what defines the in-group, and the story of agency — the out-group. The story of a threat, catalyzed by the in-group’s story of belonging, is often based on the story of agency: the threat from whom? — the out-group, of course.

For example, a team’s narrative might be about building something truly revolutionary (story of agency + story of opportunity) while persevering in a rapidly shifting, or even hostile conditions (story of a threat + story of belonging). If such a narrative is particularly resonant and crisp, it tends to live for a very long time, sustaining coherence of a group and becoming this group’s identity.

The language frames the story

Suppose you’ve said to me that “the falling maple leaves whirl in a delicate dance with the gentle breeze.” It’s late fall, so it feels like a reasonable thing to say. The trouble is, my language only has words like “eat, fight, run, here, that, there, now, later.” I might be fascinated by what you’ve said, but get very little out of it — and even less to pass on to others. At best, I will point at the sky and say “that!” and bulge my eyes meaningfully.

This might seem like one of those — duh! — obvious observations. Of course the language frames the story. However, I am finding that I easily forget this in the contexts of teams and how they are organized. To communicate with each other, teams establish a common language, a set of semantic shortcuts that allow them to work together effectively. This is where the non-obvious bits hide. This common language also frames what is being communicated.

For example, let’s imagine a hypothetical organization where communicating strategy across teams is done through a list of annual objectives and key results (OKRs). There is a process to assemble them into a coherent whole. When it’s all said and done, the story written in the language of OKRs tells where we will go next year.

However, some of our desired destinations take longer than a year to reach. To communicate these destinations, we need a language that can describe ideas that last longer than a year. Can you guess what happens when we try to express them in the language that only speaks in year-long sentences? Sure, within teams there might be long-term thinking and sound strategic artifacts. However, given the pidgin of annual OKRs that prevails outside, it is unlikely that these artifacts survive cross-team communication. The multi-year ideas will be neatly chopped or scrunched into the one-year box — rendering them as useful as my eye-bulging-while-pointing.

If I am lucky enough to work in an organization full of brilliant individuals, I will also start seeing these folks adapt to the common language. More and more, I will see how they pick out ideas that fit within the language to reduce the friction, making sure that only year-long journeys are those that count, whether in impact or attention of leads. Sure, there will still be the linguistic idealists who rail helplessly trying to overcome the limits of the OKR pidgin, but those will eventually give up and leave.

While the organization wonders why it struggles to think strategically, it might be worth it to examine the language it uses to organize itself. Is the language flexible enough to accommodate both short-term and long-term destinations? Are all ideas that matter expressible in the semantic shorthand that everyone is expected to speak?

The developer funnel

If I ever chatted with you about developer experience in person, I’ve probably drawn the developer funnel for you on the whiteboard. For some reason, I always draw it as a funnel — but any power-law visualization can suffice. As an aside, I do miss the whiteboards. 

At the bottom of the funnel, there are a rare few who know how to speak to computers as directly as humans can. Their perspective on writing data to storage involves programming a controller. As we travel a bit higher, we’ll find a somewhat larger number peeps who write hardcore code (usually C/C++, and more recently, Rust)  that powers operating systems. Higher still, the power law kicks into high gear: there are significantly more people with each click. Developers who write system frameworks are vastly outnumbered by developers who consume them, and there are orders of magnitudes more of those who write Javascript. They are still entirely eclipsed by the number of those who create content.

With each leap in numbers, something else happens — the amount of power passed upward diminishes. Each new layer of abstraction aims to reduce the underlying complexity of computing and in doing so, also collapses the number of choices available to developers who work with that layer. Try to follow the rabbit trail of setting a cookie value, a one-liner in Javascript — and a massive amount of work in the browser that goes into that. Reducing complexity makes the overall mental model of computing simpler and easier to learn, which helps to explain the growing number of developers.

This funnel can be a helpful framing for a conversation about desired qualities of the API. Do we want to have rapid growth? Probably want to be aiming somewhere higher in the funnel, designing convenient, harder to mess up APIs. Want to introduce powerful APIs and not worry about the sharper edges? Expect only a small number of consumers who will understand how to use them effectively.

Developer surface

I mentioned this concept before, and I feel like it’s worth expanding on a little bit. If we are in the business of making a product that developers rely on to create user experiences, the developer surface of this product is the union of all means through which developers create these experiences. 

Let’s unpack this, starting with a simple case. Suppose you and I decided to ship a library that has one function. Applying the definition, that library is the product and its developer surface is the function. Easy, right? As our product becomes popular, we start noticing something weird. Remember that one-line file where we track the version of the library, just for ourselves? Well, turns out some developers started using its contents in their build. So when we thought — “oh hey, let’s just delete that file, we don’t need it anymore” — all hell broke loose? That file became developer surface, too!

In mature developer-facing products, the developer surface becomes far more than just the API. Shipping samples along with the library? Yep, these are part of the developer surface, too. Got some clever heuristics deep in your code? Or maybe just bugsHyrum’s Law captures beautifully the spirit of this phenomenon: 

With a sufficient number of users of an API,
it does not matter what you promise in the contract:
all observable behaviors of your system
will be depended on by somebody.

This sufficiently high number of API users can truly mess with what is or is not a developer surface. While we imagine the contract with developers as a crisp document of high transparency and clarity, we are usually mesmerized by the messy innards that are the outcome of developers just trying to get things to work. Even messier in comparison will be our attempts to convince developers to use the APIs the way we intended.

When we embark on a project that intends to ship a developer-facing product, it’s worth planning the work and structuring the team in a way that anticipates this messiness. We are not writing the developer contract. Developers write the contract with us, and frequently, their contributions carry more weight. Walking this line of carrying our original intention while having awareness of where the developers want to take is not something that comes intuitively or easily.

The story of belonging

Next in my adventure across the coherence narrative realm is the story of belonging. It sort of maps into one of the fundamental needs from the Four Needs Framework, but plays a subtly different role here.

The story of belonging is also something that is easy to spot as a felt experience. Someone wise suggested that humans are wired for connection, and the web of these connections is what creates the gravitational pull in the story of belonging. There’s something about being together with others, being part of the group, next to those who consider you kin, being loved, included, and understood.

When I try to examine stories of belonging, I notice something interesting. They usually contain the words “we,” “community,” “together,” “teamwork,” “alignment,” “unity,” and so on, but structurally, it’s almost always not a standalone story. Instead, the story of belonging acts as a powerful catalyst, laced into the story of a threat or the story of an opportunity. Just milling around together is one thing, but something magical happens when the “we are”  is combined with “under attack” or “the future”: the capacity for coherence shoots up like a rocket. No matter what kind of compounding loop we might face, it seems that doing it as a tightly knit group feels natural and right to us humans. 

To add to the weirdness, the loss of belonging is a common story of a threat — and finding it a common story of an opportunity. In our interconnected world, this kind of ouroboros is in itself an abundant source of compounding loops. It’s one reason why teams tend to form boundaries and organizations grow silos. It is also the undercurrent behind the craving to gain more likes or followers and many similar societal dynamics. 

Considering the story of belonging as means to improve organizational coherence, a couple of thoughts come to mind. First, the stories of belonging are quite inert by themselves. The need to combine with compounding-loop stories to get traction. Second, we live and tell multiple stories of belonging simultaneously. Navigating all these stories is tricky, and growing new stories of belonging (“we are a team!”) is a careful, finicky process that often bumps against all the participants’ stories, taking patience and time to develop. Maybe this is why we use the word “culture” to describe a mature organization’s story of belonging?

Veering toward first-order effects

Have you ever driven a car that pulls to one side? It’s often subtle, but after a while, the counter-steering effort becomes impossible to ignore. This metaphor comes to my mind whenever I encounter a common developer experience pattern: the veering toward first-order effects.

To set the context a bit more, let’s arrange the effects of producing developer surfaces in two orders. The first-order effects relate to producing the developer surface. When we ship an API, we want it to be adopted, to be used broadly. Thus, when we measure first-order effects of our efforts, we look at the API adoption rate, developer satisfaction, etc.

The second-order effects relate to developers producing user experiences using our developer surface. At the end of the day, an organization that invests into shipping APIs does so — intentionally or not — to influence the overall state of user experience in some way. When we measure second-order effects, our metrics will likely track changes in the user experience. Does using our APIs result in products that are more secure, performant, accessible, etc. for the user?

Based on what I’ve seen working with developer experience teams throughout my career, there’s a pronounced pull toward first-order effects. They are easier to measure, have a shorter feedback loop, and are more familiar to folks accustomed to shipping consumer products. Even if a team sets out to influence the state of user experience at the beginning of their journey, the appeal of relative immediacy of first-order effects is so strong that the original intention often gets left behind.

A common symptom of forgetting to counter-steer toward second-order effects is the loss of strategic flexibility within a larger organization. When the first-order effects become the means onto themselves, they tend to get entrenched in a local maxima of developer expectations, stuck in an optimizing loop. An organization that contains teams stuck in that particular way feels like it is unable to do anything about it: everyone is seemingly doing “the right thing,” and prioritization exercises quickly devolve into peanut buttering. When something like this is happening, it’s a good hint that the concept of second-order effects got rolled into a dusty corner of the team’s shared mental models space, or ejected altogether. 

To counter-steer, organizations must exert conscious effort to keep second-order effects in the shared mental model space. Whether it’s constantly pointing at them during the all-hands, setting up the metrics structure to reflect user experience shifts, or even just reminding about the unyielding force that — like that darned car — never quits pulling, it’s an investment that’s well-worth the price.

Cutting or highlighting?

Talking with one of my wise colleagues, we arrived at this neat framing around making decisions. “Decision” is a weird word. My friend Neel tells me that its Latin root is literally “to cut away,” and that recognition that a decision is always about narrowing the list of available options can be both liberating and anxiety-inducing. The interesting bit is that sometimes, decisions aren’t meant to cut away.

As it often happens in larger organizations, we tend to live in the swirl of the short-term and long-term objectives. And it is definitely a swirl: the art of leadership is picking out the right mix. Blend in too much short-term, and we’ll find the team stuck in the corner of a local maxima, overconstrained by its previous choices. Blend in too much long-term, and the team fails to make progress that’s necessary to keep that motor running.

To adjust the mix, leaders decide. A common mechanism here is prioritization: picking a shorter list of things that the team needs to focus on. One approach to prioritization is to apply the cutting mindset, as in cutting the list in half: keep what’s above the line and discard the rest. For example, let’s suppose I want to build an app that is available on both Android and iOS phones, but I want to prioritize iOS users. Applying this cutting mindset, I just forget about Android for a while, break out my XCode and start typing some Swift. Only after the iOS version is shipping do I start looking at the rest of the list. Given how many unexpected turns a typical software project takes, will I ever get to do that? Maybe. Will this approach result in a painful migration or two — or worse yet, the “release polka” where my app always looks out-of-date on one platform compared to the other? Probably.  

The cutting mindset is straightforward and clarifying. Yet, in situations where the rest of the list is still a thing we want to do later, it often leads to inferior choices. In these situations, we need something different. Instead of cutting the list, we want to highlight the items on which we want to focus — while still keeping the rest of the list in mind. With this highlighting mindset, the choices we make take on a different spin. Instead of asking “what’s the next step to deliver <prioritized item>?” we ask “how can we take a step toward delivering <prioritized item> that also takes us closer to completing the whole list?” The thing is, the items on our lists are rarely orthogonal and live in clean separate boxes. More often than not, considering them as a whole reveals opportunities for advancing toward completion of multiple items simultaneously. In my app example, while still focused on the iOS release first, I might consider picking a UI framework that also runs on Android, or at least build my middleware in a way that is portable.

When making prioritization decisions, it’s worth being explicit about the mindset with which you’re approaching, discussing with the team the reason you chose one over the other. Otherwise, despite your desire to highlight, an eager PM might swiftly cut your long-term objectives out of the mix. Or conversely, the team will continue to swirl aimlessly in the ideals you have already forgotten about, from back when you thought you cut them away.