domingo, 16 de agosto de 2009

Delegar acciones en AppController

Al trabajar en mi actual proyecto me estaba molestando la cantidad de código básicamente idéntico que se produce.

Como he comentado de pasada en una entrada anterior, estoy trabajando desde un enfoque modular basado en plugins para poder incorporar funcionalidades de forma sencilla a las aplicaciones que tendré que desarrollar durante el próximo año.

Ocurre que hay plugins que básicamente aportan un modelo y un controlador con las acciones básicas de administración y que, aparte de usar un modelo diferente y algún otro detalle menor, son calcados unos a otros.

Por otra parte, y por alguna razón, no consigo que Bake me genere el código de los controladores en los plugins. Los tests de los controladores, además, son copias unos de otros en los que lo único que tengo que hacer es sustituir el nombre del Modelo y poco más.

El caso es que me sonaba haber leído algo al respecto y rebuscando en Google encontré un post de AD7six sobre la personalización de plantillas para Bake que también comenta el mismo tema.

En pocas palabras, se trata de escribir en AppController las acciones administrativas de una manera genérica, aprovechando algunas propiedades del propio AppController. Gracias a la herencia, CakePHP lanzará las acciones adecuadas.

A partir del artículo añadí algunos pequeños retoques, como varios callbacks para permitirme personalizar un poco el comportamiento de cada controlador, de modo que no necesite reescribir el método entero cuando tengo que hacer algunos ajustes menores (por ejemplo, cambiar un campo del array de datos del formulario de forma incondicional y así).

El resultado (todavía en progreso) es que ahora no tengo que escribir código para tener un controlador básico: algo parecido al scaffolding pero que sí puedo utilizar en producción. Lo puedes ver pinchando en el enlace siguiente, como digo, es un trabajo en desarrollo y aún faltan muchas cosas (por ejemplo, controlar que no se pueda llamar a la url /app/admin_add y cosas por el estilo).

app_controller.php

2 comentarios:

AD7six dijo...

Post interesante ;)

Veo que has pensado un poco en las problemas que puede causar (refiero a tus nuevos before|after métodos) - y claro es una técnica que he promocionado antes.

Pero emphasis(?) en el antes. Si todos los controladores usan la misma logica no va a ser problemático - pero cuando encuentras algún tipo de excepción (y siempre van a ser), y tienes que crear function x() { ... algo o nada; ... parent::x(); ... algo o nada; .. } va a ser mas trabajo de entender/usar métodos 'generic' del app controller.

Ahora creo/he aprendido que a veces DRY tiene que ser equilibrado con fácilidad de entender/usar/mantener/etc. Ti doy un par de ejemplos:

Ahora mismo con el código en el app controller, tienes mensajes como "%s created" - pero si no es tu haciendo el traducción, que es mas facil: traducir muchas mensajes similares (User created, Profile created, Post created, Comment created) o jugar con "%s created - el problema es mas obvio si el mensaje es de forma "your %s has been created" y lees las posibilidades en castellano.

Que pasa si tienes que enviar a la vista un parámetro nuevo/ademas. (si, tiene una contesta fácil). Luego hay hago que quieres hacer antes tambien. Luego quieres hacer algo distincto si hay un error en el formulario etc.

Con tiempo encuentras bastante situaciones/factores excepcionales, acabas con controladores llena de excepciones llamando al parent:: en lugar que código explicito y conciso en los controladores.
Vale la pena intentar de nuevo con bake y especialmente con cake 1.3. Aqui es un ejemplo de un controladora creado con bake 1.3 (la unica cambio despues que bake fui añadir doc blocks, y las 5 lineas de lógica poco especial del $id) http://code.assembla.com/mi/subversion/nodes/branches/mi_settings/controllers/settings_controller.php

En fin: es una técnica interesante; aveces puede servir; es un paso en el camino de entender/aprender - pero no es "la" respuesta. Pero: Convertirse en un cake bake ninja nunca puedes equivocar.

Saludos,

AD
PD recomiendo override setSelects en todos tus controladores si usas la técnica de generic-app controller methodos :)

Frankie dijo...

Gracias AD por el comentario,

estoy de acuerdo en que la técnica no vale para cualquier caso.

De hecho, mi situación es que tengo una serie más o menos larga de controladores en plugins para los que necesito acciones CRUD básicas y triviales. Sobre todo para mantener listas que se guardan en la BD y que sólo gestionar el administrador de la aplicación. Quería tener más control que con Scaffold y un código más a mi gusto.

Tengo ganas de mejorar mi nivel en bake, pero voy despacio... :-) Empiezo a sentirme cómodo en 1.2 ahora, así que me tomo con calma pasar a 1.3.