Evitar los escollos orientados a objetos, migrar desde C, ¿qué ha funcionado para usted?

12

Llevo bastante tiempo programando en lenguajes de procedimiento, y mi primera reacción a un problema es comenzar a dividirlo en tareas a realizar en lugar de considerar las diferentes entidades (objetos) que existen y sus relaciones.

He tenido un curso universitario en OOP y entiendo los fundamentos de la encapsulación, la abstracción de datos, el polimorfismo, la modularidad y la herencia.

Leí enlace y enlace , y veremos algunos de los libros mencionados en esas respuestas.

Creo que varios de mis proyectos de tamaño mediano a grande se beneficiarán del uso efectivo de la POO, pero como novato me gustaría evitar errores comunes que consumen mucho tiempo.

En función de sus experiencias, ¿cuáles son estos escollos y cuáles son las formas razonables de evitarlos? Si pudiera explicar por qué son trampas, y cómo su sugerencia es efectiva para abordar el problema, se lo agradecería.

Estoy pensando en algo como "¿Es común tener un buen número de métodos de observador y modificador y usar variables privadas o existen técnicas para consolidarlos / reducirlos?"

No me preocupa usar C ++ como un lenguaje OO puro, si hay buenas razones para mezclar métodos. (Con reminiscencias de los motivos para usar GOTO, aunque con moderación).

¡Gracias!

    
pregunta Stephen 21.06.2011 - 04:45

9 respuestas

1

Quería aceptar una respuesta a esta pregunta, pero no podía decidir una respuesta para otorgar la marca de verificación. Como tal, he actualizado a los autores originales y lo he creado como una respuesta resumida. Gracias a todos los que se tomaron unos minutos, descubrí que la información que me brindaron me dio una buena dirección y un poco de seguridad de que no estaba fuera de lugar.

@nightcracker

  

Bueno, el primero es el escollo de exponer demasiada información. El valor predeterminado debe ser privado, no público.   Después de eso vienen demasiados captadores / setters.

Sentí que había observado este problema en acción en el pasado. Sus comentarios también me hicieron recordar que al ocultar las variables subyacentes y su implementación, soy libre de cambiar su implementación sin destruir nada que dependa de ellas.

Dominic Gurto

  

Diseñe la interfaz antes de que empiece a pensar en la implementación.   Gene Bushuyev   El diseño y la implementación de la interfaz a menudo van de la mano en iteraciones consecutivas hasta que la interfaz final se cristaliza.

Pensé que el comentario de Dominic era un gran ideal al que aspirar, pero creo que el comentario de Gene realmente golpea la realidad de la situación. Hasta ahora he visto esto en acción ... y me siento un poco mejor de que no es raro. Creo que a medida que voy madurando como programador me inclinaré hacia diseños más completos, pero en este momento todavía sufro por saltar y obtener un código escrito.

wantTheBest

  

Comencé lento, con aplicaciones de procedimientos de tamaño pequeño / mediano y sin tareas críticas en el trabajo.   en el código de procedimiento original, separe las estructuras de datos del código obsever / modifier

Esto tiene mucho sentido ... Me gustó la idea de mantener las cosas funcionando en el trabajo, pero refactorizar algunas de las cosas no críticas con las clases.

jpm

  

Una cosa que definitivamente no quieres hacer es tener un campo que deba verificarse para que sea consistente en el mutador, y dejarlo público

Por un tiempo he sabido que este es uno de los puntos fuertes de encapsular los datos ... ser capaz de imponer la coherencia y, para ello, las condiciones / rangos / etc.

Eddie loco

  

Alguien que piensa que debería atenerse al paradigma OO y tratar a los demás en el orden de la declaración de goto en niveles de inmoralidad, realmente se está perdiendo al no mirar este paradigma.   La capacidad de metaprogramación de las plantillas también es bastante impresionante.

Originalmente me perdí mucho en la respuesta de Crazy Eddie, creo que porque no había leído algunos de los temas mencionados ... como metaprogramación. Creo que el gran mensaje en la publicación de CE fue que C ++ es una combinación tal de capacidades y estilos que cada uno debería usar en su mejor potencial ... incluido el imperativo si eso es lo que tiene sentido.

Nuevamente, ¡gracias a todos los que respondieron!

    
respondido por el Stephen 26.06.2011 - 02:02
10

Una gran cosa que aprendí es diseñar clases desde afuera. Diseñe la interfaz antes de que empiece a pensar en la implementación. Esto hará que la clase sea mucho más intuitiva para sus usuarios (aquellos que usan la clase) que escribir los algoritmos subyacentes y construir la clase, y escribir nuevas funciones públicas de miembro según sea necesario.

    
respondido por el Dominic Gurto 21.06.2011 - 04:50
9

Bueno, el primero es el escollo de exponer demasiada información. El valor predeterminado debe ser private , no public .

Después de eso viene muchos getters / setters. Digamos que tengo un miembro de datos. ¿Necesito realmente estos datos en otra clase? Ok, haz un getter. ¿Debo realmente, realmente cambiar estos datos durante la vida útil del objeto? Luego haz un setter.

La mayoría de los programadores novatos tienen el valor predeterminado para hacer un getter / setter para cada miembro de datos. Esto desordena las interfaces y a menudo son malas elecciones de diseño.

    
respondido por el orlp 21.06.2011 - 04:48
2

Cuando crucé ese abismo me decidí por el siguiente enfoque:

0) Comencé lento, con aplicaciones de procedimiento de tamaño pequeño / mediano y sin tareas críticas en el trabajo.

1) un simple primer paso de la forma en que escribiría el programa desde cero en el estilo OO, lo más importante para mí en ese momento, y esto es subjetivo, fue determinar todas las clases básicas. Mi objetivo era encapsular todo lo posible en las clases base. Métodos virtuales puros para todo lo posible en las clases base.

2) Luego, el siguiente paso fue crear las derivaciones.

3) el paso final fue: en el código de procedimiento original, separe las estructuras de datos del código obsever / modificador. Luego use la ocultación de datos y asigne todos los datos comunes a las clases base, y en las subclases fueron los datos que no eran comunes en todo el programa. Y el mismo tratamiento para el código de observador / modificador de procedimiento: toda la lógica de "utilizado en todas partes" se incluyó en las clases básicas. Y ver / modificar la lógica que solo actuó en un subconjunto de los datos ingresados en las clases derivadas.

Esto es subjetivo pero es RÁPIDO, si conoce bien el código de procedimiento y las estructuras de datos. Un FALLO en una revisión de código es cuando un poco de datos o lógica no aparece en las clases base pero se usa en todas partes.

    
respondido por el wantTheBest 21.06.2011 - 04:58
2

Eche un vistazo a otros proyectos exitosos que utilizan OOP para obtener una sensación de buen estilo. Recomiendo mirar Qt , un proyecto que siempre busco al tomar mis propias decisiones de diseño.

    
respondido por el rcv 21.06.2011 - 05:04
1

Dependiendo de con quién hable, todos los datos en OOP deben ser privados o protegidos, y solo están disponibles a través de accesores y mutadores. En general, creo que esta es una buena práctica, pero hay ocasiones en las que divergí de esta norma. Por ejemplo, si tiene una clase (en Java, digamos) cuyo único propósito es colocar algunos datos en una unidad lógica, tiene sentido dejar los campos públicos. Si es una cápsula inmutable, simplemente márquelas como finales e inicialícelas en el constructor. Esto reduce la clase (en este caso) a poco más que una estructura (de hecho, al usar C ++, en realidad debería llamarlo estructura. Funciona como una clase, pero la visibilidad predeterminada es pública y su intención es más clara), pero Creo que encontrará que usarlo es mucho más cómodo en estos casos.

Una cosa que definitivamente no quiere hacer es tener un campo en el que se debe verificar la consistencia en el mutador y dejarlo público.

    
respondido por el jpm 21.06.2011 - 04:53
1

El libro de Patrones de Implementación de Kent Beck es una base excelente en cómo usar, no usar mal, los mecanismos orientados a objetos.

    
respondido por el Steven A. Lowe 21.06.2011 - 06:28
1

No me preocupa usar C ++ como un lenguaje OO puro, si hay buenas razones para mezclar métodos. (Con reminiscencias de las razones para usar GOTO, aunque con moderación).

Realmente no pensé que tenía mucho para ofrecer la conversación hasta que vi este bit. Tengo que estar en desacuerdo con el sentimiento. La POO es solo uno de los paradigmas que pueden y deben usarse en C ++. Francamente, en mi opinión, no es una de sus características más fuertes.

Desde un punto de vista OO, creo que C ++ en realidad se queda corto. La idea de tener funciones no virtuales, por ejemplo, es un tilde en contra de esto a este respecto. He tenido discusiones con quienes no están de acuerdo conmigo, pero los miembros no virtuales simplemente no encajan con el paradigma en lo que a mí respecta. El polimorfismo es un componente clave para OO y las clases con funciones no virtuales no son polimórficas en el sentido de OO. Así que como lenguaje OO, creo que C ++ es bastante débil en comparación con lenguajes como Java o Objective-C.

Por otra parte, la programación genérica, C ++ tiene esta muy buena. He oído decir que también hay mejores idiomas para esto, pero la combinación de objetos y funciones genéricas es algo bastante poderoso y expresivo. Además, puede ser muy rápido tanto en tiempo de programación Y tiempo de procesamiento. Realmente creo que C ++ brilla en esta área, aunque hay que admitir que podría ser mejor (por ejemplo, soporte de lenguaje para conceptos). Alguien que piensa que debería atenerse al paradigma OO y tratar a los demás en el orden de la declaración de goto en niveles de inmoralidad realmente se está perdiendo al no mirar este paradigma.

La capacidad de metaprogramación de las plantillas también es bastante impresionante. Echa un vistazo a la biblioteca Boost.Units, por ejemplo. Esta biblioteca proporciona soporte de tipo para cantidades dimensionales. He hecho un uso extensivo de esta biblioteca en la empresa de ingeniería para la que trabajo actualmente. Simplemente proporciona una retroalimentación mucho más inmediata para un aspecto del posible programador, o incluso un error de especificación. Es imposible compilar un programa que use una fórmula en la que ambos lados del operador '=' no sean dimensionalmente equivalentes sin una conversión explícita. Personalmente, no tengo experiencia con ningún otro lenguaje en el que esto sea posible, y ciertamente no con uno que también tenga la potencia y la velocidad de C ++.

La metaprogramación es un paradigma puramente funcional.

Realmente, creo que ya estás entrando en C ++ con algunos conceptos erróneos desafortunados. Los otros paradigmas además de OO no deben ser evitados, deben ser LEVERAGED. Use el paradigma que es natural para el aspecto del problema en el que está trabajando. No fuerce los objetos en lo que esencialmente no es un problema propenso a objetos. En lo que a mí respecta, OO no es ni la mitad de la historia para C ++.

    
respondido por el Crazy Eddie 21.06.2011 - 07:33
0

El mayor escollo es la creencia de que la POO es una bala de plata o el "paradigma perfecto".

    
respondido por el alternative 26.06.2011 - 02:06

Lea otras preguntas en las etiquetas