编写可维护代码(与语言无关)最重要的因素是什么?
37 回答
写出来给别人看。这意味着好名字、好评论和简单陈述的结合。
曾几何时,记忆稀缺,循环时间很慢。鼓励程序员编写复杂的单行代码来做很多事情。今天的内存很丰富,循环时间很快。您应该编写 5 行人们可以遵循的简单代码,而不是他们无法理解的一行。
好的评论不必很长,但它们必须是有帮助的。
还要保持一致。不要更改代码中的样式。例如,不要将命名样式从一个部分更改为下一个部分。
关注点分离(每个方法都做一件事)——这会停止 Spaghetti 代码。
编辑:(回应 Ash 的评论)可维护性的关键是能够快速弄清楚代码在做什么以及如何进行更改以完成任务。
将代码分离出来,以便每个任务都由专用于它的方法处理,这很容易。
例如,如果我想在机器人的软件上更改肘部弯曲的方式,使用名为 BendElbow 的方法可以轻松地进行更改。
自动化单元测试。
如果你已经用自动化测试告诉你什么时候破坏了现有的功能,你可以通过重构慢慢改变代码的设计。自动化测试降低了更改代码的风险。
好抽象
单元测试放下手。如果您从一开始就对代码进行单元测试,那么您将拥有一个测试套件,您可以在进行更改时运行该套件来验证代码的有效性。
此外,当您使用单元测试编写代码时,这些方法往往更小,因为它们更容易测试。同样,它应该鼓励您将方法用于单个任务 - 再次因为这样更容易测试。
良好的前期设计。没有什么可以挽救一个糟糕的设计。
在发布后的一两年内为您刚刚编写的软件提供一级或二级支持。
相信我,我自己也去过那里。我可能不得不在几年内维护或增强自己的代码的“恐惧”始终是提高可维护性的巨大动力。
编写代码的倾向是认为计算机是您的受众。
严格来说,这是真的,因为代码确实必须工作。但是,如果您在编写时考虑到您的人类受众,那么这种心态有助于生成更具可读性的代码。
如果您担心这会产生缓慢的代码,请记住大多数程序几乎所有时间都在非常小的代码部分中。开始编写可读性,然后使用分析器确定要优化的正确部分。
好的方法名
Read Code Complete- it covers everything about this from variable naming right through to the really big stuff and it is all necessary. There is no one thing.
My approach currently boils down to writing code to do the job that needs to be done ( not for every future job the code may need potentially to do ) using informative variable names and minimal variable scope and trying to make sure that my code needs as little supplementary documentation as possible. Sometimes this makes my variable and method names a little more verbose than they used to be ( my debugging output is very compreshensive when I use that ) but they are much easier to understand.
Maintainability is also generally an outcome of solid practice in other respects - if you are writing your code in a nice DRY way then problems are easier to find, if you've got a strong set of tests then you can see if maintenance changes are going to break anything.
Ultimately it's a question of trying to be thoughtful and writing for the future- code is only written once, after that it's all maintenance...
不要做任何这些事情!不过感谢 Roedy Green 的笑声。
没有“单一最重要的因素”,它是几个因素的组合,如上所述。
现在,这些规则中的大多数可以浓缩为:“编写代码以供以后阅读”。
或者套用一个有趣但很好的建议:“编写你的代码,就好像它必须由一个知道你住在哪里的杀人狂人维护一样。”......
当你做出假设时记录下假设——两天后你会认为这些假设是理所当然的,但是下一个维护你的代码的人不一定会做出同样的假设,并且会想知道你为什么做了你所做的……
为人编码——计算机会做任何你告诉它的事情;代码,以便人们可以理解您的代码 - 谁知道它可能是您 6 个月后!
持续重构
我不认为你可以专注于一个单一的因素。如果有,我认为它必须是良好的判断力。如果开发人员在设计阶段使用了错误的判断,即使是有据可查、易于阅读的代码也可能难以维护。无论文档和单元测试有多好,生产应用程序的糟糕设计几乎是不可能修复的。
您还可以查看诸如 The Guide to Unmaintainable Code 之类的内容,了解不该做什么的想法。内容丰富且有趣!
http://mindprod.com/jgloss/unmain.html
我实际上曾在那些对其中提到的一些事情“标准化”的公司工作过。你会认为大部分内容只是常识,但你可能会感到惊讶。
我想说最重要的因素是干燥。glenatron 在他的回答中已经提到了其他因素,但我认为这是最重要的因素。
编程就是性能;你永远不应该忘记你的听众是谁。“就像最终维护你的代码的人是一个知道你住在哪里的暴力精神病患者一样编写代码。”
Plenty of whitespace. - High density code is hard to comprehend. If you have more than 6 lines wihtout a blank line, then that group is probably not a cohesive thought/idea/operation.
Good variable names - explanatory, but succinct. Huge variable names are as bad as tiny ones.
在我看来,编写可维护代码的基本规则是您的代码应该非常容易理解。这并不像听起来那么容易,您必须使用此处提到的所有其他技术来做到这一点。它需要一定程度的同理心,因为您必须了解其他开发人员如何看待您的代码,以及它与您看待它的方式有何不同。掌握这一点的一个好方法是回头看看你几年前写的一些代码。
现在,我想从理论上讲,编写代码是可能的,这些代码非常容易理解并准确地执行其预期的任务,但也很难以任何方式修改。不过,我从未见过这样的代码。
好评论。
一致性。
毫无疑问,编写旨在被其他人阅读的代码。这包括避免打高尔夫球、神秘语法和有意义的变量名称。如果代码足够干净,您可以完全避免编写任何注释,IMO。\
[选择一种内置 OO 的语言而不是附加的语言也有帮助]
已经很久了,但我有一个答案:不要过度评论。这可能听起来很傻,但是太多解释简单事情的注释会使代码变得混乱,因为所有的东西都出来了。好的评论可以创造奇迹,但毫无意义的评论恰恰相反。
small, well defined functions and classes.
It's pretty easy to get used to other people's various coding conventions but if everything is in one giant class or function, my head explodes.
当人们随着代码的增长而修剪和塑造代码时,我更喜欢它。很多时候,你会发现一个原始的体面建筑的脊椎,上面挂着一大堆杂乱无章的东西。
对我来说编写可测试代码(结帐谷歌测试博客)是更好的可维护代码
我已经投票赞成马特的回答“良好的抽象”,但我想添加一些东西。
记录这一切都是为了解释事情。我完全赞成 Doxygen 和其他自动文档工具,但 API 中的粗略函数列表总比没有好。
如果您想让您的代码可维护,请将您的解决方案描述为适当的抽象级别,并将该级别细化到代码,以便它的作用显而易见。
找个好导师。这个人不一定是比你更好的编码人员,但是他们应该能够建议其他正确编写代码的策略。一个好的导师会建议许多以前对该主题给出的答案。它们可以是第二双眼睛,让您知道自己的缺点在哪里,同时保持鼓励、乐观的语气。他们也会像你一样灵活并不断磨练他们的技能。这样,当下一个大范式出现时,您将能够更好地将谷壳与小麦分开。当面向对象编程和源代码控制被下一件大事取代时,这将是无价的(我很难想象我知道。)
拥有良好的文档。这包括自我记录的代码(分区、描述性命名和清晰)、良好的注释、精确到(最近的)最终版本代码的详细设计文档,以及源代码管理中的描述性变更说明。
如果你要求两个,第二个肯定是单元测试。两者之间是一个艰难的选择。
好的注释可以使最糟糕的意大利面条代码更容易维护 10 倍。
一贯适用的强大、明智的约定。诸如关于从何处开始索引的约定,将内容保留在什么结束状态之类的约定。
这使得代码更容易理解,因为您的所有代码都将以更简单的方式运行。
这至少是我的重要提示之一。
好评论。好的注释通过说明代码的预期目的来帮助抽象,不好的注释只是重申代码在做什么。注释实际上可以以精心设计和命名的单元测试的形式出现。
一致的编码风格。方法和变量命名约定、注释的样式和格式,甚至模块/文件命名。
我会和其他一些人一起去,抽象。当您了解一些软件模式时,它也会有所帮助,GOF 是学习这类东西的好地方。
我猜想编写可维护的代码超越了代码。我相信最好先了解需求是什么(并以某种方式记录下来,包括功能性和非功能性的),然后让新员工了解如何将其转化为代码。
如果有人知道为什么代码会变成这样,那么让它变得更好和/或扩展它会变得更容易。
对于更多技术性的东西(例如算法),请对其进行抽象解释(目标、原则),然后注释代码和/或模式实现的关键部分。
我还要做的一件事是在我的应用程序中创建迷你实验室、工具箱和代码模板,以便人们知道做一件事或扩展另一件事所需的“标准”代码是什么(导致一些复制/粘贴,但有助于生成更多更好)。
纯函数使推理代码变得更加容易。确保正确传达副作用。(即,当您不返回“结果”时,通常会产生副作用。即无效函数。)
文档。