3

检查:http ://checkstyle.sourceforge.net/config_design.html#DesignForExtension

误报:Checkstyle“方法不是为扩展设计的”错误被错误地发出? checkstyle 方法不是为扩展而设计的 - 需要是抽象的、最终的或空的 https://sourceforge.net/p/checkstyle/bugs/688/

看起来像所有在其配置中检查关闭的开关。

有没有人可以展示这个检查有用的真实代码示例?它在实践中对开发人员有用,而不是在理论上有用吗?

4

2 回答 2

3

您链接到的文档已经解释了检查背后的理由。这在某些情况下很有用。在实践中,我从来没有打开过它,主要是因为它管理起来太麻烦了,而且你当然不希望在所有课程中都使用它。

但是您要求提供代码示例。考虑这两个类(YourSuperClass是您提供的 API 的一部分,TheirSubClass由您的 API 的用户提供):

public abstract class YourSuperClass
{
    public final void execute() {
        doStuff();
        hook();
        doStuff();
    }

    private void doStuff() {
        calculateStuff();
        // do lots of stuff
    }

    protected abstract void hook();

    protected final void calculateStuff() {
        // perform your calculation of stuff
    }
}


public class TheirSubClass extends YourSuperClass
{
    protected void hook() {
        // do whatever the hook needs to do as part of execute(), e.g.:
        calculateStuff();
    }

    public static void main(final String[] args) {
        TheirSubClass cmd = new TheirSubClass();
        cmd.execute();
    }
}

在这个例子中,TheirSubClass不能改变工作方式execute(做事,调用钩子,再做事)。它也不能改变calculateStuff()方法。因此,YourSuperClass它是“为扩展而设计的”,因为TheirSubClass它不能破坏它的运行方式(就像它可能一样,如果execute()不是这样的话final)。的设计者YourSuperClass保持控制,只提供特定的钩子供子类使用。如果hookabstractTheirSubClass则强制提供一个实现。如果是单纯的空方法,TheirSubClass可以选择不使用钩子。

CheckstyleCheck是一个为扩展而设计的类的真实示例。具有讽刺意味的是,它仍然无法通过检查,因为getAcceptableTokens()ispublic但 not final

于 2013-11-14T22:41:17.883 回答
0

我为所有基于 Spring 的项目启用了此规则。起初它是一个皇家 PITA,因为它确实代表了很多代码清理。但我已经学会了热爱这条规则的原则。我发现该规则有助于强制每个人在思考哪些类应该为扩展而哪些不应该设计时保持一致和清晰。在我使用过的代码库中,实际上只有少数几个类应该对扩展开放。大多数只是通过允许扩展来询问错误。也许不是今天,但是在当前工程师早已离开或忘记那段代码并且需要快速更改以解决“X客户抱怨Y而他们只需要Z”的道路上。

考虑:

  1. 在 Java 中随意对任何东西进行子类化太容易了,因此行为会随着时间的推移通过不同的扩展类而改变。新程序员可能会对 OOP 感到满意,然后一切都扩展了一些通用的东西,因为他们可以。

  2. 过度扩展的类深度很难推理,虽然你可能是一个了不起的开发人员,他永远不会做如此残忍的事情......我曾在代码库中工作过,这是常态。并且那些深度嵌套的 HTML 表单生成器使用起来很糟糕,并且无法推断实际会发生什么。因此,理论上,这条规则会让最初的工程师三思而后行,为他们的同行编写如此糟糕的东西。

  3. 通过执行最终规则或记录为扩展而设计的类,可以避免因无意扩展类而可能发生的错误。我个人不喜欢某些子类可能会改变我的应用程序行为的想法,因为这可能会以奇怪的方式导致意外的副作用(尤其是大型和部分测试的应用程序)。而且,正是在这些隐藏复杂行为的扩展类中,存在难以解决的错误。

  4. DesignForExtension 规则会强制开发人员之间进行对话,只要可以将某些内容作为初始选择进行扩展,以便在真正应该发生的情况是开发人员需要见面并讨论正在发生的变化,并讨论为什么扩展可能是合适的. 很多时候,修改主类更合适,并且会根据新情况编写额外的测试。这种对话的促进对于长期的代码质量和组织内的知识共享是健康的。

话虽如此,我确实在我的代码中为无法声明为 final 的特定于 Spring 的类添加了我的 checkstyle-suppressions.xml。因为,框架。

<suppress checks="DesignForExtension" files=".*Configuration\.java"/>
于 2022-01-06T18:33:00.793 回答