# Relation Types for C4 Code Elements This guide provides comprehensive documentation of relationship types between code elements at the C4 Code level. --- ## Overview Relations describe how code elements interact with each other. Each relation has: - **target**: The code element being related to - **type**: The nature of the relationship - **description**: Active voice description of the relationship --- ## Code Flow Relations ### calls **Definition:** Invokes another function or method **When to use:** When a function/method directly calls another **Examples:** ```typescript function processOrder(order: Order) { validateOrder(order); // calls validateOrder calculateTotal(order); // calls calculateTotal } ``` **JSON:** ```json { "target": "validate-order", "type": "calls", "description": "Calls validateOrder to validate order structure" } ``` --- ### awaits **Definition:** Awaits an async function **When to use:** When async function awaits another async function **Examples:** ```typescript async function getUser(id: string) { const user = await userRepository.findById(id); // awaits findById return user; } ``` **JSON:** ```json { "target": "user-repository-find-by-id", "type": "awaits", "description": "Awaits UserRepository.findById for user lookup" } ``` --- ### returns **Definition:** Returns a specific type **When to use:** When documenting what type a function returns **Examples:** ```typescript function createUser(data: UserInput): User { return new User(data); // returns User } ``` **JSON:** ```json { "target": "user-class", "type": "returns", "description": "Returns User instance with provided data" } ``` --- ### throws **Definition:** Throws an exception type **When to use:** When function explicitly throws an exception **Examples:** ```typescript function validateAge(age: number) { if (age < 0) { throw new ValidationError('Age cannot be negative'); // throws ValidationError } } ``` **JSON:** ```json { "target": "validation-error-class", "type": "throws", "description": "Throws ValidationError when age is negative" } ``` --- ## Structural Relations ### inherits **Definition:** Extends another class **When to use:** When a class extends a parent class **Examples:** ```typescript class AdminUser extends User { // inherits from User permissions: string[]; } ``` **JSON:** ```json { "target": "user-class", "type": "inherits", "description": "Inherits from User base class" } ``` --- ### implements **Definition:** Implements an interface **When to use:** When a class implements an interface contract **Examples:** ```typescript class UserService implements IUserService { // implements IUserService getUser(id: string): User { ... } } ``` **JSON:** ```json { "target": "i-user-service-interface", "type": "implements", "description": "Implements IUserService interface contract" } ``` --- ### declares **Definition:** Declares a type or interface **When to use:** When defining the shape of data used elsewhere **Examples:** ```typescript interface UserInput { // declares shape for createUser name: string; email: string; } function createUser(input: UserInput) { ... } ``` **JSON:** ```json { "target": "create-user-function", "type": "declares", "description": "Declares the input shape for createUser function" } ``` --- ### uses-type **Definition:** Uses a type in signature or body **When to use:** When function uses a type for parameters, return, or internally **Examples:** ```typescript function processPayment(payment: Payment): PaymentResult { // Uses Payment type for input // Uses PaymentResult type for output } ``` **JSON:** ```json { "target": "payment-type", "type": "uses-type", "description": "Uses Payment type for input parameter" } ``` --- ## Data Relations ### creates **Definition:** Instantiates a class **When to use:** When function creates new instance of a class **Examples:** ```typescript function createOrder(items: Item[]): Order { return new Order(items); // creates Order instance } ``` **JSON:** ```json { "target": "order-class", "type": "creates", "description": "Creates new Order instance with provided items" } ``` --- ### mutates **Definition:** Modifies state or data **When to use:** When function modifies object state **Examples:** ```typescript function updateUser(user: User, data: Partial) { Object.assign(user, data); // mutates user object } ``` **JSON:** ```json { "target": "user-class", "type": "mutates", "description": "Mutates User instance with provided data" } ``` --- ### reads **Definition:** Reads from data source **When to use:** When function reads data without modifying **Examples:** ```typescript function getUserName(user: User): string { return user.name; // reads from User } ``` **JSON:** ```json { "target": "user-class", "type": "reads", "description": "Reads name property from User instance" } ``` --- ## Dependency Relations ### imports **Definition:** Imports from another module **When to use:** When code imports from another file/module **Examples:** ```typescript import { UserService } from './services/user'; // imports UserService ``` **JSON:** ```json { "target": "user-service-class", "type": "imports", "description": "Imports UserService from services module" } ``` --- ### depends-on **Definition:** General dependency relationship **When to use:** When there's a dependency that doesn't fit other categories **Examples:** ```typescript class OrderService { constructor( private userService: UserService, // depends-on UserService private paymentService: PaymentService // depends-on PaymentService ) {} } ``` **JSON:** ```json { "target": "user-service-class", "type": "depends-on", "description": "Depends on UserService for user operations" } ``` --- ### overrides **Definition:** Overrides parent class method **When to use:** When method overrides a parent method **Examples:** ```typescript class AdminUser extends User { override toString(): string { // overrides User.toString return `Admin: ${this.name}`; } } ``` **JSON:** ```json { "target": "user-class-to-string", "type": "overrides", "description": "Overrides User.toString to include admin prefix" } ``` --- ## Relation Type Summary | Type | Category | Description | |------|----------|-------------| | `calls` | Code Flow | Invokes function/method | | `awaits` | Code Flow | Awaits async function | | `returns` | Code Flow | Returns specific type | | `throws` | Code Flow | Throws exception | | `inherits` | Structural | Extends class | | `implements` | Structural | Implements interface | | `declares` | Structural | Declares type/interface | | `uses-type` | Structural | Uses type in signature | | `creates` | Data | Instantiates class | | `mutates` | Data | Modifies state | | `reads` | Data | Reads data | | `imports` | Dependency | Imports from module | | `depends-on` | Dependency | General dependency | | `overrides` | Dependency | Overrides parent method | --- ## Complete Example ```json { "relations": [ { "target": "base-service-class", "type": "inherits", "description": "Inherits common service functionality from BaseService" }, { "target": "i-user-service-interface", "type": "implements", "description": "Implements IUserService interface contract" }, { "target": "user-repository", "type": "depends-on", "description": "Depends on UserRepository for data persistence" }, { "target": "user-repository-find-by-id", "type": "awaits", "description": "Awaits UserRepository.findById for user lookup" }, { "target": "user-class", "type": "returns", "description": "Returns User instance to caller" }, { "target": "user-not-found-error", "type": "throws", "description": "Throws UserNotFoundError when user doesn't exist" } ] } ``` --- ## Best Practices ### ✅ DO: - Use active voice in descriptions - Be specific about what is being called/used - Document all significant relationships - Use the most specific relation type ### ❌ DON'T: - Use passive voice ("is called by") - Skip obvious but important relations - Use generic descriptions - Mix relation types inappropriately --- ## Relation Direction All relations are **outbound** from the source element: - Source element → **calls** → Target element - Source element → **inherits** → Target element - Source element → **depends-on** → Target element Do NOT document reverse relations (e.g., "is called by"). The target element's incoming relations can be derived from the source elements' outbound relations.