Wednesday, June 13, 2012

The V in MVC

I just read http://addyosmani.com/blog/digesting-javascript-mvc-pattern-abuse-or-evolution/ and it's got some good points. The main points you should take away is that there are already some great frameworks to work with and that there are many different approaches to the classic pattern. Most of these approaches are similar enough that you won't feel out of place if you switch between frameworks.

There is one point that I disagree with however, and that is that a view must know about the existence of models. I agree this is how a lot of frameworks work, especially when you think about ones that offer binding through templates or attributes on dom elements - but it doesn't have to.

I wrote PlastronJS and it follows a similar model as most MV* frameworks out there where the view is really little more than a template. The reason for this is that it's easier to get started and usually when you're doing a single page application there is no need for a great deal of abstraction.

So we turn our attention to the V in MVC. How can we have a view without knowing about the model? Well the easiest way is to build a view before building anything else. The second is to give it an interface that we can get, set and listen to and that's it. Here is a rather simple example:

View = function(text) {
  this.element = $('<div>').text(text);
}

View.prototype.setText = function(text) {
  this.element.text(text);
  this.emit('textChanged');
}

View.prototype.getText = function() {
  return this.element.text();
}

We've created a view. It can be updated by passing in text and if anyone makes a change to the view then it will emit that the text has been changed and the text can be read. It doesn't know anything about a models existence - nor what type of model. We could hook up any type of model to this view. Knowing about the model is the job of the control. The control is what knows about the model and the view.

So what is the advantages of having a separate view like this and not including it in with the controller or binding it in the DOM? Well for one thing the view does not have to know about the model. You can make simple and generic views that do things like display a text area or a graph and then re-use those views. You can also easily swap out views for different devices. If you want to change the view you won't have to change the rest of the control and it's bindings (unless it implements a different interface). There is also the possibility of building up larger views by adding together smaller views (it's like point-free programming for UI!)

So why don't more frameworks (including my own) do this? Well it's just harder to get started with and takes more code. You have to defined these views to begin with. Most people will look at it and think it's an awful lot of work to do to get a single page app going, and it is. You won't see and advantage to building an app with an abstracted view until much later in development.

**EDIT**

here is a little more detail about how to use it. Let's take the text view from above - we can use this to display any model. Let's say we have the user as a model - the user might have many different things on it (like usage limits) but we want to display the username at the top of the page. All we need to do is create a Control that pipes in the username of the model. So something like:

UsernameControl = function(model, view) {
  this.model = model;
  this.view = view;
  this.view.setText(model.get('username');
  this.model.on('username:change', function(username) {
    view.setText(username);
  });

usernameC = new UsernameControl(user, new View());

Now we may also have a shopping cart model and want to to display the amount, we can do exactly the same but create a shoppingCartControl, pass in a new instance of the view and hook up the total to the text. The trick is that the view stays generic and it's the control that hooks up what should be displayed. This is a simple example with only one parameter being passed through but you could build up views from smaller views or even have a view factory (one that will replicate the "text" div however many times you need for different values).

Friday, June 8, 2012

Initial Closure Meetup review

First of all, thanks to everyone that attended. We had around 35 people show up which is more than I ever expected when this was first put together. I think it shows the interest out there in the tool set and means that there is the ability to grow a solid community around the technology.

Thanks also to Nathan Naze who organized the space and took those newer to Closure under his wing - I'm sure they all learned a lot and there will be new users coming in.

The topics ranged throughout the talk and we covered a lot of bases as it was a round table discussion. One of the main subjects was work processes and how everyone used the tools. A lot of people use http://plovr.com/ or are now going to give it a go. The rest just use the scripts that come with the library with make or ant. Because of the interest our next meetup will be called "show us your stack" and I'm hoping to get a few people to take us through their workflow. I've put it up for a couple of months time at: http://www.meetup.com/Closure-Tools/events/68334272/ though it is far from confirmed. Let me know if you would like to share your setup, I'm thinking that a quick run through of a few people's setup will help (so anywhere from 5-30 mins just let me know how long you need).

Another important topic was the sharing of closure specific libraries. At the moment you can find projects in the wiki at: http://code.google.com/p/closure-library/wiki/RelatedProjects but it can be hard to find especially for new users. I'd like to see a communtiy driven website which can list libraries, externs, IDE setups etc. that we can share with each other. Anyone good at website design?

I also talked about a "starter pack" that would include projects like plovr, http://bolinfest.com/coffee/features.html, https://github.com/rhysbrettbowen/PlastronJS, https://github.com/rhysbrettbowen/G-closure and some gss style sheets (ala bootstrap), IDE components and a tutorial that could help users start on single page apps using interfaces and patterns that are familiar to them. I haven't started on the project yet but I'm hoping for contributions (especially with the IDE components) so we can lower the bar for entry into the toolset.

There was also some discussion about a package manager (perhaps a fork of NPM) which would help users with discovery and use of modules.

These are all really exciting propositions and the future looks bright.

Monday, June 4, 2012

Routing and state

A little while ago I read and article about routing in ember which was a big surprise to me, not so much their approach but that people weren't already doing it. At the moment it seems that a router is being used across a program and individual components are listening for specific routes. The issue with this is that you end up with your routs being defined across a number of components so if you update your URL structure then you're going to have problems hunting down all those routes that were defined.

So have a read of the routing in Ember.js article then come back because we're going to take it one step further.

What I currently do is extend the router and call it State.js and then make it a singleton that is available to the whole program. This is the central repository for my state and is also where all the routing will be handled. If a user wants to change the state when clicking a link I can just send the variables that need changing to the state. This will then change it's internal variables, output it's state as a URL and then push that in to the history. The big advantage of this is that instead of declaring the whole URL on that link you only need to know which variables change. For instance if you had several filters that could be applied to a search page you could just call your State.setFilter(...) and have that added. The state then knows to keep the rest of it's filters intact and will generate the new URL with the filters it already has on still in the URL.

This makes it easier to apply URLs where you may have several filters at one. Today most routers handle tree like structures well but are difficult to use when you want  to do things like apply size and colour filters on - things which don't have an order and can be expressed many ways. The best way to put this in a URL is outside the path. Usually I like to put whatever I can in the path like structure and then give the rest of the variables as a query string on the end.

Now we've decoupled setting state, but how about reading it or running things from different controls on different states. For that I use the mediator. The router should be setup to accept all the possible routes and can then pass the changes with all the information needed through a mediator. This means that you can also do special processing of the urls in the mediator too if need be. Because we've done this the individual components will only be listening to events that you define and not to URLs that may change.

That is what I currently do, but it has struck me there might be an even better approach and one which I will be experimenting with in future. State is really just a whole lot of variables and a router is a way of setting and getting state back from the URL. This sounds just like a model and a sync. Next time I'm writing a program I'm going to see if I can create a state model with it's sync being the router and then I should be able to bind on changes to that model and send those changes through a mediator to the rest of the program. This means the logic for the binding between state variables and the URL will be pushed in to the sync, or as an interface between the model and the router and the program will only have to worry about the state model. The benefits of this should be that models already have binding magic and so should cut down on code.