robsonkades/agent-skills/java-law-of-demeter
- community
Checking that the SKILL.md file is still in the repository.
Navigation coupling: what the Law of Demeter actually constrains — structure exposure, not dot-counting — and how to tell a train wreck from a legitimate chain. Use when reviewing chains like order.getCustomer().getAddress().getCity(), when a change to one class's shape rippled through files that never mention it, when deciding whether a chain couples the caller to structure or merely reads data, or when a proposed fix would add forwarding methods to every intermediate class. Does not cover designing fluent chains (java-fluent-apis) or where the decision made on the navigated data should live (java-tell-dont-ask).
Install
npx vskill@latest install robsonkades/agent-skills/java-law-of-demeterSKILL.md
Java Law of Demeter
Purpose
The law is a coupling rule, not a dot budget: a method talks to its immediate collaborators — this, its parameters, objects it creates, its own fields. order.getCustomer().getAddress().getCity() couples the caller to the shape of three classes; reorganising any of them breaks code that had no business knowing them. This skill exists to catch that coupling, and equally to stop the dogmatic fix — forwarding methods smeared across every intermediate class — which trades one chain for a Middle Man on each link and is often worse than the chain.
Workflow
- Inspect target and call-path evidence. Check compiler release/toolchains, declared
contracts, null/empty behavior, runtime proxy/ORM types and policy ownership. Worked code fits Java 17 (records require Java 16+ without preview); List.getFirst() in the detection reference requires Java 21+. Adapt examples without upgrading or enabling preview. If only source is available, separate observed navigation from hypotheses about runtime I/O.
- Classify the chain. Fluent calls on one conceptual receiver and Stream/Optional dataflow
are not structural navigation by themselves (callbacks still may navigate). Walking an intentional record/DTO value schema is schema coupling; a data carrier can also contain a live entity or client, so classify each hop's contract. The suspect case walks _distinct collaborators' private composition_. Read references/detection.md when the classification is not obvious.
- Ask what the caller does with the result. If it decides or mutates, check whether it already
owns that policy and authorized operation. Move only a misplaced decision to its actual owner, which is not necessarily the data class. The placement decision is java-tell-dont-ask's. Only reads a value → consider a stable projection/snapshot or narrowing what is passed.
- Price the fix against the chain. Count the forwarding methods it would add and the
classes it would touch. A getCustomerCity() on Order added solely to shorten a call provides no boundary benefit; one caller can still justify a stable owned query.
- Treat boundary navigation deliberately. Mappers, serialisers, reports and assertions
may legitimately publish/inspect shape; still check invariants, nulls, consistency and I/O.
- Verify with caller contract tests and a representative intermediate-shape change.
Imports are clues: inferred types and fully qualified calls can hide edges. Check generated code/bytecode dependencies when needed, and query/trace evidence for runtime claims.
Rules
- Judge chains by exposure, not length:
list.stream().filter(p).toList()is dataflow;
inspect p separately for navigation. a.getB().getC() couples the caller to both shapes. Splitting it into local variables or passing getB() into a helper does not by itself remove that knowledge. Trace where each receiver came from and which caller still assembles it.
- A chain is coupling when the caller could not do its job without knowing how the
intermediate objects are composed. Intentional access to a published data schema is a different review question; the record keyword or a DTO name alone cannot establish that role.
- Fix priority: place behavior with the module that owns its policy and required data; otherwise pass the
needed value instead of its container; wrap only when a real abstraction boundary exists, never to launder a chain.
- Do not add a forwarding method merely to reduce dots. Even one caller can justify a query that
protects a real aggregate/module boundary or names stable domain meaning; demonstrate what internal shape can now change independently.
- Navigation at an orchestration point can be appropriate when that point owns assembly and
honors aggregate/consistency boundaries. Repetition raises change cost; one occurrence can still leak an invariant or trigger unwanted I/O.
- Accessors over a record's published data schema are not violations merely because they
form a chain. Query, reporting and mapping code can navigate structure legitimately; navigation from a record component into a live collaborator still needs its own assessment.
- Chains that mix navigation with mutation (
getX().getY().setZ(...)) warrant checking both
exposed composition and invariant enforcement. A published collaborator's authorized command may be legitimate; a raw setter bypassing the owner is a different contract. Hand misplaced decision/enforcement work to java-tell-dont-ask.
Runtime consequences
- A harmless-looking chain over ORM entities can trigger lazy loads, N+1 queries, a closed-
session failure or inconsistent reads between hops. Inspect available mapping, initialization, transaction and query evidence before concluding which occurs or violates the intended boundary. Diagnose observed fetch/round-trip cost with orm-fetch-and-batching-performance, not by adding getters.
- Distinguish remote/proxy dispatch from local access to an already returned value. When repeated
remote calls cause material cost or failure exposure, compare a coarse-grained operation or projection with the existing contract. Preserve required data, authorization, freshness and partial-failure semantics; a shorter chain alone proves neither fewer calls nor a better boundary.
- Narrowing to several scalar parameters can destroy snapshot consistency and create long
parameter lists. Prefer one immutable purpose-specific projection when values must be observed together. Copying a collection does not freeze mutable elements: capture their required values under the owner's consistency protocol too. A record or unmodifiable list alone is not an immutable snapshot; see the receipt example before replacing entities with a projection.
- Hiding a chain may reduce source coupling while leaving semantic/schema coupling unchanged.
Verify with an actual shape change and runtime query/trace evidence, not import count alone.
Deliverable
Identify the exposed composition or intentional schema, observed consequence, ownership and smallest useful correction (including keeping the chain). State which internal change should become local and which contract remains coupled. Report exact checks performed; do not claim behavior preservation, snapshot consistency or fewer queries from shorter source alone. For a findings-only review, report the correction without applying it. Implement within the requested scope and stop when the exposed dependency and affected caller contracts are verified, or state the specific missing ownership, compatibility or runtime evidence.
References
- Detection heuristics and false positives — read when deciding
whether a specific chain is structural coupling or legitimate data access.
before refactoring: one chain fixed by moving behaviour, one by narrowing a parameter, one correctly left alone, with trade-offs and verification.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/java-law-of-demeter/SKILL.md
Popularity
- Repository stars
- 2
- 7-day trend score
- 5
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/robsonkades/agent-skills/java-law-of-demeter)