Heurísticas generales para encontrar clases
Uno de los aspectos fundamentales en el desarrollo de software bajo el paradigma de la programación orientada a objetos es encontrar las clases que definen dichos objetos. Esta es una tarea fundamental ya que la estructura del software orientado a objetos está basada en la descomposición correcta, bien definida y consistente de estas clases.
Tengo la sensación de que hoy en día se le presta poca atención a esta tarea y se le dedica poco tiempo a estudiar y definir las clases que tenemos que implementar en nuestras aplicaciones. Además, pudiera parecer esta una labor sencilla o inmediata pero a medida que el problema se complica o se hace más grande resulta muy complicado hacerlo bien. Sobre cuándo crear una clase ya escribí hace tiempo un artículo que si quieres, puedes leer en este enlace, este artículo de hoy viene en cierta media a complementar al anterior.
Para encontrar clases cuando programamos, podemos llevar a cabo varios métodos o heurísticas que nos van a ayudar y a facilitar la búsqueda a la hora de encontrarlas.
Tipos de clases
En primer lugar observaremos una primera clasificación de clases que podríamos seguir como pauta general y en la cual existen tres tipos bien diferenciados:
- Clases de Análisis: describen una abstracción de datos que se desprende directamente del modelo de datos externo, es decir, pertenecen al dominio del problema y son consecuencia directa de él y los expertos del negocio de dicho dominio las usan constantemente y por esto mismo son importantes y útiles, ya que lo más probable es que estas clases tengan asociadas operaciones y propiedades significativas. En este caso, las clases deben basarse en algún modelo o aspecto del mundo relevantes para la aplicación y normalmente son aquellas que coinciden con conceptos del ‘negocio’ que vamos a resolver. Un ejemplo de estas clases podría ser cualquiera que extraigamos de dicho mundo externo como la típica clase Persona o Coche.
- Clases de Implementación: describen una abstracción de datos introducida por necesidades internas de nuestros algoritmos, por lo tanto, son las clases que introducimos los programadores. Estas clases pertenecen al dominio de la solución y son de bajo nivel. Un ejemplo de estas podrían ser las clases que implementan una lista enlazada, un array, un árbol binario, un grafo…etc.
- Clases de Diseño: estas describen una elección arquitectónica y al igual que las clases de análisis son de alto nivel y por lo tanto tienen un nivel de abstracción más alto que las anteriores clases de implementación pero también pertenecen al dominio de la solución. A este tipo de clases pertenecen, por ejemplo, todas aquellas pertenecientes a los patrones de diseño.
¿Dónde buscar clases?
Además de la clasificación anterior que ya nos puede dar una idea de dónde podemos obtener clases, hay otro grupo de heurísticas que debemos tener en cuenta a la hora de buscar abstracciones correctas de clases.
Como dije anteriormente, es posible que no exista una forma inmediata de descubrir las clases que vamos a implementar en nuestra aplicación. Si no somos capaces de descubrirlas, la mayoría de los métodos muestran dos fases bien diferenciadas que en un principio pudieran parecer obvias: una es proponer clases y, la otra, descartarlas. Simple, ¿verdad? Es decir, primeramente buscaremos las posibles clases para nuestra aplicación extraídas de varias fuentes de ideas que comentaremos a continuación y luego, posteriormente, descartaremos las menos prometedoras para nuestra solución.
Pero ¿y las clases? ¿dónde podemos encontrarlas? pues, por ejemplo, a continuación enumero unas fuentes de ideas en las cuales podemos buscar y encontrarlas.
- Bibliotecas existentes: buscaremos en bibliotecas o librerías existentes clases que satisfagan y cumplan con necesidades o que describan conceptos y/o comportamientos relevantes para la aplicación. Hoy en día repositorios como Github nos ayudan enormemente en esta tarea.
- Documentos de requisitos: Nos fijaremos en términos que aparezcan frecuentemente, en aquellos que se centren mucho con definiciones explícitas o aquellos que estén definidos con mucha precisión. Todos estos conceptos suelen tener un interés especial y casi siempre esconden clases detrás de ellos.
- Conversaciones con clientes y usuarios: Como se comentó anteriormente, es importante conocer profundamente el dominio del problema y el vocabulario que se use en él por expertos del dominio o usuarios de la aplicación. En las conversaciones debemos buscar clases que representen abstracciones importantes tantos conceptuales como materiales.
- Documentación (manuales de usuario) de otros sistemas: Por ejemplo de aplicaciones similares de la competencia. Se trata de buscar conceptos o problemas que ya estén solucionados en otro software y traerlos al nuestro. Buscaremos igualmente abstracciones importantes del dominio de la aplicación, vocabulario específico que podría haberse escapado en nuestro análisis o abstracciones de diseño útiles.
- Análisis con diseñadores experimentados: Hablar con compañeros expertos en diseño de aplicaciones nos aportará luz sobre posibles patrones que podamos implementar y por consiguiente nos descubrirán las clases asociadas a dichos patrones.
- Casos de uso: Varios autores como Ivar Jacobson, se basaron en casos de uso como forma de obtener clases. Un caso de uso se describe como una sucesión de eventos iniciados por un usuario (real o de sistema). Estos eventos generalmente describen conceptos que realizan acciones y van enlazándose unos con otros y en base a estos conceptos podríamos encontrar clases útiles. Por contra, otros autores rechazan esta forma de buscar clases en los casos de uso ya que estos ponen el foco en establecer un orden de hechos que podrían hacerlo incompatible con el desarrollo de la programación orientado a objetos ya que esta rehuye de dependencias tempranas de propiedades secuenciales porque son frágiles y tienden al cambio. Digamos que el programador orientado a objetos no debe pensar en términos de “El sistema hace a y luego b” sino que se se debe preguntar “¿Cuáles son las operaciones disponibles y cuales son las restricciones sobre dichas operaciones de la abstracción a”. Basarnos en casos de uso puede llevarnos a un enfoque funcional, basado en procesos o acciones, inverso a la descomposición orientada a objetos, que se centra en abstracciones de datos.
- Leer, leer y leer: En el dominio de la solución, como programadores, debemos tener una amplia ‘cultura’ sobre estructuras de datos, algoritmos eficientes y diseño de sistemas para obtener las mejores ideas e implementaciones.
En resumen, buscar las clases para nuestras aplicaciones principalmente depende de que tengamos un amplio conocimiento en cuanto a conceptos y vocabularios del dominio del problema y del dominio de la solución.
¡Chimpún!
Bibliografía
- Construcción de Software Orientado a Objetos — 2ª Edición. Bertrand Meyer. ISBN: 978–84–8322–040–5.