¿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í?
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í?
Respuestas:
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í.
fuente
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
fuente
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
fuente
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.
fuente
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.
fuente
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.
fuente
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.
fuente
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)
fuente
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.
fuente
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.
fuente
Creo que SÍ , 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.
fuente
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.
fuente
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.
fuente
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
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
fuente