28 de mayo de 2011

Interfaz de línea de comandos (CLI) y separación de ocupaciones.

Hace no mucho, me dí a la tarea de comenzar a crear una interfaz de línea de comandos (CLI por sus siglas en inglés) para el sistema al que actualmente estoy dando mantenimiento, además de ser un ejercicio intelectual bastante provechoso, obtuve resultados muy satisfactorios en cuanto al objetivo de lograr una separación del código de interfaz de usuario del código de dominio, el cual es uno de los problemas más críticos (y crónicos) que tiene el sistema en cuestión.


Como sabemos, debido a la filosofía subyacente en la gran mayoría de los entornos gráficos de programación actualmente en uso, los famosos IDE-RAD's (Rapid Application Development Environments), primero se diseña la interfaz de usuario y luego como no hay ningún lugar para poner la lógica del dominio, como no sea en la base de datos (stored procedures), si no se tiene cuidado, éste código acaba por desgracia casi siempre horriblemente mezclado y acoplado con el código de la interfaz de usuario. La base de código fuente así creada, se torna difícilmente mantenible y con el paso del tiempo y al ir cambiando los requerimientos se convierte en un serio problema en el mejor de los casos y la mayoría de las veces termina como una gran "bola de lodo" (del antipatrón big ball of mud).


Ya desde finales de los años 70's del siglo pasado, Smalltalk-80 introducía el paradigma (patrón de diseño propiamente dicho) MVC (Model-View-Controller) para evitar los problemas antes mencionados. Ya tendremos ocasión de discutir sobre el mencionado patrón de diseño posteriormente.


La cuestión es que muchos de nosotros no nos damos cuenta del problema, lo que es peor, ni siquiera lo vemos como tal. En mi caso fué hasta después de muchos años de recurrentes problemas de mantenimiento de código y de encontrarme una y otra vez sumergido en pantanos de código así mezclado (sin mencionar el sistema al que actualmente doy mantenimiento), que definitivamente supe que algo no estaba bien, mas aún: que algo estaba muy, muy mal.


Al principio no sabía exactamente que éra. Andando el tiempo y después de investigar, toparme con la verdadera POO y los patrones de diseño, sufrir un cambio de paradigma (paradigm-shift) y sobre todo, después de conocer, reflexionar e investigar mas a fondo algunos principios fundamentales de la programación tales como la modularidad, la no-redundancia, la claridad, la simplicidad, la alta cohesión, el bajo acoplamiento, la verificabilidad, entre otros, fué que me dí cuenta de la situación real.


Me dí cuenta que la razón, causa y origen de mis problemas era precisamente el estar transgrediendo sistemáticamente un principio fundamental que tiene su origen y aplicación en todas las areas de la vida en general y no solamente en la programación de sistemas informáticos. Me refiero al principio de separación de ocupaciones (y/o preocupaciones), mejor conocido en inglés como separation of concerns.


El origen del problema era que estaba yo mezclando a la fuerza y en un mismo recipiente dos cosas que son totalmente distintas e independientes una de la otra ("ortogonales" dirían algunos). Esto es: la interfaz de usuario y la lógica del dominio.


A continuación quiero compartir con ustedes algunas citas memorables de Martin Fowler sobre el tema.


"Domain objects should be completely self contained and work without reference to the presentation, they should also be able to support multiple presentations, possibly simultaneously. This approach was also an important part of the Unix culture, and continues today allowing many applications to be manipulated through both a graphical and command-line interface." - http://martinfowler.com/eaaDev/uiArchs.html


"So, if you write an application with a WIMP (windows, icons, mouse, and pointer) GUI, you should be able to write a command line interface that does everything that you can do through the WIMP interface—without copying any code from the WIMP into the command line." - http://www.martinfowler.com/ieeeSoftware/separation.pdf


"A good mental test to use to check you are using Separated Presentation is to imagine a completely different user interface. If you are writing a GUI imagine writing a command line interface for the same application. Ask yourself if anything would be duplicated between the GUI and command line presentation code - if it is then it's a good candidate for moving to the domain." - http://martinfowler.com/eaaDev/SeparatedPresentation.html


Así pues, al verme enfrentado por enésima ocasión al mismo problema del alto acoplamiento (o mezcla completa) de la interfaz de usuario con la lógica del dominio. Decidí llevar a la práctica los consejos de Martin Fowler y me puse a escribir una interfaz de línea de comandos para el módulo del sistema al cual estaba dando mantenimiento en ese momento. Al hacerlo obtuve una visión sumamente clara de los objetos de dominio necesarios así como de dónde y de qué manera necesitaba refactorizar el código. Asimismo, obtuve código mas limpio, objetos mejor factorizados, separación completa de la interfaz de usuario en el módulo en desarrollo y además una nueva forma de probar los objetos del dominio sin la interfaz de usuario. ¡Todo desde la línea de comandos!.


La experiencia anterior me ha llevado a recomendar ampliamente el ejercicio de escribir una interfaz de línea de comandos para las partes de los sistemas con interfaz de usuario gráfica (GUI) en los cuales no estemos muy seguros de cuáles sean los objetos de dominio necesarios o bien tengamos los problemas crónicos de acoplamiento anteriormente mencionados.


Esto también me hizo recordar que el proceso de creación de una aplicación GUI en Smalltalk es: 1.- Diseñar el modelo del dominio 2.- Probar el modelo del dominio 3.- Diseñar la interfaz de usuario. (http://www.object-arts.com/downloads/docs/index.html)


O dicho de otra forma: Primero lo primero (First things first). En cuenstiones de programación y en especial en POO: El dominio es primero.


Gracias por leernos, buen fin de semana y como siempre todos sus comentarios son bienvenidos.