【发布时间】:2019-05-24 19:11:19
【问题描述】:
我的一些背景知识:我是一名自学成才的程序员,6 年前加入 MegaCorp(TM) 时,他开始使用 Python 并学习 Java。拥有数学学位,我在算法和批判性思维方面相当扎实(不是双关语),但我经常发现自己在数据结构、设计或其他 CompSci 基础知识方面存在差距,而我的同行在他们的计算机科学中学到了这些基础知识课程。
为此,我向团队中的一位高级工程师寻求一本书推荐来帮助填补我的空白,他建议Clean Architecture。
我大约完成了三分之一,并且对这些建议的主要激励因素之一感到非常困惑。鲍勃叔叔提出了许多想法和原则(包括我以前听说过的SOLID 原则,尽管我仍在掌握里氏替换原则)旨在“保护”系统的某些部分从需求到改变。有几个例子,但最清楚的是第 73 页:
如果应该保护组件 A 免受组件 B 的更改,那么 组件 B 应该依赖于组件 A。
(我应该注意到,在没有任何我可以看到的实际定义的情况下,我认为“组件”等同于 Java 包,尽管我认为如果可以应用相同的思考过程, “组件”是一个单独的服务——两者都应该为用户提供稳定可用的接口,无论是本地调用还是通过网络调用)
这个说法没有任何证据,对我来说也不是不言而喻的。考虑组件(包)ComponentA 中的类ClassA 的情况,它在组件ClassB 中调用DoStuffReturn doStuff(DoStuffInput input, String someOtherArg) ComponentB - 其中调用是通过直接依赖或通过对接口的依赖in ComponentB(not in ComponentA,正如 Clean Architecture 所建议的那样)
- 如果 B 中的更改是功能更改,而不是签名更改(即 - 对于相同的
DoStuffInput和String输入,返回不同的DoStuffReturn),则 A 中不需要更改:-
ClassA对ClassB.doStuff的调用仍然有效(相同的参数和返回类型) -
ClassA的单元测试(应该使用模拟的ClassBs)应该仍然通过 - 任何测试
ClassA和ClassB如何协作的功能/集成测试都需要更新他们的期望,但这并不是对ComponentA的更改(除非这些测试在中 @ 987654340@ - 我通常在ComponentAIntegrationTests包中看到它们外部化,但我想它们也可以放在一起。不过,这似乎不是本书所暗示的 - 它似乎是在谈论代码的更改,而不是测试)
-
- 如果 B 中的更改是对
doStuff以外的方法的签名更改,则 A 不需要任何更改 - 如果 B 中的更改是对
doStuff的签名更改,那么 A 将需要更改 - 但如果接口也在 A 中,情况也是如此。
(请注意,在清洁架构提倡的设置下,其中提供类的接口在消费组件(A)中,只有第一种情况会构成 B 的变化 - 所以这是我们真正需要的唯一一个关心)
我错过了什么?如果 ComponentA 依赖于 ComponentB,那么在什么情况下 ComponentB 中的类的改变需要 ComponentA 的改变?
(请注意,我不反对使用接口 - 它们还有许多其他好处,尤其是允许在合同的“双方”同时开发,并允许交换接口的各种实现)
【问题讨论】:
标签: oop architecture solid-principles dependency-inversion