Han comenzado las clases en la FCC, y para la materia de Ingenieria de Software nos han informado que al finalizar el curso tendremos que presentar un software terminado y funcionando, es por eso que en estos primeros dias me he dado a la tarea de investigar cuales son los posibles temas y clientes que podríamos utilizar para nuestro proyecto.
Dentro de mis opciones destaca la del sistema que hicimos para Laserelectron, un sistema administrativo para talleres de servicio. Me interesa mucho mejorar este sistema, y agregarle nuevas características y funcionalidades, y hoy por la mañana me puse a pensar en una característica que hará la gran diferencia: Un sistema que acepte plugins.
Hoy por la mañana me he dado a la tarea de buscar algun tipo de explicación y he encotrado un foro donde davidespr explica:
Bueno, ya que viste el “sistema de plugins” que se usa en Gesbit, pero, no te enteraste de mucho (mea culpa), voy a ver si, en pocas palabras, soy capaz de resumir, no ya el sistema que usa Gesbit, pero, en general, cómo puede implementarse un sistema de plugins en un programa.
En primero lugar, hemos de tener en cuenta que lo que quieres hacer puede lograrse de muy diferentes formas. Como sabes, es raro que no existan varias soluciones y formas de hacer la misma cosa. No obstante, creo que algo sí que puede generalizarse, de manera que puedas hacerte alguna idea de cómo va el asunto.
Para que un programa implemente un sistema de plugins es menester varias cosas, algunos pasos, que, trato de resumir a continuación:
1º El programa “host” (anfitrión) ha de ocuparse de buscar y preparar los plugins para su uso
2º La naturaleza del plugin (una clase, una DLL, un ejecutable) la condicionará también el “host”
3º El programa “host” ha de poder determinar los plugins “cargados” y disponibles, en un momento dado
4º El programa “host” habrá de poder “llamar” al plugin usando algún tipo de mecanismo, y, por último…
5º El plugin ha de ser capaz de “responder” a una llamada del programa “host” de la manera establecida
Yo creo que esos podrían ser lo pasos generales, ahora bien, todo esto se puede complicar cuanto se quiera, qué sé yo, por ejempo, podríamos pensar en plugins que pudieran comunicarse entre sí mismos, además de con el programa “host” y así cualquier virgería que se te ocurriera, una vez que tienes cierta “base”, que sería lo que trato de resumir arriba.
¿Cómo se hace en Gesbit? Pues es más sencillo de lo que tal vez pueda parecer (mea culpa otra vez). Gesbit “busca” los plugins en un determinado directorio. Dentro de un determinado directorio (gbaddon/plugins), cada subdirectorio puede representar un plugin diferente, puesto que además no puede haber dos directorios con el mismo nombre. De hecho, en el caso de Gesbit, el nombre del directorio identifica en no pocas ocasiones al plugin en cuestión.
Dentro de cada subdirectorio de “gbaddon/plugins”, como decía, puede haber tantos subdirectorios como plugins, pero, esto no le basta a Gesbit para considerar a un plugin como “válido”. En efecto, cada plugin, es decir, dentro de su subdirectorio, ha de contar con un archivo con información sobre el plugin (“gbplugin.xml”) y con una clase (PHP) cuyo nombre es el mismo que el del plugin, mejor dicho, el mismo que el subdirectorio del plugin. Dicha clase además ha de derivar de la clase “GbPlugin”.
Piensa que aún estamos con el punto número uno. El programa “host”, en este caso Gesbit, de hecho “recorre” el directorio de plugins y busca en cada uno de sus subdirectorios el archivo de información (“gbplugin.xml”) correspondiente, además de un “script”, “nombre-plugin.class.php”, que, ha de contener la clase de cada uno de los plugins. Ahora bien, Gesbit no irá más allá en el caso de los plugins “inactivos”, sólamente leerá el archivo con la información del plugin, para tenerla disponible.
Quizá se me olvidó comentar antes que el programa “host” ha de conocer, en un momento dado, qué plugins están “activos” y cuáles no lo están. En el caso de Gesbit esta información se guarda en la base de datos, se trata de una cadena separada por comas con los nombres de los directorios de los plugins “activos”. Esto quiere decir lo siguiente: si el nombre del directorio de un plugin está en dicha cadena, significa que el plugin está “activo”, si no está en la cadena, es que el plugin no está “activo”.
Cuando hablo que Gesbit se encarga de buscar los plugins y tal y cual, me estoy refiriendo a que existe una clase en Gesbit, “GbPlugins”, que es realmente la encargada de todo esto. Basta instanciar esta clase para que se ponga a hacer lo dicho hasta ahora, buscar los plugins disponibles, localizar la información de los mismos, e instanciar un objeto de la clase del plugin, siempre que el plugin esté “activo”. Es la propia clase “GbPlugins” quien guarda la información sobre los plugins.
La clase “GbPlugins” contiene, básicamente, dos miembros, dos variables privadas. En una de ellas guarda la información de los diferentes plugins “inactivos” (pero disponibles), y, en otra, guarda las instancias de los objetos de los plugins “activos”. De este modo, como puedes imaginar, la clase “GbPlugins” puede “trabajar” tanto con los plugins “inactivos” como con los “activos”, la clase “GbPlugins” cuenta con métodos para “activar” y “desactivar” plugins, para “listar los disponibles”, etc.
Con esto ya hemos sobrepasado el punto número tres, así que vamos con el número cuatro. En efecto, la clase “GbPlugins” puede ejecutar diversos métodos de los plugins, y, a su vez, el propio Gesbit, en cualquier lugar, puede hacer uso de la clase “GbPlugins”. Por ejemplo, esta cuenta con un método que se llama “ExecutePluginAction”. Cuando desde cualquier punto de Gesbit se ejecuta dicho método de la clase “GbPlugins”, esta recorrerá los plugins “activos”, para confirmar que cada plugin implementa el método “ActionCallback”, en este caso.
Piensa que PHP proporciona lo necesario para averiguar si una clase cuenta con un determinado método público. De este modo, resumiendo, Gesbit ejecuta el método “ExecutePluginAction” de la clase “GbPlugin”, porque se va a llevar o se ha llevado a cabo una “acción” en el sistema, como pueda ser que se acaba de publicar un nuevo comentario. La clase “GbPlugins” recorre los plugins “activos” y, siempre que un plugin cuente con un método “ActionCallback”, la clase “GbPlugins” lo llamará, lo ejecutará y luego guardará la respuesta del plugin.
Con eso hemos cubierto ya el punto número cuatro, es decir, Gesbit cuenta con una forma (en realidad existen más, hay métodos “FilterCallback” y “PrinterCallback”, por ejemplo, pero, estamos hablando de lo mismo) para comunicarse con sus plugins y de ejecutar alguno de sus métodos, en un momento dado. Así que nos queda el punto número cinco, que, en realidad es hermano del anterior: la respuesta de los diferentes plugins se retorna en el método “ExecutePluginAction” de la clase “GbPlugins”, de manera que Gesbit, dependiendo de unas u otras respuestas, llevará a cabo esta o aquella tarea o no hará nada en absoluto, por ejemplo.
No sé si me he enrollado demasiado, y, sobre todo, no sé si todo lo dicho te ha servido de algo. Me temo que con algún ejemplo todo podría ir mejor, y, no es por no preparlo, pero, reconoce que no sería cuestión de un par de líneas de código. Los pasos mencionados anteriores han de darse, resumiendo:
1º Tu aplicación ha de buscar plugins en un determinado lugar, ha de ser capaz de validar los plugins que encuentre (en el caso de Gesbit estos han de tener un archivo “gbplugin.xml”, y una clase PHP, que además debe heredar de la clase “GbPlugin”) y ha de poder trabajar con ellos, esto es, activarlos, desactivarlos (para esto ha de “recordar” qué plugins están activos o no, en el caso de Gesbit ya sabes que se usa la base de datos), buscar métodos públicos en la clase del plugin que poder ejecutar (“ActionCallback”, “FilterCallback”, etc.) y ejecutar dichos métodos cuando sea necesario.
2º En el caso de Gesbit un plugin es una clase que ha de derivar de la clase “GbPlugin”, pero, esta es la solución empleada en Gesbit, no quiere decir que tenga que ser así en todo caso. Lo que está claro es que es la aplicación “host” la que ha de establecer una especie de “plantilla” a la que deberá ceñirse quien desarrolle plugins para la aplicación. En el caso de Gesbit, por ejemplo, basarse en una clase “base” común como “GbPlugin”, ofrece ventajas como que esta clase cuenta con métodos que podrán utilizar cada uno de los plugins en su propia clase, pues su propia clase debe ser (fíjate que no es puede, sino debe ser) una clase derivada de “GbPlugin”.
Los puntos tres, cuatro y cinco, como has visto, ya los hemos resumido en unos cuantos párrafos. Decíamos que:
3º El programa “host” ha de poder determinar los plugins “cargados” y disponibles, en un momento dado
4º El programa “host” habrá de poder “llamar” al plugin usando algún tipo de mecanismo, y, por último…
5º El plugin ha de ser capaz de “responder” a una llamada del programa “host” de la manera establecida
Y esto ya hemos visto cómo se hace en el caso de Gesbit, aunque sea por encima. Y creo que más o menos esto es todo lo que puedo decir, ya con bastante miedo porque me parece que me he alargado más de la cuenta. Creo que si puedes tomar algunas ideas generales de lo que he dicho, podrías atreverte a poner en marcha tu propio sistema de plugins, al menos algún ejemplo que pudiera poner en práctica lo dicho, de manera que se te “quedara” mejor. Si tienes dudas o lo que sea ya sabes que aquí hay gente que puede echarte una mano.
Me gusta la idea, es una explicacion clara y general de lo que se puede lograr con PHP, muy parecido a lo que hace Wordpress para administrar sus plugins, sospecho que el primer paso para comenzar con el sistema es definir cual es el elemento eje en el sistema, y para el caso de los blogs los elementos eje son los post, asi como para el sistema del taller de reparaciones son las ordenes de servicio.
Seguiré investigando y explicando todos los avances que haya obtenido con este proyecto.