在存储库上定期运行代码格式化程序会是个坏主意吗?


68

我正在考虑创建一个cron作业,以检出代码,在其上运行代码格式化程序,如果有任何更改,则提交更改并将其推回。

大多数使用自动格式化程序的项目都将它们放在git钩子中,但是每隔几个小时自动执行一次会减轻每个开发人员安装git钩子的负担。

我仍然鼓励大家编写干净,格式正确的代码,也许我可以让系统在对他们编写的代码进行重新格式化后自动对开发人员执行ping操作,以便他们知道将来要做什么。


105
这里有一个逻辑错误。这种方法不会鼓励人们编写格式正确的代码。而是鼓励人们不要格式化,而要依靠系统!如果您担心代码库是连贯的,那就可以了。您的目标是训练编码人员的代码整洁,这是一个很大的错误。
Kilian Foth,

52
还要考虑这将对诸如怪罪之类的功能产生影响-特别是如果格式化程序进行了大量更改,如果文件中的大多数行都被格式化程序标记为已更改,则您会丢失一些值。
尼尔P,

13
我遇到了自动格式化程序无法正确更新并破坏代码的问题。要记住的事情。
isaacg

22
如果这对您很重要,则当代码格式不正确时,您可能会导致构建失败。这有点苛刻,但是适当的同行评审或多或少会做同样的事情。
Erno

18
如果您的目标是要让人们讨厌您,这是一个好主意。它收效甚微,但肯定会导致无法预料的问题。
TonyK

Answers:


130

听起来不错,但我希望让负责代码更改的人员而非机器人负责。

此外,您要绝对确保这些更改不会破坏任何内容。例如,我们有一个规则,按字母顺序对属性和方法进行排序。这可能会对功能产生影响,例如,影响 WCF合同的WSDL文件中的数据和方法的顺序。


50
同样,它也破坏了VCS。您将无法知道是谁轻易责备了一行,并且如果发生冲突,您的VCS将无法知道该工具的更改只是出于样式,应该每次都丢弃。
Pierre.Sassoulas

2
与切线相关的主题是在IDE中强制执行某些“保存操作”,例如尽可能使字段最终确定。这是一个问题,因为(至少在Java中)许多框架通过反射来设置它们(例如,Spring和Hibernate)。
曼队长

20
@JeffO git blame不仅要发现错误是谁的错误,而且还要找到添加/删除某些内容时的提交,这可能出于多种原因而有用。
Pokechu22年

2
“我们有一个规则,按字母顺序对属性和方法进行排序”男孩,听起来很糟糕!您必须不断在文件中四处
Alexander

1
对于Java来说,它还包括样式检查器(该样式检查器从约定的样式中寻找派生的东西(可能甚至使其成为编译警告))和配置为格式化约定的样式的IDE的组合,这使得检测和修复非常容易。重要的是,在代码实际更改功能时(而不是在机器人重新格式化时),代码会稳定下来(因为缺少更好的词)。
托尔比约恩Ravn的安徒生

72

相反,我会尝试使团队中的每个人都非常容易直接在您的编辑器或IDE中根据您团队的标准将自动代码格式应用于当前源代码文件(或其中的选定部分)。这使您的团队成员可以更好地控制格式化的方式和时间,让他们在以最终形式提交代码之前检查代码,并在格式化完成后而不是在格式化之前进行测试。

如果您的所有或大多数团队成员都使用同一编辑器,这应该不太困难。如果每个人都使用不同的解决方案,那么只要团队支持,您的方法可能是第二好的解决方案。但是,我建议您安装额外的安全措施,例如每晚构建和自动测试,它们每次自动代码修改都会运行。


7
“手头有个格式化程序,可以100%确保它不会破坏任何东西”- 坦白地说,什么时候遇到过一段代码,而100%肯定不会破坏呢?
Zibbobz

2
@Zibbobz:我们用来编辑代码,编译和链接它的任何工具以及VCS都可能有bug,但这仍然不能阻止我们尝试开发可运行的程序;-)但是请看我的编辑。
布朗

我确实赞成编辑-如果仅仅是因为多花点功夫值得一磅的调试费用。;)
Zibbobz

@Zibbobz经常!请注意,百分百确定某件事并不意味着它有100%的机会成为真实。
immibis

@immibis:您可能错过了评论提到几天前我从答案中删除的句子。
布朗

37

这是一个坏主意,不仅是因为它使人们不愿写出体面的代码,而且还因为重新格式化将随着您的VCS中的代码更改而出现(我希望您使用的是这样),从而掩盖了代码开发的历史流程。更糟糕的是,每一个代码格式化操作(实际上是对代码的每次更改)都可能引入错误,无论是手动还是自动的。因此,格式化程序现在可以在代码中引入一些错误,直到可能几个月后,这些错误才需要进行代码审查,单元测试,集成测试等。


10
我认为,如果他正在谈论让机器人从存储库中签入和签出东西,那么VCS是给定的吗?
StarWeaver

11
您会想到@StarWeaver。但是我曾在“代码存储库”是一个受保护的目录的地方工作,该目录只能由以其自己的用户帐户运行的软件访问,除了每周一次以时间戳记下的目录名备份目录之外,根本没有版本控制权。
jwenting

14
那是……我现在要去做噩梦>。>
StarWeaver

7
@StarWeaver为什么您认为我仍然记得14年后的那个环境;)
jwenting

28

我倾向于认为这是个好主意(自动运行代码格式化程序),但这只是我的看法。

我不会定期运行它们,但是如果可能,请在版本控制提交之前运行它们。

使用git,执行此操作的预提交钩子将很有用。在许多使用Makefile构建的C或C ++项目中,我要添加一些indent目标(它们可以适当地运行诸如indent或的代码格式化程序astyle),并希望贡献者能够正常运行make indent。顺便说一句,您甚至可以添加一些make规则来确保已安装git钩子(或安装它们)。

但实际上,这不仅仅是技术问题而是社会问题您希望您的团队提交干净且格式正确的代码,这是项目的社会规则。(并非总是对每个社会问题都有技术答案)。

版本控制主要是一些工具,可以帮助人类开发人员之间进行交流(包括几个月后的您自己)。您的软件不需要VC或格式,但是您的团队需要。

顺便说一句,不同的社区和不同的编程语言对代码格式有不同的看法。例如,Go仅具有一种代码格式化样式,但是C或C ++有很多样式。


是的,但这意味着每个开发人员都需要安装提交挂钩。
bigblind

17
是的,但这是一个社会规则,您需要其中几个。您找不到所有社会问题的技术解决方案。您需要说服人们。此外,每个开发人员都需要安装一些编译器以及版本控制系统本身。
巴西尔·斯塔林凯维奇

是的,所以您说的是必须安装git hook的社会规则要比自动化系统好吗?(严重的问题,并不意味着要夸夸其谈,语气很难在互联网上传达:))
bigblind

15
是的,我是说。
巴西尔·斯塔林凯维奇

17

我认为这是个坏主意。已经有许多答案都表明,它很难确定谁真正添加了一行,从而弄脏了历史,并鼓励人们仅提交任何内容,而格式机器人将对其进行处理。

更好的方法是将格式检查器合并到构建工具中。(在Java中是Checkstyle)然后,如果构建通过(包括格式化),则仅允许人们将其分支合并到主分支。

如果您允许人们直接提交到主分支(例如在Subversion中),那么您仍然需要确保每个人都有遵守仅提交格式化代码的准则(或者让服务器仅在运行某些检查后才接受提交) )。


2
但是请确保样式检查器是理智的,并且不会执行与任何公认的(和可接受的)做法相反的怪异事物(是的,我已经看到了)。然后,当样式检查器引发(新)错误时,还可以让构建服务器使自动构建失败。
jwenting

2
我已经看到许多情况下,自动格式化会产生无法读取的代码。尤其是对于许多封闭的括号(明智的做法是将其中一些放在单独的行中,但是机器人不在乎)。另一个示例是自动拆分长Java字符串(它们很长,因为它们包含SQL查询,但机械手不知道。)。
18446744073709551615 '17

@ 18446744073709551615我不建议自动格式化,我建议自动检查。您的规则可以允许这些事情。
上尉曼

16

总的来说,我认为这是一个坏主意。从原则上讲,这是一个有效的想法,但实际上可能会出现问题。让代码格式化程序破坏您的代码是一种真实的可能性,只需运行一次格式化即可使您的开发人员以(可能是合理的)敌意进行响应(例如,“您糟糕的代码格式化程序破坏了构建,请立即将其关闭)。

与@BasileStarynkevitch的建议一样,我们使用git服务器端后接收钩子发送有关代码样式的“建议电子邮件”。

如果我推送包含样式违规的提交,则git origin服务器将向我发送一封电子邮件,通知我我违反了样式准则,并建议我修复代码。但是,它不强制执行此操作,因为可能有正当理由破坏家庭风格(例如,超出字符串长度限制的长字符串)。

如果这是损害代码库的系统性问题,那么可能是时候开始在代码审查中提出代码风格问题了。不良的代码风格可能掩盖错误,并使代码更难阅读,因此这可能是有效的代码审查问题。

为了增加事物的“社会问题”方面,值得鼓励人们在发现它们时修复外观和样式缺陷。我们有一个标准的提交消息“化妆品”。其他开发人员知道的代码样式修复不包含重大更改。

正如@DocBrown所说,另一种选择是在IDE中强制执行代码样式。我们在Visual Studio中使用CodeMaid来纠正许多常见的样式错误。它会在保存代码文件时运行,这意味着样式错误的代码甚至都不应将其放入存储库中……从理论上讲:-)。


我赞成这一点,因为它直接针对双方(希望获得更好的代码+避免破坏版本的安全性)。 但是,在代码库的状态非常好之后,我认为“坏主意”对于自动进行将来的更改来说是一个有力的措辞。
donjuedo

10

是的,我认为这是一个坏主意。别误会我的意思,这样做的理由听起来不错,但结果仍然很可怕。

拉动跟踪的分支时,您将发生合并冲突,至少我担心会发生这种情况,但是我可能是错的。

我现在不想在工作中对其进行测试,但是您应该自己尝试一下。

实际上,您只需签出最近的提交即可。新建一个分支,提交一些琐碎的东西,挑选樱桃或合并,而无需自动提交。

然后运行您的脚本,拉出,如果结果是可怕的合并混乱,那么您绝对应该在白天不要这样做。

相反,您可以将其放入每晚或每周一次的构建中。

但是,甚至每晚都可能是个坏主意。

您可以每周运行一次,当您确定不会发生合并冲突时,因为一切都在星期一完成。

否则在假日季节每年运行1-2次,这样就不会发生合并冲突。

但是解决方案可能取决于您对代码样式的重视程度。

我认为制作一个自动创建git存储库并设置项目挂钩的安装脚本会更好。

或者,您可以将挂钩安装脚本包含在项目中开发人员的文件夹中,然后将其检入git本身。


7

我未曾提及的是,有时出于合理的理由不按照一套规则格式化某些内容。有时,违反99%的时间有意义的给定准则可以提高代码的清晰度。人类需要拨打电话。在那些情况下,自动代码格式化将使事情变得不那么可读。


完全同意。例如,将变量标识符对齐在左侧,将所有等号放在同一列中,并将所有值对齐在等号右边。在这种情况下,格式化程序会通过将每个制表符/空格减少到单个空格来降低可读性。当然,可以编写格式化程序规则来防止这种情况,但是您需要指定一个开发人员来编写代码格式化程序。似乎到处都是个坏主意。采用更好的内部约定,并在代码审查期间执行。
ThisClark

7

这是一个可怕的主意。

如果我的一位开发人员同事对源文件进行了无谓的更改,则它不会通过代码审查。这只会使每个人的生活更加艰难。更改需要更改的代码,仅此而已。无意义的更改会导致合并冲突,从而可能导致错误,并且只会造成无意义的工作。

如果您想定期执行此操作,那就太糟糕了。

还有一个问题是代码格式化程序会进行哪些更改。我在编辑器中使用了自动格式化,它工作得相当好,并且当自动格式化不够完美时,我可以进行改进。如果使用超出此范围的代码格式化程序,则不会改进代码,而会使情况变得更糟。

然后是社会问题。有些人想强迫所有人使用他们的代码样式,还有一些更灵活的人。想要将样式强加给其他人的“ grammer-nazi”(故意拼写)类型的开发人员可能会建议这样的事情。会产生强烈的反响,并希望灵活,通常随和的开发人员放下脚步。


4

您没有提及要使用的VCS,但取决于另一个选择是拥有服务器端挂钩。像git这样的VCS支持这一点。您可以安装一个服务器端挂钩,该服务器挂钩在要推送的版本上运行格式化程序,然后将格式化的文件与要推送的版本进行比较。如果它们不同,则开发人员将无法使用正确的格式,并且服务器可能会拒绝推送。这将迫使您的开发人员仅按期望的格式推送代码,从而鼓励他们从一开始就编写干净的代码,这将使负责测试正确格式的代码的开发人员从繁琐的工作中解放出来,而不必手动安装客户端钩。


例如,这就是Go的工作,除了使用Mercurial。推入下面不变的东西go fmt会自动被拒绝。
约尔格W¯¯米塔格

1

这是在更干净的代码格式与更精确且更易于理解的git历史之间的权衡。取决于项目的性质以及您多久潜入git历史记录或指责以了解正在发生的事情。如果您正在研究新事物,而不必保持向后兼容性,那么历史通常就不会发挥重要作用。


1

这个想法类似于其他答案,但是我无法评论我的建议。

一种选择是为提交函数设置别名(或挂钩或其他内容),该别名在提交之前在要提交的代码上运行代码格式化程序。

它可能有2个(或更多)结果:

1)向用户显示建议的更改,并征求他们的同意以应用并提交更改。

2)忽略建议的更改并提交原始代码。

您还可以为这些选项增加更多的灵活性,例如编辑选项1中建议的更改的能力。另一个想法(取决于您要推动这些编码标准的努力程度)是让系统在以下情况下向您发送某种报告:选择了选项2。

这可能是自动检查所有所需代码的良好平衡,同时仍然允许开发人员灵活地适应他们的需求。它还允许选择不“自动拒绝”具有格式差异的代码,如其他答案中所述。通过“我已审查并批准自动格式更正;提交”选项,它仍然对每个开发人员的工作保持个人责任,并且不会与VCS混淆。


0

我不会在存储库中执行此操作,但是如果该工具支持,则会在保存时执行。Eclipse是其中之一,此外,我还将进行代码清理,包括排序。

令人高兴的是,它是项目的一部分,因此每个开发人员都会为他们的项目得到它。

另外,合并将大大简化,因为事情不会发生变化。

代码审查将防止任何错误的审查。

我会做的另一个地方是将它作为构建的一部分。以我为例,Maven构建将重新格式化XML并清理pom文件并重新格式化代码。

这样,当开发人员准备推送时,所有内容都将根据其拉取请求进行清理。

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.