8

我经常发现自己在与过度工程作斗争——负责设计软件的人提出的架构过于复杂。

拥有所有用户永远不会知道的深奥功能并获得成就感,当您做所有杂志文章都告诉您的最新,很酷的事情时,这一切都很好,但我们将花费我们在这座纪念碑上的一半工程时间是为了我们的聪明才智,而不是,你知道,我们的用户和高层管理人员期望在合理或至少有限制的时间框架内完成的实际产品。

当你开始用完时间时,你可能只需要恢复到更简单的解决方案,也就是说,如果你有机会的话。

我们都听过这样的副歌:保持简单,愚蠢™。

您如何应对团队中的过度复杂性?


最近我不得不反复使用的一个例子是,当决定采用完全非规范化的数据库设计而不是 RDBMS 时。“因为它更快!” 完全非规范化的数据库真的很难做到正确,并且只适用于像 Flickr 或 ebay 这样的真正专业的数据问题,并且相对于您的其余开发,这在开发人员时间方面可能非常昂贵。

4

14 回答 14

12

牙齿和指甲,有时你会失去。问题是总是很容易被诱惑去构建一些很酷的东西。

既然可以复杂而美妙,为什么还要构建简单而高效的东西呢?

尝试提醒人们构建可能可行的最简单的东西的 XP 规则。

于 2009-03-02T16:38:18.687 回答
6

确保从其他人那里获得任何想法。通常,我们如此专注于以某种方式做事,以至于需要另一双眼睛才能让你正确。有很多次,我通过让其他人说“我们真的需要那个吗?”来解决难题。这有助于使我的代码更简单。

关于与你不同意的人打交道,沃德坎宁安有一个很好的观点:

当我意识到我不必赢得所有争论时,这是我编程生涯的一个转折点。我会和某人谈论代码,我会说,“我认为最好的方法是 A。” 他们会说,“我认为最好的方法是 B。我会说,“不,这真的是 A。”他们会说,“好吧,我们想做 B。”当我可以说:“好吧。做 B。如果我错了,它不会对我们造成太大伤害。如果我是对的而你做 B,这不会对我们造成太大伤害,因为我们可以纠正错误。所以让我们看看它是否是一个错误。... 通常结果是 C。这对我们俩来说都是一次学习经历。如果我们在没有经验的情况下做出决定,我们都不会真正学到东西。沃德赢了,而其他人没有。或相反亦然。这是一场太多的战斗。为什么不说,“好吧,让我们编写代码,看看会发生什么。如果它不起作用,我们会改变它。”

我的建议?如果你想做更好的事情,想出一个简单的原型来证明它更好。意见很好,但代码会说话。

于 2009-03-02T17:38:35.233 回答
6

我在某处看到过这个公式:

技能=问题的复杂性/解决方案的复杂性 http://img39.imageshack.us/img39/1586/whatisskill.png

换句话说,它需要技巧来为复杂问题创建简单的解决方案。如果有人故意设计并以复杂的过度设计解决方案为荣,那么他在不知不觉中无能。

就个人而言,帮助我保持设计简单的是 TDD 循环。首先编写一个测试来指定您要达到的目标,然后生成“可能工作的最简单的东西”。并且时不时地反思一下你制作的东西,并思考如何让它变得更简单。

Never build extra flexibility and abstraction layers into the system, until it is required by something that you have now. Changing the code is easy, when you have a good unit test suite, so you can add those abstraction layers later, when the need arises, if it ever arises. Otherwise, "you ain't gonna need it".

Some symptoms of too complex design are when writing tests is complicated. If the tests require a long setup code, maybe you have too many dependencies or in some other way too much complexity. If you run into concurrency bugs, then maybe you should think about how to design the system so that concurrency is restricted to the absolute minimum number of classes. Maybe use a message-passing architecture, such as the Actor model, and make practically every component single-threaded, even though the system as a whole is multi-threaded.

于 2009-05-30T17:16:40.980 回答
4

至少对我来说,更大的问题是,由于其流行语友好、杂志企业的优点,通常很难说出其中有什么功能,而其中有哪些功能是因为它增加了一定程度的灵活性,在未来会有用。

研究表明,人们通常很难预测未来的复杂性以及当前决策的副作用。不幸的是,这并不总是意味着最简单就是最好的——就我而言,有很多事情一开始我认为太复杂了,直到很久以后(呃......春天)才看到它的价值。还有一些我认为是有道理的事情,结果被证明过于复杂(EJB1)。所以我知道我对这些事情的直觉是错误的。

最好的选择——任何类型的间接层都应该得到支持它增加的灵活性的价值与增加的开发复杂性的论据。

但是,在抽象的基础上教条地维护特定数据库设置的人可能属于“构建它,因为我读到它是正确的”阵营。这可能不切实际,但是如果您构建了一个测试版本和基准测试,有些人可能会相信,特别是如果结果显示更多的努力导致性能提升微不足道。

于 2009-03-02T16:48:33.480 回答
3

拥有用户永远不会知道的所有深奥的功能,这一切都很好,而且......

这将是功能蠕变,而不是不必要的复杂设计。它与您在数据库上的示例不同。

最近我不得不反复使用的一个例子是,当决定采用完全非规范化的数据库设计而不是 RDBMS 时。“因为它更快!”

在这种情况下,可能会发生几件事。其中之一是,你可能错了,这些人可能真的知道他们在说什么,因为他们使用了非常相似的例子。另一个是他们可能是错误的,即他们的设计没有提供他们声称的速度优势。在这种情况下,可能有两种不同的情况:(1)他们在设计中过于重视速度,或者(2)速度真的很关键。如果速度确实如此重要,那么团队不应该仅仅依赖于假设——他们应该尝试不同的原型并评估他们在关键路径中的速度。您不会仅仅“因为它更快”而以一种方式制造 F1 赛车,而是不断尝试几种替代设计解决方案,并选择速度最快且仍不会增加太多维护成本的解决方案。

有时你可以争论并达成协议,有时你不能。这是生活。

不过,最后一句话。你不会对抗复杂性。你对待它。你确定真正重要的事情并采取相应的行动。

于 2009-03-02T17:01:25.773 回答
2

我假设您的意思是“完全非规范化的数据库设计,而不是规范化的(例如,第三或第四范式)模型”,因为关系模型由 RDBMS 管理,而不管它的规范化程度如何。

如果不了解更多关于您的要求、您的能力和您的队友的能力,就无法判断。

我担心你的 KISS 警告在这种情况下可能不起作用,因为一个大的、非规范化的表可能会被认为是最简单的东西。

有人如何解决这些问题?沟通、说服、更好的数据、替代技术和技术的原型。这就是软件开发如此困难的原因。如果只有一种方法可以做这些事情,并且每个人都同意它们,我们真的可以编写脚本或让任何人开发系统并完成它。

获取一些数据。你的话可能还不够。如果一个快速原型可以证明您的观点,请创建它。

“强烈的意见,轻举妄动”应该是你的座右铭。

有时一个技术点不值得疏远整个团队。有时是的。你的来电。

于 2009-03-02T16:43:23.867 回答
2

您可以通过以下几种方式与其他人的过度设计/功能蠕变作斗争:

  1. 根据实际用户需求请求功能优先级。为 Alpha 和 Beta 测试人员模拟功能,并询问他们是否愿意为此延迟 N 个月。

  2. 积极重构以避免特殊情况。适当时将代码分解为层或模块化组件。在“现在可以正常工作”和“以后易于扩展”之间找到平衡点。

  3. 当您不同意设计决策、准备被否决并接受决策时,请通知您的管理层。不要越过任何人的头脑或破坏代码。

于 2009-03-02T17:34:13.667 回答
2

我发现最好的方法是无情地问——一次又一次——“我们试图解决的业务问题是什么”和“这个决定如何帮助解决这个问题”。

我发现人们经常跳到解决方案上,而不是清楚地知道问题是什么。

因此,在您关于如何组织数据库的示例中,我的问题是“我们认为这个项目今天、下个月、明年、五年后的交易要求是什么”。花大量时间来正确构建数据模型可能是有意义的,这可能是浪费时间。在明确问题定义之前,您不知道参数是什么。

于 2009-03-02T18:45:19.613 回答
1

您可能患有“团队中有太多架构师”综合症。最多一两个人应该设计/架构一个系统,该系统将由 5 到 10 人的团队进行编码。欢迎大家提出意见,但架构决策者应该很少且经验丰富。

(数字是半随机的,也可能因其他因素而有所不同)

于 2009-03-02T16:39:16.483 回答
0

我在讨论问题时尽量保持开放。但是当我和别人在一件看似简单的事情和另一件复杂的事情之间进行讨论时,我会变得很固执。只要您从一个决定到另一个决定非常连贯,它就会有很大帮助。

于 2009-03-02T16:39:29.603 回答
0

您的示例实际上并不是一个复杂的设计,而是您不同意的设计选择。由于您正在编写代码,因此您很可能是正确的,因为其中许多决定是由阅读文章中的文章并认为这听起来像是一个好目标的人做出的,或者该决定可能是由遇到的人做出的之前的问题,并试图防止它再次发生。

就个人而言,我做过很多简单的事情,也做过很多困难的事情,当我选择用简单的方式而不是艰难的方式做某事时,我从不快乐。现在我学会了诸如“永远不要传递裸体系列,总是把它包裹在商务舱中”这样的技巧。

如果我要向没有经历过相同经历的人解释其背后的原因,直到他们尝试将“简单方法”与“困难方法”进行几次比较后,他们才会理解。

于 2009-03-02T17:18:12.240 回答
0

解决方案不应该比问题更复杂。

这个问题与本质复杂性的思想交织在一起。排序必须触及每个元素,就其本质而言。考虑到存在的技术限制,它必须变得复杂多少才能解决问题?

于 2009-03-02T17:23:29.497 回答
0

相关人员是否有足够的时间和动力来找到简单的解决方案?不小心,复杂性会增加。如果您花费大部分时间尝试尽可能快地修复错误或添加功能,那么说“保持简单”是不够的。

确保团队中有一些因维护大程序而受过战争创伤的人,以及有重构经验的人,然后给他们时间整理软件。如果您可以安排某些功能和机会超出范围,那将有助于人们删除不需要的代码。如果你想要一个度量标准,目标是减少代码行数;但尽量不要沉迷于此。提高测试覆盖率;考虑消除难以测试的代码。

于 2009-03-02T17:24:35.330 回答
0

不要试图一口气做所有事情。将每个问题/任务分解成可管理的块。然后优先考虑,记住 KISS 和 YAGNI。这将帮助您专注于构建您需要的东西。如果你做得对,你将拥有一个很好的核心,你可以在以后添加时间、金钱、资源和灵感。

于 2009-03-02T17:34:03.403 回答