3.0 KiB
3.0 KiB
name, description, license
| name | description | license |
|---|---|---|
| backend-code-organisation | Kotlin backend layering and packaging guidelines | MIT |
Mission
- Keep backend services modular: resources handle transport, managers own business logic, and data access stays isolated.
- Maintain clean dependency flow across modules (
service→core→models) to encourage reuse and testability.
Layering Principles
- Resources: Only translate HTTP/storage inputs to domain calls. No database or cross-service logic. Convert
SecurityContextearly. - Managers: Encapsulate business rules; coordinate helpers, other managers, workflows, and DAL components. Break cycles by separating read/write responsibilities or introducing controllers.
- Helpers/Services: Reusable integrations (feature flags, external clients). Centralize external service calls to simplify retries and upgrades.
- Repos/DAL/DAO: Keep database interactions single-purpose. Compose multi-step transactions in repos/DAL; keep DAO calls single query.
- Utils/Validators/Transformers: Pure functions and extensions only; avoid hidden state.
- Cache Managers: Inject Redis/Lettuce clients, expose typed
get/invalidatehelpers.
Package & Module Structure
- Enforce lowercase package names without underscores; avoid versioned package hierarchies (
v2folders). Prefermanagers.slotsovermanagers.slots.v2. - Organize by responsibility:
managers,helpers,utils,dao,workflows, etc. Mirror structure in tests. - Module boundaries:
core: managers, helpers, data access, transient models. May depend onmodels.service: Dropwizard resources, configuration, application wiring; no direct DB access.console-service: Console-specific resources/auth; depends oncore.client: Outbound clients; depend only onmodels.models: Shared API/data contracts; no dependencies.
Dependency Injection & Config
- Add new Redis/Cosmos/DB configs across all environments (
db-test,db-dev,db-warehouse-prod) and run the service locally to validate. - Annotate injectable classes with
@Singletonwhen appropriate. - Only use
@Namedwhen multiple bindings of the same type exist; otherwise default bindings suffice. - Centralize client construction in DI modules to enforce consistent timeouts and hosts.
Review Checklist
- Check that new features land in the correct layer and module (e.g., resources calling managers, not DAOs).
- Ensure helpers/managers do not introduce cyclic dependencies; suggest splitting read/write flows or using controller orchestrators.
- Verify repos/DAL enforce validation and error translation before returning data.
- Confirm new package or module names remain lowercase and idiomatic; flag attempts to create
v2package forks. - Audit DI modules for duplicate provider methods and proper scoping.
Tooling Tips
Globfor*.ktwithinservice/orcore/to inspect layer usage.ReadDI modules when new bindings appear to ensure wiring matches guidelines.Grepfor@Namedor direct DAO usage inside resources to catch misplaced logic.