ventajas sintaxis programar programacion poo orientada objetos introduccion historia fundamentos estructurada desventajas cómo java c++ oop inheritance

programar - sintaxis de java pdf



¿Desventaja de OOP? (18)

Solo porque tengas un martillo, no significa que todo sea un clavo.

He descubierto que muchas personas a menudo confunden cuándo aplicar composition vs. inheritance cuando usan OOP como un estilo de programación. El ejemplo que citas de la pregunta de la entrevista parece ser un caso de este tipo exacto de confusión.

Una cosa que aprendí con experiencia es que, si bien la herencia es un buen paradigma para las relaciones de expresión "IS-A" entre entidades en un diseño, a menudo es mejor favorecer la composición que la herencia .

Pero examinemos el quid de la cuestión de los entrevistadores: ¿ cuándo es OOP una elección de paradigma? .

OOP funciona mejor con proyectos a gran escala, de múltiples desarrolladores y de múltiples módulos. Para el " desarrollo en lo pequeño ", como la creación de scripts o el procesamiento transformativo, puede requerir una gran cantidad de gastos generales sin necesariamente agregar valor. Pero incluso en estos casos, a menos que esté escribiendo un código descartable, yo diría que la solución grande suele evolucionar a partir de las más pequeñas, por lo que establecer la estructura y la separación de las preocupaciones desde el principio puede ahorrarle pena más adelante.

En última instancia, la programación OOP también requiere un cierto nivel de rigor y planificación de diseño, así como una comprensión de los principios básicos de la orientación a objetos . Si no está dispuesto a tomarse el tiempo para estudiar y comprender esos principios ... bueno, quizás la programación OOP no sea para usted.

Más allá de eso, ciertos tipos de problemas también se prestan a estilos de programación alternativos. Por ejemplo, el procesamiento transformativo es bastante ammendable para el estilo funcional de programación , en el que los resultados se calculan y pasan a sucesivos pasos de transformación para producir un resultado final. Los problemas donde tiene que buscar o consultar un dominio para cierta información coincidente son susceptibles de consultar los idiomas (como SQL) en los que describe su intención de forma declarativa en lugar de imperativa.

Ser capaz de reconocer qué tipo de problema está resolviendo ayuda mucho a elegir qué tipo de lenguaje o herramienta usar. Las herramientas adecuadas pueden hacer que un trabajo sea mucho más fácil ... el incorrecto puede hacerlo más difícil o imposible.

Por lo general, no quiero saber los detalles de los inconvenientes de los OOP, pero me pareció un poco extraño cuando tuve una discusión en una entrevista a la que asistí recientemente. La pregunta que me enviaron fue para decirme una desventaja de la programación orientada a objetos (OOP). En ese momento, sentí que OOP era el nivel de programación más maduro después de los modelos de procedimiento y funcionales. Entonces le respondí que no veo ningún negativo en absoluto.

Pero el entrevistador dijo que hay pocas, y le pedí que enumerara una si no le importa. Dio un ejemplo de que no digerir bien. Dijo que un patrón de OOP no implementa estrictamente las reglas de herencia y citó el ejemplo de satélite / cohete donde las partes del cuerpo se desintegrarán periódicamente para eliminar el peso durante el lanzamiento del cohete y dijo que la herencia no es compatible con esto.

Su tipo de ejemplo me pareció muy extraño, la razón es la aplicación de la herencia a este ejemplo.

Entiendo que el ejemplo que dio apenas tuvo sentido, pero tuve esta duda:

¿Podemos desconectar las jerarquías de clase de forma dinámica (estoy seguro de que Java no es posible) en un diseño ideal orientado a objetos?


¿Podemos simplemente decir usar esto en OOP?

RocketShip.BodyPart1 = nada o

RocketShip.BodyPart1.isDetached = ¿falso?

Creo que no es el OOP en sí el culpable, sino la limitación del lenguaje de programación utilizado sobre cómo se implementa.


Acerca de los métodos innecesarios en las clases principales: ¿No son un signo de mala arquitectura? Quiero decir, ¿no deberías aislar en la etapa de planeación las funcionalidades que necesita cada clase y luego tener una cadena de clases derivadas una de la otra?

Por ejemplo, tenemos clase A, B, C y D. La clase A tiene los métodos que las clases B, C y D necesitan. La clase B tiene los métodos que necesita la clase D. Entonces podríamos derivar la clase D de B y B de A. Por otro lado derivaremos C de A porque C no necesita lo que B tiene. Así que básicamente solucionamos el problema de tener cosas innecesarias al agregar una clase adicional en la jerarquía. Por supuesto, si algo como esto no se tomó en la etapa de planificación y se usó la clase B como clase base, sería más difícil dividir la clase B en dos clases, pero con un poco de esfuerzo extra se solucionó el problema del equipaje innecesario.


Aunque estoy de acuerdo con la conclusión del entrevistador (OOP es defectuoso), su lógica parece ser absurda. Parece que está criticando algo que no entiende, porque ningún programador competente de OO haría que un cohete herede de sus propulsores.

Sin embargo, las personas han hecho buenas críticas contra OOP. Por ejemplo, Ejecución en el Reino de los Nombres de Steve Yegge.


Aunque no entiendo completamente el ejemplo dado, ya que me suena a composición, le daré una desventaja de OOP

OO es difícil de probar

  • No hay acceso directo a las variables / atributos de clase de lectura / escritura; puede ser necesario introducir getters y seeters que rompan la encapsulación.

  • La herencia puede cambiar el comportamiento de un método en una subclase

  • Los objetos tienen estado. Puede ser difícil generar estos estados ya que dependemos de la interfaz pública.

  • Las clases con cohesión Loh pueden ser difíciles de probar ya que esto podría significar que la clase hace más de lo que se especifica.


Creo que su principal desventaja proviene directamente de su poder. Una de las cosas más comunes que se hacen en OOP es reemplazar las clases principales con clases derivadas en algunos lugares, para especializar el comportamiento del código. Bueno, si no se hace con cuidado, es fácil invalidar algunas de las suposiciones hechas en el código de la persona que llama; y eso podría ser muy difícil de detectar mientras revisas el código, porque los tipos que estás viendo no son los que realmente se están usando.

En resumen: el polimorfismo puede hacerse no explícito y, por lo tanto, es fácil pasar por alto comportamientos extraños en las clases derivadas.


Echa un vistazo a estos artículos . Hay varias explicaciones de algunas de las desventajas de OOP, particularmente los peligros de forzar las cosas en jerarquías, como en el ejemplo de su entrevistador.


El clásico es preferir la composición a la herencia. La herencia está ahí para capturar abstracciones a lo largo de una costura que su sistema varía a lo largo.

Si no captas claramente esa abstracción, entonces sí, obtendrás fuerzas extrañas en tus diseños. Pero este es un problema de programación en un mundo donde las abstracciones no son del todo correctas para lo que estás tratando de lograr. No es que nunca serán perfectos.


Estoy seguro de que nunca he oído hablar de un lenguaje estáticamente tipado como Java que es capaz de transformar un objeto en otro sin dejar la referencia de objeto intacta, pero estoy seguro de que puede fingirlo con delegados, etc. Dicho esto, sin algunos fundamentalmente buena idea, probablemente sería un desastre.

No puedo saber cómo formuló la pregunta el entrevistador o cómo respondió, pero uno de los defectos más importantes de OOP no es realmente el propio OOP. Es el mal uso de OOP y malas relaciones "IS-A" que las personas intentan crear. Si la única razón por la que se te ocurre crear una jerarquía de herencia es la reutilización del código, es una mala razón. Se puede argumentar que AOP es un mejor enfoque para eso. (antes de encender o bajar el voto, tenga en cuenta que dije "puede ser")

OOP trata sobre la interfaz y el tipo, no sobre la implementación. Saber que un objeto puede devolver una lista de candidatos es todo lo que necesito saber. Si esto proviene de un RDBMS, DB orientado a columna, servicio web o incluso una hoja de cálculo no tiene importancia. Sé que puedo pasar ese objeto como parámetro a otros métodos y pueden llamar a "FetchJobCandidates" y saber que obtendrán candidatos para el puesto. Hay trampas en el camino, pero sobre todo si piensas en clases basadas en lo que exponen al resto del mundo en lugar de lo que hacen internamente, estás en un IMO mejor.


La mayor desventaja que se me ocurre con OOP es la falta de soporte para funciones de orden superior. Aunque puede pasar un objeto que contiene un método, esto es detallado e ineficiente. Sería mucho mejor poder pasar una función directamente a otra función.



No estoy entendiendo completamente su ejemplo.

Sin embargo, es importante comprender que la POO es muy efectiva para las cosas que se pueden modelar naturalmente con ella, y es muy ineficaz para otras cosas (por ejemplo, cuestiones o preocupaciones transversales). Esa es una desventaja de OOP. Otra es que a menudo incurre en algún costo de tiempo de ejecución debido al envío dinámico.

Además, es muy fácil abusar de OOP para hacer abstracciones no sensibles. Tener un cohete heredado de un cuerpo es un ejemplo. Mi experiencia es que los desarrolladores principiantes no confían y no usan la herencia, o que están demasiado ansiosos y lo usan incorrectamente, cuando otros comportamientos (como la agregación) son más apropiados. Con el tiempo, la experiencia y la comprensión del mecanismo mejoran.

No estoy seguro de lo que quiso decir con "El patrón OOP no implementa estrictamente las reglas de herencia", ya que OOP no es un patrón. Un posible problema es que uno puede escribir un subtipo que puede violar el principio de sustitución de Liskov, de modo que un método de anulación no se comporta "al menos" como el método reemplazado. No hay forma de verificar esto automáticamente, por lo que es posible escribir código que viole los principios de OOP.

En cuanto a su pregunta final "¿Podemos desconectar las jerarquías de clase en un Diseño orientado a objetos ideal?", No estoy seguro de lo que quiere decir aquí. Si pregunta por cambiar la jerarquía en el tiempo de ejecución y hacer que la relación de subtipado ya no exista desde algún punto de la ejecución, entonces sí. Es posible con ciertos lenguajes como Smalltalk. Algunos argumentarían que esto es "Más POO". En smalltalk, los ''métodos'' soportados por un tipo se determinan en el punto de llamada de método en función de la jerarquía actual y el contenido actual de cada clase. Aunque me encanta Smalltalk, esta es una característica que no me entusiasma, ya que prefiero la verificación en tiempo de compilación con menos sorpresas en el tiempo de ejecución.


Otros ya lo han cubierto, pero si lo piensas, no todo es un objeto. En informática, nada es realmente un objeto. Simplemente abstraemos el concepto de un objeto.

Por ejemplo, las rocas están compuestas de materia. Podríamos pensar en las rocas como objetos en términos informáticos (términos OOP), pero eso no ayuda a la programación en torno al concepto de una roca.

Si piensas en los conceptos principales de la programación orientada a objetos; encapsulación, polimorfismo, clases, herencia ... hay problemas con todos esos conceptos básicos de POO.


Puedo ver el punto en el que estaba conduciendo. Creo que la discusión se centró básicamente en la desventaja de la herencia: si no tienes cuidado, o si heredas demasiadas veces para seguir ampliando la funcionalidad, puedes terminar con un caos de una clase con muchas funciones redundantes y falta de recursos. de cohesión

Su analogía funciona si se tiene en cuenta que, una vez que el cohete ha quemado el combustible en un segmento, el segmento se vuelve redundante y, por lo tanto, de peso muerto. El cohete puede descartar el segmento, pero no creo que sea posible excluir secciones de una clase que no quieras heredar (aunque corrígeme si me equivoco, porque me parece útil).


Su ejemplo no tiene sentido. Un cohete no hereda de un cuerpo. "Tiene" un cuerpo. Eso es contención. Entonces, en cierto punto, "borrarías" la parte unida al cohete cuando se descartó.


Una forma de modelar un objeto que cambia su subclase es usar el patrón de estado . Usando su pregunta de la entrevista y algo de ayuda de Wikipedia , aquí hay un código de Java que muestra cómo puede modelar las transiciones de estado a medida que el cohete atraviesa sus diversas etapas. No he mostrado las etapas del Módulo de Comando, pero siguen un patrón similar a través del descenso lunar, el ascenso lunar, el encuentro en la órbita lunar y el regreso a la Tierra. Probablemente puedas encontrar comportamientos mucho más interesantes para agregar a la interfaz ISpaceShipState.

public class SpaceShip { private ISpaceShipState m_state = new SaturnFiveState(); public void setState(ISpaceShipState state) { m_state = state; } public void jettison() { m_state = m_state.transition(); } public int getStageNumber() { return m_stage.getStageNumber(); } public int getNumberOfRocketMotors() { return m_stage.getNumberOfRocketMotors(); } public String getRocketMotorTypeName() { return m_stage.getRocketMotorTypeName(); } } interface ISpaceShipState { public ISpaceShipState transition(); public int getStageNumber(); public int getNumberOfRocketMotors(); public String getRocketMotorTypeName(); } public class SaturnFiveState implements ISpaceShipState { public ISpaceShipState transition() { return new SaturnFiveSecondStageState(); } public int getStageNumber() { return 1; } public int getNumberOfRocketMotors() { return 5; } public String getRocketMotorTypeName() { return "F-1"; } } public class SaturnFiveSecondStageState implements ISpaceShipState { public ISpaceShipState transition() { return new SaturnFiveThirdStageState(); } public int getStageNumber() { return 2; } public int getNumberOfRocketMotors() { return 5; } public String getRocketMotorTypeName() { return "J-2"; } } public class SaturnFiveThirdStageState implements ISpaceShipState { public ISpaceShipState transition() { return new SaturnFiveCommandModuleState(); } public int getStageNumber() { return 3; } public int getNumberOfRocketMotors() { return 1; } public String getRocketMotorTypeName() { return "J-2"; } }

¿Podemos desconectar las jerarquías de clase de forma dinámica (estoy seguro de que Java no es posible) en un Diseño orientado a objetos ideal?

Es posible simular el tipado dinámico en Java utilizando la reflexión, aunque el código es muy torpe en comparación con lo mismo en un lenguaje de tipado dinámico.


tal vez algo así como el problema círculo-elipse


¿Podría el ejemplo del cohete haber aludido al hecho de que en muchos lenguajes orientados a objetos, el tipo de un objeto es inmutable? Es decir, si tengo un objeto Student y la persona que representa termina sus estudios y se convierte en empleada, no puedo convertir el objeto Student en un objeto Employee . Tengo que crear uno nuevo, perder identidad de objeto en el proceso y, en consecuencia, actualizar todas las referencias que apuntan al antiguo alumno.

Por supuesto, tal característica interferiría con el tipado estático (el tipo invariante de que el tipo de un objeto es un subtipo del tipo estático de cualquier referencia que lo señale). Pero en algunos contextos, la flexibilidad puede valer la pena.