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:
- 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.
- Empower, don't restrict: The language should enable all developers, not limit them, but guide them toward good design.
- Approachability first: Complex concepts should be available but not encouraged unless truly needed.
- Prevent over-engineering: The language itself should make simple designs easier than complex ones.
- Systems thinking made simple: Enable holistic system understanding through intuitive syntax, without requiring complex theory.
Methodology Analysis
| Methodology | Core Concepts | Jargon Level | Student Intuition | Sruja Mapping |
|---|---|---|---|---|
| C4 | System, Container, Component | Low | "Boxes and lines" - Easy to grasp. | system, container, component |
| DDD | Bounded Context, Aggregate, Entity, Value Object, Domain Event | High | "Aggregate Root" is confusing. "Value Object" is abstract. | Not currently supported |
| ER (DB) | Entity, Attribute, Relationship, Table, Column | Medium | "Entity" is standard. "Relationship" is clear. | data, datastore, -> (relation) |
| API (OpenAPI) | Path, Method, Schema, Property | Medium | "Endpoint" is clear. "Schema" is clear. | api, data (as schema) |
| DOD | Data, Struct, Array, Transform | Low | "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.
| Methodology | Term | Sruja Keyword | When to Use |
|---|---|---|---|
| C4 | Container | container | Technical deployment boundary (e.g., "Web Server", "Database") |
| General | Grouping | module | Generic 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.
| Methodology | Term | Sruja Keyword | Semantics |
|---|---|---|---|
| General | Entity/Struct | data (with id) | Has identity, mutable |
| General | Value/Struct | data (no id) | Immutable, defined by values |
| ER | Table/Entity | data or datastore | Persistent storage |
| DOD | Struct | data | In-memory structure |
| API | Schema | data | Request/response structure |
Decision: data is the unified keyword.
Rules:
- If
datahas anidfield → Implicitly an Entity (has identity) - If
datahas noid→ Implicitly a Value Object (value-based) - If
datais in adatastore→ Implicitly a database table - If
datais in anapi→ 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.
| Type | Sruja Keyword | Purpose | Example |
|---|---|---|---|
| API Endpoint | api | External interface | REST endpoint, GraphQL query |
| Event | event | Something that happened | OrderPlaced, PaymentProcessed |
| Function/Method | (implicit in component) | Internal behavior | Business 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
systemfor technical/deployment modeling (C4 style) - Use
modulefor 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,eventwhen you need more detail - Use only what you need for your use case
3. Natural Constraints
systemsyntax 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):
- Constraints/Validation: How to express "email must be valid", "age > 0"?
- Relationships with Cardinality:
User -> Order[1:*](one-to-many)? - Inheritance/Polymorphism: How to model "Payment extends Transaction"?
- Enums:
status: OrderStatuswhereOrderStatus = [PENDING, COMPLETED, CANCELLED] - Optional Fields:
email?: stringvsemail string - Defaults:
status string = "PENDING" - Computed Fields:
total: float = items.sum(price * qty)
Recommendations:
- Add
enumkeyword for enumerations - Support
?for optional fields:email? string - Support
=for defaults:status string = "PENDING" - Consider
constraintkeyword for validation rules - Consider relationship syntax:
User -> Order[1:*] - ✅
flowandscenario/storyalready 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:
- Parts and Relationships: How components connect and interact
- Boundaries: What's inside vs outside the system
- Flows: How information/data moves through the system
- Feedback Loops: How actions create reactions
- 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
floworstoryto show how data/actions move through the system" - Don't say: "Define the system boundary using context mapping"
- Do say: "Use
systemto show what's inside,personto show who uses it" - Don't say: "Create a DFD (Data Flow Diagram)"
- Do say: "Use
flowto 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:
systemvsperson/external) - How things flow (
flowfor data flows,story/scenariofor 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
- ✅ Flows and Scenarios: Already implemented!
flowfor data flows (DFD),scenario/storyfor user stories (BDD-style Given-When-Then) - Optional Fields: Practical data modeling (
email? string) - 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
eventis 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:
- Add
enumsupport - Add optional fields (
?syntax) - Add relationship cardinality
- Add constraint/validation syntax
- ✅
flowandscenario/storyalready implemented - enhance documentation and examples - Improve error messages for beginners
- 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.