[feat] add guides
This commit is contained in:
parent
1fbf77f879
commit
c5d5e243c1
7 changed files with 836 additions and 43 deletions
83
docs/CODESTYLE.md
Normal file
83
docs/CODESTYLE.md
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
# Code Style Guide
|
||||
|
||||
## Purpose
|
||||
|
||||
This repository is a Python clean architecture template.
|
||||
Write code that keeps the core portable, adapters thin, and wiring explicit.
|
||||
|
||||
## Layer rules
|
||||
|
||||
- `domain/` contains entities and domain errors only
|
||||
- `usecase/` contains application logic and ports
|
||||
- `repository/` contains repository implementations
|
||||
- `adapter/` contains framework, config, DI, HTTP, and observability integrations
|
||||
- Dependencies must point inward
|
||||
- `domain/` must not import anything from project internals
|
||||
- `usecase/` may import `domain/`, but must not import `adapter/`, `repository/`, FastAPI, or OpenTelemetry
|
||||
- `repository/` and `adapter/` may depend on `usecase/` ports and `domain/`
|
||||
|
||||
## Dependency inversion
|
||||
|
||||
- Define interfaces as `Protocol` types at the point of use
|
||||
- Keep implementations in outer layers
|
||||
- Inject dependencies through constructors
|
||||
- Prefer explicit wiring in `adapter/di/container.py`
|
||||
- Do not hide object creation behind magic globals
|
||||
|
||||
## Python conventions
|
||||
|
||||
- Use simple names
|
||||
- Prefer dataclasses for immutable values, config sections, and request models inside inner layers
|
||||
- Keep `__init__.py` files empty
|
||||
- Do not use `from __future__ import annotations`
|
||||
- Prefer one clear responsibility per class
|
||||
- Keep functions small and direct
|
||||
|
||||
## Comments and errors
|
||||
|
||||
- Add comments only when the code is not obvious
|
||||
- Keep comments short
|
||||
- Do not end comments with a period
|
||||
- Keep error messages short
|
||||
- Do not end error messages with a period
|
||||
|
||||
## HTTP rules
|
||||
|
||||
- Keep FastAPI code inside `adapter/http/fastapi/`
|
||||
- Keep HTTP request and response schemas inside the HTTP adapter
|
||||
- Handlers should translate HTTP input to usecase calls and map domain errors to HTTP responses
|
||||
- Do not move business logic into routers, dependencies, or middleware
|
||||
|
||||
## Observability rules
|
||||
|
||||
- Inner layers know only `Logger`, `Metrics`, and `Tracer` ports
|
||||
- OpenTelemetry code stays in `adapter/otel/`
|
||||
- Use `Noop` implementations when a signal is disabled
|
||||
- Request logging belongs in the HTTP adapter
|
||||
|
||||
## Configuration rules
|
||||
|
||||
- Keep non-secret defaults in `config/app.yaml`
|
||||
- Read secrets from env vars
|
||||
- Merge YAML, `.env`, and process env into one typed config tree
|
||||
- Do not read env vars directly inside `domain/` or `usecase/`
|
||||
|
||||
## Example
|
||||
|
||||
```py
|
||||
from typing import Protocol
|
||||
|
||||
|
||||
class UserRepository(Protocol):
|
||||
def get(self, user_id: str) -> User | None: ...
|
||||
|
||||
|
||||
class GetUser:
|
||||
def __init__(self, repository: UserRepository, logger: Logger, tracer: Tracer) -> None:
|
||||
self._repository = repository
|
||||
self._logger = logger
|
||||
self._tracer = tracer
|
||||
```
|
||||
|
||||
The use case owns the contract.
|
||||
The repository implementation lives outside the use case layer.
|
||||
Loading…
Add table
Add a link
Reference in a new issue