¿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!
¿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!
Respuestas:
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.
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.
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.
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.
Para responder a su pregunta, necesitamos dos elementos:
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.
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.