【问题标题】:Method signature best practices - overloading vs. long name方法签名最佳实践 - 重载与长名称
【发布时间】:2014-11-20 09:01:21
【问题描述】:

只是想知道您对这两种不同的方法有何看法:重载方法与冗长/冗长的方法名称。

更新:我正在寻找一般模式/最佳实践。以下只是一个示例。

给定具有父/子关系的组织结构

> OrgUnit
> - OrgUnit
> -- OrgUnit
> -- OrgUnit

两种方法在很大程度上使用相同的代码来获取 xml 元素的子元素。

// 1) only 1 level down children
getSubOrgUnits()

// 2) all levels down
getSubOrgUnits(boolean includeChildren)

// 3) alternative naming of 1)
getDirectSubOrgUnits()

// 4) alternative naming of 2)
getAllSubOrgUnits()

所以 1 和 2 正在使用参数 而 3 和 4 是使用无参数命名。

你会去做什么,为什么?还要考虑到 1) 和 2) 可以获得额外的参数,这会导致诸如 getChilds(true,false,null) 之类的东西,但 3) 和 4) 可能会获得像 getDirectSubUnitsExcludeSome() 这样的名称

可以是特定于 JAVA 的,但对此有更广泛的看法是值得赞赏的。

【问题讨论】:

    标签: java language-agnostic naming-conventions overloading


    【解决方案1】:

    在我看来,使用详细的方法名是一个更好的解决方案。

    • 更容易理解,您的代码将需要更少的 cmets
    • 它更易于维护,您可以在不影响现有签名的情况下更改实现。您仍然可以添加新签名,无需回归。

    但要小心,在某些情况下最好添加一些参数

    示例 1

    private List<Element> getElementsByType(MyTypeEnum type);
    
    public List<Element> getElementsOfType1();
    public List<Element> getElementsOfType2();
    public List<Element> getElementsOfType3();
    
    /* VS */
    
    public List<Element> getElementsByType(MyTypeEnum type);
    

    两种实现都很好,这取决于您,取决于MyTypeEnum 的大小,取决于它增加大小的能力。你想暴露什么?你想让getElements***的调用者能够得到Element的所有类型吗?

    示例 2

    public void log(Level l, String s, Exception e);
    
    /* VS */
    
    public void logInfo(String s);
    public void logWarning(String s);
    public void logError(String s, Exception e);
    

    在这种情况下,第二部分更好。因为它更具可读性,第一眼就容易理解。并且因为在登录INFO 和WARNING 级别时,不需要指定Exception。所以专门化方法是好事。但是,将方法 public void log(Level l, String s, Exception e); 保持为公共而不是私有很重要,因为在某些情况下使用此通用方法可能很有用。

    结论

    这确实取决于具体情况,但如果您有可能添加具有详细名称、专门针对目标行为的特定方法,请执行此操作。

    【讨论】:

    • 很好的答案,也很好 来自真实用例的日志记录示例。谢谢。
    • 我不同意。我会单独写一个回复。
    【解决方案2】:

    这一切都归结为味道。

    作为一般做法,您可以选择“参数越少越好”。它在代码清晰性方面既方便又实际上节省了堆栈内存(不多,但从长远来看,每一点都很重要)。

    使用不同的名称也有助于自动完成分配。

    例如我会去

    GetAllSubOrgUnitsList()
    GetFirstSubOrgUnitsList()
    

    之所以这样,在get之后,我写的第一个字母就说明了我想要什么。

    正如你所说,如果你不能有一个直观的名字,你可以添加默认参数。

    在你的例子中,

    GetDirectSubUnitsExcludingSome()
    

    我会用最少的参数集替换它

    GetFilteredSuborgUnits(ISuborgFilter aFilter);
    

    然后,从架构中要求开发人员实现他们的自定义过滤器。 过滤器可以要求提供层次结构深度、特定所有权等(您是架构师,由您决定)。

    所以,作为一个简短的总结:KISS!

    即使 GetAllSuborgUnits() 将提供与 GetFilteredSubOrgUnits(null) 相同的功能,为行为提供快速而清晰的替代方案也比使用复杂的名称/参数集更好。毕竟,裁员并不总是一件坏事:)。

    【讨论】:

    • 我选择 ToYonos 的答案是因为他给出了更好的例子。 filter 参数是一个好主意,但在另一个答案中也包含一个枚举。非常感谢。
    • 没问题,很乐意提供帮助。
    【解决方案3】:

    我不同意更长的名字是更好的方法。

    它确实“依赖”,但让我们澄清一下:

    • 两个实现相同的方法,但采用不同的选项,恕我直言,它们应该具有相同的名称(被重载)。
    • 两种做不同事情的方法(除了确定的 通过参数)应该有不同的名字。换句话说,有 应该是通用 function 的一个名称(尽管有变体), 并为不同的功能分别命名。

    值得注意的是,重载是 JRE 中使用的几乎统一的做法。

    我发现在实际使用中较长的名称没有什么优势。授予:

     getSubOrgUnits()
    

    比:

     getSubOrgUnits(true)
    

    如果我将它包含在正式的 API 中,我会给它们单独的名称,或者将第二个名称作为常量:

     getSubOrgUnits(INCLUDE_SUB_UNITS)
    

    尽管大多数 IDE 允许您通过将鼠标悬停在方法上立即看到 true 参数是如何解释的(这通常会在弹出窗口中显示 Javadoc)。

    对我来说,重载的优点是它使变体的正式关联。它也是 Javadocs 中更好的表示形式。

    【讨论】:

      【解决方案4】:

      处理这种结构的通常方式是:

      // Used when you KNOW there is only one child.
      getFirstChild();
      // Used when there may be many children.
      getChildren();
      

      这是 XOM getChildElements 和 getFirstChildElement 用于遍历 XML 文件结构的模式。

      您可以随时使用:

      thing.getFirtsChild().getChildren();
      

      进入更深层次。

      【讨论】:

      • 我正在寻找更通用的模式/最佳实践。我不知何故有一种感觉,“旧”Java库大量使用带有do(boolean activateX,boolean activateY,int someParam)的方法重载,这可能导致您必须阅读源代码的do(boolean,boolean,int)之类的签名(你必须拥有它;))-“较新”的库更像 doWithXAndY(int param)-希望我能说清楚。
      • 文档是关键,当涉及到有很多参数的方法时。当你为每一个论点引入一种新方法时,这并不能改善事情。您将拥有许多带有很少参数的方法,而不是拥有一个带有许多参数的方法。你只是在转移问题。
      【解决方案5】:

      首先,我将该方法称为getChildren(),而不是getChilds()。 :)

      如果您有多个级别,为什么不引入深度级别的参数?

      // Get children up to depthLevel
      getChildren(final int depthLevel)
      
      // For convenience
      getChildren()
      

      如果是无参数方法,请添加有意义的信息,以便其他开发人员知道您是返回全部还是仅返回第一级。


      编辑: OP 问:“那么总的来说,您使用什么方法,为什么,哪些用例?您能否分享一下您对此的想法。” p>

      这是非常基于意见的。正如@OldCurmudgeon 所说,许多处理树状结构的库使用专用方法来访问下层。这很好,只要你经常这样做。另一方面,如果您想访问结构的特定级别,则引入depthLevel 参数会为您提供更多功能。这在很大程度上取决于您通常的用例。

      因此,如果您很可能需要经常获取对象的第一个孩子,请引入getFirstChild() 和getChildren()。如果您更有可能更频繁地访问更深层次的数据,或者您需要访问专用级别,请引入深度参数。

      【讨论】:

      • 嗨,谢谢。我更新了问题。所以一般来说你使用什么方法,为什么,哪些用例?你能分享一下你对此的看法吗?
      • 我在回答中添加了更多信息。但是,基于选项的问题在这里不受欢迎,所以要小心,否则你的问题可能会被关闭。
      猜你喜欢
      • 2019-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多