La publicación contiene una cierta cantidad de bromas, el Ministerio de Salud le pide de manera convincente a un lector no preparado que se abstenga de leer.Los artículos sobre el tema "AF es mejor" o "OOP es mejor" se asemejan a un debate sobre lo que es mejor para el almuerzo, un tenedor o una cuchara. Tradicionalmente, los junes comenzaron con una cuchara, pero alguien muy autoritario me dijo una vez que solo come carne y usa un tenedor, por lo que ha surgido una nueva moda: comer con un tenedor. Comen gachas y sopas, e incluso se las arreglan para batir batidos. Internet está plagado de artículos, qué buenos somos, que aprendimos a comer un licuado con un tenedor y superar todos los rastrillos. Esto es divertido y triste, por un lado, les da una ventaja competitiva a los hombres experimentados que muestran excelentes resultados simplemente ignorando esta exageración, por otro lado, tienen que volver a capacitar a sus colegas y empleados, limpiando la basura causada por el viento de sus cabezas. En este artículo intentaré contar mi visión, que no pretende ser una verdad absoluta, pero funciona muy bien en la práctica.
Como es habitual en la ciencia, comenzamos con definiciones. La definición clásica de OOP implica seguir los principios de herencia, encapsulación y polimorfismo. Pero si no tenemos uno de estos componentes, ¿será OOP? Y si no, ¿qué será?
Mientras que la parte aburrida de la audiencia se cernía sobre este poco práctico y no nos pregunta nada, recordemos lo que sucedió antes de la OLP . Y ante él estaba la programación procesal. Y la idea principal de OOP en ese momento era la
conexión de datos y funciones para su procesamiento . La idea es simple, pero bastante revolucionaria, es difícil imaginar cuánto, pero más sobre eso más adelante.
La programación funcional, en una interpretación libre, considera el
programa como una fórmula matemática . Las fórmulas están bien formalizadas y con la misma entrada devuelven la misma salida. Todo el programa consta de rutinas que siguen los mismos principios. ¿Cómo difiere esto de la misma programación procesal? FP utiliza activamente
funciones puras ; idealmente, todo el programa debería ser una función pura. Las funciones puras
no tienen efectos secundarios , se pueden memorizar fácilmente, probar fácilmente, etc. ... Podemos decir que en las funciones puras la idea principal y la ventaja de FP.
Y ahora dos preguntas:
- ¿Podemos usar funciones puras en OOP?
- ¿Podemos vincular funciones a datos en el FP?
La respuesta a ambos es sí. Los métodos de clase estática pueden ser puros, incluso los métodos de instancia pueden considerarse limpios si no crean efectos secundarios y consideramos las propiedades de la instancia de clase como parámetros. Los límites de las definiciones clásicas están inflados y algunos pueden estar en desacuerdo, pero en la práctica simplemente funciona. Y tales métodos se formalizan y prueban no peor que las funciones puras clásicas escritas de acuerdo con todos los cánones. Acerca de los métodos de enlace a los datos es un poco más complicado, el lenguaje y las bibliotecas utilizadas imponen restricciones. Digamos que en JavaScript esto se hace principalmente, no estoy seguro acerca de Haskell y Erlang. Ahora lo más interesante es lo que ofrece, y por qué la OOP ya ha provocado tanta expectación hace 20-30 años. Si escribe un programa pequeño, puede escribir como desee, excepto por su sentido de la belleza, no afecta nada. Cuando crea un programa realmente grande, surge un problema de complejidad. No de complejidad computacional, creemos que aquí estamos haciendo todo bien, sino de complejidad percibida. Digamos que tiene 50,000 líneas de código, y todas son útiles. ¿Cómo organizarlos para no volverse loco (o no dejar el trabajo a las 11 noches)? No podemos reducir la cantidad de operaciones, pero podemos reducir la cantidad de conexiones entre ellas (la encapsulación nos ayuda con esto). Ocultamos la implementación compleja detrás de una interfaz simple y seguimos trabajando solo con la interfaz. Por ejemplo, Internet es una cosa terriblemente complicada, pero la mayoría de los desarrolladores tienen suficiente conocimiento del protocolo HTTP para hacer su trabajo
y dejar los niveles de red, físicos y de otro tipo a los administradores del sistema . Cuanto más débil es la conectividad de nuestros módulos,
menor es la complejidad en la etapa de integración entre ellos. Cuanto menos un módulo sepa sobre el otro, menos conectados estarán. Los métodos vinculantes a los datos dentro del módulo nos ayudan a eliminar este conocimiento de los consumidores del módulo. Esta es la principal ventaja pragmática de OOP. ¿Sobre qué? Enfoque anterior sin enlace de datos y método. FP, como descubrimos, no dice nada sobre esto. Puede pasar clases como argumentos a funciones puras, o puede usar funciones puras como métodos de una clase, no se contradice entre sí, sino que solo la complementa.
En la práctica, ¿dónde funciona principalmente un enfoque y dónde está el otro principalmente? Cuando escribo un
back-end en NodeJS, de alguna manera resulta en un paradigma
funcional por sí mismo. Por qué Porque la solicitud al servidor es por su naturaleza una función, con una entrada y salida fija. El enfoque funcional recae en las solicitudes del servidor de forma muy natural y el código es más compacto y flexible. Cuando creo una
interfaz para el navegador,
OOP generalmente funciona mejor, porque además de entrada y salida, también tenemos una
secuencia de eventos de usuario , así como eventos de programa, como el comienzo y el final de animaciones, solicitudes de servidor, etc. El enfoque funcional funcionó si fuera solo para dibujar una página estática sin interactividad, cuando se usa el FP en la interfaz, el tiempo de desarrollo o interactivo sufre (según nuestras mediciones, cada 3 veces). Por qué
Cualquier paradigma de programación se basa en un cierto modelo de realidad, y un modelo siempre es una simplificación. En FP, el modelo impone más restricciones al mundo, por lo que es más fácil de formalizar. Por la misma razón, cuando se vuelve irrelevante para las condiciones del problema, comienza a requerir más muletas. Por ejemplo, las IF de front-end resolvieron el problema de la entrada del usuario creando una matriz de eventos (acciones, redux hi). Pero esta es una abstracción irrelevante que, además de su impacto en el rendimiento, aumenta considerablemente el tiempo de desarrollo. Con este enfoque, puede crear una lista de tareas pendientes, pero en proyectos realmente grandes debe romper ladrillos con la frente y luego escribir artículos victoriosos para los mismos desafortunados. A modo de comparación, cuando escribimos el terminal de intercambio (en vanilla js, por supuesto) con canvas, svg y actualizado varias veces por segundo a través de websockets, en algunos componentes actualizados con frecuencia no eliminamos divs, sino que los reutilizamos, ya que recrearlos es relativamente costoso operación en el navegador (y esto es importante si tiene una
aplicación realmente grande ). Si programa en el front-end, ni siquiera tendrá ese pensamiento, ya que ya ha aceptado la inmutabilidad (por cierto, esto es algo maravilloso para trabajar con subprocesos múltiples, lo
que no sucede en JS), por lo que cada acción pasa por cada reductor y otra basura. Por otro lado, en el back-end a menudo resulta no tener clases, ya que allí, simplemente, puedes evitar el costo de crearlos, ya que las condiciones de las tareas son muy relevantes para el modelo FP. Pero, en su mayor parte, los desarrolladores de Java y PHP no tienen prisa por estudiar el FP, los proveedores de front-end están a la vanguardia, quienes realmente lo necesitan menos. Como ejercicio para la mente, por supuesto, es interesante, solo se obtienen los programas g ... pero, y alguien más para usarlos. A pesar del hecho de que la interfaz es una sección relativamente joven de TI, y sus tareas no resueltas allí durante varias generaciones. ¿Qué, al parecer, no es un ejercicio para la mente?