CelinQ Insights · No. 69

Can AI Detect Architecture Smells in Sparx Enterprise Architect Models?

Most architecture smells are graph patterns with a name, detectable by a rule long before any AI gets involved — the honest question is which smells actually need judgement, and which just needed someone to count.

A NILUS perspective on collaborative modelling for Sparx Enterprise Architect

The term "code smell" entered software engineering because it named something useful: a pattern in the code that is not, by itself, a bug, but that experience says correlates strongly with trouble later. A very long method, a class that does everything, a pair of modules that keep changing together for no obvious reason — none of these crash the program today, but each one is a reasonable predictor of a maintenance headache tomorrow. Architecture smells are the same idea one level up. A cycle between two subsystems that were supposed to be layered cleanly will not fail a test today. A component that half the portfolio depends on, with no redundancy anywhere near it, will not cause an incident this quarter. But both are the kind of structural pattern an experienced architect learns to notice and worry about, and both are exactly the kind of pattern that a graph, once you have one, can be searched for mechanically.

That last point is the one worth dwelling on before asking whether AI can find these smells, because the honest answer changes depending on which smell you mean. Some of the classic list — cyclic dependencies, god components, orphaned elements — are graph-theoretic patterns with precise definitions, and a program that can traverse a graph correctly will find every instance of them, every time, with no ambiguity about what counts. Others — missing business alignment, in particular — are not graph patterns at all, and pretending otherwise is where "AI-powered smell detection" tends to overreach. Working through the list smell by smell makes the boundary concrete rather than rhetorical.

Cyclic dependencies

A cycle exists when you can start at a component, follow dependency relationships outward, and eventually arrive back where you started. In a model that is supposed to respect a layered architecture — presentation depending on business logic depending on data access, and never the reverse — a cycle usually means two layers have quietly become entangled, often through a small, well-intentioned shortcut that nobody flagged as a layering violation at the time it was added. Finding every cycle in a dependency graph is a completely standard graph algorithm, decades old, with no ambiguity in its output: either a set of elements forms a cycle under the relationship types you are checking, or it does not. Running it against a model with a few thousand elements takes a fraction of a second and misses nothing, which is precisely the kind of exhaustiveness a manual review, done by even a careful architect working from a diagram, cannot reliably match, because diagrams show the relationships someone chose to draw, not the complete graph.

God components and excessive coupling

A god component is the architecture-level cousin of a god class: one element that has accumulated so many relationships, of so many kinds, that it has effectively become a single point of coordination for a large part of the system, which is rarely how the design was intended to work and usually the residue of years of "it's easiest to just connect it to the thing that's already connected to everything." Detecting a candidate is a matter of counting: how many distinct relationships touch this element, compared to the distribution across the rest of the portfolio. An element sitting far out on the tail of that distribution is worth a look, and the threshold that defines "far out" is a parameter an organisation sets based on its own portfolio's shape, not a universal constant.

Excessive coupling is the same measurement applied more narrowly, between a specific pair or small cluster of components rather than one component against the whole portfolio: how many distinct relationships connect them, and does that count look more like two components sharing a genuine, well-defined interface, or two components that have gradually become impossible to change independently. Both checks are counting exercises against the relationship graph, run consistently, with a defined threshold an architect can adjust — not a judgement call made freshly each time someone happens to look at a diagram.

Presentation Business logic Data access cycle: data access calls back to presentation Integration Hub 41 relationships against a median of 5
Two smells a graph algorithm finds completely, every time: a layering cycle on the left, where data access loops back to presentation, and a god component on the right, sitting far out on the tail of the relationship-count distribution.

Orphan components and unowned applications

An orphan component is an element with no meaningful relationships to the rest of the model at all — present in the repository, but disconnected from everything, which usually means one of two things: it genuinely is disconnected in production, which is itself worth knowing, or the relationships that connect it in reality were simply never modelled, which is a documentation gap rather than an architectural one. Either way, the detection is trivial once you have the graph: walk every element in scope and report the ones with zero relevant relationships. What the finding means is a judgement call for the architect who investigates it; that it exists at all is not.

An unowned application is not a graph pattern but a field-presence check, exactly as described in the discussion of deterministic model analysis — does the element carry a populated ownership field, yes or no. It belongs on this list because it behaves exactly the way an architecture smell should: individually unremarkable, collectively a real governance risk, since an application nobody is accountable for is an application nobody will notice going stale, and one of the more common triggers for an unplanned, expensive rediscovery project years later.

Duplicate applications

Duplication is the smell most tempting to hand entirely to a language model, because recognising that "Customer Portal" and "Customer Self-Service Portal" probably refer to overlapping functionality feels like a task for something that understands meaning rather than exact matches. There is real substance to that instinct, and it is one of the places in this list where deterministic rule matching genuinely runs out of reach on its own — exact name matching will not catch two applications with different names covering the same ground, and neither will a simple similarity score reliably separate genuine duplication from two applications that happen to sound alike but serve different business units for good reasons.

The honest position is that duplicate detection benefits from a layered approach rather than either extreme. Deterministic signals still carry real weight and should run first: exact or near-exact name matches, elements sharing an identical set of downstream dependencies, applications classified with the same stereotype serving what tagged data suggests is the same business capability. Those signals narrow a portfolio of thousands down to a short candidate list mechanically and defensibly. Deciding whether a given candidate pair is a genuine duplicate worth consolidating, or two systems that only look alike from the outside, is where an experienced architect's judgement — possibly assisted by an AI-generated summary of what each candidate's documented purpose says, drawn strictly from the model's own content rather than invented — earns its place. The rule narrows; the human, and only secondarily an AI narrating what the rule already found, decides.

A rule that narrows a portfolio of thousands to a handful of duplicate candidates has already done the expensive part. Whatever finishes the job — a human's judgement, or an AI summary a human still has to accept — is cheap by comparison, and neither should be trusted to do the narrowing on its own.

Unused interfaces and single points of failure

An unused interface is one declared in the model with no relationship indicating that anything actually consumes it — an application programming interface everyone assumed something was using, until a check reveals nothing in the repository is connected to it at all. This is worth surfacing not because it is necessarily wrong (the consumer might exist and simply never have been modelled) but because it is the kind of finding that either uncovers dead surface area worth retiring, or uncovers a documentation gap worth closing, and either outcome is useful. The check itself is, again, a presence check against the relationship graph: does this interface have at least one inbound usage relationship, yes or no.

Single points of failure are a graph question answered with the same family of algorithm used for cyclic dependencies: given the dependency graph within scope, which elements sit on every path between two parts of the system that are supposed to be able to function somewhat independently, such that removing that one element would sever the connection entirely. This overlaps directly with the dependency-structure checks described in the piece on AI-assisted architecture review, and it is one of the more valuable smells to catch early, because a single point of failure discovered during a governance review is a design conversation; the same single point of failure discovered during an actual outage is an incident report.

Stale technology and missing business alignment

Stale technology is a comparison, not a discovery: does the technology tag on an in-scope element appear on the organisation's current approved list, or does it match something the organisation has formally deprecated. Mechanically trivial, and valuable mainly because it turns a standards register that nobody reads cover to cover into an actively enforced check that runs against every element, every time, rather than relying on someone remembering to look something up.

Missing business alignment is the smell on this list that genuinely resists a clean rule, and it is worth naming honestly rather than folding it into the same confident language as the rest. Whether a technical component actually serves a documented business capability, or exists for reasons nobody can quite trace back to a business need any more, is a question about meaning and context that a graph traversal cannot settle on its own, because "alignment" is not a relationship type — it is a judgement about whether the relationships that do exist add up to a coherent story. A deterministic check can get partway there: does this application have any modelled relationship to a business capability or business process element at all, which at least surfaces the components with no traceable business connection whatsoever as candidates for review. Whether the ones that do have a connection are actually well aligned, rather than connected by a relationship someone drew once and never revisited, is exactly the kind of question that belongs with a human architect, possibly aided by an AI summary of what the model does say about the connection — never settled by the tool on its own authority.

The smells with a graph-theoretic definition are the ones a rule will find completely, every time. The smells that are really questions about meaning are the ones no amount of computation should be allowed to quietly answer on its own.

Rule-based versus AI-based findings

Laid out smell by smell, the pattern is consistent enough to state as a general principle rather than a case-by-case judgement call: where a smell has a precise structural definition — a cycle, a degree threshold, a missing field, a graph-connectivity property — a deterministic rule finds every instance completely, reproducibly, and explainably, and there is no accuracy to be gained by routing that same question through a language model, only latency, cost, and a new source of silent error to worry about. Where a smell is fundamentally about meaning or intent that the model's structure only partially captures — genuine duplication versus coincidental similarity, real business alignment versus an unrevisited relationship — a deterministic rule can narrow the field usefully but cannot close the question on its own, and this is where an AI-assisted second look, applied to a rule-narrowed candidate list and grounded strictly in what the model actually contains, adds real value that a rule alone does not.

This is the same deterministic-first discipline described across the rest of this series, from the private, AI-free analysis layer through to how a quality score is computed: CelinQ's default position for any given check is to ask whether it has a precise, rule-expressible definition, and if it does, that is where the answer comes from, full stop, with AI switched off changing nothing about the result. AI is reserved, deliberately and narrowly, for the genuinely harder minority of smells where structure alone cannot settle the question, and even there its output is offered as a labelled suggestion for a human architect to weigh, never as a finding presented with the same unqualified certainty as a cycle the graph algorithm actually proved exists.

A worked scenario: chasing down a god component

The general principle behind all of this reads more convincingly with a concrete case attached to it, so consider how a god-component finding might actually unfold inside a real portfolio. A coupling check, run against a workspace covering a mid-sized organisation's core systems, flags an element called "Integration Hub" sitting far out on the tail of the relationship-count distribution: forty-one distinct relationships touch it, against a portfolio median of five. On its own, that number does not say whether the finding is a genuine problem or a perfectly reasonable integration layer doing exactly the job an integration layer is meant to do — plenty of well-designed architectures have a legitimate hub-and-spoke element that is supposed to have many connections, and flagging every one of them as a smell without further context would train architects to ignore the check entirely within a month.

This is exactly where the deterministic layer's job ends and an architect's investigation begins, and it is worth tracing what that investigation actually looks like in practice rather than treating "a human decides" as a hand-wave. The architect pulls the specific list of forty-one relationships the check produced — not a summary, the actual list, each one linking back to the element on the other end — and starts sorting them by relationship type. Roughly thirty of them turn out to be the expected kind: point-to-point interfaces between line-of-business applications and a genuine, documented integration layer, which is precisely what the element was built to be. The remaining eleven, though, are a different shape entirely: direct database-level connections that bypass the integration layer's own published interface altogether, added one at a time over several years by different project teams each solving their own short-term problem the fastest way available at the time. Those eleven are the actual smell, buried inside a count that looked uniform from the outside.

Notice what made this investigation tractable rather than another vague, unresolved worry on a backlog somewhere: the check did not merely assert "this component is over-coupled" and stop there. It produced a complete, traceable list that the architect could sort, filter, and reason about using their own domain knowledge of which relationship types were supposed to exist and which were opportunistic shortcuts. A purely AI-generated impression of the same component — asked in isolation to assess whether "Integration Hub" looked over-coupled — could plausibly have reached a similar-sounding conclusion in prose, but without the underlying list attached, the architect would have had no way to distinguish the thirty legitimate relationships from the eleven problematic ones, and no way to check the AI's reasoning against the actual graph rather than trusting its narrative. The rule's exhaustive, evidenced list is what turned an ambiguous smell into an actionable eleven-item cleanup with a clear rationale the architect could take straight into a design review.

The resolution, in this case, was not to eliminate the god component — Integration Hub remained, entirely appropriately, the most-connected element in the portfolio after the investigation closed. What changed was that eleven relationships were rerouted through the interface the integration layer was actually designed to expose, and a new rule was added to the workspace's own check configuration flagging any future database-level connection that bypasses a designated integration element, so the same shortcut could not silently reaccumulate over the next three years the way it had over the last three. That last step is worth underlining: a smell-detection ruleset is not a static catalogue handed down once. Every investigation that finds a real, previously unnamed pattern is an opportunity to encode that pattern as a new check, which is exactly how the honest limitation named earlier — that a rule engine only finds what it has been told to look for — gets narrowed over time, one confirmed finding at a time, rather than staying fixed forever at whatever list a vendor shipped on day one.

Honest limits

None of this list is exhaustive, and no fixed catalogue of smells ever will be, because architecture problems keep inventing new shapes as fast as anyone can name the old ones. A rule engine only finds what it has been told to look for, which means a genuinely novel structural problem — one that does not resemble a cycle, a coupling outlier, or any of the other named patterns — can sit in a model indefinitely without a single rule ever flagging it, waiting for a human reviewer's eye or, eventually, someone extending the ruleset once the pattern has been recognised often enough to deserve a name and a check of its own. That is a real limitation, and it is the honest reason architecture smell detection, however thorough, is a complement to experienced review rather than a substitute for it.

What the deterministic-first approach does guarantee is narrower and, for a governance process, more valuable than exhaustive novelty detection: every smell that does have a precise definition gets found completely and consistently, every time the check runs, against the model as it actually stands rather than as someone remembers it from the last review. Combined with a rule-narrowed, human-decided approach to the smells that genuinely need judgement, that is a realistic and defensible answer to the question this piece opened with — not "AI detects your architecture smells," but "the smells with a real definition get found by something that cannot get tired or distracted, and the ones that need a human get put in front of one with the evidence already assembled."

It is worth being honest, too, about why this framing matters beyond the immediate accuracy of any single finding. A governance process that leans on smell detection to justify real decisions — retiring a component, escalating a coupling problem, blocking a release over a newly introduced cycle — needs to be able to say, to a sceptical stakeholder or an external auditor, exactly why a given finding was raised. "The graph algorithm proved a cycle exists between these named elements, and here is the path" survives that scrutiny without difficulty. "The AI thought this looked concerning" does not, no matter how often the AI turns out to be right in practice, because being usually right is not the same as being independently checkable, and governance processes are built on the latter. Keeping the rule-based majority of this list rule-based is what lets the smaller, genuinely judgement-dependent minority — duplication, business alignment — be handled openly as judgement calls, rather than dressed up in the same false certainty as a proven cycle.