¿Existe una correlación entre la escala del proyecto y el rigor del idioma?

69

Al explicar la diferencia entre el rigor de los lenguajes y los paradigmas para un colega mío, terminé afirmando que:

  • Los lenguajes tolerantes, como los lenguajes dinámicos e interpretados, se usan mejor para prototipos y proyectos pequeños o aplicaciones web de tamaño mediano. Al elegir lenguajes dinámicos elegantes como Python o JavaScript con Node.js, los beneficios son:

    1. Desarrollo rápido,

    2. Código de placa de caldera reducido,

    3. Capacidad para atraer programadores jóvenes y creativos que huyen de "lenguajes corporativos" como Java.

  • Los idiomas escritos de forma estática / compilada son mejores para las aplicaciones que requieren mayor rigidez, como aplicaciones críticas para la empresa o aplicaciones para aplicaciones de tamaño mediano a grande.

    1. Paradigmas y patrones conocidos desarrollados durante décadas,

    2. Facilidad de verificación estática,

    3. Capacidad para encontrar muchos desarrolladores profesionales con décadas de experiencia.

  • Los lenguajes estrictos como Haskell, Ada o técnicas como los contratos de Código en C # son mejores para los sistemas que favorecen la seguridad sobre la flexibilidad (incluso si Haskell puede ser extremadamente flexible), como los sistemas críticos para la vida y los sistemas que se espera sean extremadamente estable. Los beneficios son:

    1. Capacidad para detectar tantos errores como sea posible en tiempo de compilación,

    2. Facilidad de verificación estática,

    3. Facilidad de pruebas formales.

Sin embargo, al observar los lenguajes y tecnologías utilizados por las grandes corporaciones en los proyectos a gran escala, parece que mi afirmación es errónea . Por ejemplo, Python se usa con éxito para sistemas grandes como YouTube u otras aplicaciones de Google que requieren una cantidad importante de rigor.

¿Todavía hay una correlación entre la escala del proyecto y el rigor del lenguaje / paradigma que se debe usar?

¿Hay un tercer factor que he olvidado tener en cuenta?

¿En qué me equivoco?

    
pregunta Arseni Mourzenko 24.08.2013 - 19:18

5 respuestas

38

Un estudio de caso interesante sobre temas de escalamiento de proyectos que utilizan lenguaje dinámico e interpretado se puede encontrar en Beginning Scala por David Pollak.

  

Comencé a buscar una manera de expresar el código en mi cerebro de una manera más simple y directa. Encontré Ruby y Rails. Me sentí liberado. Ruby me permitió expresar conceptos en muchas menos líneas de código. Rails era mucho más fácil de usar que Spring MVC, Hibernate y los otros marcos web de Java "optimizados". Con Ruby y Rails, pude expresar mucho más de lo que estaba en mi cabeza en un período de tiempo más corto. Fue similar a la liberación que sentí cuando me mudé de C ++ a Java ...

     

A medida que mis proyectos de Ruby y Rails crecieron más allá de unos pocos miles de líneas de código y cuando agregué miembros del equipo a mis proyectos, los desafíos de los lenguajes dinámicos se hicieron evidentes.

     

Estábamos gastando más de la mitad de nuestras pruebas de escritura de tiempo de codificación, y gran parte de los aumentos de productividad que vimos se perdieron en la escritura de prueba . La mayoría de las pruebas no hubieran sido necesarias en Java porque la mayoría de ellas estaban orientadas a garantizar que habíamos actualizado a las personas que llamaban cuando refaccionábamos el código cambiando los nombres de los métodos o los recuentos de parámetros. Además, descubrí que al trabajar en equipos en los que se formaban mentes entre dos y cuatro miembros del equipo, las cosas fueron bien en Ruby, pero cuando intentamos atraer nuevos miembros al equipo, las conexiones mentales eran difíciles de transmitir a los nuevos miembros del equipo .

     

Fui en busca de un nuevo lenguaje y entorno de desarrollo. Estaba buscando un lenguaje tan expresivo como Ruby pero tan seguro y de alto rendimiento como Java ...

Como puede ver, los principales desafíos en la escala del proyecto para el autor resultaron estar en el desarrollo de pruebas y la transferencia de conocimientos.

En particular, el autor explica más detalladamente las diferencias en la escritura de prueba entre idiomas tipificados de forma dinámica y estática en el Capítulo 7. En la sección "Matar de forma conmovedora a los conejos: las escaleras de Dwemthy", el autor analiza el puerto de Scala de un ejemplo particular de Ruby:

  

Por qué Lucky Stiff ... presenta algunos de los conceptos de metaprogramación de Ruby en Dwemthy's Array en la que un conejo lucha contra una serie de criaturas. N8han14 actualizó el ejemplo para que funcione en Scala ...

     

En comparación con el código de Ruby, las partes de la biblioteca del código de Scala eran más complejas. Tuvimos que hacer mucho trabajo para asegurarnos de que nuestros tipos fueran correctos. Tuvimos que volver a escribir manualmente las propiedades de Creature en las clases DupMonster y CreatureCons. Esto es más trabajo que method_missing . También tuvimos que hacer una buena cantidad de trabajo para apoyar la inmutabilidad en nuestras criaturas y armas.

     

Por otro lado, el resultado fue mucho más poderoso que la versión Ruby. Si tuviéramos que escribir pruebas para nuestro código Ruby para probar lo que el compilador de Scala nos asegura, necesitaríamos muchas más líneas de código. Por ejemplo, podemos estar seguros de que nuestro Conejo no podría manejar un Hacha. Para obtener esta garantía en Ruby, tendríamos que escribir una prueba que asegure que la invocación de |^ en un Rabbit falle. Nuestra versión de Scala garantiza que solo las Armas definidas para una Criatura dada puedan ser utilizado por esa criatura, algo que requeriría mucha reflexión de tiempo de ejecución en Ruby ...

Leer más arriba puede hacer que uno piense que a medida que los proyectos se hacen aún más grandes, la escritura de prueba puede volverse prohibitiva. Este razonamiento sería incorrecto, como lo demuestran los ejemplos de grandes proyectos exitosos mencionados en esta pregunta ("Python se usa con éxito para ... YouTube").

La cosa es que la escala de los proyectos no es realmente sencilla. Los proyectos muy grandes y de larga vida pueden "permitir" un proceso de desarrollo de pruebas diferente, con suites de pruebas de calidad de producción, equipos de desarrollo de pruebas profesionales y otras cosas de peso pesado.

Las suites de prueba de Youtube o Kit de compatibilidad de Java de seguro viven una diferente life que las pruebas en un pequeño proyecto tutorial como Dwemthy's Array .

    
respondido por el gnat 24.08.2013 - 23:10
24

Su afirmación no es incorrecta. Solo necesitas profundizar un poco más.

En pocas palabras, los grandes sistemas utilizan varios idiomas, no solo un idioma. Puede haber partes que se crean utilizando idiomas "estrictos", y puede haber partes que se crean utilizando idiomas dinámicos.

En cuanto a su ejemplo de Google y YouTube, escuché que usan Python principalmente como "pegamento" entre varios sistemas. Solo Google sabe con qué se construyen esos sistemas, pero apuesto a que muchos de los sistemas críticos de Google se crean utilizando lenguajes estrictos y "corporativos" como C ++ o Java, o tal vez algo que ellos mismos crearon como Go.

No es que no pueda usar idiomas tolerantes para sistemas a gran escala. Mucha gente dice que Facebook usa PHP, pero se olvidan de mencionar que Facebook tuvo que crear pautas de programación extremadamente estrictas para usarlo de manera eficiente en esta escala.

Entonces, sí, se requiere cierto nivel de rigor para proyectos a gran escala. Esto puede provenir ya sea del rigor del lenguaje o del marco, o de las pautas de programación y las convenciones de código. No puedes simplemente atrapar a pocos graduados universitarios, darles Python / Ruby / JavaScript y esperar que escriban software que se extienda a millones de usuarios.

    
respondido por el Euphoric 24.08.2013 - 21:10
3

Hay dos tipos de errores para verificar: errores de tipo (concatenar un entero + lista de flotadores) y errores de lógica de negocios (transferir dinero a una cuenta bancaria, verificar si la cuenta de origen tiene dinero).

La parte "dinámica" de un lenguaje de programación dinámico es el lugar donde se realiza la comprobación de tipos. En un lenguaje de programación "de tipo dinámico", la comprobación de tipos se realiza mientras se ejecuta cada instrucción, mientras que en un lenguaje de programación "de tipo estático" se realiza en el momento de la compilación. Y puede escribir un intérprete para un lenguaje de programación estático (como emscriptem hace), y también puede escribir un compilador estático para una dinámica lenguaje de programación (como gcc-python o shed-skin hace).

En un lenguaje de programación dinámico como Python y Javascript, debe escribir pruebas unitarias no solo para la lógica de negocios del programa, sino también para verificar si su programa no tiene errores de sintaxis o de tipo. Por ejemplo, si agrega "+" un número entero a una lista de flotantes (lo que no tiene sentido y emitirá un error), en un lenguaje dinámico, el error se generará en tiempo de ejecución al intentar ejecutar la declaración. En un lenguaje de programación estático como C ++, Haskell y Java, este tipo de error de tipo será detectado por el compilador.

Una base de código pequeña en un lenguaje de programación comprobado dinámicamente es más fácil de buscar errores de tipo porque es más fácil tener una cobertura del 100% del código fuente. Eso es todo, ejecutas el código a mano varias veces con diferentes valores y listo. Tener una cobertura del 100% del código fuente le da una pista justa de que su programa puede no tener errores de tipo .

Con una base de código grande en un lenguaje de programación comprobado dinámicamente, es más difícil probar cada declaración con cada combinación de tipo posible, especialmente si es descuidado y escribe una función que puede devolver una cadena, una lista o un objeto personalizado según sus argumentos.

En un lenguaje de programación comprobado estáticamente, el compilador detectará la mayoría de los errores de tipo en el momento de la compilación. Lo digo más porque un error de división por cero o un error de matriz fuera de los límites también son errores de tipo.

Más a menudo que no, la discusión real no es sobre los lenguajes de programación, sino sobre las personas que usan esos lenguajes. Y esto es cierto porque, por ejemplo, el lenguaje ensamblador es tan poderoso como cualquier otro lenguaje de programación, sin embargo, estamos escribiendo código en JavaScript. ¿Por qué? Porque somos humanos. Primero, todos cometemos errores y es más fácil y menos propenso a errores utilizar una herramienta dedicada especializada para una tarea específica. Segundo, hay una restricción de recursos. Nuestro tiempo es limitado, y escribir páginas web en el ensamblaje tardaría mucho tiempo en terminarse.

    
respondido por el vz0 30.06.2014 - 09:56
3

Mi experiencia con los sistemas grandes es que no se paran o caen por elección de idioma, sino por problemas de diseño / arquitectura o cobertura de prueba . Prefiero tener un equipo de Python con talento en mi gran proyecto empresarial, que uno mediocre de Java.

Habiendo dicho eso, cualquier lenguaje que te permita escribir significativamente menos código , debe valer la pena verlo (por ejemplo, Python vs Java). Quizás el futuro esté en lenguajes inteligentes de tipo estático con inferencia de tipo avanzada (por ejemplo, en el molde de Scala). ¿O híbrido, como C # está intentando con su calificador dynamic ...?

Y no olvidemos el "otro" beneficio de la escritura estática: la finalización correcta del código IDE / intellisense, que desde mi punto de vista es una característica esencial, no es bueno tenerla.

    
respondido por el Cornel Masson 25.03.2015 - 14:26
0

Otra consideración es el quién detrás de escribir aplicaciones a gran escala. He trabajado en muchos lugares que quieren usar Ruby o Python en algunos proyectos grandes de tipo empresarial, pero los gerentes de TI y los equipos de seguridad corporativos los "rechazan" de manera constante debido a la naturaleza de código abierto de los proyectos.

Me han dicho: "No podemos usar Ruby on Rails porque es de código abierto y alguien podría poner hacks allí que roben información crítica o protegida". Lo siento, pero una vez que alguien tiene esa mentalidad de código abierto == mal, es casi imposible cambiarlo. Esa línea de pensamiento es una enfermedad corporativa.

C # y Java son lenguajes de confianza con confianza . Ruby y Python no son idiomas de confianza.

    
respondido por el Jarrett Meyer 24.08.2013 - 21:41