I'm doing a fairly complex emberjs application, and tying it to a backend of APIs.
The API calls are not usually tied to any particular model, but may return objects of various types in different sections of the response, e.g. a call to Events API would return events, but also return media assets and individuals involved in those events.
I've just started with the project, and I'd like to get some expert guidance on how best to separate concerns to have a clean maintainable code base.
The way I am approaching this is:
- Models: essentially handle records with their fields, and other computed properties. However, models are not responsible for making requests.
- e.g. Individual, Event, Picture, Post etc.
- Stores: They are essentially caches. For example, an
eventStore
would store all events received from the server so far (from possibly different requests) in an array, and also in an hash of events indexed byid
.- e.g. individualStore, eventStore etc.
- Controllers: They tie to a set of related API calls, e.g. eventsController would be responsible for fetching events or a particular event, or creating a new event etc. They would 'route' the response to different
stores
for later retrieval. They don't keep the response once it has been sent to stores.- e.g. eventsController, userSearchController etc.
- Views: They are tied to a particular view. In general, my application may have several views at different places, e.g.
latestEventsView
on the Dashboard in addition to having a separate events page. - Templates: are what they are.
Quite often, my templates require to be bound directly to the stores (e.g. peopleView
wants to list all the individuals in the individualStore in a list, sorted by some order).
And sometimes, they bind to a computed property
alivePeople: function () { ... }.property('App.individualStore.content.@each'),
The various filtering and sorting options 'chosen' in the view, should return different lists from the store. You can see my last question at what is the right emberjs way to switch between various filtering options?
Who should do this filtering, the view themselves or the stores?
Is this kind of binding across layers okay, or a code smell? Is the separation of concerns good, or am I missing something? Shouldn't controllers be doing something more here? Should my views directly bind to stores?
Any particular special case of MVC more suited to my needs?
Update 17 April 2012 My research goes on, particularly from http://vimeo.com/user7276077/videos and http://jzajpt.github.com/2012/01/17/emberjs-app-architecture.html and http://jzajpt.github.com/2012/01/24/emberjs-app-architecture-data.html
Some issues with my design that I've figured out are:
- controllers making requests (stores or models or something else should do it, not controllers)
- statecharts are missing -- they are important for view-controller interactions (after sometime you realize your interactions are no more simple)
This is a good example of state charts in action: https://github.com/DominikGuzei/ember-routing-statechart-example
UPDATE 9th JANUARY 2013
Yes, it's been long but this question is lately getting lots of views, and that's why I'd like to edit it so that people may get a sense.
Ember's landscape has changed a lot since this question was framed, and the new guides are much improved. EmberJS has come up with conventions (like Rails) and the MVC is much more well defined now.
Anybody still confused should read all the guides, and watch some videos: Seattle Ember.js Meetup
At the moment, I'm upgrading my application to Ember.js 1.0.0-pre2
.