在Java中,给定一对公共方法enableFoo和disableFoo,它们分别将名为isEnabledFoo的布尔字段设置为true或false,如果方法在设置之前检查Foo是否已经启用?如果是,是否应该抛出异常?如果是,是应该检查还是取消选中?如果不加以控制,应该扔什么? IllegalStateException异常?
扭曲:虽然当前实现只是设置一个布尔字段,但我故意不将它实现为一个带有布尔参数的setFoo“setter”方法,因为稍后可能会改变实现以包含副作用(甚至可能不会总之设置一个字段)。保持enableFoo / disableFoo似乎是保证封装的最佳方式。
我应该这样做:
public void enableFoo() throws myCheckedException
{
if (! this.isEnabledFoo)
{
this.isEnabledFoo = true;
}
// Is this overkill?
else
{
// Foo is already enabled...Should a checked exception be thrown?
throw new myCheckedException ("Foo is already enabled.");
// What about an unchecked exception?
// throw new IllegalStateException ("Foo is already enabled.");
}
}
或者只是这样:
public void enableFoo()
{
// I guess we don't care if foo is already enabled...
this.isEnabledFoo = true;
}
甚至:
public void enableFoo()
{
// Is this just code bloat?
if (! this.isEnabledFoo)
{
this.isEnabledFoo = true;
}
}
我认为虽然最后两个版本更简单,但它们会隐藏一个可能的错误,开发人员在调用enableFoo时认为它已被禁用,而实际上它已经启用了(但这真的很重要吗?)。这里最好的设计是什么?
答案 0 :(得分:4)
我真的不认为你的问题有答案。所有这些看起来都是有效的,这取决于你正在进行的操作以及操作后对象的一致状态。
例如:我有一个方法可以启用语法高亮显示,如果你选择启用它并且它已经启用你会关心什么。在这种情况下,您只需设置布尔标志,而不管先前的状态(选项2)。
另一方面,如果我不只是更改一个布尔字段,而是执行一些复杂的逻辑,这可能是重新运行的昂贵,例如浏览文档的DOM并为所有正确的位置着色我不会想要再次这样做只是因为某人“重新检查”了启用标志。
这样的事情:
public void enableHighlighting() {
if (!isHighlighting) {
isHighlighting = true;
colorView(); // very expensive method
}
}
现在让我们假设您有一个双重启用反映机器状态不一致的情况(类似于您使用assert
的情况。在这种情况下,您可能希望抛出异常来表示用户已执行此操作非法的东西。
例如,假设语法突出显示仅影响某些类型的文件(如XML或Java代码),并且用户尝试将其应用于PHP代码。现在突出显示已经启用,但受挫的用户尝试启用它,因为他没有看到任何更改。在这种情况下,您可能想要向用户打印消息,说明已启用突出显示。在这种情况下,更改是否发生的返回值可能更有意义,但您也可以使用异常。
返回值:
public boolean enableHighlighting() {
prevState = isHighlighting;
isHighlighting = true;
return prevState != isHighlighting; //return true if value changed
}
答案 1 :(得分:0)
不。你为什么要关心? enableFoo
和disableFoo
非常明确 - 一个启用,另一个禁用。无需检查当前状态。
如果你真的想要,可以返回一个表示先前状态的布尔值。您也可以使用public boolean isEnabled()
方法。
答案 2 :(得分:0)
没有直接答案。这取决于要求。具体而言,您的操作是否是幂等的。
答案 3 :(得分:0)
如果您的程序是多线程的,建议使用锁定启用和禁用功能,如果锁不是原子的,则检查可能会有所帮助。否则你不必担心检查状态。
答案 4 :(得分:0)
您可以使用 Facet 来启用/禁用功能。
<块引用>免责声明:我是该平台的作者之一
您可以将方面视为应用程序的所有方法。您可以在运行时启用/禁用方法。
如何整合:
implementation 'run.facet.agent.java:facet-agent:0.0.8'
facet.yml
:workspaceId: WORKSPACE~ID
name: My-Application
environment: dev
apiKey: API_KEY
注意:您可以从 Facet dashboard
获取这些密钥为了让您了解它与其他人提到的功能标志有何不同,您可以认为分面会自动应用于您的应用程序,而不是每次开发功能时都以编程方式声明。
注意:这还不是生产就绪的。很高兴与您一起解决问题!