知识卡片

一个基于Web/数据库的Java系统案例:完整走通整洁架构数据流

结构图卡

内容

一个把[[整洁架构四层的具体职责业务实体用例接口适配器框架驱动]]和[[跨越架构边界用输出端接口反转控制流与源码依赖的方向]]落到具体实现的完整例子:Web服务器从用户处收集信息交给Controller(接口适配器层),Controller把这些信息包装成一个简单Java对象,穿过InputBoundary传给UseCaseInteractor(用例层);UseCaseInteractor解析数据、控制与Entities(业务实体层)的交互,同时通过DataAccessInterface把Entities需要的数据从Database(框架驱动层)加载进内存;UseCaseInteractor再从Entities收集数据、把结果组装成另一个简单Java对象OutputData,OutputData穿过OutputBoundary传给Presenter(接口适配器层)。Presenter的任务是把OutputData重新打包成可展示的ViewModel(同样是简单Java对象)——ViewModel基本只包含字符串和View要用的开关型数据:OutputData里的Date对象会被Presenter格式化成对用户展示的字符串填进ViewModel,Currency对象等业务数据也经历类似处理,Button和MenuItem的命名连同它们是否可用的开关数据也定义在ViewModel里。最后View(接口适配器层)除了把ViewModel的数据转换成HTML格式外,不承担任何其他功能。贯穿整条链路最值得注意的是依赖关系方向:所有跨边界的依赖箭头(Controller→InputBoundary→UseCaseInteractor,Presenter实现OutputBoundary,DataAccessInterface由Database一侧的实现类反向实现)无一例外都指向内层,完整遵守了整洁架构的依赖关系规则——这套划分让系统天生可测试(UseCaseInteractor和Entities的测试完全不需要真正的Web服务器或数据库),也让Web框架、数据库这些外层组件在过时时能被轻松替换,而不牵动内层的业务逻辑。

结构图

flowchart LR
    Web[Web服务器] --> Controller
    Controller -->|包装成简单Java对象| InputBoundary[InputBoundary接口]
    InputBoundary --> UseCaseInteractor
    UseCaseInteractor <--> Entities[Entities业务实体]
    UseCaseInteractor -->|DataAccessInterface| Database[(Database)]
    UseCaseInteractor -->|组装OutputData| OutputBoundary[OutputBoundary接口]
    OutputBoundary --> Presenter
    Presenter -->|格式化Date/Currency等| ViewModel[ViewModel: 字符串+开关数据]
    ViewModel --> View
    View -->|仅做HTML转换| HTML[HTML输出]

参考来源

- 位置:《架构整洁之道》第22章《整洁架构》"一个常见的应用场景""本章小结"(源文件:_epub-src/text/part0014_split_007.html) - 结论依据:原文详述Controller→InputBoundary→UseCaseInteractor→Entities/Database→OutputData→OutputBoundary→Presenter→ViewModel→View的完整数据流,并强调所有跨边界依赖箭头都指向内层、遵守依赖关系规则,说明这套结构使系统天生可测试且外层组件可被轻松替换,直接支撑本卡片的结构图与解释。 - 原始内容:Controller将这些信息数据包装成一个简单的Java对象……最后,OutputData会穿越OutputBoundary被传递给Presenter……View除了将ViewModel中的数据转换成HTML格式之外,并没有其他功能……所有跨边界的依赖线都是指向内的,这很好地遵守了架构的依赖关系规则。