在Interfaces中为接口方法的布尔参数设置常量是一种很好的做法还是代码味道?

时间:2017-05-30 07:26:28

标签: design-patterns parameters interface language-agnostic anti-patterns

所以我有以下界面:

public interface RoleService {
    boolean INCLUDE_DEACTIVE_OBJECTS = true;
    boolean EXCLUDE_DEACTIVE_OBJECTS = false;
    Set<? extends BaseBusinessObject> getOwnedBusinessObjectsOf(final Employee employee, final boolean includeDeactiveObjects);
}

在上层的某处,示例用法如下..

if (someCondition) {
    ownedBusinessObjects = roleService.getOwnedBusinessObjectsOf(employee, RoleService.INCLUDE_DEACTIVE_OBJECTS);
} else {
    ownedBusinessObjects = roleService.getOwnedBusinessObjectsOf(employee, RoleService.EXCLUDE_DEACTIVE_OBJECTS);
}

因此,我不是传递true(或false)等值,而是在我说INCLUDE_DEACTIVE_OBJECTS时阅读方法调用要容易得多。

但我不确定,这只是愚蠢吗?这是反模式还是代码气味或某种违反最佳做法的行为?

我认为这类似于以某种方式避免Magic Numbers,但它是否有用或者是否相当令人困惑?

5 个答案:

答案 0 :(得分:3)

因为这使API更具可读性,所以没关系。底层值是什么并不重要,重要的是你传递一个触发某种行为的标志。如果您选择的语言仅允许位置参数传递,那么这样的常量使得调用更具可读性。比较:

roleService.getOwnedBusinessObjectsOf(employee, RoleService.INCLUDE_DEACTIVE_OBJECTS);
roleService.getOwnedBusinessObjectsOf(employee, true);

“获取员工拥有的业务对象......什么?”没有人知道“true”在这里意味着什么,命名值要好得多。

另一种选择是当您选择的语言支持调用时命名参数(此处为Python)时:

roleService.getOwnedBusinessObjectsOf(employee, include_deactivated=True);

API应该在这里强制执行命名参数(再次:Python):

def getOwnedBusinessObjectsOf(employee, *, include_deactivated): ...

在Objective-C中,您可以使用显式方法命名执行类似的操作:

[roleService getOwnedBusinessObjectsOf:employee includingDeactivated:YES]

答案 1 :(得分:1)

在接口中放置常量字段绝对不好,IMO。我来自C#背景,它甚至不允许getOwnedBusinessObjectsIncludingInactive(...) getOwnedBusinessObjectsExcludingInactive(...) 中的const字段。即使在Java中,您也有Constant Interface(反模式),其唯一目的是包含多个类可以共享的常量。你并不完全是那样做的。仍然只是参考。

  

所以不要传递诸如true(或false)之类的值,我相信它是   我说的时候,更容易阅读方法调用   INCLUDE_DEACTIVE_OBJECTS

选项1

要在保持可读性的同时替换常量,你可以定义2个方法,这些方法表明是否有效(我会选择'非活动'而不是。它有取消激活动词但没有反应形容词)对象。

RoleService

这些只是private类中的包装方法,true分别通过传递falsegetOwnedBusinessObjectsOf(employee, Constants.INCLUDE_INACTIVE_OBJECTS) getOwnedBusinessObjectsOf(employee, Constants.EXCLUDE_INACTIVE_OBJECTS) 来调用检索实际数据的方法。

选项2

有一个单独的类在一个地方定义应用程序级别常量。

WHERE

答案 2 :(得分:0)

任何采用布尔参数的方法都违反了单一责任原则,因为它为true做了一件事,对于false做了第二件事。

这总是代码味道。 Clean Code告诉我们将方法拆分为两个:

  1. getOwnedBusinessObjectsIncludingDeactiveObjectsOf(Employee employee);

  2. getOwnedBusinessObjectsExcludingDeactiveObjectsOf(Employee employee);

  3. 当然,如果要广泛使用该方法,您可能需要更简洁的名称,例如: getAllObjectsgetActiveObjects

答案 3 :(得分:0)

如果您不想在常量命名中使用具有相反含义的词,则还可以尝试将布尔值包装到枚举中。

public interface RoleService {

    /**
    * Boolean wrapper for easy reading of values in method parameters.
    */
    enum IncludeDeactiveObjects {

        TRUE(true),
        FALSE(false);

        private final boolean flag;

        private IncludeDeactiveObjects(boolean flag) {
            this.flag = flag;
        }

        public boolean get() {
            return flag;
        }
    }

    Set<? extends BaseBusinessObject> getOwnedBusinessObjectsOf(final Employee employee, final IncludeDeactiveObjects includeDeactiveObjects);
}

电话为:

roleService.getOwnedBusinessObjectsOf(employee, RoleService.IncludeDeactiveObjects.TRUE);
roleService.getOwnedBusinessObjectsOf(employee, RoleService.IncludeDeactiveObjects.FALSE);

答案 4 :(得分:-1)

如果只是为了可读性,在抽象类中,您可以使用静态变量来保存这些布尔值,并且可以使用ClassName.AttributeName分配

public YourClass
{
    public bool static INCLUDE_DEACTIVE_OBJECTS = true;
    public bool static EXCLUDE_DEACTIVE_OBJECTS = false;

    public static void Main (String args[])
    {

    }
}