Dec 12

Control de la dependencia invertida por patrones inyectables en el contenedor.

Perdón por el título, pero se me hace muy difícil traducir el título del artículo Inversion of Control Containers and the Dependency Injection  Pattern de Martin Fowler.

El caso es que en la Chuwiki he empezado a hacer una traducción al cristiano de este artículo de Contenedores de Inversión de Control y el patrón de inyección de dependencias … ¡¡buff!! … titulito.

Aunque el artículo es muy largo, voy a tratar de hacer aquí un pequeño resumen en cuatro líneas, o alguna más. La idea es la siguiente:

Supongamos que una clase A para realizar su trabajo necesita unos datos. Esos datos se los pide a una  clase B que los lee de un fichero. La forma directa de realizar esto es que la clase A haga un new de la clase B. Esto, sin embargo, hace que la clase A sea menos reutilizable, ya que depende totalmente de la clase B y sólo podrá leer los datos de un fichero en el formato que entiende la clase B.

Este patrón de inyectables nos dice que hagamos una interfaceB con los métodos interesantes de la clase B y hagamos que la clase B implemente esa interfaceB. Por otro lado, la clase A en vez de hacer directamente el new de B, recibe en algún método -el constructor o un método set()- la interfaceB. De esta forma, alguien fuera de la clase A hace el new de B y se lo pasa a A. Haciéndolo así, si algún día cambiamos el formato del fichero o bien deseamos leer los datos de una base de datos, sólo tendremos que hacernos una clase OtraB que implemente la interrfaceB y pasársela a A. La clase A, sin tocar su código, será capaz de leer los datos del nuevo fichero o de la base de datos.

A esto lo llama inversión de control o inyección de depedencia. En vez de ser la clase A la que decide de quien depende, alguien desde fuera le "inyecta" la dependencia a través de un método set().

Y eso es todo.

El resto del artículo se extiende en contarnos que muchos de los frameworks actuales, como Spring, PicoContainer o Avalon, se basan en esto. Esos framework se encargan de instanciar las clases A y B y de pasarle a A la clase B. Todo ello desde código o desde un maravilloso fichero de configuración en donde se les dice qué tienen que instanciar y qué tienen que pasar a quien.

El artículo también menciona otra forma de conseguir todo esto, que es por medio de un localizador de servicios, pero viene a ser lo mismo, aunque metiendo otra interface y otra clase por medio. La idea es que haya una interfaceLocalizador con un método getInterfaceB() que devuelve la InterfaceB. Y es esa InterfaceLocalizador la que le pasamos a A.

No sé, la verdad es que a mi todo esto en realidad me parece un simple patrón Estrategia, pero adornado. Y la verdad, es que el patrón estrategia me ha parecido que no es más que el polimorfismo de cualquier lenguaje orientado a objetos.

Nov 17

¿Son buenos los frameworks?

Como programador, después de años programando y participando en varios proyectos, veo claramente la necesidad de frameworks.

En la historia de un programador, primero hace su código en su primer proyecto. En su segundo proyecto ve la necesidad de tener componente reutilizables y librerías, para no repetir código. Cuando ya ha participado en varios proyectos similares, aunque distintos, ve que todos ellos tienen muchas cosas en común, aunque no se parezcan. Suele ser necesaria una autentificación de usuarios, suele haber accesos a bases de datos, suele haber clases o módulos configurables que se necesita instanciar y configurar, suele tenerse que establecer conexiones por red con otros módulos, las interfaces de usuario tienen un esqueleto similar, consistente en menús, áreas de trabajo, baras de botones, etc, etc.

Todo esto le lleva a plantearse la necesidad de una especie de "esqueleto" de la aplicación. Algo que no haga nada concreto, en lo que se pueda meter cualquier cosa, pero que nos diga claramente cómo hacer las cosas, cómo instanciar los módulos, cómo configurarlos, cómo establecer las relaciones entre ellos, cómo manejar la base de datos, etc, etc.

Y eso es precisamente lo que hacen los frameworks. Una librería/aplicación que nos facilita mucho la construcción de nuestro proyecto y nos da hechas muchas de las cosas que son comunes en las estructuras de muchos proyectos.

Sin embargo, puestos que estos frameworks no saben nada de la aplicación concreta que queremos construir, ya que podemos querer hacer un cajero automático, un juego de ajedrez o un programa de contabilidad, deben ser altamente configurables. Eso requiere que tengamos muchos o grandes y complejos ficheros de configuración y que nuestros módulos implementen determinadas interfaces para que se adapten al framework,

Y eso hace que las aplicaciones hechas con frameworks sean siempre algo más lentas que las aplicaciones hechas "a pelo". Siempre es menos costoso hacer un new de una clase específica nuestra que hacer un new de un framwork, esperar que el framework lea los ficheros de configuración para al final hacer el mismo new que hebríamos hecho nosotros en una sola línea. También hace, según lo complejo de esas interfaces que tengamos que implementar, que nos "casemos" con el framework y una vez empezado a usar, no podamos echarnos atrás.

Desde el punto de vista del programador, un framework es una maravilla, puesto que da mucho trabajo hecho. Pero desde el punto de vista del usuario final, un framework es algo que le hace más lenta la aplicación y tiene que soportarlo por la pereza del programador: "Tengo que aguantar esta aplicación lenta porque el programador no ha querido hacérmela a medida desde cero". Desde este punto de vista, los frameworks no son tan buenos.

Pero, incluso desde el punto de vista del usuario final, pueden tener sus ventajas.

Por un lado, si los programadores ahorran trabajo usando un framework, el precio del producto final debería ser menor.

Y por otro, si nos metemos en el mundo real y no el ideal en el que todos somos "buenos y maravillosos", el framework soluciona otro pequeño problema. Si no hay frameworks, la calidad de las aplicaciones será muy variable. Hay empresas que se esfuerzan en dar productos de calidad y otras que no tanto. Hay programadores estupendos y hay programadores chapuzas. Desgraciadamente, en los tiempos que corren, las empresas no se preocupan demasiado de la calidad, subcontratan programadores recien salidos y sin experiencia por sueldos irrisorios, dejan que los programadores con experiencia se vayan porque les salen caros, tienen mucha rotación de gente  y en la mayor parte de los casos, el software sale como sale, si es que sale.

El usar un framework desde luego no soluciona este problema, pero al menos, si el framework es bueno, una parte de la aplicación, normalmente la más importante que es el esqueleto, va a tener una cierta calidad. Si un programador chapucero hace un módulo defectuoso, es más fácil que sólo se vea afectado ese módulo y suele ser más fácil, en caso de necesidad, reemplazarlo completamente por otro hecho desde cero.

Supongo que como en el 100% de los casos, la solución ideal es un compromiso entre ambos extremos. Por un lado no "casarse" con un framework especialmente complejo y pesado, pero sí usar uno de calidad que nos ahorre una cantidad significativa de trabajo.

Nov 05

Utilización de patrones de diseño

En el comentario #5 de este post de Programania veo una cuestión que me ha llamado la atención:

yo tengo una duda.
cuales son las ventajas y desventajas de NO utilizar patrones de diseño en mi aplicación web.

Es realmente curioso pensar cómo hay bastante gente cree que los patrones de diseño son como las herramientas o librerías que tienes disponibles para un proyecto. La realidad es muy distinta.

Una persona empieza de programador novato y a lo largo de su carrera profesional va participando en varios proyectos. A poco que sea espabilidado, verá que suele repetir una y otra vez trozos de código similares, se le presentan problemas similares y está haciendo una y otra vez lo mismo en distintos proyectos -no el mismo código, sino resolviendo los mismos problemas-. También va viendo como el ćodigo que hizo en el proyecto anterior se puede mejorar, se puede hacer más reutilizable e incluso se puede hacer con un diseño más elegante.

Después de doscientos proyectos, esa persona acaba encontrando unas soluciones o forma de hacer las cosas que le funcionan para todos esos problemas que se le presentan una y otra vez y, al final, adopta mecánicamente esas soluciones, sin necesidad de pensar mucho. Pues bien, esas soluciones, o unas como esas, son los patrones de diseño.

Aplicar o no aplicar patrones de diseño en un proyecto no es como decidir si uso o no uso una librería o una herramienta. Si no usas patrones de diseño, lo más probable es que no estés haciendo tu código de la mejor forma posible. Debes usar patrones de diseño siempre.

Otro tema es que un programador novato o con poca experiencia puede tener dificultades para elegir el patrón de diseño adecuado en cada caso. Es bastante probable, sobre todo cuando se descubren los patrones de diseño, que tiendas a aplicar patrones complejos a problemas sencillos y, de la que estás, matar esa molesta mosca de un cañonazo.

Oct 22

Burocracia informática

Ultimamente estoy alucinado a los niveles a los que llega el papelo de un proyecto.

Se nos encarga un proyecto. Ese proyecto lleva varios hitos de pago. Un diseño preliminar que hay que entregar en una determinada fecha. Posteriormente, en otra fecha, un diseño detallado con un preliminar del manual de usuario. Más adelante el software entregado y funcionando.

La política -incorrecta- que seguimos es que los programadores, sin apenas especificaciones y sin diseño alguno se ponen "ya" a hacer el código. Mientras, el responsable del proyecto y para el hito va preparando el diseño preliminar para entregar. Llega el hito del diseño preliminar, el código ha llegado hasta donde haya llegado y se entrega un documento que poco tiene que ver con el código real.

Luego llega el momento de entregar el documento con el diseño detallado y el preliminar de manual de usuario. Eso ya es excesivo para el responsable del proyecto. El nivel de profundidad en el código que requiere el documento se va de las manos de un jefe -¡¡cómo va un jefe a meterse en el nivel de las clases!! Si no tiene ni p..a idea-. Así que llega el momento de pedir ayuda.

El jefe coge a los programadores -a todos, incluidos los nuevos- y les pide que le ayuden a hacer el diseño detallado. El diseño detallado que hagan, por supuesto, debe parecerse al código que están haciendo, pero por supuesto también, no puede discrepar con el diseño preliminar que se hizo anteriormente.

Y ahí tienes a todos los programadores, parados dos, tres o cuatro semanas, haciendo ingeniería inversa -a mano o con herramienta- y luego eliminando clases que son de demasiado bajo nivel, cambiando nombres de paquetes para que coincidan con el nombre que se les dio en el preliminar, juntando clases de paquetes separados en uno solo, y haciendo malabarismos varios con los diagramas UML.

Aparte de todos los fallos evidentes de esta forma de trabajo y del caos que salta a la vista, hay dos pequeños detalles que me llaman la atención.

Por un lado, el diseño preliminar se supone que es una fase intermedia del diseño. Cuando se pasa al diseño detallado y se va profundizando más en el problema, el diseño preliminar debería ser perfectamente modificable. Sin embargo, el papelo -las ganas de evitar hacer la versión 2.0 del diseño preliminar- hace que el diseño detallado se haga mal a posta, sin parecido al código real que se está desarrollando en paralelo.

Por otro lado…. si vas a parar a TODOS los programadores varias semanas para pintar unos monos que no valen para nada… ¿no es mejor pararlos al principio, antes de que se pongan a codificar a lo loco, para pensar al menos un esbozo de diseño real?.

Ya lo dice el refrán, "vísteme despacio que tengo prisa".

Sep 18

Sigo aprendiendo a ser un jefe pérfido

En su día, cuando entré a trabajar en la empresa, empecé de programador puro y duro. Alguien me decía qué tenía que hacer y lo hacía. Eran tiempos felices.

Más adelante, me dieron un grupo reducido de gente, tres o cuatro personas, a los que organizar y controlar el trabajo. Yo seguía programando, miraba los programas de esos tres o cuatro, y seguía siendo feliz, aunque un poco menos.

Hace ya unos meses que pretenden que organice y controle el trabajo de treinta personas. Apenas programo y me resulta imposible mirar el código de todos ellos ni organizarlos. Llevo desde que escribí el post del principio de Peter dándole vueltas al asunto sin llegar a nada en claro. De hecho, por eso escribí lo del principio de Peter, porque creo haber llegado a mi máximo nivel de incompetencia.

Sin embargo, esta mañana se me hizo la idea féliz. Ya sé cómo controlar a treinta personas -o a las que se tercien-. Basta seguir la tradición de los jefes que he tenido hasta ahora y que supongo que son como los que hemos tenido casi todos. La idea básica consiste en entrar a trabajar por la mañana, elegir a uno de los treinta al azar, preguntárle

  • ¿Qué estás haciendo?

luego preguntarle

  • ¿Cómo lo estas haciendo?

 y finalmente soltarle la bomba.

  • Así como lo estás haciendo no vale. Bórralo y hazlo de esta otra forma peregrina que se me acaba de ocurrir Además date prisa, porque sería bueno que hicieras también esta otra cosa estrafalaria que he visto en internet.

Bueno. Por supuesto, es broma … creo. Lo cierto es que es complejo organizar tanta gente. Y después de leer mucho sobre buenas constumbres de programación -test unitarios, diseño, UML, etc, etc-, cuando es responsabilidad tuya implantarlas y el si funcionan bien o no cae sobre tus hombros, te empizas a plantear si realmente son tan buenas cosas, si realmente son tan efectivas. Sobre todo, cuando no tienes pruebas reales ni estadísticas serias. Sólo lo que comentan los "gurus" sobre lo bueno que es todo eso.

Y también te entra la duda, cuando quieres implantar esas cosas, si la gente que programa no te verán como ese " jefe" que inventa cosas raras para fastidiarnos. Y te preguntas hasta que punto ellos están en lo cierto, al igual que tu lo estabas cuando juzgabas a tu jefe.

Sep 13

¿Merece la pena la documentación de diseño?

Me refiero a la documentación, a los diagramas UML y todo lo demás. Por supuesto, un programa si hay que pensarlo un poco antes de ponerse a codificar.

El tema es el siguiente:

Suponte que eres un programador listo, que sabes hacer bien el código, reutilizable, bien hecho y que funciona correctamente. Suponte también que trabajas tú solo en el proyecto. Posiblemente piensas en cómo vas a hacer el programa e intentas plasmarlo en una documentación con UML. Según lo haces, como eres inteligente, te vas dando cuenta de problemas de diseño y los vas corrigiendo. Al final tienes una documentación buena que te ha llevado un tiempo hacer. Luego te pones a codificar, pero no consultas en absoluto la documentación porque la conoces y tienes las ideas claras. Según codificas, vas haciendo pequeños cambios en el diseño, cosas que no previste anteriormente. Al final te sale un buen programa en condiciones … y has perdido el tiempo en hacer una documentación que no has necesitado y que ahora no es coincide exactamente con el código y tienes que arreglar.

¿Qué pasa si no hubieras hecho documentación?. Habrías pensado igualmente, quizás te habrías hecho unos esquemas en borrador para aclarar ideas, te habrías puesto a hacer el código, habrías ido corrigiendo y arreglando cosas sobre la marcha y al final llegarías a un resultado parecido e igual de bueno. Posiblemente lo hayas hecho en menos tiempo, ya que no lo has perdido en hacer una documentación formal. Basta con los esquemas en borrador para aclararte las ideas. ¿Necesitas la documentación ahora para el cliente? Una buena ingeniería inversa hace maravillas.

¿Y qué pasa si eres un programador torpe?. Da igual que hagas o no documentación. En cualquier caso tardarás mucho y no llegarás a un buen código. Si eres avispado, en cualquiera de ambos casos cogerás experiencia y la próxima vez lo harás mejor. La documentación mala que hagas no te ayudará  a hacer el código mejor y el código que has hecho seguramente no se parece en absoluto a la documentación que hiciste, porque no fuiste capaz de prever las cosas correctamente.

Vamos ahora a ser programadores en grupo. Si todos son experimentados, inteligentes y buenos programadores, posiblemente les baste con unas reuniones, unos esquemas en borrador y una pequeña planificación/distribución del trabajo. Cada uno cogerá bien la idea de lo que tiene que hacer y si se comunica con frecuencia con los demás, no habrá problemas graves de integración. Ganarán tiempo si no hacen esa documentación formal que posiblemente luego no miren y al final no se parecerá a la realidad y tendrán que corregir.

Si todos los programadores o algunos de ellos son torpes, nuevamente da igual hacer o no documentación. Las partes de ellos fallarán, irán peor o darán problemas.

Incluso aunque sólo haya un programador del grupo con conocimientos y experiencia suficiente, sería perder el tiempo. El diseño y documentación debería hacerlo él y los demás dedicarse a codificar estrictamente lo que ha diseñado el programador experimentado. Pero aún así ahorraría tiempo si en vez de documentos UML se dedica a escribir los esqueletos de las clases para que sus compañeros rellenen el código. Quizás herramientas como Together que según pintas UML genera esqueletos de clases sean más útiles, pero precisamente porque generan las clases.

Según voy cogiendo experiencia en el trabajo y me voy olvidando de "idealidades" , me voy convenciendo más de que es imposible convertir esas idealidades en realidad y que los métodos ágiles son mejores. Las metodologías deben ir orientadas a las personas, no a los procedimientos, no a generar documentación por generarla. Como he leído en algún sitio, "no hay mejor documentación que el código".

Mi experiencia me dice que a un grupo de programadores se les ayuda bien dándoles una especificación clara de lo que tienen que hacer en un lenguaje informal que les resulte agradable de leer. Se les ayuda viendo el trabajo conjunto de ellos por encima, de forma que les puedes advertir de cuándo dos de ellos están haciendo cosas parecidas o cuando puede haber conflictos entre lo que están haciendo. Funcionan bien cuando cada uno tiene bien definido qué tiene que hacer y como se relaciona con lo que hacen los otros. Y lo mejor es hacer todo esto de forma ágil, día a día. No con un documento formal al principio del trabajo.

¿Conoceis algún caso en el que una documentación formal haya resuelto algún problema? ¿En el que el tiempo de hacer la documentación más el tiempo de codificar y depurar sea menor que el de pensar informalmente, codificar y depurar?.

Aug 18

Reutilizacion & Mantenibilidad

Sigo preocupado y dándole vueltas al tema.

Si se hace código reutilizable, tenemos una serie de ventajas, pero también una serie de inconvenientes. Las ventajas son claras:

  1. Codificaremos menos en futuros proyectos. En vez de hacer código similar otra vez, podremos instanciar una clase o módulo ya hecho. Nuestros futuros proyectos llevarán menos tiempo de codificación.
  2. Con el tiempo tendremos un componente reutilizable fiable y libre de errores. Con el tiempo, esa clase que simplemente instanciamos, tendremos una cierta garantía de que no tiene errores. Nuestros futuros proyectos llevarán menos tiempo en depuración.

Sin embargo, también tiene pegas, y no son tontas.

  1. Se pierde más tiempo ahora. Un componente reutilizable se tarda más en hacer. El proyecto que estamos haciendo ahora tardará más.
  2. Por otro lado, el código es más críptico y menos intuitivo. Siempre es más fácil un código todo seguido que instanciar una clase configurable a la que debemos pasarle para configurarla un fichero, un patrón estrategía o heredar obligatoriamente de una interface. Depurar esas cosas mientras el componente no es totalmente fiable puede ser un pequeño infierno.
  3. Requiere un tiempo de aprendizaje. Si no hemos hecho esos componentes reutilizables nosotros mismos, puede llevar tiempo. Cualquiera que haya intentado utilizar alguna de las librerías que hay por internet -javamail, jasperreport, ibatis, etc- sabe que no es tan sencillo como bajarse la librería y ponerse a codificar.
  4. Los componentes reutilizables a veces nos obligan a una gestión de versiones compleja. A veces necesitamos añadir o modificar la funcionalidad de un componente reutilizable para un nuevo proyecto. Por compatibilidad con proyectos anteriores no podemos hacerlos, así que tenemos que empezar a crear versiones del componente reutilizable, o bien apañarnos para hacer las modificaciones sin perder compatibilidad. En el primer caso, si más adelante encontramos errores en el componente reutilizable, tendremos que corregirlos dos veces -o tantas como versiones distintas afectadas por el error tengamos-. En el segundo caso, tendremos que andar cargando con métodos y clases obsoletas. Todos vemos en la API de java la cantidad de métodos obsoletos que hay que no se pueden eliminar por compatibilidad.

Todo esto me lleva a pensar ¿cuál es el punto de compromiso?. ¿En qué punto compensa hacer el componente reutilizable frente a hacer un copy/paste del código anterior?.

Yo hasta hace poco tendía a hacer componentes reutilizables siempre que podía, a pesar del esfuerzo que supone. Actualmente, tras unos años de experiencia con esa política, empiezo a pensármelo dos veces antes de hacer un componente reutilizable. Sobre todo tras ver a compañeros de trabajo heredar código de otros que se han ido, no conocer los componentes reutilizables que se usan en ese código y ver cómo tarda una semana en encontrar un bug tonto, simplemente por no poder seguir el código fácilmente.

También me ha pasado a mí, a pesar de conocer los componentes reutilizables que tenemos. A veces me piden un pequeño cambio de funcionalidad en el proyecto y me basta con una sola línea de código para introducirla, pero me tiro dos días para encontrar dónde y cómo meter esa puñetera línea, precisamente porque el código no se ve a simple vista.

Un ejemplo tonto muy claro. Supongamos que vamos a leer un registro de una tabla de una base de datos. Podemos hacer un código específico que lea el registro y lo meta en un bean de java -con atributos, métodos set() y get()-. Eso sería muy claro en el código, aunque poco reutilizable. Tendríamos que hacer código similar para cada tabla distinta en base de datos.

Su equivalente muy reutilizable y que ahorra código -no hay que hacer ninguna clase- sería un Hashtable. Leemos la tabla y sus metadatos. Usando el nombre del campo como clave del Hashtable, metemos su contenido como valor. Un simple método en una clase al que pasemos en nombre de la tabla a consultar y el where de la consulta puede construirnos el Hashtable de cualquier tabla. Sin embargo, a la hora de depurar o seguir código, cualquiera prefiere tener un bean y ver los métodos get() y set() o los atributos, que andar con un Hastable intentando averiguar con el debugger qué claves tiene y qué valores.

Con el bean, para reutilización, puede usarse la introspección de java, pero a la hora de depurar o seguir el código cualquiera prefiere ver un getValor() que ver un montón de líneas de código extrañas en las que se buscan los atributos y nombres de métodos del bean para invocarlos de forma oscura y críptica.

Aug 17

Impedido para programar

Siempre que me pongo a programar, aunque sea una tontería, me pasa lo mismo. Me quedo bloqueado.

Como comenté en un post anterior, estoy haciendo un pequeño programa PHP para que la gente pueda apuntar en qué proyectos trabaja durante el mes y cuánto tiempo dedica a ello. Cosas del trabajo.

Me puse a ello. Lo primero, una tabla de base de datos para apuntar a los programadores y una serie de páginas php para que se puedan registrar, hacer login y, por supuesto, para que el administrador pueda administrar esa tabla: añadir, borrar y modificar usuarios.

Todo estupendo hasta este momento.

Iba a ponerme ahora con otra tabla de base de datos en la que se apunten los proyectos en marcha. Por supuesto hay que hacer otra serie de páginas php para administrar esa tabla: crear, borrar o modificar proyectos.

Ahí me he quedado bloqueado.

Es otra vez lo mismo. Otra tabla a la que  hay que hacerle nuevamente tres páginas php para lo mismo de antes, altas, bajas y modificaciones. Lo más cómodo, copy/paste de las de usuarios e ir modificando. Pero copy/paste desde mi punto de vista ¡¡es pecado!!. El código no debería repetirse. Hay que hacer lo posible por extraer lo común a una función o grupo de funciones y reutilizarlas.

Rápidamente, me puse a darle vueltas a la cabeza. Tendría que hacer unos ficheros de configuración que digan cómo son las tablas -o bien mirar directamente los metadatos de la base de datos- y luego hacer tres funciones que me den la página de alta, baja y modificación simplemente pasándoles el nombre de la tabla y qué campos son el identificador principal de la tabla. Seguramente sea necesario algún parámetro más.

Esto, por supuesto, lleva más tiempo que un copy/paste y hacerlo todo a piñón fijo, repitiendo el código cada vez que se presente una tabla. También es más versátil. Si se hace bien, te ahorrará un montón de trabajo cada vez que tengas que hacer una tabla con añadir, borrar y modificar. En contra, también, que el código resultante será mucho menos claro.

Y en eso estoy.

Una aplicación que me podía llevar una o dos semanas a ratos libres -estoy de vacaciones-, me va a llevar:

  • unos días para hacer la primera tabla
  • otro día para empezar la segunda tabla y ver que el copy/paste me vendría bien pero no quiero usarlo.
  • una semana entera para darle vueltas a si hago o no hago la cosa esa común/reutilizable para no utilizar el copy/paste.
  • otras dos semanas para ponerme a hacerla y meterme en complicaciones.
  • un minuto para mandarlo todo a la mierda. No acabaré el común/reutilizable porque es más complejo de lo que parece y no hago el copy/paste porque es pecado. La aplicación y yo nos quedamos bloqueados.
  • Varios meses para estar pensando: "debería acabar eso que tengo a medias…."

Pues eso, ahora mismo estoy en el punto 3, empezando la semana de darle vueltas a ver si hago o no la cosa común/reutilizable. Para este proyectito no merecería seguramente la pena, pero seguro que este proyectito no es el último.

¿No estais hasta las narices de hacer siempre lo mismo, una y otra vez tabla en base de datos, ventana de alta, de modificación y de baja?. ¿Haríais la cosa común/reutilizable?.

Jun 01

5 motivos para no hacer diseño.

¿Por qué no se hace diseño de verdad en los proyectos software de las empresas de verdad?. Estos son los motivos

  1. El diseño es un documento que no sirve para nada. Eso justifica los siguientes puntos.
  2. Como no sirve para nada, hay que hacerlo porque lo pide el cliente, lo más rápido posible para quitarse el muerto de encima.
  3. Como no sirve para nada, puede hacerlo cualquier "mindundi", aunque no sepa UML ni mucho menos diseño. Total, el cliente tampoco sabe y no se va a dar cuenta.
  4. Como no sirve para nada, ¿para qué entregárselo a los programadores luego?
  5. Se termina el proyecto. El diseño, como ya sabíamos, no se parece en nada al código hecho, hay que hacer ingeniería inversa. Esto demuestra el punto 1: el diseño es un documento que no sirve para nada.

Claramente una pescadilla que se muerde la cola y que se autojustifica.

May 18

Código pegamento (Glue Software)

Cuando llevas tiempo programando y te preocupas de que tu código sea reutilizable en varios proyectos, vas consiguiendo componentes -o librerías- de cierta embergadura que puedes usar en varios proyectos. Ojo, no hablo de librerías normalitas, de componentes pequeños reutilizables, sino de módulos grandes. Normalmente estos módulos interactúan entre sí, por lo que se suelen poner interfaces para que las dependencias no sean muy fuertes.

Sin embargo, estos módulos no son independientes. Dependen unos de otros a través de sus interfaces. Si no vamos con cuidado, es fácil que para usar un módulo tengamos que traernos otros que no nos interesan, símplemente porque necesitamos sus interfaces.

Veamos todo esto con un poco más de detalle. Imagina que vamos a controlar un GPS y vamos a pintar en un mapa la posición del GPS. Si queremos hacer módulos reutilizables, podemos hacer los siguientes

  • Una clase o grupo de clases que se conecta con el GPS para obtener la posición que nos vaya dando este equipo.
  • Una clase o grupo de clases que hacen de MAPA. En ella pintaremos la posición que nos de el GPS.

Solo dos, que si no, nos liamos mucho…

Tenemos que comunicar estos módulos entre sí de alguna forma, para que el GPS pase las posiciones al MAPA. Podríamos, por ejemplo, aplicar un patrón observador al GPS de forma que MAPA implemente la interface ObservadorDePosicion y se suscriba a cambios de posición en el GPS.

¿Cual es el problema?. La interface del observador de Posición estará posiblemente en GPS, así que MAPA necesita el módulo GPS, sólo por la interface, aunque en otro proyecto no haya GPS. Si ponemos esta interface en MAPA, entonces GPS necesita a MAPA sólo por esa interface, aunque no haya mapa en nuestro próximo proyecto con GPS.

¿Cómo podemos evitarlo?. Usando lo que yo creo que se conoce como código pegamento -Glue Software-. La verdad es que no tengo ni idea si es eso del código pegamento. Se que existe algo que llaman código pegamento, pero nunca lo he visto "en acción", pero lo que vamos a hacer responde muy bien a esa descripción.

Para evitar la dependencia, hacemos nuestro GPS con su interface ObservadorDePosicion y su patrón observador. Al MAPA le ponemos un método tomaPosición(). Ambos módulos son totalmente independientes, ni MAPA implementa ObservadorDePosicion ni GPS ve a MAPA para nada. Para comunicarlos únicamente tenemos que hacer una clase PEGAMENTO en nuestro proyecto que reciba tanto a GPS como a MAPA. La clase PEGAMENTO se suscribe a GPS implementando su interface ObservadorDePosicion y cuando reciba una posición, llama al método tomaPoscion() de MAPA. Es más, incluso puede traducir la posición en el formato que la reciba del GPS para adaptarla al formato que necesite el MAPA.

El resultado son dos módulos, GPS y MAPA, totalmente independientes, que ni siquiera tienen que estar de acuerdo en el formato en que se pasan el dato Posición. En el proyecto se hace una clase PEGAMENTO, únicamente válida para ese proyecto y bastante sencilla de hacer.

Imagina ahora un proyecto más grande, con varios módulos. Pueden hacerse los módulos totalmente independientes entre ellos y perfectamente reutilizables en cualquier otro proyecto ellos solos. Dentro del proyecto, cada asociación entre dos módulos se establecería haciendo una clase PEGAMENTO. Habría tantas clases PEGAMENTO como asociaciones entre módulos.

Lo más divertido sería el main(), que quedaría algo parecido a esto.

Modulo1 m1 = new Modulo1();
Modulo2 m2 = new Modulo2();
Modulo3 m3 = new Modulo3();

Pegamento1Con2 p12 = new Pegamento1Con2(m1,m2);
Pegamento1Con3 p13 = new Pegamento1Con3(m1,m3);
Pegamento2Con3 p23 = new Pegamento2Con3(m2,m3);

En fin, todo ventajas. Módulos completamente independientes que se pueden desarrollar por separado, de forma aislada, probar aislados e incluso instanciar sueltos. Un montón de clases Pegamento que representan claramente una asociación. Casi, casi es como coger un diagrama UML y por cada paquete/módulo hacer una librería y por cada línea de asociación una clase Pegamento.

Obviamente, esto tan "complejo", vale para módulos de cierto nivel. Si vamos a hacer una librería matemática, no vamos a andar poniendo un ObservadorResultadoOperacionSeno …