我自己,当我需要做两次以上的事情时,我迫不及待地想编写一个函数。但是当涉及到只出现两次的事情时,这会比较棘手。

对于需要两行以上的代码,我将编写一个函数。但是当遇到类似这样的事情:

print "Hi, Tom"
print "Hi, Mary"


我犹豫要写:

def greeting(name):
    print "Hi, " + name

greeting('Tom')
greeting('Mary')


第二个


但是如果我们有:

for name in vip_list:
    print name
for name in guest_list:
    print name


这是替代方法:

def print_name(name_list):
    for name in name_list:
        print name

print_name(vip_list)
print_name(guest_list)


事情变得棘手,不是吗?现在很难下定决心。

您对此有何看法?

评论

我永远都不会把它当作危险信号。有一种叫做“上下文”的东西,即使总的来说,永远不变和永不规则可能并不适合。当心那些绝对的软件开发人员。 ;)

在最后一个示例中,您可以执行以下操作:从itertools导入链;链中名称的名称(vip_list,guest_list):print(name)。

@ user16547我们称这些为“软件开发人员”!

提姆·彼得斯(Tim Peters)的《 Python禅》(Zen of Python):特殊情况不够特殊,无法打破规则。尽管实用性胜过纯度。

还考虑是否要使用“潮湿的代码”或“干燥的代码”,请参见stackoverflow.com/questions/6453235/…

#1 楼

尽管这是决定拆分功能的一个因素,但是重复某件事的次数不应是唯一的因素。为只执行一次的对象创建函数通常很有意义。通常,您希望在以下情况下拆分函数:


它简化了每个抽象层。
拆分函数有很好的有意义的名称,因此您不必通常,您需要在抽象层之间跳转以了解发生了什么。

您的示例不符合该标准。您正在从一种模式转换为一种模式,而名称在清晰度方面并没有真正为您带来任何好处。话虽如此,简单的功能在教程和学校作业之外很少见。大多数程序员倾向于以其他方式犯错。

评论


这就是我在罗伯特·哈维的回答中想念的重点。

–布朗博士
15年1月13日在7:30



确实。我经常将复杂的函数拆分为内联的子例程-不会出现性能下降,但很干净。匿名作用域也很好。

–imallett
15年1月13日在17:42

还有一个范围问题。编写整个类或整个模块都可以看到的print_name(name_list)函数可能没有任何意义,但是(在这种情况下仍然是一小段)在函数中创建局部函数以清理几行重复的代码。

–约书亚·泰勒(Joshua Taylor)
15年1月13日在17:50



我可能要补充的另一点是标准化。在第一个示例中,正在做一个问候语,将其粘贴在一个函数中以确保您对两个人的问候语相同是很有意义的。特别是考虑到问候语将来可能会改变:)

–Svish
15年1月15日在11:31

仅为+1为只执行一次的函数创建函数通常很有意义。曾经有人问我如何设计用于模拟火箭发动机行为的功能的测试。该函数的循环复杂性是在90年代,在某些情况下(不是很丑,但可测试)并不是90的switch语句。相反,它是由工程师编写的令人费解的混乱,完全无法测试。我的回答是,它是无法测试的,需要重写。他们听了我的建议!

–David Hammen
2015年1月17日14:12



#2 楼


或者,只是重复是有意的,而不是偶然的。
,或者换种说法:
只有当您希望它们在将来共同发展时,。

这是为什么:< br有时,即使它们之间没有任何关系,两段代码也恰好变得相同。在那种情况下,您必须抵制将它们组合在一起的冲动,因为下次有人对其中一个进行维护时,该人将不会期望所做的更改会传播到以前不存在的调用者,因此该功能可能会中断。因此,您只需要在有意义的时候就将代码分解出来,而不必在似乎要减小代码大小的情况下。
经验法则:
如果代码仅返回新数据且不修改现有数据或具有其他副作用,那么很可能可以安全地将其单独考虑在内。 (我无法想象在没有完全改变函数预期语义的情况下会导致损坏的任何情况,这时函数名称或签名也应更改,在这种情况下,您需要格外小心。 )

评论


+1我认为这是最重要的考虑因素。没有人重构代码,期望它们的更改是最后的更改,因此请考虑您的更改将如何影响代码中的未来更改。

– yoniLavi
2015年1月14日19:31



它是红宝石,但是来自Avdi Grimm的有关巧合复制的截屏视频仍然与以下问题有关:youtube.com/watch?v=E4FluFOC1zM

– DGM
15年1月15日在16:21

#3 楼

不,并非总是最佳做法。

所有其他相等的东西,线性,逐行代码比在函数调用周围跳转更容易阅读。非平凡的函数调用总是带有参数,因此您必须将所有内容整理清楚,并使从函数调用到函数调用的思维上下文跳跃。除非您有充分的理由(例如获得必要的性能改进),否则始终希望更好的代码清晰度。

那么为什么要将代码重构为单独的方法呢?改善模块化。收集单个方法背后的重要功能并为其赋予一个有意义的名称。如果您未完成此操作,则不需要这些单独的方法。

评论


代码的可读性是最重要的。

–汤姆·罗宾逊
15年1月13日在5:30

如果您没有忘记创建函数的主要原因之一,那么我会赞成这个答案:通过给函数的一个好名字来创建抽象。如果您添加了这一点,很显然线性的逐行代码并不总是比使用格式正确的抽象的代码更容易阅读。

–布朗博士
15年1月13日在7:26

我同意布朗博士的观点,代码不一定比正确抽象时逐行可读。好的函数名称使高级函数非常易于阅读(因为您正在阅读意图而不是实现),而低级函数则易于阅读,因为您正在执行一项任务,仅执行一项任务,仅执行该任务。这使功能简洁而精确。

–乔恩的故事
15年1月13日在12:38

当您没有从中获得重大收益时,为什么还要降低函数调用的性能呢?表现如何?通常情况下,小型函数会内联,大型函数的开销可以忽略不计。 CPython可能不会内联,但是没有人使用它来提高性能。我也质疑逐行代码...位。如果您想在大脑中模拟执行,那会更容易。但是调试器会做得更好,尝试通过遵循循环的执行来证明循环的某些事情就像通过遍历所有整数来证明有关整数的语句一样。

–Doval
2015年1月13日在12:43



@Doval提出了一个非常有效的观点-编译代码时,该函数被内联放置(并重复了),因此,尽管编译过程中很小,但运行时性能不会受到影响。对于解释型语言而言并非如此,但是即使如此,函数调用也只占执行时间的一小部分。

–乔恩的故事
15年1月13日在12:48

#4 楼

在您的特定示例中,执行功能可能看起来过于矫kill过正。相反,我会问一个问题:这种特殊的问候语将来可能会改变吗?怎么办?

函数不仅仅用于包装功能和简化重用,而且还易于修改。如果需求发生变化,复制粘贴的代码将需要手动查找和更改,而使用一个功能,该代码只需修改一次。

您的示例将从中受益,而无需通过函数-因为逻辑几乎不存在-但可能是GREET_OPENING常数。然后可以从文件中加载此常量,以便您的程序可以轻松地适应例如不同的语言。请注意,这是一个粗略的解决方案,一个更复杂的程序可能需要一种更完善的方式来跟踪i18n,但这再次取决于需求与工作量。

这一切都与最终可能的需求有关。 ,并事先计划好事情,以减轻将来的工作负担。

评论


使用GREET_OPENING常量假定所有可能的问候都以相同的顺序进行。与母语几乎与英语相反的一切的人结婚使我对这种假设持怀疑态度。

–Loren Pechtel
2015年11月15日,下午3:57

#5 楼

我个人采用了三个规则-我将通过致电YAGNI来证明这一点。如果我需要编写一次代码,那么我可以复制/粘贴两次(是的,我刚刚承认要复制/粘贴!),因为我不再需要它,但是如果我需要这样做再说一遍,然后我将重构并将其提取到它自己的方法中,我向我自己证明,我将再次需要它。

我同意卡尔·比勒费尔特和罗伯特·哈维所说的我对他们所说的解释是,首要原则是可读性。如果它使我的代码更易于阅读,请考虑创建一个函数,请牢记DRY和SLAP之类的东西。如果我可以避免在函数中更改抽象级别,那么我会发现这很容易管理,因此不要在函数之间跳转(如果我无法仅通过读取函数名称来了解函数的功能),则意味着我的开关更少心理过程。
同样,不必在函数和内联代码之间切换上下文,例如print "Hi, Tom"对我有用,在这种情况下,如果我整体功能的其余部分大部分是函数调用,则我可以提取函数PrintNames()

评论


c2 Wiki在“三规则”上有一个不错的页面:c2.com/cgi/wiki?RuleOfThree

– Pimlottc
2015年1月13日在23:02



#6 楼

它很少是明确的,因此您需要权衡以下选择:


最后期限(尽快修复服务器机房)
代码的可读性(可能会影响任一选择)
共享逻辑的抽象级别(与上面相关)
重用要求(即具有完全相同的逻辑很重要,或者现在只是方便)
共享困难(这是python的亮点,请参见下文)

在C ++中,我通常遵循三个规则(即第三次我需要相同的东西时,我将其重构为可适当共享的部分),但是根据经验,最初更容易做出选择您对正在使用的范围,软件和域有了更多的了解。

但是,在Python中,重用(而不是重复)逻辑相当轻巧。因此,与其他许多语言(至少从历史上来讲)相比,IMO更为重要。

因此,请考虑仅在本地重新使用逻辑,例如,通过从本地参数创建列表:

def foo():
    for name_list in (vip_list, guest_list): # can be list of tuples, for many args
        for name in name_list:
            print name


如果需要多个参数,则可以使用元组的元组并将其直接拆分为for循环:

def foo2():
    for header, name_list in (('vips': vip_list), ('people': guest_list)): 
        print header + ": "
        for name in name_list:
            print name


或创建一个局部函数(也许是您的第二个例子),它使逻辑重用变得明确,但也清楚地表明在函数外没有使用print_name():

def foo():
    def print_name(name_list):
        for name in name_list:
            print name

    print_name(vip_list)
    print_name(guest_list)


函数是首选,尤其是当您需要中途中断逻辑(即使用return)时,因为中断或异常可能会不必要地使事情混乱。

两者都比重复更好与IMO相同的逻辑,并且比声明仅由一个调用者使用(尽管两次)的global / class函数要简单得多。

评论


在看到这个答案之前,我对新功能的范围发表了类似的评论。我很高兴有一个针对该问题的答案。

–约书亚·泰勒(Joshua Taylor)
15年1月13日在17:54

+1-也许这不是OP所寻求的答案,但至少就他所问的问题而言,我认为这是最明智的回答。这种东西可能会以某种方式为您嵌入到语言中。

–帕特里克·柯林斯(Patrick Collins)
15年1月14日在9:07

@PatrickCollins:感谢您的投票! :)我添加了一些注意事项以使答案更加完整。

– Macke
2015年1月20日在6:44



#7 楼

所有最佳实践都有一个特殊的原因,可以回答这个问题。
当潜在的未来变化也意味着其他组件也会发生变化时,您应该始终避免出现波动。

因此在您的示例中:
如果您假设自己有一个标准的问候语并想确保所有人都一样,那么请写

def std_greeting(name):
    print "Hi, " + name

for name in ["Tom", "Mary"]:
    std_greeting(name)   # even the function call should be written only once


否则,您必须注意并在两个地方更改标准问候语,如果碰巧会发生变化。

但是,如果“ Hi”只是偶然和更改而相同问候语之一不一定会导致其他问候语发生变化,然后将它们分开。因此,如果有合理的理由相信,请将它们分开,以便更可能进行以下更改:

print "Hi, Tom"
print "Hello, Mary"


第二部分,决定要包装多少”转换为函数可能取决于两个因素:


保持较小的块以提高可读性
保持足够大的块,以便仅在少数几个块中发生更改。不需要过多地聚集,因为很难跟踪调用模式。

理想情况下,发生更改时,您会认为“我必须更改以下大部分内容”,而不是“我必须更改大块内某处的代码”。

评论


考虑到您的循环,这只是个愚蠢的选择-如果确实只需要少数几个硬编码的名称来进行迭代,并且我们不希望它们更改,那么我认为不使用清单。 “ Tom”,“ Mary”中的名称:std_greeting(name)

– yoniLavi
2015年1月14日19:39



好吧,可以继续说一个硬编码列表不会出现在代码中间,并且无论如何都将是一个变量:)但是,我实际上忘记了可以在此处跳过花括号。

–盖伦努克
15年1月15日在6:39

#8 楼

命名常量和函数最重要的方面不是减少它们的键入量,而是它们“附加”了使用它们的不同位置。关于您的示例,请考虑以下四种情况:


有必要以相同的方式更改两个问候语,例如到Bonjour, TomBonjour, Mary]。
有必要更改一个问候语,但保留另一个问候语,例如[
必须以不同方式更改两个问候语(例如, Hi, TomGuten Tag, Mary]。
不需要更改任何问候语。

如果不必更改任何问候语,采用哪种方法都没有关系。使用共享功能将具有自然的效果,即更改任何问候语都会以相同的方式更改它们。如果所有问候都应以相同的方式更改,那将是一件好事。但是,如果不应该,则每个人的问候都必须单独编码或指定;使它们使用通用功能或规范的所有工作都必须撤消(最好不要一开始就做)。

可以肯定的是,并非总是可以预测未来,但是如果有人有理由相信这两种问候语更有可能需要一起更改,那么这就是使用通用代码(或命名常量)的一个因素;如果有人有理由相信一个或两个都可能需要更改以使它们不同,那么这就是尝试使用通用代码的一个因素。

评论


我喜欢这个答案,因为(至少对于这个简单的示例而言),您几乎可以通过一些博弈论来计算选择。

–RubberDuck
15年1月15日,0:35

@RubberDuck:我认为对于事物应该或不应该被“混淆”的问题通常没有给予太多关注,并且在很多方面,我希望错误的两个最常见原因是(1)相信事物是不在时使用别名/附加,或者(2)更改某些内容而未意识到其他内容已附加。这样的问题在代码和数据结构的设计中都会出现,但是我不记得曾经对这个概念给予过多关注。别名通常只在某项中只有一项或永远不会改变时才重要,但是...

–超级猫
15年1月15日在16:04

@RubberDuck:...如果有两个匹配并且它们匹配,那么重要的是要知道更改一个是否应该使另一个值保持不变,或者应该保持关系不变(这意味着另一个值会改变)。我经常看到保持价值不变的优势很受重视,但是关系的重要性却远没有得到重视。

–超级猫
15年1月15日在16:08

我完全同意。我只是想弄清楚传统知识是如何将其干燥的,但是从统计学上讲,重复的代码以后将不再是重复的代码的可能性更大。您基本上有2比1的赔率。

–RubberDuck
2015年1月15日在16:10



@RubberDuck:我给出了两种情况,其中分离是重要的,而其中附着性更好的是,它并没有说明各种情况发生的相对可能性。重要的是要识别两条代码是“巧合”还是因为它们具有相同的基本含义而匹配。此外,当存在两个以上的项目时,还会出现另外的情况,其中一个最终想要使一个或多个与另一个有所不同,但仍以相同的方式更改两个或多个。即使一个动作只在一个地方使用

–超级猫
15年1月15日在16:40

#9 楼

我认为您应该有理由创建一个程序。创建过程有多种原因。我认为最重要的是:


抽象
模块化
代码导航
更新一致性
递归
测试

抽象

过程可用于从算法中特定步骤的细节中提取通用算法。如果我能找到一个适当的连贯抽象,这将帮助我构建思考算法功能的方式。例如,我可以设计一种适用于列表的算法,而不必考虑列表表示形式。

模块化

过程可用于将代码组织到模块中。模块通常可以分开处理。例如,分别构建和测试。精心设计的模块通常会捕获一些连贯的有意义的功能单元。因此,它们通常可以由不同的团队拥有,可以完全替换为其他团队,或者可以在不同的上下文中重用。

代码导航

在大型系统中,查找与特定的系统行为可能具有挑战性。库,模块和过程中代码的分层组织可以帮助应对这一挑战。特别是如果您尝试a)以有意义且可预测的名称组织功能b)将与类似功能相关的过程彼此靠近。

Update Consistency

在大型系统中,它可以很难找到所有需要更改以实现特定行为更改的代码。使用过程来组织程序的功能可以使此过程更容易。特别是,如果程序的每个功能仅出现一次并且在一组紧密的过程中出现,那么(根据我的经验),您不太可能错过应该更新的地方或进行不一致的更新的地方。

请注意,您应该根据程序的功能和抽象来组织过程。并非基于当前两个代码是否相同。

递归

使用递归要求您创建过程

测试

通常,您可以相互独立地测试过程。独立测试过程主体的不同部分更加困难,因为通常必须在第二部分之前执行过程的第一部分。这种观察通常还适用于指定/验证程序行为的其他方法。

结论

其中许多要点与程序的可理解性有关。您可能会说,过程是一种创建特定于您的域的新语言的方法,用于组织,编写和阅读有关域中的问题和流程的信息。

#10 楼

您给出的两种情况似乎都不值得重构。

在两种情况下,您都执行的操作清晰明了,并且没有发生不一致更改的危险。

我建议您始终在以下位置寻找隔离代码的方法:


有一个可以识别的,有意义的任务可以分离出来,并且



a。该任务很难表达(考虑到您可以使用的功能),或者

b。该任务已执行多次,并且您需要一种方法来确保在两个地方都以相同的方式对其进行更改。


如果不满足条件1,那么您将找不到正确的代码接口:如果尝试强制使用它,最终将导致大量的参数,要返回的多个内容,大量的上下文逻辑,并且很可能找不到好名字。尝试记录一下您首先想到的接口,这是测试假设它是正确的功能捆绑的一种好方法,并且附带了一个额外的好处,那就是在编写代码时,它已经被指定和记录了!

2a可能没有2b:有时即使我知道它仅被使用一次,我也会从流程中删除代码,这仅仅是因为将其移动到其他位置并用一行替换它意味着被调用的上下文突然变多了更具可读性(特别是如果这是一个简单的概念,该语言恰巧难以实现)。当读取提取的函数时,逻辑的起点和终点以及其作用也很清楚。

没有2a,2b是可能的:诀窍在于感觉哪种变化更有可能发生。如果您发送付款要求或服务中断道歉,您的公司政策很有可能会从始终到处打“ Hi”变成“ Hello”,或者打招呼变成更正式的语气?有时可能是因为您不确定所使用的外部库,并希望能够快速将其交换给另一个库:即使功能未实现,实现也可能会更改。

但是,大多数情况下,您会混合使用2a和2b。而且,您必须运用自己的判断力,考虑到代码的商业价值,代码的使用频率,是否经过充分记录和理解,测试套件的状态等。

如果您发现不止一次使用同一逻辑位,那么绝对应该利用机会考虑重构。如果在大多数语言中,新语句开始的缩进级别超过n,则这是另一个稍微不那么重要的触发器(请为您使用的给定语言选择n的值,例如,Python可能为6)。 br />
,只要您考虑这些事情并清除大型意粉代码怪兽,就应该没问题-不要花太长时间担心您的重构需要多精细您没有时间进行测试或编写文档。如果确实需要做,时间会证明一切。

#11 楼

总的来说,我同意罗伯特·哈维(Robert Harvey)的观点,但是我想添加一个案例,以将功能分解为功能。提高可读性。考虑一种情况:

def doIt(smth,smthElse)
    for x in getDataFromSomething(smth,smthElse):
        if not check(x,smth):
            continue
        process(x,smthElse)
        store(x) 


即使未在其他任何地方使用这些函数调用,但是如果所有3个函数都相当长且具有嵌套循环等,则可读性会大大提高。 。

#12 楼

没有必须应用的严格规则,这取决于将要使用的实际功能。对于简单的姓名打印,我不会使用函数,但是如果它是一个数学和,那就是另一回事了。然后,即使它仅被调用两次,您也将创建一个函数,这是为了确保数学和在更改后始终保持不变。在另一个示例中,如果您执行任何形式的验证,则将使用一个函数,因此在您的示例中,如果您需要检查名称长于5个字符,则可以使用一个函数来确保始终进行相同的验证。

因此,当您说“对于需要两行以上的代码,我必须编写一个func”时,我认为您回答了自己的问题。通常,您将使用函数,但还必须使用自己的逻辑来确定使用函数是否会带来任何类型的增值。

#13 楼

我已经相信这里没有提到过的重构问题,我知道这里已经有很多答案了,但是我认为这是新的。

我一直是一个残酷的重构者自该条款出现之前就坚信DRY。这主要是因为我难以保持较大的代码库,部分是因为我喜欢DRY编码,而对C&P编码则一无所知,实际上这对我来说是痛苦且非常缓慢的事情。

就是说,坚持使用DRY在一些我很少看到的其他技术上给了我很多练习。许多人坚持认为Java很难或不可能进行DRY,但实际上他们只是不尝试。

很久以前的一个例子与您的例子有些相似。人们倾向于认为Java GUI的创建很困难。当然,如果您编写这样的代码,那就是:

Menu m=new Menu("File");
MenuItem save=new MenuItem("Save")
save.addAction(saveAction); // I forget the syntax, but you get the idea
m.add(save);
MenuItem load=new MenuItem("Load")
load.addAction(loadAction)


任何人都认为这很疯狂是绝对正确的,但这不是Java的错-永远不要编写代码这条路。这些方法调用是旨在包装在其他系统中的函数。如果您找不到这样的系统,请构建它!

您显然无法像这样编写代码,因此您需要退后一步来查看问题,重复的代码实际上在做什么?它指定了一些字符串及其关系(一棵树),并将该树的叶子连接到动作上。
所以,您真正要说的是:

class Menu {
    @MenuItem("File|Load")
    public void fileLoad(){...}
    @MenuItem("File|Save")
    public void fileSave(){...}
    @MenuItem("Edit|Copy")
    public void editCopy(){...}...


一旦以简洁明了的方式定义了关系,就编写了一种处理该关系的方法-在这种情况下,您遍历传入的类的方法并构建一棵树,然后使用该树来构建菜单和操作以及(显然)显示菜单。您将没有重复,并且您的方法是可重用的……与许多菜单相比,它可能更容易编写,而且,如果您真正喜欢编程,那么您将获得更多的乐趣。这并不难-您需要编写的方法可能比手工创建菜单所需的行数要少!

要做到这一点,您需要练习很多。您需要善于准确分析重复部分中的独特信息,提取该信息并弄清楚如何很好地表达它。学习使用诸如字符串解析和注释之类的工具会很有帮助。学习弄清错误报告和文档的知识也非常重要。

只需编写良好的代码,您就可以实现“免费”练习-很有可能,一旦您精通它,就会发现编码某种DRY(包括编写可重用的工具)要比复制和粘贴以及所有错误,重复的错误和编码类型导致的困难更改快。

我认为我不会如果我没有尽可能多地练习DRY技术和构建工具,就可以享受我的工作。如果我不得不削减工资而不必执行复制和粘贴编程,那我会接受。

所以我的观点是:


除非您不知道如何正确重构,否则复制和粘贴会花费更多的时间。
即使在最困难和琐碎的情况下,也要坚持使用DRY,从而学会通过重构来实现良好的重构。是一名程序员,如果您需要一个小的工具来使代码干燥,请对其进行构建。


#14 楼

通常,将某物拆分为一个函数可以提高代码的可读性是一个好主意,或者,如果经常重复的部分在某种程度上是系统的核心。
在上面的示例中,如果您需要打招呼您的用户(取决于语言环境),则具有单独的问候功能是很有意义的。

#15 楼

作为@DocBrown对@RobertHarvey使用函数创建抽象的评论的必然推论:如果您无法提供一个信息丰富的函数名称,其名称远不比其背后的代码更简洁或更清晰,那么您就没有太多抽象。缺少使它成为函数的其他任何很好的理由,则没有必要这样做。

此外,函数名称很少能完整地体现其语义,因此,如果以前并不熟悉它。特别是使用功能语言以外的其他语言时,您可能需要知道它是否具有副作用,可能发生什么错误以及如何对它们进行响应,其时间复杂度,是否分配和/或释放资源以及它是否是线程-安全。

当然,根据定义,我们在这里仅考虑简单函数,但这是双向的-在这种情况下,内联不太可能增加复杂性。此外,读者可能不会意识到这是一个简单的功能,除非他看上去。即使使用将您超链接到定义的IDE,视觉上的跳跃也会妨碍理解。

一般来说,将代码递归分解为更多,更小的函数将最终使您到达功能所在的地步。不再具有独立的含义,因为随着代码片段的组成变得越来越小,这些片段将从周围代码创建的上下文中获得更多的含义。打个比方,把它想像成一张图片:如果放大得太近,就看不清所要查看的内容。

评论


即使将其包装在函数中是最简单的语句,也应使其更具可读性。有时,将其包装在函数中会显得过大,但是如果您不能提供一个比语句所执行的操作更简洁明了的函数名,则可能是一个不好的信号。您对使用函数的否定并不是什么大不了的事。内联的负面影响更大。内联使其难以阅读,难以维护和重用。

–pllee
15年1月14日在21:39

@pllee:我已经介绍了为什么将函数分解到极端时会适得其反的原因(请注意,问题是专门针对极端而不是一般情况。)您没有对这些观点提出反驳,但是仅声称它“应该”有所不同。写出命名问题“可能”是一个不好的信号的说法并不是在这里考虑的情况下可以避免的论点(我的论点当然是至少是警告,您可能已经达到了仅仅为自己着想进行抽象。)

–斯登纳姆
15年1月15日在13:07

我提到了3个否定内联的负面因素,即不确定我仅在哪里声称它“应该有所不同”。我要说的是,如果您不能提出一个名字,那么您的内联可能做得太多。另外,我认为您在这里甚至遗漏了即使是很小的曾经使用过的方法也没有什么要点。微小的命名方法已经存在,因此您不必知道代码要做什么(无需IDE跳转)。例如,即使`if(day == 0 || day == 6)`与`if(isWeekend(day))`的简单陈述也变得更易于阅读和思维导图。现在,如果您需要重复该语句,则isWeekend变得毫不费力。

–pllee
2015年11月5日在22:25

@pllee如果您无法为几乎每个重复的代码片段都找到一个明显更短,更清晰的名称,则您认为这“是一个不好的信号”,但这似乎是出于信仰问题-您不提供任何支持性的论点(在这种情况下,您需要的不只是示例。)isWeekend确实有一个有意义的名称,因此它可能无法通过我的标准的唯一方法是,它的长度既不明显也不比其实现清晰得多。通过争论您认为是后者,您断言这不是我的立场的反例(FWIW,我本人使用过isWeekend。)

–斯登纳姆
2015年11月9日在23:19

我举了一个例子,其中甚至单行语句也更易读,而我给出了内联代码的反面。那是我的拙见,我只是说说而已,不,我不是在反对或谈论“无法命名的方法”。我不确定是什么使我感到困惑,或者你为什么认为我需要“理论证明”。我以提高可读性为例。维护比较困难,因为如果代码块发生更改,则需要N个点(有关DRY的信息)。除非您认为复制粘贴是一种可行的代码重用方法,否则显然很难重用。

–pllee
2015年11月10日15:50