Dejando aparte errores de sintaxis y algunos fallos lógicos, más o menos normales, he estado pensando que hago algunas cosas mal en mi "estrategia" (por decir algo) de desarrollo.
Una de las principales es que tiendo a centrarme demasiado en lo periférico, con lo cual avanzo relativamente poco en mis tareas, aunque teclee innumerables líneas de código.
Por ejemplo, llevo unos meses trabajando (un poco irregularmente) en el desarrollo de un proyecto que, en principio, será un CMS y la base para una aplicación de Intranet para el colegio en el que trabajo.
Pues bien, he dejado la parte de CMS para el final, y mientras tanto he estado desarrollando módulos auxiliares que, si bien son importantes, no son el objetivo principal de la cuestión. Sólo últimamente he empezado a trabajar en el módulo de contenidos, el cual, en muchos aspectos debería haber sido el primero (o uno de los primeros, ya que también me resulta muy importante el de gestión de usuarios y autorización).
Con todo, no he estado parado, sino que he desarrollado una serie de módulos que aportan gran cantidad de funcionalidad: comentarios, etiquetas, licencias, colecciones, uploads..., pero todavía no hay una aplicación real que esté funcionando. Lo que resulta frustrante.
La cuestión es que desde un punto de vista más "pragmático" lo lógico hubiera sido empezar a desarrollar la parte de gestion de contenidos (dejaré fuera de la cuestión la parte de acceso, que estoy revisitando ahora mismo) y seguramente estos otros elementos hubieran ido surgiendo de forma natural, aportando funcionalidad "avanzada" a la básica.
Mi CMS se estructura en torno a los modelos Channels e Items. Los Channels son canales, que pueden ser blogs, podcasts, photologs o similares. Los Items son los posts, episodios, etc. Si conoces la estructura de los RSS entenderás en qué me he inspirado.
La idea que intento explicar es que probablemente es más eficaz y mejor práctica comenzar por desarrollar una funcionalidad básica "gruesa", sin preocuparse de detalles. Es decir, en este caso, poner a funcionar mis channels e items, perfeccionando luego, de forma iterativa, el sistema añadiendo nuevas prestaciones.
Probablemente eso ayudaría también a mantener una buena motivación a lo largo del trabajo, cosa que en algunos momentos hecho de menos.
Diario de aprendizaje del framework CakePHP. Otras notas de desarrollo y diseño web, realizado sobre Mac.
Mostrando entradas con la etiqueta estilo de programación. Mostrar todas las entradas
Mostrando entradas con la etiqueta estilo de programación. Mostrar todas las entradas
miércoles, 18 de noviembre de 2009
jueves, 16 de julio de 2009
Usando plugins para modularizar aplicaciones
Después de una temporada de alejamiento "forzoso" del desarrollo con CakePHP he decidido afrontar un par de nuevos proyectos utilizando nuevos enfoques en mi metodología de trabajo.
El primero de ellos es la modularización del código en base a plugins. El otro es la introducción del unit-testing y del desarrollo dirigido por tests.
Hoy voy a escribir sobre los plugins, por qué me he decidido a replantear mis aplicaciones con ellos y qué detalles he descubierto que hay que tener en cuenta para hacerlos funcionar bien.
Modularizar con plugins
Una queja habitual de la estructura de CakePHP es que no se pueden organizar los modelos, controladores y vistas de forma significativa, pues todos los modelos tienen que ir juntos en su carpeta, al igual que todos los controladores, etc.
Los plugins nos permiten abordar ese problema ya que con ellos agrupamos los modelos, controladores y vistas (y sus extensiones) que guarden alguna relación. Cada plugin es como una mini-aplicación CakePHP y en su interior reproduce su estructura general.
Los plugins pueden ser bastante autocontenidos, de modo que es sencillo reutilizarlos en nuevos proyectos. Supongamos, por ejemplo, que hemos creado un sistema de gestión de usuarios y grupos con el que nos encontramos muy a gusto. Si lo tenemos como plugin, tan sólo debemos copiar la carpeta que lo contiene en la nueva aplicación para disponer de toda la funcionalidad.
En cambio, si no está en forma de plugin, es más fácil perder la pista de algún archivo a la hora de copiarlo, en especial si se manejan varios modelos, etc.
Mi objetivo al usar plugins
Pues mi objetivo es muy sencillo. Se trata de tener "piezas" de código relativamente independientes que puedan servir para montar una diversidad de aplicaciones. De este modo dispondré de una especie de "superframework" con módulos reutilizables. Cada aplicación o proyecto tendría partes propias, y partes comunes. De este modo, al avanzar en uno, estoy contribuyendo a otros. Y, por otro lado, me puedo concentrar en el núcleo de una aplicación específica.
Y en caso de trabajar en equipo, es fácil distribuir el trabajo.
Por otra parte, los plugins son también una buena manera de crear bibliotecas de behaviors, components o helpers, que puedan reutilizarse en varios proyectos. Lo bueno, es que puedes agruparlos por algún criterio útil. Por, ejemplo, una biblioteca de helpers relacionados con la interfaz de usuario. O un módulo con un behavior para añadir comentarios a cualquier otro objeto, que incluye la gestión de los mismos.
Creando un plugin
Lo mejor es utilizar cake bake para crear la estructura básica del plugin.
cake bake plugin nombre_del_plugin
Lo más importante a tener en cuenta es que los modelos y controladores dentro de un plugin no deberían descender de AppModel o de AppController, sino indirectamente, a través de AppPluginModel o AppPluginController. Cake Bake se ocupa de eso por nosotros.
También podemos generar modelos y controladores básicos mediante cake bake
cake bake plugin NombreDelPlugin model NombreDelModelo
Accediendo a las acciones de un plugin
Las URL que nos llevan a un plugin son las típicas de cake prefijadas con el nombre del plugin:
/plugin/controller/action/param
Como, por ejemplo:
/content/posts/edit/first_post
/admin/tickets/tickets/edit/123
Como puedes ver, también es posible usar el admin routing con plugins.
Por otra parte, es perfectamente posible llamar a las acciones de los plugins con RequestAction.
Creando URL
En el caso de que crees las URL para link o redirect con el formato array, debes incluir la clave 'plugin' con valor true.
array('admin' => true, 'plugin' => true, 'action' => 'index')Asociaciones con modelos dentro de un plugin
Cuando necesitamos asociar un modelo con otro que está en un plugin, tenemos que indicárselo. Puede ser en la forma simple:
var $hasMany = array('Plugin.Modelo');O si tienes que especificar parámetros de la asociación, incluyendo la clave
'className' = 'Plugin.Modelo',
Recuerda que ésta, y las demás indicaciones, se aplican incluso cuando los modelos asociados están en el mismo plugin.
Usando behaviors, components o helper de un plugin
Decláralos como siempre, añadiendo antes el nombre del plugin, como en este ejemplo:
var $actsAs = array('Comments.Commentable);Usando elementos de un plugin
Entre los parámetros que pasamos al elemento, hay que indicar la clave 'plugin' y el nombre del plugin.
element('ejemplo', array('plugin' => 'el_plugin')); ?>Importando modelos o controladores
Hay que indicar el nombre del plugin, para que importe el objeto correcto.
App::import('Model', 'Plugin.Model');App::import('Controller', 'Plugin.Controller');Testing con plugins
Algunas cosas que he observado que es necesario tener en cuenta son:
Los controladores que usamos para testar deben incluir el parámetro plugin (gracias a Mark Story)
class TestPostsController extends PostsController { var $plugin = 'Content';
}
Y hay que tener en cuenta el apartado anterior para importar los objetos que estén en plugins.
La declaración de las fixtures, también lo tiene en cuenta:
var $fixtures = array('plugin.content.post);El test suite de CakePHP trata cada plugin aisladamente, lo que resulta muy cómodo y casi te evita tener que hacer grupos de tests por funcionalidad u otro criterio.
Shells
Puedes empaquetar shells en plugins. Crea la ruta vendors/shell dentro de la carpeta del plugin que se trate y pon ahí los shells que desees. La utilidad de línea de comandos cake sabrá acceder a ellos.
Por supuesto, hay más información en el Cookbook.
Etiquetas:
estilo de programación,
generalidades,
plugin
miércoles, 17 de septiembre de 2008
Encuesta chorra (o no)
Aprovechando que el Blogger ahora admite encuestas (ver arriba), se me ha ocurrido la siguiente pregunta. Supongamos que tienes un sistema de blogs con los modelos Blog y Post, asociados de modo que Blog hasMany Post.
Ahora supongamos que la raíz del sitio (/) saca una lista de todos los Post recientes, con independencia del Blog al que estén asociados. Es decir, una accion como /posts/index.
Por supuesto, cada Blog tiene su página principal, que muestra una lista de posts. Mi primera tendencia fue a crear una accion /blogs/view/blog_id, pero me dije: "Un momento, esto no es más que un /posts/index/blog_id. Puedo hacer que /posts/index maneje la situación de listar sólo los post de un blog determinado".
Así que en principio creé una acción que modificaba la búsqueda de datos en función de si se pasaba un parámetro para indicar un blog. Luego en la vista, incluí una lógica para actuar de manera ligeramente distinta si se listaban los post de todo el sitio o si eran sólo los del blog indicado. Como tampoco me gustaba, preparé dos vistas y dejé que el controller eligiese la adecuada.
Sin embargo, esta solución tampoco me convence. Finalmente he decidido crear dos acciones en el PostsController (index y blog), cada una con su vista. El Controller ahora no toma tantas decisiones, y la vista tampoco. Pero ¿Qué opinas tú?
Etiquetas:
estilo de programación,
generalidades,
MVC
Suscribirse a:
Entradas (Atom)