OOP vs Programación funcional vs Procedimiento [cerrado]

237

¿Cuáles son las diferencias entre estos paradigmas de programación? ¿Se adaptan mejor a problemas particulares o algún caso de uso favorece a uno sobre los demás?

¡Ejemplos de arquitectura apreciados!

Ashutosh Singh-MVP SharePoint
fuente
Esta no es una respuesta completa, pero escribo un poco sobre cómo "funcional" afecta / contrasta el estilo "OO" (en el contexto de F #) aquí: lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!511. entrada
Brian
¡Podría considerar leer esto! Hay muchos ejemplos de cuándo usar el que la hormiga es lo que las principales diferencias, pros / contras etc
Nikita Ignatov
1
Ver también: stackoverflow.com/questions/1530868
dreftymac
El tío Bob ha tuiteado sobre esto. Y también aquí .
jaco0646

Respuestas:

129

Todos ellos son buenos a su manera: son simplemente enfoques diferentes para los mismos problemas.

En un estilo puramente de procedimiento, los datos tienden a estar muy desacoplados de las funciones que operan en ellos.

En un estilo orientado a objetos, los datos tienden a llevar consigo una colección de funciones.

En un estilo funcional, los datos y las funciones tienden a tener más en común entre sí (como en Lisp y Scheme) al tiempo que ofrecen más flexibilidad en términos de cómo se utilizan realmente las funciones. Los algoritmos también tienden a definirse en términos de recursión y composición en lugar de bucles e iteraciones.

Por supuesto, el lenguaje en sí solo influye en el estilo preferido. Incluso en un lenguaje puramente funcional como Haskell, puede escribir en un estilo de procedimiento (aunque eso es altamente desaconsejado), e incluso en un lenguaje de procedimiento como C, puede programar en un estilo orientado a objetos (como en GTK + y API de EFL).

Para ser claros, la "ventaja" de cada paradigma está simplemente en el modelado de sus algoritmos y estructuras de datos. Si, por ejemplo, su algoritmo involucra listas y árboles, un algoritmo funcional puede ser el más sensato. O, si, por ejemplo, sus datos están altamente estructurados, puede tener más sentido componerlos como objetos si ese es el paradigma nativo de su lenguaje, o podría escribirse tan fácilmente como una abstracción funcional de mónadas, que es el paradigma nativo de lenguajes como Haskell o ML.

La opción que utiliza es simplemente lo que tiene más sentido para su proyecto y las abstracciones que admite su idioma.

Greyfade
fuente
55
Lo que dijiste no parece reflejar lo que escribiste. Dices que no tienen "pros y contras", y luego dices cómo son diferentes enfoques. ¿Por qué alguien elegiría un enfoque sobre otro, basado en una situación dada? fortalezas y debilidades, pros y contras, ¡como los llames, existen! No digo que uno sea inherentemente mejor, y tú tampoco. Creo que eso es lo que realmente estabas tratando de decir. a menos que realmente crea que cualquier enfoque elegido no tiene aspectos positivos y negativos, en relación con otro enfoque.
JM Becker
1
@TechZilla: Estoy de acuerdo en que mi redacción era deficiente, pero lo que quise decir es que no hay realmente una lista de características a las que pueda apuntar y decir que el idioma X es mejor que Y sin calificar que el idioma X es más adecuado para escribir el algoritmo U y el idioma Y podría ser más adecuado para escribir el algoritmo V, mientras que ambos pueden implementarse fácilmente en cualquier idioma.
greyfade
2
La diferencia entre procedimiento y funcional no me resulta clara. Estoy aprendiendo Scheme / Rackett en la universidad, pero realmente no puedo ver la gran diferencia entre este y el procedimiento C o PHP, ¿podría dar algún ejemplo?
Leonel
77
@Leonel: La mayor diferencia que la mayoría de la gente citará es que en los lenguajes de procedimiento, puede usar un bucle for, pero en los lenguajes funcionales, no existe tal cosa; en cambio, usa llamadas recursivas a funciones para realizar la misma tarea. Los lenguajes funcionales también hacen que las funciones sean objetos de primera clase, puede pasarlos como lo haría con un número, pero no puede hacerlo en C (y el soporte de PHP para él está roto).
greyfade
2
@tastro: cuando un paradigma tiene más sentido que el otro. Eso es realmente todo. A veces tiene más sentido modelar su código como la composición de funciones, y a veces tiene más sentido modelar sus datos como objetos. Hay muchas formas de expresar algoritmos y estructuras de datos. OOP y funcional resultan ser dos de esas cosas.
greyfade
25

Creo que las bibliotecas, herramientas, ejemplos y comunidades disponibles superan por completo el paradigma en estos días. Por ejemplo, ML (o lo que sea) podría ser el último lenguaje de programación de uso múltiple , pero si no puede obtener buenas bibliotecas para lo que está haciendo, está jodido.

Por ejemplo, si está haciendo un videojuego, hay más buenos ejemplos de código y SDK en C ++, por lo que probablemente esté mejor con eso. Para una aplicación web pequeña, hay algunos marcos de Python, PHP y Ruby geniales que lo ayudarán a comenzar a usarlo rápidamente. Java es una gran opción para proyectos más grandes debido a la verificación en tiempo de compilación y a las bibliotecas y plataformas empresariales.

Solía ​​ser el caso de que las bibliotecas estándar para diferentes idiomas eran bastante pequeñas y fáciles de replicar: C, C ++, Assembler, ML, LISP, etc. venían con lo básico, pero tendían a reducirse a la hora de estandarizar las cosas. como comunicaciones de red, cifrado, gráficos, formatos de archivos de datos (incluido XML), ¡incluso se omitieron estructuras de datos básicas como árboles equilibrados y tablas hash!

Los lenguajes modernos como Python, PHP, Ruby y Java ahora vienen con una biblioteca estándar mucho más decente y tienen muchas buenas bibliotecas de terceros que puede usar fácilmente, gracias en gran parte a su adopción de espacios de nombres para evitar que las bibliotecas choquen entre sí, y recolección de basura para estandarizar los esquemas de administración de memoria de las bibliotecas.

Dobes
fuente
55
Python, ruby, ... no tienen bibliotecas "estándar" como C o LISP, ya que son lenguajes de implementación únicos. Python es lo que dice Guido, no hay un estándar. Cualquier implementación particular de C o LISP (o lo que sea) en la actualidad viene con un gran conjunto de bibliotecas más allá de las estándar.
Dan Andreatta
8
La pregunta era sobre las diferencias entre la programación orientada a objetos, funcional y de procedimiento. Si bien los idiomas mencionados en estas respuestas ciertamente se prestan a uno de estos enfoques, la respuesta no menciona ninguno de estos conceptos ... Independientemente de si "las bibliotecas [...] disponibles [triunfan] en el paradigma", eso no responde a la pregunta en cuestión, evitando así lo que es una pregunta completamente válida.
rinogo
1
diatriba relacionada de ircmaxell
rinogo
20

Estos paradigmas no tienen que ser mutuamente excluyentes. Si observa Python, admite funciones y clases, pero al mismo tiempo, todo es un objeto, incluidas las funciones. Puede mezclar y combinar el estilo funcional / oop / procedural en un solo código.

Lo que quiero decir es que, en lenguajes funcionales (al menos en Haskell, el único que estudié) ¡no hay declaraciones! ¡solo se permiten funciones dentro de ellas! PERO, las funciones son ciudadanos de primera clase, puedes pasarlas como parámetros, junto con muchas otras habilidades. Pueden hacer cosas poderosas con pocas líneas de código.

Mientras que en un lenguaje de procedimiento como C, la única forma de pasar las funciones es mediante el uso de punteros de función, y eso por sí solo no permite muchas tareas potentes.

En python, una función es un ciudadano de primera clase, pero puede contener un número arbitrario de declaraciones. Por lo tanto, puede tener una función que contenga código de procedimiento, pero puede pasarla como si fuera un lenguaje funcional.

Lo mismo vale para OOP. Un lenguaje como Java no le permite escribir procedimientos / funciones fuera de una clase. La única forma de pasar una función es envolverla en un objeto que implemente esa función y luego pasar ese objeto.

En Python, no tienes esta restricción.

hasen j
fuente
Creo que quiso decir "estos paradigmas no tienen que ser mutuamente excluyentes". Los 3 de ellos son ortogonales, ya que idealmente podría usar uno, 2 o 3 en un solo programa (si su idioma lo permite).
Joe Pineda
Sí, supongo que mutuamente excluyentes es un mejor término para eso. gracias
hasen
14

Para GUI, diría que el Paradigma orientado a objetos es muy adecuado. La ventana es un objeto, los cuadros de texto son objetos y el botón Aceptar también es uno. Por otro lado, cosas como el procesamiento de cadenas se pueden hacer con mucha menos sobrecarga y, por lo tanto, más sencillo con un paradigma de procedimiento simple.

No creo que sea una cuestión de idioma tampoco. Puede escribir funcional, procesal u orientado a objetos en casi cualquier lenguaje popular, aunque puede ser un esfuerzo adicional en algunos.

panschk
fuente
17
Tentado a rechazar por perpetuar la idea errónea de que "Object = GUI widget", pero me abstendré. OOP funciona igual de bien para representar conceptos abstractos, como "UserAccount" o "PendingSale", como para elementos de interfaz visibles como "Window" y "Button".
Dave Sherohman
55
Escribí que una ventana puede ser un objeto. ¿Cómo se llega a la conclusión de que cada Objeto es una ventana desde allí? Fue solo un ejemplo. Por supuesto, la POO se puede usar igualmente para modelar entidades abstractas y su relación. De todos modos, gracias por no votar negativamente. De todos modos no tengo muchos puntos: D
panschk
66
-1. OOP no tiene nada que ver con la GUI. Idealmente, el mejor método para diseñar guis es usar un archivo de texto externo (por ejemplo, HTML). Mientras que cosas como el procesamiento de cadenas en realidad se hacen mucho mejor con objetos. (piensa en cuerdas en C) !!
hasen
1
No sé, tal vez solo estoy acostumbrado a programar con objetos para darme cuenta. Pero, ¿cómo haría algunas cosas interactivas como cambiar el valor en TextBox X cuando el valor de TextBox Y ha sido alterado sin usar objetos? Está bien, simplemente podría utilizar VARs globales para todo ...
panschk
1
El procesamiento de cadenas se realiza increíblemente en perl (100 veces mejor que en Java, C ++ o C #), pero la funcionalidad de cadena del lenguaje NO está absolutamente orientada a objetos. El manejo de la cadena de C fue terrible, pero C no es el único lenguaje de procedimiento (ni el mejor).
Joe Pineda
6

Para responder a su pregunta, necesitamos dos elementos:

  1. Comprensión de las características de diferentes estilos / patrones de arquitectura.
  2. Comprensión de las características de los diferentes paradigmas de programación.

Se muestra una lista de estilos / patrones de arquitectura de software en el artículo de arquitectura de software en Wikipeida. Y puede investigar sobre ellos fácilmente en la web.

En resumen y en general, el procedimiento es bueno para un modelo que sigue un procedimiento, OOP es bueno para el diseño y funcional es bueno para la programación de alto nivel.

Creo que deberías intentar leer la historia de cada paradigma y ver por qué la gente lo crea y puedes entenderlos fácilmente.

Después de comprenderlos a ambos, puede vincular los elementos de estilos / patrones de arquitectura a paradigmas de programación.

Gabriel Chung
fuente
2

Creo que a menudo no son "versus", pero puedes combinarlos. También creo que a menudo, las palabras que mencionas son solo palabras de moda. Hay pocas personas que realmente saben lo que significa "orientado a objetos", incluso si son los evangelistas más feroces de la misma.

Svante
fuente
1

Uno de mis amigos está escribiendo una aplicación de gráficos usando NVIDIA CUDA . La aplicación encaja muy bien con el paradigma OOP y el problema se puede descomponer en módulos perfectamente. Sin embargo, para usar CUDA necesita usar C, que no admite la herencia . Por lo tanto, debes ser inteligente.

a) Diseña un sistema inteligente que emulará la herencia hasta cierto punto. ¡Se puede hacer!

i) Puede usar un sistema de enlace , que espera que cada niño C del padre P tenga una anulación determinada para la función F. Puede hacer que los niños registren sus anulaciones, que se almacenarán y se llamarán cuando sea necesario.

ii) Puede utilizar la función de alineación de memoria de estructura para convertir a los hijos en padres.

Esto puede ser bueno, pero no es fácil encontrar una solución confiable y a prueba de futuro. Pasará mucho tiempo diseñando el sistema y no hay garantía de que no tendrá problemas a mitad del proyecto. Implementar la herencia múltiple es aún más difícil, si no casi imposible.

b) Puede utilizar una política de nomenclatura coherente y utilizar el enfoque de divide y vencerás para crear un programa. No tendrá ninguna herencia, pero debido a que sus funciones son pequeñas, fáciles de entender y consistentemente formateadas, no las necesita. La cantidad de código que necesita escribir aumenta, es muy difícil mantenerse enfocado y no sucumbir a soluciones fáciles (hacks). Sin embargo, esta forma de codificación ninja es la forma C de codificación. Mantenerse en equilibrio entre la libertad de bajo nivel y escribir un buen código. Una buena manera de lograr esto es escribir prototipos usando un lenguaje funcional. Por ejemplo, Haskell es extremadamente bueno para los algoritmos de creación de prototipos.

Tiendo hacia el enfoque b. Escribí una posible solución usando el enfoque a, y seré honesto, se sintió muy poco natural usar ese código.

Sneg
fuente
Los primeros copmpilers de c ++ no fueron más que preprocesadores que generaron código C. Como tal, TODAS las características de c ++, incluida la herencia múltiple, se pueden implementar usando C. (emular el manejo de excepciones de C ++ en C requeriría algún tipo de soporte de plataforma para excepciones, pero las implementaciones de c ++ también lo requieren, así que no creo que sea lo básico idea inválida).
Chris Becke
2
@ Chris Becke tu respuesta es demasiado filosófica. Por un lado, C tiene múltiples estándares (a través de los años), casi ninguno de ellos completamente adoptado por los compiladores de C, y mucho menos c ++. Decir que C ++ es un superconjunto de C porque usa la sintaxis de C no significa mucho porque ni siquiera puedes escribir código para un compilador de C que compila en otro compilador de C sin un esfuerzo significativo. Además, hay características de lenguaje (sistemas de tipos, compatibilidad con OOD) ofrecidas en otros idiomas que serían imposibles de implementar en C sin usar C para diseñar un nuevo lenguaje (que es exactamente la razón por la cual hay 'nuevos idiomas')
Sprague
Ya sabes. Ya no puedo ver qué relevancia tiene mi comentario para esta publicación. : P
Chris Becke
Cuda ha soportado C ++ desde hace algún tiempo.
Aryeh Leib Taurog