martes, 3 de febrero de 2009

Diseño orientado a objetos: The S.O.L.I.D. principles

Acá van los principios propuestos por el Tío Bob para un buen diseño orientado a objetos, en versión ultra condensada. No los sigo a rajatabla pero son una guía que conviene tener presente, como mínimo. En otro post voy a resumir las reglas de testeabilidad, que son un buen complemento a estos principios (y en parte se superponen).

Single Responsibility Principle (Principio de Responsabilidad Única)

Nunca debe haber más de un motivo por el cual modificar una clase.

Este principio se ve violado por todas partes. Un ejemplo típico es cuando un Servlet hace más de lo que debe. Ya de por sí trabajar directamente con servlets sin un framework que los esconda es una mala idea, pero cuando los usamos, debe ser solamente para dar acceso web a nuestra aplicación: levantar parámetros del request y elementos posteados, invocar las validaciones y servicios que corresponda (en otra capa) y manejar el response.

Open / Closed Principle (Principio Abierto / Cerrado)

Los elementos de software (clases, módulos, funciones, etc.) deben estar abiertos a la extensión, pero cerrados a la modificación.

En realidad, no podemos evitar completamente las modificaciones, pero el diseño puede tener en cuenta qué tipo de modificaciones contemplar, y permitir que cierto cambio de comportamiento se resuelva con nuevas implementaciones o subclases. De acá podemos derivar la regla general de "programar a interfaces", que las dependencias sean sobre abstracciones.

Liskov Substitution Principle (Principio de Sustitución de Liskov, o "Diseño por Contrato")

Los módulos que usen referencias a clases base deben poder utilizar objetos de subclases sin saberlo.

Las subclases deben seguir el comportamiento que se espera de la superclase. La superclase define un contrato. Si las subclases lo respetan, la superclase es sustituible por una subclase, y las subclases son intercambiables. Una regla relacionada con este principio es tratar de que el diseño permita a los usuarios del mismo prescindir del operador instanceof.

Interface Segregation Principle (Principio de Segregación de Interfaces)

Los clientes no deben verse obligados a depender de interfaces que no utilizan.

Las interfaces "gordas" producen acoplamiento entre clientes que deberían estar aislados. Un cliente no tiene por qué "ver" más de lo que necesita de una clase, entonces debería poder accederla a través de una interfaz particular. Por ejemplo, si tenemos una PavaElectrica, y la interfaz Pava define una dependencia con Agua, puede haber clientes para los cuales la PavaElectrica interesa sólo en tanto que ArtefactoElectrico. Y esos clientes deberían poder reutilizarse en proyectos donde haya otras implementaciones de ArtefactoElectrico pero donde no exista la definición de Agua.

Dependency Inversion Principle (Principio de Inversión de Dependencias, también conocido como "Inversión de Control")

Los módulos de alto nivel no deben depender de módulos de bajo nivel: ambos deben depender de abstracciones. Las abstracciones no deben depender de detalles: los detalles deben depender de las abstracciones.

El término "inversión" se debe a que este principio propone dar vuelta las dependencias con respecto a la tradición procedural: módulos de alto nivel que llaman a módulos de bajo nivel. En OOP creamos estas dependencias hardcodeadas cuando usamos el operador new. Cuando dependemos de abstracciones, las dependencias pueden ser inyectadas, en un módulo de inicialización o con un framework de inyección de dependencias.

1 comentario:

  1. Este comentario ha sido eliminado por un administrador del blog.

    ResponderEliminar