命名:您是否应该为了简洁而牺牲简洁性?


11

例如,以下函数循环遍历包含输入字段名称和错误的数组。它通过检查验证字段的名称,然后将错误信息推送到无效的字段数组来完成此操作。

简短点说并写成更好:

addInvalidField (field, message) {
  const foundField = this.invalidFields.find(value => {
    return value.name === field.name
  })
  const errors = foundField.errors
  if (!errors.some(error => error.name === message)) {
    errors.push({ name: message, message })
  }
},

还是更具体地这样?

addInvalidField (validatingField, message) {
  const foundField = this.invalidFields.find(invalidField => {
    return validatingField.name === invalidField.name
  })
  if (!foundField.errors.some(foundFieldError => foundFieldError.name === message)) {
    fouldField.errors.push({ name: message, message })
  }
},

1
相关(可能重复):短变量名有借口吗?
蚊蚋

不想写答案,但我们总是尽力在名称长度和清晰度之间找到一个好的折衷方案。短名称可能对原始程序员很明显,但对其他所有人却不明显。长名称会使代码难以阅读。两者之间存在折衷。
MetalMikester '16

1
需要更多评论
Ewan

旁注,并且不确定代码中是否可能,但是如果将invalidFields等存储在map中,而不是数组中,则此代码将变得更加简单。
user949300 '16

1
@alex为了回应您的评论,如果您可以获取或借用Marijn Haverbeke的Eloquent JavaScript副本(2014版),请转到第73-75页,以查看使用映射而不是数组的绝佳示例。希望能有所帮助。
user949300 '16

Answers:


23

如果可以为了简洁而牺牲简洁性,应该这样做。但是如果为了清晰起见可以牺牲冗长,甚至更好。

addInvalidField (field, message) {
  const foundInvalidField = this.invalidFields.find(x => x.name === field.name)
  if (!foundInvalidField.errors.some(x => x.name === message)) {
    foundInvalidField.errors.push({ name: message, message })
  }
},

当一个变量的寿命只有一行时,它确实可能很短。 FoundInvalidField分三行使用,是本工作的重点。它应有一个解释性的名称。

一如既往,环境为王。


2
+1表示“如果可以为了简洁而牺牲简洁性,那么应该。但是如果为了清晰而牺牲冗长性,那就更好了。” 即使在几乎每种情况下我都力求清晰时。但这绝对是一个引号。
图兰斯·科尔多瓦

12

我实际上很喜欢您的第一个代码示例。

只需阅读即可清楚看到代码的功能。通过使变量名尽可能小,可以使代码更易于阅读。仅当您的函数更长,变量更多和/或在较大的代码范围内使用了变量时,才需要使用更具描述性的变量名称。

这是因为您使函数简短,所以也可以使变量名称简短。在所有其他条件相同的情况下,代码越少越好。


2
通常,我倾向于使用较小的变量名作为我的方法/函数。我唯一要使用更详细的名称的时间是在名称空间冲突的情况下。如果您的函数很小,则也更容易实现。
弗洛雷斯

4
我曾与一个非常熟悉冗长名字的人一起工作。变量和方法名称基本上是完整的英语句子,例如,ResultOfMethodDoFooWithBar。想法是,这本来应该使事情变得清楚,但让我头疼的是试图(精神上)解析所有这些绒毛。对于此示例,我们已经知道该方法与字段验证有关。没有其他“字段”参数。使用“ validatingField”之类的名称不会增加清晰度,并且在浏览时会掩盖重要信息。
JimmyJames

@unflores我也尝试这样做。validatingFields是带有验证的表单字段。原名是fieldWithValidation。很难找到这个名字的简称。我可以调用它,field但随后它将与field方法中的另一个冲突。
亚历克斯

4

我想我同意鲍勃叔叔的观点,他更喜欢清晰而不引起过多的冗长。在您显示的示例中,我要说的是第二个人的意图更加明确,而不会引起过多的冗长。同样,在通过搜寻代码库而invalidField不是时,找到特定代码段会更容易value


好吧,我在这里引用“干净代码”(如果您对鲍伯叔叔的讲学感到厌倦,请跳过它(我不是):

使用意图透露名称

说名字应该显示意图很容易。我们想给您留下的印象是,我们对此很认真。选择好名字要花时间,但要花很多时间。因此,请注意您的名字,并在找到更好的名字时进行更改。如果您这样做,那么读取您的代码(包括您)的每个人都会更快乐。


避免虚假信息

程序员必须避免留下掩盖代码含义的错误线索。我们应该避免那些根深蒂固的意思与我们


做出有意义的区分

当程序员仅仅为了满足编译器或解释器的要求而编写代码时,就会为他们自己创造问题。


使用可搜索名称

使用可以帮助您完成操作的名称grep -iIR whateveryouaresearching . (不是干净代码,此处CC仅讨论单字母变量)。


避免思维导图

读者不必在头脑上将您的名字翻译成他们已经知道的其他名字。这个问题通常是由于选择不使用问题域术语或解决方案域术语而引起的。


使用问题域名

如果您的工作没有“程序员”,请使用问题域中的名称。至少维护您代码的程序员可以询问域专家这是什么意思。



1

这些天我总是会选择更具描述性的-IDE代码完成意味着您不必编写描述性变量名,因此我看不到任何不利之处。

在史前时代,您具有变量名限制,使用有意义的变量名实际上会产生可衡量的成本(例如,在BBC BASIC中,使用整数静态变量A%等比使用有意义的整数便宜得多,并且在1MHz的系统中处理器,实际上节省了一个循环中的几个时钟周期)


6
不利的一面是您不必输入太多内容。键入仅发生一次。名称太长的缺点是阅读变得更难。这是阴险的,因为在代码库的整个生命周期内都会发生多次读取,而且由于读取已根深蒂固,人们没有有意识地注意到问题的根源。
凯莉安·佛斯

而且,如果您不得不花费时间和上下文转移来尝试记住有关变量的某些信息,因为它的描述性不够,则会花费更多的时间:)。
mcottle

1

第二个变种看起来让我感到困惑。当我仅查看签名时,我想知道该字段是否已经被认为是无效的?还是首先验证它(称为validatingField),以确认它是否真的无效?因此,这不仅是多余的信息,而且额外的信息似乎有些误导。这种“澄清度”不明确,相反。

实际上,当我看到您的第一个功能时,也让我感到困惑。我问自己为什么您的函数只占用一个字段,然后不使用它并在其中搜索另一个invalidFields?当只给出一个字段名时,寻找一个字段似乎更有意义,像这样:

addInvalidField (fieldname, message) {
  const foundField = this.invalidFields.find(value => {
    return value.name === fieldname
  })
  const errors = foundField.errors
  if (!errors.some(error => error.name === message)) {
    errors.push({ name: message, message })
  }
}

但是,我想鲍勃·马丁可能会更进一步,使代码更冗长(更清晰),朝着另一个方向发展。按照“清除代码”这本书的方式进行的典型重构可能看起来像这样:

addInvalidField (fieldname, message) {
  const foundField = findInvalidField(fieldName)
  addMessageForInvalidField(foundField,message)
}

具有三个附加功能

  findInvalidField(fieldname){
    return this.invalidFields.find(value => { return value.name === fieldname })
  }

  addMessageForInvalidField(field,message){
    const errors = field.errors
    if (!doesErrorsContain(message)) {
      errors.push({ name: message, message })
    }
  }

  doesErrorsContain(message){
     return errors.some(error => error.name === message)
  }

如果在单一责任原则上走得那么远还值得商pay。它实际上有一些优点和缺点。我个人的观点是,对于大多数生产代码而言,原始代码“足够干净”,但是重构代码更好。

当我知道必须在第一个变体中添加一些东西,以便使其越来越多时,我会事先将其拆分为这些较小的函数,因此代码甚至不会变得一团糟。


validatingFields是具有验证形式的字段。最初,我为它们命名,fieldsWithValidation但是有点长。
Alex

0

一般来说,命名没有正确答案。当许多人被赋予完全相同的任务集时,它们对结果函数和变量的命名将有很大不同。当然,您希望其他阅读您的代码的人理解,但是更长的时间并不总是意味着更清晰。如果您的代码更加密集,那么就需要如此,那么即使您的函数的每一行都尽可能清晰和描述性,也将需要更多的时间来理解。

我个人更喜欢第一个示例。即使变量不像第二个示例那样具有描述性的名称,也很简单。老实说,在我看来,第二个示例中的变量名称比第一个示例中的名称更清晰,并且使函数简短,可以更轻松地理解函数本身。

归根结底,更好的将取决于您和与您一起工作的任何人。毕竟,那是谁会阅读并维护它。

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.