软件公司如何有效管理代码复杂性

本文深入探讨了软件公司中代码复杂性的管理策略,从个体程序员的角色到管理者的协调方法,提供了具体可行的步骤来识别、优先处理和解决代码质量问题,帮助团队构建更可维护的代码库。

软件公司如何管理代码复杂性

作者:Max Kanat-Alexander
发布日期:2015年1月6日

以下是一个显而易见但具有微妙影响的陈述:只有个体程序员能够解决代码复杂性。

也就是说,解决代码复杂性需要个体人员对该代码的关注。他们当然可以使用适当的工具来简化任务,但最终,简化代码的是人类智慧、关注和工作的应用。

那么,这又有什么关系呢?为什么这很重要?更明确地说:解决代码复杂性通常需要在个体贡献者层面进行详细的工作。

如果经理只是说“简化代码!”然后就此打住,通常什么也不会发生,因为(a)他们不够具体,(b)他们不一定具备关于每个代码片段的具体知识,(c)理解问题的过程实际上就是解决问题的过程,而经理并不是编写解决方案的人。

经理在公司中的级别越高,这一点就越明显。当CTO、副总裁或工程总监发出“提高代码质量”这样的指令,但没有更具体说明时,往往会发生的情况是公司内部有很多动作,但代码库并没有显著改善。

如果你是一名软件工程经理,很容易提出广泛、全面的解决方案来解决影响大面积的问题。这种方法在应对代码复杂性时的问题是,问题通常由许多不同的小项目组成,需要个体程序员进行详细的工作。因此,如果你尝试用同样的广泛解决方案处理所有问题,该解决方案将不适合大多数需要处理的情况。你尝试的广泛解决方案实际上会适得其反,软件工程师会感觉他们做了很多工作,但实际上并没有产生可维护、简单的代码库。(这是软件管理中的常见模式,它助长了代码复杂性不可避免且无能为力的错误观念。)

那么,如果你有一个复杂的代码库并希望解决它,作为经理你能做什么呢?诀窍是从个体贡献者那里获取数据,然后与他们合作帮助他们解决问题。大致流程如下:

收集问题清单

要求团队的每个成员写下他们对代码感到沮丧的事项清单。代码复杂性的症状包括对代码的情绪反应、对代码的困惑、感觉修改某部分会破坏代码、优化困难等。因此,你需要回答诸如“系统中是否有部分在修改时让你感到紧张?”或“代码库的某部分是否让你感到沮丧?”等问题。

每个软件工程师应编写自己的清单。我不建议实施某种系统来收集清单——只需让人们以最方便的方式为自己记录问题。给他们几天时间编写清单;他们可能会随着时间的推移想到其他事情。

清单不必只针对自己的代码库,也可以是开发人员必须使用或处理的任何代码。

此时你寻找的是症状,而不是原因。开发人员可以尽可能笼统或具体地列出清单。

召开团队会议

召集团队会议,让每个人带上他们的清单和可以访问代码库的计算机。这种团队会议的理想规模约为六到七人,因此你可能需要将其分解为子团队。

在会议中,你要审查清单,并为每个症状关联一个具体的目录、文件、类、方法或代码块的名称。即使有人说“整个代码库没有单元测试”,你也可以说“告诉我一个具体影响你的例子”,并用其回答来缩小当前最需要编写单元测试的文件范围。你还要确保真正获得问题的描述,可能更像是“因为不知道是否会破坏其他人的模块,所以重构代码库很困难”。那么单元测试可能是解决方案,但你首先需要尽可能缩小问题的具体位置。(确实,几乎所有代码都应进行单元测试,但如果你没有任何单元测试,你需要从一些可行的任务开始。)

总的来说,这里的想法是只有代码才能被修复,因此你必须知道哪段代码是问题所在。可能存在广泛的问题,但该问题可以分解为受影响的特定代码片段的具体问题,逐一解决。

提交问题报告

使用会议中的信息,为每个命名的目录、文件、类等提交一个描述问题(而非解决方案,仅问题!)的缺陷报告。缺陷可以简单如“FrobberFactory难以理解”。

如果在会议期间提出了解决方案,你可以在缺陷中注明,但缺陷本身应主要关注问题。

优先级排序

现在需要确定优先级。首先要看哪些问题对大多数开发人员的影响最严重。那些是高优先级问题。通常,优先级排序的这一部分由对团队或公司开发人员有全局视野的人完成。通常是经理。

也就是说,有时问题的解决顺序与其严重性不直接相关。例如,问题X必须在问题Y之前解决,或者解决问题A会使解决问题B更容易。这意味着问题A和问题X应首先修复,即使它们不如它们所阻碍的问题严重。通常,存在这样的问题链,诀窍是找到堆栈底部的问题。错误处理优先级排序的这一部分是软件设计中最常见和主要的错误之一。它可能看起来是一个小细节,但实际上对于解决复杂性的成功至关重要。在所有情况下,良好软件设计的本质是以正确的顺序采取正确的行动。强迫开发人员不按顺序处理问题(不考虑哪些问题是其他问题的基础)会导致代码复杂性。

优先级排序的这一部分是一项技术任务,通常由团队的技术负责人完成。有时这是经理,但其他时候是高级软件工程师。

有时,直到你在某段代码上进行开发时,你才真正知道应该先处理哪个问题,并发现先修复另一段代码会更容易。尽管如此,如果你能提前确定顺序,最好这样做。但如果你发现为了确定顺序而必须实际找出解决方案,暂时跳过它。

无论你是在开发前还是在开发过程中进行,个体程序员必须意识到在他们被分配的任务之前存在需要处理的基础任务。他们必须有权从当前任务切换到实际阻碍他们的任务。这有一个限制(例如,为了修复一个文件而将整个系统重写为另一种语言不是对时间的良好利用),但通常,“找到堆栈底部的问题”是开发人员在执行此类清理工作时最重要的任务之一。

分配任务

现在你将每个缺陷分配给个体贡献者。这是一个相当标准的管理过程,虽然它肯定涉及一些详细的工作和沟通,但我认为大多数软件工程经理已经熟悉如何操作。

这里的一个棘手之处是,一些缺陷可能涉及不由你的团队维护的代码。在这种情况下,你必须通过组织适当的方式让相应的团队对问题负责。在这里,获得你与其他团队共同的上司经理的支持会有所帮助。

在一些组织中,如果其他团队的问题不太复杂或详细,你的团队也可能自行进行更改。这是一个你可以根据对整体生产力最有利的判断做出的决定。

安排解决时间

既然你已经提交了所有这些缺陷,你必须确定何时处理它们。通常,正确的做法是确保开发人员定期修复你提交的一些代码质量问题,同时进行功能开发。

如果你的团队为某个时间段(如一个季度或六周)制定计划,你应在每个计划中包含一些代码清理工作。最好的方法是让开发人员首先进行会使他们特定功能工作更容易的清理工作,然后进行功能开发。通常这甚至不会减慢他们的功能工作总体进度。(也就是说,如果操作正确,开发人员通常可以在一个季度内完成相同数量的功能工作,即使他们同时进行代码清理,这也证明代码清理已经在提高生产力。)

不要完全停止正常的功能开发而只专注于代码质量。相反,确保持续进行足够的代码质量工作,使代码库的质量总体上始终在提高,而不是随着时间的推移恶化。

如果你做了这些事情,你应该能够很好地走上代码库实际改进的道路。实际上,关于这个过程还有很多需要了解的地方——可能足够写另一整本书。然而,上述内容加上一些常识和经验应足以在你的代码库质量上取得重大改进,甚至可能改善你作为软件工程师或经理的生活。

-Max

附言:如果你确实需要更多帮助,我很乐意到你的公司演讲。请告诉我。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计