From a30502edd9a175bb4d33bc14718e6ccf81abd5e7 Mon Sep 17 00:00:00 2001 From: Nano Taboada <87288+nanotaboada@users.noreply.github.com> Date: Mon, 16 Mar 2026 20:59:31 -0300 Subject: [PATCH 1/3] docs(readme): update architecture diagram and add explanatory text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Adds aiocache node, fixes sqlalchemy→routes to soft dependency, and reorganizes arrows with Strong/Soft groupings - Adds Arrow Semantics, Composition Root, Layered Architecture, and Color Coding sections - Adds Claude co-author to commit template in copilot-instructions.md Co-Authored-By: Claude Sonnet 4.6 --- .github/copilot-instructions.md | 1 + README.md | 69 ++++++++++++++++++++++----------- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 8cb8fe8..3523477 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -130,4 +130,5 @@ Example: `feat(api): add player stats endpoint (#42)` feat(scope): description (#issue) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> +Co-authored-by: Claude ``` diff --git a/README.md b/README.md index d318829..4fc8568 100644 --- a/README.md +++ b/README.md @@ -86,68 +86,93 @@ Proof of Concept for a RESTful API built with [Python 3](https://www.python.org/ ## Architecture +Layered architecture with dependency injection via FastAPI's `Depends()` mechanism and Pydantic for request/response validation. + ```mermaid %%{init: { "theme": "default", "themeVariables": { "fontFamily": "Fira Code, Consolas, monospace", "textColor": "#555", - "lineColor": "#555", - "lineWidth": 2 + "lineColor": "#555" } }}%% -graph BT - %% Core application packages +graph RL + + tests[tests] + main[main] routes[routes] + fastapi[FastAPI] + aiocache[aiocache] + services[services] - schemas[schemas] - databases[databases] + models[models] + pydantic[Pydantic] - %% External dependencies - fastapi[FastAPI] + schemas[schemas] + + databases[databases] sqlalchemy[SQLAlchemy] - pydantic[Pydantic] - %% Test coverage - tests[tests] + %% Strong dependencies - %% Module dependencies routes --> main fastapi --> main + + fastapi --> routes + aiocache --> routes services --> routes models --> routes databases --> routes + schemas --> services models --> services - databases --> schemas - fastapi --> routes - sqlalchemy --> routes sqlalchemy --> services + pydantic --> models + + databases --> schemas sqlalchemy --> schemas sqlalchemy --> databases - pydantic --> models + + %% Soft dependencies + + sqlalchemy -.-> routes main -.-> tests - %% Node styling + %% Node styling with stroke-width classDef core fill:#b3d9ff,stroke:#6db1ff,stroke-width:2px,color:#555,font-family:monospace; classDef deps fill:#ffcccc,stroke:#ff8f8f,stroke-width:2px,color:#555,font-family:monospace; classDef test fill:#ccffcc,stroke:#53c45e,stroke-width:2px,color:#555,font-family:monospace; class main,routes,services,schemas,databases,models core - class fastapi,sqlalchemy,pydantic deps + class fastapi,sqlalchemy,pydantic,aiocache deps class tests test ``` -**Arrow Semantics:** Solid arrows represent import-time module dependencies — the arrow points from the dependency to the consumer. The dotted arrow to `tests` indicates the integration tests validate the full application stack as wired by `main`. +*Simplified, conceptual view — not all components or dependencies are shown.* + +### Arrow Semantics + +Arrows point from a dependency toward its consumer. Solid arrows (`-->`) denote **strong (functional) dependencies**: the consumer actively invokes behavior — registering route handlers, dispatching requests, executing async queries, or managing the database session. Dotted arrows (`-.->`) denote **soft (structural) dependencies**: the consumer only references types without invoking runtime behavior. This distinction follows UML's `«use»` dependency notation and classical coupling theory (Myers, 1978): strong arrows approximate *control or stamp coupling*, while soft arrows approximate *data coupling*, where only shared data structures cross the boundary. + +### Composition Root Pattern + +The `main` module acts as the composition root — it creates the FastAPI application instance, configures the lifespan handler, and registers all route modules via `app.include_router()`. Rather than explicit object construction, dependency injection is provided by FastAPI's built-in `Depends()` mechanism: `routes` declare their dependencies (e.g. `AsyncSession`) as function parameters and FastAPI resolves them at request time. This pattern enables dependency injection, improves testability, and ensures no other module bears responsibility for wiring or lifecycle management. + +### Layered Architecture + +The codebase is organized into four conceptual layers: Initialization (`main`), HTTP (`routes`), Business (`services`), and Data (`schemas`, `databases`). + +Third-party dependencies are co-resident within the layer that consumes them: `FastAPI` and `aiocache` inside HTTP, and `SQLAlchemy` inside Data. `SQLAlchemy` holds a soft dependency on `routes` — `AsyncSession` is referenced only as a type annotation in `Depends()`, without any direct SQLAlchemy method calls at the route level. -**Composition Root Pattern:** The `main` module acts as the composition root — it imports `FastAPI` and the route modules, creates the app instance, and registers all routers. This pattern enables dependency injection via `Depends()`, improves testability, and maintains clear separation of concerns. +The `models` package is a **cross-cutting type concern** — it defines Pydantic request and response models consumed across multiple layers, without containing logic or behavior of its own. Dependencies always flow from consumers toward their lower-level types: each layer depends on (consumes) the layers below it, and no layer invokes behavior in a layer above it. -**Layered Architecture:** Each layer has a specific responsibility — routes handle HTTP mapping, validation, and in-memory caching, services contain business logic, schemas define the ORM model, and databases manage the async session. +### Color Coding -**Color Coding:** Core packages (blue) implement the application logic, external dependencies (red) are third-party frameworks and ORMs, and tests (green) ensure code quality. +Core packages (blue) implement the application logic, third-party dependencies (red) are community packages, and tests (green) ensure code quality. ## API Reference From 29087e6de968a05831d2fc592e23641b9ac9e7c3 Mon Sep 17 00:00:00 2001 From: Nano Taboada <87288+nanotaboada@users.noreply.github.com> Date: Mon, 16 Mar 2026 21:01:01 -0300 Subject: [PATCH 2/3] docs(github): add bug report issue template Co-Authored-By: Claude Sonnet 4.6 --- .github/ISSUE_TEMPLATE/bug_report.md | 40 ++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..2a780c9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,40 @@ +--- +name: Bug report +about: Report a bug or unexpected behavior +title: "[BUG]" +labels: bug +assignees: '' + +--- + +## Description + +A clear and concise description of what the bug is. + +## Steps to Reproduce + +1. Step 1 +2. Step 2 +3. Step 3 + +## Expected Behavior + +What you expected to happen. + +## Actual Behavior + +What actually happened. + +## Environment + +- **Python version:** (output of `python --version`) +- **FastAPI version:** (from `pyproject.toml`) +- **OS:** (e.g., macOS 14.0, Ubuntu 22.04, Windows 11) + +## Additional Context + +Add any other context about the problem here (logs, screenshots, etc.). + +## Possible Solution + +(Optional) Suggest a fix or workaround if you have one. From 502b256c055277060c6b9130c205e8726608a959 Mon Sep 17 00:00:00 2001 From: Nano Taboada Date: Mon, 16 Mar 2026 21:21:48 -0300 Subject: [PATCH 3/3] docs(readme): fix soft dependency direction for routes and SQLAlchemy Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Claude --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4fc8568..3f26678 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,7 @@ The `main` module acts as the composition root — it creates the FastAPI applic The codebase is organized into four conceptual layers: Initialization (`main`), HTTP (`routes`), Business (`services`), and Data (`schemas`, `databases`). -Third-party dependencies are co-resident within the layer that consumes them: `FastAPI` and `aiocache` inside HTTP, and `SQLAlchemy` inside Data. `SQLAlchemy` holds a soft dependency on `routes` — `AsyncSession` is referenced only as a type annotation in `Depends()`, without any direct SQLAlchemy method calls at the route level. +Third-party dependencies are co-resident within the layer that consumes them: `FastAPI` and `aiocache` inside HTTP, and `SQLAlchemy` inside Data. `routes` holds a soft dependency on `SQLAlchemy` — `AsyncSession` is referenced only as a type annotation in `Depends()`, without any direct SQLAlchemy method calls at the route level. The `models` package is a **cross-cutting type concern** — it defines Pydantic request and response models consumed across multiple layers, without containing logic or behavior of its own. Dependencies always flow from consumers toward their lower-level types: each layer depends on (consumes) the layers below it, and no layer invokes behavior in a layer above it.