Conventions¶
Detailed rationale is in the development rules and the ADRs. Here's the short version as a reference.
Packages¶
- Root:
dev.universaladmin. - Architecture packages (
core,module,action,gui,command,permission,storage,audit,config,localization,notification,scheduler) - platform-wide abstractions. - Built-in modules:
dev.universaladmin.modules.<name>(pluralmodules). Adapter/Bukkit-specific code in a subpackage likejdbc, not in the interface package.
Naming¶
- Interfaces without a prefix/suffix:
Repository,Module,Action,SettingsService. - Implementations with a descriptive prefix naming the technology/context:
JdbcPlayerProfileRepository,YamlSettingsService,InGameNotificationService,PaperTaskScheduler. - Typed IDs instead of raw strings for anything that lands in a registry:
ModuleId,ActionId,GuiPageId,AuditEventType(all viadev.universaladmin.core.id.Key, formatnamespace:name).PermissionNode/MessageKeyare their own, simple dotted-string records (external conventions, see their Javadoc). ModuleId.core(...)/ActionId.core(...)/... as shorthand for thecorenamespace every built-in module uses.
Domain Models¶
record, not classes with setters. A state change produces a new record (PlayerProfile.withLastSeen(...)), never mutation.- No
nullreturns for "not found" -Optional<T>for repository lookups,ActionResult.Failurefor actions.
Error Handling¶
- Actions:
ActionResult<R>(sealedSuccess/FailurewithFailureReason), no exceptions for expected failure cases (not found, no permission, validation). - Repository/storage errors: a dedicated, module-specific unchecked
exception (
PlayerStorageException,AuditStorageException) wrapping aSQLException- no rawSQLExceptionpassed through to a caller outside thejdbclayer.
Formatting¶
- UTF-8, the
-parameterscompiler flag is on (seebuild.gradle.kts). - No fixed auto-formatter tool set up currently; follow the existing style in the respective package (4-space indentation, roughly ~110 character line length, one import per line, no wildcard imports).
- Javadoc on public interfaces/classes explains why, not what (see existing classes as examples) - no Javadoc requirement for private/obvious methods.