Mostrando entradas con la etiqueta mvc. Mostrar todas las entradas
Mostrando entradas con la etiqueta mvc. Mostrar todas las entradas

lunes, 27 de mayo de 2013

Knockout.js ... lo que Usted no vió

KnockoutJs banner

Le dediqué un tiempo a conocer más acerca del patrón MVVM . Me agrada, así que se suma a la lista de tecnologías relacionadas con Microsoft que realmente recomiendo. Este es un enfoque propuesto por la compañía que consiste, según sus propios autores, en una especialización del enfoque Modelo Vista Controlador para tecnologías como Windows Presentation Foundation y Silverlight. En la ingeniería de software este tipo de soluciones resulta muy útil para construir interfaces de usuario. Su ámbito de aplicación se ha extendido también al framework ZK (del cual tengo muy buenas referencias) y a HTML5. Incluso existe Google mdv, una variante relacionada con estos temas. En mi caso particular puse mi atención en la implementación para Javascript conocida como KnockuotJs. En esta ocasión no pretendo comentarles las peculiaridades de su uso . Para esto les recomiendo leer este artículo y la documentación de KnockoutJs. Más bien pretendo comentarles algunos detalles que me llamaron la atención al probar los tutoriales.

Dependencias y <select />

KnockoutJs tutorial 1

Al terminar con el primer tutorial debe quedarnos como resultado un modelo más o menos como el que se muestra a continuación.

// This is a simple *viewmodel* - JavaScript that defines the data and behavior of your UI
function AppViewModel() {
    this.firstName = ko.observable("Bert");
    this.lastName = ko.observable("Bertington");

    this.fullName = ko.computed(function() {
        return this.firstName() + " " + this.lastName();    
    }, this);

    this.capitalizeLastName = function() {
        var currentVal = this.lastName();        // Read the current value
        this.lastName(currentVal.toUpperCase()); // Write back a modified value
    };
}

// Activates knockout.js
ko.applyBindings(new AppViewModel());

A continuación se muestra la vista relacionada después de añadir un elemento <select /> conectado con el atributo lastName del modelo.

<!-- This is a *view* - HTML markup that defines the appearance of your UI -->

<p>First name: <strong data-bind="text: firstName">todo</strong></p>
<p>Last name: <strong data-bind="text: lastName">todo</strong></p>
<p>First name: <input data-bind="value: firstName" /></p>
<p>Last name: <input data-bind="value: lastName" /></p>
<p>Full name: <strong data-bind="text: fullName"></strong></p>
<button data-bind="click: capitalizeLastName">Go caps</button>

<p>Last name: 
  <select data-bind="value: lastName" >
      <option value="x">Pérez</option>
      <option>Suárez</option>
      <option value="z">García</option>
      <option>Bertington</option>
      <option>BERTINGTON</option>
  </select>
</p>

En este punto me resultó muy interesante que la librería preserva automáticamente la consistencia del modelo teniendo en cuenta los bindings. Esta es la razón por la cual el botón Go caps solo funciona cuando el apellido es Bertington . La razón es que el binding con el combobox limita el número de valores que se le puede asignar al atributo del modelo. En el ejemplo el valor mencionado es el único que tiene también una opción con las letras mayúsculas.

Las listas y <select /> ... otra vez …

KnockoutJs tutorial 2

Pasando la página (literalmente ;) llegamos al segundo ejemplo que trata sobre los bindings para listas y colecciones de objetos. Lo que se muestra es impresionante y se completa cada paso satisfactoriamente; pero ... hay (al menos) un detalle muy sutil que se escapa. Utilizando Firebug, DragonFly o una herramienta similar es posible constatar que el atributo value de los elementos <option /> utilizados para escoger el menú siempre está asignado a una cadena vacía (al menos en las versiones de Opera, Firefox y Google Chrome que utilicé para probar ...). Con el fin de enviar los datos hacia el servidor es posible que sea útil asignar ciertos identificadores. Para lograr ese objetivo en la versión final es posible añadir en el model el atributo mealId

// Class to represent a row in the seat reservations grid
function SeatReservation(name, initialMeal) {
    var self = this;
    self.name = name;
    self.meal = ko.observable(initialMeal);

    self.formattedPrice = ko.computed(function() {
        var price = self.meal().price;
        return price ? "$" + price.toFixed(2) : "None";        
    });
}

// Overall viewmodel for this screen, along with initial state
function ReservationsViewModel() {
    var self = this;

    // Non-editable catalog data - would come from the server
    self.availableMeals = [
        { mealId: "s", mealName: "Standard (sandwich)", price: 0 },
        { mealId: "p", mealName: "Premium (lobster)", price: 34.95 },
        { mealId: "u", mealName: "Ultimate (whole zebra)", price: 290 }
    ];    

    // Editable data
    self.seats = ko.observableArray([
        new SeatReservation("Steve", self.availableMeals[0]),
        new SeatReservation("Bert", self.availableMeals[0])
    ]);

    self.addSeat = function() {
        self.seats.push(new SeatReservation("", self.availableMeals[0]));
    }

    self.removeSeat = function(seat) { self.seats.remove(seat) }

    self.totalSurcharge = ko.computed(function() {
       var total = 0;
       for (var i = 0; i < self.seats().length; i++)
           total += self.seats()[i].meal().price;
       return total;
    });
}

ko.applyBindings(new ReservationsViewModel());

Después es necesario utilizar el binding optionsValue en la vista como se muestra a continuación:

<h2>Your seat reservations</h2>

<button data-bind="click: addSeat">Reserve another seat</button>

<table>
    <thead><tr>
        <th>Passenger name</th><th>Meal</th><th>Surcharge</th><th></th>
    </tr></thead>
    <!-- Todo: Generate table body -->
    <tbody data-bind="foreach: seats">
        <tr>
            <td><input data-bind="value: name" /></td>
            <td><select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName', optionsValue: 'mealId'"></select></td>
            <td data-bind="text: formattedPrice"></td>
            <td><a href="#" data-bind="click: $root.removeSeat">Remove</a></td>
        </tr>
    </tbody>
</table>

<h3 data-bind="visible: totalSurcharge() > 0">
    Total surcharge: $<span data-bind="text: totalSurcharge().toFixed(2)"></span>
</h3>

Al aplicar estos cambios se logra generar unos elementos como los siguientes:

<select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName', optionsValue: 'mealId'">
  <option value="s">Standard (sandwich)</option>
  <option value="p">Premium (lobster)</option>
  <option value="u">Ultimate (whole zebra)</option>
</select>

¡Urra! ... pero no todo es color de rosa. Como resultado la columna Surcharge deja de actualizarse . Por consiguiente no se muestra el sub-total que se calcula en el último paso. Sin embargo el comando Remove introducido en esa misma etapa sí sigue funcionando. Esto me hace pensar que haya algún problema al calcular alguno de los diferentes tipos de bindings involucrados.

Quizás existe una forma de hacer que vuelvan a funcionar las actualizaciones, pero hasta este momento no la he encontrado. Tampoco he tenido mucho tiempo para profundizar en el tema.

Conclusiones

KnockuotJs es una librería excelente. Sinceramente preferiría que algunos detalles de los bindings fueran más parecidos al estilo de Genshi. De todas maneras los própositos son diferentes; quizás ni siquiera sea apropiado o posible realizarlo.

Me da la impresión de que no voy a poder dejar de utilizarlo después que lo pruebe en alguna aplicación. La recomiendo. Le invito a suscribirse a este blog mediante RSS si desea conocer si descubro algo más en el resto de los tutoriales . En próximos artículos comentaré cómo utilizar esta solución para enriquecer la experiencia de usuario de sus aplicaciones. A pesar de estas pifias los resultados son impresionantes.

miércoles, 21 de enero de 2009

Mirando la web de una forma distinta con Google Visualization API

Mirar hacia Google puede llegar a ser para algunos como mirar a las estrellas. Para algunos partiendo de una perspectiva peculiar de admiración, para otros simplemente para estar seguros de que algún día esa estrella no se les venga encima. Lo que si es innegable es que hay que prestarle atención al desarrollo del gigante de Mountain View. Es por esto que hoy comenzamos introduciendo una de las tecnologías de Google que más me ha impresionado: Google Visualization API. Quizás se asombre de saber de mi relación con ella, incluso antes de conocerla.

Mirando hacia Google

Google es una de las grandes empresas que más sigo porque realmente cada día me asombra más. Primeramente es una de las principales defensoras de la adopción del código abierto, y ha encontrado en este ecosistema una vía de sostener un modelo de negocios muy sólido. Por tal razón también se inclina por la adopción de otras tecnologías y estándares abiertos, y es el ente aglutinador que ha logrado movilizar a otras grandes empresas en disímiles proyectos. Por otra parte es admirable su inclinación pronunciada por traer el órden a este océano turbulento que es Internet y especialmente con respecto al caos de las tecnologías web. Estas dos características convergen en este artículo. Quizás la mejor manera de comenzarlo sería así ...

Había una vez un mundo lleno de bases de datos incompatibles cuyo formato permanecía escondido y guardado celosamente por sus creadores. En este tiempo surgió SQL. A la par se hizo general el malestar de los usuarios al dificultarse la migración sus datos de un gestor de base de datos hacia otro y el de los programadores al ver limitada la distribución de sus aplicaciones y emplear gran esfuerzo en hacerlas compatibles con cada gestor. Por tanto surgieron varios estándares (sí ... unos más abiertos que otros ;) para lograr que todas las aplicaciones pudieran consultar cualquier base de datos utilizando solamente el muy estable SQL.

Pero a medida que Internet ganaba en popularidad e importancia fueron surgiendo herramientas que facilitaban la construcción de herramientas web. Y surgió AJAX y los sitios lograron ser más dinámicos. Y muchos brindaron soporte para AJAX porque era bueno. Luego proliferaron las tecnologías como Yahoo! User Interfaces concentradas en enriquecer las páginas web de los sitios. Además surgieron los ORM, y muchos frameworks incorporaban uno porque así se podía acceder más facilmente a los datos. Y los frameworks web hacían cada vez más alusión a su diseño MVC. Y muchos buscábamos esta característica porque así era posible ser más eficientes al crear componentes que eran reutilizables. Pero ... ¿qué era lo que había en el fondo realmente?

Mi experiencia personal

Ya por esos tiempos, mientras cursaba una certificación de programación web en Java ofrecido por el NIIT, me vi con posibilidades de matricular otros dos: uno de Django (Python) y otro de ASP.NET AJAX (C#). Y fue en ese momento cuando me cuestioné ... ¿Qué podría hacer para lograr aprobarlos los tres considerando mi extremadamente poco tiempo libre?.

Fue en ese momento cuando logré darme cuenta de que, una vez que eligiera cualquiera de ellos, caería en una tiranía de ese framework particular. Si seguía sus reglas, tales ataduras serían tan fuertes que me costaría mucho trabajo después reutilizar lo ya hecho para migrar el sitio hacia otra plataforma de desarrollo. Y entonces me asaltó una duda ... como es que todos podían ser MVC. Un entorno de desarrollo web basado en este paradigma, debería permitir la sustitución de una tecnología por otra sin que hubiera necesidad de rehacer (siquiera tocar ...) la implementación de la interfaz de usuarios. Sin embargo, cada una de las herramientas mencionadas se limitaba a adoptar el patrón MVC para estructurar las clases del propio framework ... pero quizás no notaron que la separación entre modelo, vista y controlador venía asociada al hecho de que existían datos administrados por un gestor, usuarios que acceden al sitio desde su PC a través de su navegador web, y un servidor web cuyo papel era preparar esos datos y hacerlos llegar a quién los solicitó.

Y fue entonces cuando me decidí a hacer junto con Orapma, Evelin y Carlitos un proyecto de curso basado en AJAX + JSON ... La ventaja de este enfoque reside en que el mismo sitio se puede implementar variando las tecnologías de programación en el servidor (en mi caso particular Django, ASP.NET AJAX y JSP ) con un mínimo de esfuerzo, y no se apreciarían cambios de ningún tipo en la interfaz de usuarios y en la navegación. Todo esto es ideal, por ejemplo, para migrar el sistema hacia un servidor, o plataforma.

El punto de vista de Google

Al parecer los ingenieros de Google (y otros como los desarrolladores de DoJo ;) tenían inquietudes similares. Lo único que ellos pensaron en grande ... El primer paso era darse cuenta de que muchas veces las trabas venían dadas por la carencia de una tecnología abierta basada en los estándares de la web que acercara los datos a los programadores , por las limitaciones de acceso desde la web a los datos gestionados por las diferentes organizaciones, y por la sumisión de los desarrolladores a la tiranía de los frameworks. El próximo paso ya ha sido dado.

Google ha lanzado su plataforma Google Visualization API. Su misión es erguirse como el nuevo ODBC para vencer las barreras de acceso a los datos según la estructura actual de Internet. Esta tecnología se vale de JSON para independizar la implementación de la vista (en la PC del cliente) del servidor web y de la forma en que se almacenan los datos; y todo esto a través de un protocolo abierto, relativamente sencillo y muy bien documentado. Por lo tanto se logra separar el desarrollo de un sitio en dos roles: los programadores de componentes web, y desarrolladores de los servicios que ofrecerá el servidor. Todo esto me recuerda la explosión que implicó la aplicación del enfoque de Delphi para aplicaciones de escritorio. En ambos casos se puede escoger las tecnologías para implementar las visualizaciones y los servicios debido a que Google Visualization API no presenta obstáculos para enlazar tecnologías de cualquier tipo. Ya para terminar, al mismo tiempo Google ha concebido un repositorio de manera que sea muy fácil buscar el componente que se ajuste más a nuestras necesidades; y ha conectado esta plataforma con la tecnologíua de gadgets para facilitar su uso.

Nada ... que simelo preguntan, solo se me ocurriría responderles que este año 2009 parece ser que se estrecharán las distancias entre los modelos de desarrollo de aplicaciones para la web y las de escritorio. Y acerca de Google ... cualquier comentario se queda chiquito.