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

  1. What is Clean Architecture?
  2. Core Principles
  3. Dependency Rule
  4. Clean Architecture Layers
  5. Angular Layer Mapping
  6. Domain Layer
  7. Application Layer
  8. Infrastructure Layer
  9. Presentation Layer
  10. Repository Pattern
  11. Dependency Injection
  12. Enterprise Banking Example
  13. Best Practices
  14. Common Mistakes
  15. Top 10 Interview Questions
  16. Interview Cheat Sheet
  17. 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