¿La POO se está volviendo más fácil o más difícil? [cerrado]


36

Cuando los conceptos de Programación Orientada a Objetos se presentaron a los programadores hace años, parece interesante y la programación fue más limpia. OOP era así

Stock stock = new Stock();
stock.addItem(item);
stock.removeItem(item);

Eso fue más fácil de entender con un nombre autodescriptivo.

Pero ahora OOP, con patrones como Objetos de transferencia de datos, Objetos de valor, Repositorio, Inyección de dependencias, etc., se ha vuelto más complejo. Para lograr lo anterior, es posible que deba crear varias clases (por ejemplo, resumen, fábrica, DAO, etc.) e implementar varias interfaces

Nota: no estoy en contra de las mejores prácticas que facilitan la colaboración, las pruebas y la integración


23
Crear una buena arquitectura de software siempre ha sido difícil y lo será (muy probablemente) siempre.
johannes

66
Cambiaría el nombre addItempor addy removeItempara remove. Porque es más fácil de leer. stock.add(item)o stock.remove(item). Y más orientado a OOP.
razpeitia

1
La OOP original no se parecía en nada a lo que has mostrado. OOP no se trata de sintaxis , se trata de un tipo de abstracción popularizada por Smalltalk. Esto no prueba necesariamente que su punto sea incorrecto, ni la premisa es defectuosa; más bien, es aún más cierto de lo que crees.
Konrad Rudolph

1
está comparando manzanas y naranjas, según su lógica, entonces la programación imperativa (es decir, bucles y condición if) es más simple que todas las cosas que tenemos hoy. La programación imperativa son los componentes básicos para las clases / OOP, y las clases / OOP son los componentes básicos para los patrones de diseño. Las cosas se vuelven más complejas a medida que avanzas porque estás resolviendo problemas más complejos.
Mentira Ryan

2
@LieRyan: he visto que los problemas se vuelven complejos solo porque nadie a cargo pudo resolverlos con una simple programación imperativa y los atacó con patrones de diseño además de OOP además de la solución imperativa simple que debería haberse implementado solo.
mouviciel

Respuestas:


35

OOP en sí no ha cambiado mucho desde su inicio. Se han explorado algunos ángulos nuevos, pero los principios básicos siguen siendo los mismos. En todo caso, el conocimiento colectivo reunido a lo largo de los años hace que la vida del programador sea más fácil que difícil. Los patrones de diseño no son un obstáculo; Proporcionan una caja de herramientas de soluciones a problemas estándar, destilada de años y años de experiencia.

Entonces, ¿por qué percibes la POO hoy como más compleja que cuando comenzaste a usarla?

Una razón puede ser que el código al que está expuesto se vuelve más complejo, no porque OOP se haya vuelto más complejo, sino porque ha avanzado en la escala de aprendizaje y puede leer bases de códigos más grandes y complejas.

Otra razón puede ser que, si bien el paradigma de la complejidad no ha cambiado, el tamaño y la complejidad de un proyecto de software promedio pueden muy bien haber cambiado. Con la potencia de procesamiento disponible en los teléfonos celulares de nivel de cliente que hubiera sido el sueño húmedo de un desarrollador en un servidor hace menos de dos décadas, el público en general básicamente esperaba una GUI animada ingeniosa incluso para la aplicación desechable más barata, y las PC de escritorio de nivel de entrada son más potentes que una "supercomputadora" de 1980, es natural que la barra se haya elevado desde los primeros días de Smalltalk y C ++.

Y luego está el hecho de que en las aplicaciones modernas, la concurrencia y el paralelismo son la norma en lugar de la excepción, y las aplicaciones con frecuencia necesitan comunicarse entre diferentes máquinas, generando y analizando todo un zoológico de protocolos. Si bien OOP es excelente como paradigma organizacional, tiene sus limitaciones, al igual que cualquier otro paradigma: por ejemplo, no proporciona mucha abstracción para la concurrencia (la mayoría de las implementaciones son más o menos una idea de último momento o se externalizan a bibliotecas por completo) , y no es el mejor enfoque posible para construir analizadores y transformar datos. La programación moderna con frecuencia se encuentra con las limitaciones del paradigma OOP, y los patrones de diseño solo pueden llevarlo hasta cierto punto. (Personalmente, Considero el hecho de que necesitamos patrones de diseño como una señal de esto: si el paradigma proporcionara esta solución de forma inmediata, sería más expresivo para estos problemas y las soluciones estándar serían obvias. No existe un patrón de diseño para describir la herencia del método, porque es una característica central de OOP; pero hay un patrón de fábrica, porque OOP no proporciona una forma natural obvia de construir objetos de forma polimórfica y transparente).

Debido a esto, los lenguajes OOP más modernos incorporan características de otros paradigmas, lo que los hace más expresivos y más potentes, pero también más complejos. C # es el mejor ejemplo de esto: tiene raíces obvias de OOP, pero características como delegados, eventos, inferencia de tipos, tipos de datos variantes, atributos, funciones anónimas, expresiones lambda, genéricos, etc., se originan a partir de otros paradigmas, especialmente la programación funcional. .


Entonces los patrones de diseño agregaron las complejidades. Significa que los patrones de diseño no son necesariamente OOP sino que se agregan para mejorar OOP
tunmise fasipe

@tunmisefasipe: No del todo. Los patrones de diseño son solo soluciones comprobadas para problemas estándar; no son una "adición" a OOP, sino una consecuencia. La complejidad ya estaba allí; los patrones de diseño solo proporcionan estrategias de libros de cocina para abordarlo.
tdammers

17

No, se está volviendo más sobre diseñado. Y tiene razón: en el chat de SO C ++, con frecuencia bromeamos sobre AbstractSingletonFactoryProxyBeanBridgeAdapterManagers que vemos en el código Java.

Pero un buen código no exhibe esta propiedad. En buen código, todavía puedes decir

std::stack<int> s;
s.push(5);
s.pop();

44
No está claro en su publicación, pero creo que la ingeniería excesiva es evidente tanto en el código Java como en C ++. No es una propiedad de ninguno de los lenguajes en sí, sino de la práctica de los programadores ... Ambos lenguajes permiten escribir un buen código, aunque ninguno (IMO) es particularmente adecuado para ello :) Los marcos en Java apestan, lamentablemente.
Andres F.

12
Hablando de sobre ingeniería, este hilo es obligatorio: discusion.joelonsoftware.com/default.asp?joel.3.219431
Seguro

3
@AndresF. cierto, pero parece que no obtienes tanto en código C ++, mientras que lo haces en Java y .NET: solo mira el patrón de diseño MVVMVMMD msdn.microsoft.com/en-us/magazine/hh965661.aspx como Un ejemplo de cómo tomar el 'código simple' y aplicarle un patrón de diseño para que se vea 'más fácil' y luego aplicar otro patrón de diseño en el patrón de diseño porque el patrón original no era tan simple como se anunciaba. El exceso de ingeniería se está volviendo cada vez más común.
gbjbaanb

55
Yo discutiría con el bit de "convertirse". El exceso de ingeniería es tan antiguo como la ingeniería.
Gort the Robot

44
@AndresF. Somos particularmente anti-Java en el chat, pero es cierto que Java, más que C ++ , fomenta el exceso de ingeniería porque lo hace más asequible (GC), y las bibliotecas Java empresariales populares han popularizado este estilo, como ya ha notado. usted mismo.
Konrad Rudolph

10

Diría que los problemas con la "complejidad" que mencionas no tienen nada que ver con la POO. Tiene más que ver con las preocupaciones de separación.

Hace muchos años trabajé en un sistema, donde la clase de dominio tenía la responsabilidad de cargarse desde la base de datos, p. Ej.

var userId = Request.QueryString["UserID"].ToInt();
var user = new User(userId);
user.Name = ...;
...
user.Save();

Este es un código muy claro. No hay problema en entender esto. Sin embargo, el problema estaría en la unidad probando el código. A saber, ¿cómo probaría la Userclase la unidad sin tener que cargar una de la base de datos? ¿Y cómo probaría este código de manejo de solicitud web sin tener acceso a la base de datos? Es simplemente imposible.

Es por eso que tenemos un patrón como un repositorio, para separar la responsabilidad de manejar la lógica de dominio de un usuario de la funcionalidad de cargar y guardar uno en un almacén de datos. El COI ayuda a reducir el acoplamiento, también hace que el código sea más verificable, etc.

Entonces, si volvemos al ejemplo que escribe, ¿qué haría con el stock después de crearlo? Guardarlo en la base de datos

Stock stock = new Stock();
stock.addItem(item);
stock.removeItem(item);
this.StockRepository.Add(stock);

¡El rojo! No hay movimiento en la progresión de la POO que sugiera que debería ser más difícil. Desafortunadamente, si elige usar un mapeador OR para su código de acceso a datos, podría encontrarse con el problema de que el mapeador OR está imponiendo restricciones sobre cómo puede escribir su sistema. Pero eso es otro asunto.

Si eres nuevo en estos patrones, es posible que debas aprender un nuevo estilo de programación. Pero ese estilo de programación no es de ninguna manera más difícil que la programación OOP de la vieja escuela.


Conoces el esfuerzo que tienes que hacer para configurar tu repositorio. Aunque después de configurarlo, se vuelve reutilizable.
tunmise fasipe

quizás el problema es con las pruebas unitarias, si tuviéramos mejores herramientas para probar el conjunto (como tienes que hacer de todos modos) en lugar de las piezas pequeñas, ¿tendríamos sistemas que tuvieran menos errores?
gbjbaanb

2
@gbjbaanb: ya tenemos eso, se llama integración / prueba funcional. Las pruebas unitarias tienen un propósito diferente pero igualmente necesario
Kevin

@gbjbaanb: ya tenemos excelentes herramientas para las pruebas de aceptación / de todo el sistema, por ejemplo, la plataforma Cucumber on the Rails. Pero los equipos que son realmente buenos y escriben muy pocos errores, pero también entregan rápidamente, escriben muchas pruebas unitarias y solo unas pocas pruebas en todo el sistema. Vea sobre el "Triángulo de prueba", por ejemplo, aquí jonkruger.com/blog/2010/02/08/the-automated-testing-triangle
Pete

4

Ninguno. Nuestros problemas no han cambiado realmente; se ha elevado la barra para el código aceptable.

Para lograr lo anterior, es posible que deba crear varias clases (por ejemplo, resumen, fábrica, DAO, etc.) e implementar varias interfaces

No tienes que hacer eso. Pero si no lo haces, entonces surgen problemas; problemas que siempre han estado ahí. Ahora, sin embargo, los programadores tienen suficiente experiencia para identificar esos problemas y proporcionar mecanismos para aliviarlos (si es necesario). Aprendemos más sobre eso y obtenemos mejores soluciones (ver, por ejemplo, las opiniones de los programadores sobre el singleton).

Pero también debe darse cuenta de que introducir a los programadores en OO (o cualquier otra cosa) tenderá a pasar por alto las circunstancias excepcionales. Simplemente es más fácil explicar el camino feliz, y preocuparse por el resto una vez que los principiantes tengan eso. No hay bala de plata; así que sí, supongo que las cosas siempre parecerán más difíciles cuando se rompa esa ilusión idílica ...


3

Los ejemplos de "introducción a OO" son mucho más simples que una aplicación del mundo real. Solo necesita una clase para lograr lo anterior. El problema es que no hace mucho. Algunos patrones de diseño intentan acercarse (como ActiveRecord). Pero finalmente, cualquier ejemplo que no sea trivial tendrá más de una clase; Es correcto.


También tenga en cuenta que los marcos se acumulan con el tiempo. Entonces sí, la programación requiere más conocimiento. También significa que uno puede hacer más en menos tiempo.
Jeanne Boyarsky

3

Los lenguajes de programación que usan OO hoy están tratando de satisfacer requisitos complejos y entornos que siguen cambiando. OO permite a sus usuarios ocultar una variedad de niveles de complejidad (entre otras características) para que la codificación sea más clara y más fácil de construir y comprender. Sin embargo, esta característica no siempre está lista para usar. En su ejemplo, OO me ha permitido ocultar algunos detalles al proporcionarme un método para administrar elementos en una colección e incluso puede persistirlo utilizando el método "AddItem". El esfuerzo en ocultar la complejidad puede resultar en un marco fácil de usar y reutilizable que simplifica la vida. Por ejemplo, muchas implementaciones de ORM le permiten comunicarse con bases de datos sin que el programador escriba los detalles de SQL. Esto es realmente poderoso y lo hace más simple para el desarrollador.

Los patrones a los que te refieres son solo eso. Se supone que te harán la vida más fácil. Pero depende de usted adoptarlos y ajustarlos. El hecho de que se requiera más trabajo es solo porque obtienes más beneficios. Es como pagar más por un Ferrari. Si quieres los extras que pagas por ellos. Por lo tanto, si decide crear una solución escalable de N-Tier que se pueda ejecutar en varios servidores y en diferentes bases de datos de back-end, esto tiene un costo. Si su aplicación no requiere esta complejidad, ignore las piezas adicionales y recurra a la solución más simple que cubra sus necesidades (KISS & YAGNI).

Entonces, para concluir, no creo que OOP como concepto en sí mismo se esté volviendo más complejo, nosotros, los usuarios de OOP tenemos la opción de usarlo de diferentes maneras, y eso es algo bueno.


Puntos claros Yo se YAGNI. ¿Qué es KISS?
tunmise fasipe

2
@tunmisefasipe, KISS es un nombre corto para un principio de diseño. Las palabras originales son "Keep It Simple (Stupid)" (ref: en.wikipedia.org/wiki/KISS_principle ) pero una frase más cortés puede ser "Keep It So Simple".
NoChance

3
@tunmisefasipe - KISS = Mantenlo simple, estúpido. Una frase que me repito OVER, y OVER, y OVER, y todavía no siempre parece hundirse.
Michael Kohne

@MichaelKohne, ¡todos lo hacemos! Supongo que es un arte poder simplificar las cosas. E = M C C dice mucho en una forma muy concisa!
NoChance

3

Respuesta corta : Sí, porque lidias con problemas más difíciles.

Respuesta larga (muy sesgada) : para mí, los patrones de diseño generalmente indican que algunos paradigmas tienen problemas en un área determinada. Los patrones OOP tratan problemas de OOP (en el nivel inferior los patrones Java tratan problemas de Java), los patrones FP tratan problemas de FP etc.

Durante la programación puede tener diferentes prioridades. Es posible que desee tener un programa correcto, es posible que tenga un tiempo de comercialización más corto, un programa lo más rápido posible, mantenimiento a largo plazo o mantenimiento instantáneo por parte de un nuevo empleado. Dependiendo del matorral en el que se encuentre, tendrá diferentes diferencias: si está programando el controlador de la planta de energía, desea hacerlo correctamente la primera vez y no corregir errores de vez en cuando ("¿Se produce la fusión cada vez que presiona Ctrl+Alt+Del?"). Si está en HPC, la lógica puede ser relativamente simple pero desea ejecutarla lo más rápido posible, etc. Además, algunos paradigmas se ajustan mejor a ciertos problemas (por ejemplo, programación de inteligencia artificial y lógica, datos y bases de datos relacionales).

OOP es, hasta cierto punto, "demasiado bueno" en casos simples y es una historia de "modelado en vivo real". Por ejemplo, en primer libro sobre programación orientada a objetos que había leído clases Person, Employeey Managercon la is-arelación. Hasta ahora todo bien, pero ¿qué pasa si el empleado es ascendido a gerente?

Por otro lado, otros paradigmas tienen lecciones más difíciles por primera vez, por ejemplo, FP con variables inmutables (lo curioso es que las personas que tenían experiencia en programación a menudo encuentran más difícil de aprender que aquellos para quienes este es el primer idioma), sin embargo, en última instancia, son No más difícil que OOP. Probar funciones puras es trivial y en Haskell / Scala / ... tienes herramientas que generan pruebas para ti.

PD. Sí, la respuesta está sesgada en contra de OOP y admito que hasta cierto punto está 'en reacción' a OOP. OOP tiene sus usos, pero no es la única solución definitiva en mi opinión.

PPS Sí, use patrones de diseño, hacen que la programación de OOP sea más simple.

PPPS Usé OOP como sinónimo de programación imperativa OOP.


2

Creo que es más un caso de los documentos y ejemplos cada vez más realistas.

Los primeros libros de OOP (particularmente los primeros libros de Java) presentaron una visión absurdamente simplificada de la programación de aplicaciones. Los ejemplos de "Débito de una cuenta bancaria con un programa Java de 10 líneas" siempre fueron particularmente molestos, ya que he visto ejemplos de la vida real de esta tarea simple que se ejecuta en 6000 líneas de código COBOL (y el intento de reemplazo de Java que se ejecuta en 3500 líneas antes de ser abandonado como inviable!).

Afortunadamente, los libros de OO ahora tienden a reconocer las complejidades de la vida real y proporcionan ejemplos útiles de cómo lidiar con ellos.

Pero si desea ver cómo ejecutar una cuenta bancaria en solo 15 líneas de código , la programación funcional es su hombre

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.