clean-architecture

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Clean Architecture Framework

Clean Architecture 框架

A disciplined approach to structuring software so that business rules remain independent of frameworks, databases, and delivery mechanisms. Apply these principles when designing system architecture, reviewing module boundaries, or advising on dependency management.
这是一种结构化软件的严谨方法,可确保业务规则独立于框架、数据库和交付机制。在设计系统架构、评审模块边界或提供依赖管理建议时,可应用这些原则。

Core Principle

核心原则

Source code dependencies must point inward -- toward higher-level policies. Nothing in an inner circle can know anything about something in an outer circle. This single rule, applied consistently, produces systems that are testable, independent of frameworks, independent of the UI, independent of the database, and independent of any external agency.
The foundation: Software architecture is about drawing lines -- boundaries -- that separate things that matter from things that are details. Business rules are what matter. Databases, web frameworks, and delivery mechanisms are details. When details depend on policies (not the other way around), you can defer decisions, swap implementations, and test business logic in isolation.
源代码依赖必须向内指向——指向更高层级的策略。 内圈中的任何内容都不得了解外圈中的任何内容。持续应用这单一规则,就能打造出可测试、独立于框架、独立于UI、独立于数据库且独立于任何外部代理的系统。
基础: 软件架构的关键在于划分界限——将重要事项与细节区分开。业务规则是重要事项,而数据库、Web框架和交付机制都是细节。当细节依赖于策略(而非反过来)时,你可以推迟决策、替换实现,并独立测试业务逻辑。

Scoring

评分标准

Goal: 10/10. When reviewing or creating software architecture, rate it 0-10 based on adherence to the principles below. A 10/10 means full alignment with all guidelines; lower scores indicate gaps to address. Always provide the current score and specific improvements needed to reach 10/10.
目标:10/10。 在评审或创建软件架构时,根据对以下原则的遵守程度,以0-10分进行评级。10/10表示完全符合所有准则;分数越低,说明存在越多需要解决的问题。请始终提供当前分数以及达到10/10所需的具体改进措施。

The Clean Architecture Framework

Clean Architecture 框架

Six principles for building systems that survive the passage of time:
打造长期可维护系统的六大原则:

1. Dependency Rule and Concentric Circles

1. 依赖规则与同心圆结构

Core concept: The architecture is organized as concentric circles. The innermost circle contains Entities (enterprise business rules). The next circle contains Use Cases (application business rules). Then Interface Adapters. The outermost circle contains Frameworks and Drivers. Source code dependencies always point inward.
Why it works: When high-level policies don't depend on low-level details, you can change the database from MySQL to MongoDB, swap a web framework, or replace a REST API with GraphQL -- all without touching business logic. The system becomes resilient to the most volatile parts of the technology stack.
Key insights:
  • The Dependency Rule is the overriding rule: inner circles cannot mention outer circle names (classes, functions, variables, data formats)
  • Data that crosses boundaries must be in a form convenient for the inner circle, never in a form dictated by the outer circle
  • Dependency Inversion (interfaces defined inward, implemented outward) is the mechanism that enforces the rule
  • The number of circles is not fixed -- four is typical, but you may have more; the rule stays the same
  • Frameworks are details, not architecture -- they belong in the outermost circle
Code applications:
ContextPatternExample
Layer directionInner circles define interfaces; outer circles implement them
UserRepository
interface in Use Cases;
PostgresUserRepository
in Adapters
Data crossingDTOs or simple structs cross boundaries, not ORM entitiesUse Case returns
UserResponse
DTO, not an ActiveRecord model
Framework isolationWrap framework calls behind interfaces
EmailSender
interface hides whether you use SendGrid or SES
Database independenceRepository pattern abstracts persistenceBusiness logic calls
repo.save(user)
, never raw SQL
Dependency directionImport arrows on a diagram always point inwardController imports Use Case; Use Case never imports Controller
See: references/dependency-rule.md
核心概念: 架构以同心圆形式组织。最内圈包含实体(Entities,企业级业务规则),下一圈包含用例(Use Cases,应用级业务规则),再外层是接口适配器(Interface Adapters),最外圈是框架与驱动(Frameworks and Drivers)。源代码依赖始终向内指向。
为何有效: 当高层级策略不依赖于低层级细节时,你可以将数据库从MySQL替换为MongoDB、更换Web框架,或是用GraphQL替代REST API——所有这些操作都无需改动业务逻辑。系统对技术栈中最易变的部分具备更强的适应性。
关键见解:
  • 依赖规则是首要规则:内圈不得提及外圈的名称(类、函数、变量、数据格式)
  • 跨边界的数据必须采用内圈最便捷的格式,绝不能由外圈决定
  • 依赖反转(DIP,向内定义接口,向外实现)是执行该规则的机制
  • 同心圆的数量并非固定——通常为四层,但也可更多;规则保持不变
  • 框架是细节,而非架构——它们属于最外圈
代码应用:
场景模式示例
分层方向内圈定义接口,外圈实现接口用例层的
UserRepository
接口;适配器层的
PostgresUserRepository
实现
数据传递数据传输对象(DTO)或简单结构体跨边界,而非ORM实体用例返回
UserResponse
DTO,而非ActiveRecord模型
框架隔离用接口封装框架调用
EmailSender
接口隐藏底层使用的是SendGrid还是SES
数据库独立性仓储模式抽象持久化逻辑业务逻辑调用
repo.save(user)
,而非直接执行原生SQL
依赖方向架构图中的导入箭头始终向内控制器导入用例;用例绝不会导入控制器
参考:references/dependency-rule.md

2. Entities and Use Cases

2. 实体与用例

Core concept: Entities encapsulate enterprise-wide business rules -- the most general, highest-level rules that would exist even if no software system existed. Use Cases contain application-specific business rules that orchestrate the flow of data to and from Entities.
Why it works: By separating what the business does (Entities) from how the application orchestrates it (Use Cases), you can reuse Entities across multiple applications and change application behavior without altering core business rules.
Key insights:
  • Entities are not database rows -- they are objects (or pure functions) that encapsulate critical business rules and data
  • Use Cases describe application-specific automation rules; they orchestrate Entities but do not contain enterprise logic
  • Use Cases accept Request Models and return Response Models -- never framework objects
  • Each Use Case represents a single application operation (e.g.,
    CreateOrder
    ,
    ApproveExpense
    )
  • The Interactor pattern: a Use Case class implements an input boundary interface and calls an output boundary interface
  • Changes to a Use Case should never affect an Entity; changes to an Entity may require Use Case updates
Code applications:
ContextPatternExample
Entity designEncapsulate critical business rules with no framework dependencies
Order.calculateTotal()
applies tax rules; knows nothing about HTTP
Use Case boundaryDefine Input Port and Output Port interfaces
CreateOrderInput
interface;
CreateOrderOutput
interface
Request/ResponseSimple data structures cross the boundary
CreateOrderRequest { items, customerId }
-- no ORM models
Single responsibilityOne Use Case per application operation
PlaceOrder
,
CancelOrder
,
RefundOrder
as separate classes
InteractorUse Case class implements Input Port, calls Output Port
PlaceOrderInteractor implements PlaceOrderInput
See: references/entities-use-cases.md
核心概念: 实体封装企业级业务规则——这些是最通用、最高层级的规则,即便没有软件系统也依然存在。用例包含应用特定的业务规则,负责协调数据与实体之间的流转。
为何有效: 通过分离业务的核心逻辑(实体)与应用的编排方式(用例),你可以在多个应用中复用实体,且无需改动核心业务规则就能修改应用行为。
关键见解:
  • 实体并非数据库行——它们是封装关键业务规则与数据的对象(或纯函数)
  • 用例描述应用特定的自动化规则;它们协调实体,但不包含企业级逻辑
  • 用例接收请求模型并返回响应模型——绝不使用框架对象
  • 每个用例代表单个应用操作(例如
    CreateOrder
    ApproveExpense
  • 交互器模式:用例类实现输入边界接口,并调用输出边界接口
  • 用例的变更绝不应影响实体;实体的变更可能需要更新用例
代码应用:
场景模式示例
实体设计封装关键业务规则,无框架依赖
Order.calculateTotal()
应用税务规则;完全不了解HTTP
用例边界定义输入端口与输出端口接口
CreateOrderInput
接口;
CreateOrderOutput
接口
请求/响应简单数据结构跨边界
CreateOrderRequest { items, customerId }
——无ORM模型
单一职责每个应用操作对应一个用例
PlaceOrder
CancelOrder
RefundOrder
为独立类
交互器用例类实现输入端口,调用输出端口
PlaceOrderInteractor implements PlaceOrderInput
参考:references/entities-use-cases.md

3. Interface Adapters and Frameworks

3. 接口适配器与框架

Core concept: Interface Adapters convert data between the format most convenient for Use Cases and Entities and the format required by external agencies (database, web, devices). Frameworks and Drivers are the outermost layer -- glue code that connects to the outside world.
Why it works: When the web framework, ORM, or message queue is confined to the outermost circles, replacing any of them becomes a localized change. The database is a detail. The web is a detail. The framework is a detail. Details should be plugins to your business rules, not the skeleton of your application.
Key insights:
  • Controllers translate HTTP requests into Use Case input; Presenters translate Use Case output into view models
  • Gateways implement repository interfaces defined by Use Cases -- the Use Case defines the contract, the gateway fulfills it
  • The database is a detail: business rules don't need to know whether data is stored in SQL, NoSQL, or flat files
  • The web is a detail: business rules don't know they're being delivered over HTTP
  • Treat frameworks with suspicion -- they want you to couple to them; keep them at arm's length
  • Plugin architecture: the system should be structured so that frameworks plug into business rules, not the reverse
Code applications:
ContextPatternExample
ControllerTranslates delivery mechanism to Use Case input
OrderController.create(req)
builds
CreateOrderRequest
and calls Interactor
PresenterTranslates Use Case output to view model
OrderPresenter.present(response)
formats data for JSON/HTML
GatewayImplements repository interface using a specific DB
SqlOrderRepository implements OrderRepository
Framework boundaryFramework code calls inward, never called by inner circlesExpress route handler calls Controller; Controller never imports Express
Plugin architectureMain component wires dependencies at startup
main()
instantiates concrete classes and injects them
See: references/adapters-frameworks.md
核心概念: 接口适配器负责在最适合用例与实体的数据格式,和外部代理(数据库、Web、设备)要求的数据格式之间进行转换。框架与驱动是最外层——用于连接外部世界的胶水代码。
为何有效: 当Web框架、ORM或消息队列被限制在最外圈时,替换其中任何一个都只是局部修改。数据库是细节,Web是细节,框架也是细节。细节应作为业务规则的插件,而非应用的骨架。
关键见解:
  • 控制器将HTTP请求转换为用例输入;呈现器将用例输出转换为视图模型
  • 网关实现用例定义的仓储接口——用例定义契约,网关履行契约
  • 数据库是细节:业务规则无需了解数据存储在SQL、NoSQL还是平面文件中
  • Web是细节:业务规则不知道自身通过HTTP交付
  • 对框架保持警惕——它们会诱导你与其耦合;保持距离
  • 插件架构:系统应被设计为框架可插入业务规则,而非反过来
代码应用:
场景模式示例
控制器将交付机制转换为用例输入
OrderController.create(req)
构建
CreateOrderRequest
并调用交互器
呈现器将用例输出转换为视图模型
OrderPresenter.present(response)
为JSON/HTML格式化数据
网关使用特定数据库实现仓储接口
SqlOrderRepository implements OrderRepository
框架边界框架代码向内调用,绝不由内圈调用Express路由处理器调用控制器;控制器绝不会导入Express
插件架构主组件在启动时注入依赖
main()
实例化具体类并注入依赖
参考:references/adapters-frameworks.md

4. Component Principles

4. 组件原则

Core concept: Components are the units of deployment. Three cohesion principles govern what goes inside a component; three coupling principles govern relationships between components. Together they determine a system's releasability, maintainability, and stability.
Why it works: Poorly composed components create ripple effects: one change forces redeployment of unrelated code. The cohesion and coupling principles provide a systematic way to group classes and manage inter-component dependencies so that changes remain localized.
Key insights:
  • REP (Reuse/Release Equivalence): classes in a component should be releasable together -- if you can't version and release them as a unit, they don't belong together
  • CCP (Common Closure): classes that change for the same reason at the same time belong in the same component (SRP for components)
  • CRP (Common Reuse): don't force users to depend on things they don't use -- if you must import a component, you should need most of its classes
  • ADP (Acyclic Dependencies): the dependency graph of components must have no cycles; break cycles with DIP or by extracting a new component
  • SDP (Stable Dependencies): depend in the direction of stability -- a component with many dependents should be hard to change
  • SAP (Stable Abstractions): stable components should be abstract; unstable components should be concrete
Code applications:
ContextPatternExample
Component groupingGroup classes that change together (CCP)All order-related Use Cases in one component
Breaking cyclesApply DIP to invert a dependency edgeExtract an interface into a new component to break a circular dependency
Stability metricsMeasure instability: I = Ce / (Ca + Ce)A component with many incoming and no outgoing deps has I near 0 (stable)
Abstractness balanceStable components should contain mostly interfacesCore domain component is abstract; adapter component is concrete
Release granularityVersion and release components independently
order-domain v2.1.0
released without touching
payment-adapter
See: references/component-principles.md
核心概念: 组件是部署的单元。三个内聚原则管理组件内部的内容;三个耦合原则管理组件之间的关系。它们共同决定了系统的可发布性、可维护性与稳定性。
为何有效: 组件组合不当会引发连锁反应:一处变更会迫使无关代码重新部署。内聚与耦合原则提供了系统化的类分组方式,可管理组件间的依赖,使变更保持局部化。
关键见解:
  • REP(复用/发布等价原则):组件内的类应可一起发布——如果你无法将它们作为一个单元进行版本控制和发布,它们就不属于同一组件
  • CCP(共同封闭原则):因相同原因、在相同时间变更的类应属于同一组件(组件级的单一职责原则)
  • CRP(共同复用原则):不要强制用户依赖他们不需要的内容——如果必须导入某个组件,你应该需要它的大多数类
  • ADP(无环依赖原则):组件的依赖图不得存在循环;通过DIP或提取新组件打破循环
  • SDP(稳定依赖原则):依赖方向应朝向稳定性——拥有多个依赖者的组件应难以变更
  • SAP(稳定抽象原则):稳定组件应是抽象的;不稳定组件应是具体的
代码应用:
场景模式示例
组件分组将一起变更的类分组(CCP)所有订单相关用例放在同一组件中
打破循环应用DIP反转依赖边将接口提取到新组件中,打破循环依赖
稳定性指标测量不稳定性:I = Ce / (Ca + Ce)拥有多个传入依赖、无传出依赖的组件,其I值接近0(稳定)
抽象性平衡稳定组件应主要包含接口核心领域组件是抽象的;适配器组件是具体的
发布粒度独立版本控制和发布组件
order-domain v2.1.0
发布时无需改动
payment-adapter
参考:references/component-principles.md

5. SOLID Principles

5. SOLID原则

Core concept: Five principles for managing dependencies at the class and module level: Single Responsibility (SRP), Open-Closed (OCP), Liskov Substitution (LSP), Interface Segregation (ISP), and Dependency Inversion (DIP). They are the mid-level building blocks that make the Dependency Rule possible.
Why it works: SOLID principles keep source code flexible, understandable, and amenable to change. They prevent the rigidity, fragility, and immobility that turn codebases into legacy nightmares. Each principle addresses a specific way that dependencies can go wrong.
Key insights:
  • SRP: a module should have one, and only one, reason to change -- it serves one actor (not "does one thing")
  • OCP: extend behavior by adding new code, not by modifying existing code; strategy and plugin patterns are the mechanism
  • LSP: subtypes must be usable through the base type interface without the client knowing the difference; violated when subclass throws unexpected exceptions or ignores methods
  • ISP: clients should not be forced to depend on methods they do not use; fat interfaces create unnecessary coupling
  • DIP: high-level modules should not depend on low-level modules; both should depend on abstractions defined by the high-level module
Code applications:
ContextPatternExample
SRP violationClass serves multiple actors
Employee
handles pay calculation (CFO), reporting (COO), and persistence (CTO)
OCP via strategyNew behavior through new classes, not editsAdd
ExpressShipping
class implementing
ShippingStrategy
, no changes to
Order
LSP violationSubtype changes expected behavior
Square extends Rectangle
breaks
setWidth()
/
setHeight()
contract
ISP applicationSplit fat interfaces into role interfaces
Printer
,
Scanner
,
Fax
instead of one
MultiFunctionDevice
DIP wiringHigh-level defines interface; low-level implements
OrderService
depends on
PaymentGateway
interface, not
StripeClient
See: references/solid-principles.md
核心概念: 用于管理类和模块级依赖的五个原则:单一职责(SRP)、开闭原则(OCP)、里氏替换(LSP)、接口隔离(ISP)、依赖反转(DIP)。它们是实现依赖规则的中层构建块。
为何有效: SOLID原则保持源代码的灵活性、可读性与可修改性。它们可防止代码库变得僵化、脆弱且难以迁移,避免沦为遗留系统噩梦。每个原则都针对依赖可能出现的特定问题。
关键见解:
  • SRP:一个模块应有且仅有一个变更的理由——它服务于一个角色(而非「只做一件事」)
  • OCP:通过添加新代码扩展行为,而非修改现有代码;策略模式和插件模式是实现机制
  • LSP:子类型必须可通过基类型接口使用,且客户端无需知晓差异;当子类抛出意外异常或忽略方法时,该原则被违反
  • ISP:客户端不应被迫依赖他们不使用的方法;臃肿的接口会产生不必要的耦合
  • DIP:高层模块不应依赖低层模块;两者都应依赖高层模块定义的抽象
代码应用:
场景模式示例
SRP违反类服务于多个角色
Employee
处理薪资计算(CFO)、报表(COO)和持久化(CTO)
通过策略实现OCP通过新增类实现新行为,而非修改现有代码添加实现
ShippingStrategy
ExpressShipping
类,无需修改
Order
LSP违反子类型更改预期行为
Square extends Rectangle
违反
setWidth()
/
setHeight()
契约
ISP应用将臃肿接口拆分为角色接口拆分为
Printer
Scanner
Fax
,而非单一的
MultiFunctionDevice
DIP注入高层定义接口;低层实现接口
OrderService
依赖
PaymentGateway
接口,而非
StripeClient
参考:references/solid-principles.md

6. Boundaries and Boundary Anatomy

6. 边界与边界结构

Core concept: A boundary is a line drawn between things that matter and things that are details. Boundaries are implemented through polymorphism: source code dependencies cross the boundary pointing inward, while the flow of control may cross in either direction. The Humble Object pattern makes code at boundaries testable.
Why it works: Every boundary you draw gives you the option to defer a decision or swap an implementation. Boundaries separate the volatile from the stable, the concrete from the abstract. Early and strategic boundary placement determines whether a system is a joy or a pain to maintain over years.
Key insights:
  • Full boundaries use reciprocal interfaces on both sides; partial boundaries use a simpler strategy pattern or facade
  • The Humble Object pattern: split behavior at a boundary into two classes -- one hard to test (close to the boundary) and one easy to test (contains the logic)
  • Services are not inherently architectural boundaries -- a microservice with a fat shared data model is just a monolith with network calls
  • The Main component is a plugin: it creates all factories, strategies, and dependencies, then hands control to the high-level policy
  • Test boundaries: tests are the most isolated component; they always depend inward and nothing depends on them
  • Premature boundaries are expensive, but so are missing boundaries -- draw them when the cost of crossing is less than the cost of not having them
Code applications:
ContextPatternExample
Full boundaryInput/Output port interfaces on both sidesUse Case defines both
PlaceOrderInput
and
PlaceOrderOutput
Partial boundaryStrategy or Facade without full reciprocal interfaces
ShippingCalculator
accepts a
ShippingStrategy
-- simpler than full ports
Humble ObjectSeparate testable logic from hard-to-test infrastructure
PresenterLogic
(testable) produces
ViewModel
;
View
(humble) renders it
Main as pluginComposition root assembles the system
main()
wires all concrete implementations and starts the app
Test boundaryTests depend on source; source never depends on testsTest imports
PlaceOrderInteractor
; production code never imports test code
See: references/boundaries.md
核心概念: 边界是划分重要事项与细节的界限。边界通过多态实现:源代码依赖跨边界向内指向,而控制流可双向跨边界。谦逊对象模式(Humble Object pattern)使边界处的代码可测试。
为何有效: 你绘制的每一条边界都能让你推迟决策或替换实现。边界将易变部分与稳定部分、具体部分与抽象部分分隔开。早期且战略性的边界划分决定了系统在多年后是易于维护还是成为负担。
关键见解:
  • 完整边界在两侧使用双向接口;部分边界使用更简单的策略模式或外观模式
  • 谦逊对象模式:将边界处的行为拆分为两个类——一个难以测试(靠近边界),一个易于测试(包含逻辑)
  • 服务并非天生就是架构边界——拥有臃肿共享数据模型的微服务只是带有网络调用的单体应用
  • 主组件是插件:它创建所有工厂、策略和依赖,然后将控制权交给高层策略
  • 测试边界:测试是最独立的组件;它们始终向内依赖,没有任何组件依赖测试
  • 过早的边界会增加成本,但缺失边界同样昂贵——当跨越边界的成本低于没有边界的成本时,就绘制边界
代码应用:
场景模式示例
完整边界两侧都有输入/输出端口接口用例同时定义
PlaceOrderInput
PlaceOrderOutput
部分边界无完整双向接口的策略或外观模式
ShippingCalculator
接收
ShippingStrategy
——比完整端口更简单
谦逊对象将可测试逻辑与难以测试的基础设施分离
PresenterLogic
(可测试)生成
ViewModel
View
(谦逊对象)渲染它
主组件作为插件组合根组装系统
main()
注入所有具体实现并启动应用
测试边界测试依赖源代码;源代码绝不依赖测试测试导入
PlaceOrderInteractor
;生产代码绝不会导入测试代码
参考:references/boundaries.md

Common Mistakes

常见错误

MistakeWhy It FailsFix
Letting the ORM leak into business logicEntities become coupled to the database schema; changing the DB means rewriting business rulesSeparate domain entities from persistence models; map between them at the adapter layer
Putting business rules in controllersLogic becomes untestable without spinning up HTTP; duplication across endpointsMove all business logic into Use Case Interactors; controllers only translate and delegate
Framework-first architectureThe framework dictates folder structure and dependency flow; swapping frameworks means a rewriteTreat the framework as a plugin in the outermost circle; structure code by business capability
Circular dependencies between componentsChanges ripple unpredictably; impossible to release independentlyApply DIP to break cycles or extract a shared abstraction component
One giant Use Case per featureUse Cases become bloated orchestrators with thousands of linesSplit into focused Use Cases with single application operations
Skipping boundaries "because it's simple"Coupling accumulates silently; by the time you need a boundary, the cost is enormousDraw boundaries proactively at points of likely volatility
Treating microservices as automatic good architectureA distributed monolith with shared databases and tight coupling is worse than a well-structured monolithApply the Dependency Rule within and across services; services are deployment boundaries, not architectural ones
错误失败原因修复方案
让ORM渗透到业务逻辑中实体与数据库模式耦合;更改数据库意味着重写业务规则将领域实体与持久化模型分离;在适配器层进行两者之间的映射
将业务规则放在控制器中逻辑无法脱离HTTP环境进行测试;端点间存在重复代码将所有业务逻辑移至用例交互器;控制器仅负责转换和委托
以框架为先的架构框架决定文件夹结构和依赖流;更换框架意味着重写将框架视为最外圈的插件;按业务能力组织代码
组件间存在循环依赖变更会引发不可预测的连锁反应;无法独立发布应用DIP打破循环,或提取共享抽象组件
每个功能对应一个庞大的用例用例变得臃肿,成为包含数千行代码的编排器拆分为聚焦单一应用操作的用例
因「简单」而跳过边界耦合会悄然累积;当你需要边界时,成本已高得惊人在可能易变的点主动绘制边界
将微服务视为天生的优秀架构带有共享数据库和紧密耦合的分布式单体应用比结构良好的单体应用更糟糕在服务内部和跨服务应用依赖规则;服务是部署边界,而非架构边界

Quick Diagnostic

快速诊断

QuestionIf NoAction
Can you test business rules without a database, web server, or framework?Business rules are coupled to infrastructureExtract entities and use cases behind interfaces; mock the outer layers
Do source code dependencies point inward on every import?The Dependency Rule is violatedIntroduce interfaces at the boundary; invert the offending dependency
Can you swap the database without changing business logic?Persistence is leaking inwardImplement the Repository pattern; isolate persistence in adapters
Are Use Cases independent of the delivery mechanism?Use Cases know about HTTP, CLI, or message queuesRemove delivery-specific types from Use Case signatures; use plain DTOs
Is the framework confined to the outermost circle?The framework is your architecture instead of a detailWrap framework calls behind interfaces; push framework code to the edges
Can you identify the component dependency graph and confirm it has no cycles?Circular dependencies existApply ADP: use DIP or extract new components to break every cycle
Does Main (or the composition root) wire all dependencies?Concrete classes are instantiated in inner circlesMove all construction logic to Main; use dependency injection or factories
问题如果回答否行动
你能否在无数据库、Web服务器或框架的情况下测试业务规则?业务规则与基础设施耦合将实体和用例提取到接口后;模拟外层
所有导入的源代码依赖是否都向内指向?违反了依赖规则在边界处引入接口;反转违规的依赖
你能否在不更改业务逻辑的情况下更换数据库?持久化逻辑渗透到内部实现仓储模式;将持久化逻辑隔离在适配器层
用例是否独立于交付机制?用例了解HTTP、CLI或消息队列从用例签名中移除交付特定类型;使用纯DTO
框架是否被限制在最外圈?框架成为了你的架构,而非细节用接口封装框架调用;将框架代码移至边缘
你能否识别组件依赖图并确认无循环?存在循环依赖应用ADP:使用DIP或提取新组件打破所有循环
主组件(或组合根)是否注入所有依赖?具体类在内圈中实例化将所有构造逻辑移至主组件;使用依赖注入或工厂

Reference Files

参考文件

  • dependency-rule.md: The Dependency Rule explained, concentric circles, data crossing boundaries, keeping the inner circle pure
  • entities-use-cases.md: Enterprise Business Rules, Application Business Rules, the Interactor pattern, request/response models
  • adapters-frameworks.md: Interface adapters, frameworks as details, database as a detail, plugin architecture
  • component-principles.md: REP, CCP, CRP, ADP, SDP, SAP -- component cohesion and coupling
  • solid-principles.md: SRP, OCP, LSP, ISP, DIP with code examples and common violations
  • boundaries.md: Boundary anatomy, Humble Object pattern, partial boundaries, Main as a plugin, test boundaries
  • dependency-rule.md:依赖规则详解、同心圆结构、跨边界数据、保持内圈纯净
  • entities-use-cases.md:企业级业务规则、应用级业务规则、交互器模式、请求/响应模型
  • adapters-frameworks.md:接口适配器、框架作为细节、数据库作为细节、插件架构
  • component-principles.md:REP、CCP、CRP、ADP、SDP、SAP——组件内聚与耦合
  • solid-principles.md:SRP、OCP、LSP、ISP、DIP,含代码示例和常见违规情况
  • boundaries.md:边界结构、谦逊对象模式、部分边界、主组件作为插件、测试边界

Further Reading

延伸阅读

This skill is based on Robert C. Martin's definitive guide to software architecture. For the complete methodology with detailed examples and case studies:
本技能基于Robert C. Martin的权威软件架构指南。如需获取包含详细示例和案例研究的完整方法论:

About the Author

关于作者

Robert C. Martin ("Uncle Bob") is a software engineer, author, and one of the founding signatories of the Agile Manifesto. He has been programming since 1970 and has consulted for and trained development teams worldwide. Martin is the author of Clean Code, The Clean Coder, Clean Architecture, and Clean Agile, among other books. He is the founder of Uncle Bob Consulting LLC and cleancoder.com. His SOLID principles have become foundational vocabulary in object-oriented design, and his advocacy for craftsmanship and discipline in software development has influenced generations of programmers. Martin's work consistently argues that software architecture is about managing dependencies, drawing boundaries, and keeping business rules independent of delivery mechanisms and infrastructure details.
Robert C. Martin(「鲍勃大叔」) 是软件工程师、作家,也是敏捷宣言的创始签署人之一。他自1970年开始编程,曾为全球各地的开发团队提供咨询和培训。Martin是《Clean Code》、《The Clean Coder》、《Clean Architecture》和《Clean Agile》等多部著作的作者。他是Uncle Bob Consulting LLC和cleancoder.com的创始人。他提出的SOLID原则已成为面向对象设计的基础词汇,他对软件开发工艺与严谨性的倡导影响了一代又一代程序员。Martin的著作始终强调,软件架构的核心是管理依赖、划分边界,以及保持业务规则独立于交付机制和基础设施细节。