Clean Architecture in Angular
Learn Clean Architecture in Angular with layers, dependency rule, use cases, repositories, domain-driven design principles, enterprise architecture, best practices, and interview questions.
Clean Architecture is a software design philosophy introduced by Robert C. Martin (Uncle Bob) that focuses on creating applications that are:
- Independent of frameworks
- Easy to test
- Easy to maintain
- Highly scalable
- Loosely coupled
- Easy to evolve
In Angular, Clean Architecture helps separate:
- Business rules
- Application logic
- Infrastructure
- User Interface
This separation allows developers to modify one layer without impacting others.
Table of Contents
- What is Clean Architecture?
- Core Principles
- Dependency Rule
- Clean Architecture Layers
- Angular Layer Mapping
- Domain Layer
- Application Layer
- Infrastructure Layer
- Presentation Layer
- Repository Pattern
- Dependency Injection
- Enterprise Banking Example
- Best Practices
- Common Mistakes
- Top 10 Interview Questions
- Interview Cheat Sheet
- Summary
What is Clean Architecture?
Clean Architecture organizes an application into independent layers.
Each layer has a specific responsibility and depends only on layers closer to the center.
Benefits include:
- Better maintainability
- Easier testing
- Framework independence
- Clear separation of concerns
- Long-term scalability
Clean Architecture Overview
flowchart TD
Presentation
Presentation --> Application
Application --> Domain
Infrastructure --> Application
The Domain layer is the core of the application and should not depend on Angular or infrastructure technologies.
Core Principles
Clean Architecture is based on:
- Separation of Concerns
- SOLID Principles
- Dependency Inversion
- High Cohesion
- Low Coupling
- Testability
- Framework Independence
Dependency Rule
The most important rule is:
Dependencies always point inward.
Outer layers depend on inner layers.
Inner layers never depend on outer layers.
flowchart LR
Presentation --> Application
Infrastructure --> Application
Application --> Domain
The Domain layer has no knowledge of Angular components, HTTP clients, databases, or UI frameworks.
Clean Architecture Layers
| Layer | Responsibility |
|---|---|
| Presentation | UI and user interaction |
| Application | Use cases and orchestration |
| Domain | Business rules |
| Infrastructure | APIs, databases, external systems |
Angular Layer Mapping
| Angular Element | Layer |
|---|---|
| Components | Presentation |
| Routes | Presentation |
| Services (Use Cases) | Application |
| Domain Models | Domain |
| Repository Interfaces | Domain |
| HttpClient | Infrastructure |
| API Services | Infrastructure |
| Local Storage | Infrastructure |
High-Level Architecture
flowchart TD
User
User --> Component
Component --> UseCase
UseCase --> RepositoryInterface
RepositoryInterface --> RepositoryImplementation
RepositoryImplementation --> HttpClient
HttpClient --> BackendAPI
Presentation Layer
Responsibilities:
- Display UI
- Handle user input
- Navigation
- Form validation
- Delegate work to the Application layer
Example
@Component({
selector: 'app-customers',
standalone: true,
templateUrl: './customers.html'
})
export class CustomersComponent {
constructor(
private loadCustomers:
LoadCustomersUseCase
){}
load(){
this.loadCustomers.execute();
}
}
Presentation should contain very little business logic.
Presentation Flow
flowchart LR
User
User --> Component
Component --> UseCase
Domain Layer
The Domain layer contains the business rules.
Typical contents:
- Entities
- Value Objects
- Business Rules
- Repository Interfaces
- Domain Services
Example
export interface Customer {
id: number;
name: string;
email: string;
}
Repository abstraction
export interface CustomerRepository {
getCustomers():
Observable<Customer[]>;
}
Notice that the Domain knows nothing about Angular or HTTP.
Domain Layer Architecture
flowchart LR
Entities
Entities --> RepositoryInterface
RepositoryInterface --> BusinessRules
Application Layer
The Application layer coordinates business use cases.
Responsibilities:
- Execute workflows
- Call repositories
- Coordinate domain logic
- Handle application rules
Example
@Injectable()
export class LoadCustomersUseCase {
constructor(
private repository:
CustomerRepository
){}
execute(){
return this.repository
.getCustomers();
}
}
Application Flow
flowchart LR
Component
Component --> UseCase
UseCase --> Repository
Infrastructure Layer
Infrastructure communicates with external systems.
Examples:
- REST APIs
- GraphQL
- Databases
- Browser Storage
- Authentication Providers
Example
@Injectable()
export class CustomerApiRepository
implements CustomerRepository {
constructor(
private http: HttpClient
){}
getCustomers(){
return this.http.get<Customer[]>(
'/api/customers'
);
}
}
The repository implementation fulfills the interface defined in the Domain.
Infrastructure Flow
flowchart LR
RepositoryImplementation
RepositoryImplementation --> HttpClient
HttpClient --> BackendAPI
Repository Pattern
Instead of directly using HttpClient inside components:
❌ Bad
@Component({...})
export class CustomerComponent {
constructor(
private http: HttpClient
){}
}
✅ Better
Component
↓
Use Case
↓
Repository Interface
↓
Repository Implementation
↓
Backend API
Benefits:
- Easier testing
- Loose coupling
- Replaceable data sources
Dependency Injection
Angular Dependency Injection connects abstractions with implementations.
Example
providers: [
{
provide:
CustomerRepository,
useClass:
CustomerApiRepository
}
]
The component depends on an abstraction instead of a concrete implementation.
Request Lifecycle
sequenceDiagram
participant User
participant Component
participant UseCase
participant Repository
participant API
User->>Component: Click Load
Component->>UseCase: Execute
UseCase->>Repository: Get Customers
Repository->>API: HTTP Request
API-->>Repository: Response
Repository-->>UseCase: Customers
UseCase-->>Component: Customers
Component-->>User: Render UI
Enterprise Banking Example
Business domains
Customer
Accounts
Payments
Loans
Cards
Investments
Reports
Architecture
flowchart TD
Dashboard
Dashboard --> CustomerUseCase
Dashboard --> PaymentUseCase
Dashboard --> LoanUseCase
CustomerUseCase --> CustomerRepository
PaymentUseCase --> PaymentRepository
LoanUseCase --> LoanRepository
CustomerRepository --> Backend
PaymentRepository --> Backend
LoanRepository --> Backend
Each business capability remains isolated and independently testable.
Recommended Folder Structure
src/
app/
├── presentation/
│ ├── components/
│ ├── pages/
│ └── routes/
├── application/
│ ├── use-cases/
│ └── services/
├── domain/
│ ├── entities/
│ ├── repositories/
│ ├── value-objects/
│ └── models/
├── infrastructure/
│ ├── api/
│ ├── repositories/
│ ├── interceptors/
│ └── storage/
Clean Architecture with Standalone Components
Modern Angular works well with Clean Architecture.
bootstrapApplication(
AppComponent,
{
providers:[
provideHttpClient(),
provideRouter(routes)
]
});
The architecture remains independent of whether the application uses NgModules or Standalone Components.
Performance Best Practices
| Practice | Benefit |
|---|---|
| Keep Components Thin | Better maintainability |
| Use Repository Pattern | Decoupled data access |
| Separate Business Rules | Easier testing |
| Depend on Interfaces | Flexible implementations |
| Feature-Based Organization | Better scalability |
| Lazy Load Features | Faster startup |
| Use Signals for UI State | Better rendering |
| Cache API Responses | Improved performance |
Common Mistakes
Business Logic Inside Components
Avoid
@Component({...})
export class CustomerComponent {
save(){
// validation
// calculations
// HTTP calls
}
}
Move business rules into the Application or Domain layer.
HttpClient Everywhere
Do not inject HttpClient into every component.
Use repositories or data-access services.
Skipping the Domain Layer
The Domain should contain business rules and contracts, not just interfaces.
Tight Coupling
Avoid components depending directly on infrastructure implementations.
Depend on abstractions instead.
Mixing Responsibilities
A class should have one primary responsibility.
Separate:
- UI
- Business logic
- Data access
- Infrastructure
Clean Architecture Best Practices
| Practice | Recommendation |
|---|---|
| Thin Components | Yes |
| Use Cases | Yes |
| Repository Pattern | Yes |
| Interface-Based Design | Yes |
| Feature-Based Organization | Yes |
| Dependency Injection | Yes |
| Unit Testing | Yes |
| Independent Layers | Yes |
Layer Responsibilities
| Layer | Knows About |
|---|---|
| Presentation | Application |
| Application | Domain |
| Domain | Nothing Outside Itself |
| Infrastructure | Application + External Systems |
Advantages
| Benefit | Description |
|---|---|
| Maintainability | Easier long-term evolution |
| Testability | Business logic is isolated |
| Scalability | Supports enterprise growth |
| Loose Coupling | Independent layers |
| Framework Independence | Domain is reusable |
| Enterprise Ready | Large-team friendly |
Top 10 Clean Architecture Interview Questions
1. What is Clean Architecture?
Answer
Clean Architecture is an architectural pattern that separates business logic, application logic, infrastructure, and presentation into independent layers with clear responsibilities.
2. What is the Dependency Rule?
Answer
Dependencies must always point inward. Outer layers can depend on inner layers, but inner layers must never depend on outer layers.
3. What belongs in the Domain layer?
Answer
The Domain layer contains entities, value objects, business rules, repository interfaces, and domain services.
4. What is the responsibility of the Application layer?
Answer
The Application layer coordinates use cases, orchestrates workflows, and interacts with repositories to fulfill business operations.
5. What belongs in the Infrastructure layer?
Answer
Infrastructure contains framework-specific and external integrations such as HttpClient, REST APIs, databases, authentication providers, and browser storage.
6. Why use the Repository Pattern?
Answer
The Repository Pattern abstracts data access, allowing the application to switch data sources without changing business logic.
7. Why should Angular components remain thin?
Answer
Thin components focus on presentation and user interaction while delegating business logic to use cases or services, improving maintainability and testability.
8. Is Clean Architecture suitable for Angular?
Answer
Yes. Angular's Dependency Injection, Standalone Components, routing, and services align well with Clean Architecture principles.
9. How does Dependency Injection support Clean Architecture?
Answer
Dependency Injection allows abstractions such as repository interfaces to be connected with concrete implementations without tightly coupling layers.
10. What are Clean Architecture best practices?
Answer
- Keep components thin
- Separate business logic from UI
- Use repository interfaces
- Depend on abstractions
- Keep layers independent
- Organize by feature
- Write unit tests for use cases
- Minimize framework dependencies in the Domain layer
Interview Cheat Sheet
| Topic | Recommendation |
|---|---|
| UI | Presentation Layer |
| Business Logic | Application Layer |
| Business Rules | Domain Layer |
| External Systems | Infrastructure Layer |
| Data Access | Repository Pattern |
| Dependencies | Point Inward |
| Component Design | Thin Components |
| DI | Interface-Based |
| Enterprise Projects | Clean Architecture |
| Testing | Independent Layers |
Summary
Clean Architecture provides a structured approach for building scalable, maintainable, and testable Angular applications by separating presentation, application logic, business rules, and infrastructure into independent layers. Using patterns such as Repository, Dependency Injection, and Use Cases, Angular applications become easier to evolve, test, and maintain. Combined with modern Angular features such as Standalone Components and Signals, Clean Architecture remains a strong choice for enterprise-scale frontend development.
Key Takeaways
- ✅ Clean Architecture separates UI, business logic, domain, and infrastructure.
- ✅ The Dependency Rule requires dependencies to point inward.
- ✅ Keep Angular components focused on presentation.
- ✅ Business rules belong in the Domain layer.
- ✅ Use Cases coordinate application workflows.
- ✅ Repository interfaces decouple business logic from data access.
- ✅ Dependency Injection connects abstractions with implementations.
- ✅ Organize projects into clear architectural layers.
- ✅ Clean Architecture improves maintainability, scalability, and testability.
- ✅ Clean Architecture is a frequently discussed topic in senior Angular architecture interviews.
Next Article
➡️ 126-Repository-Pattern-QA.md