Layer-by-Layer Setup
Reading time: ~15 minutes
Introduction​
Setting up each layer of Prism Architecture requires careful consideration of responsibilities, dependencies, and implementation patterns. This document provides a practical guide to implementing each layer, from Core to Presentation, with a focus on creating clean boundaries while enabling the natural flow of data and operations.
Understanding how to set up each layer correctly is essential for realizing the benefits of Prism Architecture. By following these guidelines, you'll create a codebase that's modular, maintainable, and aligned with the architecture's core principles.
General Setup Considerations​
Before diving into individual layers, there are several cross-cutting considerations that apply to the overall setup:
Dependency Direction​
Remember that dependencies in Prism Architecture should generally flow inward:
- Core Layer is dependency-free (except for standard libraries)
- Domain Layer depends only on Core
- Orchestration Layer depends on Core, Domain, Infrastructure, and Common
- Infrastructure Layer depends on Core and Common
- Presentation Layer depends on Core, Orchestration, and Common
- Common Layer depends only on Core
Clear Boundaries​
Establish clear boundaries between layers using:
- Explicit interfaces (protocols)
- Access modifiers (public, internal, private)
- Project/package structure (when using multi-package approach)
- Consistent dependency injection
- Layer-specific tests with mocks
Communication Mechanism​
Prism Architecture uses a package delivery model for communication between layers:
All Intent and State type definitions reside in the Common Layer, while actual instances are created in the originating layer at runtime.
Common Layer Setup​
The Common Layer is a critical part of Prism Architecture as it provides definitions for all communication types that flow between layers.
Key Components to Implement​
-
Intent and State Base Types:
- Set up base interfaces for Intent and State objects
- Organize types in a clear folder structure
- Create layer-specific subfolders for better organization
-
Data Transfer Objects (DTOs):
- Create serializable objects for data exchange
- Implement different DTOs for different contexts
- Add mappable interfaces for consistent conversion
-
Display Objects (DOs):
- Design UI-ready data structures
- Include formatted, localized data
- Create purpose-specific display objects for different UI contexts
-
Utilities:
- Develop formatting utilities
- Create validation helpers
- Implement common algorithms
- Add error handling utilities
Organized Structure for Intent and State​
Folder organization:
- Base/: Core interfaces and abstract types
- UI/: Types related to user interface actions and display
- Application/: Types related to application operations
- Data/: Types related to data operations
- Response/: Types related to operation responses
Implementation Approach​
The Common Layer should be implemented with a focus on:
- Clear type definitions for cross-layer communication
- Organization by purpose and layer usage
- Framework independence
- Immutability of data objects
- Consistency across all communication types
Key Implementation Tips for Common Layer​
- Organized Structure: Follow the folder organization pattern for Intent and State types
- Purpose-Specific Types: Create different types for specific use cases rather than general-purpose ones
- Immutability: Design all DTOs and communication objects to be immutable
- Framework Independence: Keep Common Layer free from UI or infrastructure frameworks
- Clean Responsibilities: Each utility should have a single, clear responsibility
- Naming Conventions: Use clear, consistent naming for all types
- Documentation: Document the purpose and usage of each type clearly
Core Layer Setup​
The Core Layer forms the foundation of your Prism Architecture application, containing domain entities, value objects, and core protocols.
Key Components to Implement​
-
Base Entity and Value Object Protocols:
- Establish foundational interfaces for domain objects
- Define identity and equality requirements
- Set up serialization capabilities if needed
-
Value Objects:
- Create immutable types for important domain concepts
- Implement domain-specific operations
- Use value objects for entity identifiers
- Include self-validation logic
-
Entities:
- Define core business objects with identity
- Decide on mutability approach (immutable vs. controlled mutability)
- Include entity-specific validation
- Implement business methods
-
Core Protocols:
- Define repository interfaces
- Establish service contracts
- Create factory interfaces
- Set up domain event interfaces
Implementation Approach​
The Core Layer should be implemented with a focus on:
- Domain correctness over technical concerns
- Rich domain model with meaningful operations
- Strong typing and domain-specific types
- Clear interfaces for other layers to implement
- Independence from frameworks and external dependencies
Core Layer Structure​
Key Implementation Tips for Core Layer​
- Keep It Pure: The Core Layer should be free from any external dependencies or frameworks
- Immutability: Prefer immutable entities and value objects to prevent unexpected state changes
- Rich Domain Model: Include meaningful business methods on entities, not just data
- Type Safety: Use custom types for IDs and other important concepts rather than primitives
- Validation: Include basic validation in entity and value object initialization
- Clear Interfaces: Define clear, concise protocols that other layers will implement
Domain Layer Setup​
The Domain Layer contains business logic, validation rules, and domain services that implement core business operations.
Key Components to Implement​
-
Domain Services:
- Implement business operations that don't belong to a single entity
- Create services for cross-entity processes
- Develop calculation and business rule services
-
Validation Services:
- Build comprehensive validation for complex rules
- Create validation result structures
- Implement context-specific validation logic
-
Rule Services:
- Develop services for dynamic business rules
- Implement policy enforcement mechanisms
- Create rule evaluation services
-
Domain Events:
- Design event types for significant domain occurrences
- Create event publishing mechanisms
- Implement event-related interfaces
Domain Layer Structure​
Implementation Approach​
The Domain Layer should be implemented with a focus on:
- Pure business logic
- Rich, expressive domain operations
- Comprehensive validation
- Business rule enforcement
- Domain event generation
Key Implementation Tips for Domain Layer​
- Pure Business Logic: Keep domain services focused on business rules without infrastructure concerns
- Immutability: Design for immutability to prevent unexpected state changes
- Rich Validation: Implement comprehensive validation that captures business rules
- Meaningful Errors: Create domain-specific error types that communicate business rule violations clearly
- Service Composition: Design services to be composable and reusable
- Testing: Make domain services highly testable with clear inputs and outputs
Infrastructure Layer Setup​
The Infrastructure Layer handles data access, external service integration, and technical concerns.
Key Components to Implement​
-
Repositories:
- Implement Core Layer repository interfaces
- Create data source abstractions
- Develop caching mechanisms
- Build transaction handling
-
API Clients:
- Develop HTTP/network clients
- Create API endpoint management
- Implement authentication handling
- Build request/response processing
-
Query Services:
- Create optimized data access services
- Implement GraphQL-specific query handling
- Develop complex query builders
- Build efficient data loaders
-
System Services:
- Implement device/platform capabilities
- Create file system services
- Develop logging mechanisms
- Build configuration services
Infrastructure Layer Communication​
Implementation Approach​
The Infrastructure Layer should be implemented with a focus on:
- Clean interfaces to technical capabilities
- Abstraction of external dependencies
- Efficient data access
- Error handling and resilience
- Performance optimization
- Creating State objects using Common Layer definitions
Key Implementation Tips for Infrastructure Layer​
- Interface Adherence: Strictly implement interfaces defined in the Core Layer
- Error Translation: Convert technical errors to domain-meaningful errors
- Caching Strategy: Implement appropriate caching for performance optimization
- Resilience Patterns: Add retry logic, circuit breakers, and other resilience patterns
- Testability: Create test doubles for external dependencies
- State Creation: Use Common Layer State definitions when creating response objects
Orchestration Layer Setup​
The Orchestration Layer coordinates operations between all other layers, managing application flow and transactions.
Key Components to Implement​
-
Use Cases:
- Create atomic, entity-focused operations
- Implement single responsibility operations
- Develop input validation and error handling
- Build result formatting
-
Orchestration Services:
- Implement feature-area coordination
- Create multi-use-case operations
- Develop feature-specific state management
- Build service composition
-
Workflow Coordinators:
- Create complex, multi-step process management
- Implement cross-domain coordination
- Develop state machines for process flows
- Build saga patterns for distributed operations
-
Event Handlers:
- Implement domain event subscribers
- Create event-driven workflows
- Develop event recording and auditing
- Build event-based notifications
Orchestration Layer Communication Flow​
Implementation Approach​
The Orchestration Layer should be implemented with a focus on:
- Clear flow coordination
- Proper delegation to other layers
- Transaction management
- Error handling and recovery
- Hierarchical organization
- Processing Intents from Presentation Layer
- Creating States using Common Layer definitions
Key Implementation Tips for Orchestration Layer​
- Single Responsibility: Each Use Case should have a clear, focused purpose
- Proper Delegation: Delegate domain logic to Domain Layer, data access to Infrastructure
- Error Handling: Implement comprehensive error handling and recovery strategies
- Transactional Integrity: Ensure operations maintain data consistency
- Clear Interfaces: Provide clean, well-defined interfaces to the Presentation Layer
- Intent Processing: Design for processing Intents from the Presentation Layer
- State Creation: Use Common Layer State definitions when creating response objects
Presentation Layer Setup​
The Presentation Layer manages the user interface, captures user input, and presents application data in a user-friendly format.
Key Components to Implement​
-
Presenters/ViewModels:
- Create hierarchical presenter structure (PrismUI)
- Implement UI logic and state management
- Develop intent handling
- Build state transformation
-
UI State Management:
- Create immutable state structures
- Implement state propagation
- Develop state derivation
- Build state diffing
-
Intent System:
- Create intent objects for user actions
- Implement intent bubbling
- Develop intent handlers
- Build intent translation to Use Cases
-
Navigation Management:
- Implement screen navigation
- Create deep linking support
- Develop navigation state management
- Build modal and dialog coordination
Presentation Layer Communication Flow​
Implementation Approach​
The Presentation Layer should be implemented with a focus on:
- Clear UI logic separation from views
- Hierarchical component organization
- Unidirectional data flow
- Predictable state management
- Creating Intents using Common Layer definitions
- Processing State objects from the Orchestration Layer
Key Implementation Tips for Presentation Layer​
- Hierarchical Organization: Follow the three-tier presenter hierarchy of PrismUI
- Separation from Views: Keep presenters independent of view implementation details
- Immutable State: Use immutable state objects for predictable UI updates
- Intent-Based Communication: Use explicit intents for user actions
- Unidirectional Flow: Maintain state down, intents up flow pattern
- Intent Creation: Use Common Layer Intent definitions when creating intent objects
- State Processing: Process State objects received from the Orchestration Layer
Implementation Sequence​
When setting up Prism Architecture, follow this recommended sequence:
-
Start with Common Layer:
- Define Intent and State base types
- Set up the organizational structure
- Create initial DTOs and DOs
-
Set up Core Layer:
- Define key entities and value objects
- Establish core protocols
- Create domain vocabulary
-
Implement Domain Layer:
- Create domain services
- Build validation logic
- Implement business rules
-
Add Infrastructure Layer:
- Implement repository interfaces
- Create API clients
- Develop system services
-
Develop Orchestration Layer:
- Create use cases
- Build orchestration services
- Implement workflows
-
Finally, Build Presentation Layer:
- Implement presenter hierarchy
- Create state management
- Develop intent system
This sequence ensures that each layer builds upon a solid foundation from the layers before it.
Common Layer Setup Challenges​
Challenge 1: Maintaining Layer Boundaries​
Problem: Layers accessing each other in ways that violate the dependency rules.
Solution:
- Use compiler enforcement through project structure when possible
- Implement layer boundary tests
- Conduct regular architecture reviews
- Use dependency injection to make dependencies explicit
Challenge 2: Over-Engineering​
Problem: Creating overly complex structures that introduce unnecessary abstraction.
Solution:
- Start simple and evolve as needed
- Focus on business requirements first
- Introduce abstractions only when needed
- Regularly refactor to simplify
Challenge 3: Data Transformation Overhead​
Problem: Excessive mapping between different data models across layers.
Solution:
- Use Core Layer entities throughout when appropriate
- Create purpose-specific DTOs rather than generic ones
- Implement efficient mapping utilities
- Consider performance-critical paths carefully
Challenge 4: Incomplete Layer Implementation​
Problem: Layers missing key components needed for proper architecture function.
Solution:
- Use checklists for layer implementation
- Create architecture verification tests
- Document layer responsibilities clearly
- Conduct peer reviews for architectural compliance
Conclusion​
Setting up each layer of Prism Architecture requires careful planning and attention to responsibilities, dependencies, and communication patterns. By following the guidelines in this document, you can create a clean, maintainable implementation that realizes the benefits of Prism Architecture.
Remember that Prism Architecture is designed to be practical rather than dogmatic. Adapt these guidelines to your specific project needs while maintaining the core principles of separation of concerns, dependency rules, and intent-based communication.
The key to successful implementation is consistency and clarity. Establish clear conventions for your team, document your approach, and ensure all team members understand the architectural patterns being used.