Do I Have a Big Ball of Mud in My Frontend?
You join a new project. The application runs. There are folders, components, services, perhaps even architecture diagrams.
And at first, you understand nothing.
That is not a reason to worry. A new domain comes with new terminology, an established application comes with history, and a larger codebase takes time to learn. Even in an excellently structured system, you will not understand on day one why a certain state exists, what a specific business term means, or why a process follows exactly those five steps.
The more interesting question is therefore not how much you understand at the beginning, but how your understanding develops.
Does the system become simpler as you learn more? Do you discover rules, boundaries and recurring patterns that eventually let you predict unfamiliar parts of the codebase with reasonable confidence?
Or do you mainly learn why the rules do not apply here, why this service is an exception, why that component directly reaches into three other business areas for historical reasons, and why one particular part of the system should definitely not be used the way its name would suggest?
At some point, an uncomfortable suspicion appears:
You are not learning the architecture. You are learning the exceptions to the architecture.
Even that does not automatically mean you are looking at a Big Ball of Mud. Not every bad architecture is one. A huge component is not one. A God Service is not one. A custom routing system is not one. A few dependency cycles are not one. And the fact that an Angular feature treats the framework’s intended mechanisms more like optional suggestions is not enough either.
The more important question is:
How much effective order does this system still have?
Foote and Yoder originally described a Big Ball of Mud as a casually, even haphazardly structured system whose organization is dictated more by immediate expediency than by a recognizable design. Later research on architecture erosion similarly focuses not merely on individual violations, but on the growing distance between intended and effective architecture and on the consequences for maintenance and evolution.
For diagnosing a frontend, this distinction matters: a Big Ball of Mud is not simply a system with many architecture problems. It becomes critical when those problems lose their local boundaries and order increasingly stops functioning as a real constraint.
A Local God Is Not Yet a Big Ball of Mud
Section titled “A Local God Is Not Yet a Big Ball of Mud”Let us start with a counterexample.
Imagine a complex planning feature. Perhaps it contains a map, several planning states, substantial domain logic and a great deal of interaction. At the center sits one component that has grown to an impressive size over the years. Around it are roughly ten smaller components, all closely wired to it.
The central component loads data, holds state, orchestrates user interactions, opens dialogs, makes domain decisions, navigates, triggers updates and looks after several concerns that, in another life, might have become responsibilities of their own. Meaningful layering is barely visible. Framework mechanisms are used where they happen to fit; elsewhere, custom paths have emerged.
In short: the thing is a small god.
That is bad frontend architecture. The component combines multiple responsibilities, meaningful layering is effectively gone, and presentation, domain logic and orchestration meet in the same place. Locally, it really is a kind of God Object, and every larger change becomes harder than it needs to be.
But now comes the more important observation: the problem stops at a business boundary.
The planning feature is poorly structured internally, but other domains do not reach arbitrarily into its state. The feature, in turn, does not automatically know half of the rest of the system. Other slices still exist with boundaries that remain understandable. Someone working on billing does not inevitably end up inside the planning component. Someone changing user administration does not need to understand its internal state machine.
The problem is serious, but bounded.
A God Object inside a bounded slice is not yet a Big Ball of Mud.
Or more generally:
Bad architecture can be local. A Big Ball of Mud is systemic loss of boundaries.
That is an important negative test. Otherwise almost every sufficiently old application would eventually qualify as a Big Ball of Mud. A useful diagnosis therefore asks less whether bad structures exist somewhere, and more whether the system is still capable of containing them.

A local God Object is not yet a Big Ball of Mud. It becomes critical when the boundaries themselves stop working.
Just Open Any Component
Section titled “Just Open Any Component”Back to the new project.
You click around the application for a while. Nothing scientific, no metrics. You simply want to see what a typical component looks like.
So you open one.
At the top begins the list of dependencies. User state. Navigation. Permissions. Cache. Dialog service. A domain service. Another domain service. Global state. Then something from another domain. Then something whose name you have never seen before but which apparently matters quite a lot.
That proves very little. A shell, a complex page component or an intentionally chosen orchestration point may legitimately have many dependencies.
So you open a second component. Then a third. At some point, the random observation turns into a pattern.
The more useful question is not:
How many dependencies does this component have?
It is:
If I open ten arbitrary components, do their dependencies mostly stay inside their own business area and intended layer?
If the answer is usually yes, you have probably found local outliers. If almost any component knows user state, navigation, global services and several foreign business areas, the observation becomes much more interesting.
Not because of the number of injections, but because local building blocks apparently require knowledge of the system as a whole.
The Innocently Named 5,000-Line Service
Section titled “The Innocently Named 5,000-Line Service”Then you meet cache.service.ts.
The name is reassuring at first. A cache. Familiar territory.
You open the file.
It does indeed contain caching. Among other things.
It also contains user state. Navigation logic. Some initialization. Several domain derivations. State transitions. Global communication. Perhaps permissions, plus a number of methods whose relationship to caching is mainly documented by the fact that they happen to live in cache.service.ts.
Five thousand lines later, you know at least one thing: caching is only one of its many occupations.
That still does not make the application a Big Ball of Mud. Large services are initially design problems. Perhaps the service can even be decomposed relatively cleanly.
More important is its fan-in: who depends on it?
When a historically grown service is consumed by more and more unrelated business areas, its role changes. It becomes a gravitational center of the system. Every new feature has an apparently reasonable excuse to use it as well: the service is already there, already has access to almost everything and is already injected everywhere.
That creates reinforcement.
At some point, the name describes only where the service started, not what it is responsible for now.
Such nodes are diagnostically much more interesting than their raw size. A 5,000-line service with three clearly bounded consumers is different from a 1,500-line service on which almost the entire application structurally depends.
The Base Class Almost Everything Extends
Section titled “The Base Class Almost Everything Extends”Elsewhere, the world looks surprisingly tidy.
Many components are small. A hundred lines. Sometimes less. Almost exemplary.
Then you notice one line:
extends BaseComponentYou open BaseComponent.
It contains navigation, user information, permissions, loading state, error handling, caches, several global services and perhaps a few domain helpers that apparently became too useful to remain in only one place.
Then you search for usages.
A hundred results.
The complexity was not removed. It was moved into a place that travels with almost everything.
Inheritance, of course, is not a Big-Ball-of-Mud clue by itself. A well-defined technical base class can be perfectly legitimate. It becomes problematic when it crosses technical and business boundaries at the same time and implicitly connects large parts of the system.
At that point, a local component loses an important property: its visible code no longer tells you reliably what it depends on or what behavior it inherits.
Visible structure and effective structure begin to diverge.
The First User Flow
Section titled “The First User Flow”Sooner or later, you stop looking at individual files and try to understand one complete flow.
Take something that sounds simple:
Login → initialization → navigation → first business view.
You start at login. From there you move into an authentication service, then global state, then an initialization service. A guard joins in. An interceptor as well. Somewhere a user is loaded; somewhere else permissions are assembled. Navigation depends on a custom abstraction, and before the first business view appears you have travelled through files whose existence you did not even know about two hours earlier.
At some point you stare at a service and ask yourself a surprisingly fundamental question:
Why exactly am I in this file?
That is funny when it happens occasionally. Real flows in large systems naturally cross several technical building blocks.
As a recurring pattern, however, it touches a central architectural property: locality of reasoning.
I use the term pragmatically here. The question is how much context you must hold at once in order to reason about something that appears local.
Parnas did not justify modularization merely as a way to produce nicer file trees. Good decomposition was meant, among other things, to improve comprehensibility and changeability by hiding relevant design decisions behind module boundaries.
Applied to a frontend, that means a substantial part of the rest of the system should not need to be relevant when you work on a small business capability.
A system becomes suspicious when small business questions repeatedly require system-wide understanding.
That is a much stronger signal than one huge file. This is no longer mainly about style or code cleanliness. It is about whether the architecture still limits the context required to reason safely.

Good architecture does more than organize files. It reduces the context a change requires.
When Business Boundaries Are Only Folder Names
Section titled “When Business Boundaries Are Only Folder Names”The file tree may even look excellent:
customers/orders/planning/schools/billing/users/administration/That is reassuring at first. Business slices exist.
Then you work in planning.
You find a direct dependency on schools. That makes business sense. The flow also needs users. Understandable as well.
Then administration joins in. And customers. A shared service from billing is also required. Somewhere else, schools imports back from planning, while users uses a type from customers.
Every individual connection may even have a plausible story.
That is exactly what makes diagnosis difficult.
Business areas obviously need to communicate. Total isolation would be neither realistic nor automatically good architecture. What matters is how communication happens. Are there defined integration points? Can dependency directions be explained? Is it clear which area owns information and which merely consumes it?
Or can essentially everyone know everyone else?
A business boundary that almost any area can cross arbitrarily eventually stops being a boundary. It becomes a folder name.
This is where the distinction between visible and effective architecture becomes important. The directory structure can continue to display customers, orders and billing. That tells you little about whether those areas actually hide information, constrain dependencies or shield changes from one another.
The file tree increasingly describes an aspiration. The dependency graph shows which boundaries still work in code.
Then the Layers Lose Their Meaning Too
Section titled “Then the Layers Lose Their Meaning Too”The same pattern can appear on a second axis.
Slices answer, at their core:
Who is responsible for what in the business?
Layers answer a different question:
What kind of responsibility is allowed to live here?
A structured frontend can use many different layer models. The important point is not whether they are literally called presentation, application, domain and infrastructure. What matters is that their meaning is repeatable and dependable.
In an eroding system, that reliability disappears.
Components load data, transform DTOs, make domain decisions, mutate global state, orchestrate processes, navigate and also keep their local UI state.
Services open dialogs, contain business rules, perform HTTP calls, manage caches and decide which view should appear next.
Infrastructure begins making business decisions. Presentation owns domain state transitions. Shared services contain a little of everything.
The problem is not that one component contains a rule that would be better elsewhere. Almost every real application contains such violations.
The pattern becomes relevant when the question
Where do our business rules live?
no longer has a useful answer.
If the answer is “it depends,” that is still normal.
If the answer is “basically everywhere,” things get more interesting.
If business rules can live practically anywhere, layering may still exist as a directory structure, but no longer as architecture.
Research on architecture erosion similarly does not treat erosion as merely visual messiness. Studies describe architectural violations, structural issues and problems in maintenance and evolution as related manifestations of the same phenomenon.

When slices no longer constrain dependencies and layers no longer constrain responsibilities, architecture eventually becomes little more than labels.
The Router That Is Not the Router
Section titled “The Router That Is Not the Router”Eventually, you want to understand navigation.
You search for the router.
You find something called Router.
Promising start.
Then you discover that actual navigation runs through a custom infrastructure. Routes have numerous properties. Some are obvious; others sound meaningful without revealing what they actually mean. Some affect permissions, some initialization, others the behavior of global state.
You look for documentation.
There is none.
But there is someone who has been on the project for nine years.
This is explicitly not proof of a Big Ball of Mud. A framework can be abstracted. Angular’s router can be wrapped. Under suitable requirements, a team may even build a completely custom navigation model.
The question, again, is whether the complexity remains bounded and explainable.
When central infrastructure depends on many domains, has system-wide side effects, cannot be understood reliably from code or documentation, and important rules mainly survive in the memory of individual people, several previously separate problems start to overlap.
The custom infrastructure is not the real signal.
The combination is.
The System’s Gravitational Centers
Section titled “The System’s Gravitational Centers”After a few weeks, you notice something else.
The tickets are completely different. One concerns user administration, another planning, then permissions, then a form change.
And yet you keep ending up in the same five files.
A global store. Two large services. One base class. A helper whose name probably dates from a time when it actually helped with one specific thing.
You can think of such structures as gravitational centers. They attract responsibility.
The mechanism is mundane. If a central service already knows users, navigation, permissions and several domain states, the next requirement is extremely convenient to place there as well. Almost everything you could need is already available.
Its fan-in grows further. Often its fan-out grows too, because the center needs to know more and more of the system in return.
By the next ticket, the decision is even easier:
“We’ll put it in the global service. The rest is already there.”
This is not a law of physics, and “black hole” is obviously not a software metric. As a metaphor, however, it describes a real reinforcing tendency: existing centrality makes further centralization locally attractive.
A hub is not automatically bad. Applications need intentionally central technical mechanisms. Logging, telemetry or certain infrastructure can legitimately have high fan-in.
A center becomes suspicious when its centrality comes not from one clear central responsibility, but from accumulating more and more unrelated responsibilities.
Eventually You Draw the Dependency Graph
Section titled “Eventually You Draw the Dependency Graph”Up to this point, much of the evidence comes from experience and observation.
Eventually that is not enough.
Perhaps you want to know whether you have simply been unlucky enough to land in the ugliest corners. Perhaps you want to verify whether the supposed slices actually exist structurally. Perhaps you simply want to know whether the diffuse feeling has a technical basis.
So you analyze imports and dependencies.
The initial hope is straightforward: the graph should reveal business clusters. There may be a few central technical components and a handful of undesirable cross-links, but fundamentally the structures from the architecture diagram should still be recognizable.
Sometimes that is exactly what happens.
And sometimes something else happens.
You see countless cross-slice dependencies. Arrows run in both directions. Nodes with extreme fan-in connect large parts of the system. Others have enormous fan-out. Cycles appear between supposedly independent areas. Several cycles merge into large strongly connected components.
In a directed dependency graph, a strongly connected component groups nodes that are mutually reachable through directed paths. For software dependencies, a large SCC therefore means that, on this level, the contained parts can no longer be cleanly ordered in an acyclic direction. Research and tools for dependency analysis use SCCs as a useful structural unit for precisely that reason — not as an automatic Big-Ball-of-Mud diagnosis.
One cycle is not a Big Ball of Mud.
Ten cycles are not automatically one either.
It becomes much more interesting when a substantial part of the system is contained in large cyclic structures, when those cycles cut across slice boundaries and when the same nodes also appear as global gravitational centers.
Sangal, Jordan, Sinha and Jackson showed in 2005 how statically extracted dependencies can be used to expose the real structure of large systems and compare it with explicit architecture rules. That is the diagnostic value of such models: the diagram itself is not architecture, but it can reveal whether the boundaries claimed by the architecture still exist in code.
And when weighted dependency lines eventually merge into a dark mass, the name “Big Ball of Mud” gains a surprising visual plausibility.
That last sentence is only a joke, of course. The historical term was not coined because of dependency diagrams.
Do Changes Stay Where They Belong?
Section titled “Do Changes Stay Where They Belong?”Dependency graphs show static structure. Everyday development gives you a second perspective.
You receive a ticket:
“Additional validation in Planning.”
Sounds local.
You change something in Planning. Then a global service needs to change. Then a shared base class. Then you discover that another business area indirectly uses the same state. To be safe, you test three other flows because you cannot confidently predict which side effects the global mechanism has.
That can happen. Some requirements are broader than the ticket initially suggests.
Again, repetition is what matters.
How closely does the business change radius match the technical change radius?
If a local business requirement can usually be implemented locally in the code, the system’s boundaries are doing useful work.
If small business changes repeatedly require modifications or broad regression checks across distant areas, the system loses locality of change.
The less the business change radius matches the technical change radius, the more interesting the diagnosis becomes.
You do not have to rely only on static imports to examine this. Gall, Hajek and Jazayeri investigated logical or evolutionary coupling in the late 1990s: modules may appear structurally separate and still repeatedly change together over time. Recurring co-changes across module or subsystem boundaries can reveal hidden dependencies and questionable decomposition.
That is particularly relevant for a possible Big Ball of Mud. Perhaps orders and customers still look reasonably separate in a dependency graph. If changes to one have forced changes in the other for years, version history tells an additional story.
Architecture is visible not only in how code is arranged.
It is also visible in how code is able to change.
Who Owns This, Exactly?
Section titled “Who Owns This, Exactly?”After technical structure comes a surprisingly simple question:
Who is responsible for it?
For the Planning slice? For global state? For the cache service? For the base class? For navigation? For the business rule that exists in five places?
The answers vary:
“Everyone, somehow.”
“Historical reasons.”
“You need to ask X.”
“No one, really.”
Or the classic:
“Better not touch that.”
Ownership is not merely an org-chart concept. Even when teams are not formally assigned to modules, a system can express ownership structurally.
If I search for a business rule, can I infer which area should own it? If state changes, is there a recognizable place that controls that decision? If a module exposes an interface, is it clear what it promises to the outside and what remains internal?
In a strongly unbounded system, not only code but responsibility becomes diffuse.
That reinforces the problem: when no one can say who owns a decision, defending a boundary consistently becomes difficult.
Research on architecture erosion likewise shows that causes are not purely technical. Organizational factors, knowledge, development practices and long-term architecture maintenance matter alongside technical violations.
Architecture Should Make a System More Predictable
Section titled “Architecture Should Make a System More Predictable”At this point, it is worth stepping back.
Why do slices, layers, dependency directions and ownership matter at all?
Not because architecture diagrams look nice.
Architecture reduces the possible solution and search space.
If I know that the business rules of an area live in its domain, I do not need to search arbitrary components, HTTP services and shared helpers.
If I know billing must not directly depend on planning, I can rule out entire paths.
If I know presentation talks to a slice only through a defined application interface, I do not need to understand all of its infrastructure for a UI change.
Good structure therefore produces predictability over time.
You open an unfamiliar area and have a reasonable idea of what to expect. You do not know the code yet, but you know the rules of the game.
That is why onboarding is diagnostically interesting. A complex but well-structured system can be overwhelming at first. As your knowledge grows, however, your mental model should compress: many individual observations can be explained by a smaller number of stable rules.
In a Big Ball of Mud, the learning curve can move in the opposite direction.
You know more and more details, but you can infer less and less from them.
From a Feeling to a Diagnosis
Section titled “From a Feeling to a Diagnosis”Hardly anyone begins their first week in a project with architecture forensics.
It starts with small irritations:
“Why does this depend on that?”
Then:
“Why am I in this file?”
Later:
“Why does everyone know this service?”
And eventually:
“Why does everyone know everyone?”
The feeling is a useful starting point. It is not a sufficient result.
That is why it helps to combine several perspectives:
- visible dependencies,
- actual change patterns,
- slice boundaries,
- layer boundaries,
- gravitational centers,
- reasoning radius,
- change radius,
- ownership.
Only when several of them tell the same story does irritation become a structural suspicion.

Suspicion often starts with a feeling. Diagnosis should not end with one.
Not Every Symptom Carries the Same Weight
Section titled “Not Every Symptom Carries the Same Weight”That leaves the uncomfortable question: which of these observations is actually a strong clue?
There is no scientifically validated Big-Ball-of-Mud scale. The weighting below is therefore deliberately an architecture heuristic, not a diagnostic threshold.
Weak or Local Clues
Section titled “Weak or Local Clues”By themselves, these observations say surprisingly little:
- one very large component,
- a God Service,
- a problematic base class,
- missing layering inside one isolated feature,
- individual dependency cycles,
- outdated framework patterns,
- custom infrastructure,
- a difficult business domain.
Every item on this list can represent a serious architecture problem. The decisive question is: does the problem still have a boundary?
The planning feature from the beginning can be terribly structured while still living inside a functioning business slice. A globally used technical service can have high centrality and still perform one precise responsibility.
Clearly Stronger Clues
Section titled “Clearly Stronger Clues”Things become more interesting when the same problems recur across boundaries:
- the same pattern appears in many business slices,
- components systematically reach into several foreign domains,
- business rules can live practically anywhere,
- central services are used by large parts of the application while accumulating unrelated responsibilities,
- cross-slice dependencies no longer have a recognizable direction,
- small changes repeatedly require knowledge of distant parts of the system,
- architecture rules have so many accepted exceptions that they lose predictive value,
- the architecture diagram and actual dependencies tell different stories.
At this point the diagnosis shifts from a local design problem toward the structure of the system as a whole.
Very Strong Clues
Section titled “Very Strong Clues”It becomes especially serious when several fundamental mechanisms of order fail at the same time:
- large parts of the application sit inside common dependency cycles or strongly connected components,
- business boundaries have little technical effect,
- layers no longer have reliable meaning,
- ownership of central areas cannot be identified sensibly, organizationally or structurally,
- small changes regularly have unexpected system-wide consequences,
- new developers learn more and more special cases over time but still fail to develop a stable mental model,
- several of these effects occur together and reinforce one another.
The important point is the combination.
One large SCC is not a mathematical definition of a Big Ball of Mud. High fan-in is not one. A high change rate is not one. Ten layer violations are not one.
There is therefore no serious rule such as:
Five symptoms means you have a Big Ball of Mud.
A Big Ball of Mud is a system state, not a single metric.
What I Am Actually Looking For in a Diagnosis
Section titled “What I Am Actually Looking For in a Diagnosis”If I had to examine an unfamiliar frontend today, I would not start by asking which bad patterns I can find.
You can almost always find some.
I would try to determine whether the most important forms of structural containment still work.
Do business slices constrain dependencies? Not absolutely, but enough that integration points and directions remain understandable?
Do layers constrain responsibilities? Can I reasonably predict where business rules, UI state, orchestration and infrastructure live?
Do dependencies have a recognizable direction? Or do large mutually dependent spaces emerge?
Does reasoning remain local? How much of the application do I need to understand to explain a small business flow?
Do changes remain local? How often does a local ticket force me into distant business areas?
Are central building blocks central because their responsibility is central? Or are they simply historical collection points for whatever was convenient to put there?
Can I recognize ownership? Is it clear who owns a decision and which other parts merely consume it?
And finally:
Does the visible architecture still explain the real software?
That may be the most important question of all.
A system does not need to be perfect in order to have architecture. It may contain legacy code. It may contain ugly features, transitional solutions, historical compromises and technical debt.
As long as its boundaries still mean something, there is a basis for reasoning.
A Big Ball of Mud starts where fewer and fewer possibilities can be ruled out.
Any responsibility might live anywhere. Any area might depend on any other. Any change might unexpectedly affect some distant place. And every rule needs to be followed immediately by:
“Except, of course, …”
Do I Have a Big Ball of Mud?
Section titled “Do I Have a Big Ball of Mud?”You may have recognized your own project in an uncomfortable number of places by now. Individual symptoms are still not enough to diagnose a Big Ball of Mud. If you want to weigh these observations a little more systematically, there is a small architecture self-check for that.
Do I Have a Big Ball of Mud? →
Does the System Become Easier to Understand Over Time?
Section titled “Does the System Become Easier to Understand Over Time?”In the end, we return to your first day in the project.
You join a large system and initially understand nothing.
That is normal.
In a structured, complex system, this changes over time. You learn the domain. You recognize responsibilities. You understand boundaries and dependency directions. Many individual files slowly turn into a model.
That model makes unfamiliar parts of the system more predictable.
You may not know a component yet, but you can estimate which responsibilities it is likely allowed to have. You may never have changed a slice, but you have a reasonable idea where its business rules should live. You see a dependency and can explain why its direction makes sense.
Your knowledge grows, while the amount of mental context you need becomes smaller.
In a Big Ball of Mud, the opposite can happen.
After a few months, you know an astonishing number of details. You know method A must run before method B. You know the three special cases in the global cache. You know why one particular navigation must never be triggered directly. You know which person can explain why BaseComponent owns that one piece of business state.
You know more than you did on day one.
But it does not add up to a reliable model.
You therefore do not recognize a Big Ball of Mud merely because there is a 5,000-line file somewhere, because someone uses the framework strangely, or because one feature is poorly structured. Those problems can be serious while still having a recognizable boundary.
A system becomes suspicious when those boundaries themselves disappear.
In a frontend, a Big Ball of Mud is most clearly visible in the interaction of several forms of structural boundary loss: business slices no longer constrain dependencies, layers no longer constrain responsibilities, changes no longer stay local, central building blocks accumulate more and more unrelated duties, dependency direction disappears, and ownership becomes increasingly difficult to identify.
At that point, the real problem is no longer one bad component, one God Service or one wrong import.
The problem is that the architecture can rule out fewer and fewer possibilities with confidence.
And if, after months, you know a great deal about a system but still cannot reliably say where a responsibility begins, where it ends and whom it is allowed to know, you probably do not merely have an onboarding problem.
Sources and Further Reading
Section titled “Sources and Further Reading”- Brian Foote, Joseph W. Yoder: Big Ball of Mud. Technical Report WUCS-97-34, 1997; later Chapter 29 in Neil Harrison, Brian Foote, Hans Rohnert (eds.): Pattern Languages of Program Design 4. Addison-Wesley, 2000.
- Ruiyin Li, Peng Liang, Mohamed Soliman, Paris Avgeriou: Understanding Software Architecture Erosion: A Systematic Mapping Study. Journal of Software: Evolution and Process 34(3), 2022, e2423. DOI:
10.1002/smr.2423. - Ruiyin Li, Peng Liang, Mohamed Soliman, Paris Avgeriou: Understanding Architecture Erosion: The Practitioners’ Perceptive. Proceedings of the 29th IEEE/ACM International Conference on Program Comprehension (ICPC), 2021, pp. 24–35. DOI:
10.1109/ICPC52881.2021.00037. - David L. Parnas: On the Criteria To Be Used in Decomposing Systems into Modules. Communications of the ACM 15(12), 1972, pp. 1053–1058. DOI:
10.1145/361598.361623. - Harald Gall, Karin Hajek, Mehdi Jazayeri: Detection of Logical Coupling Based on Product Release History. Proceedings of the International Conference on Software Maintenance (ICSM), 1998, pp. 190–197. DOI:
10.1109/ICSM.1998.738508. - Neeraj Sangal, Ev Jordan, Vineet Sinha, Daniel Jackson: Using Dependency Models to Manage Complex Software Architecture. OOPSLA 2005, pp. 167–176. DOI:
10.1145/1094811.1094824.