我已经从事软件开发工作多年了。我的经验是,随着越来越多的开发人员参与产品开发,项目变得更加复杂和难以维护。

似乎在开发的某个特定阶段,软件趋向于变得“骇客”和“骇客”,尤其是当没有一个定义架构的团队成员在公司工作时。 />
我感到沮丧的是,必须更改某些内容的开发人员很难了解架构的概况。因此,存在一种解决问题或以与原始体系结构相抵触的方式进行更改的趋势。结果是代码变得越来越复杂,甚至更难以理解。

是否有关于如何保持源代码多年来真正可维护的有用建议?

评论

强烈推荐的书籍:史蒂夫·麦康奈尔(Steve McConnell)的“软件项目生存指南”,史蒂夫·麦康奈尔(Steve McConnell)的“快速开发”,马丁·福勒(Martin Fowler)的“重构”

...以及Bob叔叔(Bob叔叔)的“清洁代码”;)(Robert C. Martin)

难道这不是几十年来在大学引起大量阅读和整个课程价值的问题吗?

@Eric Yin-我不同意这些评论。对我来说,它们是一种代码味道,从长期来看,项目往往弊大于利,因为它们不可避免地会过时并产生误导。

@Eric Yin:争取自记录代码。仅在意图增进理解的情况下使用意图注释。

#1 楼

避免代码腐烂的唯一真正的解决方法就是编写好代码!

如何编写良好的代码是另一个问题。即使您是一个优秀的程序员,单独工作也很难。在一个异构团队中,这变得更加困难。在外包(子)项目中...只需祈祷。

通常的良好做法可能会有所帮助:


保持简单。
保持简单。这尤其适用于架构“大局”。如果开发人员很难掌握大局,那么他们将根据它进行编码。因此,使体系结构简单,以便所有开发人员都能使用。如果架构必须不那么简单,那么必须培训开发人员以了解该架构。如果他们没有将其内部化,则不应在其中进行编码。
目标是实现低耦合和高内聚性。确保团队中的每个人都理解这个想法。在一个由松散耦合的内聚部件组成的项目中,如果某些部件变得无法维护,则只需拔下插头并重写该部件即可。如果联接紧密,则更难或几乎不可能。
保持一致。遵循哪些标准无关紧要,但是请遵循某些标准。在团队中,每个人当然都应遵循相同的标准。另一方面,很容易变得过于依赖标准而忘记了其余的内容:请务必理解,尽管标准很有用,但它们只是编写良好代码的一小部分。不要花很多。

代码审查对于使团队保持一致的工作可能很有用。
确保所有工具(IDE,编译器,版本控制,构建系统,文档生成器,库,计算机,椅子,整体环境等)都得到良好维护,以使开发人员不必浪费时间在诸如此类的次要问题上由于战斗项目文件的版本冲突,Windows更新,噪音以及任何平庸但令人讨厌的内容。不得不反复浪费大量时间处理这些无趣的东西,这会降低士气,至少不会提高代码质量。在一个大型团队中,可能会有一个或多个主要工作是维护开发人员工具的人。
在做出技术决策时,请考虑一下如何切换技术;哪些决定是不可逆的,哪些不是。仔细评估不可逆转的决策。例如,如果您决定用Java编写项目,那是一个几乎不可逆的决定。如果您决定对数据文件使用某种自煮式二进制格式,那也是一个相当不可逆的决定(一旦代码狂放了,您就必须继续支持该格式)。但是GUI的颜色很容易调整,以后可以添加最初遗漏的功能,因此减轻了此类问题的负担。


评论


这些都是要点。我必须承认,我一直在为“保持简单”而努力。这似乎在不同的上下文中对不同的人意味着不同的事物,这使“简单”变得相当复杂(但是我确实有使事物复杂化的自然倾向)。

–克拉米
2012年1月10日上午10:06

我完全同意您的观点,尤其是“ KIS”。但是我看到一种趋势,即越来越多的(年轻的)开发人员使用相当复杂的结构来描述最简单的上下文。

–chrmue
2012年1月10日10:29



@chrmue:请参阅“如何用Java编写阶乘” ;-)

–乔纳斯·普拉卡(Joonas Pulakka)
2012年1月10日上午10:49

嗯,然后说“ 8.保持简单”。

–达伍德·伊本·卡里姆(Dawood ibn Kareem)
2012年1月11日在2:57

#6值得+10。

– Jim G.
2012年1月11日下午4:41

#2 楼

单元测试是您的朋友。实施它们会降低耦合度。这也意味着可以轻松识别和重构程序的“ hacky”部分。这也意味着可以快速测试所有更改,以确保它们不会破坏现有功能。这应该鼓励您的开发人员修改现有方法,而不是因为担心会破坏代码而重复代码。通过广泛的单元测试,程序员无需了解程序的整个体系结构即可进行更改并使用现有的类/方法。

作为一个很好的副作用,单元测试也有望减少您的错误计数。

评论


非常重要的一点。我接管了一个旧系统,许多类,许多行代码,没有文档,没有单元测试。努力为所有代码修复和增强创建单元测试后,系统设计已演变为更清洁,更可维护的状态。而且我们有“勇气”来重写重要的核心部分(由单元测试覆盖)。

–山姆·戈德堡
2012年1月10日于20:08

#3 楼

这里的每个人都很快提到了代码腐烂,我完全理解并同意这一点,但是它仍然怀念这里更大的前景和更大的问题。代码腐烂不只是发生。此外,提到的单元测试很好,但是它们并不能真正解决问题。一个人可以拥有良好的单元测试覆盖范围和相对无缺陷的代码,但是仍然烂掉了代码和设计。总体架构,从而实现对系统的入侵。负责实施和影响设计的技术领导者在哪里?此过程中的代码审查在哪里?

您实际上并没有遭受代码腐烂的困扰,但是却遭受团队腐烂的困扰。事实是,软件的原始创建者不再在团队中也没关系。如果现有团队的技术负责人能够完全,真正地理解底层设计,并且擅长担任技术负责人,那么这将不是问题。

评论


很好,您击中了靶心!说来可悲,但这正是这里发生了什么。没有技术领导者,似乎不可能改变事情……

–chrmue
2012年1月10日12:57

@chrmue我想事情发展的方向,但是我对此感到厌倦。从很多方面来说,我希望我能再次成为初级开发人员,而当时我还没有意识到周围的一切似乎有多糟糕。看来我正处于职业中期危机的早期。但是我正在漫步...很高兴能提供帮助。

– Maple_shaft♦
2012年1月10日13:11

@Murph在维护阶段为什么不应该有一个全知的团队负责人?我曾经遇到过的每个老板,无论团队领导,都期待着什么,而当我还是团队领导时,我对自己的期望也一样。

– Maple_shaft♦
2012年1月10日13:27

@maple_shaft,因为a)我不认为有专门负责该项目的团队负责人,或多或少是第一个要求,并且b)我认为您需要了解设计和实现(所有这些),并且硬。一方面,我们都认为我们不应该在项目中使用所有知识的单一字体,但是在这里我们要说我们必须拥有一个字体?那不累加吗?

–墨菲
2012年1月10日13:36

@maple_shaft可能让我成为一个脾气暴躁的老程序员(-:但有一个问题,就是在现有代码库中经常需要遵循实现“样式”,这可能与编码器和领导者都不一样(很多现实原因)。

–墨菲
2012年1月10日14:44

#4 楼

我们可以做几件事:

让一个人全面负责架构。选择该人员时,请确保他们具有开发和维护体系结构的远见和技能,并具有帮助其他开发人员遵循体系结构的影响力和权威。该人应该是一个经验丰富的开发人员,应该得到管理层的信任,并且应该得到同行的尊重。所有开发人员都需要参与开发和维护体系结构完整性的过程。

开发一种环境,在此环境中可以轻松传达体系结构决策。鼓励人们谈论设计和架构-不仅在当前项目的上下文中,而且在总体上也是如此。注释代码,开发单元测试等。诸如命名约定和简洁的编码实践之类的东西可以在沟通体系结构方面大有帮助,因此作为一个团队,您需要花一些时间来开发和遵循自己的标准。 br />确保所有必要的文档都是清晰,简洁,最新且可访问的。公开高低级的架构图(将它们固定在墙上会有所帮助)并且可以公开维护。 ,但是还有更重要的事情-例如组建一个可以很好地协同工作并实际交付有效产品的团队。

评论


+1,特别是对于“组建一支可以很好地协同工作并实际交付有效产品的团队”。

–deworde
2012年1月10日上午10:16

让一个人负责架构是一个好主意。但是,如果经常使用该职责,则您会有“团队气味”:团队自然应该达成共识,而不是依靠一个人来提供答案。为什么?该项目的全部知识总是共享的,将其钉在一个人身上最终会带来更大的问题:只有他的观点得到满足,才能有效地割裂团队其他成员的翅膀。而是雇用最优秀的人才,让他们一起努力。

–凯斯
2012年1月12日15:44

@casper:是的。您表达的是我的想法,而不是我的想法。

–克拉米
2012年1月12日23:12

#5 楼

我解决此问题的方法是在根目录下进行剪裁:

我的解释将使用Microsoft / .NET中的术语,但适用于任何平台/工具箱:


使用标准来命名,编码,签入,错误流,过程流-基本上是任何东西。有些开发人员根本无法在一套既定的标准内工作,并且会成为战场上的第5列敌人,以保持代码库的清洁。
使用军械库中的所有工具来避免检入烂掉代码:这涉及专用工具以及用于测试构建文件,项目文件,目录结构等的预先编写的单元测试。
大约5至8名成员组成的团队,几乎要不断地让您最好的人进行重构-清理其他人留下的混乱局面。即使您在该领域找到了最优秀的专家,您仍然会一团糟-这是不可避免的,但是它会受到不断重构的约束。
编写单元测试并进行维护-不要依赖单元测试为了保持项目清洁,他们没有。
讨论所有内容。不要害怕花一些时间来讨论团队中的事情。这将散布信息并消除导致代码错误的根本原因之一:技术,目标,标准等方面的混乱。
请顾问编写代码时格外小心:实际上,他们的代码将是真实的糟糕的东西。
最好在办理登机手续之前进行审核。不要害怕回滚提交。
除非在发布前的最后阶段,否则不要使用打开/关闭原则:它只会导致腐烂的代码被闻到。
每当遇到问题时,在实施解决方案之前都要花点时间充分理解它-大多数代码腐烂来自实施解决方案以解决尚未完全理解的问题。
使用正确的技术。这些通常是成组出现的,而且是新鲜的:最好依靠将来可以确保获得支持的beta版本的框架,而不要依靠不受支持的极其稳定但过时的框架。最好的人。
放开其余的人-您不是在经营咖啡店。
如果管理人员不是最好的建筑师,并且他们干扰了决策过程,请另谋高就。


评论


现在,如果您必须在“业余时间”中进行C#重写时必须维护和增强具有100种形式和类的12年噩梦般的VB6应用程序,该怎么办?

– jfrankcarr
2012年1月10日15:31

与#3不同。测试不应被视为对未经培训的惩罚。实际上,它应该由所有开发人员完成,并且与编码和设计同样重要!如果您的团队中有未经培训的先生,那么请让他离开团队进行培训!。

–新创建
2012年1月11日,9:54

“与#3不同。测试不应被视为对未经训练的人的惩罚。” -它不是我写的,也不是我写的。让我解释一下:测试是让您不知道的人信任所做的更改以进入代码的一种好方法。我发现最好的测试人员是那些渴望成为代码贡献者的人员,他们通过浏览代码,运行程序来证明自己的能力,并展示了将运行时的发现与源代码相关联的能力。这不是惩罚-它的训练。

–凯斯
2012年1月12日15:37

“不同意#10-如果正确完成,将有助于提高代码质量”在我的工作经验中,这绝对是错误的:无法重构锁定的代码,这意味着它将一直保持当前状态,直到被解锁为止。可以在某种情况下验证此状态是否正常,但是在以后的阶段,此验证是错误的肯定:应保留所有代码以进行重构,直到进行最终系统测试为止。

–凯斯
2012年1月12日15:37

@casper:恕我直言,打开/关闭原则不应理解为“您不能更改源代码”,而应“设计代码使其变得冻结”。确保可以根据需要扩展代码,而不需要对其进行更改。其结果是,与普通代码相比,其耦合性和灵活性大大增强。当开发供第三方使用的库时,该原则也至关重要,因为第三方不能随便进入并修改您的代码,因此您需要将其适当地扩展。

–凯文·卡斯卡特(Kevin Cathcart)
2012年1月12日21:00



#6 楼

在编写单元测试时,通过重构来清理烂掉的代码。每当您进行以下操作时,都将为所有涉及的代码付出设计债务:


开发新功能
解决问题

速度很快您的测试优先开发周期:


重构以将代码模块转换为脚本语言
使用基于云的快速测试机

重构通过以下方式使用低耦合(具有高度内部凝聚力的单元)的代码:


更简单的(更多)函数(例程)原型)
纯函数(无副作用)
在继承上优先考虑委托>
有机增长良好;大的前期设计是不好的。

有一位对当前设计有知识的领导者。如果没有,请阅读项目的代码,直到您了解为止。

阅读重构书籍。

评论


+1好的第一个答案,是向我们介绍自己的完美方法!

– yannis
2012年1月11日在8:22

#7 楼

简单的答案:您不能。

这就是为什么您应该致力于编写小型而简单的软件的原因。这并不容易。

只有当您对看似复杂的问题思考了足够长的时间,并以尽可能简单和简洁的方式对其进行定义时,这才可能。

解决问题的方法确实,大型和复杂的解决方案通常仍然可以通过使用小型和简单的模块来解决。 />如果这不可能或不可行,则您可能正在进行研究(复杂的问题,没有已知的简单解决方案,或者根本没有已知的解决方案)。不要指望研究会直接生产可维护的产品,这不是研究的目的。

#8 楼

我为自1999年以来就一直在持续开发的产品开发代码库,因此您可以想象到现在它已经相当复杂了。代码库中最大的黑手根源是无数次,我们不得不将其从ASP Classic移植到ASP.NET,从ADO移植到ADO.NET,从回发到Ajax,切换UI库,编码标准等。

总而言之,我们已经做了合理的工作来保持代码库的可维护性。我们所做的主要贡献在于:

1)持续重构-如果您不得不接触一段hacky或难以理解的代码,那么您将需要花费额外的时间进行清理,并在时间表中留有余地。单元测试使这一点不那么令人恐惧,因为您可以更轻松地对回归进行测试。

2)保持整洁的开发环境-警惕删除不再使用的代码,不要离开项目目录中存在备份副本/工作副本/实验代码。

3)在项目生命周期中使用一致的编码标准-让我们面对现实,我们对编码标准的看法会随着时间而发展。我建议您在项目的整个生命周期中都坚持使用您开始使用的编码标准,除非您有时间回过头来对所有代码进行改造以符合新标准。很高兴您现在掌握了匈牙利符号,但可以将这堂课应用到新项目中,而不仅仅是在新项目上切换中游。

#9 楼

由于您已用项目管理标记了问题,因此我尝试添加一些非代码点:)


营业额计划-假设整个开发团队将消失进入维护阶段的时间–没有值得花时间的开发人员想要永远维护其系统。有时间后就开始准备移交材料。
一致性/一致性不够强。这将阻止“独自一人”的文化,并鼓励新开发人员提出疑问(如果他们有疑问的话)。级别)将有更多的机会快速启动并运行。
文档-尤其是架构-制定决策的原因以及编码标准。还要保留参考/注释/路线图以记录业务领域-您将惊讶于公司业务向没有领域经验的开发人员解释他们所做的工作有多么困难。
明确制定规则-不仅适用于您当前的开发团队,但请考虑将来的维护开发人员。如果这意味着在每个页面上都提供指向相关设计和编码标准文档的超链接,那么就做到这一点。随着新技术的出现,例如,用HTML5 jQuery UI等替换Web Forms UI,这可能会增加一年的寿命。


#10 楼

高度可获取的代码的一个特性是函数纯度。

纯度意味着函数对于相同的参数应返回相同的结果。也就是说,它们不应依赖于其他功能的副作用。此外,如果它们本身没有副作用,则很有用。

与耦合/内聚特性相比,此特性更容易被看到。您不必全力以赴来实现它,我个人认为它更有价值。

当您的函数是纯函数时,其类型本身就是一个很好的文档。此外,以参数/返回值的形式编写和阅读文档比提及某些全局状态(可能被其他线程O_O访问)要容易得多。 ,您可以看到GHC。这是一个大约有20年历史的大型项目,正在进行大型重构,并且仍在引入新的主要功能。

最后,我不太喜欢“保持简单”的观点。在对复杂事物进行建模时,不能使程序保持简单。尝试制作一个简单的编译器,您生成的代码可能会变得非常缓慢。当然,您可以(并且应该)使单个功能简单,但结果整个程序将变得不简单。

评论


您所描述的另一个名称是确定性的属性

– jinglesthula
2014年2月20日在20:41

#11 楼

除了其他答案之外,我还建议您使用图层。不是很多,但足以分隔不同类型的代码。

我们对大多数应用程序使用内部API模型。有一个内部API连接到数据库。然后是一个UI层。不同的人可以在每个级别上工作而不会破坏或破坏应用程序的其他部分。

另一种方法是让每个人都阅读比较风险和The Daily WTF,以便他们了解不良设计和不良编程的后果,而他们会看到在《每日WTF》上发布自己的代码而感到恐惧。

#12 楼

由于许多答案似乎都集中在庞大的团队上,即使从一开始,我就将自己的观点视为一个由两人组成的开发团队(如果包括设计师在内,则为三个)的初创公司。

显然,简单的设计和解决方案是最好的选择,但是当您真正付了薪水的家伙垂涎三尺时,您不一定就没有时间考虑最优雅,简单和可维护的解决方案。考虑到这一点,我的第一个重点是:

文档不是注释,代码主要应该是自我文档,但是诸如设计文档,类层次结构和依赖关系,体系结构范式之类的东西。新的甚至是现有的程序员来了解代码库。另外,记录最终弹出的那些奇怪的伪库,例如“将此类添加到用于此功能的元素中”,可能会有所帮助,因为它还可以防止人们重写功能。

即使您确实有严格的时间限制,我也要记住的另一件好事是:

避免黑客和快速修复。除非快速解决方案是实际解决方案,否则总要找出某个问题的根本问题,然后再进行解决。除非您确实有一个“在接下来的2分钟内解决该问题,否则您将被解雇”的方案,那么立即进行修复是一个更好的主意,因为您稍后将不修复代码,而只是转到下一个任务。

我个人最喜欢的提示是加引号,尽管我不记得来源:当你是一个知道自己住在哪里的杀人心理变态者之后。“

评论


我一直发现函数和类注释是有用的,即使只是通过使用语法突出显示来在函数和类位置提供代码段的分隔。我很少在函数代码中添加注释,但是我为每个类和函数写了一行,例如/ **获取特定日期的临床医生的可用时间。 ** /或/ **代表临床医生。 ** /。

–尼克·贝德福德(Nick Bedford)
18-10-19在5:17

#13 楼


做一个侦察兵。始终让代码清洁器保持原状。
修复破损的窗户。当您使用3.0版时,所有这些注释都将“在2.0版中进行更改”。如果您不能作为一个团队来修复黑客,那么您对系统的了解就不够。 “请大人帮助。”周围的最年长的人可能以前见过。尝试绘制或提取系统图。尝试以交互图的形式绘制或提取特别难用的用例。这不能解决问题,但至少您可以看到。
将设计推向特定方向的不再是什么假设?
如果您解释了系统的工作原理(甚至只是一个用例),并且发现自己不得不一遍又一遍地向子系统道歉,那就是问题所在。行为将使系统的其余部分变得更简单(无论实现起来看起来有多困难)。要重写的经典子系统是一个用其操作语义和实现污染所有其他子系统的子系统。 “哦,在将值输入到froo子系统之前,必须对这些值进行上浆,然后在从froo中获得输出时再次取消对它们的上浆。也许在从用户和存储读取时,所有值都应该上浆,而系统的其余部分是错误的呢?当存在两个或多个不同的化石时,这会变得更加令人兴奋。
花一个星期的时间来团队清除警告,以便看到真正的问题。
将所有代码重新格式化为
确保您的版本控制系统与bug跟踪器绑定在一起。这意味着将来的更改是很好且负责任的,并且您可以制定出为什么。
做一些考古。查找原始设计文档并进行审查。它们可能位于办公室一角的那台旧PC上,废弃的办公空间或文件柜中,从来没有人打开过。这有助于使知识制度化。
编写类似清单的过程以进行发布和构建。这使人们不必思考,因此他们可以专注于解决问题。尽可能自动进行构建。
尝试持续集成。构建失败越早,项目花费的时间就越少。获得适当的单元测试和覆盖范围。因此问题不会变得更糟。
尝试对一些未经单元测试的旧位进行单元测试。这有助于减少对变更的恐惧。
如果可能的话,可以自动执行集成和回归测试。至少有一个清单。飞行员很聪明,可以拿到很多薪水,他们使用清单。他们也很少搞砸。


#14 楼

开放/封闭原则是我没有提到但我认为很重要的一个原则。相反,可以通过子类扩展现有的类,或者使用它们编写包装器,装饰器类或使用您认为合适的任何模式。但是请不要更改工作代码。

我只需2美分。

评论


如果工作代码中表达的业务需求发生变化怎么办?从长远来看,不要轻描淡写但技术上“有效”的代码可能会伤害您,特别是当需要进行必要的更改时。

– jinglesthula
2014年2月20日下午0:49

@jinglesthula:开放扩展意味着您可以将新功能添加为现有接口的新实现(例如,类)。当然,结构不良的代码不允许这样做:应该有一个类似于接口的抽象,允许通过添加新代码而不是修改现有代码来“更改”代码。

–乔治
2014-02-20 6:52



不更改旧代码正是代码腐烂的发生方式。如果您依赖垃圾,则只能产生垃圾。有时,要清理掉代码腐烂,您必须舍弃数千行代码。唯一的方式是截止日期。

–贝斯特
20年7月21日在16:47

#15 楼

阅读然后重新阅读Steve McConnell的《代码完成》。从最初的项目设计到单行代码,以及介于两者之间的所有内容,这就像是一本善于编写软件的圣经。我最喜欢它的是它得到了数十年可靠数据的支持。这不仅仅是次佳的编码风格。

#16 楼

我来称它为“温彻斯特神秘屋效应”。就像房子一样,它的开始非常简单,但是多年来,许多不同的工人在没有总体计划的情况下增加了如此多的奇特功能,以至于没有人真正了解它。为什么这个楼梯无处可去,为什么那扇门只能以一种方式打开?谁知道?

限制这种效果的方法是从一个良好的设计开始,该设计应具有足够的灵活性以应对扩展。已经对此提出了一些建议。

但是,通常情况下,您会从事已经造成破坏的工作,并且对于一个好的设计而言,为时已晚,而又不进行昂贵且可能有风险的重新设计和重写。在这种情况下,最好尝试找到方法来限制混乱,同时在一定程度上接受混乱。一切都必须经过巨大的,丑陋的,单例的“经理”类,或者数据访问层与UI紧密耦合,这可能会烦恼您的设计敏感性,但要学会处理它。在该框架内进行防御性代码编写,并尝试当程序员的“鬼魂”过去时出现意外情况。

#17 楼

代码重构和单元测试非常好。但是,由于这个长期运行的项目正在遭受黑客攻击,因此这意味着管理层不会放下脚步清理腐败。该团队需要引入黑客手段,因为有人没有分配足够的资源来培训人员和分析问题/请求。

维护长期运行的项目与单独的开发人员一样,都是项目经理的责任。

人们不会引入黑客,因为他们喜欢它。他们是受环境所迫。

评论


迫于环境?人们之所以介绍骇客,是因为(a)他们不了解=>需要辅导;(b)他们没有看到大局面=>需要沟通,文档和纪律;(c)他们认为自己更聪明=>那是最大克服由环境造成的障碍(d)=>在有时间压力的情况下,可以快速修复此错误,但是必须有人负责并随后清理代码。任何其他“情况”就是BS。该经验法则有例外,但最常见的例外是“懒惰”。

– JensG
14-6-5在8:17



#18 楼

我只想提出一个非技术性问题,并提出一种(也许)务实的方法。

如果您的经理不关心技术质量(可管理的代码,简单的体系结构,可靠的基础结构等等) ,因此很难改善项目。在这种情况下,有必要对上述经理进行教育,并说服他们“投入”精力进行可维护性和解决技术债务。有关此内容。

或者,如果您只是想驯服“ Frankenstein项目”,这些是我的提示:


组织和简化
缩减功能
优先考虑可读性而不是效率(当然,在可接受的情况下,有些效率提高太惨了而无法保持)

根据我的经验,编程是熵的,而不是紧急的(至少在流行的命令中,结构化范例)。当人们编写代码以“正常工作”时,趋势就是失去组织。现在组织代码需要时间,有时甚至还不止于工作。

除了功能实现和错误修复之外,还要花时间清理代码。

评论


“……这个项目注定要失败”-以我的经验来看,不一定如此。另一种方法是教育所说的经理,并说服“投入”精力进行可维护性和解决技术债务

– gna
2014年2月5日在19:09

抱歉,我无法坚持自己的看法,因为当经理无视我关于技术债务的所有建议时,我已经有了经验。但是我认为您是对的:在我放弃该项目大约一年后,经理因无法管理项目而失去了对技术团队的所有权限。

– Eric.Void
2014年2月5日19:30在

#19 楼

我很惊讶地发现,众多答案中没有一个能凸显出显而易见的意义:使该软件包含众多小型独立库。使用许多小型库,您可以构建大型而复杂的软件。如果需求发生变化,则不必扔掉整个代码库,也不必研究如何修改大型honking代码库来执行除当前正在执行的操作之外的其他操作。您只需确定需求更改后哪些库仍然相关,以及如何将它们组合在一起以具有新功能。请注意,例如任何支持函数指针的非面向对象语言都实际上支持面向对象编程(OOP)。因此,例如在C中,您可以执行OOP。

您甚至可以考虑在许多项目之间共享那些小的独立库(git子模块是您的朋友)。

不用说,每个小型独立图书馆应进行单元测试。如果某个特定的库无法进行单元测试,则说明您做错了。较大的.so文件,或者您也可以执行静态链接。对于Java同样如此,只需将.so更改为.jar。

评论


从我的角度来看,这似乎有点过于理论化。当然,我在问题中提到的项目是由多个库和模块构成的。我在过去26年的软件开发中的经验是,项目越老越能得到最初的组织

–chrmue
17年7月21日在9:29

#20 楼

简单:将大部分代码的维护成本降低到零,直到您拥有可维护数量的活动部件为止。无需更改的代码不会产生维护成本。我建议旨在使代码真正具有零维护成本,而不是试图在许多小而繁琐的重构迭代中降低成本。立即使其成本为零。

好吧,诚然,这比听起来要难得多。但是开始并不难。您可以获取一部分代码库,对其进行测试,如果接口设计一团糟,则可以在其上构造一个不错的接口,并同时开始扩展代码库中可靠,稳定(例如无需更改的原因)的部分缩小不可靠和不稳定的零件。感觉像是噩梦般维护的代码库通常无法将需要更改的活动部分与不需要更改的部分区分开来,因为一切都被认为是不可靠的且容易更改。我实际上建议一路将代码库的组织分为“稳定”部分和“不稳定”部分,稳定部分是要重建和更改的巨大PITA(这很好,因为它们不需要如果它们确实属于“稳定”部分,则可以对其进行更改和重新构建。)

使维护变得困难的不是代码库的大小。这是需要维护的代码库的大小。每当我说使用操作系统的API时,我就依赖数百万行代码。但这并不会增加产品的维护成本,因为我不必维护操作系统的源代码。我只是使用代码,它可以工作。我只使用而不需要维护的代码最终不会产生维护成本。