-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture Guide
The project follows Clean Architecture principles adapted for Python/FastAPI. The architecture is built in layers with clear separation of concerns.
┌─────────────────────────────────────────────────────┐
│ Presentation Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Router │ │ Router │ │ Router │ │
│ │ (auth.py) │ │ (roles.py) │ │ (audit.py) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
└─────────┼─────────────────┼─────────────────┼───────┘
│ │ │
┌─────────▼─────────────────▼─────────────────▼───────┐
│ Adapter Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Identity │ │ Role │ │ Audit │ │
│ │ Adapter │ │ Adapter │ │ Adapter │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
└─────────┼─────────────────┼─────────────────┼───────┘
│ │ │
┌─────────▼─────────────────▼─────────────────▼───────┐
│ Application/Service Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Identity │ │ Role │ │ Audit │ │
│ │ Manager │ │ Service │ │ Service │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Password │ │ Role │ │ Audit │ │
│ │ UseCase │ │ UseCase │ │ UseCase │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
└─────────┼─────────────────▼─────────────────▼───────┘
│ │ │
┌─────────▼─────────────────▼─────────────────▼───────┐
│ DAO Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Identity │ │ Role │ │ Audit │ │
│ │ DAO │ │ DAO │ │ DAO │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ DTO │ │ DTO │ │ DTO │ │
│ │ (dataclass) │ │ (dataclass) │ │ (dataclass) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
└─────────┼─────────────────┼─────────────────┼───────┘
│ │ │
┌─────────▼─────────────────▼─────────────────▼───────┐
│ Domain/Entity Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ User │ │ Role │ │ Audit │ │
│ │ (models) │ │ (models) │ │ (models) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
└─────────┼─────────────────┼─────────────────▼───────┘
│ │
┌─────────▼─────────────────▼─────────────────────────┐
│ Infrastructure │
│ (SQLAlchemy ORM) │
└─────────────────────────────────────────────────────┘
HTTP Request
│
▼
┌─────────────┐
│ Router │ ◄── Validation, Dependency Injection
│ │
└─────┬───────┘
│
▼
┌─────────────┐
│ Adapter │ ◄── HTTP ↔ Domain mapping, Exception handling
│ │
└─────┬───────┘
│
▼
┌─────────────┐
│ Service/ │ ◄── Business Logic, Orchestration
│ UseCase │
└─────┬───────┘
│
▼
┌─────────────┐
│ DAO/ │ ◄── Data Access, DTO ↔ Entity mapping
│ Repository │
└─────┬───────┘
│
▼
┌─────────────┐
│ Entity │ ◄── Domain Models (SQLAlchemy)
│ (models) │
└─────┬───────┘
│
▼
┌─────────────┐
│ Database │
│ │
└─────────────┘
Purpose: Contains business entities and domain rules Location: models.py Principles:
- Contain minimal business logic (properties, domain methods)
- Independent from external layers
- Use SQLAlchemy ORM (temporary Clean Architecture violation for practicality)
- Define data structure and relationships between entities
Purpose: Objects for transferring data between layers
Location: */dataclasses.py
Principles:
- Use
@dataclass - Contain only data, no logic
- Isolate internal layers from Entity changes
- Provide contract between architecture layers
Purpose: Encapsulate simple CRUD operations with data
Location: */*_dao.py
Principles:
- Inherit from
AbstractDAO - Use DTO for all operations
- Contain mapping between Entity and DTO
- Handle data access exceptions
- Focus on atomic operations (create, read, update, delete)
Purpose: Encapsulate complex queries and business-oriented data operations
Location: */*_repository.py
Principles:
- Contain complex SQL queries, aggregations, analytics
- Work directly with ORM for performance optimization
- Used when CRUD operations are insufficient
- Can return both DTO and raw data for reports
- Isolate complex query logic from business layer
Purpose: Encapsulate use case scenarios
Location: */*_use_case.py
Principles:
- Focus on a single use case scenario
- Contain domain validation logic
- Independent from external layers
- Reused in Services
- Describe system business processes
Purpose: Contain application business logic
Location: */*_service.py, */*_manager.py
Principles:
- Inherit from
AbstractService - Orchestrate interaction between DAO and Repository
- Contain complex business logic
- Use UseCases for domain operations
- Coordinate transactions between multiple data sources
Purpose: Adapt external interfaces to internal ones
Location: api/*/adapters/*.py
Principles:
- Inherit from
BaseAdapter - Transform HTTP schemas to DTO
- Handle domain exceptions → HTTP status codes
- Only layer that knows about FastAPI
- Isolate data transfer protocol from business logic
For a new feature module, create the following structure:
app/ldap_protocol/feature/
├── __init__.py # Public API exports
├── dataclasses.py # DTO objects
├── feature_dao.py # Data Access Objects
├── feature_service.py # Business Logic Services
├── feature_use_case.py # Domain Use Cases
├── exceptions.py # Domain exceptions
└── schemas.py # Request/Response schemas
app/api/feature/
├── __init__.py
├── router.py # FastAPI routers
└── adapters/
├── __init__.py
└── feature.py # HTTP ↔ Domain adapters
app/models.py