是否有人不同意以下说法:“使用 switch 是糟糕的 OOP 风格"?

2022-01-19 00:00:00 oop switch-statement java

我已经看到它在 stackoverflow 上的多个线程/评论中编写,使用 switch 只是糟糕的 OOP 风格.我个人不同意这一点.

I have seen it written in multiple threads/comments on stackoverflow that using switch is just bad OOP style. Personally I disagree with this.

在很多情况下,您无法将代码(即方法)添加到要打开的 enum 类中,因为您无法控制它们,可能它们位于第 3 方 jar 文件中.在其他情况下,将功能放在枚举本身是一个坏主意,因为它违反了一些关注点分离的考虑,或者它实际上是其他东西的功能以及枚举.

There will be many cases where you cannot add code (i.e. methods) to enum classes you want to switch on because you don't control them, perhaps they are in a 3rd-party jar file. There will be other cases where putting the functionality on the enum itself is a bad idea because it violates some separation-of-concerns considerations, or it is actually a function of something else as well as the enumeration.

最后,开关简洁明了:

boolean investable;
switch (customer.getCategory()) {
    case SUB_PRIME:
    case MID_PRIME:
        investible = customer.getSavingsAccount().getBalance() > 1e6; break;
    case PRIME:
        investible = customer.isCeo(); break;
}

我并不是在为 switch 的每次使用辩护,也不是说它总是要走的路.但在我看来,像Switch 是一种代码味道"这样的说法是错误的.其他人同意吗?

I'm not defending every use of switch and I'm not saying it's always the way to go. But statements like "Switch is a code smell" are just wrong, in my opinion. Does anyone else agree?

推荐答案

跟进:

如果这只是希望获得商业贷款的客户的投资"逻辑怎么办.也许客户对另一种产品的可投资性决定真的很不同......另外,如果一直有新产品出现,每个产品都有不同的可投资性决定,我不想每次都更新我的核心客户类这是什么时候发生的?

还有你的一条评论:

我不完全确定将逻辑保持在它所操作的数据附近.现实世界不是这样运作的.当我申请贷款时,银行会决定我是否符合条件.他们不要求我自己做决定.

就目前而言,你是对的.

you are right, as far as this goes.

boolean investable = customer.isInvestable();

不是您所说的灵活性的最佳解决方案.但是,最初的问题没有提到存在单独的 Product 基类.

is not the optimal solution for the flexibility you're talking about. However, the original question didn't mention the existence of a separate Product base class.

鉴于现在可用的其他信息,最好的解决方案似乎是

Given the additional information now available, the best solution would appear to be

boolean investable = product.isInvestable(customer);

产品可根据您的真实世界"论点(多态性!)做出可投资性决策,并且它还避免了每次添加产品时都必须创建新的客户子类.产品可以根据客户的公共接口使用它想要做出该决定的任何方法.我仍然会质疑是否可以对客户界面进行适当的添加以消除切换的需要,但它可能仍然是所有弊端中最小的.

The investability decision is made (polymorphically!) by the Product, in accordance with your "real world" argument and it also avoids having to make new customer subclasses each time you add a product. The Product can use whatever methods it wants to make that determination based on the Customer's public interface. I'd still question whether there are appropriate additions which could be made to Customer's interface to eliminate the need for switch, but it may still be the least of all evils.

不过,在提供的特定示例中,我很想这样做:

In the particular example provided, though, I'd be tempted to do something like:

if (customer.getCategory() < PRIME) {
    investable = customer.getSavingsAccount().getBalance() > 1e6;
} else {
    investable = customer.isCeo();
}

我发现这比在 switch 中列出所有可能的类别更清晰、更清晰,我怀疑它更有可能反映现实世界"的思维过程(它们是否低于质数?"与它们是次质数还是mid-prime?"),并且如果在某个时候添加了 SUPER_PRIME 名称,它可以避免重新访问此代码.

I find this cleaner and clearer than listing off every possible category in a switch, I suspect it's more likely to reflect the "real world" thought processes ("are they below prime?" vs. "are they sub-prime or mid-prime?"), and it avoids having to revisit this code if a SUPER_PRIME designation is added at some point.

相关文章