¿La programación orientada a objetos es una solución a la complejidad? [cerrado]

18

¿Crees que la programación orientada a objetos es una solución a la complejidad? ¿Por qué? Este tema puede ser un poco controvertido, pero mis intenciones de saber la respuesta de ¿Por qué de los expertos aquí?

Tony
fuente
15
¿Asignación de ensayo difícil? ; p
glenatron
1
La pregunta no tiene sentido ya que no hay solución a la complejidad. Existen estrategias para lidiar con la complejidad (en particular, la complejidad intrínseca e irreducible). Pero soluciones, no, no las hay. Es como buscar una solución para llevar una distancia física de una milla a cero.
luis.espinal
1
La programación orientada a objetos es una herramienta para gestionar la complejidad.
Robert Harvey
Pregunta: ¿Puedes programar problemas complejos con OOP? - Respuesta: claro. Si usa OOP, será complejo.
Mouviciel
"puede ser controvertido" lo convierte en un elemento de discusión, en lugar de una cuestión técnica ...
jwenting

Respuestas:

24

No hay solución a la complejidad.

En "The Mythical Man-Month", Fred Brooks analiza la diferencia entre la complejidad accidental y esencial en la programación. La complejidad accidental es causada por nuestras herramientas y métodos, como tener que escribir y probar código adicional en un idioma porque no podemos expresar nuestras ideas directamente, y cosas así. Los nuevos métodos y técnicas pueden reducir la complejidad accidental. Puedo escribir programas más rápido y mejor que hace veinticinco años, porque tengo mejores idiomas y herramientas.

La complejidad esencial proviene del hecho de que lo que intentamos hacer con la programación es intrínsecamente complicado y que existe una complejidad irreducible. "Esencial", en este contexto, significa "relacionado con la esencia de la cosa" en lugar de "muy necesario".

Por lo tanto, afirmó que no habría una bala de plata, que el software de escritura continuaría siendo difícil.

Le recomiendo que lea su libro: específicamente, le recomiendo la edición del Aniversario de Plata, con un ensayo adicional "No Silver Bullet". En eso, revisa las soluciones propuestas a la complejidad y considera su impacto. (Lo que encuentra más efectivo es el software retráctil: escriba algo complejo una vez y venda miles o millones de copias).

Ahora, la programación orientada a objetos ayuda, cuando se hace correctamente, al crear abstracciones y ocultar la complejidad. Un objeto de una clase tiene un determinado comportamiento definido del que podemos razonar, sin importarnos la complejidad de la implementación. Las clases escritas correctamente tienen un bajo acoplamiento entre ellas, y dividir y conquistar es una excelente manera de lidiar con la complejidad si puedes salirte con la tuya. También tienen una alta cohesión, ya que son un conjunto de funciones y datos que se relacionan muy estrechamente entre sí.

David Thornley
fuente
3
La edición del 20 aniversario también contiene "'No Silver Bullet' Refired", en el que se refiere a OOP como una "bala de bronce", y dice que es: "... un concepto muy prometedor".
Jerry Coffin
18

Espero que obtenga algunas mejores respuestas en breve, pero aquí hay una simple:

OOP ayuda * con la complejidad al modelar el software de una manera más cercana a la forma en que modelamos todo lo demás en el mundo. En general, es más fácil imaginar un objeto de bola que interactúa con un objeto de pared que imaginar una serie de rutinas y estructuras de datos para hacer lo mismo, ya que está más cerca de cómo interactuamos con el mundo real.

* Porque nada puede 'resolver' la complejidad

Fishtoaster
fuente
44
Así es como funciona la OOP en teoría. En la práctica, los ejemplos de OOP, como perros que ladran, patos que vuelan y camiones que son vehículos, comienzan a descomponerse cuando se escribe un software real, porque los objetos reales del programa siempre son más abstractos que esto.
Robert Harvey, el
8
@Robert: No estoy afirmando que realmente modeles objetos del mundo real en OOP muy a menudo, solo que es más fácil pensar en la mayoría de la programación en términos de objeto (incluso si se trata de objetos de proxy de socket y de fachada de modelo), porque así es como Vemos el mundo de los perros y los patos en la vida real.
Fishtoaster el
2
No, este es un error común sobre la POO. Se supone que no debe modelar su programa basado en objetos de la vida real. No existe un BufferReader en la vida real.
hasen
1
@ Hasen j: Sí, eso es lo que dije cuando aclaré en mi comentario.
Fishtoaster el
Hay una muy buena discusión en programmers.stackexchange.com/questions/16189/…
Bill Michell
15

Creo que la definición actual de OOP no es una buena solución para gestionar la complejidad.

Si vuelves a sus raíces, creo que Alan Kay estuvo muy influenciado por el "lisp".

Debido a que Lisp no ha sido corrompido por la adopción generalizada, probablemente logró conservar sus valores centrales. Así que creo que mirar cómo aborda Lisp este problema de complejidad podría darnos una idea, y podemos usarlo como una base para juzgar qué tan útil es la POO para lidiar con la complejidad.

Si observa el final de la "Lección 3a: Ejemplo de Henderson Escher" del SICP , Hal Abelson propone que la complejidad se gestiona no dividiendo la tarea en subtareas más pequeñas, sino creando capas de abstracción. En el nivel más alto, expresa la solución al problema complicado en términos de la solución al nivel más bajo de abstracción.

Creo que OOP fue originalmente pensado como un mecanismo para crear estas capas de abstracciones.

Desafortunadamente hoy en día, OOP se usa (ab) para escribir estructuras / código de espagueti.

Voy a inventar un ejemplo: un juego multijugador FPS.

En el nivel más alto, el juego funciona al tener un grupo de jugadores corriendo alrededor de un mapa y disparándose unos a otros usando armas.

En el siguiente nivel inferior, tenemos que hablar sobre mapas, armas y jugadores. Tal vez podamos hablar de ellos como objetos físicos que interactúan dentro del mundo del juego.

En el siguiente nivel inferior, podemos hablar sobre cómo los objetos interactúan físicamente (movimiento, colisiones, etc.).

Y así sucesivamente y así sucesivamente.

Lo que esto significa, (y estoy citando de SICP ...), es que en cada capa, no solo resolvemos un problema específico en particular, sino una clase de problemas que caen en la vecindad del problema que ' estás tratando de resolverlo. Entonces, si hay un pequeño cambio en la descripción del problema, es probable que solo requiera un pequeño cambio en la solución.

Entonces, la forma más inteligente de usar OOP es crear capas de abstracciones, en cada nivel de abstracción, resuelve el problema en cuestión usando los "objetos" del nivel que está directamente debajo.

Aquí está lo que estaba citando de la conferencia: http://www.youtube.com/watch?v=CYtrfncMqHQ

Hasen
fuente
55
Al igual que muchas herramientas, la OOP es altamente efectiva cuando se usa de manera inteligente y cuidadosa, y no es tan efectiva cuando se abusa de ella.
Robert Harvey, el
1
+1 para "capas de abstracción" - muy buena explicación. OOP también le permite limitar el alcance de lo que ve a un objeto a la vez, lo que facilita a las personas visualizar el diseño y las interacciones.
Michael K
1
Me parece la idea de que un concepto teórico no está "corrompido por la adopción generalizada" haría mejor en el manejo de la complejidad en proyectos del mundo real ... extraño.
Michael Borgwardt
@MichaelBorgwardt, la adopción convencional corrompe una idea útil porque muchas personas en la corriente principal no entienden de qué se trata la idea, por lo que cuando intentas buscar qué es POO, ves varias ideas erróneas de varias personas. LISP todavía se usa, pero solo por una minoría, por lo que es menos probable que las ideas originales sufrieran la corrupción causada por los jefes de pelo puntiagudo que no tienen idea de qué se trata.
hasen
@hasen j: OTOH es más probable que las "ideas originales" que nunca vieron la adopción convencional fueran cosas de la torre de marfil que no funcionan en el mundo real. La falta de popularidad ciertamente no es un punto claro a favor de nada.
Michael Borgwardt
10

Como de costumbre, no estoy de acuerdo con todos. Lejos de brindarle herramientas para administrar la complejidad, OOP crea una gran cantidad de complejidad porque es un paradigma inadecuado y matemáticamente falso. Confunde a los programadores sin fin, para tratar de modelar cosas con OOP que no se pueden modelar con OOP.

En mi opinión, el trabajo fundamental aquí es la construcción de software orientado a objetos de Meyer. Detalla un conjunto de requisitos, incluido uno que considero crucial: el Principio Abierto-Cerrado. Esto dice que una cosa debe estar abierta para la extensión pero cerrada para su uso, al mismo tiempo.

Meyer procede a derivar la Orientación del objeto a partir de estos requisitos, tal como se plasma en Eiffel. La encapsulación proporciona cierre, apertura de herencia, y la "cosa" mencionada es la clase.

Considero que este trabajo es una buena ciencia porque Meyer se demostró que estaba equivocado, y es posible, debido a la calidad de su trabajo, señalar el error y corregirlo.

El error está haciendo que la clase, o tipo, sea la unidad de modularidad. Eso está mal, y probablemente así sea. Incluso Meyer reconoció el problema (llamado problema de covarianza), que OOP no puede manejar relaciones de aridad superiores a uno (es decir, OOP funciona bien para propiedades pero falla en relaciones binarias). ¡En Eiffel, este problema resultó en un mal funcionamiento en el sistema de tipos!

La solución es bastante clara. La unidad de modularidad debe ser más grande que un solo tipo. Debe constar de varios tipos y los métodos que los relacionan.

No es sorprendente que este modelo de abstracción esté respaldado por la teoría matemática de la abstracción, a saber, la teoría de categorías: los tipos son objetos de una categoría y los métodos (funciones) son flechas.

Con este modelo, las representaciones de varios tipos son conocidas por un conjunto de funciones. La representación está oculta al público, por lo que esto es encapsulación, pero usamos módulos, no clases.

El metalenguaje estándar (SML) y Ocaml se basan directamente en este modelo. Ocaml también tiene clases y OOP: no es inútil porque OOP le brinda despacho de propiedades, también conocido como enlace dinámico. Sin embargo, la mayoría de los problemas del mundo real involucran relaciones y no sorprende que las clases no se usen mucho en Ocaml.

No es sorprendente que la herencia apenas se utilice en la biblioteca de plantillas estándar de C ++.

El hecho simple es que OOP no le brinda las herramientas adecuadas para manejar la complejidad, ni siquiera le brinda las herramientas para manejar problemas realmente simples, sino que ha confundido y confundido a dos generaciones de programadores. Lejos de ayudar, OOP es lo más malo y malo que le ha sucedido a la programación desde que C, Fortran y Cobol comenzaron a cansarse.

Yttrill
fuente
tentado a crear otra cuenta para votarte un poco más;)
Marco Mariani
Usted hace una serie de afirmaciones. Quizás pueda proporcionar argumentos que respalden sus afirmaciones o referencias a argumentos. De esta manera, que no es compatible con sus diversas tesis (en el sentido de que dice "hay cosas mal con OO; esto es lo que tiene que hacer"): lucacardelli.name/Papers/BadPropertiesOfOO.pdf
Frank Shearar
3
Decir "foo es lo más malo y malo ..." es activamente corrosivo para cualquier argumento que puedas intentar hacer, por cierto.
Frank Shearar
6

La programación orientada a objetos tiene raíces que se remontan a la década de 1960. A medida que el hardware y el software se volvieron cada vez más complejos, la capacidad de administración a menudo se convirtió en una preocupación. Los investigadores estudiaron formas de mantener la calidad del software y desarrollaron programación orientada a objetos en parte para abordar problemas comunes al enfatizar fuertemente las unidades discretas y reutilizables de lógica de programación.

Por lo tanto, un programa orientado a objetos puede verse como una colección de objetos que interactúan, en oposición al modelo convencional, en el que un programa se ve como una lista de tareas (subrutinas) para realizar. En OOP, cada objeto es capaz de recibir mensajes, procesar datos y enviar mensajes a otros objetos. Cada objeto puede ser visto como una 'máquina' independiente con un rol o responsabilidad distintos. Las acciones (o "métodos") en estos objetos están estrechamente asociadas con el objeto mismo.

http://en.wikipedia.org/wiki/Object-oriented_programming

Esta separación de inquietudes, junto con otras características de la Orientación de objetos, como el polimorfismo, la herencia, el paso de mensajes, el desacoplamiento y la encapsulación, proporcionan un marco lógico y conceptual por el cual la complejidad de los grandes programas se puede gestionar de una manera altamente efectiva.

Robert Harvey
fuente
2

Hay muchos tipos de complejidad para el desarrollo de software. A nivel de programación, OOP busca abordar la complejidad mediante el uso de objetos y clases para modelar el dominio del problema. Un conocido gurú dijo que la resolución de problemas solo representa el problema, de modo que la solución es la representación misma. Por lo tanto, mediante la abstracción usando clases, la encapsulación usando modificadores de acceso y métodos, la herencia para especificar la relación y la reutilización, la composición para establecer la relación y la colaboración entre clases, el polimorfismo como un medio para simplificar la determinación de diferentes comportamientos en objetos similares, la complejidad puede ser manejada.

También hay otras formas de administrar la complejidad del software, por ejemplo, programación lógica (Prolog) y funcional (Haskell).

En un nivel superior a la programación, necesitamos patrones y principios de diseño para guiar la POO. Por lo tanto, OOP está gestionando la complejidad en un nivel bajo (codificación), mientras que estas metodologías, como los patrones y principios de diseño, guían el diseño de la solución a un nivel superior (sistema y aplicación) y hacen que el desarrollo de software y el manejo de las complejidades sean más manejables.

Para responder a su pregunta, sí, OOP es solo una solución para manejar la complejidad entre muchas otras soluciones. Es una solución a bajo nivel. Necesitamos Patrones y Principios de Diseño para guiar a OOP en un nivel superior.

StartClass0830
fuente
3
Tendría mucho cuidado al decir que "necesitamos" patrones de diseño. Son artefactos naturales de un buen diseño OO: no deben usarse para conducirlo. "Oh, no tenemos un patrón para esto, así que no podemos hacerlo". Son un medio de comunicar el diseño.
Michael K
2

La programación orientada a objetos gestiona la complejidad esencial y opcional, pero tampoco reduce.

Prefiero la definición proporcionada por Eric Steven Raymond en The Art of Unix Programming , porque delinea entre la complejidad esencial, opcional y accidental. http://www.faqs.org/docs/artu/ch13s01.html#id2964646

OOP no hace nada por la complejidad esencial u opcional, son una función de los requisitos del programa. Puede tener un efecto en la complejidad accidental, ya que puede crear un diseño más elegante a veces con OOP. A veces, sin embargo, el diseño es peor cuando se usa OOP.

Thomas Langston
fuente
2

Los problemas complejos no pueden simplificarse a través de la tecnología, solo pueden gestionarse a través de la tecnología.

OOP es una tecnología, un concepto y una forma de abordar un problema.

OOP le brinda las herramientas para aplicar un diseño que puede facilitar la administración de la complejidad, pero también puede tener un diseño incorrecto que aumenta su complejidad. En otras palabras, si no se usa correctamente, puede tener complejidad inducida por la tecnología en sus problemas.

Tenga en cuenta que hay muchos otros aspectos que determinarán el éxito de su proyecto (es decir, estilo de gestión del proyecto, definición del problema, gestión del cambio, etc.). La tecnología que usa solo es relevante en cuanto le ayudará a manejar el problema.

Al final, la programación orientada a objetos no puede ser una solución a la complejidad; es solo una herramienta para administrarlo. (si se usa correctamente)

Remus
fuente
+1 Al final, la programación orientada a objetos no puede ser una solución a la complejidad; es solo una herramienta para administrarlo. (si se usa correctamente)
Karthik Sreenivasan
2

La orientación a objetos (como se usa convencionalmente) es una herramienta útil en muchas circunstancias, pero no es una solución suficiente para la complejidad.

En particular, a menudo agrega mucha " complejidad incidental ". Algunos ejemplos son la complejidad que rodea la herencia de implementación, la necesidad de proporcionar una gran cantidad de "funcionalidades estándar" como equals () y hashCode (), etc. Una buena presentación de Stuart Halloway sobre este tema: "La simplicidad no es fácil "

Los objetos en la mayoría de los lenguajes también tienden a encapsular una gran cantidad de estado mutable , que en un mundo concurrente cada vez más parece una mala decisión de diseño. Una vez más, un video interesante de Rich Hickey analiza la distinción entre identidad de objeto y estado, y cómo podría ser un error combinar los dos.

mikera
fuente
1

La programación orientada a objetos es una forma de representar un problema, nada más y nada menos. Es, en sí mismo, no menos complejo que cualquier otro paradigma de programación. Un sistema OOP bien diseñado gestiona y reduce la complejidad, pero también es muy fácil diseñar un sistema que sea mucho más complejo de lo necesario y se interponga en el camino de todo.

Como se suele decir de C ++, OOP te da suficiente cuerda para ahorcarte.

Dominique McDonnell
fuente
Pero eso es cierto para cualquier lenguaje o paradigma poderoso. ¿Quieres una cuerda que sea demasiado corta para colgarte? ¡Nunca subirías una montaña con él!
Michael K
@Michael, algunos más que otros. Pero esencialmente sí. No hay balas de plata, siempre hay retrocesos a cualquier lenguaje o paradigma que esté utilizando.
Dominique McDonnell el
1

Creo que , solo porque le permite dividir la complejidad en pequeños "bloques de construcción" autocontenidos que ocultan detalles, y luego usarlos para crear la funcionalidad que necesita, paso a paso, capa por capa.

Divide y conquistaras.

Miguel Veloso
fuente
1

OOP es un intento de solución.

La mejor manera de gestionar la complejidad es crear abstracciones. Si puedo convertir mis datos en colecciones útiles, con funciones reconocibles que operan en esas colecciones, puedo comenzar a pensar en las colecciones como "cosas" discretas. Esa es la base de las clases y los métodos. En ese sentido, la OOP diseñada adecuadamente puede ayudar a gestionar la complejidad.

En algún momento, alguien decidió que podíamos usar OOP para ayudar a resolver el problema de la reutilización de código. Quiero decir, ¿por qué reinventar la rueda? Si alguien más ha hecho gran parte del trabajo para resolver este problema, aproveche lo que ha hecho, agregue los ajustes que su proyecto particular requiere y ¡listo! Ha creado una aplicación potente y sofisticada con relativamente poco trabajo de su parte. Los programadores OO pueden ser programadores muy productivos.

El resultado final es que los programadores modernos de OO terminan siendo "aprendices de brujo", donde unen un montón de bibliotecas grandes y difíciles de manejar con unas pocas líneas de "pegamento" y obtienen algo que funciona. Sorta Un poco La mayor parte del tiempo ¿Hay posibles efectos secundarios al usar esta biblioteca con esa? Tal vez. Pero, ¿quién tiene tiempo para profundizar en el código contenido en esas bibliotecas? Especialmente cuando las bibliotecas están evolucionando. El resultado es que terminamos con aplicaciones hinchadas, donde un programador necesitaba un puñado de clases y métodos de esa biblioteca, pero la aplicación tiene que soportar el peso de TODAS las OTRAS cosas que no necesitaban.

El resultado final es que terminas con mucha más complejidad de la que necesitas.

Otro mecanismo para lidiar con la complejidad que desea separar la funcionalidad. Desea todas sus funciones de acceso a datos en un solo lugar. Desea toda la funcionalidad de su interfaz de usuario en un solo lugar. Desea todos sus controladores en un solo lugar. Entonces crea diferentes clases que administran diferentes partes de la funcionalidad. Hasta aquí todo bien. Y esto escala, hasta cierto punto; sus desarrolladores expertos en acceso a datos pueden escribir esas clases, su personal de interfaz de usuario puede escribir las clases de interfaz de usuario, etc. Todo está bien.

Hasta que tenga que mantener algo escrito por otra persona.

Sí, es bueno saber que todas las funciones de acceso a datos se encuentran aquí. ¿Pero qué los llama?

Este método está llamando a ese método en esa clase. Pero cuando miro la definición de clase, no hay ningún método con ese nombre. Oh, eso se hereda de otra cosa una o dos capas en la cadena de herencia. Espera un minuto; esa clase implementó una interfaz? ¿Cuántas clases diferentes implementan esa interfaz? ¿Y estamos usando un sistema complicado de tiempo de ejecución (te estoy mirando, Spring) para "conectar" instancias de clases en tiempo de ejecución? ¿Dónde se puede usar CUALQUIER clase que implemente esa interfaz?

Terminas con muchos métodos pequeños y discretos que hacen cosas precisas. Pero este lo llama, en otra clase. Lo cual llama a ese, en otra clase más. Lo cual llama a ese, en otra clase más. Que llama a ese, en una clase adicional. Que devuelve un resultado de un tipo particular. En el que tienes que llamar a un método para hacer una determinada cosa. Que devuelve un resultado de otro tipo. Etc.

Hay un término para esto: código de espagueti.

Terminas con un sistema muy complejo necesario solo para componer el código. Por lo tanto, IDEs como Visual Studio, Eclipse y NetBeans. Todos los cuales tienen una curva de aprendizaje significativa. De hecho, muchos de ellos pueden encapsular / agregar múltiples herramientas, desarrolladas por diferentes grupos, cada uno de los cuales tiene sus propias curvas de aprendizaje.

Esto es gestionar la complejidad?

El código de depuración es el doble de difícil que escribirlo. Buena suerte depurando algunas de estas cosas. Especialmente si está usando múltiples bibliotecas, "conectadas entre sí" en tiempo de ejecución usando algún tipo de sistema de inyección de dependencia.

En resumen: OOP proporciona lo que parece una herramienta prometedora para ayudar a gestionar la complejidad. La realidad es que el código resultante tiende a estar horriblemente hinchado (porque no puede extraer solo las piezas que necesita de todas esas bibliotecas vinculadas) y necesita herramientas sofisticadas solo para navegar por el código. Rápidamente se convierte en una pesadilla de mantenimiento.

En mi humilde opinión, es una pérdida neta; agrega más complejidad de la que elimina. Le permite hacer cosas que serían extremadamente difíciles, posiblemente incluso imposibles, sin él. Pero cualquier gran proyecto evoluciona rápidamente en un desastre imposible de mantener.

Si ya sabe cómo funciona y puede recordarlo, puede tener la oportunidad de mantenerlo.

Recuerde aplicar la Ley de Eagleson: cualquier código propio, que no haya visto en seis meses, bien podría ser escrito por otra persona.

Meower68
fuente
0

Hasta cierto grado...

¿Por qué? Porque facilita una modularidad muy lógica. Al menos en comparación con la programación de procedimientos donde es demasiado tentador escribir grandes cantidades de código de espagueti.

Mesas Bobby
fuente
0

La razón por la que la programación orientada a objetos parece ayudarnos a manejar la complejidad es porque nos obliga a escribir código de una manera específica en lugar de una gran variedad de formas. La programación orientada a tareas es mucho más intuitiva, por eso la programación comenzó de esa manera. La orientación a objetos requiere capacitación y práctica para comprender y usar de manera efectiva, pero al restringir la programación en un camino determinado, permite a los capacitados mantener de manera efectiva el código que se escribió.

No es más lógico o del mundo real que cualquier otro método, es solo una forma de enfocar nuestra resolución de problemas a través de lentes similares. Muchas especialidades técnicas utilizan el paradigma de una metodología rígida no intuitiva para manejar la complejidad de sus tareas.

Un tercer método para manejar la complejidad sería la programación funcional, y probablemente habrá otros métodos nuevos también en el futuro.


fuente
1
Comentarios eliminados; intenta mantenerlos civiles.
Fishtoaster
0

Creo que es más una solución para el mantenimiento, porque, como programador, se supone que debes poner los métodos donde tienes los datos, creando así un modelo de objeto de tu aplicación.

sí, también es una solución a la complejidad al proporcionar un modelo para que "vea" su código de forma natural, como objetos que tienen propiedades y posibles acciones

Belun
fuente