docs
This commit is contained in:
156
docs/architecture/website/COMMAND_MODELS.md
Normal file
156
docs/architecture/website/COMMAND_MODELS.md
Normal file
@@ -0,0 +1,156 @@
|
||||
Command Models
|
||||
|
||||
This document defines Command Models as a first-class concept in the frontend architecture.
|
||||
Command Models are UX-only write models used to collect, validate, and prepare user input
|
||||
before it is sent to the backend as a Command DTO.
|
||||
|
||||
Command Models are not View Models and not Domain Models.
|
||||
|
||||
⸻
|
||||
|
||||
Purpose
|
||||
|
||||
A Form Model answers the question:
|
||||
|
||||
“What does the UI need in order to safely submit user input?”
|
||||
|
||||
Command Models exist to:
|
||||
• centralize form state
|
||||
• reduce logic inside components
|
||||
• provide consistent client-side validation
|
||||
• build Command DTOs explicitly
|
||||
|
||||
⸻
|
||||
|
||||
Core Rules
|
||||
|
||||
Command Models:
|
||||
• exist only in the frontend
|
||||
• are write-only (never reused for reads)
|
||||
• are created per form
|
||||
• are discarded after submission
|
||||
|
||||
Command Models MUST NOT:
|
||||
• contain business logic
|
||||
• enforce domain rules
|
||||
• reference View Models
|
||||
• reference Domain Entities or Value Objects
|
||||
• be sent to the API directly
|
||||
|
||||
⸻
|
||||
|
||||
Relationship to Other Models
|
||||
|
||||
API DTO (read) → ViewModel → UI
|
||||
|
||||
UI Input → FormModel → Command DTO → API
|
||||
|
||||
• View Models are read-only
|
||||
• Command Models are write-only
|
||||
• No model is reused across read/write boundaries
|
||||
|
||||
⸻
|
||||
|
||||
Typical Responsibilities
|
||||
|
||||
A Form Model MAY:
|
||||
• store field values
|
||||
• track dirty / touched state
|
||||
• perform basic UX validation
|
||||
• expose isValid, canSubmit
|
||||
• build a Command DTO
|
||||
|
||||
A Form Model MUST NOT:
|
||||
• decide if an action is allowed
|
||||
• perform authorization checks
|
||||
• validate cross-aggregate rules
|
||||
|
||||
⸻
|
||||
|
||||
Validation Guidelines
|
||||
|
||||
Client-side validation is UX validation, not business validation.
|
||||
|
||||
Allowed validation examples:
|
||||
• required fields
|
||||
• min / max length
|
||||
• email format
|
||||
• numeric ranges
|
||||
|
||||
Forbidden validation examples:
|
||||
• “user is not allowed”
|
||||
• “league already exists”
|
||||
• “quota exceeded”
|
||||
|
||||
Server validation is the source of truth.
|
||||
|
||||
⸻
|
||||
|
||||
Example: Simple Form Model (with class-validator)
|
||||
|
||||
import { IsEmail, IsNotEmpty, MinLength } from 'class-validator';
|
||||
|
||||
export class SignupFormModel {
|
||||
@IsEmail()
|
||||
email = '';
|
||||
|
||||
@IsNotEmpty()
|
||||
@MinLength(8)
|
||||
password = '';
|
||||
|
||||
isSubmitting = false;
|
||||
|
||||
reset(): void {
|
||||
this.email = '';
|
||||
this.password = '';
|
||||
}
|
||||
|
||||
toCommand(): SignupCommandDto {
|
||||
return {
|
||||
email: this.email,
|
||||
password: this.password,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
⸻
|
||||
|
||||
Usage in UI Component
|
||||
|
||||
const form = useFormModel(SignupFormModel);
|
||||
|
||||
async function onSubmit() {
|
||||
if (!form.isValid()) return;
|
||||
|
||||
form.isSubmitting = true;
|
||||
|
||||
await authService.signup(form.toCommand());
|
||||
}
|
||||
|
||||
The component:
|
||||
• binds inputs to the Form Model
|
||||
• reacts to validation state
|
||||
• never builds DTOs manually
|
||||
|
||||
⸻
|
||||
|
||||
Testing
|
||||
|
||||
Command Models SHOULD be tested when they contain:
|
||||
• validation rules
|
||||
• non-trivial state transitions
|
||||
• command construction logic
|
||||
|
||||
Command Models do NOT need tests if they only hold fields without logic.
|
||||
|
||||
⸻
|
||||
|
||||
Summary
|
||||
• Command Models are UX helpers for writes
|
||||
• They protect components from complexity
|
||||
• They never replace backend validation
|
||||
• They never leak into read flows
|
||||
|
||||
Command Models help users.
|
||||
Use Cases protect the system.
|
||||
Reference in New Issue
Block a user