我经常遇到这个问题。例如,我目前正在编写一个读取函数和一个写入函数,它们都检查是否buf
为NULL指针以及mode
变量是否在一定范围内。
这是代码重复。可以通过将其移入其自身的功能来解决。但是我应该吗?这将是一个非常贫乏的功能(不会做很多事情),而是局部化的(所以不是通用的),并且不能很好地独立运行(除非您知道它的位置,否则无法确定您的需求)用过的)。另一个选择是使用宏,但我想在这篇文章中谈谈功能。
那么,您应该使用类似这样的功能吗?优缺点都有什么?
我经常遇到这个问题。例如,我目前正在编写一个读取函数和一个写入函数,它们都检查是否buf
为NULL指针以及mode
变量是否在一定范围内。
这是代码重复。可以通过将其移入其自身的功能来解决。但是我应该吗?这将是一个非常贫乏的功能(不会做很多事情),而是局部化的(所以不是通用的),并且不能很好地独立运行(除非您知道它的位置,否则无法确定您的需求)用过的)。另一个选择是使用宏,但我想在这篇文章中谈谈功能。
那么,您应该使用类似这样的功能吗?优缺点都有什么?
Answers:
这是对函数的极大利用。
这将是一个非常贫乏的功能(不会做太多)...
非常好。函数只能做一件事。
相当本地化...
使用OO语言,将其设为私有。
(因此不是通用)
如果处理多个案件, 就是通用。而且,泛化不是函数的唯一用途。实际上,它们的存在是为了(1)避免您多次编写同一代码,而且(2)将代码分解成较小的块以使其更具可读性。在这种情况下,它既实现了(1)又实现了(2)。但是,即使仅从一个位置调用了函数,它也可能对(2)有所帮助。
并且不能很好地独立运行(除非您看到它的使用位置,否则无法弄清楚它的用途)。
为此起一个好名字,它本身就很好。“ ValidateFileParameters”之类的。现在靠自己很好。
因此,这完全应该是一个功能。
if (isBufferValid(buffer)) {
// ...
}
更具可读性和可维护性(如果检查逻辑发生更改,则只需在一个地方进行更改)。
此外,这类事情很容易内联,因此您甚至不必担心函数调用开销。
让我问你一个更好的问题。怎么做不是一个好习惯?
做正确的事。:)
return buffer != null;
那么我认为您正在那里损害可读性。
isBufferValid
(在我的书中)绝对比更具可读性buffer != null
,因为它可以更清楚地传达目的。再说一次,更不用说它在这里也可以避免重复。您还需要什么?
通常,最好使用函数来消除代码中的重复项。
但是,它可能太过分了。这是一个判断电话。
以您的空缓冲区检查为例,我可能会说以下代码很清楚,即使在某些地方使用了相同的模式,也不应将其提取到单独的函数中。
if (buf==null) throw new BufferException("Null read buffer!");
如果将错误消息作为通用null检查函数的参数包括在内,并且还考虑了定义该函数所需的代码,则用以下代码代替它不是节省净LOC的费用:
checkForNullBuffer(buf, "Null read buffer!");
另外,调试时必须深入研究该函数以查看其功能,这意味着该函数调用对用户而言不太“透明”,因此可以认为其可读性/可维护性较低。
集中代码通常总是一个好主意。我们必须尽可能地重复使用代码。
但是,重要的是要注意如何做到这一点。例如,当您具有执行compute_prime_number()或check_if_packet_is_bad()的代码时,这很好。很有可能功能性算法本身将会发展,这将是有益的。
但是,任何重复散文的代码都没有资格立即集中。这不好。您可能会在函数内部隐藏任意代码行,只是为了隐藏代码,随着时间的流逝,当应用程序的多个部分开始使用时,它们都必须与该函数的所有被调用方的需求保持兼容。
这是您应该问的一些问题
您所创建的函数是否具有其固有的含义,或者仅仅是几行?
哪个其他上下文需要使用相同的功能?在使用此功能之前,您是否可能需要稍微概括一下API?
当您引发异常时,对应用程序(不同部分)的期望是什么?
可以看到功能发展的场景是什么?
您还应该检查是否已经有类似的东西。我已经看到很多人总是倾向于重新定义其宏MIN,MAX,而不是搜索已经存在的宏。
本质上,问题是:“这个新功能真的值得重复使用吗?还是仅仅是复制粘贴?” 如果是第一个,那就去吧。
应该避免代码重复。每次您期望它时,都应避免代码重复。如果您没想到,请应用3的规则:在同一段代码重复3次之前重构,在重复2次后对注释进行注释。
什么是代码重复?
考虑以下示例:
if(user.getPrileges().contains("admin")) {
// Do something
}
变成
if(user.isAdmin()) {
// Do something
}
您改进了封装(现在可以透明地将条件更改为管理员)和代码的语义。如果以检查用户是否为管理员的方式发现了错误,则无需扔掉整个代码库并在任何地方进行修复(有放弃该代码并在应用程序中出现安全漏洞的风险)。
如果发现重复,则应该找到一种集中化方法。
函数是一种好方法(也许不是最好的方法,但这取决于语言)即使您所说的函数贫乏,也不意味着它会保持这种状态。
如果您还必须检查其他东西怎么办?
您是否要查找所有必须添加额外支票或仅更改功能的位置?