Does anyone disagree with the statement: “using sw

2019-02-02 03:57发布

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

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.

Last of all, switches are concise and clear:

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

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?

22条回答
SAY GOODBYE
2楼-- · 2019-02-02 04:15

Sure switches are poor OO, you shouldn't put a return in the middle of a function, magic values are bad, references should never be null, conditional statements must go in {braces}, but these are guidelines. They shouldn't be followed religiously. Maintainability, refactorability, and understandability are all very important, but all second to actually getting the job done. Sometimes we don't have time to be a programming idealist.

If any programmer is to be deemed competent, it should be assumed he can follow guidelines and use the tools available with discretion and it should be accepted that he will not always make the best decision. He may choose a less-than-optimal route or make a mistake and run into a hard-to-debug problem because he chose a switch when maybe he shouldn't have or passed around too many null pointers. That's life, and he learns from the mistake, because he is competent.

I don't religiously follow programming dogma. I consider guidelines in the context of myself as a programmer and apply them as seems reasonable. We shouldn't harp on these sorts of programming practices unless they are fundamental to the problem at hand. If you want to assert your opinion on good programming practices, it's best to do so in a blog or an appropriate forum (such as right here).

查看更多
Ridiculous、
3楼-- · 2019-02-02 04:18

I find nothing wrong with using the switch statement in OO code. My only criticism is that I would have made a new method on Customer called IsInvestible which hid this logic. There is 0 wrong with using an switch statement as the internal implementation of this method. As you've said you can't add methods to enum's but you can add more methods to Customer.

In the case you don't have access to the source, I'd say a non-instnance method is fine. An OOP purest would require a brand new object but that seems like it may be overkill in this case.

查看更多
我命由我不由天
4楼-- · 2019-02-02 04:19

I think statements like

Using a switch statement is bad OOP style.

and

Case statements can almost always be replaced with polymorphism.

are oversimplifying. The truth is that case statements that are switching on type are bad OOP style. These are the ones you want to replace with polymorphism. Switching on a value is fine.

查看更多
淡お忘
5楼-- · 2019-02-02 04:20

My issue with switch statements is that in real world application there are rarely switch statements that exist in isolation.

A lot of the code that required refactoring in my company's codebase would have entire classes riddled with multiple switch statements throughout such that you had to know of the existence of every single switch statement.

Ultimately, the cleanest refactoring the entire system into a Strategy pattern with a Factory controlling the creation of the strategies based on the single remaining copy of the switch statement.

Due to time constraints we didn't take it any farther because this served our needs. There was still a big giant switch statement, but there was only one, so adding additional strategies only required ipmlementing the interface and adding the creation step to the master switch statement.

查看更多
\"骚年 ilove
6楼-- · 2019-02-02 04:25

I do believe switching on type is a code smell. However I share your concerns about separation-of-concerns in code. But those can be solved in many ways that allow you to still use polymorphism, e.g. the visitor pattern or something similar. Read up on "Design Patterns" by the Gang of Four.

If your core objects like Customer stays fixed most of the time but operations change often, then you can define operations as objects.

    interface Operation {
      void handlePrimeCustomer(PrimeCustomer customer);
      void  handleMidPrimeCustomer(MidPrimeCustomer customer);
      void  handleSubPrimeCustomer(SubPrimeCustomer customer);    
    };

    class InvestibleOperation : public Operation {
      void  handlePrimeCustomer(PrimeCustomer customer) {
        bool investible = customer.isCeo();
      }

      void  handleMidPrimeCustomer(MidPrimeCustomer customer) {
        handleSubPrimeCustomer(customer);
      }

      void  handleSubPrimeCustomer(SubPrimeCustomer customer) {
        bool investible = customer.getSavingsAccount().getBalance() > 1e6;    
      }
    };

    class SubPrimeCustomer : public Customer {
      void  doOperation(Operation op) {
        op.handleSubPrimeCustomer(this);
      }
    };

   class PrimeCustomer : public Customer {
      void  doOperation(Operation op) {
        op.handlePrimeCustomer(this);
      }
    };

This looks like overkill, but it can easily save you a lot of coding when you need to handle operations as collections. E.g. display all of them in a list and let user select one. If operations are defined as functions you easily end up with a lot of hard coded switch-case logic, multiple places which needs to be update each time you add another operation, or product as I see it referred to here.

查看更多
仙女界的扛把子
7楼-- · 2019-02-02 04:25

I view switch statements as a more readable alternative to if/else blocks.

I find that if you can boil down your logic to a structure that can be evaluated integrally, the code is likely to be providing a level of encapsulation that is required in OOP.

At some point real (messy) logic has to be written for a practical program to ship. Java and C# are not strictly OOP languages, given that they inherit from C. If you want to enforce strictly OOP code, then you'll need to use a language that does not provide idioms which violate that mindset. My view is that both Java and C# are intended to be flexible.

One of the things that made VB6 so successful, oddly enough, is that it was Object-based, not Object-oriented. So, I would say that pragmattic programmers will invariably combine concepts. Switch can also lead to more manageable code, as long as there is decent encapsulation already programmed in.

查看更多
登录 后发表回答