我是否应该仅遵循工作场所中已建立的约定而遵循不良编码风格?


102

我已经工作了大约一年了。我主要在GUI界面中工作,该界面使用C后端的方法,但是除了返回值外,我通常不必处理它们。考虑到我们的局限性,我们的GUI结构相当合理。

我的任务是向程序的命令行部分添加功能。这些功能大多数都长达300行,难以使用。我正在尝试收集其中的一些信息以获取特定的警报信息,但在保持井井有条的过程中遇到了麻烦。我知道我要通过一个长函数来使测试变得更加复杂。

我应该按照现有功能的样式将所有功能都保留在一个巨大的功能中,还是应该将警报封装在它们自己的功能中?

我不确定是否适合违反当前的编码约定,或者我是否应该硬着头皮让代码编写自己的代码更加混乱。

总而言之,我正在比较

showAlarms(){
    // tons of code
}

反对

showAlarms(){
   alarm1();
   alarm2();
   return;
}

alarm1(){
    ...
    printf(...);
    return;
}

编辑:谢谢大家的建议,我决定我将设计我的分解代码,然后询问他们想要什么,如果他们想要全部融合在一起,我可以从分解的代码中切下来,然后将其重新变成1大功能。即使他们希望所有代码都在一个定义中,这也应该允许我编写它并更轻松地对其进行测试。

更新:他们最终对分解式代码感到满意,并且有一个以上的人感谢我树立了这一先例。


117
您所工作的公司是否认为您的职能应该长达300行非常令人怀疑,因为“这就是我们一直这样做的方式”。那不是“编码样式约定”;这只是坏风格。
罗伯特·哈维

64
您应该与团队中的其他成员讨论这种事情,以弄清您看到的惯例是他们认为对每个人都重要的惯例,以及某人仅做过一次而您没有做过的事情需要模仿。毫无疑问,两者都有。
Servy

17
@beginnerBinx取决于您的表达方式。不要这样说:“ X做的事情确实很愚蠢,我是否也必须做那个愚蠢的事情。” 但是,就像“我注意到X正在做这件事,是否有一个特定的原因说明它这样做的原因;如果我在编写Y时没有做同样的事情会不会有问题呢?” 然后,这是他们决定是否破坏旧代码或解释为什么必须这样做的决定(无论是勉强还是热情)。
Servy

11
好的或坏的风格经常被争论并且很少被商定。大学的教学是功能应该简短一些,但是如果这模糊了含义,那就不要这样做。测试应该清晰明了,而不是无意识地遵循一系列规则。
quick_now

9
互联网上的随机人不介意阅读您的队友,因此,您在此处获得的所有答案都只是人们的个人喜好。您应该与您的团队交谈。长功能是故意设计的原则吗?他们是否希望您继续使用长函数样式,还是希望您写出您认为最干净的东西?
JacquesB 2013年

Answers:


102

这确实是在您和您的队友之间。没有其他人可以告诉您正确的答案。但是,如果我不敢在这两行之间读一读,那么您称这种样式为“不良”的事实可以提供一些信息,表明最好慢慢来。实际上,很少有编码样式是“不好的”。我自己有些东西我不会用,但是它们总是带有韵律或理由。在我看来,这表明故事的内容比您到目前为止所看到的更多。问周围将是一个非常明智的选择。可能有人知道您不知道的东西。

我个人是在首次尝试实时执行关键任务编码时遇到这个问题的。我看到了这样的代码:

lockMutex(&mutex);
int rval;
if (...)
{
    ...
    rval = foo();
}
else
{
    ...
    rval = bar();
}
unlockMutex(&mutex);
return rval;

作为我曾经是一位聪明又有光泽的OO C ++开发人员,我立即通过手动锁定和解锁互斥锁而不是使用RAII告知他们存在的错误风险。我坚持认为这样做更好:

MutexLocker lock(mutex);
if (...)
{
    ...
    return foo();
}
else
{
    ...
    return bar();
}

更简单,更安全,对吧?当编译器可以为您做时,为什么要求开发人员记住在所有控制流路径上解锁其互斥锁!

好吧,我后来发现的是程序上的原因。我们必须确认,是的,软件确实可以正常工作,并且我们可以使用的工具数量有限。我的方法在不同的环境中可能会更好,但是在我正在使用的环境中,我的方法很容易将验证算法所需的工作量增加了十倍,因为我只是将C ++ RAII概念引入了一段代码中所遵循的标准实际上更适合C风格的思考。

因此,对我来说,看起来很糟糕,非常危险的编码风格实际上是经过深思熟虑的,而我的“好的”解决方案实际上是危险的解决方案,它将在以后引起问题。

所以问一下。肯定会有一位高级开发人员可以与您合作,以了解他们为什么这样做。或者,有一位高级开发人员可以帮助您了解代码这一部分中重构的成本和收益。无论哪种方式,请四处询问!


60
可以说互斥锁示例中最危险的部分是显然缺少代码注释,无法解释为什么不能使用RAII。当然,如果此显式锁定/解锁遍及整个代码库,则为每个实例添加注释可能很麻烦。在那种情况下,也许应该写一份入门文档,要求新开发人员熟悉。
开尔文

10
当然,与年长者交谈总是很好,并且重构必须谨慎(并经过测试)。当然,并发/互斥体本身就是一种特殊的野兽。但是,当看到功能大于300行的功能时,我不会花太多时间寻找这些功能太大的“隐藏技术原因”。函数变得太冗长的原因始终是相同的,并且不是技术性的。
布朗

8
@DocBrown仅仅因为它们不是技术性的并不意味着它们不是原因。对于开发人员而言,重要的是要记住它们是大型计算机的一部分。(我无法数出必须重新学习该课程的次数)
Cort Ammon

4
@DocBrown无论哪种方式,应该与高级开发人员进行交流。我之所以选择该示例,是因为它很容易找到无数参数来说明为什么愚蠢的代码是愚蠢的。找出为什么看起来愚蠢的代码实际上并不愚蠢的论据变得更加困难。
Cort Ammon

3
@DocBrown从您的评论和答案中,我想我可以说出我们的观点的不同之处是,您是基于您所提供的证据,从代码已经是“不好的”这一假设开始的,而我希望采取探究代码是否“错误”的路径。
Cort Ammon

84

老实说,您认为拥有300行难于使用的功能仅仅是样式问题吗?因此,遵循一致的错误示例可以使整个程序保持更好的状态,因为它具有一致性吗?我想您不这么认为,否则您不会在这里问这个问题。

我的猜测是这些功能之所以这么长,是因为在我们的业务中,有许多平庸的程序员只是将功能堆叠在功能之上,而不关心可读性,代码质量,正确的命名,单元测试,重构,而且他们从未学会创建正确的抽象。您必须自己决定是要跟随一群人,还是要成为一个更好的程序员。

附录,由于注释:“ 300行”和“难于使用”是恕我直言强烈表示错误代码。以我的经验,很可能没有某种“隐藏的技术原因”,导致这种代码无法以更具可读性的方式实现,这与Cort Ammon的答案示例相当。但是,我同意Cort的观点,您应该与团队负责人讨论这个问题-不是找到无法更改代码或这种“样式”的晦涩原因,而是要找到如何安全地重构代码而不破坏事物的原因。 。


127
在紧迫的期限内,即使是有能力的程序员也会犯下这些罪行。
gardenhead

13
@gardenhead,我可以理解不重构300行函数可以节省时间,但是编写300行函数无法节省时间。
Dangph '16

39
@gardenhead:当我因为需要紧急帮助而去找外科医生时,我仍然希望他在开始对我表演之前先花些时间洗手。这是很多人在我们的业务中必须学习的才能获得真正的能力:始终将代码保持在比以前更好的状态,这也将提高保留截止日期的能力。300行功能通常由无关紧要的人每天增加,他们将始终以“截止日期”为借口。
布朗

17
@Dangph可以在您仅向函数添加5行而不是对其进行重构时节省时间。当初始函数很长(超过30行)并且下一个程序员认为“这不是我的代码,我不会重构不破坏它,只需在这里和那里添加几行”时,这些通常会增加。
Džuris

7
据我了解,@ Juris的问题是关于创建新功能,而不是重构现有功能。如果您要编写新功能,则不能通过将其变成单个怪物功能来节省时间。
Dangph '16

42

没有。

在《实用程序员》一书中,作者谈到了“ 破窗理论”

这个理论状态:

考虑一栋破窗户的建筑物。如果不修理窗户,则有可能破坏者破坏更多窗户。最终,他们甚至可能闯入建筑物,如果空置,可能会成为棚户区或小火。

或考虑人行道。一些垃圾堆积。不久,更多的垃圾堆积。最终,人们甚至开始将垃圾袋从那里的外卖餐厅丢下,甚至闯进汽车。

在这本书中,作者在这一理论和代码之间写了一条平行线。找到这样的代码后,您将停止并向自己问同样的问题。

答案是:不会。

一旦您离开了这个破碎的窗口(在我们的例子中是糟糕的代码),这将产生使每个人都将破碎的窗口抛在后面的效果。

有一天,代码将崩溃。

清洁代码清洁编码器的副本提供给所有人。

而且,当您在学习本主题时,TDD副本也是一个不错的选择。


6
如果代码库是一个只有破窗的温室,该怎么办?
艾伦·舒特科

8
@AlanShutko然后确保您的简历是最新的?找到一个不同的雇主现在
大卫·蒙哥马利

12
代码很少“崩溃”。添加新功能变得越来越困难,花费越来越多的时间,并且清理代码的估计将增加-这意味着获取任何时间预算以进行必要清理的难度越来越大。
布朗

8
哇,“破窗”理论似乎是个任意类推。
Samthere '16

4
TDD与之无关。无论您要进行的业务/域/测试/虚无驱动程序设计,都不会改变任何事情,请遵循干净代码的基础。抱歉,看到“ TDD”到处都引人注目,真是太累了
Walfrat

25

是的,去吧。结构!=样式

您在说的是结构,而不是风格。风格指南没有(通常)规定结构,因为通常选择结构是因为它适合于特定问题,而不是适合组织。

小心

请确保您不会在可能未发生的其他方面造成负面影响。例如,

  • 确保您没有使差异或代码合并复杂化,因为您消除了与现有代码的任何相似之处。
  • 确保异常流正确冒泡,并且堆栈痕迹不会被一大堆难以理解的废话污染。
  • 确保您不会意外暴露会直接引发问题的公共入口点(请勿将其放置在地图中和/或不导出它们)。
  • 不要弄乱全局名称空间,例如,如果所有较小的函数都需要某种先前在函数局部范围内声明的全局上下文。
  • 确保查看所有日志,并问自己是否在支持团队中,如果您看到的代码生成的日志与您从未触摸过的任何代码的日志交织在一起,是否会造成混淆。
  • 确保您确实遵守现有样式,例如,即使他们使用的是老式的匈牙利符号,并且会使您流血,也要与通用代码库保持一致。与阅读匈牙利符号相比,唯一更痛苦的事情是阅读代码,该代码使用十几种不同类型的符号,具体取决于谁编写了什么。

要温柔

请记住,您是团队的一员,尽管良好的代码很重要,但是团队成员保持假期时编写的内容也很重要。尝试坚持对习惯旧样式的人有意义的流程。仅仅因为您是会议室中最聪明的人,并不意味着您应该在每个人的头上讲话!


“尝试坚持对习惯旧样式的人有意义的流程。” -那么,您的编程建议是否像以前的无能小丑一样?添加300行功能将使其变得不那么容易。
BЈовић

11
我没有说要坚持类似的流程。我说要坚持他们会理解的流程。
John Wu

2
好建议。当我在此答案中将单个命令重构为5个函数时我通过预先计算最初仅是有条件地计算的逻辑表达式内的值来巧妙地更改了语义。评论者虽然抓住了它;-)。认真的建议是彻底检查和测试。每次更改都会引入错误,这可能是没人犯错误的主要原因。
彼得·施耐德

6

我不认为这是一种代码约定。我将其视为不了解如何编写易于理解的可维护代码的人。我会按照您的建议将您的代码分解为不同的功能,并对您的团队进行此操作的好处进行教育,同时尝试理解为什么他们认为300行功能可以接受。我会很感兴趣听到他们的推理。


1
没有理由,这只是我们的政策。

5

答案在代码审查中。

真正的问题是,如果您提交完善的代码,您将成为唯一愿意使用它的人吗?

我像这里的大多数人一样,相信300个行功能是可恶的。但是,将Windex带到垃圾填埋场并不会带来多大好处。问题不在于代码,而在于编码员。

仅仅正确是不够的。您需要向这种风格的人推销。至少在阅读时。如果您不这样做,您最终会像这个可怜的家伙一样:被开除,因为您的技能远远超出了您的同事

从小开始。四处询问,看看是否还有其他人喜欢较小的功能。更好地窥探一下代码库,看看是否可以找出谁编写最小的代码(您可能会发现最丑的代码是最早的代码,而当前的编码人员正在编写更好的代码)。与他们讨论此事,看看您是否有盟友。询问他们是否认识其他有相同想法的人。询问他们是否认识到讨厌小功能的人。

召集这个小组,讨论进行更改。向他们展示您想要编写的代码类型。确保他们可以阅读。认真对待任何异议。进行更改。批准您的代码。您现在可以在身后举行会议。这些中的更多一些,您可以生成一个一页纸的文档,该文档明确接受您引入的新样式。

会议是令人惊讶的强大功能。他们可以产生影响力。消极影响力是您用来与反对这一运动的人作斗争的方式。这就是这一点。运动。您正在争取改善现状的权利。人们害怕改变。您将需要甜言蜜语,哄骗和刺耳。但是如果运气好的话,您会变成正确的被接受。


5
如果花费大量的社交时间和多次会议才能说服开发人员300行方法太长,那么我认为谈话不会有所帮助。上面方法的问题是,如果您请求编写好的代码的权限,那您就处于防御状态。但是,如果您只是编写良好的代码并花时间重构现有代码,那么任何反对的人都在防御性地解释为什么300行方法是好的,并花时间将其放回去是合理的。
布兰登

3
我可以告诉你,如果邀请我参加一系列会议,讨论每个功能限制的代码行,我将找到逃避此类会议的方法。没有正确的数字,您将永远不会让人同意。有时,需要向人们展示更好的方法。
布兰登

有时,拆分一个巨大的功能(更好地命名并添加注释和文档,据我所知是在进行更改之前先进行必要的第一步。)
JDługosz16

@Brandon您可能不是想这样听起来,但我听到的是您是对的,其他所有人都可以解决。只要您的代码有效,团队其他成员是否不理解它就无关紧要。当然,不值得您花时间去教他们任何东西。您很高兴看到他们以自己的方式编写代码时继续创建300行功能。
candied_orange

1
@CandiedOrange我当然不是要反对球队。我的意思是,通过在行动中看到一些主题可以最好地学习它们,但是试图让一个团队就风格进行民主决策将不会有成效。我已经看到一致性被用作编写不可读代码的借口。结果?更多不可读的代码。我可以召开一系列会议来讨论它,或者我可以解决它,然后人们展示结果。
布兰登

3

有时,您必须顺其自然。

就像您说的那样,您受命在现有的工作代码库中实现功能。

不管混乱如何,我都知道很容易清理它。但是在商业世界中,您并非总是有机会重构代码。

我想说的是做您被要求做的事情并继续前进。

如果您认为值得重构或重写,则需要将其提出来与团队讨论。


2
如果您在每一个小的重构过程中都请求许可,那么您将永远拥有无法维护的代码,这对企业来说是危险的。经理只考虑变更的成本,而很少考虑变更的成本。
布兰登

5
已要求OP编写不修改数百行代码的函数
meda

2
完全是@meda!我的处境大致相同。我正在为公司的Intranet开发新模块,并且发现了所谓的“多年无法修复的疏忽”,服务器软件和库自2006年以来就没有进行过任何更新。 ,但是由于这些限制,我花了更长的时间编写代码。(想象一下MySQl 5.2,MySQL 5.0)。我无法更新任何内容,因为由于不推荐使用的代码,现有的代码可能无法在较新的版本上运行。
roetnig

3
“如果没有破裂,请不要修复它。” 我有一辆20岁的旧车,漏了一点油。值得花钱吗?不可靠吗?是。

3

在声明这些做法不好之前,我将首先迈出一步,以了解采用大方法和其他做法可能会导致不好的原因。

然后,您需要确保测试覆盖率非常高或确实很高(就可以在不进行重大重构的情况下进行)。如果不是这样,即使您没有编写代码,我也将努力使覆盖率达到很高。这有助于建立融洽的关系,而您的新团队将更加重视您。

一旦涵盖了这些基础,他们中没有一个人会挑战您。作为奖励项目,进行一些微基准测试,这确实会增加您的案子。

通常,您的语言表达方式对改变代码文化大有帮助。以身作则。甚至更好的是,等待一段您可以编写的代码-对它进行重构和单元测试,中提琴-您将被听到。


我没有重构当前代码,我只是在编写一个新函数,不确定是否应该按照“惯例”并将其编码为300多行代码,或者像我通常那样将其分解为逻辑块,但是在代码库的这一部分中没有完成。
贾斯汀

1
他们有规则来确保您在300多个行中编写新方法吗?如果没有,我会用正确的方式写出来。但是我绝对会尽力确保我测试它们,包括分支。我也经历过类似的经历,通常您会赢得他们。技巧是随着时间的流逝并建立融洽的关系。
skipy

3

这类问题基本上是“ 请介意我的队友 ”。互联网上的随机人无法做到这一点,因此您获得的所有答案都只是人们对编码风格的个人看法。共识是较短的方法是更可取的,但是您自己似乎已经这样认为,因此无需重申。

因此,当前的代码库似乎使用了与您喜欢的编码样式不同的编码样式。你该怎么办?首先,您需要弄清楚:

  1. 这是您当前团队支持的故意设计决策吗?
  2. 他们是否要您遵循这种风格?

只有一种找出方法。询问

具有长功能可能有多种原因。这可能是因为该团队认为长功能优于多个短功能。也可能是因为它是遗留代码,并且团队更喜欢新代码遵循更简洁的设计。因此,如果您不与团队交谈并了解他们的推理,那么任何一种选择都可能给您带来开发人员麻烦。


1
我完全同意并补充说:“您可能会因为不遵循别人的工作而被炒鱿鱼或遇到其他麻烦?” 那么答案是肯定的!跟踪公司的每件坏事,都需要您去处理。
罗布

1

有不同级别的“样式”。

在一个级别上,通常是编码约定的一部分,这意味着在哪里放置空格,空白行,方括号以及如何命名(混合大小写,下划线等)。

在另一个层次上是编程模型,有时诸如避免静态操作或在抽象类上使用接口之类的方法,如何公开依赖项,甚至可能避免某些深奥的语言功能。

然后是该项目正在使用的库和框架。

有时,功能大小会有最大限制。但是很少有最低限额!因此,您应该找出其中哪些功能被视为重要,并应予以尊重。

您需要确定团队是否不利于重构现有代码,这应该独立于可能的情况下添加新代码来完成。

但是,即使他们不想重构现有代码,也可以为添加的新代码引入一些抽象层,这意味着随着时间的流逝,您可以开发更好的代码库,也可以将旧代码迁移为维护它的要求。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.