8.8 KiB
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
┌──────────────────────────────┐
│ 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:
AppStackInputs:
environment: string
region: string
global_tags: map<string,string>
Output Contract (ABC‑C5)
The Application Stack exposes:
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
DataUnitInputs:
environment: string
region: string
storage_class: string
db_engine: string
db_instance_size: string
Output Contract
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
LogicUnitInputs:
environment: string
region: string
compute_size: string
message_retention: number
database_endpoint: string # Provided by DataUnit via AppStack
Output Contract
LogicUnitOutputs:
api_endpoint: string
message_queue_url: string
Internal Wiring
- ComputeGroup receives
database_endpointvia 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
PresentationUnitInputs:
environment: string
region: string
frontend_assets_bucket: string
api_endpoint: string # Provided by LogicUnit via AppStack
Output Contract
PresentationUnitOutputs:
frontend_url: string
Internal Wiring
- WebAppGroup receives
api_endpointvia 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
DatabaseGroupInputs:
db_engine: string
db_instance_size: string
environment: string
Output Contract
DatabaseGroupOutputs:
database_endpoint: string
Instantiation Interface
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)
-
- AppStack → DataUnit
environmentregionstorage_classdb_enginedb_instance_size
-
- DataUnit → StorageGroup
environmentregionstorage_class
-
- DataUnit → DatabaseGroup
environmentdb_enginedb_instance_size
- AppStack → LogicUnit
environmentregioncompute_sizemessage_retentiondatabase_endpoint(bubbled up from DataUnit)
-
- LogicUnit → ComputeGroup
environmentcompute_sizedatabase_endpoint
-
- LogicUnit → MessagingGroup
environmentmessage_retention
-
- AppStack → PresentationUnit
environmentregionfrontend_assets_bucketapi_endpoint(bubbled up from LogicUnit)
-
- PresentationUnit → WebAppGroup
environmentfrontend_assets_bucketapi_endpoint
-
- PresentationUnit → CDNGroup
environmentwebapp_origin_url(bubbled up from WebAppGroup)
Upward Flow (Bubbling Up — ABC‑F2)
-
- StorageGroup → DataUnit
storage_bucket_name
-
- DatabaseGroup → DataUnit
database_endpoint
-
- DataUnit → AppStack
storage_bucket_namedatabase_endpoint
-
- ComputeGroup → LogicUnit
api_endpoint
-
- MessagingGroup → LogicUnit
message_queue_url
-
- LogicUnit → AppStack
api_endpointmessage_queue_url
-
- WebAppGroup → PresentationUnit
webapp_origin_url
-
- CDNGroup → PresentationUnit
frontend_url
-
- 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.).