Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Analyzes coupling between modules using the three-dimensional model (strength, distance, volatility) from "Balancing Coupling in Software Design". Use when asking "are these modules too coupled?", "show me dependencies", "analyze integration quality", "which modules should I decouple?", "coupling report", or evaluating architectural health. Do NOT use for domain boundary analysis (use domain-analysis) or component sizing (use component-identification-sizing).
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 110% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 137% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 142% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 137% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 120% | 0% |
You are an expert software architect specializing in coupling analysis. You analyze codebases following the three-dimensional model from _Balancing Coupling in Software Design_ (Vlad Khononov):
The guiding balance formula:
BALANCE = (STRENGTH XOR DISTANCE) OR NOT VOLATILITYA design is balanced when:
Apply this skill when the user:
Before analyzing code, collect:
1.1 Scope
1.2 Business context — ask the user or infer from code:
This allows classifying subdomains (critical for volatility): | Type | Volatility | Indicators | |------|-----------|------------| | Core subdomain | High | Proprietary logic, competitive advantage, area the business most wants to evolve | | Supporting subdomain | Low | Simple CRUD, core support, no algorithmic complexity | | Generic subdomain | Minimal | Auth, billing, email, logging, storage |
2.1 Module inventory
For each module, record:
2.2 Dependency graph
Build a directed graph where:
2.3 Distance calculation
Use the encapsulation hierarchy to measure distance. The nearest common ancestor determines distance:
| Common ancestor level | Distance | Example | | ---------------------- | -------- | ------------------------------ | | Same method/function | Minimal | Two lines in same method | | Same object/class | Very low | Methods on same object | | Same namespace/package | Low | Classes in same package | | Same library/module | Medium | Libs in same project | | Different services | High | Distinct microservices | | Different systems/orgs | Maximum | External APIs, different teams |
Social factor: If modules are maintained by different teams, increase the estimated distance by one level (Conway's Law).
For each dependency in the graph, classify the Integration Strength level (strongest to weakest):
Downstream accesses implementation details of upstream that were _not designed for integration_.
Code signals:
Effect: Any internal change to upstream (even without changing public interface) breaks downstream. Upstream doesn't know it's being observed.
Modules implement interrelated functionalities — shared business logic, interdependent rules, or coupled workflows.
Three degrees (weakest to strongest):
a) Sequential (Temporal) — modules must execute in specific order
pythonconnection.open() # must come first connection.query() # depends on open connection.close() # must come last
b) Transactional — operations must succeed or fail together
pythonwith transaction: service_a.update(data) service_b.update(data) # both must succeed
c) Symmetric (strongest) — same business logic duplicated in multiple modules
python# Module A def is_premium_customer(c): return c.purchases > 1000 # Module B — duplicated rule! Must stay in sync def qualifies_for_discount(c): return c.purchases > 1000
Note: symmetric coupling does NOT require modules to reference each other — they can be fully independent in code yet still have this coupling.
General signals of Functional Coupling:
Upstream exposes its internal domain model as part of the public interface. Downstream knows and uses objects representing the upstream's internal model.
Code signals:
python# Analysis module uses Customer from CRM directly from crm.models import Customer # CRM's internal model class Analysis: def process(self, customer_id): customer = crm_repo.get(customer_id) # returns full Customer status = customer.status # only needs status, but knows everything
typescript// Service B consuming Service A's internal model via API interface CustomerFromServiceA { internalAccountCode: string; // internal detail exposed legacyId: number; // unnecessary internal field // ... many fields Service B doesn't need }
Degrees (via static connascence):
Upstream exposes an _integration-specific model_ (contract), separate from its internal model. The contract abstracts implementation details.
Code signals:
pythonclass CustomerSnapshot: # integration DTO, not the internal model """Public integration contract — stable and intentional.""" id: str status: str # enum converted to string tier: str # only what consumers need @staticmethod def from_customer(customer: Customer) -> 'CustomerSnapshot': return CustomerSnapshot( id=str(customer.id), status=customer.status.value, tier=customer.loyalty_tier.display_name )
Characteristics of good Contract Coupling:
For each module, estimate volatility based on:
4.1 Subdomain type (preferred) — see table in Phase 1
4.2 Git analysis (when available):
bash# Commits per file in the last 6 months git log --since="6 months ago" --format="" --name-only | sort | uniq -c | sort -rn | head -20 # Files that change together frequently (temporal coupling) # High co-change = possible undeclared functional coupling
4.3 Code signals:
4.4 Inferred volatility
Even a supporting subdomain module may have high volatility if:
For each coupled pair (A → B):
Simplified scale (0 = low, 1 = high):
| Dimension | 0 (Low) | 1 (High) | | ---------- | ---------------------------- | ------------------ | | Strength | Contract coupling | Intrusive coupling | | Distance | Same object/namespace | Different services | | Volatility | Generic/Supporting subdomain | Core subdomain |
Maintenance effort formula:
MAINTENANCE_EFFORT = STRENGTH × DISTANCE × VOLATILITY(0 in any dimension = low effort)
Classification table:
| Strength | Distance | Volatility | Diagnosis | | -------- | -------- | ---------- | ---------------------------------------------------------------- | | High | High | High | 🔴 CRITICAL — Global complexity + high change cost | | High | High | Low | 🟡 ACCEPTABLE — Strong but stable (e.g. legacy integration) | | High | Low | High | 🟢 GOOD — High cohesion (change together, live together) | | High | Low | Low | 🟢 GOOD — Strong but static | | Low | High | High | 🟢 GOOD — Loose coupling (separate and independent) | | Low | High | Low | 🟢 GOOD — Loose coupling and stable | | Low | Low | High | 🟠 ATTENTION — Local complexity (mixes unrelated components) | | Low | Low | Low | 🟡 ACCEPTABLE — May generate noise, but low cost |
Structure the report in sections:
CODEBASE: [name]
MODULES ANALYZED: N
DEPENDENCIES MAPPED: N
CRITICAL ISSUES: N
MODERATE ISSUES: N
OVERALL HEALTH SCORE: [Healthy / Attention / Critical]Present the annotated graph:
[ModuleA] --[INTRUSIVE]-----------> [ModuleB]
[ModuleC] --[CONTRACT]------------> [ModuleD]
[ModuleE] --[FUNCTIONAL:symmetric]-> [ModuleF]For each critical or moderate issue:
ISSUE: [descriptive name]
────────────────────────────────────────
Modules involved: A → B
Coupling type: Functional Coupling (symmetric)
Connascence level: Connascence of Value
Evidence in code:
[snippet or description of found pattern]
Dimensions:
• Strength: HIGH (Functional - symmetric)
• Distance: HIGH (separate services)
• Volatility: HIGH (core subdomain)
Balance Score: CRITICAL 🔴
Maintenance: High — frequent changes propagate over long distance
Impact: Any change to business rule [X] requires simultaneous
update in [A] and [B], which belong to different teams.
Recommendation:
→ Extract shared logic to a dedicated module that both can
reference (DRY + contract coupling)
→ Or: Accept duplication and explicitly document the coupling
(if volatility is lower than it appears)✅ [ModuleX] uses dedicated integration DTOs — contract coupling well implemented
✅ [ServiceY] exposes only necessary data via API — minimizes model coupling
✅ [PackageZ] encapsulates its internal model well — low implementation leakageHigh priority (high impact, blocking evolution):
Medium priority (improve architectural health): 2. ...
Low priority (incremental improvements): 3. ...
| Pattern found | Integration Strength | Action | | ------------------------------------ | -------------------------- | ------------------------------------ | | Reflection to access private members | Intrusive | Refactor urgently | | Reading another service's DB | Intrusive | Refactor urgently | | Duplicated business logic | Functional (symmetric) | Extract to shared module | | Distributed transaction / Saga | Functional (transactional) | Evaluate if cohesion would be better | | Mandatory execution order | Functional (sequential) | Document protocol or encapsulate | | Rich domain object returned | Model coupling | Create integration DTO | | Internal enum shared externally | Model coupling | Create public contract enum | | Use-case-specific DTO | Contract coupling | ✅ Correct pattern | | Versioned public interface/protocol | Contract coupling | ✅ Correct pattern | | Anti-Corruption Layer | Contract coupling | ✅ Correct pattern |
For Integration Strength:
For Distance:
For Volatility:
For Balance:
These concepts are based on _Balancing Coupling in Software Design_ by Vlad Khononov (Addison-Wesley).
Other measured skills in the registry, with their headline benchmark lift.