Skip to content

Architecture Decision: Use src/ (core) instead of domains/ for NodeSpec #3

@deepracticexs

Description

@deepracticexs

Context

During the design phase, we discussed whether to use domains/ (DDD approach) or src/ (core/technical layering) for the product's business logic.

Key Insight

One monorepo = One product = One bounded context

The repository boundary itself defines the domain boundary. There's no need for an additional domains/ directory when:

  • Each monorepo represents a single product
  • Future products will have their own repositories (e.g., DeepracticeAccount, DeepracticeCI)

Architecture Philosophy

The Nature of src/

src/ contains product-specific business logic that:

  • Is highly specialized for this product
  • Is NOT intended for sharing across projects
  • Serves only this product's needs

Naming Semantics: domain vs core

When to use domain/ (DDD approach)

  • Business-heavy products: Complex business rules, frequent changes
  • Modeling approach: Entities, Aggregates, Domain Services, Value Objects
  • Thinking mode: Business concepts first (Order, User, Payment)
  • Advantage: Express business rules without deep technical details
  • Examples: E-commerce, CRM, Financial systems

```typescript
// domain style
class Order extends AggregateRoot {
items: OrderItem[];

addItem(product: Product, quantity: number) {
if (this.items.length >= 100) {
throw new BusinessRuleError('Max 100 items per order');
}
}
}
```

When to use core/ (Technical layering)

  • Tech-heavy products: Algorithm-intensive, clear technical logic
  • Modeling approach: Modules, Services, Utility functions
  • Thinking mode: Technical implementation first (Template Engine, Parser, Executor)
  • Advantage: Clear technical details, optimization-friendly
  • Examples: CLI tools, Compilers, Frameworks

```typescript
// core style
class TemplateEngine {
parse(template: string): AST { }
compile(ast: AST): Function { }
render(compiled: Function, data: object): string { }
}
```

Decision for NodeSpec

NodeSpec is a technical product, characterized by:

  • Template generation = technical logic
  • File operations = technical logic
  • Command orchestration = technical logic
  • Performance-sensitive (CLI startup speed)

Therefore: Use src/ (core approach)

Final Architecture

```
DeepracticeNodeSpec/
├── src/ # Product core (technical layering)
│ ├── template/ # Template engine
│ ├── guide/ # Documentation lookup
│ └── executor/ # Task executor

├── packages/ # Ecosystem - Reusable capabilities
│ ├── logger/ # Used internally and externally
│ └── error-handling/

├── configs/ # Ecosystem - Reusable standards
│ ├── eslint-config/
│ └── prettier-config/

└── apps/ # Product interfaces
└── cli/ # Command-line interface (depends on src/)
```

Product as Ecosystem

The monorepo serves dual purposes:

  1. Product: NodeSpec itself
  2. Ecosystem: packages/ and configs/ become independently usable

Evolution path:

  • Build the product → Polish the tools
  • Good tools → External adoption
  • External usage → Tool improvement

This is the "sharpening stone" strategy - building a product naturally creates an ecosystem.

Decision Rationale

Simple and clear: src/ = business logic, obvious meaning
Scalable: packages naturally become ecosystem
Clear responsibilities: Each directory has obvious purpose
Occam's Razor: Simplest solution that works

Next Steps

  • Remove domains/ directory
  • Create src/ directory with appropriate structure
  • Update architecture documentation
  • Begin CLI implementation using this structure

Core principle: Repository boundary = Domain boundary. Use domain/ for business complexity, core/ (src/) for technical products.

🤖 Generated via github-issue-manager agent

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions