Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding the internal structural dependencies of MVC in Backbone.js

I'm a bit confused w.r.t. the structural dependencies when designing your MVC - so we have a Model, Collection and View (I'm not using controllers as yet, but the question applies to it too). Now who has a reference of whom to speak in OO terms. So the collection is a list of models so we can think of it as a one to many dependency from collection to model. In some of the example codes I sometimes see some reference to a view in the 'model' object and the reference of the model in the view. Sometimes a collection in the view.

In the model I sometimes see a this.view and in the view I see something like this.model.view or a this.model and thus the confusion to clarify :)

So what is the 'right' set of dependencies (if there is "a" right way that is) or can everyone be dependent on everyone (don't think that is correct) I.e., who should ideally be dependent on whom in Backbone's MVC design of objects? It's just a bit confusing to know how should they be structurally related when I see such disparate examples - from a noob point of view :) As a noob what is the 'right' way to start structuring my dependencies - once I'm up the learning curve I'd probably figure it out myself, but to start with, how should one go about it? A UML-like diagram would be an added bonus ;)

Another question: Sometimes I see two views in the same piece of code: Eg: the famous todo.js http://documentcloud.github.com/backbone/docs/todos.html

Now although I understand the need of multiple views, what is confusing is how are they different? I mean what's the difference between an 'el' and 'tagName' and how does the view behave differently if either one of them is absent? I mean in the link above one view uses 'tagName' and the other 'el' and I'm not really sure how they correlate (if at all).

I've gone through the documentation intensively, but as I said I'm still learning so I may just not understand parts of it clearly even with all the resources in place and may need some human intervention :)

like image 573
PhD Avatar asked Jul 12 '11 05:07

PhD


People also ask

What is MVC in backbone?

js. Source files of each module follow the Model View Controller (MVC) architectural pattern. One of the core principles of the MVC pattern is to separate the presentation layer (view) of an application from the data (model) used by the application.

How does Backbone JS work?

Backbone. js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.

What are the main components of backbone JS?

Unlike most of the MVC frameworks, Backbone. js consists of six main components: Models, Views, Collections, Events, Routers and Sync.

Is Backbone JS still relevant?

Backbone. Backbone has been around for a long time, but it's still under steady and regular development. It's a good choice if you want a flexible JavaScript framework with a simple model for representing data and getting it into views.


1 Answers

Since Backbone.js is not a framework as such, there's no single "right" way to do anything. However, there are some hints in the implementation that help you to get the idea. Also, there are some general time-tested code organization practices which you can apply. But I'll explain the views first.

Views

Views in Backbone are tied to particular DOM elements (that's what the el property is for).

If, when the view is initialized, it has an el attribute, then Backbone.js makes it a property of the new view instance. Otherwise it looks for tagName, id, and className attributes, creates the corresponding DOM object, and assigns it to the el property of the new view instance anyway. (It's explained in the source.) If there's even no tagName, then <div> element is created by default.

So, you can guess why TodoView and AppView use different approaches. The #todoapp element exists initially on the page in the HTML, so AppView can just use it. But when a view for a todo item is created, there's no DOM element for it yet; so the developer has tagName defined on the class for Backbone to create a list item automatically. (It wouldn't be hard to do by hand in the initialize() method, but Backbone saves some time by doing it for you.)

Usually a view falls into one of two categories: views for model instances, and views for collections. Backbone doesn't force it, but it suggests that it's probably what you want: if you instantiate the view with collection or model options, they become properties of the newly created view instance, so you can access them via view.collection or view.model. (If you, for example, instantiate the view with foo option, it will be put into view.options.foo.)

Dependencies

Good practices

This is just my opinion.

  • Less dependency is better.

  • Following the MVC pattern has a lot of advantages.

    Note that Backbone.js terminology does not match MVC's classical one. That's normal, MVC != a set of classes, and its definitions vary a bit. It's more of ‘an ideal that you should have in the back of your mind’ (quoted from What is MVC and what are the advantages of it?).

 MVC        | Backbone.js                 | What it does Controller | View (mostly)               | Handles user interaction View       | template rendered by a view | Displays the data Model      | Model & Collection          | Represents the data, handles data access 
  • The model layer should not normally depend on anything. In MVC, model is where you access your data. That has nothing to do with, say, the presentation of this data.

    In Backbone, a model can be a part of some collection, but that's not a heavy dependency (AFAIK, it just helps to automatically figure out URLs of API endpoints corresponding to this model.)

  • In Backbone, a collection may have a corresponding model class assigned, but that's also not necessary.

  • In Backbone, a router usually depends on higher-level views (like views for entire pages or sections of the page), to render them in response to a change in application's state. These views, in turn, depend on some lower-level views, like widgets / page sections. These views can depend on collections and other, even more low-level views. These, in turn, can depend on particular model instances.

As an example (arrows denote "depends on" type of relationship):

            +-------------+              +---------------+   +------------+ State      |MainRouter   |       Data:  |ItemCollection |   |ItemModel   | Control:   |-------------|              |---------------|   |------------|            |             |              |/api/items     +-->|/api/items/*|            |             |              |               |   |            |            |             |              |               |   |            |            +---+-+-------+              +---------------+   +------------+                | +----------------+                  ^              ^                v                  v                  |              |            +-------------+   +-------------+         |              | Page-level |AboutView    |   |AppView      |         |              | views:     |-------------|   |-------------|         |              |            | section     |   | section     |         |              |            | role="main" |   | role="main" |         |              |            +--+-+--------+   +--+-+-+------+         |              |               | +---------------|-|-|----+           |              |               |      +----------+ | +----|---------+ |              |               v      v            v      v         v |              |            +--------------+   +--------------+   +---+-----------+  | Widget     |SidebarView   |   |HeaderView    |   |ItemListView   |  | views:     |--------------|   |--------------|   |---------------|  |            | aside        |   | header       |   | ul            |  |            |              |   |              |   |               |  |            |              |   |              |   |               |  |            +--------------+   +--------------+   +-----------+---+  |                                                              |      |                                                              v      |                                                            +--------+---+                                                            |ItemAsLiView|                                                            |------------|                                                            | li         |                                                            |            |                                                            +------------+ 

Note that you can have multiple routers set up, in which case things may look a bit differently.

todos.js

In the Todos example, the developer decided that Todo model instances should depend on corresponding TodoView instances. When TodoView is instantiated, it creates on the corresponding model instance a property view and assigns itself to it. So that it could be accessed by some_todo_model.view. However, it should be noted that model.view is only used once—in Todo model's clear() method, to remove the view instance when the model is cleared.

I think that particular dependency isn't necessary. However, for such a small application, it may be okay.

I couldn't find any example of accessing this.model.view in the view, so I can't comment on this.

See also

  • Answers by Julien Guimont—almost all of them are about Backbone.js, I think it's a great source of information.
like image 126
Anton Strogonoff Avatar answered Oct 02 '22 15:10

Anton Strogonoff