Glossary

Clean Architecture

Technology should serve the application’s rules. Architecture helps when it keeps the direction of dependencies clear as the system changes.

Short definition

Business rules are not a detail of the framework or database.

Clean Architecture describes a system as concentric areas of responsibility. Near the centre are the rules with the longest lifetime: enterprise business rules, or entities, and application-specific rules expressed as use cases. At the edge are the HTTP controller, database, ORM, message queue, framework, and external-service clients.

The core dependency rule states that source code in an inner area must not know the names or concrete implementations of an outer area. The inner area can therefore define a contract it needs, and an adapter at the edge implements it. This does not mean an application should not use a framework; it means the framework should not dictate the shape of its essential rules.

The problem it solves

Changes in technical details should not rewrite application decisions.

The approach is useful when code evolves beyond one small feature and multiple inputs or integrations share the same rules.

  • separating order rules from a particular ORM and database schema
  • running the same use case from an HTTP controller, CLI command, and queue consumer
  • testing decisions without a real marketplace API or database connection
  • replacing an external-service provider without its SDK leaking into application logic
  • a clear place for the transaction, authorization, and conversion of input data to the use-case model
  • gradually clarifying a long-lived module without rewriting the entire system at once

Practical example

Importing an order from a marketplace

An HTTP controller receives an order identifier and passes an input model to the ImportMarketplaceOrder use case. The use case decides whether the order can be created, converts external items to the internal model, and requests persistence. Order rules, such as a forbidden state transition or handling an amount, belong in the domain area.

The use case does not call the marketplace SDK or database client directly. Instead, it works with contracts for loading and storing an order. The marketplace HTTP adapter and database adapter implement these contracts at the edge. A test can supply controlled substitutes and verify that an order with an invalid currency is not stored. The same use case can later run from a backfill command without duplicating the decision logic.

Text diagram

HTTP controller
  → ImportMarketplaceOrder (application use case)
    → Order a pravidla objednávky (domain)
    → MarketplaceOrderSource (výstupní kontrakt)
      → HTTP adaptér marketplace
    → OrderStore (výstupní kontrakt)
      → databázový adaptér

How it works

From input to infrastructure details without reversing dependencies

The text diagram describes the direction of collaboration. A runtime arrow may point outward, but the source-code dependency remains controlled by a contract in the inner area.

  1. Input adapter A controller, CLI command, or message handler converts technical input into a simple input model. It should not contain business decisions or database queries.
  2. Use case The application layer coordinates one goal of a user or system: it loads required data, invokes domain rules, defines the transaction boundary, and prepares the output.
  3. Domain rules Entities and other domain objects protect meaning and valid state. They are not automatically copies of tables or a place for sending HTTP requests.
  4. Output contract The inner area defines the capability it needs, such as loading an order or storing a change. The contract speaks the language of the use case, not necessarily that of a specific library.
  5. Adapter and framework Database, HTTP, or framework code implements the required capability. Its concrete type is selected when assembling the application and can be tested and changed independently.

Main components

The circles are a guide to responsibilities, not a mandatory directory map.

The original model uses four areas. A real module may combine them or use different names as long as the direction of dependencies remains clear.

Entities and enterprise business rules

In the original sense, these are broader enterprise rules not tied to one delivery mechanism. In a smaller system, this may simply be an object that protects the validity of an order or price.

Use cases

Application-specific rules compose the steps of one scenario. They decide when to work with data and what result to return, but should not be tightly bound to an HTTP request or ORM entity.

Interface adapters

Convert data between the outside world and use cases. Examples include a controller, presenter, mapper, or output-contract implementation; there is no prescribed number of classes.

Frameworks and drivers

The framework, database, web server, and SDK are technical choices at the edge. They can be highly useful, but their APIs should not needlessly permeate rules meant to outlive their replacement.

Input and output models

A use case can work with small data models independent of transport. There is no need to create a DTO, mapper, and interface for every field; a boundary should reflect a real translation of meaning or risk of change.

Benefits and limitations

Boundaries protect against change, but also cost code and attention.

Benefits

  • critical rules do not depend directly on one database, transport, or framework
  • the same use case can serve multiple entry points
  • tests can verify decisions quickly without remote infrastructure
  • technical integrations have a clearer place, and changing their details has less impact

Limitations and common mistakes

  • adding layers, DTOs, interfaces, and mappers to every small operation without a real boundary
  • confusing a domain object with an ORM entity or forcing their separation where it adds no value
  • assuming the framework is the enemy instead of treating it as a sensibly constrained tool
  • treating a diagram or folder name as proof of sound architecture without checking dependencies and behaviour

Pragmatism

Structure should match the complexity it actually protects.

For a small form, one-off import, or simple administration screen, a direct framework service may be clearer than a full four-circle model. The key question is not whether another abstraction can be created, but whether technology changes, multiple inputs, difficult rules, or independent tests are expected.

Orders, payments, inventory reservations, and integrations, by contrast, often change for different reasons. There it pays to identify one genuinely painful boundary first and maintain it. If exceptions, pass-through mappers, and empty contracts multiply quickly, that is a signal to simplify, not add another layer.

What to consider

Architecture should be verifiable in every change.

The most useful rules can be explained with a concrete scenario and checked both in code review and automatically.

  • start with one critical use case and one real integration boundary
  • keep framework and database code at the edge when changing it should not change the rules
  • name contracts after application needs, not a provider implementation
  • test domain decisions and integration adapters at their respective boundaries
  • check dependency direction in review or with an automated rule when the boundary matters

Common questions

Clean Architecture in practice

Does Clean Architecture require exactly four layers?

No. The circles model responsibilities. A module may combine, split, or rename areas as long as technical details do not begin to dictate rules that should remain stable.

Must the domain area avoid every library?

There is no universal ban. A dependency is mainly a problem when it pulls a technical detail into rules that should not be tied to it. A small, stable library may be preferable to custom code that is harder to maintain.

Is Clean Architecture just another name for dependency injection?

No. Dependency injection supplies objects with their dependencies. Clean Architecture addresses a broader division of responsibilities and dependency direction; DI is one practical way to assemble the application.

When is the solution unnecessarily complex?

When most classes merely pass data between layers, contracts have no real consumers, and changing a simple rule requires traversing many empty abstractions. The boundaries should then be reduced.

How I use architecture in practice

I choose boundaries according to the changes the application must safely absorb.

In more complex areas, I separate application rules from the database, HTTP, and external services. The goal is not a number of layers, but clear responsibility and safe change.

Request a call

I will call you on the next working day between 9:00 and 17:00.

You can also call me directly.

+420 605 181 728

Leave your phone number and send a callback request.

By sending, you agree to processing your data in order to handle your request.