Create Controllers Layer
Issue: #TBD
Parent Epic: #154 - Presentation Layer Reorganization
Related: Presentation Layer Reorganization Refactor Plan
Overview
Transform the src/presentation/commands/ directory into a Controllers Layer using standard MVC terminology and integrate it fully with the existing ExecutionContext and Container for dependency injection. This proposal establishes the third layer of the four-layer presentation architecture.
Goals
🏗️ Architecture Requirements
DDD Layer: Presentation
Module Path: src/presentation/controllers/
Pattern: Controller Layer (MVC pattern)
Module Structure Requirements
Architectural Constraints
Anti-Patterns to Avoid
- ❌ Direct service instantiation in controllers
- ❌ Business logic in presentation layer
- ❌ Factory pattern duplication of Container
- ❌ Inconsistent naming between controller modules
Specifications
Current State Analysis
Existing Structure:
src/presentation/commands/
├── constants.rs
├── context.rs # Will be deprecated/removed
├── create/
│ ├── handler.rs
│ ├── mod.rs
│ ├── errors.rs
│ └── subcommands/
├── destroy/
│ ├── handler.rs
│ ├── mod.rs
│ └── errors.rs
├── factory.rs # Will be removed
├── mod.rs
└── tests/
Target Structure:
src/presentation/controllers/
├── constants.rs # Moved from commands/
├── create/
│ ├── handler.rs # Updated to use ExecutionContext
│ ├── mod.rs
│ ├── errors.rs
│ └── subcommands/
├── destroy/
│ ├── handler.rs # Updated to use ExecutionContext
│ ├── mod.rs
│ └── errors.rs
├── mod.rs # Updated documentation and exports
└── tests/ # Moved and updated
Target Structure:
src/presentation/controllers/
ExecutionContext Integration
Current Handler Signatures:
// create/handler.rs
pub fn handle_create_command(
action: CreateAction,
working_dir: &Path,
user_output: &Arc<Mutex<UserOutput>>,
) -> Result<(), CreateSubcommandError>
// destroy/handler.rs
pub fn handle_destroy_command(
environment: &str,
working_dir: &Path,
user_output: &Arc<Mutex<UserOutput>>,
) -> Result<(), DestroySubcommandError>
Target Handler Signatures:
// create/handler.rs
pub fn handle(
action: CreateAction,
working_dir: &Path,
context: &ExecutionContext,
) -> Result<(), CreateSubcommandError>
// destroy/handler.rs
pub fn handle(
environment: &str,
working_dir: &Path,
context: &ExecutionContext,
) -> Result<(), DestroySubcommandError>
Router Integration
Current Router Calls:
// dispatch/router.rs
Commands::Create { action } => {
create::handle_create_command(action, working_dir, &context.user_output())?;
Ok(())
}
Commands::Destroy { environment } => {
destroy::handle_destroy_command(&environment, working_dir, &context.user_output())?;
Ok(())
}
Target Router Calls:
// dispatch/router.rs
use crate::presentation::controllers::{create, destroy};
Commands::Create { action } => {
create::handle(action, working_dir, context)?;
Ok(())
}
Commands::Destroy { environment } => {
destroy::handle(&environment, working_dir, context)?;
Ok(())
}
Implementation Plan
Phase 1: Preparation and Structure (30 min)
Phase 2: Handler Signature Updates (45 min)
Phase 3: Router Integration (30 min)
Phase 4: Module Documentation and Exports (30 min)
Phase 5: Remove Factory Pattern (30 min)
Phase 6: Test Updates and Cleanup (45 min)
Acceptance Criteria
Note for Contributors: These criteria define what the PR reviewer will check. Use this as your pre-review checklist before submitting the PR to minimize back-and-forth iterations.
Quality Checks:
Structural Changes:
Integration Verification:
Documentation and Testing:
Container Integration:
Related Documentation
Notes
Why "Controllers" Instead of "Commands"?
- Standard Terminology: Controllers is the standard term in MVC patterns
- Clear Responsibility: Controllers handle request routing and coordinate responses
- Industry Alignment: Familiar terminology for developers from web frameworks
- Separation of Concerns: Clear distinction from business logic (commands) vs presentation logic (controllers)
ExecutionContext Benefits
- Clean Dependencies: Controllers get typed access to services without Container complexity
- Future-Proof: Easy to add new services without changing controller signatures
- Thread Safety: Proper concurrent access to shared services
- Testing: Easy to inject test doubles through Container
Factory Pattern Removal Rationale
The commands/factory.rs duplicates the Container pattern from bootstrap/container.rs:
- Container: Centralized dependency injection with lazy loading
- Factory: Redundant pattern that creates the same services
- ExecutionContext: Provides clean access to Container services
Removing the factory simplifies the architecture and eliminates duplicate dependency management.
Create Controllers Layer
Issue: #TBD
Parent Epic: #154 - Presentation Layer Reorganization
Related: Presentation Layer Reorganization Refactor Plan
Overview
Transform the
src/presentation/commands/directory into a Controllers Layer using standard MVC terminology and integrate it fully with the existing ExecutionContext and Container for dependency injection. This proposal establishes the third layer of the four-layer presentation architecture.Goals
commands/tocontrollers/with standard terminology🏗️ Architecture Requirements
DDD Layer: Presentation
Module Path:
src/presentation/controllers/Pattern: Controller Layer (MVC pattern)
Module Structure Requirements
handleinstead ofhandle_create_command)Architectural Constraints
Anti-Patterns to Avoid
Specifications
Current State Analysis
Existing Structure:
Target Structure:
Target Structure:
ExecutionContext Integration
Current Handler Signatures:
Target Handler Signatures:
Router Integration
Current Router Calls:
Target Router Calls:
Implementation Plan
Phase 1: Preparation and Structure (30 min)
src/presentation/controllers/directorycommands/directory contents tocontrollers/src/presentation/mod.rsto declarecontrollersmodulePhase 2: Handler Signature Updates (45 min)
controllers/create/handler.rs:handle_create_commandtohandleuser_output: &Arc<Mutex<UserOutput>>withcontext: &ExecutionContextcontext.user_output()instead of directuser_outputcontrollers/destroy/handler.rs:handle_destroy_commandtohandleuser_output: &Arc<Mutex<UserOutput>>withcontext: &ExecutionContextcontext.user_output()instead of directuser_outputPhase 3: Router Integration (30 min)
src/presentation/dispatch/router.rs:crate::presentation::commandstocrate::presentation::controllershandlenamescontextinstead ofcontext.user_output()Phase 4: Module Documentation and Exports (30 min)
controllers/mod.rs:src/presentation/mod.rs:Phase 5: Remove Factory Pattern (30 min)
controllers/factory.rs(duplicate of Container pattern)controllers/context.rs(superseded by dispatch/context.rs)Phase 6: Test Updates and Cleanup (45 min)
controllers/tests/:commands/directory completelyAcceptance Criteria
Quality Checks:
./scripts/pre-commit.shStructural Changes:
src/presentation/commands/directory no longer existssrc/presentation/controllers/directory exists with all command handlerscontrollers/factory.rshas been removedhandleinstead ofhandle_create_command)Integration Verification:
dispatch/router.rscorrectly calls new controller functionspresentation::controllerspathsDocumentation and Testing:
Container Integration:
Related Documentation
Notes
Why "Controllers" Instead of "Commands"?
ExecutionContext Benefits
Factory Pattern Removal Rationale
The
commands/factory.rsduplicates the Container pattern frombootstrap/container.rs:Removing the factory simplifies the architecture and eliminates duplicate dependency management.