惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
T
The Exploit Database - CXSecurity.com
I
Intezer
P
Privacy & Cybersecurity Law Blog
C
CERT Recently Published Vulnerability Notes
T
Tor Project blog
K
Kaspersky official blog
AWS News Blog
AWS News Blog
Schneier on Security
Schneier on Security
雷峰网
雷峰网
www.infosecurity-magazine.com
www.infosecurity-magazine.com
宝玉的分享
宝玉的分享
G
Google Developers Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Forbes - Security
Forbes - Security
T
The Blog of Author Tim Ferriss
S
Security @ Cisco Blogs
NISL@THU
NISL@THU
N
News and Events Feed by Topic
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
爱范儿
爱范儿
GbyAI
GbyAI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
Blog — PlanetScale
Blog — PlanetScale
Help Net Security
Help Net Security
F
Full Disclosure
V
Vulnerabilities – Threatpost
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
A
Arctic Wolf
D
Docker
T
Tailwind CSS Blog
L
LangChain Blog
The Last Watchdog
The Last Watchdog
美团技术团队
博客园 - Franky
H
Hacker News: Front Page
Stack Overflow Blog
Stack Overflow Blog
W
WeLiveSecurity
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Recorded Future
Recorded Future
V
Visual Studio Blog
N
Netflix TechBlog - Medium
Hacker News: Ask HN
Hacker News: Ask HN
博客园 - 司徒正美
Cyberwarzone
Cyberwarzone
S
Schneier on Security
Know Your Adversary
Know Your Adversary

Lobsters

CIFSwitch: a non-universal Linux local root vulnerability RIPE NCC session fixation: poaching logins with an Atlas probe GNOME 2.20 but its Web Components Agentic Search for Context Engineering – Leonie Monigatti Garnix is shutting down [not OC] akashina.tngl.sh/jjc Concerning Emacs (and Jazz) Nitpicking the shell history scene in ‘Tron: Legacy’ What's cooking on SourceHut? Q2 2026 The tenth OpenPGP email summit Package managers that package package managers Clojure on Fennel part three: parsing WordPress at 23 Finding Miscompiles for Fun, Not Profit GitHub - creusot-rs/creusot: Creusot helps you prove your Rust code is correct. Announcing Rust 1.96.0 | Rust Blog A Love Letter to Neovim sqlite AGENTS.md Am I a Bad Friend? CSS vs. JavaScript • Josh W. Comeau Erlang Ecosystem Foundation - Supporting the BEAM community A brief note about slot access cost in Common Lisp Keyboard latency probe Rethinking the GNOME clipboard issues Back to the Building Blocks’ Building Blocks Tech Notes: Theseus: translating win32 to wasm Fast is better than slow Content-addressed Rust builds (or, what kache actually caches) Intent to Prototype: Embedding API Canada’s Bill C-22 and the security cost of collecting more data 5 PostgreSQL locking behaviors that trip people up okmij.org Stop advertising in your commits! | AksDev GitHub - mplsllc/macsurf: A modern web browser for Classic Mac OS 9 PowerPC. Real CSS3, ES5 JavaScript, native HTTPS — built with CodeWarrior on the Carbon API. Introducing DoomBench - Can Your Data Stack Run DOOM? What are some of your favourite developer tools? Building a Scalable Ingestion Pipeline with Temporal (Part 1) Converting shallow Git bundles into normal repositories Are you a member of any professional associations? What is a harmonic? An interactive comic about additive synthesis How Virtual Tables Work in the Itanium C++ ABI Using SwiftUI to Build a Mac-assed App in 2026 Rust (and Slint) on a jailbroken Kindle. ~jack/lambda-on-lambda - Serverless Haskell on AWS - sourcehut git Human proof for FOSS contributions Extremely simple internet radio controlled via IRC Announcing BABLR Splitting Konsole views from Helix to run tools | AksDev GitHub - yugr/rust-slides Serving files over HTTP three ways: synchronous, epoll, and io_uring update docs with information about building with build.py (#979) · astral-sh/python-build-standalone@c9c40c5 A Simple Makefile Tutorial On C extensions, portability, and alternative compilers Switching to Colemak | Pedro Alves Just How Bad Was The Intel IAPX432? Nix's Substituter List Is Not a Routing Table Accelerating copy_if using SIMD Lambda on Lambda: Serverless Haskell on AWS | Blog Announcing feed-repeat v1.0 Scaling Akvorado BMP RIB with sharding EYG news: A host of CLI improvements, new guides and new effects The social contract of writing JS Crossword C array types are weird; and related topics Flatpak will depend on systemd – OSnews Migrating from Go to Rust | corrode Rust Consulting A portentous reunion Vivado Licensing Options How my minimal, memory-safe Go rsync steers clear of vulnerabilities the entropy layer of a wavelet codec, on its own GitHub - nferhat/fht-compositor: A dynamic tiling Wayland compositor. Debian SE Linux and PinTheft Does bulk memmove speed up std::remove_if? (No.) 声明式部分更新 | Blog | Chrome for Developers Fully in-browser container builds Dianne Skoll's Web Site - Remind The Architecture of Open Source Applications (Volume 1)Berkeley DB Pardon MIE? - ironPeak Blog “Long-Term Support” doesn’t mean what you think Jira IS Turing-Complete May I recommend thinking of Emacs as your Fortress of Solitude hershey Floodgap Gopher-HTTP gateway gopher://thelambdalab.xyz/1cuneiforth/ HP QuickWeb, Singular And Pointless That one time I used Go panics for flow control A new suite of modern tools coming for editing and publishing RFCs From the Tabletop… The Digital Antiquarian Building a Host-Tuned GCC to Make GCC Compile Faster Are we self-sovereign PKI yet? Claw Patrol: an open-source security firewall for agents | Deno Revised^7 Report on Scheme, Large: Procedural Fascicle Draft is now public A Network Allow-List Won't Stop Exfiltration — André Graf From AFSK to Goertzel – µArt.cz Software For My New Home Server Introducing Neptune: Direct3D virtualization for QEMU AI Agent Bankrupted Their Operator While Trying to Scan DN42 - Lan Tian @ Blog mimalloc: A new, high-performance, scalable memory allocator for the modern era Making wl_shm fast The Soul of Maintaining a New Machine - Third Draft | Books in Progress What is Git made of?
The essence of architectural work - Part 3
Uwe Friedrichsen · 2026-06-27 · via Lobsters

The essence of architectural work - Part 3

In the previous post, we discussed several architectural anti-patterns. We have seen that we are a lot more vulnerable to them if we do not understand why we do architectural work, i.e., understand its purpose. We understood that the focus and thus value of architectural work is accidental without having a clear understanding of why we are doing it.

Therefore, we will start looking at the purpose of architectural work in this post.

Over the years, I distilled three different facets regarding the purpose of architectural work 1:

  • The economic purpose
  • The cognitive purpose
  • The humane purpose

All three facets are relevant. Each one provides a different focus, looking at architectural work from a different perspective. There may be more facets I have not yet discovered, but it is important to understand that additional facets do not invalidate the existing ones. They simply add more perspectives, complementing the purpose. They do not create a different purpose but a more complete one, refining the focus it provides us.

Depending on the context, the different facets may be weighted differently. Based on what I have seen over the course of my career, the first one is always relevant when discussing with decision-makers – at least in commercial software development. The second facet is also very important; however, it is often misunderstood and thus implemented in contorted ways. Personally, I find the third one very powerful, but too often this aspect is completely overlooked, to the detriment of us all.

Let us start with the first facet.

The economic purpose of architectural work

When asked why we need to do architectural work, I sometimes say with a wink:

We need architecture to address

  • an optimization problem over time
  • with changing constraints

If this creates a WTF feeling, it is perfectly fine. To be honest, I do not expect anyone to understand it. It is more of a teaser. I also would not understand without additional explanation what this highly cryptic sentence is intended to mean. Thus, let me explain what I mean by this sentence.

Quality attributes

Many architects (including me) talk a lot about quality attributes. We try to express the properties of an architecture using quality attributes. To be more precise: We first try to understand the quality properties a solution must fulfill. Then we try to design an architecture that ensures the solution implements the desired quality properties. Usually, figuring out the desired quality attributes is a very early activity in any architectural work.

Quality attributes are often called “*ilities” because most of them have names that end in “-ility”, like, e.g.:

  • Accessibility
  • Availability
  • Effectiveness
  • Efficiency
  • Evolvability
  • Fault Tolerance
  • Functionality
  • Installability
  • Interoperability
  • Learnability
  • Maintainability
  • Observability
  • Operability
  • Portability
  • Recoverability
  • Reliability
  • Resource utilization
  • Scalability
  • Security
  • Time behavior
  • Understandability
  • Usability
  • Usefulness

This is a subset I often use as a tailoring basis for my projects. I compiled it from various sources like the software engineering quality standards ISO/IEC 9126 and its successor ISO/IEC 25010 as well as other sources like the quality attribute description of the SEI or the list of system quality attributes that partially also applies to software.

The list is not exhaustive, and based on your context, you may need to create a bit different list as your tailoring basis. I wrote a whole blog series about quality in software systems. Therefore, I will not dive deeper into the topic here. If you are interested in diving deeper into the idea of quality and quality attributes, you may want to read that blog series.

I mentioned the quality attributes for a different reason. If you ponder them for a bit, you can make an interesting observation. All the attributes can basically be divided into two classes:

  • Attributes that influence the appearance and behavior of the solution at development time (including build and test)
  • Attributes that influence the appearance and behavior of the solution at runtime which does not only include operations but also how users experience the solution

I have seen lots of discussions about software architecture going nowhere because one person had one type of attributes in mind and the other person the other type. Hence, let us take a closer look at both types.

Development time related quality attributes, e.g., understandability (of code), changeability, evolvability, or portability, describe the desired behavior of a system from a development perspective 2. They primarily influence how efficiently a system can be modified, i.e., they target the cost of change. The cost of change is important, as software normally needs to be modified regularly. This is a special property of software. However, it is poorly understood in general (see, e.g., my blog series “Software - It’s not what you think it is” for more details about this topic, especially the part about the value preservation dilemma).

But it is not only a lack of understanding of the properties and needs of software that makes development time related quality attributes hard to grasp. The much bigger problem is that the effectiveness of a measure taken to satisfy such an attribute can only be measured in hindsight.

To illustrate this issue, let us assume we have two options regarding an architecture decision we need to make: option A and option B, and we want to decide which option to pick regarding the cost of change. To make an accurate decision, we would need to do the following:

We need to identify all future changes to the software until its end of life first because only these changes are relevant regarding the cost of change. It is very important to understand that only the actual future changes to the software matter. We may have a feeling that an option might negatively affect the cost of change. However, as long as implementing the option does not affect any actual future change negatively, our feeling is irrelevant. It could be the ugliest hack imaginable. We might cringe just thinking of it. Still, if it does not affect any future change to the solution, it does not have any effect in terms of cost of change. 3

Then, we calculate the costs of all these changes after implementing option A and sum them up. Afterward, we do the same for option B. Finally, we compare the sums of the costs of future changes for option A and option B, and we pick the option with the lower sum, as this is the better option regarding the cost of change.

When reading this prescription, it becomes immediately clear where the problem lies. To make this kind of calculation, we would need to be able to split our timeline into two timelines. In one timeline, we would implement option A. In the other timeline, we would implement option B. Then, we would need to be able to travel forward in time until the end of the life of the software to identify all future changes to the software and calculate their costs.

While time travel and multiverses may be possible in science fiction and fantasy, they are not in our current reality. We cannot create two timelines, and we have no means to know all future changes to our software until its end of life. Therefore, we cannot accurately evaluate our two options, A and B. Instead, we need to resort to probabilities and heuristics.

This is the reason why we see so much “arcane guesswork” and so many heated discussions regarding how to create maintainable and changeable architectures. We can neither prove nor disprove whether option A is better than option B, C or D regarding the cost of change. While there are a few general heuristics that have proved to be useful based on experience, everything else is more a matter of belief than of knowing. This is a place where opinions tend to prevail and debates start. Additionally, we have a hard time proving our needs regarding the cost of change to people outside of software development.

Still, when considering the cost of change, the optimal architecture would be one that allows us to implement a software solution including all changes over its lifetime at minimal effort and cost. But as we cannot identify such an optimal architecture in a defined, deterministic fashion, we need to resort to probabilities and heuristics, accepting that our decisions – while aiming towards an optimal solution – will never result in the optimal solution. Therefore, we will apply the heuristics we know and a few other tools that help to increase the probability of making good decisions regarding the cost of change 4. But it will always be an optimization process under uncertainty.

This is the optimization problem over (the life-)time (of the solution) I talked about.

Runtime related quality attributes line, e.g., availability, scalability, security, performance, but also operability (usability from an operator’s point of view) or usability, accessibility and functional correctness (determining the usefulness of a solution from a user’s perspective) are something completely different. They describe the desired behavior of a system based on a usage and operations perspective, i.e., they target the correctness of a solution in terms of desired properties. 5

We do not optimize anything. Either the solution meets the required quality property, or it does not. This way, runtime-related quality attributes define invariants that constrain our solution space. They support us in evaluating different options for a given problem. If the option under evaluation would fail to meet a given runtime-related quality attribute, the option is not a suitable choice. This is more of an “in” or “out”.

E.g., if we have a quality requirement that the application responds within 500ms for 99% of all requests, a solution that responds within 1s on average is not a viable option. Or if we need to ensure 99,9% uptime (less than 9h downtime per year), we cannot pick an option that requires 2h maintenance downtime per month.

These constraints tend to change over time because the runtime-related needs and expectations tend to change over time. E.g., a new user group may be added to an existing solution, resulting in different availability, scalability, performance, or security needs. Or a new legal requirement may result in changed durability demands. Etcetera.

These are the changing constraints I mentioned.

Overall cost optimization

Looking only at quality attributes, we could leave it there. Optimizing for the cost of change while not violating the runtime-related quality attributes is hard enough already.

However, there is a big caveat: Cost of change ignores a lot of cost types that are relevant for an IT system over its lifetime. Even if we were able to find an optimal architecture regarding the cost of change, it might be a bad choice regarding the overall costs that would result from that architecture.

A very simple example: I have once seen a team that intended to introduce Kafka to their solution because they expected lower implementation efforts from using Kafka. It was not about throughput, performance, or anything else you would expect if you hear “Kafka”. Those demands were negligibly low. This decision only targeted the expected cost of change. The team expected to save a few implementation days during their project, and maybe a few more later. The overall savings would have been around 50 person-days over the lifetime of the system at best, i.e., something along the lines of 20,000 to 50,000 EUR overall (depending on who implements the changes).

However, they completely ignored the license costs and the cost of operations. The company did not use Kafka at the time, and it had no reason to introduce it anytime soon. They would have needed to hire specialists to run Kafka, as their current operations team was not able to pick up the new technology. Additionally, they would have needed to pay the license cost (you do not want to run the OSS version in production as it lacks some features that are vital for running Kafka in production).

Overall, this would have added approximately EUR 500,000 per year, i.e., several million euros over the lifetime of the software. Even if the company had introduced Kafka only one year after the team’s decision anyway, it would have been a very bad decision in terms of overall costs.

Still, looking at the cost of change alone, the decision would have made sense.

Looking at this little example, we immediately see that the cost of change is not sufficient as the sole optimization goal, as it neglects all other relevant types of costs. Instead, we need to optimize for the cumulative costs over all cost types and over the lifetime of the system. Besides the cost of change, this includes:

  • all other development costs
  • test costs
  • deployment costs
  • operation costs
  • maintenance costs
  • license costs
  • infrastructure costs
  • usage costs
  • administration costs
  • training costs
  • lost revenue
  • and more, depending on your context

Unfortunately, these other cost types are not covered by the quality attributes. We have to add them ourselves to complete the picture.

This makes the optimization aspect of architectural work even harder, as we have to cover more dimensions while the quality attributes, including the knowledge of how to implement them, are of little help here. We have to add this part ourselves to our architect’s toolbox.

Another issue is that most people solely focus on immediate development costs, i.e., they only focus on the costs software development creates now. They neglect future costs as well as all other cost types. Convincing such people to consider the cost of change alone can be hard enough. Discussing a holistic cost perspective over the lifetime of a system can quickly turn into an impossible task.

Summing up

With all that explanation, we can rewrite the initial, cryptic explanation why we need architectural work in a better, understandable way:

With architecture, we attempt

  • to minimize the cumulative costs of a system over its lifetime
  • while ensuring its correctness of behavior at runtime

This is the economic purpose of architecture. While it may appear obvious in hindsight, I have seen very little architectural work that worked towards this purpose. Based on my experience, it takes a lot of work and experience to get there. Most of the available literature is of little help as it only focuses on quality attributes and – sometimes – the cost of change. Thus, maybe this is a good point to pause for a moment and ponder this definition and its implications for architectural work.

In the next post (link will follow), we will move on to the other two facets regarding the purpose of architectural work: the cognitive purpose and the humane purpose. Stay tuned …