A "controller" class? How to design really complex functionality.

8 views
Skip to first unread message

Ryan Florence

unread,
Nov 4, 2009, 4:09:45 PM11/4/09
to MooTools Users
Most public facing websites I do are pretty basic, with a handful of
unrelated classes instantiated (a gallery, some menu navigation, maybe
some ajax fun). You know, a fancy "brochure" website.

But when developing web applications I've ended up either created a do-
everything-class that has tens if not hundreds of methods; or
splitting up each piece of the page into separate classes with a lot
of events used to communicate with each other.

The do-everything-class just feels wrong.

10-20 classes on a page with all sorts of `onWhatever` functions makes
a mess out of my domready code.

Is there a happy medium? Like a "controller" class?

So I'd instantiate all the classes, and then pass them in to the
controller class and from there define how and when they communicate
with each other?

Simple Example to better illustrate the concept:

A photo gallery has
1) a carousel full of thumbnails with next and previous buttons
2) and an image viewer that loads an image, zooms in and zooms out.

When a thumbnail is clicked, the image viewer should load the image.

In the end will be some theoretical methods:
- loadImage
- next
- previous
- zoomIn
- zoomOut

I could either
1) create a single class that does everything or
2) have a class for the image viewer with loadImage, zoomIn, and
zoomOut, and then a carousel class with an onSelect event, used to
send a message to the viewer class to load the correct image.

I'm currently doing number 2 on a project but all the onWhatevers are
starting to drive me nuts and I'm tempted to go back to a do-
everything class. But I just thought about creating a class to handle
all the communication between my classes. So I could just pass in the
two class instances (carousel and image viewer) to the controller
class and then define inside there what to do onSelect of a thumbnail.

Is that making sense? Again, the photo viewer is a simple example to
illustrate a problem. I don't need any links to good photo viewers.
Any tips, articles, thoughts?

Ryan Florence

[Writing TextMate Snippets] ( http://blog.flobro.com/ )

Aaron Newton

unread,
Nov 4, 2009, 4:23:27 PM11/4/09
to mootool...@googlegroups.com
I can tell you I've done this 8 different ways. In general, my rule of thumb is to make things as small as is possible and still be useful. This applies to methods, to classes, to applications. Make a method that does one thing, and only one thing. Make a class that does one thing, and only one thing. Then write controller classes that stitch this stuff together. It's hard, but it ultimately pays off because so much of it is reusable and easy to maintain. If you have a class that only does one thing, and it has a bug - i.e. in some state it WON'T do that one thing - it's much easier to fix than a class with 100 methods. Unraveling that kind of thing is nearly impossible. Having 25 classes, each with 5 methods and 2 callback events, is challenging to maintain, too, but the difference is you can look at any one of them and understand its purpose, it's contract with the things that make use of it, and you can fix it (and so can anyone else).

As for all your callbacks, they don't bother me. The trick is to be clear and deliberative in the places you add them and how they work. Try and make things consistent without confusing. For instance, I have a class that manages a lot of server communication. Urls get passed around a lot. I could make the argument for fetching a url just be "url" and the callback, which includes the url which it is calling back for, could also have a "url" value. And I could store the current url as "this.url". But then you start getting confused as to which url you are working with. Thus, I name them requestUrl, responseUrl, and currentUrl. Things like this feel consistent and aren't confusing.

As for automating a lot of this stuff, that's where abstractions pay off. Writing a class that is abstract and does one small thing comes in handy in all sorts of places you may not have planned on. It's also important to document what you're writing, which is a task that is all too often forgotten about until the last minute. Inline comments about what this thing does are enough to help you keep it straight.

On Wed, Nov 4, 2009 at 1:09 PM, Ryan Florence <rpflo...@gmail.com> wrote:

Most public facing websites I do are pretty basic, with a handful of unrelated classes instantiated (a gallery, some menu navigation, maybe some ajax fun).  You know, a fancy "brochure" website.

But when developing web applications I've ended up either created a do-everything-class that has tens if not hundreds of methods; or splitting up each piece of the page into separate classes with a lot of events used to communicate with each other.


The do-everything-class just feels wrong.

10-20 classes on a page with all sorts of `onWhatever` functions makes a mess out of my domready code.

Is there a happy medium?  Like a "controller" class?

So I'd instantiate all the classes, and then pass them in to the controller class and from there define how and when they communicate with each other?

Simple Example to better illustrate the concept:

A photo gallery has
 1) a carousel full of thumbnails with next and previous buttons
 2) and an image viewer that loads an image, zooms in and zooms out.

When a thumbnail is clicked, the image viewer should load the image.

In the end will be some theoretical methods:
 - loadImage
 - next
 - previous
 - zoomIn
 - zoomOut

I could either
 1) create a single class that does everything or
 2) have a class for the image viewer with loadImage, zoomIn, and zoomOut, and then a carousel class with an onSelect event, used to send a message to the viewer class to load the correct image.

I'm currently doing number 2 on a project but all the onWhatevers are starting to drive me nuts and I'm tempted to go back to a do-everything class.  But I just thought about creating a class to handle all the communication between my classes.  So I could just pass in the two class instances (carousel and image viewer) to the controller class and then define inside there what to do onSelect of a thumbnail.

Ryan Florence

unread,
Nov 4, 2009, 5:05:22 PM11/4/09
to mootool...@googlegroups.com
Thanks for the detailed response. Glad to hear my thought process was on the right track.

Ryan Florence

[Writing TextMate Snippets] ( http://blog.flobro.com/ )



evan

unread,
Nov 4, 2009, 6:21:08 PM11/4/09
to MooTools Users
I don't abstract my classes out as far as I have seen Aaron do in some
of the clientcide plugins. I tend to keep each "widget/control" as a
single class and then any interaction that will need to take place
between classes I do through custom events. I usually only need to
create a few events on each class to set up the interactions I need. I
also usually use a domready event to instantiate my classes and make
the connections through the events. If things got a little more
complex I could see moving it in to a controller class.

The complexity of a project has a lot to do on how I end up doing
things. I also change my mind on each project and usually try
something new. I am still hunting for that one solution that I will
use each time.

Ryan Florence

unread,
Nov 4, 2009, 6:37:25 PM11/4/09
to mootool...@googlegroups.com
So far this controller class is exactly what the doctor ordered, I
guess I just sent the email out to see if I was on the right track.

Like you, I typically have a few classes and connect them through
events right there in domready. But on this page those event handlers
were getting gruesome, and I don't like seeing that much logic in my
domready. I prefer to just create class instances and leave it at that.

Ryan Florence

[Writing TextMate Snippets] ( http://blog.flobro.com/ )

Daniel Lohse

unread,
Nov 4, 2009, 7:07:33 PM11/4/09
to mootool...@googlegroups.com
Can we have a look at that "Controller Class"? Please? :)

Ryan Florence

unread,
Nov 4, 2009, 7:15:56 PM11/4/09
to mootool...@googlegroups.com
Sure, when I'm back on my computer I'll post what I've done so far.

Sent from my iPhone

On Nov 4, 2009, at 5:07 PM, Daniel Lohse

Daniel Lohse

unread,
Nov 4, 2009, 7:26:45 PM11/4/09
to mootool...@googlegroups.com
Thanks! I'm also having a hard time keeping up with my client's
demands. I'm at around 10 JavaScript files, a few 'shared' files with
all the classes in it and because the client decided he might be
including all (!) of the js files as he pleases it's crashing
everywhere. Bad. Really bad.

So, today I stumbled over $Uses: http://blog.citycrawler.com/?p=47 and
now you're also talking about something that could make it easier to
manage this 'class hell'. I'm all for MooTools but the HTML shackles
are shining through. :) "this.element is undefined" anyone? :D

Cheers, Daniel

Aaron Newton

unread,
Nov 4, 2009, 7:27:03 PM11/4/09
to mootool...@googlegroups.com
The stuff I have is a) somewhat abstract, and understanding it requires you to look at a lot more stuff. It's not really easily sharable without me doing some work. And b) internal Cloudera stuff, and we haven't decided if we're going to release it yet or not.

CroNiX

unread,
Nov 4, 2009, 7:42:47 PM11/4/09
to MooTools Users
I don't waste time writing a class unless its general purpose. That
is it can be used on many websites/projects just the way it is.
Something like the mootools Tips class. If its something that is only
going to be used on one website and will only work on that one
website, I just go with straight functions.

Ryan Florence

unread,
Nov 4, 2009, 8:09:22 PM11/4/09
to mootool...@googlegroups.com
I was actually thinking while picking up dinner I'd love to see how cloudera's code looks.

Ryan Florence

Stewart Mckinney

unread,
Nov 4, 2009, 8:18:11 PM11/4/09
to mootool...@googlegroups.com
I tend to use the largest JS-active DOM element as the "Controller", and if there are several of them, I have several. Usually what I do is build an abstract class that can be reused nearly anywhere, and then extend that class for each view (for those that need it, sometimes re-extension is not necessary), adding extra needed class initialization calls as needed. Then I generally just include that DOM element in the domready, and away we go.

Another thing I do which helps to fight the one-class-to-rule-them-all and a cluttered domready is to employ an event listener class, which adds an element to the DOM that listens to events for another class. Classes can add event listeners, which then add listener events to that dom element. That way, you don't always need to declare classes together - you can just declare them seperately and they will do the event association themselves, which cleans your domready code up a bit. The event listener class always knows which DOM element to add events to, so you dont need to worry about misfiring (as much).

Don't worry so much about having a class that is only used on one view - there are a lot of merits to having all your other class variable declarations (outside of the one in the domready) in your initialize function, where you can keep them under safe watch. (I may be paranoid, but working in iFrames has changed me). It also makes getting rid of events on those classes easier - you can just write one "clear" function for the container class that will dispose of all events that it has added.

As a general rule of thumb, when a class has over 10 methods, I start to worry - unless its a core component of a framework that is being diligantly reused. I also build lots of classes, and while I can't see them all in one place, its much easier to deal with them individually, and overall I have to say I think its the right way to do things.

I hope that helps!

Stew

Aaron Newton

unread,
Nov 4, 2009, 8:29:57 PM11/4/09
to mootool...@googlegroups.com
I'm the opposite. I write classes for almost everything. I do my best to abstract them so they aren't esoteric, but I find that if I take the time to write classes, my code is cleaner, easier to maintain, and I end up re-using things that I didn't plan on.

Ryan Florence

unread,
Nov 4, 2009, 9:37:37 PM11/4/09
to mootool...@googlegroups.com
@Daniel

http://paste.mootools.net/m5fff7a79

That's essentially what my first controller is looking like. Again,
that's not even an hour or work or thought, and it's my first time
working with this concept, so I'd hardly consider it best practice ...
or practice at all at this point. All I know is I'm very happy with
it. It's out of my domready and a lot cleaner.

It's essentially just adding events to the various objects, and then a
bunch of handlers for those events.

@Cronix

"I just go with straight functions."

That's basically what I'm doing but wrapping it up in a class. I
can't reuse the class anywhere, so you're right, it's not really
valuable outside of this application. But I wouldn't call it a waste
of time. I prefer to work with code in a class, it just looks and
feels more organized. However, I learned MooTools before I really
learned javascript, so maybe that's why I prefer working in a class.

Ryan Florence

[Writing TextMate Snippets] ( http://blog.flobro.com/ )

Rolf -nl

unread,
Nov 5, 2009, 9:47:45 AM11/5/09
to MooTools Users
I think most of us are using similar ways to accomplish things. The
more skilled you get (I think) the more abstract you start to program.
Or maybe, those with a formal programming training history tend to
abstract a lot. Because I'm not a trained programmer (but graphic
designer) I learned actionscript/php/mootools by just doing it. For me
abstraction sometimes gets too difficult to understand, especially
when you see code from a large project and you have to figure out what
bit is doing what :) I tend to "view source" alot, hehe.

Basically I follow Ryan & Evan's way of doing things; a few classes an
when needed a bunch of events that get fired and picked up by other
classes. Also, during a project I tend to rip more things apart if
possible (and if there is time) but not to a level of abstraction
others would do I guess.
Sometimes you just think: ok, I can create a seperate class for this
now, but why would I, it works now, and I don't have the extra
hour.....

An event listener class like Stewart mentioned or a controller class
sounds good to me :)
@Ryan: with your example, you would write a controller class for every
project, no? Like adding events and telling them what to do with the
specific classes included in the project (e.g. a gallery thing).


PS > It's funny.. sometimes you wonder how others work and in a post
like this you see ppl are having similar questions as yourself

Aaron Newton

unread,
Nov 5, 2009, 1:41:08 PM11/5/09
to mootool...@googlegroups.com
I'm not sure this abstraction really scales. It seems to me you're writing a lot of code to get a behavior that you could be more explicit about and do the same amount of work.

You might also consider event arbiters:

Perrin Perrin

unread,
Nov 5, 2009, 4:07:32 PM11/5/09
to mootool...@googlegroups.com
On a similar line of thought (on composite object rather than massive controllers):

What do you all think about combining Options with dependency injection when defining a composite object Class?
  Too much code with little gain?
  Makes the code more flexible?

Here is somewhat silly example of what I'm talking about.
http://mooshell.net/6XDcD/


SillyCompositeObj has two different objects, a Fx type object, and a Log type object, and it gives as options what type of object that it will be creating but another type can be passed in instead. (The final three js statements show this)

(cLog prints to console if available)
(eLog makes elements that are injected into the dom when Logging)

--Perrin
CrypticSwarm

Aaron Newton

unread,
Nov 5, 2009, 4:33:22 PM11/5/09
to mootool...@googlegroups.com
I use this pattern quite often. For instance, in many of my classes that use StickyWin instances, you can pass in a pointer to any of the various types of StickyWin subclasses.

In a few special cases I also pass in *instances* of a class. This is dangerous though, as if you call setOptions and your options contain a pointer to an instance of a class you'll get a recursion error, so you have to remove it from the options object before hand.

The only reason to do this is when your constructor must have this pointer rather than having a method. I.e.:

when this won't work:

new Foo().setParent(someInstanceOfAClass);

and you need to do this:

new Foo({
  parent: someInstanceOfAClass
});

Because you need to know about that instance on invocation. To deal with this, the initialize method of Foo has to look like this:

initialize: function(options) {
  this.setParent(options.parent);
  delete options.parent;
  this.setOptions(options);
}

It's annoying (really, it's a bug in $merge), but sometimes necessary. ART.Widget does this to avoid rendering elements more often than it has to, for instance.

Ryan Florence

unread,
Nov 5, 2009, 6:43:08 PM11/5/09
to mootool...@googlegroups.com
Does the mootools book go into this type of discussion?  Anywhere else to look?

You're right Aaron, my funny little controller is no less unwieldy than what I had before, and it doesn't scale at all.


Ryan Florence

Aaron Newton

unread,
Nov 5, 2009, 8:07:22 PM11/5/09
to mootool...@googlegroups.com
The current book doesn't have much stuff like this. The second book, which is on hold waiting for MooTools 2.0, has a lot more. I can't recall if it covers this particular topic. I'm pretty sure it covers event arbitration and singletons.
Reply all
Reply to author
Forward
0 new messages