107 karma · joined February 18, 2019
"There exists an identifiable programming style based on the widespread use of type information handled through mechanical typechecking techniques. This typeful programming style is in a sense independent of the language it is embedded in; it adapts equally well to functional, imperative, object-oriented, and algebraic programming, and it is not incompatible with relational and concurrent programming."
[1] Luca Cardelli, Typeful Programming, 1991. http://www.lucacardelli.name/Papers/TypefulProg.pdf
[1] Gwern on Peter Naur's Programming as Theory Building, which includes Naur's essay and related comments. https://gwern.net/doc/philosophy/epistemology/index#naur-198...
[2] https://www.youtube.com/playlist?list=PLRqKmfi2Jh3uoMnZdaWmC...
[3] Continuous Design, https://www.georgefairbanks.com/ieee-continuous-design/
100% this. I've been teaching software design since the 1990's and it's so much easier when the audience has enough experience that I can wave my hands and say "you know when things go like this ... ?" and they do, and then we can get on with how to think about it and do better.
Without that, it's tedious. Folks with less experience have the brainpower to understand but not the context. I try to create the context with a synthetic example, but (again, waving hands...) you know how much richness your current system has compared to any example I can put on a page or a slide.
The book uses the jargon from the architecture community. Chapter 12 section 11 on Quality Attribute Scenarios is what you're looking for. But [1] seems to be a summary of Michael Keeling's treatment on qualities and scenarios, which I like better.
My thinking on this has been greatly influenced by Titus Winters who I've been teaching with in Google for the past couple years. He's tied together the ideas of quality attribute scenarios, compile-time tests, monitored metrics, and alerts in a way that is, in hindsight, completely obvious but I've not seen elsewhere. Maybe we can get him to write that up as an essay.
[1] https://dev.to/frosnerd/quality-attributes-in-software-1ha9
[2] Titus Winters, Design is Testability, May 8 2024. https://on.acm.org/t/design-is-testability/3038 (note: video doesn't seem to be posted yet)
I have youtube videos too [3] but they aren't as effective.
[1] https://www.youtube.com/results?search_query=simon+brown+arc...
[3] https://www.youtube.com/playlist?list=PLRqKmfi2Jh3uoMnZdaWmC...
Which ideas have survived since 2010?
Some operating systems are microkernels, others are monolithic. Some databases are relational, others are document-centric. Some applications are client-server, others are peer-to-peer. These distinctions are probably eternal and if you come back in 100 years you may find systems with those designs even though Windows, Oracle, and Salesforce are long-gone examples. And we'll still be talking about qualities like modifiability and latency.
The field of software architecture is about identifying these eternal abstractions. See [2] for a compact description.
"ABSTRACT: Software architecture is a set of abstractions that helps you reason about the software you plan to build, or have already built. Our field has had small abstractions for a long time now, but it has taken decades to accumulate larger abstractions, including quality attributes, information hiding, components and connectors, multiple views, and architectural styles. When we design systems, we weave these abstractions together, preserving a chain of intentionality, so that the systems we design do what we want. Twenty years ago, in this magazine, Martin Fowler published the influential essay “Who Needs an Architect?” It’s time for developers to take another look at software architecture and see it as a set of abstractions that helps them reason about software."
[1] Michael Keeling, Design It: From Programmer to Software Architect, https://pragprog.com/titles/mkdsa/design-it/
[2] George Fairbanks, Software Architecture is a Set of Abstractions Jul 2023. https://www.computer.org/csdl/magazine/so/2023/04/10176187/1...
"It democratizes architecture. You may have software architects at your organization — indeed, you may be one of them. Every architect I have met wishes that all developers understood architecture. They complain that developers do not understand why constraints exist and how seemingly small changes can affect a system’s properties. This book seeks to make architecture relevant to all software developers, not just architects."
In hindsight, my book hasn't been very good at that but perhaps it was a stepping stone on the path. Michael Keeling's book Design It: From Programmer to Software Architect does a better job of saying how developers can engage with architecture ideas. I'm a personal friend of his and a huge fan of his work. His experience report [2] on how to democratize architecture is what I aspire to do.
[1] Michael Keeling, Design It: From Programmer to Software Architect, https://pragprog.com/titles/mkdsa/design-it/
[2] Keeling and Runde, Agile2018 Conference. Share the Load: Distribute Design Authority with Architecture Decision Records. https://web.archive.org/web/20210513150449/https://www.agile...
1) Not all qualities are requirements. Requirements tend to be pass/fail, either you meet them or you don't. Latency is a quality and typically lower is better, not pass/fail (though sometimes it is).
2) "Nonfunctional" in other contexts means broken. If you saw a machine with a sign on it saying "nonfunctional" what would you conclude?
At one point I tried to find the origin of the term "quality attributes". It's way older than the software community. I found it being used in the 1960's by the US National Academy of Sciences. If anyone knows the origin I'm interested in learning more.
But, have you seen this kind of mistake / failure? A system is built so flexibly that it can handle all kinds of future needs, but it's slow. Maybe it's a shopping cart that takes 5 seconds to update. So start with modifiability as the primary heuristic but keep an eye out for other failure risks.
Meta-commentary:
This is an example of why it's so hard to discuss architecture. My book talks about "failure risks", which is pretty abstract or generic. There's no easy heuristic for avoiding "failure risks" like there is for web / IT systems.
Software architecture is a discipline that's bigger than just web / IT systems. Some systems must respond with X milliseconds, otherwise the result is useless, so the architecture should make that possible -- and preferably make it easy.
"I’m not ready to argue against Brooks’ Law that adding people to a late project makes it later. But today, when developers are working on a clean codebase, I see lots of work happening in parallel with tool support to facilitate coordination. When things are going smoothly, it’s because the architecture is largely set, the design patterns provide guidance for most issues that arise, and the code itself (with README files alongside) allow developers to answer their own questions."
[1] Scale Your Team Horizontally, George Fairbanks, IEEE Software July 2019. https://www.georgefairbanks.com/ieee-software-v36-n4-july-20...
Even if you clone us, our gut feel doesn't transfer to our clones. So, we can recognize under- and over-engineering in our guts, but how can we help someone else? Is there a better way than the risk-driven model?
1. Identify and prioritize risks
2. Select and apply a set of techniques
3. Evaluate risk reduction
[1] JESA Chapter 3: Risk-Driven Model. https://www.georgefairbanks.com/assets/jesa/Just_Enough_Soft...Yes, this happens too easily. It's the crux of Ward Cunningham's original observation on tech debt discussed recently [1]. He basically said: all of you thinking you can use waterfall to figure it all out up front are deluded. By getting started right away, you make mistakes and you avoid working on non-problems. I can fix the mistakes with refactoring but you can't ever get your time back.
Most teams live in his world now. Few do too much up-front design, most suffer from piled up tech debt.
I hope you give architecture another chance. Focus on the abstractions themselves [2] and divorce that from the process and team roles [3].
[1] https://news.ycombinator.com/item?id=40616966#40624446
[2] Software Architecture is a Set of Abstractions, George Fairbanks, IEEE Software July 2023. https://www.computer.org/csdl/magazine/so/2023/04/10176187/1...
[3] JESA section 1.5, https://www.georgefairbanks.com/assets/jesa/Just_Enough_Soft... "Job titles, development processes, and engineering artifacts are separable, so it is important to avoid conflating the job title “architect,” the process of architecting a system, and the engineering artifact that is the software architecture."
"The risk-driven model guides developers to apply a minimal set of architecture techniques to reduce their most pressing risks. It suggests a relentless questioning process: “What are my risks? What are the best techniques to reduce them? Is the risk mitigated and can I start (or resume) coding?” The risk-driven model can be summarized in three steps:
1. Identify and prioritize risks
2. Select and apply a set of techniques
3. Evaluate risk reduction
You do not want to waste time on low-impact techniques, nor do you want to ignore project-threatening risks. You want to build successful systems by taking a path that spends your time most effectively. That means addressing risks by applying architecture and design techniques but only when they are motivated by risks."An example of "architecture" is using the Client-Server style, where servers never take initiative and simply respond to client requests. That might be a good or bad fit to the problem.
[1] https://www.georgefairbanks.com/assets/jesa/Just_Enough_Soft...
[1] Garlan, Allen, and Ockerbloom. Architectural Mismatch: Why Reuse Is So Hard. IEEE Software 1994. https://ics.uci.edu/~andre/ics223w2006/garlanallenockerbloom...
Today, the term "tech debt" includes sloppy code, shortcuts, novice code -- really any kind of bad code. The original conception of tech debt is more limited and tied to waterfall vs iterative process choices. [2]
[1] Ward Cunningham, The WyCash Portfolio Management System, OOPSLA 1992. https://c2.com/doc/oopsla92.html
[2] George Fairbanks, Ur-Technical Debt, IEEE Software 2020. https://ieeexplore.ieee.org/document/9121630
The iterative process that a team follows is a bit like a garbage collection algorithm, and we can compare software development processes like we can any algorithm. A process can help developers do two things: clean up tech debt after it exists, or avoid creating it. When an iterative process does neither, tech debt buildup will lead to bankruptcy, so it is only suitable for projects with a short lifespan. A process that does both has the best chance at minimizing tech debt over a long lifespan. In particular, focusing on the system’s design will keep tech debt low.
[1] https://www.georgefairbanks.com/ieee-software-v38-n5-sep-202...
I like this way of expressing it. My book chapter is a much more long-winded. The chapter explains why the round-trip loses info, which is interesting to some people, but this insight cuts right to why the gap is important. Thanks!
ABSTRACT: The term technical debt was coined by Ward Cunningham in 1992. In recent years, people have broadened the definition to include ideas not present in the original formulation, including lack of skill, expedient hacking, and obliviousness to software architecture. By lumping these together, it’s harder to choose the right repair. This article proposes that we use the term ur-technical debt to refer to the original idea, which was: When I build systems iteratively, my understanding of the problem and solution grow gradually, and inevitably my current thoughts do not match code I wrote earlier, so I must expend effort to fix that code, much like paying interest on a debt. https://ieeexplore.ieee.org/document/9121630. Ur Technical Debt
I think Dijkstra wouldn't be satisfied with anything other than proofs. The article is meant to look at the ways we write programs that fall short of his standard (ie almost everything) and ask if there are gradations there. I find pretty big differences in code that's written to meet the lowest bar of "just pass the tests" vs code that's written with the intent of keeping its state space small, methods tidy, and overall complexity limited. I don't know of great language to convey that distinction so I'm borrowing the term "intellectual control".
The article is also available as HTML: https://ieeexplore.ieee.org/document/8611447