347 lines
8.8 KiB
Markdown
347 lines
8.8 KiB
Markdown
# Canonical Example
|
||
|
||
This example demonstrates how the ABC Pattern structures a real application
|
||
using only:
|
||
|
||
* Constructs (ABC‑C0)
|
||
* Application Stack (ABC‑C1)
|
||
* Logical Units (ABC‑C2)
|
||
* Resource Groups (ABC‑C3)
|
||
* Input/Output Contracts (ABC‑C4, ABC‑C5)
|
||
* Instantiation Interface (ABC‑C6)
|
||
* Capturing Down (ABC‑C7)
|
||
* Bubbling Up (ABC‑C8)
|
||
|
||
Every interaction is explicit. Every dependency is visible. Nothing leaks
|
||
sideways.
|
||
|
||
## Overview
|
||
|
||
We model a classic 3‑tier architecture:
|
||
|
||
* Data Tier - database + storage
|
||
* Logic Tier - compute + messaging
|
||
* Presentation Tier - CDN + web frontend
|
||
|
||
Each tier is a Logical Unit (ABC‑C2).
|
||
|
||
Each component inside a tier is a Resource Group (ABC‑C3).
|
||
|
||
The Application Stack (ABC‑C1) composes them, wires them, and exposes the final
|
||
outputs.
|
||
|
||
## Conceptual Diagram
|
||
|
||
```default
|
||
┌──────────────────────────────┐
|
||
│ Application Stack │
|
||
│ (ABC‑C1) │
|
||
└─────────────┬────────────────┘
|
||
│
|
||
┌──────────────────────┼────────────────────────┐
|
||
│ │ │
|
||
┌───────▼────────┐ ┌───────▼────────┐ ┌─────────▼────────┐
|
||
│ DataUnit │ │ LogicUnit │ │ PresentationUnit │
|
||
│ (C2) │ │ (C2) │ │ (C2) │
|
||
└───────┬────────┘ └───────┬────────┘ └────────┬─────────┘
|
||
│ │ │
|
||
│ │ ┌────────│──────┐
|
||
┌────▼─────┐ ┌────▼─────┐ ┌────▼──────┐ ┌──────▼─────┐
|
||
│StorageGrp│ │ComputeGrp│ │WebAppGrp │ │ CDNGrp │
|
||
│ (C3) │ │ (C3) │ │ (C3) │ │ (C3) │
|
||
└──────────┘ └──────────┘ └───────────┘ └────────────┘
|
||
```
|
||
|
||
## Application Stack (ABC‑C1)
|
||
|
||
The Application Stack is the root construct.
|
||
|
||
It has no parent and defines the deployment boundary.
|
||
|
||
### Responsibilities
|
||
|
||
* Instantiate each Logical Unit (ABC‑R1).
|
||
* Provide downward inputs (ABC‑F1).
|
||
* Receive upward outputs (ABC‑F2).
|
||
* Route outputs between Logical Units (ABC‑R44).
|
||
* Expose a final Output Contract representing the whole system.
|
||
|
||
### Input Contract (ABC‑C4)
|
||
|
||
The Application Stack receives only global configuration:
|
||
|
||
```default
|
||
AppStackInputs:
|
||
environment: string
|
||
region: string
|
||
global_tags: map<string,string>
|
||
```
|
||
|
||
### Output Contract (ABC‑C5)
|
||
|
||
The Application Stack exposes:
|
||
|
||
```default
|
||
AppStackOutputs:
|
||
frontend_url: string
|
||
api_endpoint: string
|
||
```
|
||
|
||
These values originate from the Presentation and Logic tiers, respectively.
|
||
|
||
## Logical Units (ABC‑C2)
|
||
|
||
Each Logical Unit encapsulates a functional domain.
|
||
|
||
They do not know about each other.
|
||
|
||
They communicate only through the Application Stack.
|
||
|
||
We define three:
|
||
|
||
* DataUnit
|
||
* LogicUnit
|
||
* PresentationUnit
|
||
|
||
Each has its own Input/Output Contracts and internal Resource Groups.
|
||
|
||
### Data Logical Unit (ABC‑C2)
|
||
|
||
#### Purpose
|
||
|
||
Provide persistent storage and database capabilities.
|
||
|
||
#### Resource Groups (ABC‑C3)
|
||
|
||
* StorageGroup - object storage
|
||
* DatabaseGroup - relational database
|
||
|
||
#### Input Contract
|
||
|
||
```default
|
||
DataUnitInputs:
|
||
environment: string
|
||
region: string
|
||
storage_class: string
|
||
db_engine: string
|
||
db_instance_size: string
|
||
```
|
||
|
||
#### Output Contract
|
||
|
||
```default
|
||
DataUnitOutputs:
|
||
storage_bucket_name: string
|
||
database_endpoint: string
|
||
```
|
||
|
||
#### Internal Wiring
|
||
|
||
* StorageGroup produces `storage_bucket_name`.
|
||
* DatabaseGroup produces `database_endpoint`.
|
||
* DataUnit aggregates both and bubbles them up (ABC‑F2).
|
||
|
||
#### NOTE
|
||
* StorageGroup and DatabaseGroup do not know about each other (ABC‑R10).
|
||
* All configuration flows downward from DataUnit (ABC‑F1).
|
||
|
||
### Logic Logical Unit (ABC‑C2)
|
||
|
||
#### Purpose
|
||
|
||
Provide compute and messaging capabilities for the application backend.
|
||
|
||
#### Resource Groups
|
||
|
||
* ComputeGroup - application compute (e.g., functions, containers)
|
||
* MessagingGroup - queue or pub/sub system
|
||
|
||
#### Input Contract
|
||
|
||
```default
|
||
LogicUnitInputs:
|
||
environment: string
|
||
region: string
|
||
compute_size: string
|
||
message_retention: number
|
||
database_endpoint: string # Provided by DataUnit via AppStack
|
||
```
|
||
|
||
#### Output Contract
|
||
|
||
```default
|
||
LogicUnitOutputs:
|
||
api_endpoint: string
|
||
message_queue_url: string
|
||
```
|
||
|
||
#### Internal Wiring
|
||
|
||
* ComputeGroup receives `database_endpoint` via Capturing Down (ABC‑F1).
|
||
* MessagingGroup is independent.
|
||
* LogicUnit aggregates outputs and bubbles them up.
|
||
|
||
#### NOTE
|
||
* LogicUnit does not know where the database came from.
|
||
* It only knows it received a database_endpoint in its Input Contract
|
||
(ABC‑R22).
|
||
|
||
### Presentation Logical Unit (ABC‑C2)
|
||
|
||
#### Purpose
|
||
|
||
Serve the frontend and expose the public entry point.
|
||
|
||
#### Resource Groups
|
||
|
||
* CDNGroup - global content distribution
|
||
* WebAppGroup - static or dynamic frontend
|
||
|
||
#### Input Contract
|
||
|
||
```default
|
||
PresentationUnitInputs:
|
||
environment: string
|
||
region: string
|
||
frontend_assets_bucket: string
|
||
api_endpoint: string # Provided by LogicUnit via AppStack
|
||
```
|
||
|
||
#### Output Contract
|
||
|
||
```default
|
||
PresentationUnitOutputs:
|
||
frontend_url: string
|
||
```
|
||
|
||
#### Internal Wiring
|
||
|
||
* WebAppGroup receives `api_endpoint` via Capturing Down.
|
||
* CDNGroup receives the output of WebAppGroup.
|
||
* PresentationUnit bubbles up the final `frontend_url`.
|
||
|
||
## Resource Groups (ABC‑C3)
|
||
|
||
Each Resource Group is a small, focused construct with:
|
||
|
||
* A minimal Input Contract
|
||
* A minimal Output Contract
|
||
* No knowledge of siblings
|
||
* No access to parent state except via inputs
|
||
* No side effects during instantiation (ABC‑R33)
|
||
|
||
### Example: Database Group
|
||
|
||
#### Input Contract
|
||
|
||
```default
|
||
DatabaseGroupInputs:
|
||
db_engine: string
|
||
db_instance_size: string
|
||
environment: string
|
||
```
|
||
|
||
#### Output Contract
|
||
|
||
```default
|
||
DatabaseGroupOutputs:
|
||
database_endpoint: string
|
||
```
|
||
|
||
#### Instantiation Interface
|
||
|
||
```default
|
||
new DatabaseGroup(DatabaseGroupInputs) -> DatabaseGroupOutputs
|
||
```
|
||
|
||
This pattern repeats for all Resource Groups.
|
||
|
||
## Full Data Flow (ABC‑F1 and ABC‑F2)
|
||
|
||
The complete data flow includes:
|
||
|
||
* AppStack → Logical Units
|
||
* Logical Units → Resource Groups
|
||
* Resource Groups → Logical Units
|
||
* Logical Units → AppStack
|
||
|
||
This is the full vertical chain required by the ABC Pattern.
|
||
|
||
### Downward Flow (Capturing Down — ABC‑F1)
|
||
|
||
1. AppStack → DataUnit
|
||
: * `environment`
|
||
* `region`
|
||
* `storage_class`
|
||
* `db_engine`
|
||
* `db_instance_size`
|
||
2. DataUnit → StorageGroup
|
||
: * `environment`
|
||
* `region`
|
||
* `storage_class`
|
||
3. DataUnit → DatabaseGroup
|
||
: * `environment`
|
||
* `db_engine`
|
||
* `db_instance_size`
|
||
4. AppStack → LogicUnit
|
||
> * `environment`
|
||
> * `region`
|
||
> * `compute_size`
|
||
> * `message_retention`
|
||
> * `database_endpoint` (bubbled up from DataUnit)
|
||
5. LogicUnit → ComputeGroup
|
||
: * `environment`
|
||
* `compute_size`
|
||
* `database_endpoint`
|
||
6. LogicUnit → MessagingGroup
|
||
: * `environment`
|
||
* `message_retention`
|
||
7. AppStack → PresentationUnit
|
||
: * `environment`
|
||
* `region`
|
||
* `frontend_assets_bucket`
|
||
* `api_endpoint` (bubbled up from LogicUnit)
|
||
8. PresentationUnit → WebAppGroup
|
||
: * `environment`
|
||
* `frontend_assets_bucket`
|
||
* `api_endpoint`
|
||
9. PresentationUnit → CDNGroup
|
||
: * `environment`
|
||
* `webapp_origin_url` (bubbled up from WebAppGroup)
|
||
|
||
### Upward Flow (Bubbling Up — ABC‑F2)
|
||
|
||
1. StorageGroup → DataUnit
|
||
: * `storage_bucket_name`
|
||
2. DatabaseGroup → DataUnit
|
||
: * `database_endpoint`
|
||
3. DataUnit → AppStack
|
||
: * `storage_bucket_name`
|
||
* `database_endpoint`
|
||
4. ComputeGroup → LogicUnit
|
||
: * `api_endpoint`
|
||
5. MessagingGroup → LogicUnit
|
||
: * `message_queue_url`
|
||
6. LogicUnit → AppStack
|
||
: * `api_endpoint`
|
||
* `message_queue_url`
|
||
7. WebAppGroup → PresentationUnit
|
||
: * `webapp_origin_url`
|
||
8. CDNGroup → PresentationUnit
|
||
: * `frontend_url`
|
||
9. PresentationUnit → AppStack
|
||
: * `frontend_url`
|
||
|
||
## Rationale
|
||
|
||
This example demonstrates:
|
||
|
||
* Strict encapsulation
|
||
* Explicit dependencies
|
||
* No lateral references
|
||
* Deterministic wiring
|
||
* Testability at every level
|
||
* Predictable evolution
|
||
* Agent‑friendly structure
|
||
|
||
It is the canonical reference for all profiles (CDK, Terraform, etc.).
|