¿Qué es BackboneJS? Primeros pasos

Si algo tiene de especial el mundo del desarrollo Web es que cada día siempre hay algo nuevo que aprender, tecnologías que probar y frameworks con los que experimentar otros caminos para hacer del desarrollo de nuestros proyectos una experiencia más sencilla y productiva.

En la actualidad existen tantos frameworks diferentes como multitud de lenguajes y técnicas de programación podamos imaginar.

Si todavía te preguntas la razón por la que utilizar un framework para tus proyectos es una siempre una buena idea. Imagina la cantidad de código espagueti que puede puedes generar para hacer que tu programa realice todas las funciones deseadas. Después siempre podemos minimizar el código agrupando funciones, selectores y callbacks en uno o varios archivos y pero esto a la larga se convierte en un infierno imposible de mantener.

¿Seguro que ahora entiendes dónde radica la importancia de utilizar un framework moderno? Podemos ser muy buenos programando pero pretender hacer las cosas por nuestra cuenta, además de reinventar la rueda, supone una dedicación y tiempo que pocas veces es asumible.

De entre todos los Framework para JavaScript Backbone.js recibió mucha atención entre los desarrolladores web debido a su capacidad para organizar el código JavaScript.. No solo implementa el patrón de diseño MVC alrededor de la cual podemos estructurar nuestras aplicaciones web sino que nos ofrece infinidad de funciones, interfaces y utilidades que facilitan de forma “obscena” nuestra tarea. Y esa es una de las razones por las que sigue siendo muy utilizado.

Backbone se trata de un framework muy indicado para desarrollar nuestras propias aplicaciones de una sola página, aunque también resulta útil para proyectos multipágina en donde necesitaremos una interfaz de usuario más avanzada. Entre sus ventajas, facilita la ordenación del código y la sincronización de las vistas con los datos de la aplicación, facilitar el trabajo con datos, vistas para producir nuestro HTML, las interacciones para implementar comportamientos que debe realizar frente a acciones del usuario y los servicios para comunicar con cualquier tecnología que usemos del lado del servidor, ya sea NodeJS, PHP, Ruby, .NET, etc.

Backbone.js implementa cuatro clases:

  • Model: se utiliza para representar los datos de su aplicación. Por ejemplo, un modelo de empleado.
  • Collection: se utiliza para mantener una lista de los objetos de su modelo. Por ejemplo, una colección de empleados que contiene una lista del modelo de empleado.
  • View: cada modelo y colección se puede asociar con una vista Backbone. También puede crear una vista para un elemento DOM existente para que la vista pueda responder a eventos generados a partir de ese elemento DOM.
  • Controller o Router: Como routes.rb en Rails y acciones de controlador. Mapea URLs con funciones.

Resumen de características:

  • Componentes centrales: Modelo, Vista, Colección y Controlador.
  • Comunicación dirigida por eventos entre la capa Vista y Modelo. Ofrece a los desarrolladores un control detallado sobre los cambios que se produzcan en la Vista.
  • Admite enlaces de datos a través de eventos manuales o una mediante el uso de una biblioteca separada para la observación de valores clave (KVO).
  • Compatibilidad con interfaces RESTful listas para usar, por lo que los modelos se pueden vincular fácilmente a un back-end.
  • Los prototipos se instancian con el uso de una palabra clave.
  • La microplantilla Underscore se encuentra disponible por defecto.
  • Convenciones claras y flexibles para estructurar aplicaciones. Backbone no fuerza el uso de todos sus componentes y podemos trabajar sólo con aquellos que sean necesarios.

¿Quien utiliza BackBoneJS?

A día de hoy, Backbone.js no es ningún desconocido en el desarrollo Web. Muchas empresas han usado este framework para construir sus web y aplicaciones. Algunos ejemplos son:

  • Disqus: Disqus eligió Backbone.js para impulsar la última versión de su widget de comentarios. El equipo de Disqus consideró que era la elección correcta para su aplicación web distribuida, dada la pequeña huella de Backbone y la facilidad de extensibilidad.

  • Airbnb: Airbnb desarrolló su aplicación web móvil usando Backbone y ahora la usa en muchos de sus productos.

 

Primeros pasos: Nuestra primera aplicación con BackBone.js

Seguro que estás deseando crear tu primera aplicación con BackBoneJS. Más adelante verás que el proceso no es para nada complicado y te sonará mucho de lo que ya hemos visto programando con JavaScript u otros framework como Angular o React. Pero antes de profundizar en el siguiente código de ejemplo debemos definir un código básico que definirá nuestro proyecto. Se trata de un documento escrito en HTML5 que dará forma a nuestro Index y que puede ser reutilizado para futuros proyectos.

 

Puedes pegar lo siguiente en el editor de texto de su elección, reemplazando la línea comentada entre las etiquetas de script con JavaScript de cualquier ejemplo dado:

index.html

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
       <!-- Your Code -->

     

       <!-- JavaScript Includes -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
        <script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
        <script src="assets/js/script.js"></script>
</body>
</html>

 

Hecho esto, ahora vamos con nuestro proyecto. Se trata de un formulario de selección de servicios con Backbone.js, que le permite elegir un conjunto de elementos de una lista. Un campo de precio total se calculará de manera automática tomando el precio de los servicios. que seleccionemos. El elemento principal en la página será por tanto el formulario que contendrá una lista de elementos para los servicios:

 

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8" />
        <title>Tu primera aplicación con Backbone.js App</title>

        <!-- Google web fonts -->
        <link href="http://fonts.googleapis.com/css?family=PT+Sans:400,700" rel='stylesheet' />

        <!-- The main CSS file -->
        <link href="assets/css/style.css" rel="stylesheet" />

    </head>

    <body>

        <form id="main" method="post" action="submit.php">
            <h1>My Services</h1>

            <ul id="services">
                <!-- The services will be inserted here -->
            </ul>

            <p id="total">total: <span>$0</span></p>

            <input type="submit" id="order" value="Order" />

        </form>

        <!-- JavaScript Includes -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
        <script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>

        <script src="assets/js/script.js"></script>

    </body>
</html>

 

Como puedes ver, al finalizar nuestro formulario es donde luego añadimos las diferentes librerías que utilizaremos además de la propia de Backbone o Underscore que nos ayudará a dotar de funciones al formulario.

Vamos ahora con la parte del programar nuestro JavaScript. Lo primero que haremos será crear un nuestro modelo de servicio que contendrá las propiedades para el nombre del servicio, precio y un campo de estado para saber si este servicio está seleccionado o no.

A partir de aquí se creará un objeto de esta clase para cada servicio que ofrecemos en el formulario y almacenaremos todos los sevicios en una colección Backbone. La idea de fondo es que a partir de una lista predeterminada nuestra aplicación pueda escuchar los eventos que se produzcan (que se generan cada vez que se actualiza la propiedad marcada) y actualizar la vista de nuestra aplicación.

assets/js/script.js

$(function(){

    // Create a model for the services
    var Service = Backbone.Model.extend({

        // Will contain three attributes.
        // These are their default values

        defaults:{
            title: 'My service',
            price: 100,
            checked: false
        },

        // Helper function for checking/unchecking a service
        toggle: function(){
            this.set('checked', !this.get('checked'));
        }
    });

    // Create a collection of services
    var ServiceList = Backbone.Collection.extend({

        // Will hold objects of the Service model
        model: Service,

        // Return an array only with the checked services
        getChecked: function(){
            return this.where({checked:true});
        }
    });

    // Prefill the collection with a number of services.
    var services = new ServiceList([
        new Service({ title: 'web development', price: 200}),
        new Service({ title: 'web design', price: 250}),
        new Service({ title: 'photography', price: 100}),
        new Service({ title: 'coffee drinking', price: 10})
        // Add more here
    ]);

    // This view turns a Service model into HTML. Will create LI elements.
    var ServiceView = Backbone.View.extend({
        tagName: 'li',

        events:{
            'click': 'toggleService'
        },

        initialize: function(){

            // Set up event listeners. The change backbone event
            // is raised when a property changes (like the checked field)

            this.listenTo(this.model, 'change', this.render);
        },

        render: function(){

            // Create the HTML

            this.$el.html('<input type="checkbox" value="1" name="' + this.model.get('title') + '" /> ' + this.model.get('title') + '<span>$' + this.model.get('price') + '</span>');
            this.$('input').prop('checked', this.model.get('checked'));

            // Returning the object is a good practice
            // that makes chaining possible
            return this;
        },

        toggleService: function(){
            this.model.toggle();
        }
    });

    // The main view of the application
    var App = Backbone.View.extend({

        // Base the view on an existing element
        el: $('#main'),

        initialize: function(){

            // Cache these selectors
            this.total = $('#total span');
            this.list = $('#services');

            // Listen for the change event on the collection.
            // This is equivalent to listening on every one of the 
            // service objects in the collection.
            this.listenTo(services, 'change', this.render);

            // Create views for every one of the services in the
            // collection and add them to the page

            services.each(function(service){

                var view = new ServiceView({ model: service });
                this.list.append(view.render().el);

            }, this);   // "this" is the context in the callback
        },

        render: function(){

            // Calculate the total order amount by agregating
            // the prices of only the checked elements

            var total = 0;

            _.each(services.getChecked(), function(elem){
                total += elem.get('price');
            });

            // Update the total price
            this.total.text('$'+total);

            return this;
        }
    });

    new App();

});

 

Como se puede ver el programa tiene un poco de “truco” ya que tenemos que extender las clases proporcionadas por Backbone y anular los métodos que deseamos realizar de una manera diferente. Pero esto también es un buen ejemplo de hasta qué punto este Framework nos permite hacer lo que queramos gracias a su flexibilidad.

La vista principal de nuestra aplicación es App, que está vinculada al formulario #main, inicializa las otras vistas y actualiza el precio total en su método de representación.

Lo que nos queda ahora es poner todo a funcionar y para manejar los envíos desde el formulario vamos a necesitar añadir una línea de PHP. Todo lo que hace es imprimir los nombres de los campos de casilla seleccionados:

submit.php

echo htmlspecialchars(implode(array_keys($_POST), ', '));

 

Y ya lo tenemos. El último paso sería ya personalizar nuestra aplicación mediante CSS pero esa parte ya es algo que va más a gusto de cada uno. Lo importante es que con estos pasos nuestro formulario de selección de servicios desarrollado con Backbone ya está listo.

Como ves es un ejemplo muy sencillo y espero que lo encuentres útil para entender y tener una buena visión general de este framework.

Conclusiones

¿Es Backbone un marco de desarrollo maduro? La respuesta es sí aunque con matices. La elección de un framework no se limita a una cuestión de gustos, que también, o qué tan fácil nos resulte trabajar con ellos. Conviene tener en cuenta qué tan activa es su comunidad y se se producen nuevos lanzamientos periódicos con actualizaciones y mejoras.

A veces ocurre que lo que es futuro ayer, es pasado hoy y no es buena idea dejarse llevar por modas a la hora de seleccionar el framework que utilizaremos en la producción de nuestra aplicación para evitar que este se quede desfasado o facilitar su mantenimiento posterior.

Los framework maduros también tienden a tener disponible una documentación más detallada, ya sea como parte de sus documentos oficiales o impulsados por la comunidad. En el caso de Backbone, su última versión (1.4.0) fue liberada hace ya algo más de un año, más de 3 años de su última versión estable (1.3.3), y aunque cuenta con aplicaciones de referencia, tutoriales y ejemplos más que suficientes para acometer cualquier proyecto su salud o mejor dicho su capacidad de ofrecernos las novedades que necesita el sector puede ser un condicionante para apostar por BackBone en el futuro.