Pregunta

Local

Creo que hay una manera de definir objetivamente "bueno" y "malo" técnicas de diseño orientado a objetos y que, como comunidad podemos determinar cuáles son. Este es un ejercicio académico. Si se hace con seriedad y determinación, creo que puede ser de gran beneficio para la comunidad en su conjunto. La comunidad se beneficiará por tener un lugar donde podemos todos apuntan a decir, "Esta técnica es 'bueno' o 'malo' y que debe o no debe usarlo a menos que existan circunstancias especiales."

Plan de

En este esfuerzo, debemos centrarnos en principios orientados a objetos (en lugar de funcional, basado Set-u otro tipo de lenguajes).

No estoy pensando en aceptar una respuesta, en lugar me gustaría las respuestas a contribuir a la recogida final o ser un debate racional de los problemas.

Me doy cuenta de que esto puede controvertido, pero creo que podemos limar algo. Hay excepciones a casi todas las reglas y creo que aquí es donde el desacuerdo caerá. Debemos hacer declaraciones y luego en cuenta las excepciones y objeciones relevantes de los disidentes.

Basis

Me gustaría tomar una puñalada en la definición de "bueno" y "malo":

  • "bueno" - Esta técnica funcionará la primera vez y ser una solución duradera. Será fácil cambiar más tarde y pagará la inversión momento de su puesta en práctica rápidamente. Puede ser aplicado consistentemente y fácilmente reconocida por los programadores de mantenimiento en el futuro. En general, contribuye al buen funcionamiento y reduce el coste de mantenimiento durante la vida útil del producto.

  • "malo" - Esta técnica puede funcionar en el corto plazo, pero pronto se convierte en un pasivo. Es difícil cambiar de inmediato o se vuelve más difícil con el tiempo. La inversión inicial puede ser pequeño o grande, pero rápidamente se convierte en un costo cada vez mayor, llegando a ser un costo hundido y debe ser eliminado o trabajado en torno constantemente. Subjetivamente se aplica e inconsistente y puede ser una sorpresa o no son fácilmente reconocibles por los programadores de mantenimiento en el futuro. En general, contribuye a la mejor relación coste creciente de mantenimiento y / o funcionamiento del producto e inhibe o impide cambios en el producto. Al inhibir o impedir el cambio, se convierte no sólo un costo directo, pero un coste de oportunidad y una responsabilidad significativa.

Arrancador

Como un ejemplo de lo que creo que una buena contribución se vería así, me gustaría proponer un "buen" principio:

separación de intereses

[Breve descripción]

Ejemplo

[Código o algún otro tipo de ejemplo]

Objetivos

[explicación de lo que previene los problemas de este principio]

Aplicabilidad

[¿Por qué, dónde y cuándo debería utilizar este principio?]

Excepciones

[Cuando no se iba a utilizar este principio, o dónde podría en realidad ser perjudicial?]

Excepciones

[Nota alguna votos particulares o las objeciones de la comunidad aquí]

¿Fue útil?

Solución

separación de intereses

Prefiero Agregación de estilo Mixin Herencia

Mientras que la funcionalidad puede ser adquirida por la herencia de una clase de utilidad, en muchos casos todo puede ser adquirida utilizando un miembro de dicha clase.

Ejemplo (Boost.Noncopyable):

Boost.Noncopyable es una clase de C ++ que carece de un constructor de copia o operador de asignación. Se puede utilizar como una clase base para evitar la subclase de la copia o asignado (este es el comportamiento común). También se puede utilizar como un miembro directo

Convertir esto:

class Foo : private boost::noncopyable { ... };

A esto:

class Foo {
    ...
private:
    boost::noncopyable noncopyable_;
};

Ejemplo (objeto bloqueable):

Java introdujo el synchronized palabra clave como un idioma para permitir que cualquier objeto para ser utilizado en una modalidad de hebras. Esto se puede reflejar en otros idiomas para proporcionar mutex a objetos arbitrarios. Un ejemplo común es estructuras de datos:

class ThreadsafeVector<T> : public Vector<T>, public Mutex { ... };

En lugar de ello, las dos clases podrían ser agregados juntos.

struct ThreadsafeVector<T> {
    Vector<T> vector;
    Mutex mutex;
}

Objetivos

Inheritance se abusa con frecuencia como un mecanismo de reutilización de códigos. Si se utiliza herencia para nada, además de una relación es-un, la claridad del código global se reduce.

Con cadenas más profundas, las clases base mixin aumentar en gran medida la probabilidad de un escenario "diamante de la muerte", en el que una subclase termina heredando varias copias de una clase mixin.

Aplicabilidad

Cualquier lenguaje que soporta la herencia múltiple.

Excepciones

Cualquier caso donde la clase mixin proporciona o requiere que los miembros sobrecarga. En este caso, la herencia por lo general implica un IS-implementadas-en-los términos de relación, y un agregado no será suficiente.

Excepciones

El resultado de esta transformación puede conducir a los miembros públicos (por ejemplo MyThreadSafeDataStructure puede tener un acceso público Mutex como un componente).

Otros consejos

Hay algunos principios bien entendidos que podrían constituir un buen punto de partida:

También es una buena idea para estudiar los patrones de diseño existentes para encontrar principios detrás de ellos, el más importante es (generalmente) prefieren composición sobre la herencia.

Creo que la respuesta corta es que los "buenos" diseños OO son robustos bajo el cambio, con la rotura de código menos para cambiar cualquier requisito. Si se tiene en cuenta todas las reglas habituales, todos ellos tienden a la misma conclusión.

La dificultad es que no se puede evaluar la "bondad" del diseño sin marco; es, creo, un teorema que para cualquier modularización, existe un cambio en los requisitos que maximicen la rotura, haciendo que cada clase para ser tocado en cada método.

Si desea ser rigurosos al respecto, se puede desarrollar una colección de "cambio" y los casos ellos para el fin de probabilidad, de manera que se minimiza la rotura de los más altos cambios de probabilidad.

En la mayoría de los casos, sin embargo, alguna intuición bien desarrollada ayuda mucho: específico del dispositivo o plataforma específica cosas tienden a cambiar, reglas de negocio y procesos de negocio tienden a cambiar, mientras que las implementaciones de, por ejemplo, la aritmética, cambian muy raramente . (No, como se puede imaginar, no. Consideremos, por ejemplo, un sistema de negocio que pueden o no ser capaz de hacer uso de la aritmética BCD-plataforma compatible.)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top