¿La orientación a objetos seguiría siendo el paradigma de programación dominante en un futuro en el que las computadoras personales suelen tener 10 o 100 núcleos?

No hay incompatibilidad fundamental entre OO y paralelismo.

En Google implementamos regularmente programas OO que se escalan a cientos de miles de máquinas, algunas con más de 16 núcleos cada una. Más núcleos en una caja significa mejor paralelismo y mejor localidad. Entonces, si tuviéramos más de 100 núcleos en una sola máquina, los programas actuales probablemente se ejecutarían aún más rápido. Quizás con un poco de ajuste podríamos obtener aún más rendimiento.

Gran parte del código que escribo está en C ++. El lenguaje mezcla paradigmas de programación procesal (de sus orígenes C), genéricos (de plantillas), orientados a objetos (de clases y objetos) y funcionales (de C ++ 11 lambdas, objetos de función, etc.). Todos estos elementos se utilizan en nuestros programas en diversos grados. Si bien evitamos ciertas funciones (por ejemplo, excepciones), es poco probable que decidamos abandonar todas las funciones OO. Después de todo, algunos de ellos son bastante útiles. (Separar la interfaz de la implementación, por ejemplo).

Si observa otros lenguajes populares como Java y Python, también utilizan una mezcla de diferentes paradigmas de programación. Los lenguajes “puristas” como Smalltalk y Haskell tienden a ser mucho más especializados. Cada uno tiene su lugar. No sospecho que un lenguaje purista dominará el mercado, e incluso si lo hiciera probablemente tendría que adoptar otros paradigmas o volverse menos relevante con el tiempo.

En cualquier caso, no creo que los conjuntos de características o las metodologías de los idiomas se vean influenciados mucho más por la cantidad de núcleos por máquina. Después de todo, ya estamos en un mundo altamente paralelo.

Estoy de acuerdo con la respuesta de Alan, pero quiero agregarle un poco de mi propia perspectiva. Si retrocede un paso y examina la estructura de su programa como un conjunto de comportamientos e interacciones, entonces la programación funcional y orientada a objetos todavía tiene mucho sentido en sistemas altamente paralelos. De hecho, ya puede ver esto en acción en la mayoría de los servicios web a escala horizontal y en sistemas como Hadoop y Elastic Map Reduce (EMR), donde el énfasis principal está en coordinar tareas grandes y tráfico pesado entre muchas máquinas individuales.

El punto aquí no es tanto la estructura del programa en sí, sino la naturaleza de la coordinación entre sus múltiples hilos. Un sistema cooperativo, ya sea distribuido entre núcleos de CPU o máquinas físicas, se asegura de que los datos sobre los que actúa se mantengan en un estado coherente. En ambos escenarios, el código multiproceso mal escrito puede causar condiciones de carrera, problemas de consistencia de datos e incluso procesos desbocados dependiendo de la naturaleza de la falla.

El problema es más obvio en los sistemas de múltiples hosts por dos razones: una, la mayoría de estos sistemas se basan en una fuente de datos común (por ejemplo, Amazon DynamoDB como servicio), y dos, la latencia entre cada host (generalmente a su maestro) y La fuente de datos es mucho más alta que en un sistema interno. Pero también existe el mismo problema en un sistema de host único y núcleo múltiple: por ejemplo, acceder a un archivo en el disco duro es equivalente a llamar a DynamoDB, y si varios hilos lo hacen de manera conflictiva, del mismo tipo de corrupción de datos puede ocurrir.

En mi opinión, esto tiene muy poco que ver con el paradigma de programación que se utiliza. Los mismos problemas existen ya sea que tenga clases complejas o primitivas simples, ya sea que pase instancias de objetos complejos como parámetros a diferentes subprocesos, los serialice en cadenas o use referencias de funciones para hacer su trabajo por usted. Si sus hilos no están coordinando y cooperando, corre el mismo riesgo de problemas y condiciones de carrera.

Por lo tanto, creo que la expansión de los núcleos de la CPU tendrá poco efecto en el tipo de programación que la gente usará en el futuro. La POO sigue siendo bastante popular en parte porque es relativamente fácil de explicar y porque le brinda una buena forma de visualizar y encarnar comportamientos de manera realista. Pero la programación funcional también se está volviendo bastante popular, y tiene algunas ventajas obvias sobre la OOP directa. Personalmente, espero que eventualmente encontremos un buen equilibrio entre los dos y tengamos un nuevo “súper lenguaje” que brinde los mejores aspectos de ambos enfoques. (Ir parece estar yendo en esa dirección ya, y Java está tratando de mantenerse al día).

La programación concurrente y paralela es un poco diferente. Cuando hablamos de múltiples núcleos, hablamos principalmente de computación paralela, pero también de servidores concurrentes. Creo que la comparación en la escala de núcleos es entre la programación imperativa y declarativa (por ejemplo, lazy-pure-FP), mientras que en la escala de proyectos entre los paradigmas OOP y FP (estas son solo ideas aproximadas ya que los límites entre imperativo y OOP, y entre declarative y FP son borrosos. En principio, declarative incluye FP, mientras que OOP puede aplicarse tanto en paradigmas declarativos como imperativos. Aún así, OOP tradicional se basó en un estado mutable, mientras que la programación funcional promueve estructuras inmutables).

Con el número de núcleos, la programación imperativa disminuirá y la programación declarativa referencialmente transparente aumentará (programación funcional, programación lógica, programación de flujo de datos, computación vectorizada), porque el compilador tendrá mucho más espacio para reescribir el programa y el antiguo. los programas serán generados casi completamente / automáticamente por la tecnología.

El OOP tiene algunas versiones, con la herencia sustituida por interfaces o incluso rasgos en algunos idiomas, así como prácticas mutables vs inmutables. Las adiciones recientes a C # y Java inyectan bastantes poderes de FP en lenguajes OOP tradicionales. OOP y FP no son totalmente incompatibles como los espectáculos de Scala, pero en cierta medida lo son (especialmente en la mentalidad del programador y la estructuración a gran escala de los programas). Aquí la competencia está en la escala del programa / proyecto / equipo: cuando su programa crece más rápido, cambia más rápido, el equipo crece más rápido, que la programación funcional escala mejor porque es más seguro, compositivo, sin efectos o explícito, sus elementos son más reutilizables (funciones, estructuras de datos), especialmente en la variante perezosa como Haskell, el compilador puede garantizar más, los tipos son más descriptivos (documentación) y el sistema de tipos lo guía más en algunas opciones para escribir código a veces.

De hecho, la escala declarativa (FP y programación lógica) con núcleos y miembros de equipo o líneas de código debido a las mismas cosas: como siempre puede reemplazar una función con su resultado (transparencia referencial), y los tipos le permiten saber qué Las funciones toman y dan de manera bastante explícita, incluidos los efectos: para que pueda comprender su contexto local, que es más simple, más explícito, más parecido a Lego. El compilador también puede entender más para poder reescribirlo para escalarlo. Los humanos también “reescriben” el código en sus mentes para comprenderlo, o modelarlo en papel, o incluso refactorizar el código para que el equipo actual pueda entenderlo mejor. La refactorización es más segura con FP.

Creo que la OOP seguirá siendo el paradigma dominante en el futuro previsible.

¡Sin embargo!

Creo que FP seguirá creciendo, pero se utilizará principalmente junto con OOP en lugar de un paradigma independiente. Es un mito completo que son dos ideas competidoras y una debe ganar, son totalmente compatibles y utilizables dentro del mismo programa y el mismo idioma.

Scala, Java, Swift, C # son todos lenguajes OOP, pero también tienen FP incorporado, puede usar ambos en el mismo programa con total facilidad.

Solía ​​hacer un trabajo en el que usaba una máquina SPARC con 96 núcleos lógicos, OOP es * totalmente * compatible con eso, OOP permite la concurrencia con bastante facilidad.

Ahora, con OOP, tendrá un “estado” y FP puede fruncir el ceño porque, idealmente, las funciones no tienen efectos secundarios y funcionan completamente en la entrada y entregan una salida. El mundo real llama a la mierda esta idea, y acepta que existe una realidad en las computadoras que existe * estado * y que no puede simplemente hacer copias de datos para pasar como inmutables cuando sus datos son una imagen de 1GB o algo así.

Pure FP se adapta a muchas tareas en las que tiene un alto rendimiento de pequeños trabajos, por ejemplo, por ejemplo, estamos hablando de millones / miles de millones de pequeños mensajes para procesar. La FP pura se adapta muy bien, es un trabajo simple dentro y fuera hecho millones de veces.

Absolutamente * no * se adapta al trabajo como las aplicaciones GUI, donde tienes tareas de larga ejecución trabajando en el mismo, tal vez un gran conjunto de datos por un tiempo. OOP tiene mucho más sentido allí.

Sin embargo, no son paradigmas competitivos, puedes usar ambos, nadie necesita ser religioso aquí. FP es una maravillosa comodidad en Java 8, pero no puede reemplazar a OOP, por citar al Almirante Greer en Patriot Games:

Las posibilidades de que viniera aquí, de que lo intentara, de que pudiera venir aquí son tan remotas que incluso tengo problemas para decirlo.

Reemplazar OOP con FP es como reemplazar autos con motocicletas. Es solo cosas diferentes, para diferentes trabajos, y puede tener ambos si lo desea.

Gran pregunta

La concurrencia es lo principal con muchos núcleos, y aquí la orientación del objeto es un poco indiferente.

Puede dividir los programas para que sean independientes y puedan escalar horizontalmente a través de los núcleos.

Pero puede hacer esto con cualquier estructura de programa, dado que los programas en cada núcleo no se comunican entre sí.

OO es más complicado con múltiples subprocesos en el mismo núcleo. Puede poner bloqueos de sincronización para proteger el estado interno del objeto o ir en sentido contrario. Use objetos de valor inmutable.

Pero entonces, su OO comienza a parecerse más a la programación funcional

Pero con núcleos independientes, no estoy convencido de que sea un factor determinante. Pero todavía usaría OO en ese caso, porque me gusta

Escribir programas altamente concurrentes no es el problema.

Incluso con un millón de núcleos, el problema principal en la informática seguirá siendo cómo modelar y representar mejor los conceptos de los dominios de problemas no informáticos en el código.

Ese ha sido el desafío desde la década de 1940, y sigue siendo el caso hoy.

Hasta que aparezca una mejor manera de representar un problema o sistema en el código de un dominio fuera de la informática, la orientación a objetos, el modelado de datos y la descomposición funcional seguirán siendo dominantes.

“La parte más difícil de construir un sistema de software es decidir con precisión qué construir”. – Fred Brooks, No Silver Bullet

Con la forma en que han ido las cosas en el campo, es realmente difícil predecir eso, porque el campo se da a las modas pasajeras. Actualmente, la preferencia es que la programación funcional domine en ese entorno, pero se trata de personas que buscan fruta baja. Algunos en CS han pensado que FP es el camino a seguir, porque hay cierta familiaridad con FP en el campo. Con la evaluación diferida, se ha demostrado teóricamente que puede realizar un procesamiento paralelo o concurrente de manera coherente con él. Solo necesita una VM que pueda dividir los cálculos en los diferentes núcleos. Es mejor que usar hilos, bloqueos y semáforos, al menos. Sin embargo, sería completamente posible que un entorno OOP funcione de manera eficiente en múltiples núcleos. Erlang ha existido por al menos un par de décadas. Puede hacer OOP en él, y distribuye el procesamiento a múltiples procesadores. Simplemente no es tan conocido, incluso en la comunidad CS.

Hay ventajas y desventajas de usar FP para la programación concurrente. FP no es una panacea. Entiendo el argumento sobre los datos inmutables, pero hay muchas otras cosas a considerar cuando se trata de escribir software complejo.

Todavía prefiero OO. OO es una excelente manera de organizar el código del programa (y no, no tiene que usar una herencia profunda). Creo que Go es un lenguaje excelente para escribir software concurrente, aunque no sea FP.

OO sigue siendo inmensamente popular hoy. No veo ninguna razón por la que eso debería cambiar en el futuro. Ni siquiera si saltamos de octo-core a hecta-core, kilo-core o mega-core.

Creo que encontrarás que FP tendrá dificultades para competir con OO. Para la mayoría de las personas es más difícil asimilar.

Casi seguro que no. Los actores ya se están convirtiendo en el paradigma principal para la concurrencia masiva. Echa un vistazo a Erlang.