mirror of
https://github.com/s-frick/effigenix.git
synced 2026-03-28 15:29:34 +01:00
docs: and skills
This commit is contained in:
parent
e4f0665086
commit
ccd4ee534a
25 changed files with 10412 additions and 0 deletions
685
bin/.claude/skills/ddd-model/languages/java/structure.md
Normal file
685
bin/.claude/skills/ddd-model/languages/java/structure.md
Normal file
|
|
@ -0,0 +1,685 @@
|
|||
# Project Structure for Java DDD
|
||||
|
||||
This guide covers organizing a Java project following Clean Architecture and Domain-Driven Design principles.
|
||||
|
||||
## Maven Structure
|
||||
|
||||
Standard Maven project organization:
|
||||
|
||||
```
|
||||
project-root/
|
||||
├── pom.xml
|
||||
├── src/
|
||||
│ ├── main/
|
||||
│ │ └── java/
|
||||
│ │ └── com/example/
|
||||
│ │ ├── domain/ # Domain layer
|
||||
│ │ ├── application/ # Application layer
|
||||
│ │ ├── infrastructure/ # Infrastructure layer
|
||||
│ │ └── shared/ # Shared utilities
|
||||
│ └── test/
|
||||
│ └── java/
|
||||
│ └── com/example/
|
||||
│ ├── domain/
|
||||
│ ├── application/
|
||||
│ ├── infrastructure/
|
||||
│ └── shared/
|
||||
├── README.md
|
||||
└── .gitignore
|
||||
```
|
||||
|
||||
### Maven Dependencies Structure
|
||||
|
||||
```xml
|
||||
<project>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>banking-system</artifactId>
|
||||
<version>1.0.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.release>21</maven.compiler.release>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Java 21 features (no additional dependencies needed) -->
|
||||
|
||||
<!-- Testing -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Logging (infrastructure layer only) -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>2.0.7</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Database (infrastructure only) -->
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.6.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<release>21</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
```
|
||||
|
||||
## Gradle Structure
|
||||
|
||||
Gradle-based alternative:
|
||||
|
||||
```gradle
|
||||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = '21'
|
||||
targetCompatibility = '21'
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Testing
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
|
||||
|
||||
// Logging
|
||||
implementation 'org.slf4j:slf4j-api:2.0.7'
|
||||
runtimeOnly 'org.slf4j:slf4j-simple:2.0.7'
|
||||
|
||||
// Database
|
||||
implementation 'org.postgresql:postgresql:42.6.0'
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
```
|
||||
|
||||
## Complete Directory Structure
|
||||
|
||||
### Domain Layer
|
||||
|
||||
```
|
||||
src/main/java/com/example/domain/
|
||||
├── account/ # Bounded context: Account
|
||||
│ ├── Account.java # Aggregate root
|
||||
│ ├── AccountId.java # Value object (ID)
|
||||
│ ├── AccountStatus.java # Value object (enum-like)
|
||||
│ ├── Money.java # Value object (shared across contexts)
|
||||
│ ├── AccountError.java # Sealed interface for errors
|
||||
│ ├── AccountRepository.java # Repository interface (domain contract)
|
||||
│ └── DomainEventPublisher.java # Event publishing interface (optional)
|
||||
│
|
||||
├── transfer/ # Bounded context: Transfer
|
||||
│ ├── Transfer.java # Aggregate root
|
||||
│ ├── TransferId.java # Value object
|
||||
│ ├── TransferStatus.java # Status enum
|
||||
│ ├── TransferError.java # Errors
|
||||
│ ├── TransferRepository.java # Repository interface
|
||||
│ └── TransferService.java # Domain service (if needed)
|
||||
│
|
||||
├── shared/
|
||||
│ ├── result/
|
||||
│ │ ├── Result.java # Result<E, T> interface
|
||||
│ │ ├── Success.java # Success case
|
||||
│ │ └── Failure.java # Failure case
|
||||
│ └── DomainEvent.java # Base domain event
|
||||
```
|
||||
|
||||
### Application Layer
|
||||
|
||||
```
|
||||
src/main/java/com/example/application/
|
||||
├── account/
|
||||
│ ├── OpenAccountUseCase.java # One use case per file
|
||||
│ ├── DepositMoneyUseCase.java
|
||||
│ ├── WithdrawMoneyUseCase.java
|
||||
│ ├── GetAccountBalanceUseCase.java
|
||||
│ ├── dto/
|
||||
│ │ ├── OpenAccountRequest.java
|
||||
│ │ ├── OpenAccountResponse.java
|
||||
│ │ ├── DepositRequest.java
|
||||
│ │ └── DepositResponse.java
|
||||
│ └── AccountApplicationError.java # App-specific errors
|
||||
│
|
||||
├── transfer/
|
||||
│ ├── TransferMoneyUseCase.java
|
||||
│ ├── GetTransferStatusUseCase.java
|
||||
│ ├── dto/
|
||||
│ │ ├── TransferRequest.java
|
||||
│ │ └── TransferResponse.java
|
||||
│ └── TransferApplicationError.java
|
||||
│
|
||||
├── shared/
|
||||
│ ├── UseCase.java # Interface/base class for use cases
|
||||
│ └── UnitOfWork.java # Transaction management interface
|
||||
```
|
||||
|
||||
### Infrastructure Layer
|
||||
|
||||
```
|
||||
src/main/java/com/example/infrastructure/
|
||||
├── persistence/
|
||||
│ ├── account/
|
||||
│ │ ├── JdbcAccountRepository.java # Implements AccountRepository
|
||||
│ │ ├── AccountRowMapper.java # Database row mapping
|
||||
│ │ └── AccountQueries.java # SQL constants
|
||||
│ ├── transfer/
|
||||
│ │ ├── JdbcTransferRepository.java
|
||||
│ │ └── TransferRowMapper.java
|
||||
│ ├── connection/
|
||||
│ │ ├── ConnectionPool.java
|
||||
│ │ └── DataSourceFactory.java
|
||||
│ └── transaction/
|
||||
│ └── JdbcUnitOfWork.java # Transaction coordinator
|
||||
│
|
||||
├── http/
|
||||
│ ├── handler/
|
||||
│ │ ├── account/
|
||||
│ │ │ ├── OpenAccountHandler.java
|
||||
│ │ │ ├── WithdrawHandler.java
|
||||
│ │ │ └── GetBalanceHandler.java
|
||||
│ │ └── transfer/
|
||||
│ │ ├── TransferHandler.java
|
||||
│ │ └── GetTransferStatusHandler.java
|
||||
│ ├── router/
|
||||
│ │ └── ApiRouter.java # Route definition
|
||||
│ ├── response/
|
||||
│ │ ├── SuccessResponse.java
|
||||
│ │ └── ErrorResponse.java
|
||||
│ └── middleware/
|
||||
│ ├── ErrorHandlingMiddleware.java
|
||||
│ └── LoggingMiddleware.java
|
||||
│
|
||||
├── event/
|
||||
│ ├── DomainEventPublisherImpl.java # Publishes domain events
|
||||
│ ├── event-handlers/
|
||||
│ │ ├── AccountCreatedEventHandler.java
|
||||
│ │ └── TransferCompletedEventHandler.java
|
||||
│ └── EventDispatcher.java
|
||||
│
|
||||
├── config/
|
||||
│ └── AppConfiguration.java # Dependency injection setup
|
||||
│
|
||||
└── persistence/
|
||||
└── migrations/
|
||||
├── V001__CreateAccountsTable.sql
|
||||
└── V002__CreateTransfersTable.sql
|
||||
```
|
||||
|
||||
### Test Structure
|
||||
|
||||
```
|
||||
src/test/java/com/example/
|
||||
├── domain/
|
||||
│ ├── account/
|
||||
│ │ ├── AccountTest.java # Unit tests for Account
|
||||
│ │ ├── MoneyTest.java
|
||||
│ │ └── AccountRepositoryTest.java # Contract tests
|
||||
│ └── transfer/
|
||||
│ ├── TransferTest.java
|
||||
│ └── TransferRepositoryTest.java
|
||||
│
|
||||
├── application/
|
||||
│ ├── account/
|
||||
│ │ ├── OpenAccountUseCaseTest.java
|
||||
│ │ ├── WithdrawMoneyUseCaseTest.java
|
||||
│ │ └── fixtures/
|
||||
│ │ ├── AccountFixture.java # Test data builders
|
||||
│ │ └── MoneyFixture.java
|
||||
│ └── transfer/
|
||||
│ └── TransferMoneyUseCaseTest.java
|
||||
│
|
||||
├── infrastructure/
|
||||
│ ├── persistence/
|
||||
│ │ ├── JdbcAccountRepositoryTest.java # Integration tests
|
||||
│ │ └── JdbcTransferRepositoryTest.java
|
||||
│ └── http/
|
||||
│ └── OpenAccountHandlerTest.java
|
||||
│
|
||||
└── acceptance/
|
||||
└── OpenAccountAcceptanceTest.java # End-to-end tests
|
||||
```
|
||||
|
||||
## Three Organizational Approaches
|
||||
|
||||
### Approach 1: BC-First (Recommended for Most Projects)
|
||||
|
||||
Organize around Bounded Contexts:
|
||||
|
||||
```
|
||||
src/main/java/com/example/
|
||||
├── account/ # BC 1
|
||||
│ ├── domain/
|
||||
│ │ ├── Account.java
|
||||
│ │ ├── AccountError.java
|
||||
│ │ └── AccountRepository.java
|
||||
│ ├── application/
|
||||
│ │ ├── OpenAccountUseCase.java
|
||||
│ │ └── dto/
|
||||
│ └── infrastructure/
|
||||
│ ├── persistence/
|
||||
│ │ └── JdbcAccountRepository.java
|
||||
│ └── http/
|
||||
│ └── OpenAccountHandler.java
|
||||
│
|
||||
├── transfer/ # BC 2
|
||||
│ ├── domain/
|
||||
│ ├── application/
|
||||
│ └── infrastructure/
|
||||
│
|
||||
└── shared/ # Shared across BCs
|
||||
├── result/
|
||||
│ └── Result.java
|
||||
└── events/
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
- Clear BC boundaries
|
||||
- Easy to navigate between layers within a context
|
||||
- Natural place for context-specific configuration
|
||||
- Facilitates team ownership per BC
|
||||
|
||||
**Cons:**
|
||||
- Duplication across contexts
|
||||
- More code organization overhead
|
||||
|
||||
### Approach 2: Tech-First (Better for Microservices)
|
||||
|
||||
Organize by technical layer:
|
||||
|
||||
```
|
||||
src/main/java/com/example/
|
||||
├── domain/
|
||||
│ ├── account/
|
||||
│ │ ├── Account.java
|
||||
│ │ ├── AccountRepository.java
|
||||
│ │ └── AccountError.java
|
||||
│ └── transfer/
|
||||
│
|
||||
├── application/
|
||||
│ ├── account/
|
||||
│ │ ├── OpenAccountUseCase.java
|
||||
│ │ └── dto/
|
||||
│ └── transfer/
|
||||
│
|
||||
├── infrastructure/
|
||||
│ ├── persistence/
|
||||
│ │ ├── account/
|
||||
│ │ │ └── JdbcAccountRepository.java
|
||||
│ │ └── transfer/
|
||||
│ ├── http/
|
||||
│ │ ├── account/
|
||||
│ │ └── transfer/
|
||||
│ └── config/
|
||||
│
|
||||
└── shared/
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
- Clear layer separation
|
||||
- Easy to review layer architecture
|
||||
- Good for enforcing dependency rules
|
||||
|
||||
**Cons:**
|
||||
- Scattered BC concepts across files
|
||||
- Harder to find all code for one feature
|
||||
|
||||
### Approach 3: Hybrid (Best for Large Projects)
|
||||
|
||||
Combine both approaches strategically:
|
||||
|
||||
```
|
||||
src/main/java/com/example/
|
||||
├── domain/ # All domain objects, shared across project
|
||||
│ ├── account/
|
||||
│ ├── transfer/
|
||||
│ └── shared/
|
||||
│
|
||||
├── application/ # All application services
|
||||
│ ├── account/
|
||||
│ └── transfer/
|
||||
│
|
||||
├── infrastructure/ # Infrastructure organized by BC
|
||||
│ ├── account/
|
||||
│ │ ├── persistence/
|
||||
│ │ └── http/
|
||||
│ ├── transfer/
|
||||
│ ├── config/
|
||||
│ └── shared/
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
- Emphasizes domain independence
|
||||
- Clear infrastructure layer separation
|
||||
- Good for large teams
|
||||
|
||||
**Cons:**
|
||||
- Two different organizational styles
|
||||
- Requires discipline to maintain
|
||||
|
||||
## One Use Case Per File
|
||||
|
||||
### Recommended Structure
|
||||
|
||||
```
|
||||
src/main/java/com/example/application/account/
|
||||
├── OpenAccountUseCase.java
|
||||
├── DepositMoneyUseCase.java
|
||||
├── WithdrawMoneyUseCase.java
|
||||
├── GetAccountBalanceUseCase.java
|
||||
├── CloseAccountUseCase.java
|
||||
└── dto/
|
||||
├── OpenAccountRequest.java
|
||||
├── OpenAccountResponse.java
|
||||
├── DepositRequest.java
|
||||
└── DepositResponse.java
|
||||
```
|
||||
|
||||
### Use Case File Template
|
||||
|
||||
```java
|
||||
package com.example.application.account;
|
||||
|
||||
import com.example.domain.account.*;
|
||||
import com.example.shared.result.Result;
|
||||
import static com.example.shared.result.Result.success;
|
||||
import static com.example.shared.result.Result.failure;
|
||||
|
||||
/**
|
||||
* OpenAccountUseCase - one file, one use case.
|
||||
*
|
||||
* Coordinates the opening of a new account:
|
||||
* 1. Create Account aggregate
|
||||
* 2. Persist via repository
|
||||
* 3. Publish domain events
|
||||
*/
|
||||
public class OpenAccountUseCase {
|
||||
private final AccountRepository accountRepository;
|
||||
private final AccountIdGenerator idGenerator;
|
||||
private final UnitOfWork unitOfWork;
|
||||
|
||||
public OpenAccountUseCase(
|
||||
AccountRepository accountRepository,
|
||||
AccountIdGenerator idGenerator,
|
||||
UnitOfWork unitOfWork
|
||||
) {
|
||||
this.accountRepository = accountRepository;
|
||||
this.idGenerator = idGenerator;
|
||||
this.unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the use case.
|
||||
*
|
||||
* @param request containing account opening parameters
|
||||
* @return success with account ID, or failure with reason
|
||||
*/
|
||||
public Result<OpenAccountError, OpenAccountResponse> execute(
|
||||
OpenAccountRequest request
|
||||
) {
|
||||
try {
|
||||
// Phase 1: Create aggregate
|
||||
AccountId accountId = idGenerator.generate();
|
||||
Result<AccountError, Account> accountResult = Account.create(
|
||||
accountId,
|
||||
request.initialBalance(),
|
||||
request.accountHolder()
|
||||
);
|
||||
|
||||
if (accountResult instanceof Failure f) {
|
||||
return failure(mapError(f.error()));
|
||||
}
|
||||
|
||||
Account account = ((Success<AccountError, Account>) accountResult).value();
|
||||
|
||||
// Phase 2: Persist
|
||||
return unitOfWork.withTransaction(() -> {
|
||||
accountRepository.save(account);
|
||||
|
||||
// Phase 3: Publish events
|
||||
account.publishedEvents().forEach(event ->
|
||||
eventPublisher.publish(event)
|
||||
);
|
||||
|
||||
return success(new OpenAccountResponse(
|
||||
account.id().value(),
|
||||
account.balance()
|
||||
));
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Unexpected error opening account", e);
|
||||
return failure(new OpenAccountError.RepositoryError("Failed to save account"));
|
||||
}
|
||||
}
|
||||
|
||||
private OpenAccountError mapError(AccountError error) {
|
||||
return switch (error) {
|
||||
case InvalidAmountError e ->
|
||||
new OpenAccountError.InvalidInitialBalance(e.message());
|
||||
case InvalidAccountHolderError e ->
|
||||
new OpenAccountError.InvalidHolder(e.message());
|
||||
default ->
|
||||
new OpenAccountError.UnexpectedError(error.message());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenAccountRequest - input DTO.
|
||||
*/
|
||||
public record OpenAccountRequest(
|
||||
Money initialBalance,
|
||||
String accountHolder
|
||||
) {
|
||||
public OpenAccountRequest {
|
||||
if (initialBalance == null) {
|
||||
throw new IllegalArgumentException("Initial balance required");
|
||||
}
|
||||
if (accountHolder == null || accountHolder.isBlank()) {
|
||||
throw new IllegalArgumentException("Account holder name required");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenAccountResponse - output DTO.
|
||||
*/
|
||||
public record OpenAccountResponse(
|
||||
String accountId,
|
||||
Money balance
|
||||
) {}
|
||||
|
||||
/**
|
||||
* OpenAccountError - use case specific errors.
|
||||
*/
|
||||
public sealed interface OpenAccountError permits
|
||||
InvalidInitialBalance,
|
||||
InvalidHolder,
|
||||
RepositoryError,
|
||||
UnexpectedError {
|
||||
String message();
|
||||
}
|
||||
|
||||
public record InvalidInitialBalance(String reason) implements OpenAccountError {
|
||||
@Override
|
||||
public String message() {
|
||||
return "Invalid initial balance: " + reason;
|
||||
}
|
||||
}
|
||||
|
||||
// ... other error implementations
|
||||
```
|
||||
|
||||
## Package Naming
|
||||
|
||||
```
|
||||
com.example # Root
|
||||
├── domain # Domain layer
|
||||
│ ├── account # BC 1 domain
|
||||
│ │ └── Account.java
|
||||
│ └── transfer # BC 2 domain
|
||||
│ └── Transfer.java
|
||||
├── application # Application layer
|
||||
│ ├── account # BC 1 use cases
|
||||
│ │ └── OpenAccountUseCase.java
|
||||
│ └── transfer # BC 2 use cases
|
||||
│ └── TransferMoneyUseCase.java
|
||||
├── infrastructure # Infrastructure layer
|
||||
│ ├── persistence # Persistence adapters
|
||||
│ │ ├── account # BC 1 persistence
|
||||
│ │ └── transfer # BC 2 persistence
|
||||
│ ├── http # HTTP adapters
|
||||
│ │ ├── account # BC 1 handlers
|
||||
│ │ └── transfer # BC 2 handlers
|
||||
│ └── config # Configuration
|
||||
│ └── AppConfiguration.java
|
||||
└── shared # Shared across layers
|
||||
├── result # Result<E, T>
|
||||
├── events # Domain events
|
||||
└── exceptions # Shared exceptions (use sparingly)
|
||||
```
|
||||
|
||||
## Example: Account BC Structure
|
||||
|
||||
Complete example of one bounded context:
|
||||
|
||||
```
|
||||
com/example/account/
|
||||
├── domain/
|
||||
│ ├── Account.java # Aggregate root
|
||||
│ ├── AccountId.java # ID value object
|
||||
│ ├── AccountStatus.java # Status value object
|
||||
│ ├── AccountError.java # Sealed error interface
|
||||
│ ├── AccountRepository.java # Repository interface
|
||||
│ ├── DomainEvents.java # Domain events (AccountCreated, etc.)
|
||||
│ └── AccountIdGenerator.java # Generator interface
|
||||
│
|
||||
├── application/
|
||||
│ ├── OpenAccountUseCase.java
|
||||
│ ├── DepositMoneyUseCase.java
|
||||
│ ├── WithdrawMoneyUseCase.java
|
||||
│ ├── GetAccountBalanceUseCase.java
|
||||
│ ├── ApplicationError.java # App-level errors
|
||||
│ ├── dto/
|
||||
│ │ ├── OpenAccountRequest.java
|
||||
│ │ ├── OpenAccountResponse.java
|
||||
│ │ ├── DepositRequest.java
|
||||
│ │ └── DepositResponse.java
|
||||
│ └── fixtures/ (test directory)
|
||||
│ └── AccountFixture.java
|
||||
│
|
||||
└── infrastructure/
|
||||
├── persistence/
|
||||
│ ├── JdbcAccountRepository.java
|
||||
│ ├── AccountRowMapper.java
|
||||
│ └── AccountQueries.java
|
||||
├── http/
|
||||
│ ├── OpenAccountHandler.java
|
||||
│ ├── DepositHandler.java
|
||||
│ ├── WithdrawHandler.java
|
||||
│ └── GetBalanceHandler.java
|
||||
└── events/
|
||||
└── AccountEventHandlers.java
|
||||
```
|
||||
|
||||
## Configuration Example
|
||||
|
||||
```java
|
||||
package com.example.infrastructure.config;
|
||||
|
||||
public class AppConfiguration {
|
||||
private final DataSource dataSource;
|
||||
private final DomainEventPublisher eventPublisher;
|
||||
|
||||
public AppConfiguration() {
|
||||
this.dataSource = createDataSource();
|
||||
this.eventPublisher = createEventPublisher();
|
||||
}
|
||||
|
||||
// Account BC dependencies
|
||||
public AccountRepository accountRepository() {
|
||||
return new JdbcAccountRepository(dataSource);
|
||||
}
|
||||
|
||||
public AccountIdGenerator accountIdGenerator() {
|
||||
return new UuidAccountIdGenerator();
|
||||
}
|
||||
|
||||
public OpenAccountUseCase openAccountUseCase() {
|
||||
return new OpenAccountUseCase(
|
||||
accountRepository(),
|
||||
accountIdGenerator(),
|
||||
unitOfWork()
|
||||
);
|
||||
}
|
||||
|
||||
// Transfer BC dependencies
|
||||
public TransferRepository transferRepository() {
|
||||
return new JdbcTransferRepository(dataSource);
|
||||
}
|
||||
|
||||
public TransferMoneyUseCase transferMoneyUseCase() {
|
||||
return new TransferMoneyUseCase(
|
||||
accountRepository(),
|
||||
transferRepository(),
|
||||
unitOfWork()
|
||||
);
|
||||
}
|
||||
|
||||
// Shared infrastructure
|
||||
public UnitOfWork unitOfWork() {
|
||||
return new JdbcUnitOfWork(dataSource);
|
||||
}
|
||||
|
||||
public DomainEventPublisher eventPublisher() {
|
||||
return eventPublisher;
|
||||
}
|
||||
|
||||
private DataSource createDataSource() {
|
||||
// Database pool configuration
|
||||
return new HikariDataSource();
|
||||
}
|
||||
|
||||
private DomainEventPublisher createEventPublisher() {
|
||||
return new SimpleEventPublisher();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Organize by BC first** when starting a project
|
||||
2. **One use case per file** in application layer
|
||||
3. **Keep test directory structure** parallel to main
|
||||
4. **Place DTOs near their use cases** (not in separate folder)
|
||||
5. **Shared code in `shared` package** (Result, base classes)
|
||||
6. **Database migrations** in dedicated folder
|
||||
7. **Configuration at root** of infrastructure layer
|
||||
8. **HTTP handlers** group by BC
|
||||
9. **Repository implementations** group by BC
|
||||
10. **No circular package dependencies** - enforce with checkstyle
|
||||
Loading…
Add table
Add a link
Reference in a new issue