Sunday, January 15, 2012

Lesson 4: Introducing classes

Suppose we have one state-of-the-art html content representing 5 colorful frogs sitting on a big leaf: Ok, the markup is bulky, but it still looks great, right?
We could select those divs and put them into variables like 'frog1', 'frog2' etc, but we're no kids anymore. Instead, we put them in one place, and use some cool techniques at the same time!

The first line enumerates the integer range [0..4] and for every n creates an id selector via string interpolation (yep, that #{n} in "#ani3_bar#{n}" puts in a value ). 5 query results are collected and stored to 'bars' variable. Lookup Loops and Comprehensions for more. Short and readable, but it makes 5 id queries instead of one. If we were obsessed with execution speed, that would be bad, so there's a line with a single query too.
Same form of iteration over an array to change every element's attributes. From now on I'm going to omit some usual stuff, like that line '$j=jQuery' at the beginning of every script, but you know it's there :)

Now we know how to define functions, let's be nice and provide our frogs with capability to jump around. Check out the four functions' different syntax, meaning totally the same. Pick the flavor that suits you at the moment. Good. Now unleash the frog!
Wow! It surely is enjoyable to see it frolick. But does it go the right way?
Our jumping functions are stackable, cause they accept and return jQuery objects. That's the good part. But the frog goes doesn't start with 'left down right' as somebody less experienced with operations priority concept may expect from our click handler code. The first effective call is on the right, the string should be read like this:

left(down(right(right(up(up(left(left(down(right(bars2[4]))))))))))

We just drop the brackets for the obvious reasons ( like because we can ).

Would be nice to have directed jump functions behaving like jQuery animate(), being able to append function calls next to each other and seeing them execute in the same order. For that we need them to return something that also has all four functions inside. ( Instance methods instantly come to my mind, what do you think? )

Normally, using just JavaScript, to get many objects behave uniformly we'd need to understand how JS prototypes work. Blessed are those who do. I still find that somewhat tricky. But today we can relax and do it the good old OOP way - define a class. And once again, we'll write less code for that!
CS classes documentation, just a friendly reminder :)

Ok, lets do it:

Wait, that's not cool. All we did is was wrapping functions code with a class declaration. Yes, we got something by this: now we can queue our jumps more naturally, like
frog.right().down().left() etc.
But that's just not cool enough. There are reasons to change it:

  • Code duplication. Four very similar lines of code, with the only defference in animate() arguments.
  • The main asset of every instance is created outside and gets inside as a constructor argument. But, unlike proper decorator implementations, class code relies on the assumption that animated objects are made just the way the class needs to work, without checking it. The class is unseparable from html outside - every time one is updated, the other has to be re-checked.
  • Methods could accept path length. Much gain easily with our new OOP powers.

To git rid of duplication, let's put all the repeated code in one method, say 'jump', that will accept direction as argument and use predefined arguments for animate(). A key-value map with 'r','l','u','d' for keys should do fine. Then we add another argument to the new jump methods and put animation logic in a loop. Then transform right,left, up and down into convenience methods, each of them now calls jump with proper direction argument. Done.

Next - the constructor. Let it accept what varies in those html lines declaring frogs' bodies and inject it into a static html line with string interpolation, then use jQuery to create new element from html, then append it to a container ( another div in our case - the square green leaf ) and store it as the only variable of the newly created class instance. Done. The whole block of html lines flattens to just one, letting us concentrate on frogs' color and position.

Looks a bit different:

Let's see if it works.

Not bad. Readable set of just 4 instructions for each unit, predictable result. In fact, they are so perfectly organized one may even think they are not free-minded lively frogs, but programmed robots!

On the other hand, to heck with direction-named methods, compact path strings are the best for a case like this. Look at this:

One character per jump - and still readable. Next would be programming in absolute code! (Just kidding)

Time to stop - it's a bit overdone already. Of course, we love these frisky little creatures, but now it's time to move on to the next adventure!

Source code links:

No comments :

Post a Comment