Webapps

Como conocerlas y amarlas

Created by Javi A. / @johnhackworth

Un poco de historia

De dónde venimos

Pre-2004

  • Html plano
  • Plantillas renderizadas en servidor (java, asp, algo de php..)
  • AJAX? WTF?
  • El server manda en TODO

Por ejemplo:

YUI, Prototype & Dojo Toolkit

2004 - 2006

  • Plantillas renderizadas en servidor (java, php)
  • Interacción "rica" en cliente, vía javascript
  • Primeros intentos de 'domar' la prog. cliente (dojo)
  • Complicado de la hostia, incompatibilidades entre browsers

Por ejemplo:

2006

jQuery

2006 - 2010

  • Estandarización entre browsers
  • Eliminación de diferencias entre browsers
  • Consistencia entre browsers
  • Un sólo desarrollo para diferentes browsers
  • La programación en cliente como programación, no como puzzle
  • Sistema de plugins FÁCIL + componentes interfaz estandar

2011

Backbone, Spine, Ember, Angular, Coffeescript, Batman, blahblahblah

2011+

  • Incorporación de gente de servidor (AKA: Gente que sabe programar)
  • Aplicación de paradigmas de servidor al cliente
  • MVC, MVVM, etc
  • Lógica de presentación en cliente
  • Thick Client (cliente pesado)
  • AMD

Anatomía de una webapp actual

Templates

Plantillas renderizadas y refrescadas desde cliente. Propuestas por primera vez (hasta donde yo sé) por John Resig en http://ejohn.org/blog/javascript-micro-templating/.


Logiless

Mustache, Handlebars, Hogan


Logicfull

Underscore, dot, ejs

Aspecto de una plantilla

Handlebars

            <div class="entry">
              <h1>{{title}}</h1>
              <div class="body">
                {{body}}
              </div>
            </div>
          

Underscore

            <div class="entry">
              <h1><%= title %></h1>
              <div class="body">
                <% print(body.toLowercase()) %>
              </div>
            </div>
          

Presentación y animaciones

CSS3

  • Animaciones
  • Menús
  • Transiciones
  • MAGIA

Código

MVC vs MVVM

MVC

  • Model - View - Controller
  • Separación entre datos y presentación
  • Más fácil para gente de back, más limpio
  • Backbone, Spine, Ember


MVVM

  • Model - View - Viewmodel
  • Datos y presentación unidos
  • Más fácil para gente de front
  • Angular, Knockout

Backbone

Qué es backbone?

Backbone es un framework MVC muy muy ligero
(1500 lineas de código en total).

Proporciona:

  • Una abstracción de la capa de persistencia de datos (una API rest)
  • Un sistema de gestión de rutas
  • Un sistema de herencia de clases (para modelos y controladores)
  • Una estructura estandar (models (modelos), views (controllers), vistas (el sistema de plantillas que quiera el usuario))

Qué NO es backbone?

Para todo lo demás, Backbone es no-opionated. Es agnóstico a que sistema de plantillas se utilize, a que se use para hacer el data binding, testing, etc.

Las únicas dependencias 'duras' de backbone son jquery/zepto y underscore (y json2 si se quiere compatibilidad con Satán (ie < 9))

Ventajas y desventajas del un-opinionantismo

  • + Da mucha flexibilidad al usuario y no te impone como hacer las cosas
  • - Obliga a tomar decisiones desde el principio, por lo que los primeros pasos pueden ser más duros
  • + Mucho más adaptable al proyecto
  • - Necesidad de mucho boilerplate

MVC en backbone

(L)User
OutputInput
View (Templates)
.html()DOM events
Controllers (Backbone.View)
model eventsmodel methods
Models (Backbone.Model)
AJAX
Data persistence ⛁ (API REST)

Modelos

Modelan un recurso. Normalmente se "suscriben" (vía .url) a un punto de entrada de una API rest y consumen y persisten los datos a través de ese entry point.



Propiedades importantes

  • .url / .url()
  • .get() / .set() (siempre!)
  • .toJSON()
  • .defaults (cuidado!)
  • .fetch() -> GET
  • .save() -> POST o PUT
  • .destroy() -> DELETE
  • .validate()

Un modelo de backbone

            
              var userModel = Backbone.Model.extend({
                defaults: {
                  name: '',
                  age: 0
                },
                initialize: function(params) {
                  this.friends = [] // importante hacer esto así!
                },
                url: 'http://example.com/user/'
              })
            
          

Colecciones

Arrays de modelos con cierta funcionalidad propia


  • .url -> Recurso que devuelve un array de datos
  • .model -> Model de backbone al que castea los datos
  • .fetch / .toJSON / etc
  • No ofrece paginación (maaaaaal)

Controller (Backbone.View)

Enlaza los datos (modelo) con lo que ve el usuario (temmplates). Escucha eventos en ambos sitios y lanza las acciones adecuadas cuando se producen


Propiedades importantes

  • .el -> nodo jQuery del DOM dónde se pintará la vista asociada
  • .render() -> Método que lanza el pintado de la vista en el DOM
  • .events -> Diccionario con las acciones que se lanzan cuando se producen eventos en el DOM
  • .model -> Instancia de un model asociada a la vista

Un ejemplo de controller

            
              var userProfileController = Backbone.View.extend({
                events: {
                  "click .save": "saveUser",
                  "change .name": "updateName"
                },
                template: 'http://example.com/userProfile.html',
                initialize: function() {
                  this.model.on('change', this.render.bind(this));
                  this.model.fetch();
                },
                saveUser: function() {
                  this.model.save();
                },
                updateName: function() {
                  var userName = this.$('.name').val();
                  this.model.set('name', userName);
                },
                render: function() {
                  var userData = this.model.toJSON();
                  var view = _.template(this.template, userData);
                  this.$el.html(view)
                }
              })
            
          

Routers

Escuchan los cambios en el hash de la url y ejecutan acciones en función de ellos. También pueden usarse con urls completas, usando Push State.

Backbone.history.start() pone a backbone a escuchar los cambios en la url


Un ejemplo de Router

            
              var routes = Backbone.Router.extend({
                routes: {
                  "!/userProfile/:id": "showUserProfile"
                  // http://example.com/#!/userProfile
                },
                showUserProfile: function(id) {
                  var userModel = new userModel({id: id});
                  var userController = new userProfileController({
                    el: $('.profile'),
                    model: userModel
                  })
                }
              })

              Backbone.history.start()
            
          

Boilerplate

(AKA: Cosas que hay que escribir en cada proyecto)

  • Data Binding
  • Carga de Templates & estáticos
  • Parent inheritance
  • Gestión de memoria en binds a modelos


En principio, Marionette dará algunas de estas cosas resueltas, el resto están ya resueltas en sonata Retail

process.end()

Preguntas?