Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphism vs if and logic

class Person { 
  private state ="normal" //cripple

  run() { 
    if (this.state === "normal") { 
      console.log("run")
    } else {
      console.log("hobble")
    }
  }
}


//vs

abstract class AttemptRun { 
  abstract run();
}


class NormalRun extends AttemptRun { 
  run() { 
    console.log("run")
  }
}

class CrippleRun extends AttemptRun { 
  run() { 
    console.log("hobble")
  }
}

class Person { 
  protected runAbility: AttemptRun;

  run() { 
    this.runAbility.run()
  }
}

Assuming that I understood the concept here is my question. Why is polymorphism better than if and logic.

Because it seems to me you will still need a factory or another method to set the type of person's ability. So if the logic is not here it's going to be somewhere else.

Why is this repeated some much in books i read, like clean code. It's listed as a code smell.

I feel like it can make unit test a little bit easier because then you only test the abilities and you don't need to test the actual other class that is using it.

Is that all it has to offer.

An if/else and not you need to write a different class and a factory? Hardly seems fair?

Perhaps it's more work but in the long run, it will be better.

What are the weaknesses of each case?

Is this something you would do if it's a small class? Basically, I don't know if I understand the concept, and then assuming i do. How practical is it to use.

A wise developer might use it only when they need something specific. I don't know any of the specifics.

like image 311
Lpc_dark Avatar asked Nov 20 '17 22:11

Lpc_dark


1 Answers

There's a couple of things about your simple example that don't demonstrate the benefits of the polymorphic approach.

In your case there's just one if statement (in run), just 2 variations of person, and the behaviour in each case is very similar (they both just log some text).

Consider a larger case where you've got more functionality though. If you add an attemptToDance you'd introduce a new if/else block, if you add other variation of person all your functions need a new if or case in the existing functions. As you add more functionality you end up with many cases in many if/else blocks, and there's no way the compiler can verify for you that you haven't missed one of the person types in of the if cases.

Catching errors with unit tests is great, but choosing a design that makes the error impossible is even better - the compiler never misses things like that, and you know the compiler ran and worked (you hope the unit tests were run successfully - but you're never quite as certain)

If you have an abstract base class defining an interface that all types of person implement, then the compiler will tell you if you fail to implement one of the methods for one of the derived person classes.

In a larger, real case, the implementation of each method on each type of person can and probably will vary more than just outputting different text. if these stay in an if case, all that different functionality ends up in one place, you have code that depends on many things at once, this makes testing and maintenance harder. If the people classes have state such that the methods interact, this complicates things even more, and polymorphism allows you to wrap up that behaviour in a class, without that class needing to concern itself with the other types of person class.

In the simple case the if/else version works, it just doesn't scale very well in many cases.

You may still need an if/else or switch in a factory method somewhere, but one switch that's just responsible for construction is easier to maintain than many switches or if blocks.

like image 127
ROX Avatar answered Dec 09 '22 17:12

ROX