Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Sruja Design Philosophy: The Unified Intuitive DSL

Objective

Create a modeling language that empowers all developers - from students to enterprise architects - to design systems with confidence, while naturally guiding them toward simplicity and preventing over-engineering.

Core Principles:

  1. Start simple, stay simple: A 1st-year CS student should be productive in 10 minutes, and advanced developers should be guided away from unnecessary complexity.
  2. Empower, don't restrict: The language should enable all developers, not limit them, but guide them toward good design.
  3. Approachability first: Complex concepts should be available but not encouraged unless truly needed.
  4. Prevent over-engineering: The language itself should make simple designs easier than complex ones.
  5. Systems thinking made simple: Enable holistic system understanding through intuitive syntax, without requiring complex theory.

Methodology Analysis

MethodologyCore ConceptsJargon LevelStudent IntuitionSruja Mapping
C4System, Container, ComponentLow"Boxes and lines" - Easy to grasp.system, container, component
DDDBounded Context, Aggregate, Entity, Value Object, Domain EventHigh"Aggregate Root" is confusing. "Value Object" is abstract.Not currently supported
ER (DB)Entity, Attribute, Relationship, Table, ColumnMedium"Entity" is standard. "Relationship" is clear.data, datastore, -> (relation)
API (OpenAPI)Path, Method, Schema, PropertyMedium"Endpoint" is clear. "Schema" is clear.api, data (as schema)
DODData, Struct, Array, TransformLow"Data" and "Struct" are very familiar to coders.data, [] (arrays)

The "Unified" Proposal

We need a set of keywords that map to these concepts without forcing the user to learn the specific theory first. The language should support progressive disclosure: simple concepts first, advanced concepts when needed.

1. Grouping (The "Container")

Problem: Different methodologies use different terms for logical boundaries.

MethodologyTermSruja KeywordWhen to Use
C4ContainercontainerTechnical deployment boundary (e.g., "Web Server", "Database")
GeneralGroupingmoduleGeneric logical grouping (most intuitive)

Decision:

  • module: Primary keyword for logical grouping. Familiar to Python/JS/Go developers.
  • container: For C4-style technical containers (deployment units).

Rationale: module is the most universal term. Students learn "modules" in their first programming course.

2. The "Thing" (Data Structure)

Problem: Entity vs Value Object vs Table vs Struct - all represent "data" but with different semantics.

MethodologyTermSruja KeywordSemantics
GeneralEntity/Structdata (with id)Has identity, mutable
GeneralValue/Structdata (no id)Immutable, defined by values
ERTable/Entitydata or datastorePersistent storage
DODStructdataIn-memory structure
APISchemadataRequest/response structure

Decision: data is the unified keyword.

Rules:

  • If data has an id field → Implicitly an Entity (has identity)
  • If data has no id → Implicitly a Value Object (value-based)
  • If data is in a datastore → Implicitly a database table
  • If data is in an api → Implicitly a request/response schema

Rationale: Students understand "data" immediately. The semantics emerge from context, not explicit keywords.

3. The "Action" (Behavior/Event)

Problem: Different types of actions need different modeling approaches.

TypeSruja KeywordPurposeExample
API EndpointapiExternal interfaceREST endpoint, GraphQL query
EventeventSomething that happenedOrderPlaced, PaymentProcessed
Function/Method(implicit in component)Internal behaviorBusiness logic in components

Decision:

  • api: Explicit API endpoints (students understand "API")
  • event: Events (something that happened)
  • Component behavior: Implicit (components contain behavior)

Rationale: Students learn APIs early. Events are intuitive ("something happened").

4. Relationships

Problem: How to model connections between elements?

Decision: Use arrow syntax -> for relationships.

User -> ShopAPI.WebApp "Uses"
ShopAPI.WebApp -> ShopAPI.Database "Reads/Writes"
Order -> Payment "Triggers"

Rationale: Arrows are universal. Everyone understands "A -> B" means "A relates to B".

Proposed Syntax: "The Universal Model"

Level 1: Beginner (C4 Style)

// Element kinds
person = kind "Person"
system = kind "System"
container = kind "Container"

// Elements
user = person "End User"

shop = system "Shop API" {
    webApp = container "Web Application" {
        technology "React"
    }

    db = container "PostgreSQL Database" {
        technology "PostgreSQL 14"
    }
}

// Relationships
user -> shop.webApp "Uses"
shop.webApp -> shop.db "Reads/Writes"

Level 2: Intermediate (Detailed Architecture)

// Element kinds
system = kind "System"
container = kind "Container"
component = kind "Component"
database = kind "Database"

// Architecture
ShopAPI = system "Shop API" {
    WebApp = container "Web Application" {
        technology "React"
        Cart = component "Shopping Cart"
        Checkout = component "Checkout Service"
    }

    API = container "API Gateway" {
        technology "Node.js"
    }

    DB = database "PostgreSQL Database" {
        technology "PostgreSQL 14"
    }
}

// Relationships
ShopAPI.WebApp -> ShopAPI.API "Calls"
ShopAPI.API -> ShopAPI.DB "Reads/Writes"

Level 3: Advanced (Governance + Operations)

// Element kinds
person = kind "Person"
system = kind "System"
container = kind "Container"
database = kind "Database"

// Elements
Customer = person "Customer"

Shop = system "E-commerce Shop" {
    description "High-performance e-commerce platform"

    API = container "API Gateway" {
        technology "Node.js"
        slo {
            latency {
                p95 "200ms"
                p99 "500ms"
            }
        }
        scale {
            min 3
            max 10
        }
    }

    DB = database "PostgreSQL" {
        technology "PostgreSQL 14"
    }
}

// Governance
R1 = requirement functional "Must support 10k concurrent users"
SecurityPolicy = policy "Encrypt all data" category "security" enforcement "required"

// Relationships
Customer -> Shop.API "Uses"
Shop.API -> Shop.DB "Reads/Writes"

Key Design Decisions

1. Progressive Disclosure

  • Beginner: Start with system, container, component (C4)
  • Intermediate: Add module, data, api, event (Unified)
  • Advanced: Use all features together for complex architectures

Rationale: Students can start simple and learn advanced concepts when needed.

2. Arrays: DOD-Style Syntax

Support [] syntax (e.g., items OrderItem[]) instead of just implied relationships.

Rationale: Very familiar to programmers. Makes data structures explicit.

3. Unified data Keyword

The data keyword represents data structures. The presence of an id field indicates an entity with identity.

Rationale: Reduces cognitive load. Students can model data structures without learning complex theory.

4. Explicit api Keyword

Model APIs alongside data to connect "Backend" to "Database".

Rationale: Students understand "APIs". This bridges the gap between data modeling and API design.

5. Context-Aware Semantics

The same keyword (data) means different things in different contexts:

  • In a module: Domain model
  • In a datastore: Database table
  • In an api: Request/response schema
  • In a component: Internal data structure

Rationale: One keyword, multiple interpretations based on context. Reduces vocabulary size.

Preventing Over-Engineering: Simplicity by Design

How Sruja Guides Toward Simplicity

1. Start Simple

  • Use system for technical/deployment modeling (C4 style)
  • Use module for logical grouping when needed
  • Keep it simple - don't add complexity unless necessary

2. Progressive Disclosure

  • Start with basic C4 concepts: system, container, component
  • Add module, data, api, event when you need more detail
  • Use only what you need for your use case

3. Natural Constraints

  • system syntax is straightforward for deployment modeling
  • The language guides you to use the right level of detail
  • Simple designs are easier to write than complex ones

4. Validation & Guidance (Future)

  • Warn if over-engineering simple systems
  • Help users choose the right level of detail
  • Guide toward simplicity

5. Clear Mental Models

  • system = "How is this deployed?" (Physical/Technical)
  • module = "How is this organized?" (Logical grouping)
  • Keep it focused on what you're actually modeling

Missing Concepts & Future Considerations

Currently Missing (but important):

  1. Constraints/Validation: How to express "email must be valid", "age > 0"?
  2. Relationships with Cardinality: User -> Order[1:*] (one-to-many)?
  3. Inheritance/Polymorphism: How to model "Payment extends Transaction"?
  4. Enums: status: OrderStatus where OrderStatus = [PENDING, COMPLETED, CANCELLED]
  5. Optional Fields: email?: string vs email string
  6. Defaults: status string = "PENDING"
  7. Computed Fields: total: float = items.sum(price * qty)

Recommendations:

  • Add enum keyword for enumerations
  • Support ? for optional fields: email? string
  • Support = for defaults: status string = "PENDING"
  • Consider constraint keyword for validation rules
  • Consider relationship syntax: User -> Order[1:*]
  • flow and scenario/story already implemented for flow thinking (DFD and BDD-style)

Migration Path

From C4 to Sruja:

// C4: System Context
system "E-Commerce System" {
    // C4: Container
    container "Web Application" {
        // C4: Component
        component "Order Controller"
    }
}

From Data Modeling to Sruja:

// Data structures
module Orders {
    data Order {
        id string
        items OrderItem[]
    }

    data OrderItem {
        product_id string
        qty int
    }

    data ShippingAddress {
        street string
        city string
    }
}

From ER to Sruja:

datastore Database {
    data User {
        id string
        email string
    }

    data Order {
        id string
        user_id string  // Foreign key relationship
    }
}

Systems Thinking: Simple and Intuitive

Goal: Empower developers to think about systems holistically - understanding how parts interact, boundaries, and emergent behavior - without requiring complex theory.

Core Systems Thinking Concepts (Simplified)

Systems thinking is about understanding:

  1. Parts and Relationships: How components connect and interact
  2. Boundaries: What's inside vs outside the system
  3. Flows: How information/data moves through the system
  4. Feedback Loops: How actions create reactions
  5. Context: The environment the system operates in

How Sruja Makes Systems Thinking Simple

1. Parts and Relationships (Already Built-In)

system ShopAPI {
    container WebApp
    container Database
}

ShopAPI.WebApp -> ShopAPI.Database "Reads/Writes"

Simple Insight: Just draw boxes and connect them with arrows. The relationships show how parts interact.

2. Boundaries (Natural in Sruja)

system ShopAPI {  // Inside boundary
    container WebApp
}

person User  // Outside boundary
User -> ShopAPI "Uses"

Simple Insight: system defines the boundary. person and external systems are outside. Clear and intuitive.

3. Flows (Built-In Flow Syntax)

// Data Flow Diagram (DFD) style — use scenario
scenario OrderProcess "Order Processing" {
    Customer -> Shop.WebApp "Order Details"
    Shop.WebApp -> Shop.Database "Save Order"
    Shop.Database -> Shop.WebApp "Confirmation"
}

// User Story/Scenario style
story Checkout "User Checkout Flow" {
    User -> ECommerce.CartPage "adds item to cart"
    ECommerce.CartPage -> ECommerce "clicks checkout"
    ECommerce -> Inventory "Check Stock"
}

// Or using simple qualified relationships
Customer -> Shop.WebApp "Submits Order"
Shop.WebApp -> Shop.OrderService "Processes"
Shop.OrderService -> Shop.PaymentService "Charges"

Simple Insight: Use flow for data flows (DFD), story/scenario for user stories, or simple relationships for basic flows. Events show what happens: event OrderPlaced.

4. Feedback Loops (Cycles in Relationships)

// Simple feedback: User action triggers system response
User -> System "Requests"
System -> User "Responds"

// System feedback: Component A affects Component B, which affects A
ComponentA -> ComponentB "Updates"
ComponentB -> ComponentA "Notifies"

// Event-driven cycles: Service A triggers Service B, which triggers A
ServiceA -> ServiceB "Sends Event"
ServiceB -> ServiceA "Responds with Event"

// Mutual dependencies: Microservices that call each other
OrderService -> PaymentService "Charges Payment"
PaymentService -> OrderService "Confirms Payment"

Simple Insight: When arrows form a cycle, that's a feedback loop. The system responds to itself. Cycles are valid in many architectures:

  • Feedback loops: User interactions, system responses
  • Event-driven patterns: Services triggering each other via events
  • Mutual dependencies: Microservices that need to communicate bidirectionally
  • Bidirectional flows: API <-> Database (read/write operations)

Note: Sruja allows cycles - they're a natural part of system design. The validator will inform you about cycles but won't block them, as they're often intentional architectural patterns.

5. Context (Persons and External Systems)

person Customer "End User"
person Admin "System Administrator"

system PaymentGateway "Third-party service" {
  tags ["external"]
}

Customer -> ShopAPI "Uses"
ShopAPI -> PaymentGateway "Processes payments"

Simple Insight: person and external show the context - who/what the system interacts with.

Progressive Systems Thinking

Beginner: Just model the parts and connections

// Element kinds
system = kind "System"
container = kind "Container"

// Elements
myApp = system "MyApp" {
    frontend = container "Frontend"
    backend = container "Backend"
}

// Relationships
myApp.frontend -> myApp.backend "Calls"

Intermediate: Add flows and events

// Simple qualified relationships
user -> myApp.frontend "Clicks"
myApp.frontend -> myApp.backend "Sends request"
myApp.backend -> myApp.database "Saves"

// DFD-style — use scenario
scenario OrderFlow "Order Processing" {
    user -> myApp.frontend "Submits"
    myApp.frontend -> myApp.backend "Processes"
    myApp.backend -> myApp.database "Stores"
}

Advanced: Model feedback loops and system behavior

// Feedback loop: User action -> System response -> User sees result
story CompleteOrder "Order Completion Flow" {
    user -> shop.system "Submits"
    shop.system -> shop.database "Stores"
    shop.system -> user "Confirms"
}

// Complex flow with multiple steps — use scenario
scenario PaymentFlow "Payment Processing" {
    orders.orderService -> orders.paymentGateway "Charge"
    orders.paymentGateway -> orders.orderService "Confirms"
    orders.orderService -> user "Notifies"
}

Key Principle: No Jargon Required

  • Don't say: "Model the feedback loop using systems thinking principles"
  • Do say: "Use flow or story to show how data/actions move through the system"
  • Don't say: "Define the system boundary using context mapping"
  • Do say: "Use system to show what's inside, person to show who uses it"
  • Don't say: "Create a DFD (Data Flow Diagram)"
  • Do say: "Use flow to show how data moves between components"

Result: Developers naturally think in systems without learning theory first. The syntax guides them to see:

  • How parts connect (relationships: ->)
  • What's inside vs outside (boundaries: system vs person/external)
  • How things flow (flow for data flows, story/scenario for user stories, or simple -> relationships)
  • How actions create reactions (cycles in relationships, feedback in flows)

Additional Design Philosophy Assessment

After assessing various design philosophies (Event-Driven Architecture, Hexagonal Architecture, CQRS, BDD, Reactive Systems, etc.) through a strict lens of "does this help developers learn system design?", we found:

✅ Accepted: Simple & Valuable

  1. Flows and Scenarios: Already implemented! flow for data flows (DFD), scenario/story for user stories (BDD-style Given-When-Then)
  2. Optional Fields: Practical data modeling (email? string)
  3. Enums: Practical data modeling (status: OrderStatus)

❌ Rejected: Too Complex or Unnecessary

  • Hexagonal Architecture (Ports & Adapters) - Too abstract
  • Clean Architecture / Layers - Too theoretical
  • CQRS - Too specialized, can use existing api
  • Advanced Event-Driven - Current event is sufficient
  • Reactive Systems - Too complex
  • Actor Model - Too specialized
  • GraphQL/Protocol Buffers - Technology-specific
  • Semantic Web - Overkill
  • SOLID (as syntax) - Principles, not syntax

Note: Systems thinking is accepted - but implemented simply through existing syntax (relationships, boundaries, flows). No new keywords needed.

Key Finding: Most "advanced" concepts should be rejected. Only 3 simple additions are recommended, and everything else can wait until developers master the basics. Systems thinking is naturally supported through intuitive syntax.

Conclusion

By using system, module, data, api, and event, we cover 90% of use cases with words that a 1st-year CS student already knows.

Key Success Metrics:

  • ✅ Can a beginner model a simple system in 10 minutes? Yes (C4 style)
  • ✅ Can an intermediate model data + APIs? Yes (Unified style)
  • ✅ Can an advanced user model complex architectures? Yes (Extended features)
  • ✅ Does it prevent over-engineering? Yes (simplicity by design)
  • ✅ Is it approachable for all developers? Yes (progressive disclosure)

Next Steps:

  1. Add enum support
  2. Add optional fields (? syntax)
  3. Add relationship cardinality
  4. Add constraint/validation syntax
  5. flow and scenario/story already implemented - enhance documentation and examples
  6. Improve error messages for beginners
  7. Add validation rules to guide simplicity

Key Principle: Less is more. Don't add complexity unless it clearly helps developers learn system design better. The goal is to build confidence through simplicity, not complexity through features.