关于 architecture-design
面向开发者的架构设计 Skill,采用五步流程,从需求分析、SOLID 与整洁架构设计,到测试规划和 ADR 文档。内容兼有通用指导及 Swift/iOS 专属模式。
主要功能
- 01五步架构设计流程
- 02SOLID 与整洁架构指导
- 03分层及依赖边界设计
- 04单元与集成测试策略
- 05架构决策记录(ADR)
- 06Swift/iOS 并发模式
适用场景
- 01拆分功能并明确组件职责
- 02规划代码库的架构层与依赖
- 03界定各层的测试范围
- 04用 ADR 记录设计决策
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ swiftyjourney/ architecture-design-skill --skill architecture-design安装后在 Claude Code 中输入/architecture-design确认已加载。
详细介绍
架构与设计原则技能
运用整洁架构原则、SOLID 设计模式以及 Essential Developer 方法论中的行业最佳实践,将代码库转变为易于维护、测试和扩展的架构。
概述
此技能将引导你完成一个结构化的 5 步流程:
- 分析需求 → 确定组件、职责和边界
- 应用 SOLID 原则 → 运用 SRP、OCP、LSP、ISP、DIP 进行设计
- 定义整洁架构 → 建立分层、边界和依赖规则
- 设计测试策略 → 规划单元测试、集成测试和测试边界
- 记录决策 → 创建架构决策记录(ADR)
核心理念
“良好的架构是良好的团队流程和沟通的副产品”
此技能遵循以下原则:
- 框架独立性 - 业务逻辑不依赖框架
- 可测试性 - 架构便于进行测试
- UI 独立性 - UI 可以更改,而不影响业务规则
- 数据库独立性 - 业务规则不依赖数据库
- 外部服务独立性 - 业务规则不依赖外部服务
5 步流程
第 1 步:分析需求
目标:确定组件、职责和架构边界
操作:
- 将功能拆分为不同的职责
- 区分核心业务逻辑和基础设施相关内容
- 识别横切关注点(日志记录、分析、缓存)
- 梳理系统中的数据流
- 确定潜在的架构边界
要提出的关键问题:
- 核心业务逻辑是什么?
- 有哪些外部依赖(网络、数据库、UI)?
- 哪些内容需要能够独立测试?
- 哪些组件可能独立更改?
- 每个组件的输入和输出是什么?
输出:职责明确的组件图
参考:有关组件识别模式,请参阅 references/modular_design.md
第 2 步:应用 SOLID 原则
目标:遵循 SOLID 原则设计组件
S - 单一职责原则(SRP)
每个类/模块只有一个更改理由。将业务逻辑与基础设施分离。
- ❌ 一个既加载数据又呈现数据的类
- ✅ 使用独立的
UseCase处理业务逻辑;使用独立的Presenter处理视图逻辑
O - 开闭原则(OCP)
通过协议/接口实现开放扩展、封闭修改:
// Open for extension via protocol (Swift example — same idea in any language)
protocol ItemLoader {
func load() async throws -> [Item]
}
// Closed for modification — implementations extend behavior
final class RemoteItemLoader: ItemLoader { ... }
final class CachedItemLoader: ItemLoader { ... }
final class FallbackItemLoader: ItemLoader { ... }
L - 里氏替换原则(LSP)
子类型必须能够替代基类型。所有实现都必须遵守契约。
I - 接口隔离原则(ISP)
客户端不应依赖自己不会使用的接口。创建专注且具体的协议。
- ❌
protocol DataStore { func save(_:); func load(); func delete(); func migrate(); func backup() } - ✅
protocol ItemReader { func retrieve() throws -> [Item]? }+ 独立的ItemCache
D - 依赖反转原则(DIP)
高层模块依赖抽象,而非具体实现。
class ItemListViewController {
private let loader: ItemLoader // depends on abstraction, not concrete type
init(loader: ItemLoader) { self.loader = loader }
}
输出:符合 SOLID 原则的组件设计
参考:有关详细模式和反模式,请参阅 references/solid_principles.md
步骤 3:定义整洁架构
目标:建立清晰的架构分层和恰当的依赖流向
整洁架构分层:
┌─────────────────────────────────────────┐
│ Presentation Layer │
│ (UI, ViewModels, Presenters) │
└─────────────────┬───────────────────────┘
│ depends on
┌─────────────────▼───────────────────────┐
│ Domain/Business Layer │
│ (Use Cases, Entities, Rules) │
└─────────────────┬───────────────────────┘
│ depends on
┌─────────────────▼───────────────────────┐
│ Infrastructure Layer │
│ (Network, Database, Framework Code) │
└─────────────────────────────────────────┘
依赖规则:源代码依赖只能向内指向
关键模式:
- 用例 — 包含业务规则、编排数据流,独立于 UI 和框架
- 边界(协议) — 定义层与层之间的契约,支持可测试性
- 适配器 — 在各层之间转换数据,实现边界协议
- 组合根 — 连接各项依赖,配置对象图
输出:具有清晰边界的分层架构
参考:详见 references/clean_architecture.md 中的分层定义;examples/generic/layered_architecture.md 中的语言无关示例;以及 examples/swift/ 中的 Swift/iOS 实际实现
步骤 4:设计测试策略
目标:规划涵盖所有架构层的全面测试
测试金字塔:
┌──────────┐
│ UI │ Few - End to End
├──────────┤
│Integration│ Some - Integration
├──────────┤
│ Unit │ Many - Fast & Isolated
└──────────┘
测试边界:
- 领域层(单元测试)— 隔离测试用例,模拟所有依赖项
- 基础设施层(集成测试)— 使用真实依赖项测试适配器
- 表现层(单元测试)— 测试 presenter/view model,模拟用例
测试替身术语:
- 桩:提供预设的答案
- 间谍:记录调用以供验证
- 模拟对象:验证行为预期
- 伪对象:用于测试的可运行实现
测试策略:
- 测试行为,而非实现细节
- 使用原生异步测试原语;当语言支持
await时,避免手动同步回调 - 工厂辅助函数模式:通过
makeSUT()辅助函数一并创建被测系统(SUT)及其依赖项,让各个测试方法保持简洁 - 采用 Arrange、Act、Assert 结构;提取辅助函数以提升清晰度
输出:全面的测试策略文档
参考:有关模式和最佳实践,详见 references/testing_strategies.md
步骤 5:记录决策
目标:创建清晰的架构文档和决策记录
ADR 格式:
# ADR-NNN: <Decision Title>
## Status: Accepted | Superseded | Deprecated
## Context: Why this decision was needed
## Decision: What was decided
## Consequences: Positive and negative outcomes
## Alternatives Considered: What was rejected and why
完整的 ADR 示例见 examples/generic/。
文档要求:
- 架构概述 — 系统上下文图、组件图、分层关系
- 组件文档 — 目的、依赖项、使用示例
- 所用设计模式 — 使用了哪些模式及其原因、权衡
- 测试策略 — 测试内容和方法
输出:完整的架构文档
参考:详细的文档模式见 references/
最佳实践
应该 ✅
- 将业务逻辑与基础设施分离
- 依赖抽象,而非具体实现
- 通过初始化器注入显式声明依赖项
- 为所有业务逻辑编写测试
- 在网络边界使用异步 IO 协议;在进程内存储中使用同步协议
- 使用语言的并发原语,将表现层类型隔离在主线程/UI 线程
- 从一开始就将可测试性纳入设计
不应该 ❌
- 让业务逻辑依赖框架
- 使用单例管理依赖项
- 混合表现逻辑与业务逻辑
- 创建职责过多的上帝类
- 在语言提供原生 async/await 时,使用手动回调/完成处理器模式
- 手动切换到 UI 线程 — 应改用结构化并发
**Swift/iOS:**在网络边界使用
async throws,在缓存边界使用同步throws,对表现层类型使用@MainActor,对跨越 actor 边界的值类型使用Sendable。请参阅下文的 Swift 并发部分。
常见架构模式
- 整洁架构(推荐)——职责分离清晰,依赖规则:只能向内依赖
- 六边形架构(端口与适配器)——业务逻辑位于中心,端口定义边界
- MVVM——分离 UI 和逻辑,视图模型可测试
- MVC——传统的分层方式,由控制器充当组合根
参考:参见 examples/generic/layered_architecture.md,了解与语言无关的分层示例;参见 examples/swift/,了解 Swift/iOS 中的 MVVM+Coordinator、组合根和双层视图
特定语言指南
Swift/iOS
- 网络边界使用
async throws协议 - 缓存/存储边界使用同步
throws;通过Scheduler协议桥接到异步 - 对表示层类型(
ResourceView、LoadResourcePresenter)应用@MainActor - 将领域值类型标记为
Sendable(例如:FeedImage: Hashable, Sendable) - 使用
LoadResourcePresenter<Resource, View>泛型呈现器——一个类型适用于所有功能 - 使用
WeakRefVirtualProxy<T>打破强引用循环,避免为每种类型编写样板代码 - 在
SceneDelegate中应用组合根模式;将基础设施提取到@MainActor服务对象中(参见examples/swift/composition_root.md)
参考:参见 examples/swift/,了解 Swift 特定模式
通用/与语言无关
- 普遍应用 SOLID 原则
- 根据语言使用接口/trait/协议
- 根据语言特性调整模式
- 保持整洁架构分层
参考:参见 examples/generic/,了解与语言无关的示例
Swift 并发 (仅限 Swift/iOS)
本节中的概念——异步 IO 边界、主线程隔离、值类型线程安全、泛型呈现器、内存安全代理——普遍适用。以下语法和 API 则特定于 Swift。详细实现请参见
references/concurrency_patterns.md。
异步协议边界
网络协议使用 async throws;存储协议使用同步 throws:
// Network boundary — async because IO is inherently async
public protocol HTTPClient {
func get(from url: URL) async throws -> (Data, HTTPURLResponse)
}
// Cache/store boundary — sync because the store runs on its own queue (bridged via Scheduler)
// Apply this pattern to any persistent store: CoreData, SQLite, in-memory, Realm, etc.
public protocol ItemStore {
func delete() throws
func insert(_ items: [LocalItem], timestamp: Date) throws
func retrieve() throws -> CachedItems?
}
// Essential Feed uses FeedStore with identical structure for FeedImage caching
@MainActor 隔离
表示层类型使用 @MainActor——无需手动进行线程调度:
@MainActor public protocol ResourceView {
associatedtype ResourceViewModel
func display(_ viewModel: ResourceViewModel)
}
@MainActor public final class LoadResourcePresenter<Resource, View: ResourceView> {
public typealias Mapper = (Resource) throws -> View.ResourceViewModel
public init(resourceView: View, loadingView: ResourceLoadingView,
errorView: ResourceErrorView, mapper: @escaping Mapper)
public init(resourceView: View, loadingView: ResourceLoadingView,
errorView: ResourceErrorView) where Resource == View.ResourceViewModel
public func didStartLoading()
public func didFinishLoading(with resource: Resource)
public func didFinishLoading(with error: Error)
}
Sendable 值类型
跨越 actor 边界的领域实体必须是 Sendable。所有存储属性本身也必须是 Sendable;编译器会对此进行验证:
// Generic pattern — apply to any domain entity
public struct Item: Hashable, Sendable {
public let id: UUID
public let title: String
// String, UUID, URL are all Sendable — compiler is satisfied
}
// Concrete example from Essential Feed:
// public struct FeedImage: Hashable, Sendable { ... }
WeakRefVirtualProxy
通过单一泛型类型和条件一致性来防止强引用循环:
final class WeakRefVirtualProxy<T: AnyObject> {
private weak var object: T?
init(_ object: T) { self.object = object }
}
extension WeakRefVirtualProxy: ResourceErrorView where T: ResourceErrorView {
func display(_ viewModel: ResourceErrorViewModel) { object?.display(viewModel) }
}
extension WeakRefVirtualProxy: ResourceLoadingView where T: ResourceLoadingView {
func display(_ viewModel: ResourceLoadingViewModel) { object?.display(viewModel) }
}
Scheduler 协议
将同步的 FeedStore 桥接到异步上下文,而无需将存储改为异步:
protocol Scheduler {
@MainActor
func schedule<T>(_ action: @escaping @Sendable () throws -> T) async rethrows -> T
}
参考:完整实现和迁移指南请参见 references/concurrency_patterns.md
与需求工程的集成
- 从需求开始 → 用例 → BDD 场景
- 应用此技能 → 架构 → 组件设计
- 实现 → 遵循架构模式
- 测试 → 使用定义的测试策略
参考资料
references/ 中:
- clean_architecture.md - 整洁架构的分层和规则
- solid_principles.md - SOLID 原则详解及示例
- design_patterns.md - 常见模式(适配器、装饰器、组合、空对象等)
- null_object_pattern.md - 空对象模式及测试示例
- command_query_separation.md - 用于缓存设计的 CQS 原则
- dependency_management.md - DI 模式和策略
- testing_strategies.md - 测试模式和最佳实践
- modular_design.md - 模块组织和边界
- concurrency_patterns.md - Swift 并发:async/await、@MainActor、Sendable、Scheduler
examples/ 中:
- swift/ - Essential Feed 中的真实实现(Swift 6)
- generic/ - 与语言无关的示例
输出格式
使用此技能时,请提供:
- 组件分析 - 已识别的组件及其职责
- SOLID 审查 - 应用的原则及其理由
- 架构图 - 各层及其依赖关系(Mermaid)
- 测试策略 - 测试结构和覆盖计划
- ADR - 记录的关键决策
- 实施指南 - 分步重构或实施计划
致谢
基于 Essential Developer 久经验证的架构方法:
版本历史
- 2.1.0 - 通用化以支持多项目:采用与领域无关的 SOLID 示例,分离 Swift 专属指南,添加范围标签,创建通用 ADR 模板并更新通用架构示例
- 2.0.0 - Swift 6 迁移:async/await、@MainActor、Sendable、LoadResourcePresenter、Scheduler、WeakRefVirtualProxy
- 1.0.0 - 初始版本,包含 5 步流程