Thinking about why aesthetic feedback on code is so valuable led me to the question of why the feedback techniques we have for procedural code don't work well for Architecture. There have been many attempts to lint architecture decisions, or write unit tests for them, or create frameworks people can plug together like libraries, or create prescriptivist languages, and I have yet to see any of those techniques produce the desired payoff of graceful, cheaply-modified code.
It led me to this realization: architecture is largely semantic work, rather than syntactical.
A well-architected system could potentially end up running the same byte code as a poorly-architected system, and yet be more valuable to the business because it can be more-cheaply understood and modified by people.
Good architecture lets developers make accurate guesses about how the system will behave and how parts of the system we have not read are structured. These programs exhibit the property of a "well-constructed plot", as described by Lee Devin and Robert Austin in their book The Soul of Design. Quality software embodies a coherent set of patterns that work together to fulfill the expectations of the viewer.
In a system where our expectations are fulfilled, future changes are less likely to have unanticipated consequences, directly preventing bugs. When there is unintended behavior, it is cheaper to debug and correct. The coherent understanding makes it easier to observe the system, and that information can support impactful improvements to system properties like performance, security and resiliency. When we use Domain-Driven Design techniques to align our semantic concepts with our users', we can even use that well-constructed plot to provide a predictable experience to the user.
Unfortunately, we can't have a computer measure that quality. Not for lack of trying; people have come up with a huge variety of heuristics attempting to turn architecture quality into something syntactical we can statically analyze. Reams of papers have been published attempting to flatten the question of suitability into an automatic, linear operation that didn't need to involve humans as subjective participants.
It turns out to be is mathematically infeasible to judge the quality of an architecture in isolation. The properties of coupling and cohesion are only defined relative to a change being made to the system. Referential systems and the semantics of language only carry meaning when read in the cultural and linguistic context a reader brings to the work. Software architecture is inherently postmodern.
The value of software is created in the relationship between object and subjects across time and space.
Linear models are incapable of capturing the multi-sided, participatory, evolutionary nature of software quality, just like conventional management approaches are incapable of capturing the value of good design. Just like companies that are able to buck conventional management strategies to build extraordinary products can be inexplicably successful, software development teams that are able to buck legibility-obsessed software development conventions to prioritize subjective quality are able to succeed where other approaches fail.
Luckily there is an easy pattern for collecting distributed, contextual information: ask each node in the system what it thinks. This is why code reviews, collective code ownership and pair programming can be effective tools for quality: they function like MapReduce. Each developer participating in the system contributes information about the quality of our architecture relative to the variety of changes we are actually making.
This is also why having an on-team customer is so much more effective at creating quality than the more-linear approaches of product or project management.
Distributed approaches would still be impractical if each node had to do a lot of work to come up with the answer. Luckily, humans have evolved the capacity for aesthetic pattern matching. Our reactions of pleasure and disgust give us information about whether an object gracefully fulfills the purpose we have in mind. As Devin and Austin explore, it is particularly informative about how cohesive and self-consistent a system is.
Valuable architectures exhibit low coupling and high cohesion. As Kent Beck has described, to accurately judge coupling we have to consider the system in its entirety, whereas cohesion is a local property that is often easy to increase. Similarly, our aesthetic sense is mostly tuned to judge cohesion. The sense of satisfaction we feel in reaction to a coherent, self-referential whole lets us determine at a glance how coherent our code will be after a change.
Rather than struggling to find ways to computationally judge contextual value in isolation, it is more productive to optimize the cyborg system of software+collaborators. We don't need to erase human judgement to build extraordinary software: we need to embrace it.