Inicio > Metodología > ¿Dónde está ubicada la lógica de negocio de tu aplicación? (1) – Teoría

¿Dónde está ubicada la lógica de negocio de tu aplicación? (1) – Teoría

Este post es como consecuencia de la realización de un proyecto en el cliente donde me encuentro. El objetivo del proyecto ha sido:

Independizar la capa de negocio de la capa de presentación, desacoplarla totalmente para que pueda ser reutilizada desde cualquier entorno gráfico, dispositivo móvil, en una posible evolución a orientación a servicios (SOA), etc.

El proyecto ha sido una labor de investigación y práctica continua. Se basa en la aplicación de las más actuales metodologías de desarrollo de software y en las buenas prácticas documentadas.

Como la documentación acumulada es mucha he decidido separar la parte teórica de la parte práctica. Así, este post es un resumen organizado de toda la teoría que he recopilado y que me ha servido de guía y el siguiente es un relato de la experiencia de ponerla en práctica de forma satisfactoria, un caso de éxito. Espero que os pueda ayudar o por lo menos guiar si debéis seguir este camino o uno parecido. De hecho la raíz de todas estas buenas prácticas se basan en la experiencia y el conocimiento de muchos como nosotros que nos hemos encontrado ante problemas o situaciones similares y que necesitábamos de una solución lo más efectiva y eficiente posible.

Si ya estás instruido en estas técnicas te invito a pasar directamente al segundo post: ¿Dónde está ubicada la lógica de negocio de tu aplicación? (2) – Caso práctico de desacoplamiento.

ÍNDEX.

1. ¿Dónde está la lógica de tu negocio?.

2. Organizar Lógica de negocio. Diseño Procedimental vs Orientación a Objetos.

3. Metodologías Ágiles de desarrollo de software.

3.1 Introducción a las Metodologías Ágiles.

3.2 Programación Extrema. Programación en pareja.

3.3 Patrones de diseño, Antipatrones y Refactorización.

3.4 Refactorizar. Refactorización.

1. ¿Dónde está la lógica de tu negocio?

Las aplicaciones distribuidas ofrecen la solución más optimizada para grandes sistemas que requieren alta concurrencia o máxima reutilización de código. La ubicación de los componentes lógicos impacta sobre el rendimiento, sobre la reutilización del código o sobre la facilidad de programación. En cualquier aplicación distribuida la capa de presentación debe ser completamente independiente de las reglas de negocio. Sólo se dedicará a la presentación y al manejo de los datos de la aplicación que obtendrá a través del uso de los objetos de la capa de negocio. La arquitectura 3-capas se ha convertido en el modelo por defecto de las aplicaciones basadas en web. Esta arquitectura parte una aplicación en tres capas lógicas; presentación, lógica de negocios y acceso a datos. La lógica de negocios queda en el medio, por eso generalmente también se la conoce como capa intermedia.

Un error frecuente en la creación de los interfaces de usuario consiste en olvidar que las reglas de negocio no se hallan en el interfaz, sino en los objetos subyacentes que residen en las capas inferiores de la solución. La capa de presentación no es más que un sistema de presentación y manejo de datos que se obtienen y se actualizan con los objetos de negocio comunes para todas las aplicaciones que los usan. Si se olvida este aspecto se puede caer en la tentación de colocar reglas de negocio en el interfaz de usuario, imposibilitando la reutilización de las mismas y complicando la distribución y despliegue de la aplicación.

La capa de negocio es la lógica de funcionamiento de la aplicación distribuida. En ella se encuentran todos los elementos de la aplicación que pueden ser reutilizados. La capa de negocio o capa intermedia aísla la capa de presentación de la capa de servidor. Estructura de datos y lógica que las usa son independientes de la capa de presentación.

El objetivo es la reutilización de la lógica de negocio desde cualquier capa de presentación y también poder actualizar o modificar la capa de acceso a datos para acceder a un proveedor más liviano si el objetivo es implementar nuestra aplicación en un dispositivo móvil por ejemplo, sin que esto sea un problema.

¿Pero por qué tenemos que tener en cuenta este concepto? si cuando llegamos a un cliente, nos sentamos delante, entendemos su problemática, tomamos los requerimientos, diseñamos una solución, la desarrollamos y la ponemos en producción. Esta difícil tarea es una parte del problema, pues los sistemas coexisten, cohabitan y por tanto habrá muchos factores externos relacionados con ello que evolucionarán y por tanto nuestro sistema deberá también evolucionar con él.

Pensemos ahora en la realidad, en la vida, los servicios evolucionan, los consumidores no tienen porque requerir toda la capacidad del servicio, sino estar interesados tan solo en una parte del mismo.

Todo es muy bonito y todo funciona muy bien la primera vez, pero los sistemas deben poder crecer, madurar, evolucionar, sin la única alternativa de tirarlo todo y empezar de nuevo.

Proyectos planteados con metodologías de desarrollo de software ágiles, pueden aplicar técnicas de refactorización para acomodar el producto a las nuevas necesidades, quizás por ello muchos tratan de huir de las prácticas ágiles para no tener que enfrentarse con estos problemas durante el ciclo de vida del proyecto.

En todo caso, no hay que subestimar nunca las necesidades de una aplicación compleja, ni tampoco conviene sobredimensionar la estructura de una aplicación sencilla que puede resolverse con medios más asequibles.

2. Organizar lógica de negocio. Diseño procedimental vs Orientación a Objetos.

Hay dos formas de organizar la lógica de negocio según el estilo de diseño:

Diseño procedimental u Orientado a Objetos (OO).

El diseño procedimental organiza el código en funciones y estructuras de datos simples. Las estructuras de datos, generalmente se crean, se inicializan y se pasan como parámetros a las funciones. La relación entre estas funciones y los datos que utilizan suelen asociarse en librerías según el criterio del programador.

Los principales atractivos del estilo procedimental son:

–         Implementar nuevas funcionalidades es fácil. Basta añadir código a un script transaccional o añadir un script transaccional nuevo.

–         No hace falta diseñar la aplicación. No se necesita determinar las clases ni sus responsabilidades. La lógica de negocio se distribuye en los spcripts transaccionales y los datos persistentes en simples estructuras de datos.

–         Es más asequible para programadores con poca experiencia. Este es el principal motivo por el que las empresas de software suelen decantarse principalmente por el estilo procedimental frente al OO.

El sistema funciona bien con lógicas de negocio simples pero a medida que ésta se complica, los scripts transaccionales suelen contener miles de líneas de código. Se promueve la duplicación de código, los programadores tienden a programar para si mismos debido a la dificultad de encontrar los métodos disponibles para cada modelo de datos. Se pierde el principal atractivo de la omisión del diseño. El sistema se hace demasiado difícil de entender, probar y mantener.

Por el contrario, el diseño orientado a objetos organiza el código en objetos que contienen ambos aspectos, datos y comportamiento. Dichos objetos colaboran, generalmente mediante herencia o composición para resolver la lógica de la aplicación. La relación entre los datos y las funciones que los usan está mantenida en su mayor parte por el propio lenguaje. Generalmente el diseño orientado a objetos es más fácil de entender, mantener, extender y probar.

La orientación a objetos nació con la finalidad de gestionar la mayor complejidad de los desarrollos en las empresas, que pasaron de ser desarrollos para un solo ordenador a desarrollos que son la columna vertebral o el sistema nervioso de toda la empresa. Por otro lado también permite la reutilización del código generado para gestionar la lógica de negocio.

Para desarrollar en objetos es necesaria una gran cantidad de análisis para generar los objetos adecuados que definan correctamente la empresa, negocio o institución. Por cada objeto a su vez el analista programador se debe preguntar, qué debe conocer, que atributos debe tener, qué debe hacer. El objetivo del análisis es conseguir una abstracción de la gestión para poder modelar de forma óptima la solución. De esta forma se podrá entender, mantener y extender mucho más fácilmente el sistema.

A pesar de los beneficios del diseño OO, muchas aplicaciones J2EE modernas se han escrito utilizando el estilo procedimental. Uno de los precursores principales de dicho estilo fue la especificación EJB (anterior a 3.0).

Las principales ventajas de la arquitectura de Framework ligero (diseño OO) son:

–         Es simple y versátil

–         Escalable horizontalmente mediante el uso de clusters en los contenedores web aunque limitada por las sesiones y el servidor de base de datos

–         Reutilización de código: Los contenedores ligeros manejan POJOs que son independientes del contenedor. Es posible reutilizar los modelos del dominio en cualquier otro entorno.

–         Servicios declarativos mediante contenedores ligeros con soporte de AOP. Por ejemplo, la configuración de transacciones mediante Spring es más configurable que la proporcionada por EJB CMT

–         Orientación a Objetos: Puesto que no hay limitaciones (o muy pocas, como podría ser la especificación java beans) impuestas en los POJOs, la lógica de negocio de la aplicación puede resolverse utilizando técnicas de diseño OO. Esta ventaja se hace más importante según la lógica de negocio se hace más compleja.

–         Es posible escribir test unitarios de forma independiente para cada modelo del dominio ya que no es necesario desplegarlos en el contenedor. El desarrollo dirigido por test (Test Driven Development) resulta natural en este entorno. El respaldo de los test unitarios permite que el código pueda refactorizarse con seguridad según evoluciona la aplicación.

3. Metodologías Ágiles de desarrollo de software.

3.1  Introducción a las Metodologías Ágiles.

La forma tradicional de desarrollar software se basa en procesos predefinidos con documentación muy precisa y una detallada planificación inicial que debe seguirse estrictamente. Esta forma de trabajar surgió naturalmente hace unos cincuenta años como una adaptación del manejo de proyectos de ingeniería, que era lo más parecido a desarrollar programas que se conocía en ese momento, y funcionó razonablemente bien en un comienzo. También es necesario tener en cuenta que los ordenadores eran enormemente caros, la mayor parte de la inversión informática se la llevaban los equipos y por esta razón los programas se  hacían a medida para unas máquinas que se adquirían, no lo olvidemos, para realizar unas tareas muy concretas.

Tradicionalmente los proyectos se dividen en etapas bien diferenciadas: Análisis de Factibilidad, Análisis de Requerimientos, Diseño, Programación y Testeo.

Generalmente se trata de que haya feedback (retroalimentación) entre las etapas contiguas, de tal forma de que, por ejemplo, haya un momento en que se mejoren los Requerimientos en base a comentarios, sugerencias y necesidades de los responsables del Diseño. Sin embargo, esta forma de desarrollar software genera muy serios problemas, debido a que al comienzo del proyecto, que es cuando menos se conocen las características del problema que resolver, se toman las decisiones de mayor relevancia e impacto en el resto del proyecto.

Como las posibilidades de tomar decisiones erróneas al comienzo del proyecto son generalmente mayores que cuando ya se ha trabajado un tiempo en el proyecto, muchas veces proyectos no cumplen sus objetivos, no se terminan a tiempo o resultan mucho más caros que lo presupuestado. En particular, esto ocurre frecuentemente en los casos en que el grupo de desarrollo necesita crear algo totalmente nuevo o de características específicas que nadie ha creado aún, lo cual es cierto en la mayoría de los proyectos de software, porque en caso contrario, la organización compraría directamente un producto o sistema ya desarrollado por otra empresa.

La distinción entre las tareas relevantes y las que no agregan valor se consigue a través de la creación de contextos con alto nivel de empowerment y feedback.

Esto se consigue a través de un desarrollo incremental: el producto puede probarse desde las primeras semanas y meses del proyecto al menos en cuanto a su funcionalidad más básica, que luego va creciendo y mejorando

Se entiende como desarrollo ágil de software a un paradigma de desarrollo de software basado en procesos ágiles. Los procesos ágiles de desarrollo de software, conocidos anteriormente como metodologías livianas, intentan evitar los tortuosos y burocráticos caminos de las metodologías tradicionales enfocándose en la gente y los resultados.

Es un marco de trabajo conceptual de la ingeniería de software que promueve iteraciones en el desarrollo a lo largo de todo el ciclo de vida del proyecto. Existen muchos métodos de desarrollo ágil; la mayoría minimizan riesgos desarrollando software en cortos lapsos de tiempo. El software desarrollado en una unidad de tiempo es llamado una iteración, la cual debe durar de una a cuatro semanas. Cada iteración del ciclo de vida incluye: planificación, análisis de requerimientos, diseño, codificación, revisión y documentación. Una iteración no debe agregar demasiada funcionalidad para justificar el lanzamiento del producto al mercado, pero la meta es tener una demo (sin errores) al final de cada iteración. Al final de cada iteración el equipo vuelve a evaluar las prioridades del proyecto.

Algunas metodologías ágiles de desarrollo de software:

  • Programación Extrema (XP). (ver punto 4).
  • Adaptive Software Development (ASD).
  • Agile Unified Process (AUP).
  • Crystal Clear.
  • Essential Unified Process (EssUP).
  • Feature Driven Development (FDD).
  • Lean Software Development (LSD).
  • Open Unified Process (OpenUP).
  • Scrum.

Manifiesto  Ágil.

Se trató  de un compromiso público en buscar nuevas y mejores formas de desarrollar software poniendo énfasis en las personas y sus interacciones, la colaboración y la respuesta continua al cambio, explorando nuevas formas de hacer las cosas y compartiendo experiencias, dando origen a una nueva comunidad de profesionales que explora sistemáticamente nuevas alternativas frente al modo tradicional de desarrollar software.

3.2  Programación Extrema. Programación en pareja.

Programación extrema.

La programación extrema o eXtreme Programming (XP) es el más destacado de los procesos ágiles de desarrollo de software. Al igual que éstos, la programación extrema se diferencia de las metodologías tradicionales principalmente en que pone más énfasis en la adaptabilidad que en la previsibilidad. Los defensores de XP consideran que los cambios de requisitos sobre la marcha son un aspecto natural, inevitable e incluso deseable del desarrollo de proyectos. Creen que ser capaz de adaptarse a los cambios de requisitos en cualquier punto de la vida del proyecto es una aproximación mejor y más realista que intentar definir todos los requisitos al comienzo del proyecto e invertir esfuerzos después en controlar los cambios en los requisitos.

Se puede considerar la programación extrema como la adopción de las mejores metodologías de desarrollo de acuerdo a lo que se pretende llevar a cabo con el proyecto, y aplicarlo de manera dinámica durante el ciclo de vida del software.

Valores de la programación extrema son: simplicidad, comunicación, feedback y coraje. Un quinto valor, respeto, fue añadido en la segunda edición de Extreme Programming Explained. Los cinco valores se detallan a continuación:

–          Simplicidad. Un diseño complejo del código junto a sucesivas modificaciones por parte de diferentes desarrolladores hacen que la complejidad aumente exponencialmente. Para mantener la simplicidad es necesaria la refactorización del código, ésta es la manera de mantener el código simple a medida que crece. También se aplica la simplicidad en la documentación, de esta manera el código debe comentarse en su justa medida, intentando eso sí que el código esté autodocumentado. Para ello se deben elegir adecuadamente los nombres de las variables, métodos y clases. Los nombres largos no decrementan la eficiencia del código ni el tiempo de desarrollo gracias a las herramientas de autocompletado y refactorización que existen actualmente. Aplicando la simplicidad junto con la autoría colectiva del código y la programación por parejas se asegura que cuanto más grande se haga el proyecto, todo el equipo conocerá más y mejor el sistema completo.

–          Comunicación. La comunicación se realiza de diferentes formas. Para los programadores el código comunica mejor cuanto más simple sea. Si el código es complejo hay que esforzarse para hacerlo inteligible. El código autodocumentado es más fiable que los comentarios ya que éstos últimos pronto quedan desfasados con el código a medida que es modificado. Debe comentarse sólo aquello que no va a variar, por ejemplo el objetivo de una clase o la funcionalidad de un método. Los programadores se comunican constantemente gracias a la programación por parejas.

–          Feedback. Al estar el cliente integrado en el proyecto, su opinión sobre el estado del proyecto se conoce en tiempo real. Al realizarse ciclos muy cortos tras los cuales se muestran resultados, se minimiza el tener que rehacer partes que no cumplen con los requisitos y ayuda a los programadores a centrarse en lo que es más importante. Considérense los problemas que derivan de tener ciclos muy largos. Meses de trabajo pueden tirarse por la borda debido a cambios en los criterios del cliente o malentendidos por parte del equipo de desarrollo.

–          Coraje o valentía. Para los gerentes la programación en parejas puede ser difícil de aceptar, porque les parece como si la productividad se fuese a reducir a la mitad ya que solo la mitad de los programadores está escribiendo código. Hay que ser valiente para confiar en que la programación por parejas beneficia la calidad del código sin repercutir negativamente en la productividad. No se debe emprender el desarrollo de grandes marcos de trabajo (frameworks) mientra el cliente espera. En ese tiempo el cliente no recibe noticias sobre los avances del proyecto y el equipo de desarrollo no recibe retroalimentación para saber si va en la dirección correcta. La forma de construir marcos de trabajo es mediante la refactorización del código en sucesivas aproximaciones.

–          Respeto. Los miembros respetan su trabajo porque siempre están luchando por la alta calidad en el producto y buscando el diseño óptimo o más eficiente para la solución a través de la refactorización del código.

Características de la programación extrema:

–          Desarrollo iterativo e incremental: pequeñas mejoras, unas tras otras.

–          Pruebas unitarias continuas.

–          Corrección de todos los errores antes de añadir nueva funcionalidad. Hacer entregas frecuentes.

–          Refactorización del código, es decir, reescribir ciertas partes del código para aumentar su legibilidad y mantenibilidad pero sin modificar su comportamiento. Las pruebas han de garantizar que en la refactorización no se ha introducido ningún fallo.

–          Propiedad del código compartida: en vez de dividir la responsabilidad en el desarrollo de cada módulo en grupos de trabajo distintos, este método promueve el que todo el personal pueda corregir y extender cualquier parte del proyecto.

–          Simplicidad en el código: es la mejor manera de que las cosas funcionen. Cuando todo funcione se podrá añadir funcionalidad si es necesario. La programación extrema apuesta que es más sencillo hacer algo simple y tener un poco de trabajo extra para cambiarlo si se requiere, que realizar algo complicado y quizás nunca utilizarlo.

–          Programación en parejas: se recomienda que las tareas de desarrollo se lleven a cabo por dos personas en un mismo puesto. Se supone la mayor calidad del código escrito de esta manera, el código es revisado y discutido mientras se escribe, es más importante que la posible pérdida de productividad inmediata.

La revisión de código constante es muy utilizada con la técnica de pair programming de extreme programming. Esta técnica involucra dos desarrolladores por computadora. De hecho implica una constante revisión de código y refactorizaciones a lo largo del desarrollo.

Programación en pareja.

La Programación en Pareja (o Pair Programming en inglés) requiere que dos Ingenieros en Software participen en un esfuerzo combinado de desarrollo en un sitio de trabajo. La persona que está haciendo la codificación se le da el nombre de controlador mientras que a la persona que está dirigiendo se le llama el navegador. Se sugiere a menudo para que a los dos socios cambien de papeles por lo menos cada media hora o después de que se haga una prueba de unidad.

Ventajas de la programación en pareja:

–          Más Disciplina. Emparejando es más probable que se haga lo que se debe hacer.

–          Mejor código. Emparejando es menos probable producir malos diseños ya que se tiende a diseñar con mayor calidad.

–          Flujo de trabajo constante. El emparejamiento produce un flujo de trabajo distinto al trabajar solo. En pareja el flujo de trabajo se recupera más rápidamente: un programador pregunta al otro ¿por dónde quedamos?. Las parejas son más resistentes a las interrupciones ya que un desarrollador se ocupa de la interrupción mientras el otro continúa trabajando.

–          Múltiples desarrolladores contribuyen al diseño. Si las parejas rotan con frecuencia en el proyecto significa que más personas están involucradas con una característica en particular. Esto ayuda a crear mejores soluciones, especialmente cuando una pareja no puede resolver un problema difícil.

–          Moral mejorada. La programación en parejas es más agradable para algunos programadores que programar solos.

–          Propiedad colectiva del código. Cuando el proyecto se hace en parejas, y las parejas rotan con frecuencia, todos tienen un conocimiento del código base.

–          Enseñanza. Todos, hasta los novatos, poseen conocimientos que los otros no. La programación en pareja es una forma amena de compartir conocimientos.

–          Cohesión de equipo. La gente se familiariza más rápidamente cuando programa en pareja. La programación en pareja puede animar el sentimiento de equipo.

–          Pocas interrupciones. La gente es más reticente a interrumpir a una pareja que a una persona que trabaja sola.

–          Menos estaciones de trabajo. Ya que dos personas van a trabajar en una estación de trabajo, se requieren menos estaciones de trabajo, y las estaciones extras pueden ser ocupadas para otros propósitos.

Críticas a la programación en pareja:

–          Desarrolladores expertos pueden encontrar tedioso enseñar a un desarrollador menos experimentado en un ambiente emparejado.

–          Muchos desarrolladores prefieren trabajar solos y encuentran el ambiente emparejado incómodo.

–          La productividad es difícil de medir, para comparar desarrolladores en parejas contra desarrolladores trabajando solos usan métricas de programación que son controvertidas en el mejor de los casos.

–          Diferencias en el estilo de codificación pueden dar como resultado conflictos, aunque esto a su vez promueve la normalización (estandarización), para que todo el mundo pueda entender el código.

–          En caso de que la pareja tenga cronogramas de trabajo ligeramente distintos, lo cual es común en un ambiente que valora el balance trabajo – vida, la pareja solo funcionará en la intersección de los cronogramas. Por lo tanto, se requieren más horas hombre para completar una tarea, un día típico tiene menos horas en pareja, lo cual incrementa el tiempo para completar la tarea.

–          Una compañía que funciona con Teletrabajo (trabajo desde el hogar o a distancia) o cuando un empleado debe trabajar desde afuera de las oficinas por cualquier razón, la programación en pareja se hace difícil o hasta imposible.

3.3  Patrones de diseño, Antipatrones y Refactorización.

En orientación a objetos los conceptos tales como herencia, encapsulamiento o polimorfismo no son por sí solos suficientes. Estas técnicas deben combinarse con otras de mayor nivel para poder obtener software flexible. Estas técnicas de mayor nivel son: los Patrones de Diseño, para obtener software flexible; los Antipatrones para evitar cometer errores recurrentes; y la Refactorización para asegurar reorganizaciones ordenadas de código fuente y mejorar la mantenibilidad, o salir de algún Antipatrón.

Según las buenas y las malas experiencias tenemos:

  • Los Patrones de Diseño se corresponden con las buenas experiencias, ya que reúnen resoluciones a problemas recurrentes encontrados en el diseño de software orientado a objetos.
  • Los Antipatrones, por su parte, se corresponden a las malas experiencias ya que reúnen soluciones que han producido efectos negativos. Los Antipatrones proveen dos soluciones: la problemática (aquélla con el impacto negativo), y la refactorizada (aquélla que transforma la situación negativa en una más saludable).

Los Patrones nominan soluciones exitosas, los Antipatrones situaciones no exitosas y las Refactorizaciones síntomas (“bad smells”).

Ante las nuevas metodologías ágiles de desarrollo, en las cuales la tendencia es hacia la simplicidad del diseño, el uso de Patrones de Diseño está casi rechazado en pos de un poderoso proceso de Refactorización. Estas metodologías buscan mantener el código lo más semántico posible, cosa que no necesariamente es factible mediante el uso de Patrones de Diseño donde podrían aparecer clases y colaboraciones que no necesariamente tienen su representación en el negocio.

Antipatrones.

Los antipatrones (antipatterns) son descripciones de situaciones, o soluciones, recurrentes que producen consecuencias negativas. Una problemática, que genera consecuencias altamente negativas; y otra llamada refactorizada, en la cual el problema es rediseñado y transformado en una situación más saludable

Mientras que los patrones de diseño documentan soluciones exitosas, los antipatrones documentan soluciones problemáticas. Los Antipatrones identifican claramente las malas prácticas para ayudar a evitarlas o resolverlas.

Los antipatrones de desarrollo de software describen problemas comunes con los que se encuentran los programadores durante el proceso de desarrollo.

Para que un sistema sea fácilmente extensible y mantenible debe estar bien estructurado, lo cual no siempre se logra. A menudo sucede que a medida que se va desarrollando el sistema va perdiendo la estructura definida por la arquitectura, el diseño. Esta estructura va cambiando a medida que los programadores aprenden nuevas restricciones y enfoques que modifican la forma de implementar soluciones. Una forma de volver a estructurar el código fuente es mediante la refactorización.

Ejemplos de Antipatrones generales de diseño de software:

  • Botón mágico (magic pushbutton). Tender, desarrollando interfaces, a programar la lógica de negocio en los métodos de interacción, implementando los resultados de las acciones del usuario en términos no suficientemente abstractos. Muy común en entorno de programación gráficos. Una manera mejor de hacer esto está en refactorizar la lógica del negocio en una clase o método separado.

Los problemas con este antipatrón son:

–         Mantenimiento del código difícil.

–         Cambiar la interfaz o la adición de una nueva es complicado.

–         La prueba del código es difícil.

  • Clase Gorda. Dotar a una clase con demasiados atributos y/o métodos, haciéndola responsable de la mayoría de la lógica de negocio.

Ejemplos de Antipatrones de diseño orientado a objetos:

  • Modelo de dominio anémico (anemic domain model). Usar un modelo del dominio sin ninguna lógica de negocio. Esto no es un enfoque orientado a objetos porque cada objeto debería tener tanto propiedades como comportamiento asociado.

Ejemplos de Antipatrones de programación:

  • Acumular y arrancar (accumulate and fire). Establecer una colección de variables globales para ser usadas por un conjunto de subrutinas.
  • Ancla del barco (boat anchor). Retener partes del sistema que ya no tienen utilidad.
  • Lava seca (lava flow). Código muerto e información de diseño olvidada permanecen congelados en un diseño cambiante. Esto es análogo a un flujo de lava en el que se van endureciendo pedazos de roca. La solución incluye un proceso de gestión de la configuración que elimina el código muerto y permite evolucionar o rehacer el diseño para acrecentar la calidad.
  • Programación por excepción (coding by exception). Añadir trozos de código para tratar casos especiales a medida que se identifican.

3.4  Refactorizar. Refactorización.

En ingeniería del software, el término refactorización se usa a menudo para describir la reestructuración del código fuente sin cambiar su comportamiento, lo que se conoce informalmente por limpiar el código. Mejora su legibilidad o simplifica su estructura sin cambiar sus resultados. En programación extrema y otras metodologías ágiles, el refactoring es una parte integral de ciclo de desarrollo de software. No arregla errores ni añade funcionalidad. El objetivo, por el contrario, es mejorar la facilidad de comprensión del código o cambiar su estructura y diseño y eliminar código muerto, para facilitar el mantenimiento en el futuro.

Un ejemplo de una refactorización trivial es cambiar el nombre de una variable para que sea más significativo, como una sola letra ‘t’ a ‘tiempo’. Una refactorización más compleja es transformar el trozo dentro de un bloque en una subrutina. Una refactorización todavía más compleja es remplazar una sentencia condicional if por polimorfismo.

Optimizar es diferente a refactorizar. Antes de optimizar, uno debe primero refactorizar el código de modo que el código llegue a ser fácil de entender y por lo tanto fácil optimizar. Así mientras la optimización suele agregar complejidad, la refactorización simpleza.

La refactorización es difícil de justificar a veces ya que consume recursos y no aporta ninguna nueva funcionalidad.

El libro de Martin Fowler Refactoring es la referencia clásica. Aunque la refactorización de código se ha llevado a cabo de manera informal durante años, la tesis doctoral de William F. Opdyke (1993) es el primer trabajo conocido que examina específicamente esta técnica. Todos estos recursos proporcionan un catálogo de métodos habituales de refactorización. Un método de refactorización tiene una descripción de cómo aplicar el método e indicaciones sobre cuándo debería (o no debería) aplicarse.

La refactorización es un concepto tan importante que ha sido identificado como una de las más importantes innovaciones en el campo del software según David A. Wheeler.

Algunas ventajas  de la refactorización:

–          Si se realiza durante la codificación a lo largo del ciclo de desarrollo se evita que se deteriore el diseño original. Refactorizar ayuda a que el código siga representando el diseño.

–          Los cambios hacen que se vaya perdiendo orden en el código. Cuánto más desorden mas difícil comprenderlo y mantenerlo.

–          La refactorización facilita la comprensión del código fuente, principalmente para los desarrolladores que no estuvieron involucrados desde el comienzo del desarrollo. El hecho que el código fuente sea complejo de leer reduce mucho la productividad ya que se necesita demasiado tiempo para analizarlo y comprenderlo.

–          Mejora la robustez del código escrito.

–          La refactorización permite programar más rápido, lo que eleva la productividad de los desarrolladores. Se reducen los tiempos que comportan la aplicación de cambios.

Ejemplos de refactorizaciones:

–          Duplicated code (código duplicado). Una de las principales razones para refactorizar. La solución es extraerlo y unificarlo.

–          Long parameter list (lista de parámetros extensa). Éste tipo de métodos, los que reciben muchos parámetros, suelen variar con frecuencia, se vuelven difíciles de comprender e incrementan el acoplamiento. Los mínimos parámetros necesarios para que el objeto en cuestión recupere lo necesario.

Regla de los tres strikes (Fowler, 1999).

Sostiene que la tercera vez que se debe realizar un trabajo similar a uno ya efectuado deberá refactorizarse. La primera vez se realiza directamente, la segunda vez se realiza la duplicación y finalmente, a la tercera se refactoriza.

¿Cuándo se debería refactorizar?

–          Cuando se usan identificadores mal escogidos.

–          Cuando se incluyen fragmentos de código duplicados.

–          Cuando se incluye lógica condicional compleja.

–          Cuando los métodos usan un número elevado de parámetros.

–          Cuando se incluyen fragmentos de código secuencial muy extensos.

–          Cuando la estructura está dividida en módulos enormes (estructura monolítica).

–          Cuando los módulos en los que se divide no resultan razonables desde el punto de vista lógico (cohesión baja).

–          Cuando los distintos módulos de un sistema están relacionados con otros muchos módulos de un sistema (acoplamiento fuerte).

–          Cuando los métodos que realizan funciones análogas se usan de forma diferente (tienen nombres distintos y/o reciben los parámetros en distinto orden).

–          Cuando un comentario se hace imprescindible.

–          Cuando se encuentra lógica de negocio en la capa de presentación.

  1. Aún no hay comentarios.
  1. No trackbacks yet.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: