TDD、Scrum和架构:KISS与复杂性冲突

4
我现在已经遵循Scrum、TDD、领域驱动设计和Uncle Bob的指导方针工作了一年,但我对我们是否应用了各种原则有些疑问,特别是在阅读Martin系列中的《Java应用架构》(JAA)时。如果我错了,请纠正我!(希望我错了)
问题从TDD和Scrum开始,它们认为我们应该根据需求逐步演进系统,避免预先设计。这使我留下所有可扩展点,总是滥用各种可扩展性模式。这确实有一个“黑暗面”:给整个系统添加复杂性。我不知道我的代码的某个部分是否需要进一步发展。
但是,正如到处正确地指出的那样(并且在JAA上非常频繁),只有在需要时才应该添加复杂性。我认为这意味着应该进行适当的前期分析...与其他指导方针相冲突...
因此,循环...啊啊啊,我讨厌循环依赖!
在“确认”功能后,我们应该重构以减少复杂性吗?我们应该使用允许的最简单方法,并仅在需要时扩展它吗?例如,在不需要它们时不要构建超级解耦的东西?
(欢迎提出改进问题风格和内容的建议,我是stackoverflow上的新手)
5个回答

8
在“确认”功能后,我们是否应该重构东西以减少复杂性?我们应该使用允许的最简单的方法,并仅在需要时扩展它吗?例如,当您不需要它们时,请不要构建超级解耦合的内容。
是的。虽然这相当主观,但我不喜欢那些具有改变每一个可改变元素的灵活性的系统,而您不会利用所有这些灵活性。但是您的陈述是矛盾的:测试驱动开发教导我“做可能能够起作用的最简单的事情”。
如果需要更多功能,您可以添加测试,然后重构和扩展代码,以确保它执行您想要的操作。因为您已经放置了测试,所以可以放心,您不会破坏当前现有的代码。
简而言之:不要构建灵活性,因为您可以。您应该根据情况指示来构建灵活性。我坚信按需重构会使项目的构建时间缩短,而具有(未使用的)灵活性则不然。有了您的测试,按需重构不应花费太长时间。
更短的说法是:保持简单,愚蠢。 ;)

4

我认为在系统设计中,简化和深入了解之间存在一种平衡。

我试图将短期规划与长期规划分开考虑。在短期规划中,我只考虑几步,如果这个功能在下一个迭代中可能会被扩展/修改/更新,那么我会尽量让它准备好。但如果我看不到任何扩展,我就会遵循KISS原则。

在长期规划中,我至少考虑半年。交互是什么,可能的路线图是什么?这给了我基本的想法,告诉我在哪里应该更加先进一些。

在我的看法中,我们应该在计划和完成短期目标之间做出明智的决策。


2
我怀疑有经验的设计师会在一定程度上依靠直觉。有些“显而易见”的建筑决策,分层、关注点分离等设计决策就像“自然而然”地出现了。诀窍是避免分析麻烦和过度工程化。
随着粒度的增加,接近代码时,“你不需要它”的口号变得更加重要——很容易陷入美丽的灵活性中。但你可以通过一些简单的方法实现未来的灵活性。例如,在(Java)接口方面表达组件之间的关系。您可能不会选择一个完整的抽象工厂模式,但如果消费者编码到一个接口中,引入一个接口就非常容易。同样,不要在代码中散布字符串字面量,而是将它们收集在一个地方,即使现在您不需要将字符串外部化,也可以极大地简化未来的国际化或动态配置。
我看到的真正优秀的设计师似乎几乎像下棋或围棋游戏一样,他们预测未来的走法,但当然不会在必须时立即对其进行响应。(围棋术语 aji-keshi 可以值得考虑。)
这很有趣:我查了一下“aji-keshi”这个词汇,想要解释它的含义,结果发现作者将这个术语应用于系统设计,正好解决了这个问题!

1

毫无疑问,您应该首先添加执行最简单任务的代码 - 但是您添加的代码应遵守SOLID原则。

不要仅仅通过推测未来可能发生的变化就引入复杂性(例如设计模式、框架等)。

您正在解决的问题的本质复杂性是无法改变的。这需要事先思考、头脑风暴,但是偶然复杂性会随着推测而增加。

定期进行同行代码审查有助于解决问题。如果您的同行可以阅读和理解代码而不引起任何疑虑 - 那么我认为这应该没问题。


1
这让我在所有可扩展点上工作,滥用各种可扩展性模式。这确实有一个“黑暗面”:给整个系统增加了复杂性。我事先不知道我的代码的某个部分是否需要进一步发展。
我们应该使用允许的最简单的方法,只有在需要扩展时才进行扩展吗?
我认为至少可以通过调整“简单性”和“复杂性”的定义来解决一部分难题。
JAA“配方”,SOLID原则等都是管理设计中的耦合和内聚的快捷方式。如果您将设计的“简单性”定义为实现最大内聚度和最小耦合度的程度,则可以说这些原则和模式旨在使您的设计保持简单。
因此,根据这个定义,你所谓的“可扩展性点”实际上是保持设计简单的结果,因此没有增加复杂性。此外,它们是否将来用于扩展的目的并不重要,因为简单设计的目的是为了促进未来的变化。
短语“尽可能做最简单的事情”更多地涉及到要构建什么,而不是代码的设计。例如,如果您需要显示一个HTML页面,请构建一个HTML页面,而不是一个Web应用程序。
因此,如果您按照上述“简单性”的定义维护设计方式,并且只构建解决任何给定问题的最小部分,则您的代码库将更小,设计更简单,您的应用程序将邀请未来添加功能所需的更改。
最后一点:注意您的测试对设计的影响。耦合和内聚问题通常表现为难以处理的测试夹具。当您看到这种情况时,这表明您已经跳过了一些必要的重构步骤。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接