PageRenderTime 82ms CodeModel.GetById 38ms RepoModel.GetById 1ms app.codeStats 0ms

/backbone-fundamentals.db

https://github.com/arkentos/backbone-fundamentals
Unknown | 10016 lines | 9502 code | 514 blank | 0 comment | 0 complexity | 3c9a05535dd9097fd5fcc98f1a7284f4 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
  3. "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
  4. <article>
  5. <articleinfo>
  6. <title></title>
  7. </articleinfo>
  8. <sect1 id="prelude">
  9. <title>Prelude</title>
  10. <para>
  11. Welcome to my (in-progress) book about the
  12. <ulink url="http://documentcloud.github.com/backbone/">Backbone.js</ulink>
  13. framework for structuring JavaScript applications. Its released
  14. under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0
  15. Unported
  16. <ulink url="http://creativecommons.org/licenses/by-nc-sa/3.0/">license</ulink>
  17. meaning you can both grab a copy of the book for free or help to
  18. further
  19. <ulink url="https://github.com/addyosmani/backbone-fundamentals/">improve</ulink>
  20. it.
  21. </para>
  22. <para>
  23. Im very pleased to announce that this book will be out in physical
  24. form in a few months time via
  25. <ulink url="http://oreilly.com">OReilly Media</ulink>. Readers will
  26. have the option of purchasing the latest version in either print or
  27. a number of digital formats then or can grab a recent version from
  28. this repository.
  29. </para>
  30. <para>
  31. Corrections to existing material are always welcome and I hope that
  32. together we can provide the community with an up-to-date resource
  33. that is of help. My extended thanks go out to
  34. <ulink url="https://github.com/jashkenas">Jeremy Ashkenas</ulink>
  35. for creating Backbone.js and
  36. <ulink url="https://github.com/addyosmani/backbone-fundamentals/contributors">these</ulink>
  37. members of the community for their assistance tweaking this project.
  38. </para>
  39. <para>
  40. I hope you find this book helpful!
  41. </para>
  42. </sect1>
  43. <sect1 id="table-of-contents">
  44. <title>Table Of Contents</title>
  45. <itemizedlist>
  46. <listitem>
  47. </listitem>
  48. <listitem>
  49. <itemizedlist>
  50. <listitem>
  51. <para>
  52. <link linkend="mvc-mvp">MVC, MVP &amp; Backbone.js</link>
  53. </para>
  54. </listitem>
  55. </itemizedlist>
  56. </listitem>
  57. <listitem>
  58. <itemizedlist>
  59. <listitem>
  60. <para>
  61. <link linkend="models">Models</link>
  62. </para>
  63. </listitem>
  64. <listitem>
  65. <para>
  66. <link linkend="views">Views</link>
  67. </para>
  68. </listitem>
  69. <listitem>
  70. <para>
  71. <link linkend="collections">Collections</link>
  72. </para>
  73. </listitem>
  74. <listitem>
  75. <para>
  76. <link linkend="routers">Routers</link>
  77. </para>
  78. </listitem>
  79. <listitem>
  80. <para>
  81. <link linkend="namespacing">Namespacing</link>
  82. </para>
  83. </listitem>
  84. <listitem>
  85. <para>
  86. <link linkend="additional-tips">Additional tips</link>
  87. </para>
  88. </listitem>
  89. </itemizedlist>
  90. </listitem>
  91. <listitem>
  92. <itemizedlist>
  93. <listitem>
  94. <para>
  95. <link linkend="restful">Building RESTful applications with
  96. Backbone</link>
  97. </para>
  98. </listitem>
  99. <listitem>
  100. <para>
  101. <link linkend="stack1">Building Backbone apps with Node.js,
  102. Express, Mongoose and MongoDB</link>
  103. </para>
  104. </listitem>
  105. <listitem>
  106. <para>
  107. <link linkend="stack2">Building Backbone apps with Ruby,
  108. Sinatra, Haml and MongoDB</link>
  109. </para>
  110. </listitem>
  111. <listitem>
  112. <para>
  113. <link linkend="pagination">Paginating Backbone.js Requests
  114. &amp; Collections</link>
  115. </para>
  116. </listitem>
  117. </itemizedlist>
  118. </listitem>
  119. <listitem>
  120. <itemizedlist>
  121. <listitem>
  122. <para>
  123. <link linkend="modularjs">Modular JavaScript</link>
  124. </para>
  125. </listitem>
  126. <listitem>
  127. <para>
  128. <link linkend="organizingmodules">Organizing modules with
  129. RequireJS and AMD</link>
  130. </para>
  131. </listitem>
  132. <listitem>
  133. <para>
  134. <link linkend="externaltemplates">Keeping your templates
  135. external with the RequireJS text plugin</link>
  136. </para>
  137. </listitem>
  138. <listitem>
  139. <para>
  140. <link linkend="optimizingrequirejs">Optimizing Backbone apps
  141. for production with the RequireJS Optimizer</link>
  142. </para>
  143. </listitem>
  144. <listitem>
  145. <para>
  146. <link linkend="practicalrequirejs">Practical: Building a
  147. modular Backbone app with AMD &amp; RequireJS</link>
  148. </para>
  149. </listitem>
  150. <listitem>
  151. <para>
  152. <link linkend="decouplingbackbone">Decoupling Backbone with
  153. the Mediator and Facade patterns</link>
  154. </para>
  155. </listitem>
  156. <listitem>
  157. <para>
  158. Backbone &amp; jQuery Mobile
  159. </para>
  160. </listitem>
  161. <listitem>
  162. <para>
  163. Practical: Building A Modular Mobile App With Backbone &amp;
  164. jQuery Mobile
  165. </para>
  166. </listitem>
  167. </itemizedlist>
  168. </listitem>
  169. <listitem>
  170. <itemizedlist>
  171. <listitem>
  172. <para>
  173. <link linkend="unittestingjasmine">Unit Testing Backbone
  174. Applications With Jasmine</link>
  175. </para>
  176. </listitem>
  177. <listitem>
  178. <para>
  179. Introduction
  180. </para>
  181. </listitem>
  182. <listitem>
  183. <para>
  184. Jasmine
  185. </para>
  186. <itemizedlist>
  187. <listitem>
  188. <para>
  189. Suites, Specs And Spies
  190. </para>
  191. </listitem>
  192. <listitem>
  193. <para>
  194. TDD With Backbone
  195. </para>
  196. </listitem>
  197. <listitem>
  198. <para>
  199. <link linkend="testing-jasmine-models">Testing
  200. Models</link>
  201. </para>
  202. </listitem>
  203. <listitem>
  204. <para>
  205. <link linkend="testing-jasmine-collections">Testing
  206. Collections</link>
  207. </para>
  208. </listitem>
  209. <listitem>
  210. <para>
  211. <link linkend="testing-jasmine-views">Testing
  212. Views</link>
  213. </para>
  214. </listitem>
  215. </itemizedlist>
  216. </listitem>
  217. <listitem>
  218. <para>
  219. <link linkend="unittestingqunit">Unit Testing Backbone
  220. Applications With QUnit And SinonJS</link>
  221. </para>
  222. </listitem>
  223. <listitem>
  224. <para>
  225. Introduction
  226. </para>
  227. </listitem>
  228. <listitem>
  229. <para>
  230. QUnit
  231. </para>
  232. <itemizedlist>
  233. <listitem>
  234. <para>
  235. Assertions
  236. </para>
  237. </listitem>
  238. <listitem>
  239. <para>
  240. Adding structure to assertions
  241. </para>
  242. </listitem>
  243. <listitem>
  244. <para>
  245. Assertion examples
  246. </para>
  247. </listitem>
  248. <listitem>
  249. <para>
  250. Fixtures
  251. </para>
  252. </listitem>
  253. <listitem>
  254. <para>
  255. Asynchronous code
  256. </para>
  257. </listitem>
  258. </itemizedlist>
  259. </listitem>
  260. <listitem>
  261. <para>
  262. SinonJS
  263. </para>
  264. <itemizedlist>
  265. <listitem>
  266. <para>
  267. Stubs
  268. </para>
  269. </listitem>
  270. <listitem>
  271. <para>
  272. Mocks
  273. </para>
  274. </listitem>
  275. </itemizedlist>
  276. </listitem>
  277. <listitem>
  278. <para>
  279. Practical
  280. </para>
  281. <itemizedlist>
  282. <listitem>
  283. <para>
  284. Testing Models
  285. </para>
  286. </listitem>
  287. <listitem>
  288. <para>
  289. Testing Collections
  290. </para>
  291. </listitem>
  292. <listitem>
  293. <para>
  294. Testing Views
  295. </para>
  296. </listitem>
  297. <listitem>
  298. <para>
  299. Testing Events
  300. </para>
  301. </listitem>
  302. </itemizedlist>
  303. </listitem>
  304. </itemizedlist>
  305. </listitem>
  306. <listitem>
  307. </listitem>
  308. </itemizedlist>
  309. </sect1>
  310. <sect1 id="introduction">
  311. <title><a name="introduction">Introduction</a></title>
  312. <para>
  313. As JavaScript developers, we are at an interesting point in time
  314. where not only do we have mature solutions to help organize the
  315. JavaScript powering our applications based on a separation of
  316. concerns, but developers looking to build non-trivial projects are
  317. almost spoiled for choice for frameworks that can help structure
  318. their applications.
  319. </para>
  320. <para>
  321. Maturity in software (framework) development isnt simply about how
  322. long a framework has been around. Its about how solid the framework
  323. is and more importantly how well its evolved to fill its role. Has
  324. it become more effective at solving common problems? Does it
  325. continue to improve as developers build larger and more complex
  326. applications with it?
  327. </para>
  328. <para>
  329. In this book, I will be covering the popular Backbone.js, which I
  330. consider the best of the current family of JavaScript architectural
  331. frameworks.
  332. </para>
  333. <para>
  334. Topics will include MVC theory and how to build applications using
  335. Backbones models, views, collections and routers. Ill also be
  336. taking you through advanced topics like modular development with
  337. Backbone.js and AMD (via RequireJS), how to build applications using
  338. modern software stacks (like Node and Express), how to solve the
  339. routing problems with Backbone and jQuery Mobile, tips about
  340. scaffolding tools, and a lot more.
  341. </para>
  342. <para>
  343. If this is your first time looking at Backbone.js and youre still
  344. unsure whether or not to give it a try, why not take a look at how
  345. <ulink url="http://github.com/addyosmani/todomvc">a Todo
  346. application</ulink> can be implemented in Backbone and several other
  347. popular Javascript frameworks before reading further?
  348. </para>
  349. <para>
  350. The goal of this book is to create an authoritative and centralized
  351. repository of information that can help those developing real-world
  352. apps with Backbone. If you come across a section or topic which you
  353. think could be improved or expanded on, please feel free to submit a
  354. pull-request. It wont take long and youll be helping other
  355. developers avoid problems youve run into before.
  356. </para>
  357. </sect1>
  358. <sect1 id="fundamentals">
  359. <title><a name="fundamentals">Fundamentals</a></title>
  360. <para>
  361. In this section we are going to cover the context into which a
  362. framework like Backbone.js fits. Lets begin our journey into
  363. understanding Backbone better with a look at code architecture.
  364. </para>
  365. <sect2 id="mvc-mvp-backbone.js">
  366. <title><a name="mvc-mvp">MVC, MVP &amp; Backbone.js</a></title>
  367. <para>
  368. Before exploring any JavaScript frameworks that assist in
  369. structuring applications, it can be useful to gain a basic
  370. understanding of architectural design patterns. Design patterns
  371. are proven solutions to common development problems and can
  372. suggest structural approaches to help guide developers in adding
  373. some organization to their applications.
  374. </para>
  375. <para>
  376. Patterns are useful because theyre a set of practices that build
  377. upon the collective experience of skilled developers who have
  378. repeatedly solved similar problems. Although developers 10 or 20
  379. years ago may not have been using the same programming languages
  380. when implementing patterns in their projects, there are many
  381. lessons we can learn from their efforts.
  382. </para>
  383. <para>
  384. In this section, were going to review two popular patterns - MVC
  385. and MVP. Well be exploring in greater detail how Backbone.js
  386. implements these patterns shortly to better appreciate where it
  387. fits in.
  388. </para>
  389. </sect2>
  390. </sect1>
  391. <sect1 id="mvc">
  392. <title>MVC</title>
  393. <para>
  394. MVC (Model-View-Controller) is an architectural design pattern that
  395. encourages improved application organization through a separation of
  396. concerns. It enforces the isolation of business data (Models) from
  397. user interfaces (Views), with a third component (Controllers)
  398. traditionally present to manage logic, user-input and the
  399. coordination of models and views. The pattern was originally
  400. designed by
  401. <ulink url="http://en.wikipedia.org/wiki/Trygve_Reenskaug">Trygve
  402. Reenskaug</ulink> while working on Smalltalk-80 (1979), where it was
  403. initially called Model-View-Controller-Editor. MVC was described in
  404. depth in
  405. <ulink url="http://www.amazon.co.uk/Design-patterns-elements-reusable-object-oriented/dp/0201633612"><quote>Design
  406. Patterns: Elements of Reusable Object-Oriented
  407. Software</quote></ulink> (The <quote>GoF</quote> or <quote>Gang of
  408. Four</quote> book) in 1994, which played a role in popularizing its
  409. use.
  410. </para>
  411. <sect2 id="smalltalk-80-mvc">
  412. <title>Smalltalk-80 MVC</title>
  413. <para>
  414. Its important to understand what the original MVC pattern was
  415. aiming to solve as it has changed quite heavily since the days of
  416. its origin. Back in the 70s, graphical user-interfaces were far
  417. and few between. An approach known as
  418. <ulink url="http://martinfowler.com/eaaDev/uiArchs.html">Separated
  419. Presentation</ulink> began to be used as a means to make a clear
  420. division between domain objects which modeled concepts in the real
  421. world (e.g a photo, a person) and the presentation objects which
  422. were rendered to the users screen.
  423. </para>
  424. <para>
  425. The Smalltalk-80 implementation of MVC took this concept further
  426. and had an objective of separating out the application logic from
  427. the user interface. The idea was that decoupling these parts of
  428. the application would also allow the reuse of models for other
  429. interfaces in the application. There are some interesting points
  430. worth noting about Smalltalk-80s MVC architecture:
  431. </para>
  432. <itemizedlist>
  433. <listitem>
  434. <para>
  435. A Domain element was known as a Model and were ignorant of the
  436. user-interface (Views and Controllers)
  437. </para>
  438. </listitem>
  439. <listitem>
  440. <para>
  441. Presentation was taken care of by the View and the Controller,
  442. but there wasnt just a single view and controller. A
  443. View-Controller pair was required for each element being
  444. displayed on the screen and so there was no true separation
  445. between them
  446. </para>
  447. </listitem>
  448. <listitem>
  449. <para>
  450. The Controllers role in this pair was handling user input
  451. (such as key-presses and click events), doing something
  452. sensible with them.
  453. </para>
  454. </listitem>
  455. <listitem>
  456. <para>
  457. The Observer pattern was relied upon for updating the View
  458. whenever the Model changed
  459. </para>
  460. </listitem>
  461. </itemizedlist>
  462. <para>
  463. Developers are sometimes surprised when they learn that the
  464. Observer pattern (nowadays commonly implemented as a
  465. Publish/Subscribe system) was included as a part of MVCs
  466. architecture decades ago. In Smalltalk-80s MVC, the View and
  467. Controller both observe the Model: anytime the Model changes, the
  468. Views react. A simple example of this is an application backed by
  469. stock market data - for the application to show real-time
  470. information, any change to the data in its Models should result in
  471. the View being refreshed instantly.
  472. </para>
  473. <para>
  474. Martin Fowler has done an excellent job of writing about the
  475. <ulink url="http://martinfowler.com/eaaDev/uiArchs.html">origins</ulink>
  476. of MVC over the years and if you are interested in further
  477. historical information about Smalltalk-80s MVC, I recommend
  478. reading his work.
  479. </para>
  480. </sect2>
  481. </sect1>
  482. <sect1 id="mvc-as-we-know-it">
  483. <title>MVC As We Know It</title>
  484. <para>
  485. Weve reviewed the 70s, but let us now return to the here and now.
  486. The MVC pattern has been applied to a diverse range of programming
  487. languages. For example, the popular Ruby on Rails is an
  488. implementation of a web application framework based on MVC for the
  489. Ruby language. JavaScript now has a number of MVC frameworks,
  490. including Ember.js, JavaScriptMVC, and of course Backbone.js. Given
  491. the importance of avoiding <quote>spaghetti</quote> code, a term
  492. which describes code that is very difficult to read or maintain due
  493. to its lack of structure, lets look at what the MVC pattern enables
  494. the Javascript developer to do.
  495. </para>
  496. <para>
  497. MVC is composed of three core components:
  498. </para>
  499. <sect2 id="models">
  500. <title>Models</title>
  501. <para>
  502. Models manage the data for an application. They are concerned with
  503. neither the user-interface nor presentation layers, but instead
  504. represent structured data that an application may require. When a
  505. model changes (e.g when it is updated), it will typically notify
  506. its observers (e.g views, a concept we will cover shortly) that a
  507. change has occurred so that they may react accordingly.
  508. </para>
  509. <para>
  510. To understand models better, let us imagine we have a JavaScript
  511. photo gallery application. In a photo gallery, a photo would merit
  512. its own model, as it represents a unique kind of domain-specific
  513. data. The Photo model may represent attributes such as a caption,
  514. image source and additional meta-data. A specific photo would be
  515. stored in an instance of a model. Heres an example of a simple
  516. Photo model implemented with Backbone.js:
  517. </para>
  518. <programlisting language="javascript">
  519. var Photo = Backbone.Model.extend({
  520. // Default attributes for the photo
  521. defaults: {
  522. // Ensure that each photo created has an `src`.
  523. src: &quot;placeholder.jpg&quot;,
  524. caption: &quot;A default image&quot;,
  525. viewed: false
  526. },
  527. initialize: function() {
  528. }
  529. });
  530. </programlisting>
  531. <para>
  532. The built-in capabilities of models vary across frameworks,
  533. however its common for them to support validation of attributes,
  534. where attributes represent the properties of the model, such as a
  535. model identifier. When using models in real-world applications we
  536. generally also need a way of persisting models. Persistence allows
  537. us to edit and update models with the knowledge that their most
  538. recent states will be saved somewhere, for example in a web
  539. browsers localStorage data-store or synchronized with a database.
  540. </para>
  541. <para>
  542. A model may also have multiple views observing it. Imagine our
  543. Photo model contained meta-data such as the longitude and latitude
  544. where the photo was taken, a list of people present in the photo,
  545. and a list of tags. A developer could create a single view that
  546. displayed all these attributes, or might create three separate
  547. views to display each attribute. The important detail is that the
  548. Photo model doesnt care how these views are organized, it simply
  549. announces updates to its data as necessary. Well come back to
  550. Views in more detail later.
  551. </para>
  552. <para>
  553. It is not uncommon for modern MVC/MV* frameworks to provide a
  554. means to group models together. In Backbone, these groups are
  555. called <quote>Collections</quote>. Managing models in groups
  556. allows us to write application logic based on notifications from
  557. the group, should any model it contains change. This avoids the
  558. need to manually observe individual model instances.
  559. </para>
  560. <para>
  561. Heres how we might group Photo models into a simplified Backbone
  562. Collection:
  563. </para>
  564. <programlisting language="javascript">
  565. var PhotoGallery = Backbone.Collection.extend({
  566. // Reference to this collection's model.
  567. model: Photo,
  568. // Filter down the list of all photos that have been viewed
  569. viewed: function() {
  570. return this.filter(function(photo){ return photo.get('viewed'); });
  571. },
  572. // Filter down the list to only photos that have not yet been viewed
  573. unviewed: function() {
  574. return this.without.apply(this, this.viewed());
  575. }
  576. });
  577. </programlisting>
  578. <para>
  579. If you read older texts on MVC, you may come across a description
  580. of models as also managing application <quote>state</quote>. In
  581. JavaScript applications <quote>state</quote> has a specific
  582. meaning, typically referring to the current <quote>state</quote>
  583. of a view or sub-view on a users screen at a fixed time. State is
  584. a topic which is regularly discussed when looking at Single-page
  585. applications, where the concept of state needs to be simulated.
  586. </para>
  587. </sect2>
  588. <sect2 id="views">
  589. <title>Views</title>
  590. <para>
  591. Views are a visual representation of models that present a
  592. filtered view of their current state. A view typically observes a
  593. model and is notified when the model changes, allowing the view to
  594. update itself accordingly. Design pattern literature commonly
  595. refers to views as <quote>dumb</quote>, given that their knowledge
  596. of models and controllers in an application is limited.
  597. </para>
  598. <para>
  599. Users interact with views, which usually means reading and editing
  600. model data. For example, in our photo gallery application example,
  601. model viewing might happen in a user interface with a big image, a
  602. caption, and a list of tags. Model editing could be done through
  603. an <quote>edit</quote> view where a user who has selected a
  604. specific photo could edit its caption, tags, or other metadata in
  605. a form.
  606. </para>
  607. <para>
  608. In MVC, the actual task of updating the Model falls to
  609. Controllers, which well be covering shortly.
  610. </para>
  611. <para>
  612. Lets explore Views a little further using a simple JavaScript
  613. example. Below we can see a function that creates a single Photo
  614. view, consuming both a model instance and a controller instance.
  615. </para>
  616. <para>
  617. We define a <literal>render()</literal> utility within our view
  618. which is responsible for rendering the contents of the
  619. <literal>photoModel</literal> using a JavaScript templating engine
  620. (Underscore templating) and updating the contents of our view,
  621. referenced by <literal>photoEl</literal>.
  622. </para>
  623. <para>
  624. The <literal>photoModel</literal> then adds our
  625. <literal>render()</literal> callback as one of its subscribers, so
  626. that through the Observer pattern it can trigger the view to
  627. update when the model changes.
  628. </para>
  629. <para>
  630. You may wonder where user interaction comes into play here. When
  631. users click on any elements within the view, its not the views
  632. responsibility to know what to do next. A Controller makes this
  633. decision. In our sample implementation, this is achieved by adding
  634. an event listener to <literal>photoEl</literal> which will
  635. delegate handling the click behavior back to the controller,
  636. passing the model information along with it in case its needed.
  637. </para>
  638. <para>
  639. The benefit of this architecture is that each component plays its
  640. own separate role in making the application function as needed.
  641. </para>
  642. <programlisting language="javascript">
  643. var buildPhotoView = function( photoModel, photoController ){
  644. var base = document.createElement('div'),
  645. photoEl = document.createElement('div');
  646. base.appendChild(photoEl);
  647. var render= function(){
  648. // We use a templating library such as Underscore
  649. // templating which generates the HTML for our
  650. // photo entry
  651. photoEl.innerHTML = _.template('photoTemplate', {src: photoModel.getSrc()});
  652. }
  653. photoModel.addSubscriber( render );
  654. photoEl.addEventListener('click', function(){
  655. photoController.handleEvent('click', photoModel );
  656. });
  657. var show = function(){
  658. photoEl.style.display = '';
  659. }
  660. var hide = function(){
  661. photoEl.style.display = 'none';
  662. }
  663. return{
  664. showView: show,
  665. hideView: hide
  666. }
  667. }
  668. </programlisting>
  669. <para>
  670. <emphasis role="strong">Templating</emphasis>
  671. </para>
  672. <para>
  673. In the context of JavaScript frameworks that support MVC/MV*, it
  674. is worth looking more closely at JavaScript templating and its
  675. relationship to Views.
  676. </para>
  677. <para>
  678. It has long been considered bad practice (and computationally
  679. expensive) to manually create large blocks of HTML markup
  680. in-memory through string concatenation. Developers using this
  681. technique often find themselves iterating through their data,
  682. wrapping it in nested divs and using outdated techniques such as
  683. <literal>document.write</literal> to inject the
  684. <quote>template</quote> into the DOM. This approach often means
  685. keeping scripted markup inline with standard markup, which can
  686. quickly become difficult to read and maintain, especially when
  687. building large applications.
  688. </para>
  689. <para>
  690. JavaScript templating libraries (such as Handlebars.js or
  691. Mustache) are often used to define templates for views as HTML
  692. markup containing template variables. These template blocks can be
  693. either stored externally or within script tags with a custom type
  694. (e.g <quote>text/template</quote>). Variables are deliminated
  695. using a variable syntax (e.g {{name}}). Javascript template
  696. libraries typically accept data in JSON, and the grunt work of
  697. populating templates with data is taken care of by the framework
  698. itself. This has a several benefits, particularly when opting to
  699. store templates externally as this can let applications load
  700. templates dynamically on an as-needed basis.
  701. </para>
  702. <para>
  703. Lets compare two examples of HTML templates. One is implemented
  704. using the popular Handlebars.js library, and the other uses
  705. Underscores <quote>microtemplates</quote>.
  706. </para>
  707. <para>
  708. <emphasis role="strong">Handlebars.js:</emphasis>
  709. </para>
  710. <programlisting language="html">
  711. &lt;li class=&quot;photo&quot;&gt;
  712. &lt;h2&gt;{{caption}}&lt;/h2&gt;
  713. &lt;img class=&quot;source&quot; src=&quot;{{src}}&quot;/&gt;
  714. &lt;div class=&quot;meta-data&quot;&gt;
  715. {{metadata}}
  716. &lt;/div&gt;
  717. &lt;/li&gt;
  718. </programlisting>
  719. <para>
  720. <emphasis role="strong">Underscore.js Microtemplates:</emphasis>
  721. </para>
  722. <programlisting language="html">
  723. &lt;li class=&quot;photo&quot;&gt;
  724. &lt;h2&gt;&lt;%= caption %&gt;&lt;/h2&gt;
  725. &lt;img class=&quot;source&quot; src=&quot;&lt;%= src %&gt;&quot;/&gt;
  726. &lt;div class=&quot;meta-data&quot;&gt;
  727. &lt;%= metadata %&gt;
  728. &lt;/div&gt;
  729. &lt;/li&gt;
  730. </programlisting>
  731. <para>
  732. You may also use double curly brackets (i.e
  733. <literal>{{}}</literal>) (or any other tag you feel comfortable
  734. with) in Microtemplates. In the case of curly brackets, this can
  735. be done by setting the Underscore
  736. <literal>templateSettings</literal> attribute as follows:
  737. </para>
  738. <programlisting language="javascript">
  739. _.templateSettings = { interpolate : /\{\{(.+?)\}\}/g };
  740. </programlisting>
  741. <para>
  742. <emphasis role="strong">A note on navigation and state</emphasis>
  743. </para>
  744. <para>
  745. It is also worth noting that in classical web development,
  746. navigating between independent views required the use of a page
  747. refresh. In single-page JavaScript applications, however, once
  748. data is fetched from a server via Ajax, it can be dynamically
  749. rendered in a new view within the same page. Since this doesnt
  750. automatically update the URL, the role of navigation thus falls to
  751. a <quote>router</quote>, which assists in managing application
  752. state (e.g allowing users to bookmark a particular view they have
  753. navigated to). As routers are however neither a part of MVC nor
  754. present in every MVC-like framework, I will not be going into them
  755. in greater detail in this section.
  756. </para>
  757. </sect2>
  758. <sect2 id="controllers">
  759. <title>Controllers</title>
  760. <para>
  761. Controllers are an intermediary between models and views which are
  762. classically responsible for two tasks: they both update the view
  763. when the model changes and update the model when the user
  764. manipulates the view.
  765. </para>
  766. <para>
  767. In our photo gallery application, a controller would be
  768. responsible for handling changes the user made to the edit view
  769. for a particular photo, updating a specific photo model when a
  770. user has finished editing.
  771. </para>
  772. <para>
  773. Its with controllers that most JavaScript MVC frameworks depart
  774. from this interpretation of the MVC pattern. The reasons for this
  775. vary, but in my opinion, Javascript framework authors likely
  776. initially looked at server-side interpretations of MVC (such as
  777. Ruby on Rails), realized that that approach didnt translate 1:1
  778. on the client-side, and so re-interpreted the C in MVC to solve
  779. their state management problem. This was a clever approach, but it
  780. can make it hard for developers coming to MVC for the first time
  781. to understand both the classical MVC pattern and the
  782. <quote>proper</quote> role of controllers in other non-Javascript
  783. frameworks.
  784. </para>
  785. <para>
  786. So does Backbone.js have Controllers? Not really. Backbones Views
  787. typically contain <quote>controller</quote> logic, and Routers
  788. (discussed below) are used to help manage application state, but
  789. neither are true Controllers according to classical MVC.
  790. </para>
  791. <para>
  792. In this respect, contrary to what might be mentioned in the
  793. official documentation or in blog posts, Backbone is neither a
  794. truly MVC/MVP nor MVVM framework. Its in fact better to see it a
  795. member of the MV* family which approaches architecture in its own
  796. way. There is of course nothing wrong with this, but it is
  797. important to distinguish between classical MVC and MV* should you
  798. be relying on discussions of MVC to help with your Backbone
  799. projects.
  800. </para>
  801. </sect2>
  802. <sect2 id="controllers-in-spine.js-vs-backbone.js">
  803. <title>Controllers in Spine.js vs Backbone.js</title>
  804. <para>
  805. <emphasis role="strong">Spine.js</emphasis>
  806. </para>
  807. <para>
  808. We now know that controllers are traditionally responsible for
  809. updating the view when the model changes (and similarly the model
  810. when the user updates the view). Since Backbone doesnt have its
  811. <emphasis role="strong">own</emphasis> explicit controllers, its
  812. useful to review the controller from another MVC framework to
  813. appreciate the difference in implementations. Lets take a look at
  814. <ulink url="http://spinejs.com/">Spine.js</ulink>:
  815. </para>
  816. <para>
  817. In this example, were going to have a controller called
  818. <literal>PhotosController</literal> which will be in charge of
  819. individual photos in the application. It will ensure that when the
  820. view updates (e.g a user edited the photo meta-data) the
  821. corresponding model does too.
  822. </para>
  823. <para>
  824. (Note: We wont be delving heavily into Spine.js beyond this
  825. example, but its worth looking at it to learn more about
  826. Javascript frameworks in general.)
  827. </para>
  828. <programlisting language="javascript">
  829. // Controllers in Spine are created by inheriting from Spine.Controller
  830. var PhotosController = Spine.Controller.sub({
  831. init: function(){
  832. this.item.bind(&quot;update&quot;, this.proxy(this.render));
  833. this.item.bind(&quot;destroy&quot;, this.proxy(this.remove));
  834. },
  835. render: function(){
  836. // Handle templating
  837. this.replace($(&quot;#photoTemplate&quot;).tmpl(this.item));
  838. return this;
  839. },
  840. remove: function(){
  841. this.el.remove();
  842. this.release();
  843. }
  844. });
  845. </programlisting>
  846. <para>
  847. In Spine, controllers are considered the glue for an application,
  848. adding and responding to DOM events, rendering templates and
  849. ensuring that views and models are kept in sync (which makes sense
  850. in the context of what we know to be a controller).
  851. </para>
  852. <para>
  853. What were doing in the above example is setting up listeners in
  854. the <literal>update</literal> and <literal>destroy</literal>
  855. events using <literal>render()</literal> and
  856. <literal>remove()</literal>. When a photo entry gets updated, we
  857. re-render the view to reflect the changes to the meta-data.
  858. Similarly, if the photo gets deleted from the gallery, we remove
  859. it from the view. In case you were wondering about the
  860. <literal>tmpl()</literal> function in the code snippet: in the
  861. <literal>render()</literal> function, were using this to render a
  862. JavaScript template called #photoTemplate which simply returns a
  863. HTML string used to replace the controllers current element.
  864. </para>
  865. <para>
  866. What this provides us with is a very lightweight, simple way to
  867. manage changes between the model and the view.
  868. </para>
  869. <para>
  870. <emphasis role="strong">Backbone.js</emphasis>
  871. </para>
  872. <para>
  873. Later on in this section were going to revisit the differences
  874. between Backbone and traditional MVC, but for now lets focus on
  875. controllers.
  876. </para>
  877. <para>
  878. In Backbone, controller logic is shared between Backbone.View and
  879. Backbone.Router. Earlier releases of Backbone contained something
  880. called Backbone.Controller, but it was renamed to Router to
  881. clarify its role.
  882. </para>
  883. <para>
  884. A Routers main purpose is to translate URL requests into
  885. application states. When a user browses to the URL
  886. www.example.com/photos/42, a Router could be used to show the
  887. photo with that ID, and to define what application behavior should
  888. be run in response to that request. Routers
  889. <emphasis>can</emphasis> contain traditional controller
  890. responsibilities, such as binding the events between models and
  891. views, or rendering parts of the page. However, Backbone
  892. contributor Tim Branyen has pointed out that its possible to get
  893. away without needing Backbone.Router at all for this, so a way to
  894. think about it using the Router paradigm is probably:
  895. </para>
  896. <programlisting language="javascript">
  897. var PhotoRouter = Backbone.Router.extend({
  898. routes: { &quot;photos/:id&quot;: &quot;route&quot; },
  899. route: function(id) {
  900. var item = photoCollection.get(id);
  901. var view = new PhotoView({ model: item });
  902. something.html( view.render().el );
  903. }
  904. }):
  905. </programlisting>
  906. </sect2>
  907. </sect1>
  908. <sect1 id="what-does-mvc-give-us">
  909. <title>What does MVC give us?</title>
  910. <para>
  911. To summarize, the separation of concerns in MVC facilitates
  912. modularization of an applications functionality and enables:
  913. </para>
  914. <itemizedlist>
  915. <listitem>
  916. <para>
  917. Easier overall maintenance. When updates need to be made to the
  918. application it is clear whether the changes are data-centric,
  919. meaning changes to models and possibly controllers, or merely
  920. visual, meaning changes to views.<literallayout></literallayout>
  921. </para>
  922. </listitem>
  923. <listitem>
  924. <para>
  925. Decoupling models and views means that its straight-forward to
  926. write unit tests for business
  927. logic<literallayout></literallayout>
  928. </para>
  929. </listitem>
  930. <listitem>
  931. <para>
  932. Duplication of low-level model and controller code is eliminated
  933. across the application
  934. </para>
  935. </listitem>
  936. <listitem>
  937. <para>
  938. Depending on the size of the application and separation of
  939. roles, this modularity allows developers responsible for core
  940. logic and developers working on the user-interfaces to work
  941. simultaneously
  942. </para>
  943. </listitem>
  944. </itemizedlist>
  945. <sect2 id="delving-deeper">
  946. <title>Delving deeper</title>
  947. <para>
  948. Right now, you likely have a basic understanding of what the MVC
  949. pattern provides, but for the curious, well explore it a little
  950. further.
  951. </para>
  952. <para>
  953. The GoF (Gang of Four) do not refer to MVC as a design pattern,
  954. but rather consider it a <quote>set of classes to build a user
  955. interface</quote>. In their view, its actually a variation of
  956. three other classical design patterns: the Observer (Pub/Sub),
  957. Strategy and Composite patterns. Depending on how MVC has been
  958. implemented in a framework, it may also use the Factory and
  959. Decorator patterns. Ive covered some of these patterns in my
  960. other free book, JavaScript Design Patterns For Beginners if you
  961. would like to read into them further.
  962. </para>
  963. <para>
  964. As weve discussed, models represent application data, while views
  965. handle what the user is presented on screen. As such, MVC relies
  966. on Pub/Sub for some of its core communication (something that
  967. surprisingly isnt covered in many articles about the MVC
  968. pattern). When a model is changed it <quote>publishes</quote> to
  969. the rest of the application that it has been updated. The
  970. <quote>subscriber</quote>generally a Controllerthen updates the
  971. view accordingly. The observer-viewer nature of this relationship
  972. is what facilitates multiple views being attached to the same
  973. model.
  974. </para>
  975. <para>
  976. For developers interested in knowing more about the decoupled
  977. nature of MVC (once again, depending on the implementation), one
  978. of the goals of the pattern is to help define one-to-many
  979. relationships between a topic and its observers. When a topic
  980. changes, its observers are updated. Views and controllers have a
  981. slightly different relationship. Controllers facilitate views to
  982. respond to different user input and are an example of the Strategy
  983. pattern.
  984. </para>
  985. </sect2>
  986. <sect2 id="summary">
  987. <title>Summary</title>
  988. <para>
  989. Having reviewed the classical MVC pattern, your should now
  990. understand how it allows developers to cleanly separate concerns
  991. in an application. You should also now appreciate how JavaScript
  992. MVC frameworks may differ in their interpretation of MVC, and how
  993. they share some of the fundamental concepts of the original
  994. pattern.
  995. </para>
  996. <para>
  997. When reviewing a new JavaScript MVC/MV* framework, remember - it
  998. can be useful to step back and consider how its opted to approach
  999. Models, Views, Controllers or other alternatives, as this can
  1000. better help you grok how the framework expects to be used.
  1001. </para>
  1002. </sect2>
  1003. </sect1>
  1004. <sect1 id="mvp">
  1005. <title>MVP</title>
  1006. <para>
  1007. Model-view-presenter (MVP) is a derivative of the MVC design pattern
  1008. which focuses on improving presentation logic. It originated at a
  1009. company named
  1010. <ulink url="http://en.wikipedia.org/wiki/Taligent">Taligent</ulink>
  1011. in the early 1990s while they were working on a model for a C++
  1012. CommonPoint environment. Whilst both MVC and MVP target the
  1013. separation of concerns across multiple components, there are some
  1014. fundamental differences between them.
  1015. </para>
  1016. <para>
  1017. For the purposes of this summary we will focus on the version of MVP
  1018. most suitable for web-based architectures.
  1019. </para>
  1020. <sect2 id="models-views-presenters">
  1021. <title>Models, Views &amp; Presenters</title>
  1022. <para>
  1023. The P in MVP stands for presenter. Its a component which contains
  1024. the user-interface business logic for the view. Unlike MVC,
  1025. invocations from the view are delegated to the presenter, which
  1026. are decoupled from the view and instead talk to it through an
  1027. interface. This allows for all kinds of useful things such as
  1028. being able to mock views in unit tests.
  1029. </para>
  1030. <para>
  1031. The most common implementation of MVP is one which uses a Passive
  1032. View (a view which is for all intents and purposes
  1033. <quote>dumb</quote>), containing little to no logic. MVP models
  1034. are almost identical to MVC models and handle application data.
  1035. The presenter acts as a mediator which talks to both the view and
  1036. model, however both of these are isolated from each other. They
  1037. effectively bind models to views, a responsibility held by
  1038. Controllers in MVC. Presenters are at the heart of the MVP pattern
  1039. and as you can guess, incorporate the presentation logic behind
  1040. views.
  1041. </para>
  1042. <para>
  1043. Solicited by a view, presenters perform any work to do with user
  1044. requests and pass data back to them. In this respect, they
  1045. retrieve data, manipulate it and determine how the data should be
  1046. displayed in the view. In some implementations, the presenter also
  1047. interacts with a service layer to persist data (models). Models
  1048. may trigger events but its the presenters role to subscribe to
  1049. them so that it can update the view. In this passive architecture,
  1050. we have no concept of direct data binding. Views expose setters
  1051. which presenters can use to set data.
  1052. </para>
  1053. <para>
  1054. The benefit of this change from MVC is that it increases the
  1055. testability of your application and provides a more clean
  1056. separation between the view and the model. This isnt however
  1057. without its costs as the lack of data binding support in the
  1058. pattern can often mean having to take care of this task
  1059. separately.
  1060. </para>
  1061. <para>
  1062. Although a common implementation of a
  1063. <ulink url="http://martinfowler.com/eaaDev/PassiveScreen.html">Passive
  1064. View</ulink> is for the view to implement an interface, there are
  1065. variations on it, including the use of events which can decouple
  1066. the View from the Presenter a little more. As we dont have the
  1067. interface construct in JavaScript, were using it more as more a
  1068. protocol than an explicit interface here. Its technically still
  1069. an API and its probably fair for us to refer to it as an
  1070. interface from that perspective.
  1071. </para>
  1072. <para>
  1073. There is also a
  1074. <ulink url="http://martinfowler.com/eaaDev/SupervisingPresenter.html">Supervising
  1075. Controller</ulink> variation of MVP, which is closer to the MVC
  1076. and
  1077. <ulink url="http://en.wikipedia.org/wiki/Model_View_ViewModel">MVVM</ulink>
  1078. patterns as it provides data-binding from the Model directly from
  1079. the View. Key-value observing (KVO) plugins (such as Derick
  1080. Baileys Backbone.ModelBinding plugin) introduce this idea of a
  1081. Supervising Controller to Backbone.
  1082. </para>
  1083. </sect2>
  1084. </sect1>
  1085. <sect1 id="mvp-or-mvc">
  1086. <title>MVP or MVC?</title>
  1087. <para>
  1088. MVP is generally used most often in enterprise-level applications
  1089. where its necessary to reuse as much presentation logic as
  1090. possible. Applications with very complex views and a great deal of
  1091. user interaction may find that MVC doesnt quite fit the bill here
  1092. as solving this problem may mean heavily relying on multiple
  1093. controllers. In MVP, all of this complex logic can be encapsulated
  1094. in a presenter, which can simplify maintenance greatly.
  1095. </para>
  1096. <para>
  1097. As MVP views are defined through an interface and the interface is
  1098. technically the only point of contact between the system and the
  1099. view (other than a presenter), this pattern also allows developers
  1100. to write presentation logic without needing to wait for designers to
  1101. produce layouts and graphics for the application.
  1102. </para>
  1103. <para>
  1104. Depending on the implementation, MVP may be more easy to
  1105. automatically unit test than MVC. The reason often cited for this is
  1106. that the presenter can be used as a complete mock of the
  1107. user-interface and so it can be unit tested independent of other
  1108. components. In my experience this really depends on the languages
  1109. you are implementing MVP in (theres quite a difference between
  1110. opting for MVP for a JavaScript project over one for say, ASP.net).
  1111. </para>
  1112. <para>
  1113. At the end of the day, the underlying concerns you may have with MVC
  1114. will likely hold true for MVP given that the differences between
  1115. them are mainly semantic. As long as you are cleanly separating
  1116. concerns into models, views and controllers (or presenters) you
  1117. should be achieving most of the same benefits regardless of the
  1118. pattern you opt for.
  1119. </para>
  1120. </sect1>
  1121. <sect1 id="mvc-mvp-and-backbone.js">
  1122. <title>MVC, MVP and Backbone.js</title>
  1123. <para>
  1124. There are very few, if any architectural JavaScript frameworks that
  1125. claim to implement the MVC or MVP patterns in their classical form
  1126. as many JavaScript developers dont view MVC and MVP as being
  1127. mutually exclusive (we are actually more likely to see MVP strictly
  1128. implemented when looking at web frameworks such as ASP.net or GWT).
  1129. This is because its possible to have additional presenter/view
  1130. logic in your application and yet still consider it a flavor of MVC.
  1131. </para>
  1132. <para>
  1133. Backbone contributor <ulink url="http://ireneros.com/">Irene
  1134. Ros</ulink> subscribes to this way of thinking as when she separates
  1135. Backbone views out into their own distinct components, she needs
  1136. something to actually assemble them for her. This could either be a
  1137. controller route (such as a <literal>Backbone.Router</literal>,
  1138. covered later in the book) or a callback in response to data being
  1139. fetched.
  1140. </para>
  1141. <para>
  1142. That said, some developers do however feel that Backbone.js better
  1143. fits the description of MVP than it does MVC . Their view is that:
  1144. </para>
  1145. <itemizedlist>
  1146. <listitem>
  1147. <para>
  1148. The presenter in MVP better describes the
  1149. <literal>Backbone.View</literal> (the layer between View
  1150. templates and the data bound to it) than a controller does
  1151. </para>
  1152. </listitem>
  1153. <listitem>
  1154. <para>
  1155. The model fits <literal>Backbone.Model</literal> (it isnt that
  1156. different from the classical MVC
  1157. <quote>Model</quote>)<literallayout></literallayout>
  1158. </para>
  1159. </listitem>
  1160. <listitem>
  1161. <para>
  1162. The views best represent templates (e.g Handlebars/Mustache
  1163. markup templates)
  1164. </para>
  1165. </listitem>
  1166. </itemizedlist>
  1167. <para>
  1168. A response to this could be that the view can also just be a View
  1169. (as per MVC) because Backbone is flexible enough to let it be used
  1170. for multiple purposes. The V in MVC and the P in MVP can both be
  1171. accomplished by <literal>Backbone.View</literal> because theyre
  1172. able to achieve two purposes: both rendering atomic components and
  1173. assembling those components rendered by other views.
  1174. </para>
  1175. <para>
  1176. Weve also seen that in Backbone the responsibility of a controller
  1177. is shared with both the Backbone.View and Backbone.Router and in the
  1178. following example we can actually see that aspects of that are
  1179. certainly true.
  1180. </para>
  1181. <para>
  1182. Here, our Backbone <literal>PhotoView</literal> uses the Observer
  1183. pattern to <quote>subscribe</quote> to changes to a Views model in
  1184. the line <literal>this.model.bind('change',...)</literal>. It also
  1185. handles templating in the <literal>render()</literal> method, but
  1186. unlike some other implementations, user interaction is also handled
  1187. in the View (see <literal>events</literal>).
  1188. </para>
  1189. <programlisting language="javascript">
  1190. var PhotoView = Backbone.View.extend({
  1191. //... is a list tag.
  1192. tagName: &quot;li&quot;,
  1193. // Pass the contents of the photo template through a templating
  1194. // function, cache it for a single photo
  1195. template: _.template($('#photo-template').html()),
  1196. // The DOM events specific to an item.
  1197. events: {
  1198. &quot;click img&quot; : &quot;toggleViewed&quot;
  1199. },
  1200. // The PhotoView listens for changes to its model, re-rendering. Since there's
  1201. // a one-to-one correspondence between a **Photo** and a **PhotoView** in this
  1202. // app, we set a direct reference on the model for convenience.
  1203. initialize: function() {
  1204. _.bindAll(this, 'render');
  1205. this.model.bind('change', this.render);
  1206. this.model.bind('destroy', this.remove);
  1207. },
  1208. // Re-render the photo entry
  1209. render: function() {
  1210. $(this.el).html(this.template(this.model.toJSON()));
  1211. return this;
  1212. },
  1213. // Toggle the `&quot;viewed&quot;` state of the model.
  1214. toggleViewed: function() {
  1215. this.model.viewed();
  1216. }
  1217. });
  1218. </programlisting>
  1219. <para>
  1220. Another (quite different) opinion is that Backbone more closely
  1221. resembles
  1222. <ulink url="http://martinfowler.com/eaaDev/uiArchs.html#ModelViewController">Smalltalk-80
  1223. MVC</ulink>, which we went t

Large files files are truncated, but you can click here to view the full file