Over-Architected? Maybe, Maybe Not
Reviewing a software solution? Identifying complexity beyond what you feel is necessary? Consider the implications before dissing the architecture and approach.
Join the DZone community and get the full member experience.
Join For FreeAn oft-heard criticism of way-to-many software solutions is that it's over-architected, implying that the design, abstractions, implementation, deployment, or whatever is unnecessarily complex, difficult to understand, unmaintainable, unnecessary, or wrong. Criticisms are often thrown into the ether without context or supporting narrative; criticisms that often stick.
So what's gained by labeling a solution as over-architected?
"Software architecture comparisons @obscuradigitalsf" by raganmd is licensed under CC BY-SA 2.0.
Often it's the ultimate get-out-of-jail card for software engineers, deflecting blame for larger-than-expected efforts and timelines without objective analysis or even understanding of the current implementation. Unfortunately, senior leadership often blindly accepts the explanation with a sympathetic Ah, over-architected, I'm so sorry shrug, and especially effective when the original engineers aren't available to fill in the blanks on requirements, decisions, implementation, etc.
Yes, the original architecture implemented may be orthogonal to your preferred architecture — the tech stack, the business assumptions, abstractions, etc. — but are you in a position to unequivocally say it's over-architected? Have your company's business goals or technical direction changed since the original implementation? What were the non-functional requirements that needed to be considered? Is there anything interesting in commit messages?
Most importantly, do your concerns define over-architected or is something less sinister going on? Hmmmm, I'm not sure!
Software Engineers Engineer Software
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous implementation,
Or to take arms against a sea of troubles
And to start anew with a clean slate.
Hands up if you prefer maintaining existing rather than writing new code. Keep your hands up if that includes maintaining someone else's code. Ah, thought so.
While Hamlet's original soliloquy discusses his potential suicide, my (poor) adaptation references software development: software engineers often go out of their way to take steps leading to the unfettered creation of new code over the long-term responsibility of someone else's code.
And when given maintenance work — in whatever form it may take — engineers look for angles that allow them to revamp, restructure, rewrite, and in general make the work more interesting. Correct decision if the blame shows excessive churn, the cyclomatic complexity is obnoxiously high, or the code has truly become unmaintainable. Granted, product owners and scrum masters won't be pleased, but at some point, the sins of the past can no longer be ignored.
Publicly calling the existing code over-architected and you may get your wish. However, occasionally someone requests a deeper explanation which calls into question the reasons, dubious because the engineer:
- Doesn't understand the current implementation, nor makes an effort to learn
- Doesn't understand business or technical requirements or other underlying assumptions
- Doesn't agree with design patterns or code structure used
- Doesn't like the code style or formatting, or even the programming language itself
And, to no one's surprise, the rewrite becomes larger than envisioned because, ironically, s/he has to finally understand the existing solution to reimplement it: despite claims you're not paving the cowpath, inevitably you may need to, which isn't apparent without overall comprehension. Is your organization really prepared to go API First, microservices, NoSQL, or whatever else is being added to the resume?
The timelines increase, leadership frustrations grow, and other essential work is delayed and deferred, all because the engineer insisted it was necessary. We've all seen it, many of us have been the instigators, and it's not usually a pretty story.
And the question remains: Was it truly over-architected?
Problematic Architectures
Architectures applied within software engineering disciplines are labeled in a myriad of ways: e.g., enterprise, system, application, software, cloud, and integration. To add to the confusion, organizations often define the architecture disciplines to suit their internal needs, making it difficult to clearly define each discipline's responsibilities and boundaries. It's definitely not an apples-to-apples comparison.
That said, defining problematic architectures is possible if you talk generically and don't try to define specifics within an architectural discipline. I see three basic types of potentially problematic architectures.
1. Differently-Architected
Differently-architected solutions are those solutions where opinions differ on how the non-functional requirements are addressed within the solution. Should a solution intended for the cloud be cloud-native or cloud-agnostic? Is stability and reliability more or less important than throughput and performance? Are supporting resources selected based on cost, capabilities, or both?
Any concerns or complaints you have with the underlying architecture must be balanced against the non-functional requirements identified as important for a successful solution. It may be that you disagree with the non-functional requirements; therefore, your concerns or complaints may only be relevant when non-functional requirements are re-prioritized. The solution is valid if the non-functional requirements are met, regardless of your feelings.
Even when you are in complete agreement about the non-functional requirements, it's guaranteed that different engineers will create different solutions: synchronous vs. asynchronous, object-oriented inheritance vs. composition, functional or CRUID-based API endpoints SQL vs. NoSQL, API First vs. MVC. It's subjective because each solution is essentially correct; it's just that your approach is different than mine.
"Hello, World!" can be implemented in thousands of different ways, each equally right or wrong, so different engineers and architects are going to approach each problem differently. Is that wrong? No. Is that over-architected? If the non-functional requirements are clearly identified and implemented, probably not. But you still likely disagree with what I designed and implemented.
2. Mis-Architected
Identifying a mis-architected solution usually requires deconstructing a flawed implementation from conception to deployment: poorly defined or undefined requirements, poor code quality, poor project execution, unrealistic timelines, and an unhelpful architecture. The problems — and blame — are usually multi-faceted.
Setting those complexities aside, there are common characteristics of a mis-architected solution:
- Non-functional requirements aren't addressed, assuming any are identified.
- The technical skills and background necessary for successful implementation don't exist within the organization.
- The architecture requires building components outside the organization's core competency, especially when existing components exist.
- The deployed solution is unstable and requires regular attention to avoid outages.
- Maintenance and extension rely on individuals who are deemed irreplaceable.
You likely recognize one of those if you've ever participated in a train wreck project. You might also realize that what you thought was mis-architected was actually non-architected. Most importantly, these projects and their resultant solutions are often unsalvageable, and everything involved with it was a waste of time.
3. Over-Architected
Is any solution over-architected? Probably. Is this light switch overkill? Perhaps for most of us, but the Rube Golbergs and Makers in this world would beg to differ.
This following experience may represent an over-architected; it may also just be mis-architected, definitely differently-architected.
Problem Statement
In my days as an independent software consultant, I was contracted as a backfill for a just-departed employee. The ex-employee had architected, designed, and (mostly) implemented a custom framework for building the company's first true web application: s/he left sample implementations and little (no?) documentation (design, usage, etc.), and the remaining staff had to try and pick up the pieces.
[For the Millennials reading this, remember that the early days of web development had no real standards or best practices, open source was in its infancy, and it was the wild west as everyone searched for answers. Underpowered users' computers struggled with simple browser-side scripting (pre-DOM), and each browser vendor's browser liberally interpreted the HTML standard. It's when Internet Explorer started its reign of terror (and yet somehow still exists today). So completely different than today.]
My assignment: own the framework, learn its secrets, and define a roadmap for developing the app.
Understand and Internalize
Conceptually simple from 100K feet/30.5K meters: server-side generation of HTML to create, orchestrated by a Java Servlet app (the framework) that handles requests, responses, navigation, etc. At 50K feet/15K meters, it became less simple. At 25K feet/7600 meters, it became downright scary.
The concerns increased the more I dug. Pages were tightly coupled and seemingly small changes quickly cascaded to neighboring pages. Pages directly generated HTML, making it difficult to ensure consistency across the app. Changing default framework behavior relied on finding the corresponding hooks, which were often numerous and confusing. Orchestration worked in the original servlet engine (Sun Java Web Server) but wouldn't if changed (starting to look at Tomcat for performance). Local development required regular syncing of other engineers' code, made difficult with the version control of the day (CVS, Subversion, Visual Source Safe, etc.).
I've forgotten other horrors concerns, but the barriers were daunting, and the chance of success dimmed. Hard decisions needed to be made.
Decision Time
My conclusion: the framework was fit for purpose (barely) but not fit for development; any attempt to continue would overwhelm the remaining engineers and likely never be completed.
The manager, to her credit, agreed and decided to cut her losses. Long story short: a simpler, more focused framework was designed, and within three weeks, engineers could start app development on a working model, successfully demoing our progress after two months Ultimately, very successful, and used for multiple apps before being retired.
The Verdict
Reasons to consider the original framework over-architected:
- Missing non-functional requirements: No guardrails to reign in design and implementation
- Ego-driven design: Attempt to show how smart you are by including everything but the kitchen sink
- Overly complex: Difficult to implement, maintain, and support
- Un-differentiator: Architecture functionality is not a competitive differentiator and substantially extended time-to-market
You could argue mis-architected and perhaps differently-architected, but that's semantics. Regardless, we did our due diligence before changing tact, objectively justifying instead of just saying over-architected.
Final Thoughts
What passes as architecture for a software solution varies widely, based on any number of external factors: business vs. software shop, experience and skill set of technical staff, technologies available, organizational maturity, blah blah blah. It's expected.
Too often, an implementation is quickly dismissed without understanding the context in which the work was done. Legitimate reasons may justify a partial or complete re-implementation, but may also be self-serving for engineers. As responsible software engineers, we should justify work efforts that most benefit the organization, not software for software's sake. This does not imply that nothing but features and technology be damned, but does imply that we should be able to justify the technical work proposed. Investigate, document, narrate, justify.
And don't just say, "It's over-architected!"
Published at DZone with permission of Scott Sosna. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments