Aplicaciones web con plantillas

Comencé a desarrollar aplicaciones web hace más de 6 años. Inicialmente utilicé Perl y luego también PHP, Rails, entre otros.

Al poco tiempo de escribir mi primera aplicación interesante noté algo que no me parecía apropiado. Partes de mi programa se ocupaban de obtener los datos enviados por el usuario (entrada), otras se encargaban de realizar los cómputos en función de dichos datos (proceso), en tanto que otras se encargaban de producir el código HTML que se enviaba al usuario (salida), mostrando los resultados del proceso y permitiendo la posterior interacción con el sistema (menúes, enlaces, etc.). Lo que me perturbó es que una parte demasiado significativa del programa se ocupaba de esta última función y, peor aún, no podía separarla adecuadamente del resto del sistema.

Para decirlo en términos más claros: Mi programa estaba lleno de porciones de código encargados de generar HTML, dificultando la separación entre la lógica del programa (el procesamiento de la información y cálculo de los resultados) y la generación de la salida. A continuación, expondré algunas lecciones que he aprendido de esta experiencia.

El problema

Los mayores inconvenientes que trae aparejados la no separación de la interfaz del resto del código son:

  • Mayor complejidad del código: A la complejidad de los cálculos del programa se suma la complejidad de la interfaz de usuario. Esto hace que el código crezca innecesariamente y se vuelva mucho más complejo y menos legible, con el consiguiente aumento de la probabilidad de errores y la dificultad para detectarlos. Se obtiene así código de menor calidad y de mayor dificultad de mantención.
  • Mayor rigidez de la interfaz: Dado que el código HTML está entremezclado con el lenguaje de programación, no es tarea fácil cambiar el diseño de la interfaz. Esto dificulta notablemente la posibilidad de realizar cambios en la misma, como así también la posiblidad de que un diseñador sin conocimientos de programación, pueda dedicarse a la construcción de la interfaz de usuario.

Sumando los dos puntos expuestos, el resultado es claro: se obtiene un sistema rígido y de poca calidad. Lamentablemente, aún hoy muchos desarrolladores no se han dado cuenta de este problema y continúan cometiendo el mismo error una y otra vez.

La solución

La mejor solución para este problema (y varios más, que aparecen en el caso de aplicaciones de mediana/gran envergadura, con requerimientos de cambio frecuente), es la utilización del patrón de diseño MVC («Modelo-Vista-Controlador» o, en inglés, «Model-View-Controller«), que asegura una correcta separación entre el modelo de datos, la interfaz de usuario y la lógica de control del sistema. Existen en la actualidad una gran cantidad de herramientas, para distintos lenguajes de desarrollo, que soportan esta arquitectura de diseño (mi favorita es Ruby on Rails).

Un buen primer paso

Lamentablemente, el uso de este tipo de herramientas demanda un tiempo considerable de aprendizaje y entrenamiento. Aunque personalmente recomiendo su utilización, ya que los beneficios obtenidos son muy significativos, hay al menos una pequeña mejora que debe hacerse al enfoque clásico de desarrollo de aplicaciones web: separar la generación de la interfaz de usuario del resto de la lógica del programa mediante el uso de plantillas (templates, en inglés).

Para esto también hay disponibles varias herramientas: Smarty para PHP, Template-Toolkit para Perl, entre otras.

Un ejemplo simple

A continuación ejemplificaré el uso de este tipo de herramientas (usando PHP, por ser el lenguaje en el que se inician la mayoría de los desarrolladores de aplicaciones web).

Vamos a plantear un problema muy simple: obtener los datos de un conjunto de personas (posiblemente de una base de datos) y mostrar un listado de los mismos en una página web. Utilizaremos una función, que llamaremos get_people, que devuelve un arreglo de arreglos asociativos con los datos de las personas. (Por simplicidad, he utilizado datos constantes, aunque podríamos cambiar la función para obtenerlos desde una base de datos.)

Función get_people

Un script simple que solucione nuestro problema podría ser el siguiente:

Script inicial

Este script producirá la siguiente salida:

Salida HTML inicial

Aunque es un ejemplo muy simple, puede verse que para realizar cualquier cambio en la salida (por ejemplo, agregar un menú, cambiar la estructura de la tabla, etc.) deberá modificarse el código del script. De la misma manera, si deseamos que el código HTML generado sea un poco más «legible», también deberemos realizar cambios en el programa. Basta imaginar la situación en una aplicación realmente compleja, con una interfaz de usuario muy cargada, para ver el impacto que puede tener, por ejemplo, realizar un rediseño completo de esta última.

La falta de separación también puede complicar notablemente la búsqueda de errores en el programa o en el código HTML generado.

Modificaremos el script para usar plantillas mediante Smarty:

Script con Smarty

Sin entrar en demasiados detalles (ya que este no es un tutorial sobre el uso de Smarty), el script crea una plantilla, configura los directorios a utilizar y asigna a la variable people el valor devuelto por la función get_people. Dicha variable será utilizada luego en la plantilla para mostrar los datos. Finalmente procesa la plantilla people.html.

Una plantilla es, básicamente, código HTML con el agregado de sentencias del lenguaje definido por Smarty (encerradas entre llaves). Estas sentencias nos permiten utilizar variables (definidas por el método assign utilizado en el script) y nos provee mecanismos de iteración, ejecución condicional, entre otros.

El contenido de people.html es el siguiente:

Plantilla people.html

La salida producida por el script es la siguiente:

Salida HTML con plantillas

Las ventajas de este nuevo enfoque son claras: el código HTML está totalmente separado del script. También existe la ventaja adicional de que la salida producida es muy similar el contenido de la plantilla (lo cual simplifica las tareas de diseño y de búsqueda de errores). Si bien en casos más complejos las plantillas pueden complicarse notablemente, Smarty provee un buen número de funciones auxiliares para formatear cadenas, incluir archivos, etc.

Puede descargar el código completo de este ejemplo.

Un error (lamentablemente) muy común

Muchos desarrolladores se resisten a utilizar estas facilidades (lo digo aquí: ¡el uso de CSS no soluciona el problema!). Muchos otros simplemente siguen programando de la forma en que aprendieron y no se preocupan por aumentar la flexibilidad de sus aplicaciones. De cualquier manera, Internet está plagada de sistemas web (algunos de gran calidad, otros no tanto) con interfaces difíciles de cambiar y de mantener. He aquí un par de ejemplos:

Menéame

Se trata de una excelente aplicación, muy apegada a las novedades de la llamada «Web 2.0«. Está muy bien escrita y su uso en meneame.net, un sitio con gran afluencia de usuarios, demuestra su escalabilidad. Sin embargo, la interfaz está «empotrada» en el código del programa, como puede apreciarse en el siguiente fragmento del mismo:

Código de Menéame

Si bien la interfaz HTML utiliza hojas de estilo (CSS), esto no es suficiente para permitir un rediseño total de la interfaz sin tener que realizar profundas modificaciones a lo largo del código PHP del programa.

OpenWebmail

Se trata de un webmail escrito en el lenguaje Perl, ampliamente difundido y utilizado en sistemas de gran envergadura. Su desarrollo lleva varios años y participan de él una gran cantidad de personas (yo mismo he contribuido código y realizado la traducción al castellano). Utiliza un sistema de plantillas propio, pero a pesar de esto no resulta lo suficientemente potente, requiriendo de cosas como éstas:

Código de OpenWebmail

A raíz de la pobreza del sistema de plantillas la interfaz de OpenWebmail (que solía ser muy agradable, para los estándares de hace 5 años), se ha quedado estancada. En la actualidad los desarrolladores están evaluando la reescritura completa de las porciones del programa que se encargan de la generación de la interfaz, tarea que involucra profundos cambios. (Mi opinión personal es que están equivocándose nuevamente, al elegir HTML::Template en vez de Template-Toolkit.)

Conclusión

Aunque lo ideal es apegarse a la arquitectura MVC, es indispensable al menos utilizar una buena biblioteca de plantillas para el desarrollo de cualquier aplicación web de complejidad media o alta. Si bien se está agregando una «capa» más a la aplicación, las ventajas sobrepasan por lejos a los inconvenientes.

Los sistemas web son cada vez más potentes y llenos de funciones, la complejidad de las interfaces de usuario aumenta considerablemente día a día y HTML no es un lenguaje simple. Entremezclar todo esto resulta, cada vez más, en sistemas difíciles de extender y mantener.

Dejar un comentario?

23 Comentarios.

  1. meneame.net - trackback on 17 de octubre de 2006 @8:18
  2. mnm.uib.es/gallir/posts/2006/09/26/820/ : Plantillas PHP: there is no silver bullet

    http://www.lnds.net/2006/09/not_so_smarty.html : «En el caso de Blogmemes, el 80% del tiempo de rendering de una página se consume en Smarty, y estoy hablando sólo de tiempo en el servidor.»

    Pues parece que NO, ya va el servidor de Menéame bastante cargado como para encima añadirle más carga

  3. He encontrado un análisis realizado por Ricardo Galli, autor de Menéame, sobre el por qué no se ha utilizado Smarty en su desarrollo.

    Nadie sabe mejor que él los requerimientos de velocidad y la carga de trabajo del servidor de meneame.net, así que tengo que aceptar su palabra.

    Sin embargo, me llama la atención el hecho de que Slash (el software detrás de Slashdot y Barrapunto) utilice sin problemas Template-Toolkit. Quizás Template-Toolkit sea mucho más eficiente que Smarty (¡algo más a favor de mi querido Perl!)

  4. Muy bonito, pero ¿qué tienes exactamente en contra de esto?

    http://rafb.net/paste/results/7mbLGC93.html

  5. Hola,
    la verdad que hay que tener una atención especial al rendimiento que se obtenga al manejar templates, en mi opinión prefiero utilizar una libreria que proporcione elementos html, por ejemplo, si quiero un href en php:
    echo $html_class->href(«titulo»,»enlace»,»otros»)
    en perl utilizo la libreria CGI;)
    La ventaja que se tiene es también el fácil mantenimiento y alto rendimiento.
    Un ejemplo es de esto que os cuento es Oscommerce http://oscommerce.qadram.com/

  6. excelente artículo.

    Personalmente uso una forma que considero «mejor» aunque cada uno tiene sus preferencias.

    Simplemente crear una página HTML, enlazada con unf fichero javascript en la que usando AJAX hago llamadas a la BD, y luego… mucho javascript.

    De ese modo da igual que cambies de PHP a JSP o ASP, los ficheros HTML ni javascript los tocas para nada.

    ¿Lo malo? que hay que poner algo más de atención a la seguridad.

    Un saludo.

  7. Este tema está muy a la orden del día en mi empresa. Te cuento, somos 3 programadores y cada uno trabaja a su manera. uno va a su bola total q no viene al caso, yo uso el método malo de integrar consultas a BD en las páginas HTML para mostrar las tablas y todo eso, y el tercero usa un MVC propio.

    El problema, es cuando los diseñadores tienen q modificar algo del diseño, q no saben donde meter mano. Conmigo no tienen mucho problema pq el código html, más o menos, se entiende. El problema lo tienen con el q usa MVC, y para cambiar un simple menú se las ven crudas.

    Así q, hast q los diseñadores no sepan algo de php o de las estructuras de smarty y similares, seguiremos trabajando al modo malo.

    Una pena, lo sé….

  8. No hay que perder de vista que el propio lenguaje PHP puede usarse tranquilamente para representar la lógica de la aplicación, de hecho, supongo que Smarty traducirá su lenguaje de plantillas a PHP y mantendrá una copia «compilada» en caché.

    En Sitepoint hace tiempo publicaron un artículo muy majo (http://www.sitepoint.com/article/beyond-template-engine) con una interfaz sencilla orientada a objetos donde las plantillas no tenían más que PHP.

    Es decir, la idea no es incrustar el HTML en PHP, sino hacer todo lo contrario, que es para eso para lo que estaba pensando originalmente y además, no hacerlo «a lo loco», sino separando correctamente en archivos/clases/módulos según su role en la aplicación. De hecho, en Rails, aunque puedes elegir el motor de plantillas que te salga del alma, por defecto se usa el propio Ruby con el erb.

    Por lo tanto, no es necesario abstraerse mucho (al final puedes hacer un include tranquilamente de la plantilla) ni utilizar librerías de terceros para separar la definición de la lógica del negocio y el modelo de la lógica de la presentación. Que no digo que no se deba hacer eh? :-) Pero particularmente sobrecargar la capa de la presentación con Smarty con la excusa de que «es más designer-friendly» puede añadir un overhead a tu aplicación que en casos como los de menéame.net no te puedes permitir.

    Y con esto ya termino, ésa es otra. Si un diseñador tiene que aprender la sintaxis de Smarty, por qué no la de PHP? :-)

    un saludo.

  9. Corrección, primer párrafo: quería decir «lógica de la presentación» en lugar de «..de la aplicación». :)

  10. My buen articulo javier. Quisiera saber tu opinion de CakePHP (clon de rails para PHP).

  11. Tu ejemplo de PHP no es muy válido, ya que se puede conseguir un resultado muy correcto sin hacer lo que tú enseñas:

    People Listing

    First Name
    Last Name

    No sé si este código se pegará…

  12. Con respecto a la pregunta de Nicolás, CakePHP parece ser una muy buena implementación del patrón MVC para PHP. Personalmente no lo he usado más que para jugar, por eso no podría evaluar su eficiencia, pero parece estar en el camino correcto.

    Con respecto al comentario de Lito (lamentablemente el código PHP no se pegó bien), la corrección de los resultados no está en discusión, lo que trato de destacar es la posibilidad de obtener código de fácil mantenimiento y escalabilidad separando la lógica del programa de la lógica de presentación (interfaz) a nivel de código.

  13. Yo estoy trabajando en un Framework de PHP4, basado en el modelov MVC pero sin ser tan extenso como el resto como phpcake synfony etc, de momento funciona bien, el problema viene con el el css cuando se introduce la siguiente estructura pagina.ext/otracosa
    alguien sabe porque?

  14. ImZyos!, quizas sea(si te entiendo bien) por el cambio de la ruta al css desde el archivo renderizado por php, una solucion es ocupar rutas absolutas.

  15. He encontrado artículos extremadamente interesantes y productivos en este blog, pero este puntualmente me deja sabor a poco.
    Se menciona Smarty a secas sin hacer siquiera una reseña sobre las características de un motor de templates…si lo dan como algo asumido entonces también debería serlo el punto de separar el código de la presentación, y así la nota no tendría sentido

  16. Podria ser
    Creamos una pagina HTML que enlaza a un fichero javas.. y utilizando ajax se pueden hacer llamadas a la base de datos.
    Asi al cambiar de php a js o asp no se modifican los ficheros.

  17. Interesante artículo, es una forma de ahorrarnos muchas lineas de codigo y sobre todo tiempo. Saludos

  18. Para vosotros desarrolladores mirar esta herramienta ideal para hacer paneles de control para vuestros sitios web. http://www.mkmefeelgood.com/

  19. Vaya te felicito realmente muy bueno….

    Suerte con tu proyecto…‼

  20. Estoy con Javier en eso de que el artículo «sabe a poco» con ese gran título. Smarty se puede dar por supuesto en un diseñador (o más bien desarrollador) con un poco de experiencia, pero lo que realmente esperaba era una introducción a la mejor herramienta para aplicaciones web en este momento: Ruby on Rails.
    Sólo se menciona (positivamente) de pasada….
    Aún así un buen tema para un artículo.

    Saludos

  21. Me parece muy interesante el artículo, cada uno tiene su opinión y yo como desarrollador web de ya hace varios años estoy muy de acuerdo en separar la lógica de la interfaz, cuando vienen los mantenimientos de la aplicación es que se nota esto.

    Una pregunta , veo en el código people.html que tienen un código encerrado entre llaves {}, eso lo entiende HTML o es porque est’a en Smarty?

    Mil gracias!

  22. Coincido con alguno de los comentarios en que ese mismo foreach en php podría tener exactamente la misma limpieza que el html mostrado con smarty:

    xxx XXX

    y la clase encargada de la lógica de negocio sería mucho mas sencilla.
    Saludos

Deje un comentario

NOTA - Puede usar estosHTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Trackbacks y Pingbacks: