I’ve been diving into JavaScript MVC for quite a while using Spine.js and CoffeeScript. I develop Ruby on Rails since a while so I understand what the models, the views and the controller should handle respectively (based on my moderate experience with it). But in Rails we already know that (generally speaking) each controller is basically something that controls a bunch of views (or pages) and deals with one or more Models at a time. (Maybe, so correct me if I’m wrong as I’m not a pro yet I have to confess).
However I found a whole different concept with Spine in terms of architecture. I read its documentation and dove into its sample apps. Unfortunately all the Spine sample apps are showing how to deal with a single page app, something that in a real world “larger” application would not be the case anymore. (Correct me if Spine should only be used for “single page apps”).
Assume there is a website (or app) that consists of many pages/sections/modules as follows:
1 – A home page, displaying for example, a thumbnails based list
2 – A contact page
3 – A profile management page for the current user (normal CRUD)
Each page has the same main structure (or layout) as in a header with links to the above pages, a search input field and a log out link (I already know the log in page should be separate, so I won’t ask about authentication in here).
The tricky part here is I can’t really figure out how to tie the whole parts together and I’ve been asking myself some questions, searched on Google and StackOverflow but without clear answers.
1 – “Must” a spine app application be in one page only? I mean, having header and footer fixed but with a dynamic content DIV which loads and unloads views based on which tab the user clicks on the header? Or should I treat each page as a standalone spine app?
2 – Do I have multiple controllers in one page? For example, the app main controller and navigation controller (header)?
3 – Is it true that each controller should be dealing with one Model, or the one associated with it? (In the samples there was always a 1 to 1 relationship between them, like Task Model and Tasks Controller).
4 – Where should I store interface related state variables in my app. Should I create a model that “remembers” the current user, or for example which tab is highlighted for further reference? Or should I store them into the controller(s)?
5 – If it’s going to be a single page app (but with many sections or modules), should I have a controller for each loaded section inside of this page?
I know these might be trivial questions for more experienced programmers but I really don’t know where to start. So it would be awesome if someone could guides me to the right track.
Thanks in advance!
DD
I think that this is a very good question. My answer will be quite broad, so bear with me.
The essence of my answer is that you need to get familiar with other frameworks in order to understand what the one you chose is trying to solve. Your problems are understandable. Other people have struggled with lack of one “proper” way of doing some common things. Solutions were created in terms of examples, wrappers/extensions and alternative frameworks. Perhaps, you should seeks information related to Backbone, which inspired Spine and is still similar to it.
As you said, you’re familiar with Rails’ MVC. And then comes Spine’s MVC approach and it is totally different. This should give you a hint that MVC (or MV* in general) is broad idea that has very different implementations. OK, you might be thinking that Rails is a request-based server-side framework after all and that Spine is a client-side event-based framework – so the difference is understandable. Well, there is no uniformity amongst client-side JavaScript frameworks either. For example, the mentioned Backbone has so-called Views, which actually play the role of controllers. So I guess that one thing that Spine’s creator did was renaming Views to Controllers for clarity. MV* for JavaScript is explained in detail by Addy Osmani. There is also a good overview of JavaScript frameworks.
So one “problem” with Spine and Backbone is that they do not dictate any architecture. In other words, they are not opinionated enough. You can use them as your want and this fact makes frustration. Below I try to answers your questions:
You may create an app that has multiple pages, each loading it’s own Controller. In this case, your views can be rendered on server and your models can be bootstraped from generated JavaScript. This is good when you don’t want a SPA, but still would like to organize JavaScript or have some reusable components.
However, judging from the feature set of Spine (e.g. routes), it was created with SPA in mind.
For SPAs and complex UIs in general it is good to have parts of UI (widgets) separated. In Spine, Controllers are the means of such separation. So yes, use multiple controllers and use controller nesting. Perhaps, there should be a topmost application controller.
That’s not true (no technical limitation), although single responsibility principle makes things easier.
Store those variables in the controller of corresponding level. Store them is models if you need to observe those values, otherwise store them as controller properties.
You can have an App controller, that holds a header, footer, sidebar controller and an active page. In Routes, you create a corresponding controller and pass it to App controller, which replaces the main area content with the element of that controller. This is one possible approach.
Once again:
People have struggled with lack of concreteness in terms of application architecture in Backbone/Spine. They have created some solutions like application controllers, layout managers and so on. For Backbone, you can take a look at Marionette, Chaplin or Thorax. By learning from them you will be able to come up with an architecture for your Spine application. Good luck!