48

我有几个编程工作。每个有 20-50 名开发人员,项目进行 3-5 年。

每次都是一样的。有些程序员很聪明,有些程序员很普通。每个人都有自己的 CS 学位,每个人都读过设计模式。意图是好的,人们正在努力编写好的代码,但几年后代码还是变成了意大利面条。模块 A 的更改突然破坏了模块 B。代码中总是有这些部分,除了编写它的人之外,没有人能理解。更改基础架构是不可能的,并且向后兼容性问题阻止了良好的功能进入。一半的时间你只想从头开始重写所有内容。

比我更有经验的人认为这是正常的。是吗?它必须是吗?我能做些什么来避免这种情况,或者我应该接受它作为生活的事实吗?

编辑:伙计们,我对这里的回复数量和质量印象深刻。这个网站和它的社区摇滚!

4

18 回答 18

30

无情的勤奋与不断的单元测试相结合是防止意大利面条式代码的唯一方法。即便如此,这也只是一个创可贴的解决方案。一旦你停止注意,意大利面就会出现。

我经常发现引入意大利面条代码是因为那天有人很懒惰。他们知道有更好的方法可以做到这一点,只是没有时间。当你看到这种情况发生时,只有一件事要做。

打电话给他们并要求他们改变它

我发现在代码审查期间指出更好的方法通常足以让人们继续前进。如果他们签入并且我感觉很强烈,我会自己重构它。

我偶尔会显得有点古怪吗?我确定我会的。坦率地说,虽然我不介意。我不是一个混蛋,并以最好的社交方式处理这个问题。然而,让错误的代码被签入几乎可以确保我在将来的某个时候必须对其进行调试。我宁愿现在稍微接受一下,然后输入正确的代码。

我还觉得单元测试文化也有助于防止意大利面条式代码。对分解良好的代码的意大利面条代码进行单元测试要困难得多。随着时间的推移,这迫使人们在一定程度上保留他们的代码。

于 2008-12-15T21:06:17.043 回答
15

我相信避免代码腐烂的关键在于健全的自下而上的设计和实现方法(我坚信这一点,因此我将我的业务命名为 - Think Bottom Up - 在它之后!)。这里选择的工具是:

  • 合约编程
  • 分层设计
  • 专注于脱钩
  • 始终考虑重用,寻找通用解决方案
  • 保持框架轻量、简单和专注

正如其他受访者所建议的,您需要及早发现问题。对于绿色开发人员,这意味着指导(结对编程在这里很棒)和审查(代码和设计审查)。对于更高级的开发人员,这意味着保持警惕。

最重要的是,不要害怕重构。如果重构让你感到害怕,那么你已经沉没了。如果重构被认为是“坏的”,那么你的业务就出了问题。

当您修复某些东西时,请正确修复它。我使用术语“fux”来描述以错误方式完成的修复:它只是“fux”了您的代码库。

干杯,

于 2008-12-15T23:20:13.560 回答
12

20 到 50 名开发人员可能是问题所在。这是相当高的,需要大量的管理和资源来控制一切。

我会考虑将项目分成更小的可重用部分。从核心系统中抽象出某些层。

于 2008-12-15T21:03:46.500 回答
11

在代码的不同区域之间创建“防火墙”。为此,您可以定义不同的区域或代码层,并定义每个层响应的单个 API(在 Java 中,这通常通过接口完成)。应该有 API 使用的基本接口或类,但它们对这些层的内部“一无所知”。例如,gui 不应该知道或关心您如何存储数据,并且您的数据库不应该知道或关心数据如何呈现给最终用户。

这些 API 不必一成不变——您应该能够根据需要添加一些东西,只要您确保不会污染防火墙。

于 2008-12-15T21:04:44.253 回答
7

我认为重点是当你说

您只想从头开始重写所有内容

只是拥抱它。
尽可能多地使用单元测试,然后让重构成为一种常见的做法
自动化和单元测试将确保更改不会引入回归;将一定比例的时间用于重构旧代码(这意味着更少的新功能!)确保现有代码库不会变旧,或者至少不会那么快。

于 2008-12-15T21:08:22.373 回答
7

代码审查、编码标准和公司政策。

以下适用于我们的店铺-由于我不知道您的店铺类型,您的里程可能会有所不同。在迁移到 Team Foundation Server 时,我们的大部分重点是保持代码质量 - 或至少以任何可能的方式帮助保持质量。我们添加的一些示例:

  • 代码审查工作流程 - 强制执行代码审查作为流程的一部分。包含一项政策,如果代码未经审查,将阻止签入。
  • TeamReview - 通过提供完整的“IDE 内部”体验,减少代码审查的痛苦。
  • Check-in Policies (in general) - 许多很酷的好东西可用于控制代码流。例如确保在签入之前记录公共和受保护的方法,以确保在没有相应工作项的情况下无法签入任何工作。

就像我说的,如果您使用的是不同的平台,那么可用的工具和您可以做的可能会有所不同。但不排除以任何可能的方式提供帮助的工具。如果您可以使用它来改进、控制和审核您的工作流程以及在其中移动的项目,那么它至少应该值得考虑。

请记住,流程中的任何更改都将涉及回退。我们帮助缓解这一问题的方法是将策略构建到培训中,以便从旧的版本控制/缺陷跟踪系统过渡。

于 2008-12-15T21:15:26.837 回答
3

听起来很多人没有遵循封装和良好设计的一些基本原则。

保持事物隔离且不依赖于其他部分对于避免您描述的问题至关重要。您可能需要一些更高级别的设计师或架构师。这是一个典型的场景,人们已经证明了一些严厉的流程和变更管理是合理的。(我不提倡)

您需要避免依赖和相互关系,并且只定义和使用公共接口。这当然是过于简单化了,但你可能会通过一些关于代码的指标来学习很多东西——类的复杂性、公共方法、通过对代码进行逆向工程构建的 UML 图等。

于 2008-12-15T21:07:40.130 回答
3

我认为通过全面使用依赖注入可以获得的松散耦合是一项非常有用的技术特性。当您拆分应用程序的各个部分时,您不太可能因为“有趣的”重用而得到意大利面条。

相反,您可能会走向过度碎片化,但这是另一个问题,而不是全球结构性问题。

于 2008-12-15T21:09:13.450 回答
3

软件行业最大的问题是编程代码的质量被视为一个主观问题。如果没有一些明确定义的指标,仅仅保持整洁和遵循惯例并不足以确保质量是可以接受的。

有人试图改变这一点,但它们不太可能获得足够的兴趣或接受,主要是因为长期以来建立的程序员文化是非常努力地远离任何类似于工程的东西。编程的“纯艺术”哲学意味着您的 20 到 50 名开发人员都会以自己独特的方式对代码进行猛烈抨击,因此无论单个编码人员多么出色,团队努力的总和总是会达到成为“大泥球”。

为避免这种情况,要么将所有编码人员放在同一个“页面”上,将规范化代码作为约定的一部分,要么在开发团队较小(1-3 人)并且你是大人物的情况下追逐工作。总有一天,大团队可能会找到一种方法来构建更好的东西,但在那之前,即使是最优秀的团队也非常幸运,如果他们能接近 10 个中的 6 个。我们构建低质量的软件,因为这就是我们已经建立的我们的行业要做...

保罗。

于 2008-12-15T22:27:42.307 回答
3

在至少有两双眼睛看到之前,不要让代码提交。

于 2008-12-16T02:39:56.387 回答
2

您必须密切关注软件开发实践。必须进行代码审查和单元测试,不断确保更新会影响系统中的其他内容。20 - 50 名开发人员很多,但可以做到。实施良好的流程是在这种环境中拯救您的唯一方法。强制编码标准也是关键。

于 2008-12-15T21:06:26.637 回答
2

重构

努力保持设计尽可能干净。这并不容易,但值得付出努力。

于 2008-12-15T21:06:38.367 回答
2

我不认为这是正常的。当它在那里存在几年时,它真的很难与之抗争。

避免它的唯一方法是改变态度:

“敏捷开发人员对软件设计的态度与外科医生对无菌手术的态度相同。无菌程序使手术成为可能。没有它,感染的风险将高得无法忍受。敏捷开发人员对他们的设计也有同样的感受。即使是最微小的腐烂开始的风险也太高了,无法容忍。” Martin C. Robert “C# 中的敏捷原则、模式和实践”</p>

我强烈建议您查看这本书以获取建议。它列出了所有“设计气味”、它们存在的原因以及离开它们的后果。愿这将帮助您说服您的管理层当前的情况是不合适的。

祝你好运!

于 2008-12-15T21:09:00.673 回答
1

更多的代码审查,也许还有代码所有权。

如果您只是破解一些随机代码,那么您就不会像您“拥有”的代码那样关心。如果维护项目的一个模块是您的责任,那么您希望大放异彩。

代码审查是您展示代码的时候。

于 2008-12-15T21:04:50.493 回答
1

跟踪系统各个部分的缺陷和性能将使您能够识别问题。随着系统的更改,设计不良或编写不良的功能或模块将具有更高的缺陷率。当识别出“问题”模块时,可以做出重写模块(而不是应用程序)的决定。

于 2008-12-15T21:08:09.520 回答
1

持续重构。您必须随时进行重构,尤其是在设计级别。当您看到损坏的代码或设计时,请准备好修复它。这通常是修复一些本身没有损坏的东西的情况。除了它是……它只是没有表现出它的破碎……然而。

于 2008-12-15T21:13:37.277 回答
1

Shore 和 Warden 的The Art of Agile Development是一本很棒的书,其中有一节是关于“将 XP 应用于现有项目”(在第 4 章中)。除非您努力奋斗,否则项目会随着时间的推移变得更糟:克服此类技术债务很难,并且会越来越难以发布可接受的版本。唯一的解决方案是降低交付新功能的速度,并将节省的时间用于提高测试覆盖率和重构。

通常,项目没有太多的测试覆盖率,也没有选择运行一个 10 分钟的自动化脚本来非常彻底地构建和运行您的代码。相反,大多数代码都是结构化的,因此很难测试。最好的选择是在可能的情况下添加简单的测试覆盖,同时开始重构以使代码抽象化,以便更容易测试。

尽管团队需要花时间改进代码以使其干净且可测试,但您可能无法在“完成”清理所需的时间内停止交付。因此,您必须逐步完成,同时还要添加新功能。没关系,先选择最糟糕的领域,不要指望马上有明显的好处。坚持下去,因为最终你会到达那里。不要听那些说所有大项目都不好的声音。

简而言之,每周花一点时间整理一下,确保下周的代码比这周更好。

于 2008-12-18T16:02:40.773 回答
0

开始创建单元测试,这将帮助您解耦代码并避免错误修复的后续错误。如果您有良好的覆盖范围,它也将使您更容易删除未使用的代码。

于 2008-12-15T21:09:30.810 回答