refactor(spike): ArchUnit / Spring Modulith / CQRS with module packages (not layers)#110
Draft
David Conneely (dconneely) wants to merge 11 commits into
Draft
refactor(spike): ArchUnit / Spring Modulith / CQRS with module packages (not layers)#110David Conneely (dconneely) wants to merge 11 commits into
David Conneely (dconneely) wants to merge 11 commits into
Conversation
|
You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. What Enabling Code Scanning Means:
For more information about GitHub Code Scanning, check out the documentation. |
- Rename `architecture.html.md` -> `architecture-patterns.html.md`, and add Options 4 and 5 for less exotic architecture changes - Reanme `domain.html.md` -> `domain-model.html.md` - Rename `events.html.md` -> `event-patterns.html.md`, and reference the new Options 4 and 5 from the architecture patterns document - Add `architecture-proposal.html.md` with suggestions on way forward with reasoning behind these suggestions
- Add ArchUnit rules to catch services that mix read and write transactions
- Add ArchUnit 1.4.2 as a test dependency
- Write layering, mapper-placement, and command/query naming rules
- Split `ProviderService` as the first example of the pattern the rules
enforce, to validate the approach before wider adoption in the PoC/spike
- Move `patchProvider()` into `ProviderCommandService` to fix the
write-in-readonly-class ArchUnit violation
- Rename `ProviderService` -> `ProviderQueryService` and
`ProviderCreationService` -> `ProviderCommandService`
- Update all controllers, services, and tests to use renamed types
- Apply the command/query pattern from the PoC to `OfficeService` - Create `OfficeCommandService` for write operations (create, patch) - Create `OfficeQueryService` (`@Transactional` readOnly) for reads - Delete `OfficeService`, update all callers and tests
ab4b096 to
a047d5a
Compare
- Apply the same command/query separation to bank account
operations, consistent with the ArchUnit rules and the previous
Provider and Office service splits
- Create `BankAccountCommandService` for create and link operations
- Create `BankAccountQueryService` separate from `OfficeQueryService`
to avoid pulling in four unrelated repository dependencies
- Delete `BankDetailsService`, update all callers and tests
- Apply the same command/query separation to liaison manager operations,
consistent with the ArchUnit rules and previous service splits
- Create `OfficeLiaisonManagerCommandService` for write operations
- Move `getOfficeLiaisonManagers` into `OfficeQueryService`, which
already has the required repository dependencies
- Delete `OfficeLiaisonManagerService`, update all callers and tests
- Apply the same naming convention to the contract manager services,
consistent with the ArchUnit rules and previous splits
- Rename `OfficeContractManagerAssignmentService` ->
`OfficeContractManagerCommandService`
- Rename `ContractManagerService` -> `OfficeContractManagerQueryService`
and `ProviderContractManagersService` -> `ContractManagerQueryService`
(left as two query services because the office-scoped variant uses
`ContractManagerMapper` and different repositories than global search)
- Add `@Transactional(readOnly = true)` at class level to both query
services, update all callers and tests
…cept)
- Prove Spring Boot 4 / Spring Modulith 2.0.6 compatibility before committing
to a modular package reorganisation
- Add `org.springframework.modulith:spring-modulith-core:2.0.6` as a
test dependency (version not managed by the Spring Boot BOM)
- Add `ApplicationModulesTest` calling `ApplicationModules.of(...).verify()`
- Move `ProviderSpecification` from `repository.spec` -> `repository`
to fix the module boundary violation Spring Modulith detected
- Update module layout in `architecture-proposal.html.md` to six domain modules and a `shared/` utility module - Update Option 5 in `architecture-patterns.html.md` to same layout - Rename "Current structure" heading to "Pre-refactoring structure"
…-root layout - Replace flat layered packages (entity/, service/, controller/, mapper/ etc.) with per-aggregate Spring Modulith modules: bankaccount/, contractmanager/, liaisonmanager/, office/, provider/, shared/, usecase/ - Add `ApplicationModulesTest` to enforce module boundaries with Spring Modulith - Add and update ArchUnit rules: no field injection, `@RestController` classes in `..web..` packages, repositories in `..repository..` packages, web layer does not depend on repositories - Update tests to use renamed types
- Publish a full-state snapshot event after every write
- Store published events permanently in `provider_event` table
- Implement `GET /provider-events` and `/provider-events/{eventGUID}`
- Add `spring-modulith-starter-insight` Micrometer tracing of modules
- Add unit, integration, and e2e test coverage for event publication and query
- Revise recommendation from per-entity domain modules to flat technical layers, retaining Spring Modulith for event publication, observability, and `ApplicationModulesTest` applied to the layer packages themselves - Explain why per-entity module granularity fights a workflow-oriented API spec: endpoints spanning multiple aggregates force an orchestration module that depends on everything, defeating the purpose of the boundaries - Remove specific class names from both documents and reduce illustrative CQRS examples to representative pairs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
docs: Update tech-docs (with an architecture proposal/suggestion)
architecture.html.md->architecture-patterns.html.md,and add Options 4 and 5 for less exotic architecture changes
domain.html.md->domain-model.html.mdevents.html.md->event-patterns.html.md, and referencethe new Options 4 and 5 from the architecture patterns document
architecture-proposal.html.mdwith suggestions on way forwardwith reasoning behind these suggestions
feat: Enforce command/query separation with ArchUnit (proof of concept)
ProviderServiceas the first example of the pattern the rulesenforce, to validate the approach before wider adoption in the PoC/spike
patchProvider()intoProviderCommandServiceto fix thewrite-in-readonly-class ArchUnit violation
ProviderService->ProviderQueryServiceandProviderCreationService->ProviderCommandServicerefactor: Split
OfficeServiceinto command and query servicesOfficeServiceOfficeCommandServicefor write operations (create, patch)OfficeQueryService(@TransactionalreadOnly) for readsOfficeService, update all callers and testsrefactor: Split
BankDetailsServiceinto command and query servicesoperations, consistent with the ArchUnit rules and the previous
Provider and Office service splits
BankAccountCommandServicefor create and link operationsBankAccountQueryServiceseparate fromOfficeQueryServiceto avoid pulling in four unrelated repository dependencies
BankDetailsService, update all callers and testsrefactor: Split
OfficeLiaisonManagerServiceinto command serviceconsistent with the ArchUnit rules and previous service splits
OfficeLiaisonManagerCommandServicefor write operationsgetOfficeLiaisonManagersintoOfficeQueryService, whichalready has the required repository dependencies
OfficeLiaisonManagerService, update all callers and testsrefactor: Rename contract manager services for command/query separation
consistent with the ArchUnit rules and previous splits
OfficeContractManagerAssignmentService->OfficeContractManagerCommandServiceContractManagerService->OfficeContractManagerQueryServiceand
ProviderContractManagersService->ContractManagerQueryService(left as two query services because the office-scoped variant uses
ContractManagerMapperand different repositories than global search)@Transactional(readOnly = true)at class level to both queryservices, update all callers and tests
feat: Add Spring Modulith module structure verification (proof of concept)
to a modular package reorganisation
org.springframework.modulith:spring-modulith-core:2.0.6as atest dependency (version not managed by the Spring Boot BOM)
ApplicationModulesTestcallingApplicationModules.of(...).verify()ProviderSpecificationfromrepository.spec->repositoryto fix the module boundary violation Spring Modulith detected
docs: Update target module structure in architecture docs
architecture-proposal.html.mdto six domainmodules and a
shared/utility modulearchitecture-patterns.html.mdto same layoutrefactor: Restructure provider-data-service into module-per-aggregate-root layout
with per-aggregate Spring Modulith modules: bankaccount/, contractmanager/,
liaisonmanager/, office/, provider/, shared/, usecase/
ApplicationModulesTestto enforce module boundaries with Spring Modulith@RestControllerclassesin
..web..packages, repositories in..repository..packages, web layerdoes not depend on repositories
feat: Add Spring Modulith events, implement provider-events API
provider_eventtableGET /provider-eventsand/provider-events/{eventGUID}spring-modulith-starter-insightMicrometer tracing of modulesdocs: Revise architecture recommendation to flat technical layers
layers, retaining Spring Modulith for event publication, observability,
and
ApplicationModulesTestapplied to the layer packages themselvesspec: endpoints spanning multiple aggregates force an orchestration module
that depends on everything, defeating the purpose of the boundaries
CQRS examples to representative pairs
Checklist
./gradlew testgit rebase main.