MS in Data Science Dissertation · Liverpool John Moores University

Code Smells: Microservices vs. Monoliths

A natural-experiment static analysis comparing 754 monolith versions with modern microservices repositories to assess whether architectural decomposition inherently guarantees cleaner software.

Dr. Amit Puri
Dr. Amit Puri
Master of Science (MS) in Data Science (LJMU) · Enterprise Cloud & AI Architect
Liverpool John Moores University Qualitas Corpus Baseline Designite Multi-Metric Pipeline DOI: 10.13140/RG.2.2.21689.65126
Monolith Baseline
754 Monolith Versions 112 systems in Qualitas Corpus analyzed longitudinally across release lifecycles
Structural Shift
~80% Coupling Smell Drop Sharp collapse in encapsulation flaws, cyclic dependencies, & broken hierarchies
Cloud Repos
18 Repos Microservices Corpus Curated Java & C# repos evaluated with Dockerfiles & YAML manifests
Debt Compounding
16×–17× Aging Amplification Longitudinal tracking proved non-linear smell amplification vs LOC growth

01. Executive Summary & Core Insight

Software rarely fails outright when it is poorly built—it simply becomes progressively harder, riskier, and exponentially more expensive to change.

Organizations routinely invest millions rewriting legacy monolithic applications into distributed microservices architectures with the implicit assumption that "modern" architecture automatically produces "cleaner, maintainable" code. This empirical study by Dr. Amit Puri, conducted for his MS in Data Science at Liverpool John Moores University (LJMU), treats the monolith-to-microservices migration as a controlled natural experiment to test that foundational assumption.

The Definitive Empirical Takeaway

Microservices decomposition successfully eliminates structural "God-Class" pathologies (plummeting encapsulation flaws, cyclic coupling, and broken inheritance by ~80%). However, it does not fix developer discipline: cognitive smells like Unutilised Abstraction surged by 117% (191 → 416) and Long Statements rose from 318 to 385, while Magic Numbers remained virtually identical.

02. Research Problem & Guiding Questions

Prior academic software engineering research frequently studied monoliths and microservices as isolated domains using disparate metric definitions. This left a crucial empirical void: no direct, metric-calibrated side-by-side comparison using a unified static analysis pipeline across both paradigms.

This study formulates four anchoring research questions:

RQ1: Quality Degradation During Migration

Does software quality actually degrade as organizations invest in cloud modernization and architectural rewrites?

RQ2: High-Sensitivity Metric Shifts

Which specific code-level and architectural metrics shift most dramatically when moving from monoliths to microservices?

RQ3: Friction as a Driver for Low-Code

Does the frictional overhead, cognitive load, and operational churn of microservices rewrites nudge enterprises toward No-Code/Low-Code platforms?

RQ4: Metric Evidence for Platform Adoption

Which code maintainability and complexity metrics quantitatively make the business case for adopting low-code platforms over custom microservices?

03. The 11 Microservices Bad Smells Taxonomy

In monolithic systems, code smells reside comfortably within package boundaries. In distributed microservices architectures, smells metastasize across network boundaries, becoming dramatically harder to detect with conventional class-level linters.

The research synthesizes the literature into the definitive 11 Microservices Bad Smells Taxonomy:

1. Wrong Service Cuts

Services sliced along horizontal technical tiers (UI, Logic, DB) rather than bounded business domains, causing chatty distributed anti-patterns.

2. Hard-Coded Endpoints

Services directly addressing physical IP or DNS addresses without dynamic service discovery, DNS rotation, or load balancing.

3. Cyclic Service Dependencies

Circular invocation loops across services (Service A → Service B → Service C → Service A), introducing severe distributed deadlock risks.

4. Shared Persistence

Multiple supposedly autonomous microservices reading and mutating the exact same relational database tables, breaking data encapsulation.

5. Greedy / Mega Services

A single oversized service masquerading within a microservices cluster, consuming disproportionate compute and business logic.

6. Missing API Gateways

External client apps directly invoking internal microservices without rate-limiting, SSL termination, or centralized authentication.

7. Excessive Protocol Standards

Uncontrolled sprawl of disparate communication protocols (gRPC, REST, SOAP, WebSockets) across the same service mesh.

8. API Versioning Pitfalls

Breaking contract changes deployed without backward compatibility, requiring high-friction synchronized lock-step releases.

9. Inappropriate Service Intimacy

Services bypassing public API endpoints to access internal private classes, caches, or shared storage abstractions directly.

10. Shared Distributed Libraries

Coupling all microservices to a monolithic shared utility JAR/DLL, causing upstream dependency lockouts upon every minor patch.

11. ESB Overuse & "Smart Pipes"

Burying business logic and transformation pipelines inside enterprise service buses rather than keeping endpoints smart and pipes dumb.

04. Empirical Methodology & Extraction Pipeline

The study deployed a comparative analytics pipeline using standardized static analysis across two complementary datasets:

Dataset / Dimension Composition & Repositories Analysis Tooling & Thresholds
Monolith Baseline: Qualitas Corpus 12 benchmark Java monoliths selected from the Qualitas Corpus (112 systems, 754 versions) ranked by GitHub stars and LOC: Hibernate, Spring, Tomcat, Derby, Lucene, ANTLR, Apache Ant. Designite static quality analyzer:
• Method LOC > 100
• Cyclomatic Complexity > 8
• Class LOC > 1000
• LCOM (Lack of Cohesion) > 0.8
• Fan-in / Fan-out > 20
Microservices Corpus 18 curated open-source Java & C# microservices repositories, evaluated alongside their Dockerfiles and Kubernetes YAML manifests as first-class architectural artifacts. cloc/sloc for line counts, custom R statistical scripts (process-cs-data.R, curate-data.R, analyze-data-func.R), and automated shell extractors.
Key Data Handling Decisions

Magic Number appeared ~182,000 times across monoliths and was isolated from the primary comparative index to avoid swamping fine-grained structural signals. Conversely, Unutilised/Unnecessary Abstraction (~136,000 occurrences) was intentionally preserved because it served as the most decisive indicator of speculative over-engineering in microservices.

05. Longitudinal Aging & Compounding Technical Debt

Tracking projects across historical release cycles revealed that technical debt does not accumulate linearly with code size—it compounds exponentially:

Project & Version Window Codebase Size Shift Observed Code Smell Trajectory Architectural Takeaway
Apache Ant
(v1.1 → v1.2 → v1.8.4)
~6× LOC expansion over lifecycle • Unutilised Abstraction: 67 → 135
• Broken Hierarchy: 13 → 41
• Deficient Encapsulation: 16× Jump
• Long Parameter Lists: 17× Jump
Technical debt is non-linear. As legacy monoliths age without dedicated refactoring budgets, structural smells compound at nearly triple the rate of LOC growth.
ANTLR
(v2.4.0 → v4.0)
Major architectural rewrite • Complex Method: 127 → 80 (Refactored)
• Long Statement: 46 → 318 (Spiked)
Deliberate architectural refactoring successfully reduced method complexity, but introduced long method chaining and statement sprawl.
Microsoft PowerToys
(Modern Monolith ~57 KLOC)
Modern C# / C++ codebase • Complex Method: Low (Double digits)
• Long Method: Low
Monoliths are not inherently bad. Modern monoliths equipped with rigorous CI/CD static linters maintain exceptionally clean profiles without microservice complexity.

06. The Quantitative Comparison: Monoliths vs. Microservices

When the monolithic benchmark dataset is compared directly against the microservices corpus, code smells divide into three unambiguous behavioral categories:

Code Smell Metric Monolith Baseline Microservices Corpus Empirical Variance Architectural Diagnosis
Deficient Encapsulation 187 37 - 80.2% Drop Smaller service cuts naturally limit public class and field leakage.
Cyclic-Dependent Modularisation 146 31 - 78.8% Drop Service boundaries force decoupled compilation units.
Broken Hierarchy 168 39 - 76.8% Drop Microservices favor composition over deep inheritance trees.
Complex Method (CC > 8) 80 11 - 86.3% Drop Focused endpoint handlers curtail multi-branch method sprawl.
Unutilised Abstraction 191 416 + 117.8% Surge Over-engineering: generic interfaces created for single implementations.
Long Statement (> 100 chars) 318 385 + 21.1% Increase Fluent builders, stream pipelines, and inline serialization chaining.
Magic Number 267 226 ~ Flat (Neutral) Architecture-neutral smell driven purely by individual developer habit.

07. The Infrastructure Dimension: Docker & Kubernetes Smells

A major contribution of this research was treating Infrastructure-as-Code (IaC) as code. While monoliths have minimal infrastructure definitions, microservices rely heavily on Dockerfiles, Helm charts, and Kubernetes YAML manifests.

Dockerfile Smells

Unpinned base image tags (:latest), bloated image layers without multi-stage builds, running containers as root, and un-cached package installations.

  • Root user execution
  • Unpinned apt/npm dependencies

Kubernetes YAML Smells

Missing CPU/memory resource limits, absent readiness/liveness probes, hardcoded plaintext secrets, and unconfigured pod disruption budgets (PDBs).

  • OOMKill risks from missing limits
  • Missing health check probes

08. The Bridge to Low-Code & Citizen Development

Under RQ3 & RQ4, the research investigates why so many enterprise microservices migrations end in cognitive fatigue:

The Cognitive Tax of Distributed Systems

Building and operating 50+ microservices requires managing distributed tracing, circuit breakers, service meshes, Kafka topologies, and container orchestration. For standard business CRUD applications, this massive cognitive tax yields negative ROI. This frictional overhead is the exact catalyst driving enterprises toward Low-Code / No-Code platforms (Power Platform, AppSheet, OutSystems), which abstract distributed plumbing while exposing clean API contracts.

09. Actionable Guidelines for Architects & CI/CD Linters

Never assume decomposing into microservices buys cleaner code. Configure your automated CI/CD static analysis pipelines with these calibrated rules:

recommended-sonarqube-rules.json JSON
{
  "rules": [
    {
      "key": "UnutilisedAbstraction",
      "severity": "BLOCKER",
      "description": "Fail build if interface has only one concrete implementation without extension rationale"
    },
    {
      "key": "MaxStatementLength",
      "threshold": 100,
      "severity": "MAJOR",
      "description": "Prevent unreadable fluent chaining in stream operations"
    },
    {
      "key": "SharedPersistenceBan",
      "severity": "CRITICAL",
      "description": "Disallow cross-service direct SQL schema queries"
    }
  ]
}
  • Target Unutilised Abstractions: Fail builds when interfaces or abstract base classes have only a single concrete implementation without an immediate extensibility rationale.
  • Enforce Statement Length Limits: Restrict chained fluent statements and long stream filters to prevent unreadable, bug-prone one-liners.
  • Mandate IaC Static Analysis: Integrate tools like Hadolint for Dockerfiles and Kubeconform / Checkov for Kubernetes manifests directly into the commit pipeline.
  • Enforce Shared Persistence Bans: Automated architectural linter checks must ensure no microservice can access another service's private database tables directly.

10. Academic Citation & Public Access

To cite this comparative empirical research in academic literature or industry reports, use:

Puri, A. (2021). Study trends in code smell in microservices-based architecture, Compare with monoliths. Master's Dissertation (MS in Data Science), Liverpool John Moores University. DOI: 10.13140/RG.2.2.21689.65126

Research Gate Publication

Access the official paper, citation metrics, and peer discussions on ResearchGate.

View DOI Citation

Companion Doctoral Study

Explore the complementary doctoral research (Doctorate in Business Administration with specialization in Data Science) on Cloud Transformation Challenges & Low-Code platforms.

Read LCNC Research