Inversión de Dependencias

Este el quinto principio de los principios SOLID y personalmente creo que es el que mayor impacto tiene a la hora de hacer soluciones testeables. Pero curiosamente me encuentro recurrentemente con una importante cantidad de gente que no lo usa o que lo interpreta incorrectamente. Es por esto que decidí hacer un video al respecto.

Me quedó un video bastante corto, ~10 minutos, en el que explico el principio utilizando código y diagramas. Espero les resulte útil.

Desorientados con los patrones de diseño

Los patrones de diseño son una herramienta muy popular en la actualidad, imagino que la gran mayoría de los programadores profesionales utilizan en sus soluciones algún patrón de diseño. Incluso en algunos casos, es posible que estén usando algún patrón sin ser conscientes de ello.

Sin embargo, he notado que en muchos casos se utilizan patrones sin tener en claro el problema que el patrón resuelve. En reiteradas ocasiones me he encontrado preguntado a un programador “¿Qué problema estás resolviendo con este patrón?” y he obtenido respuestas conceptualmente incorrectas. Me me encontrado con gente que cree que aplicar Model-View-Controller le dará escalabilidad a su solución. También me he encontrado con gente que organiza su solución con Layers y no sabe a ciencia cierta porque.

La razón para aplicar un patrón debería ser que el patrón en cuestión resuelve de forma satisfactoria un problema o situación concreta que uno está enfrentando. Esto implica que uno debería en primera instancia entender el problema que tiene entre manos y luego buscar un patrón que resuelva ese problema. Si no tenemos en claro el problema podríamos terminar aplicando un patrón menos apropiado.

Haciendo una analogía con la cocina: uno tiene que preparar una cena con determinas características, entonces busca en un libro de recetas alguna que se ajuste a la necesidades de la cena en cuestión. Obviamente que ese proceso de buscar el patrón apropiado puede no ser instantáneo. Uno podría estar horas buscando un patrón hasta encontrar uno apropiado o incluso podría no encontrarlo. Es ahí donde puede resultar muy valiosa la experiencia personal de cada uno y el hecho de haber leído algunos libros de patrones.

En línea con esto último, tengo que ganas de hacer un reunión (meetup) para compartir patrones diseño. Se me ocurre una consigna del tipo:

Cuentame tu problema
(y el patrón con que el que lo resolviste)

Todos los que quieran presentar se anotan con anterioridad a la reunión y al hacerlo indican que patrón presentarán. Luego durante la reunión:

  • Cada presentador tiene 15 minutos (este tiempo se puede ajustar dependiendo de la cantidad de gente presentar).
  • La presentación debe ser de un caso real de aplicación del patrón, o sea: no vale simplemente contar un patrón conceptualmente. Tiene que haber sido un caso de aplicación en un contexto de proyecto real.
  • La presentación del patrón debe empezar contando el contexto y el problema particular a resolver.
  • Debe incluir también las diferentes opciones consideradas para la solución (si es que la hubo)
  • A continuación se presenta el patrón
  • Finalmente se mencionan los efectos colaterales de la aplicación del patrón

Make sense?

El desafió de Enseñar a Diseñar

El desafió de Enseñar a Diseñar

Desde mi comienzo en la carrera docente siempre he estado en materias que en mayor o menor medida han incluido la temática de diseño de software. Cuando estaba en Algo3 y AyDOO era diseño a nivel de clases, ahora en MeMo2 cubrimos un poco de diseño a nivel de clases y también diseño de más alto nivel (arquitectura e infraestructura). Enseñar a diseñar es una tarea que me parece muy difícil. De entrada debemos decir que no hay diseños «malos» o «buenos», sino que un diseño podrá ser más o menos conveniente dependiente del contexto. Un diseño es consecuencia de un conjunto de decisiones, diseñar es decidir, elegir. Pensando en el proceso de diseño veo al menos 3 pasos:
  1. Entender el contexto, el problema a resolver, las restricciones y necesidades. Esto es lo que Kazman denomina Architectural Drivers.
  2. Entendido el contexto hay que identificar las decisiones relevantes que deben tomarse.
  3. Finalmente para cada decisión relevante hay que analizar las posibles alternativas y elegir una. Esto puede implicar hacer algunas pruebas de concepto para poder tomar decisiones con evidencia que las respalde.
El punto 1 cae dentro del área denominada ingeniería de requerimientos y cuenta con un amplio cuerpo de conocimiento. El punto 2, ya es más complejo y más allá del cuerpo de conocimiento requiere de experiencia, lo cual es bastante difícil de transmitir. El punto 3 también reviste de complejidad pero creo que en general es más fácil que el punto 2. A mi parecer identificar opciones y evaluarlas para decidir es una trabajo en esencia muy ingenieril. A comienzo de año estábamos hablando con mi colega docente Diego Marcet sobre los criterios de corrección de un ejercicio de AyDOO y lo vimos:
Pretender que en un cuatrimestre académico alguien aprenda a diseñar es demasiado ambicioso, o sea, se puede enseñar algún método/heurística pero pretender dominarlo y generar buenos resultados puede ser difícil. Por ello ajustamos nuestro objetivo para centrarnos en dar a los alumnos herramientas para ser capaces de detectar las decisiones importantes y al mismo tiempo que sean capaces de detectar decisiones inapropiadas para un contexto dado.
De cara a este objetivo trabajamos bastante sobre código ajeno, o sea, analizando y extendiendo código existente. Continuará….

Good software design

Some time ago I read the book «The Art of Agile Development» by James Shore & Shane Warden and I found a statement that really caught my attention:

A good software design minimizes the time required to create, modify, and maintain the software while achieving acceptable runtime performance.

It seems pretty obvious but despite of that it shocked me. This definition leads to some interesting implications:

  • Design quality is people-sensitive: a design that assumes some language specific knowledge maybe incomprehensible for a programmer not familiar with that language. So, a good design should take this into account.
  • Design quality is change-specific: software is designed to be easily changed in some specific ways and naturally it will be harder to change it in a different way. One size does not fit all. So a good design should anticipates what changes will be required.
  • Modification and maintenance time is are more important than creation time: in most cases the life of a software is much more longer than the time you spend in the creating the software. Because of this you write code once, but it will be read/modified many times. So, a good design priories minimizing maintenance time  over minimizing creation time.

Based on the previous three points we could say that the design quality is unpredictable, because you don’t know who is going to maintain the software, you don’t know what changes will be required and you don’t know how much maintenance time will be required. Of course you can have some ideas about these three concerns and the more idea you have, the better your design could be.

I really like this vision. The debate is open.