This lesson is for PRO members.

Unlock this lesson NOW!
Already subscribed? sign in

Refactoring: Polymorphic Functions

4:37 Angular 1.x lesson by

if-statements can add serious complexity and beg for refactoring. You can use polymorphic functions to simplify your ifs and dynamically call the appropriate method.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

Complex if-statements add a lot of complexity and beg for refactoring. You can use polymorphic functions to simplify your ifs and dynamically call the appropriate method.

Avatar
Benjamin

I feel like its a bit clearer to create a mapping of type/functions in an object:

{ "new release": "newReleaseCharge" }

Particularly useful when searching text in the app

Avatar
Krono-Safe

The problem here is with obfuscation, because methods' name will be transformed.

Avatar
chad

Really nice pointer on something that exists in nearly every code base. I think the "Strategy Pattern" is also at work here too. Could be an alternative metaphor for explaining how this pattern works. Also, Composition > Inheritance.

Today, I want to look at using polymorphism as a way to refactor. We're going to take our charge method here and we see that the logic for charging is actually based on the type of movie that we have. It's also, in part, based on the number of days rented. But that's a numeric argument that we can get passed in from the rental class if we want to.

This actually seems much more closely tied to the movie class, so we're going to move over there for right now and put it in here. Now we'll say the charge for a movie is a function that will take the days rented as an argument and we'll head back down here, close that off.

In a classical language, we would probably implement polymorphism through classes, but since JavaScript is a functional language, I think it would make more sense for us to implement polymorphism through functions.

Here we might have a regular charge method, we might have a new release charge method, days rented, and we do the same thing for our children's charge method. Here's what it would look like if we filled these in.

Now we actually have no more if/else statements, we have no more dealing with this amount. Instead, what we have to do is figure out how to call each particular method based on the name of the type that we have.

Out of the box, JavaScript is good at doing dynamic dispatch, which is where we figure out the name of the method to call it run time, but we're going to need to do some finagling with strings here to make sure we get it right.

I'm just hopping into a terminal here and we'll take an example like new release. What we want to do is to turn that into new release charge. That's going to be our end result. We want to make new release into a caramelized type thing, a camel case thing, and add charge to the end of that.

One way to do that is to call titles, which will transform this into a totally capitalized thing. We're going to split on the spaces, so we get an array. We'll join the array with no spaces, so now we get a bit closer. Now we're going to call caramelize here, so it will start as a lowercase.

Then we're just going to add charge, so that's basically the algorithm that we would need in order to always camel case this and find the name of the method. We'll bring this back in, return this dot type, calling all this fancy stuff on it.

We're going to dynamically dispatch it on this, so we're going to create that method name and then call it down here. We're going to pass in days rented and return that. Now we just need to move back to our rental and call returnthis.movie.charge and passing in this .daysrented.

If everything works, we should get passing tests. That's what we're expecting.

Let's do one final refactoring for this video. This is called introduce explaining method. The reason for that is because we want to make it easier to understand what's going on in this whole complex algorithm here.

Let's maybe call this the charge function name. This is going to just make the previous method that we wrote even easier to understand. We'll hop back up here and we'll call this .charge function name and this helps to understand that we have some kind of functional polymorphism going on here.

We improve the readability of the charge method here. Instead of this huge if/else block that was hard to understand because conditionals introduce a lot of complexity to the code, we differed to functional polymorphism, which is going to make our end goal a lot easier, which is making it easy to add new code.

That's what we want to do. We know that we're going to have some new movie types that we're going to get and it's going to be just as simple as adding a new method that computes the charge for that type of movie, when we do get those new movie types.

We're working toward our end goal here and really clarifying and simplifying a lot of the code that we have. That's it for this video, happy refactoring...

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?