我经常发现自己正在与过度工程作斗争 - 负责设计软件的人提出了一种过于复杂的架构。
拥有用户永远不会知道的所有深奥功能,并且当你做的所有杂志文章告诉你的东西都是最新的,很酷的东西时,它会变得很好,但是我们是将我们工作时间的一半留在这个纪念碑上我们的聪明,而不是,你知道,我们的用户需要的实际产品和高层管理人员希望在合理或至少有限的时间范围内完成。
当你开始没时间的时候,也就是说,如果你有机会的话,你可能只需要回到更简单的解决方案。
我们都听过这句话:保持简单,愚蠢。
你如何与团队中的过于复杂作斗争?
我最近不得不反复使用的一个例子是,当决定进入完全非规范化的数据库设计而不是RDBMS时。 “因为它更快!”完全非规范化的数据库确实难以正确,并且仅适用于Flickr或ebay等真正专业的数据问题,而且相对于开发的其他部分而言,开发人员的时间可能非常昂贵。
答案 0 :(得分:12)
牙齿和指甲,有时你输了。问题在于,很容易想要构建 cool 的东西。
为什么在复杂而精彩的时候构建简单有效的东西?
尝试提醒人们建立可能有效的最简单的事情的XP规则。
答案 1 :(得分:6)
确保将您从其他人那里获得的任何想法都反弹。通常情况下,我们会以某种方式处理事情,以至于需要另一组眼睛才能使你正确。曾经有很多次我通过让其他人说“我们真的需要那个吗?”来解决困难问题。这有助于简化我的代码。
在处理你不同意的人时,Ward Cunningham有一个很好的观点:
这是我编程生涯中的一个转折点,当我意识到我不必赢得每一个论点。我会和别人谈论代码,我会说,“我认为最好的方法是A.”而且他们会说,“我认为最好的方法就是B.我会说,”不,这真的是A.“他们会说,”好吧,我们想做B.“我可以说,“好吧,这是我的转折点。做B.如果我错了,这不会伤害我们。如果我是对的并且你做B,这不会伤害我们,因为,我们可以纠正错误。所以让我们看看这是不是一个错误。 ......通常它原来是C.这对我们两个人来说都是一次学习经历。如果我们在没有经验的情况下做出决定,我们都不会真正学习。沃德赢了,其他人没有。或相反亦然。这太激烈了。为什么不说,“好吧,让我们编写代码并看看会发生什么。如果它不起作用,我们将改变它。”“
我的建议?如果你想做更好的事情,想出一个简单的原型,证明它更好。意见很棒,但代码会谈。
答案 2 :(得分:6)
我在某处看到了这个公式:
换句话说,它需要技能来创建复杂问题的简单解决方案。如果有人故意设计并为复杂的过度设计解决方案感到自豪,那么他就会无意识地无能为力。
就个人而言,TDD周期是什么帮助我保持设计简单。首先编写一个测试,指定您要尝试访问的内容,然后生成"the simplest thing that could possibly work"。并且时不时地反思你所制作的东西,并思考如何使它更简单。
永远不要在系统中构建额外的灵活性和抽象层,直到你现在拥有的东西需要它为止。当你有一个好的单元测试套件时,更改代码很容易,所以你可以在需要时添加这些抽象层, if 它出现了。否则,"you ain't gonna need it"。
设计过于复杂的一些症状是编写测试时很复杂。如果测试需要很长的设置代码,那么您可能有太多的依赖关系或者其他方式太复杂。如果遇到并发错误,那么也许你应该考虑如何设计系统,以便将并发限制在绝对最小的类数。也许使用消息传递架构,例如Actor模型,并使几乎每个组件都是单线程的,即使整个系统是多线程的。
答案 3 :(得分:4)
至少对我而言,更大的问题是,由于它的流行语友好,杂志般的企业性优点而且通常很难分辨出那里有什么功能,因为它增加了一定程度的灵活性,未来。
已经表明,人们在预测未来的复杂性和当前决策的副作用方面通常很糟糕。不幸的是,这并不总是最简单的最好 - 在我的情况下,我认为一开始有很多东西太复杂,直到很久以后才看到它们的价值(呃......春天)。我认为有些事情变得非常复杂(EJB1)。所以我知道我对这些事情的直觉是错误的。
最好的选择 - 任何类型的间接层都应该支持一个支持其增加的灵活性值与其增加的开发复杂性的参数。
然而,那些在抽象的基础上教条地维护特定数据库设置的人可能正在“构建它,因为我读到它是正确的”阵营。这可能是不现实的,但有些人可能会相信你是否构建了一个测试版本和基准测试,特别是如果结果表明会有更多的努力导致性能提升不显着。
答案 4 :(得分:3)
拥有一切都很好,很花哨 用户将会深奥的功能 永远不知道和......
这将是feature creep,而不是不必要的复杂设计。它与您在数据库上的示例不同。
我必须与之合作的一个例子 最近一再是决定的时候 已经完全去了 非规范化的数据库设计 而不是RDBMS。 “因为它更快!”
在这种情况下,可能会发生一些事情。其中一个是,你可能错了,这些人真的可以知道他们在说什么,因为他们使用了非常相似的例子。另一个是他们可能是错的,即他们的设计没有提供他们声称的速度优势。在这种情况下,可能存在两种不同的情况:(1)它们在设计中给予速度太大的重量,或者(2)速度非常关键。如果速度确实如此相关,团队不应仅仅依赖于假设 - 他们应该尝试不同的原型并评估他们在关键路径中的速度。你不会以“因为速度更快”的方式建造一辆F1赛车,而是继续尝试几种替代设计解决方案并挑选最快但不会过多增加维护成本的解决方案。
有时你可以争辩并达成协议,有时候你不能。这就是生活。
但最后一句话。 你没有打击复杂性。你对待它。你确定了真正重要的事情,并采取相应的行动。
答案 5 :(得分:2)
我认为你的意思是“完全非规范化的数据库设计而不是规范化的(例如,第三或第四范式)模型”,因为关系模型由RDBMS管理,无论它是如何规范化的。
如果不了解您的要求,能力以及队友的能力,就无法判断。
我担心你的KISS警告在这种情况下可能不起作用,因为一个大的,非规范化的表可能被保护为最简单的事情。
有人如何解决这些问题?沟通,说服,更好的数据,替代技术和技术的原型。这就是软件开发如此艰难的原因。如果只有一种方法来做这些事情,并且每个人都同意这些事情,我们真的可以编写脚本或者让任何人开发系统并完成它。
获取一些数据。你的话可能还不够。如果快速原型可以证明你的观点,那就创建它。
“强烈的意见,轻视”应该是你的座右铭。
有时技术要点不值得疏远整个团队。有时它是。你的电话。
答案 6 :(得分:2)
您可以通过以下几种方式与其他人的过度设计/功能蔓延进行斗争:
根据实际用户要求请求功能优先级。模拟alpha和beta测试人员的功能,并询问他们是否会延迟N个月的延迟。
积极重构以避免特殊套管。在适当的时候将代码分解为层或模块化组件。在“现在工作正常”和“以后容易延长”之间找到平衡。
当您不同意设计决策,准备被推翻并接受决定时,请通知您的管理层。不要超过任何人的头部或破坏密码。
答案 7 :(得分:2)
我找到的最好的方法是不断地问 - 一次又一次 - '我们试图解决的业务问题是什么'以及'这个决定如何帮助解决这个问题'。
我发现人们经常跳到解决方案而不是清楚问题是什么。
因此,在您组织数据库的示例中,我的问题是“我们认为今天,下个月,明年,五年后该项目的交易要求是什么”。可能需要花费大量时间来正确获取数据模型,这可能是浪费时间。在明确问题定义之前,您不知道参数是什么。
答案 8 :(得分:1)
您可能会遭受“团队中太多建筑师”综合症的困扰。一个或两个人最多应该设计/构建一个由5到10人组成的团队编写的系统。欢迎所有人的参与,但建筑决策者应该很少并且经验丰富。
(这些数字是半随机数,也可能因其他因素而有所不同)
答案 9 :(得分:0)
我在讨论问题时尽量保持开放。但是,当我与其他人讨论一些看似简单而另一个看似简单的事情时,我会变得顽固。只要你从一个决定到另一个决定非常连贯,它就会有很大的帮助。
答案 10 :(得分:0)
你的例子并不是一个复杂的设计,它是你不同意的设计选择。既然你正在编写代码,你可能很容易做对,因为很多这些决定都是由人们阅读文章中的文章并认为这听起来像是一个好目标,或者决定可能是由遇到的人做出的。之前的问题,并试图阻止它再次发生。
就我个人而言,我已经做了很多简单的事情和很多艰难的事情,而且当我选择以艰难的方式做一些简单的事情时,我永远不会高兴。现在我已经学会了“永远不会绕过一个裸体集合,总是将它包装在商务舱中”的技巧。
如果我要向那些没有经历过相同经历的人解释背后的理由,他们就不会理解它,直到他们尝试将“简单方法”与“困难方式”比较几次。 / p>
答案 11 :(得分:0)
解决方案应该不比问题复杂。
这个问题与基本复杂性的思想交织在一起。排序必须触及每个元素的本质。鉴于存在技术限制,解决问题需要多少复杂?
答案 12 :(得分:0)
相关人员是否有足够的时间和动力去寻找简单的解决方案?如果不小心,复杂性就会增加。如果您花费大部分时间尝试尽可能快地修复错误或添加功能,那么说“保持简单”是不够的。
确保团队中有一些人因为维护大型程序和有重构经验的人而受到战争伤害,然后给他们时间对软件进行排序。如果您可以安排某些功能和机会超出范围,这将有助于人们删除不需要的代码。如果您想要一个指标,旨在减少代码行;但尽量不要迷恋它。提高测试覆盖率;考虑消除难以测试的代码。
答案 13 :(得分:0)
不要试图一蹴而就。将每个问题/任务分解为可管理的块。然后优先考虑,记住KISS和YAGNI。这将有助于您专注于构建您需要的内容。如果你做得对,你会有一个很好的核心,你可以在以后添加,给予时间,金钱,资源和灵感。