对于接口方法的布尔参数,在接口中使用常量是一种好的做法还是代码味道?
Is having Constants in Interfaces for boolean parameters of Interface methods a good practice or code smell?
所以我有以下界面:
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);
}
因此,我相信当我说 INCLUDE_DEACTIVE_OBJECTS
.[=16= 时,比传递 true
(或 false
)这样的值更容易阅读方法调用]
但我不确定,这是不是很愚蠢?这是反模式、代码异味还是某种违反最佳实践的行为?
我认为这类似于以某种方式避免 Magic Numbers,但它有用还是相当混乱?
因为这使 API 更具可读性,所以很好。潜在价值是什么并不重要,重要的是您传递一个触发特定行为的标志。如果您选择的语言只允许位置参数传递,那么这样的常量会使调用更具可读性。比较:
roleService.getOwnedBusinessObjectsOf(employee, RoleService.INCLUDE_DEACTIVE_OBJECTS);
roleService.getOwnedBusinessObjectsOf(employee, true);
"Get owned business objects of employee… what?" 没有人知道“true
”在这里是什么意思,命名的值要好得多。
另一种选择是当您选择的语言支持调用时命名参数(此处,Python):
roleService.getOwnedBusinessObjectsOf(employee, include_deactivated=True);
API 应在此处强制执行命名参数(再次:Python):
def getOwnedBusinessObjectsOf(employee, *, include_deactivated): ...
在 Objective-C 中,您将使用显式方法命名做类似的事情:
[roleService getOwnedBusinessObjectsOf:employee includingDeactivated:YES]
IMO,将常量字段放在接口中肯定是不好的。我来自 C# 背景,它甚至不允许 Interface
中的 const 字段。即使在 Java 中,您也有 Constant Interface(又是反模式),其唯一目的是包含多个 classes 可以共享的常量。你不完全是在做那些事情。仍然只是参考。
So instead of passing values such as true (or false), I believe it is
much easier to read the method call when I say
INCLUDE_DEACTIVE_OBJECTS
选项 1
要在保持可读性的同时替换常量,您可以定义 2 个方法来指示是否包含停用对象(我会选择 'Inactive'。有停用动词但没有停用形容词)对象。
getOwnedBusinessObjectsIncludingInactive(...)
getOwnedBusinessObjectsExcludingInactive(...)
这些只是 RoleService
class 中的包装方法,private
通过传递 true
或 false
调用方法来检索实际数据分别。
选项 2
有一个单独的 class 在一个地方定义应用程序级常量。
getOwnedBusinessObjectsOf(employee, Constants.INCLUDE_INACTIVE_OBJECTS)
getOwnedBusinessObjectsOf(employee, Constants.EXCLUDE_INACTIVE_OBJECTS)
如果只是为了可读性,在你的摘要中class,你可以用静态变量来保存这些布尔值,你可以用ClassName.AttributeName
赋值
public YourClass
{
public bool static INCLUDE_DEACTIVE_OBJECTS = true;
public bool static EXCLUDE_DEACTIVE_OBJECTS = false;
public static void Main (String args[])
{
}
}
任何采用布尔参数的方法都违反了单一职责原则,因为它为 true 做一件事,为 false 做第二件事。
这总是一种代码味道。 Clean Code 告诉我们将方法一分为二:
getOwnedBusinessObjectsIncludingDeactiveObjectsOf(Employee employee);
getOwnedBusinessObjectsExcludingDeactiveObjectsOf(Employee employee);
当然,如果要广泛使用该方法,您可能需要更简洁的名称,例如getAllObjects
和 getActiveObjects
.
如果您不想在常量命名中使用含义相反的词,您也可以尝试将布尔值包装到枚举中。
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);
所以我有以下界面:
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);
}
因此,我相信当我说 INCLUDE_DEACTIVE_OBJECTS
.[=16= 时,比传递 true
(或 false
)这样的值更容易阅读方法调用]
但我不确定,这是不是很愚蠢?这是反模式、代码异味还是某种违反最佳实践的行为?
我认为这类似于以某种方式避免 Magic Numbers,但它有用还是相当混乱?
因为这使 API 更具可读性,所以很好。潜在价值是什么并不重要,重要的是您传递一个触发特定行为的标志。如果您选择的语言只允许位置参数传递,那么这样的常量会使调用更具可读性。比较:
roleService.getOwnedBusinessObjectsOf(employee, RoleService.INCLUDE_DEACTIVE_OBJECTS);
roleService.getOwnedBusinessObjectsOf(employee, true);
"Get owned business objects of employee… what?" 没有人知道“true
”在这里是什么意思,命名的值要好得多。
另一种选择是当您选择的语言支持调用时命名参数(此处,Python):
roleService.getOwnedBusinessObjectsOf(employee, include_deactivated=True);
API 应在此处强制执行命名参数(再次:Python):
def getOwnedBusinessObjectsOf(employee, *, include_deactivated): ...
在 Objective-C 中,您将使用显式方法命名做类似的事情:
[roleService getOwnedBusinessObjectsOf:employee includingDeactivated:YES]
IMO,将常量字段放在接口中肯定是不好的。我来自 C# 背景,它甚至不允许 Interface
中的 const 字段。即使在 Java 中,您也有 Constant Interface(又是反模式),其唯一目的是包含多个 classes 可以共享的常量。你不完全是在做那些事情。仍然只是参考。
So instead of passing values such as true (or false), I believe it is much easier to read the method call when I say INCLUDE_DEACTIVE_OBJECTS
选项 1
要在保持可读性的同时替换常量,您可以定义 2 个方法来指示是否包含停用对象(我会选择 'Inactive'。有停用动词但没有停用形容词)对象。
getOwnedBusinessObjectsIncludingInactive(...)
getOwnedBusinessObjectsExcludingInactive(...)
这些只是 RoleService
class 中的包装方法,private
通过传递 true
或 false
调用方法来检索实际数据分别。
选项 2
有一个单独的 class 在一个地方定义应用程序级常量。
getOwnedBusinessObjectsOf(employee, Constants.INCLUDE_INACTIVE_OBJECTS)
getOwnedBusinessObjectsOf(employee, Constants.EXCLUDE_INACTIVE_OBJECTS)
如果只是为了可读性,在你的摘要中class,你可以用静态变量来保存这些布尔值,你可以用ClassName.AttributeName
赋值public YourClass
{
public bool static INCLUDE_DEACTIVE_OBJECTS = true;
public bool static EXCLUDE_DEACTIVE_OBJECTS = false;
public static void Main (String args[])
{
}
}
任何采用布尔参数的方法都违反了单一职责原则,因为它为 true 做一件事,为 false 做第二件事。
这总是一种代码味道。 Clean Code 告诉我们将方法一分为二:
getOwnedBusinessObjectsIncludingDeactiveObjectsOf(Employee employee);
getOwnedBusinessObjectsExcludingDeactiveObjectsOf(Employee employee);
当然,如果要广泛使用该方法,您可能需要更简洁的名称,例如getAllObjects
和 getActiveObjects
.
如果您不想在常量命名中使用含义相反的词,您也可以尝试将布尔值包装到枚举中。
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);