在临时解决方法的方法名称中包含错误编号是否被认为是不好的做法?


27

我的高级同事阻止我进行代码审查,因为他希望我将方法命名为“ PerformSqlClient216147Workaround”,因为这是某些缺陷的解决方法。现在,我的方法名称建议类似于PerformRightExpressionCast,它倾向于描述该方法的实际作用。他的论点是这样的:“这种方法仅在这种情况下用作解决方法,而在其他地方则没有。”

在临时解决方法的方法名称中包含错误号是否被视为不良做法?


只是澄清一下:缺陷###位于一个名为SqlClient的外部组件中,它于2008年提交,很可能不会很快得到修复,这超出了我们的能力,因此该方法是“解决问题”
Bojan

2
它的读起来仍然很,因此我将重点重新命名为您要问的问题的核心。我觉得这是一个公平的问题。诸如“我的上司X做错了,他错了……对吧?”之类的问题。通常关闭为“非建设性”。
maple_shaft

41
假定临时解决方法将成为永久性。他们总是这样做。
user16764

2
@maple_shaft-关于该问题的出色保存编辑。

2
错误号用于注释和版本控制提交说明,而不是方法名称。您的同事应该被打耳光。
Erik Reppen

Answers:


58

我不会按照您的同事的建议来命名该方法。方法名称应指示方法的作用。类似的名称PerformSqlClient216147Workaround并不表示其功能。如果有的话,请使用描述方法的注释来提及它是一种解决方法。看起来可能如下所示:

/**
 * Cast given right-hand SQL expression.
 *
 * Note: This is a workaround for an SQL client defect (#216147).
 */
public void CastRightExpression(SqlExpression rightExpression)
{
    ...
}

我同意MainMa的观点,错误/缺陷号不应出现在源代码本身中,而应出现在源代码控制注释中,因为这是元数据,但是如果它们出现在源代码注释中并不可怕。错误/缺陷编号绝对不能在方法名称中使用。


5
在文档注释中具有指向该错误的直接http链接将是一个好主意。您还可以定义自己的注释@Workaround(216147)
-Sulthan

2
@warning This is a temporary hack to...TODO: fix for ...
BЈовић

1
@Sulthan-当然。。。链接到几年后可能不存在的缺陷数据库。描述缺陷,放入缺陷编号(和日期),记录其解决方法,但是链接到可以更改的内部工具似乎是个坏主意。
Ramhound

4
@Ramhound您应该考虑缺陷数据库和更改历史至少与源代码一样有价值。他们告诉您有关为什么要做某事以及如何变成这样的完整故事。下一个人将需要知道。
Tim Williscroft

1
代码(在这种情况下,方法名)应自文件是什么它。注释应解释为什么代码存在或以某种方式构造。
亚伦·库尔扎尔斯

48

没有比临时修复有效的方法更永久了。

他的建议在十年后看起来不错吗?通常,通常都会在修正了每个缺陷的情况下对每个更改进行注释。最近(例如最近的30年),这种样式注释已被广泛接受,因为它降低了代码的可维护性-即仅注释而不是方法名称。

他的提议是有力的证据证明您的QC和QA系统严重不足。缺陷和缺陷修复程序的跟踪属于缺陷跟踪系统,而不是源代码。跟踪源代码更改属于源控制系统。这些系统之间的交叉引用允许将缺陷跟踪到源代码.....

源代码是今天的,不是昨天的,也不是明天的(例如,您没有键入明年计划做的事情)...


40
+1Nothing is more permanent than a temporary fix that works.
Reactgular

2
“被广泛接受” [需要引用]

3
@Graham:这够好吗,还是需要经过同行评审,发表在著名的期刊上?... stackoverflow.com/questions/123936/…–
mattnz

14

所以这是一个临时解决方案?然后使用审阅者建议的名称,但将方法标记为过时,以便每次有人编译代码时使用该方法都会产生警告。

如果不是,您可能总是会说这216147在代码中是没有意义的,因为代码没有链接到错误跟踪系统(而是链接到源代码控件的错误跟踪系统)。源代码不是引用bug票证和版本的好地方,如果您确实需要将这些引用放在此处,请在注释中进行处理。

请注意,即使在注释中,仅bug号也不是很有价值。想象以下评论:

public IEnumerable<Report> FindReportsByDateOnly(DateTime date)
{
    // The following method replaces FindReportByDate, because of the bug 8247 in the
    // reporting system.
    var dateOnly = new DateTime(date.Year, date.Month, date.Day);
    return this.FindReportByDate(dateOnly);
}

private IEnumerable<Report> FindReportsByDate(DateTime date)
{
    Contract.Requires(date.Hour == 0);
    Contract.Requires(date.Minute == 0);
    Contract.Requires(date.Second == 0);

    // TODO: Do the actual work.
}

想象一下,该代码是十年前编写的,您刚刚加入该项目,并且当您问到哪里可以找到有关错误8247的任何信息时,您的同事告诉您,该错误的网站上有一个错误列表。报告系统软件,但该网站是在五年前重做的,而新的错误列表有不同的数字。

结论:您不知道此错误是关于什么的。

相同的代码可能以略有不同的方式编写:

public IEnumerable<Report> FindReportsByDateOnly(DateTime date)
{
    // The reporting system we actually use is buggy when it comes to searching for a report
    // when the DateTime contains not only a date, but also a time.
    // For example, if looking for reports from `new DateTime(2011, 6, 9)` (June 9th, 2011)
    // gives three reports, searching for reports from `new DateTime(2011, 6, 9, 8, 32, 0)`
    // (June 9th, 2011, 8:32 AM) would always return an empty set (instead of isolating the
    // date part, or at least be kind and throw an exception).
    // See also: http://example.com/support/reporting-software/bug/8247
    var dateOnly = new DateTime(date.Year, date.Month, date.Day);
    return this.FindReportsByDate(dateOnly);
}

private IEnumerable<Report> FindReportsByDate(DateTime date)
{
    Contract.Requires(date.Hour == 0);
    Contract.Requires(date.Minute == 0);
    Contract.Requires(date.Second == 0);

    // TODO: Do the actual work.
}

现在,您可以清楚地了解问题了。即使注释末尾的超文本链接似乎已在5年前失效,也没关系,因为您仍然可以理解为什么将FindReportsByDate其替换为FindReportsByDateOnly


好的,我们到了什么地方:为什么您认为源代码不是bug编号的好地方?
Bojan

1
因为错误跟踪系统和版本控制是一个更好的选择。它并不完全相同,但类似于:stackoverflow.com/q/123936/240613
Arseni Mourzenko 2013年

好吧,总的来说是有道理的。但是,如果您要解决问题,例如偏离主要设计,我想可以留下注释来解释已完成的操作(注释中可能有缺陷编号),以便正在阅读代码的人可以理解为什么以某种方式做了一些事情。
Bojan

2
尽管只有营销人员可以争论添加过时的新东西的逻辑。
mattnz

1
如果从阅读中看不出代码为什么能解决该错误,并且您需要就此解决方法的作用进行冗长的解释,包括对在注释中可以找到外部文档的地方的引用,则这是IMO合理的。 。是的,您可以使用源代码控制工具来找出解决方法,该解决方法是其一部分,并在那里进行了解释,但代码量很大,尤其是在其他地方进行重构导致最终无法解决问题时,这样做可能会非常耗时。
Dan Neely

5

PerformSqlClient216147Workaround然后我发现更多信息PerformRightExpressionCast。毫无疑问,函数的名称是关于它的功能,为什么执行它或如何获得有关它的更多信息。这是一个显式函数,在源代码中将非常容易搜索。

使用错误跟踪系统,该编号可以唯一地标识问题,当您在系统中拉出该错误时,它会提供所需的所有详细信息。这是在源代码中做的非常聪明的事情,当试图了解进行更改的原因时,它将为将来的开发人员节省时间。

如果您在源代码中看到很多这些函数名,那么问题就不在于您的命名约定。问题是您有错误的软件。


2
我同意,PerformSqlClient216147Workaround似乎准确地描述了该方法的作用及其存在的原因。我会为您的商店使用特定于此类事物的属性(C#)对其进行标记并完成此操作。数字在名称中占有一席之地...希望如上所述,这不仅是您的商店对此类事物进行分类的方法。猛冲在茶杯恕我直言。顺便说一句,那是真正的错误代码吗?如果是这样,您是高级同事,可能有下降的机会发现此职位,这可能对您或不成问题。;)
rism

3

您同事的建议有价值。它通过将代码更改与错误代码中记录在错误数据库中的原因(进行更改的原因)相关联来提供可追溯性。

但是,这也表明该功能存在的唯一原因是解决该错误。那就是,如果问题不是问题,则您不希望软件执行该操作。大概您确实希望软件执行其任务,因此函数的名称应说明其功能以及为什么需要执行此问题域;不是错误数据库为什么需要它。该解决方案应该看起来像应用程序的一部分,而不是创可贴。


3
这应该在方法的注释中说明,而不是其名称。
Arseni Mourzenko 2013年

2
我总体上同意您的回答,但我也同意MainMa:有关方法的元信息应该在注释中,而不是名称中。
罗伯特·哈维

3

我认为您和他俩都把这件事弄得不合比例。

我同意您的技术观点,但最终不会有太大的不同,特别是如果这是一个临时的修复程序,可以在几天/几周/几个月内从代码库中删除。

我认为您应该将自我放回原处,让他有自己的方式。(如果他也听的话,我想你们需要妥协。两个自负都回到他们的盒子里。)

无论哪种方式,您和他都有更好的事情要做。


点了。但我不会低估自我的力量:)
Bojan

1

在临时解决方法的方法名称中包含错误号是否被视为不良做法?

是。

理想情况下,您的班级应该最好地映射/实现应用程序流程/状态中的概念。此类的API名称应反映它们对类状态所做的工作,以便客户端代码可以轻松使用该类(即,除非您特别阅读该名称,否则请不要指定从字面意义上讲没有任何意义的名称)。

如果该类的公共API的一部分基本上说“执行文档/位置X中描述的操作Y”,那么其他人理解API的能力将取决于:

  1. 他们知道在外部文档中寻找什么

  2. 他们知道在哪里寻找外部文档

  3. 他们花费时间和精力,并真正地寻找。

再说一遍,您的方法名称甚至都没有提到此缺陷所在的“位置X”。

它只是假设(没有任何现实原因)每个访问代码的人,也都可以访问缺陷跟踪系统,并且只要稳定的代码存在,跟踪系统仍将存在。

至少,如果您知道该缺陷始终可以在同一位置访问并且不会改变(例如,过去15年中使用相同URL的Microsoft缺陷编号),则应提供指向该缺陷的链接。 API文档中的问题。

即使这样,也可能存在其他缺陷的解决方法,这些缺陷的影响远大于一类的API。那你要怎么办

在多个类中使用具有相同缺陷编号的API(data = controller.get227726FormattedData(); view.set227726FormattedData(data);实际上并不能告诉您太多,只会使代码更加晦涩难懂。

您可以通过使用描述operation(data = controller.getEscapedAndFormattedData(); view.setEscapedAndFormattedData(data);)的名称来确定是否解决了所有其他缺陷,除非您的216147缺陷(这违反了“最少惊讶”的设计原理,或者如果您这样说,增加代码的“ WTF / LOC”的大小)。

TL; DR:不好的做法!去你的房间!


0

程序员的主要目标应该是工作代码以及表达的清晰性。

命名解决方法(....解决方法)。似乎可以实现这个目标。希望在某个阶段可以解决基本问题,并删除解决方法。


0

对我而言,在错误后命名方法表明该错误未解决或根本原因未确定。换句话说,它表明仍然存在一个未知数。如果您要解决第3方系统中的错误,那么您的解决方法是一种解决方案,因为您知道原因-他们只是无法解决,也无法解决。

如果与SqlClient交互的一部分要求您执行正确的表达式转换,则您的代码应显示为“ performRightExpressionCast()”。您总是可以注释代码以解释原因。

我花了过去四年半的时间来维护软件。使代码在进入时难以理解的一件事是仅由于历史而编写的代码。换句话说,如果今天写的话,那将是行不通的。我指的不是质量,而是观点。

我的一位同事曾经说过:“修复缺陷时,请按原本的方式编写代码。” 我的解释方式是“将代码更改为如果该错误不存在,将如何显示。”

后果:

  1. 通常,结果是更少的代码。
  2. 简明代码
  3. 对源代码中的错误的引用更少
  4. 降低未来回归的风险(一旦代码更改得到充分验证)
  5. 由于开发人员不必再负担不再相关的学习历史,因此更易于分析。

源代码不需要告诉我它如何达到当前状态。版本控制可以告诉我历史。我需要源代码简单地处于工作所需的状态。就是说,偶尔出现“ // bug 12345”注释不是一个坏主意,但会被滥用。

因此,在决定是否将方法命名为“ PerformSqlClient216147Workaround”时,请问自己以下问题:

  1. 如果在编写代码之前就知道错误216147,我将如何处理?
  2. 解决方法是什么?如果有人以前从未看过此代码,那么他们是否能够遵循它?是否需要检查错误跟踪系统才能了解此代码的工作原理?
  3. 该代码有多临时?以我的经验,如@mattnz所示,临时解决方案通常是永久的。
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.