feat: add generic Value[T] base class for value objects

- Create Value[T] (frozen dataclass + ABC + Generic) in domain/framework/
- Migrate ClassifiedAdTitle and ClassifiedAdText to inherit Value[str]
- Standardize all value access via .value instead of type-specific fields
This commit is contained in:
2026-07-29 11:13:17 -04:00
parent 05229910cd
commit d345e522bd
9 changed files with 150 additions and 102 deletions

View File

@@ -1,18 +1,45 @@
# Plan: Add FastAPI to the Project
# Plan: Value Object Base Class
## Goal
Add FastAPI as the web framework with a minimal health check endpoint.
Create a generic `Value[T]` base class in the framework layer. All value objects standardize on `.value` access via inheritance.
## Changes
## Design
### 1. Dependencies
- Add `fastapi` and `uvicorn[standard]` to `pyproject.toml` under `[project.dependencies]`
- Install dependencies into the virtual environment
### `Value[T]` base class (`domain/framework/value.py`)
```python
@dataclass(frozen=True)
class Value(ABC, Generic[T]):
value: T
```
### 2. Application Entry Point
- Create `main.py` with a FastAPI app instance
- Add a health check endpoint (`GET /`) that returns `{"status": "ok"}`
- Frozen dataclass → immutability + structural equality (core Value Object semantics)
- `Generic[T]` → type-safe `.value` access in subclasses (e.g., `Value[str]`)
- `ABC` → mirrors the `Entity` pattern
### Subclasses
- `ClassifiedAdTitle(Value[str])` — drops `title: str`, inherits `value: T` bound to `str`
- `ClassifiedAdText(Value[str])` — drops `text: str`, inherits `value: T` bound to `str`
### Ripple effects
Every `.title` / `.text` reference on these objects becomes `.value`:
- `classified_ad.py``self.title.title``self.title.value`, construction calls, method bodies
- Tests — assertions, constructions, equality checks
## Files changed
| File | Change |
|------|--------|
| `domain/framework/value.py` | New — `Value[T]` base class |
| `domain/framework/__init__.py` | Add `Value` re-export |
| `domain/marketplace/classified_ad_title.py` | Inherit `Value[str]`, rename field |
| `domain/marketplace/classified_ad_text.py` | Inherit `Value[str]`, rename field |
| `domain/marketplace/classified_ad.py` | Update `.title`/`.text` refs → `.value` |
| `tests/test_classified_ad_title.py` | Update refs |
| `tests/test_classified_ad_text.py` | Update refs |
| `tests/test_classified_ad.py` | Update refs |
## Not in scope
`ClassifiedAdId`, `UserId`, `Money`, `Price` — stay as-is.
## Verification
- `pytest tests/` — all tests pass
- `uvicorn main:app --reload` — server starts and health endpoint responds
- `pytest tests/` — all 63 tests pass
- `ruff check .` && `ruff format --check .` — clean