After recently reading George Fairbanks’ Just Enough Software Architecture and obtaining 90% in my TOGAF 9.1 Foundation Certification exam in Enterprise Architecture, I’ve naturally been thinking about Software Architecture a lot. The other day a friend and I were talking about a typical scenario, involving large scale products with multiple sprint teams on a tight delivery schedule. I will over-simplify and over-generalize it here:
The Scenario
Let’s say you’re building a product which requires a feature that a snapshot can be exported to a PNG file. This is typically what would happen:
- Product Owner: “As a user, I want to export snapshot to PNG, so that I can email it as an attachment to the Finance Department”
- Story is added to Product Backlog, prioritized during the Sprint Grooming and estimated in the Sprint Planning
- Developer Dinesh starts working on it, he adds the Export to PNG feature, it is demo’d at the end of the Sprint and everyone is happy
The feature and product iteration is shipped, customers start using it, the product team goes back to juggling new features and bugs. Priorities and sprint teams change. Somewhere down the line, another requirement comes up:
- Product Owner: “As a user, I want to export snapshot to PDF, so that I can archive it in the Document Management system” (Don’t ask why the two systems can’t work with the same format).
- Story is added, prioritized and estimated. This time though, Dinesh isn’t around (he’s either on vacation, promoted, no longer in the company or simply more focused on another aspect of the product)
- Developer Gilfoyle starts working on this feature. From this point on, 3 things can happen:
- Rearchitecture: An experienced developer or architect recognizes the potential of code reuse/refactor/rearchitecture between the two implementations. A common interface emerges, common functionality is moved up and specific functionality is moved to concrete classes. Note that:
- Code is refactored
- Some previously existing code is even thrown away
- Technical Debt is accrued: Gilfoyle has limited time to implement the new feature; on the UI side the “Export to…” menu selections show up users would expect, but the internal implementation is disjoint. The code is not clean (but does the job), the Export functionality is not unified into a single interface and there is code duplication.
- In some of the stakeholders’ minds, code has been “reused” from the previous implementation, but in reality it has been copy-pasted (imitation being the best form of flattery towards Dinesh)
- The team and PO might even recognize the Technical Debt and add it to the backlog, to be dealt with in the future at a lower priority (although that tends to lead towards a Bottomless Backlog)
- Rearchitecture: An experienced developer or architect recognizes the potential of code reuse/refactor/rearchitecture between the two implementations. A common interface emerges, common functionality is moved up and specific functionality is moved to concrete classes. Note that:
In both cases, layers emerge in software over time as features are added and the product evolves. However, the first case has architectural layers and the second exhibits feature layers: In extreme cases, you might even be able to infer the Product Backlog by looking at the order in which features were added.
The Analysis
Some thoughts:
- “The Technical Debt Trap“: Doc Norton explained it very well at CraftConf 2016 (video link): (a) Most of what we have come to call “Technical Debt” is actually code cruft, and (b) “clean, testable code is a pre-requisite to being able to pay back Technical Debt”.
- Show me the $: While a Product Owner may have limited influence over where budget is spent, a Product Manager may be in a better position to limit the long term negative effects of decisions made within the scope of individual sprints
- One size does not fit all: Complex products or long development cycles, must be overseen by an experienced Architect or Development Lead, who advises the PO, PM and other decision makers
- Stakeholders pay for the product, not the code: For stakeholders coming from a more traditional software engineering background, it may seem like throwing away (or refactoring) code is a questionable decision, because money was spent on producing it. This thinking must be erased by clarifying the benefits of a more robust and maintainable design.
The Solution (Maybe)
In summary: Features, as seen by the business, are not always the same as features, as seen by the developers. I’m tending to think the solution might be to maintain two backlogs: a business-oriented Product Backlog, and an architecture-oriented Technical Backlog. The latter would go into the details of how the business needs will be met at a technical level, driven by the objectives of overall cohesiveness, maintainability and constant reduction of Technical Debt. Here’s how I imagine it:
Note that the technical effort to achieve a given amount of business features, is more than what it would be if the team worked off of a single backlog. This is simply because the Technical Backlog takes into account the additional effort of refactoring/rewriting, which is normally not covered in the typical Product Backlog.
I’m curious about what you think, please leave a comment below or get in touch on Twitter: @survivalcrziest.
(PS: Here’s a tip: VCS-based Software Analysis by Adam Tornhill)
Update: Prioritization of Items in the Technical Backlog
Based on some of the readers’ feedback, I would like to clarify how I intend the system to be used:
- The top of the Technical Backlog is prioritized / groomed based on (a) “Technical Value” and (b) budget and schedule constraints (“effort”).
-
- Technical Value here is defined as the value delivered by the technical solution towards meeting the needs of the [prioritized] Product Backlog.
- Items may be to the Technical Backlog not just based on the insertion of new features in the Product Backlog, but also based on technical reviews / retrospectives where it is identified that an architectural change is required (e.g. for purposes of maintainability or compliance).
- The items pushed to the bottom of the Technical Backlog thus represent Technical Debt.