Code Style
This page defines mandatory architecture and style rules for Model Forge.
Layers
Host application call
↓
ModelForge facade – contract mapping, input validation, diagnostics → exceptions
↓
Service – Domain logic, orchestration, transactions
↓
Port / Adapter – Infrastructure (PostgreSQL artifact registry, XRepository/HTTP clients, in-memory cache)
↓
Contract – public records: commands, results, queries (Java records)
Rules:
- The facade contains no domain logic — only contract mapping and delegation
- Services inject no web or transport artifacts (
HttpServletRequest,ResponseEntity) — the library modules stay free oforg.springframework.web - Infrastructure details (URLs, retries, encoding) belong in adapter/client classes, not in services
ArchUnit tests (architecture/*ArchitectureTest in model-forge-contract and
per-slice tests inside model-forge-runtime for the core, application,
integrations and persistence packages) enforce these boundaries —
the contract stays transport- and infrastructure-free, the facade depends only
on the contract and the application port layer, and core/application never
depend on web, servlet, SQL or persistence types — and violations fail the
build.
Obligations per class
| Class | Javadoc | Magic-string ban |
|---|---|---|
Every public class | ✓ mandatory | private static final constants |
Every @Service bean | ✓ | – |
Forbidden patterns
// ✗ Forbidden: a new HttpClient per call inside a method
HttpResponse<String> r = HttpClient.newHttpClient().send(request, BodyHandlers.ofString());
// ✓ Correct: HttpClient as a field, built once in the constructor
private final HttpClient http;
// ✗ Forbidden: fully qualified class names in method bodies
tools.jackson.databind.ObjectMapper om = new tools.jackson.databind.ObjectMapper();
// ✓ Correct: import + injection via constructor
private final ObjectMapper mapper; // injected
// ✗ Forbidden: web/transport types outside the adapter packages
import org.springframework.web.client.RestClient; // in contract/core/application → ArchUnit fails the build
// ✓ Correct: HTTP and SQL live in the adapter packages (integrations, persistence)
// ✗ Forbidden: var with a type that is not immediately evident
var result = someService.getStuff();
// ✓ Allowed: var only when the type is directly evident from the right-hand side
var mapper = new ObjectMapper(); // clear: ObjectMapper
Magic strings / numbers → constants
// ✗
String sql = "select * from artifact where artifact_type = 'element'";
// ✓
private static final String ARTIFACT_TYPE_ELEMENT = "element";
private static final String SELECT_BY_TYPE =
"select * from artifact where artifact_type = ?";
Error handling
- No generic
catch (Exception e) { return empty; }without log output - Distinguish caller errors from backend failures clearly: bad input surfaces
as a validation error (
IllegalArgumentException, or aValidationFailedExceptioncarrying diagnostics), an unexpected infrastructure failure as anIllegalStateException/ domain-level upstream-failure exception — never collapse both into one generic failure Optional.empty()signals "not found"; no exceptions for the normal case
Known technical debt
| ID | Description | Status / Impact |
|---|---|---|
| TD-005 | Cross-artifact search returns a bare List<ArtifactSummary> from ModelForge.search(ArtifactSearchQuery) | Accepted: offset/limit paging on the facade query is deliberate |
Automated checks
| Tool | Purpose | Where |
|---|---|---|
| Spotless | Whitespace hygiene (trailing whitespace, final newline) | Maven verify |
| SpotBugs | Static bug analysis over all modules' main bytecode; build fails on findings | Maven verify |
| JaCoCo | Coverage agent + report in model-forge-contract only — no hard coverage gate, the build does not fail on coverage | Maven verify |
| ArchUnit | Layer dependencies, no package cycles | Test suite |
| commitlint | Conventional-commit messages | Repo-wide concern — not run per module (no lefthook.yml in the Model Forge module) |
SpotBugs runs at effort=Max / threshold=Medium (configured once in the
parent pom.xml, so all modules are analysed) and fails the build on any
finding at or above that confidence. Idiomatic/framework false positives —
record EI_EXPOSE_REP* on Jackson-serialised payloads and EI_EXPOSE_REP2
on Spring beans storing injected collaborators — are scoped out in the
repo-level spotbugs-exclude.xml, each entry justified inline. Genuine bugs are
fixed in the code rather than excluded.
Checkstyle/SonarQube remain candidates for future automation; the Javadoc obligations above are currently enforced through code review.
Quality reviews
The mandatory style rules above are enforced by the automated checks and by code review. The broader, periodic code- and architecture-quality review — covering correctness, design, security, tests, documentation, dependencies, minimalism and architectural aesthetics, with its own report structure and process — has its own rubric: see Code Review.