Tuve una conversación inusual y breve con un arquitecto muy experimentado sobre lenguajes dinámicos y estáticos. Dijo que los datos de la compañía muestran que hay evidencia de una mayor productividad cuando se usan lenguajes estáticos. Tenga en cuenta que es una gran empresa con una larga historia. Para mi sorpresa (y la de otros), la métrica que utilizó fue la adición de líneas de código.
Rápidamente descartó las objeciones con respecto a la métrica diciendo que dentro de una misma compañía, con una cultura, línea de negocio similar y con suficientes datos, las diferencias (en cuanto a situaciones y capacidades únicas de los individuos) se mezclan lo suficiente como para que la métrica SLOC sea útil para comparar la productividad de herramientas e idiomas.
Si bien no creo que esta afirmación esté respaldada por un riguroso análisis estadístico, ¿hay alguna evidencia en la industria que respalde esta línea de pensamiento?
fuente
Respuestas:
El argumento del arquitecto principal podría significar dos cosas.
Puede significar que un desarrollador promedio en la compañía produce más líneas de código cuando usa lenguajes estáticos que cuando usa lenguajes dinámicos. Por ejemplo, si quince desarrolladores trabajan con Java durante seis meses, escribirán 100 KLOC, y si los mismos quince desarrolladores trabajan con Python durante seis meses, escribirán solo 50 KLOC.
No hay correlación entre LOC y productividad aquí. ¿Qué sucede si se necesitan cuatro veces más líneas de código en Java para producir la misma característica que en Python? Si eso es cierto, el uso de Python daría como resultado el doble de productividad, según las métricas de KLOC anteriores.
También puede significar que un desarrollador promedio en la compañía produce menos líneas de código cuando usa lenguajes estáticos que cuando usa los dinámicos: quince desarrolladores escribirían en seis meses 100 KLOC en Java, o 200 KLOC en Python.
Si bien menos líneas de código suelen ser mejores (menos código para escribir, leer y mantener), todavía no está claro cuántas características produjeron los desarrolladores de Java en comparación con las de Python. ¿Quizás escribieron medias líneas de código en comparación con los desarrolladores de Python, pero también produjeron la mitad de la cantidad de características?
En ambos casos, LOC no es una métrica valiosa, porque la misma característica no se traduciría en la misma cantidad de líneas de código en diferentes idiomas . Algunos idiomas tienden a ser más detallados; otros, más compactos. Si bien en algunos casos, la compacidad es valiosa, no hay una regla general para eso. Un ejemplo extremo sería el lenguaje Brainfuck que tiene una compacidad extrema, pero que no es popular por su legibilidad. Comparar incluso lenguajes similares podría ser complicado: por ejemplo, cuando se trata de llaves, Java sigue el estilo K&R, mientras que en C #, la llave de apertura está en su propia línea en la mayoría de los casos cuando sigue el estilo oficial, lo que lleva a un estilo artificial aumento de LOC para C #. ¿Y qué sucede cuando uno compara un lenguaje de procedimiento con uno orientado a objetos, o con un lenguaje funcional?
En lugar de utilizar una métrica propensa a errores, el arquitecto principal podría confiar en un grupo de métricas que miden la productividad cuando se usan juntas: la cantidad de características desarrolladas por mes, la cantidad de errores introducidos en la base del código y el tiempo dedicado a resolver esos errores , la evolución de la deuda técnica, etc. Esta comparación podría ser complicada al principio, ya que hay que tener en cuenta la falta de familiaridad del equipo con el nuevo lenguaje. Una vez que el equipo se familiarice con él, la elección debe basarse en las métricas estables, así como en la mayor parte en la preferencia de los miembros del equipo.
LOC tiene un valor en algunas situaciones estrechas. Por ejemplo, podría dar una pista sobre el tamaño del proyecto y las partes del proyecto (y en promedio se correlaciona con los puntos de función, aunque a menudo es más fácil de medir), o podría indicar los métodos y clases que pueden necesitar más atención porque de su gran tamaño. Sin embargo, el LOC debe usarse con cuidado, ya que es utilizado con demasiada frecuencia por personas que imaginan alguna correlación entre cosas no relacionadas. En el pasado, el uso más desastroso de los LOC fue el intento de medir la productividad de un desarrollador individual basado en los LOC escritos por mes.
fuente
Sobre productividad y SLOC
El problema con SLOC
El problema con la métrica SLOC es que mide una aproximación de la cantidad de código escrito, sin tener en cuenta:
De lo contrario, la producción de un código de espagueti que no se puede mantener propenso a errores con muchas partes copiadas se considerará más productivo que el código reutilizable diseñado cuidadosamente.
Por lo tanto, SLOC definitivamente no es la mejor manera de medir la productividad.
¿Qué productividad estamos considerando?
La productividad se mide para un proceso. Por lo tanto, SLOC podría ser un indicador perfectamente válido para el proceso de codificación solo.
Si, por ejemplo, no comprende bien los requisitos deficientes, pasa cinco meses para producir el software, se lo muestra al usuario, descubre que está completamente equivocado y pasa otros 5 meses para reescribirlo desde cero, tendría la misma productividad en SLOC / mes, que un equipo escriba el código correctamente la primera vez, por ejemplo, porque usaron un proceso ágil que reduce los malentendidos mediante la retroalimentación frecuente. Esta aparente igual productividad esconde grandes problemas.
Por lo tanto, la medición de la productividad del desarrollo de software debe tener en cuenta todo el proceso, incluido el análisis de requisitos, el diseño de qué codificar, codificar, probar, depurar y verificar que se cumplan las expectativas del usuario. Como todas estas actividades son muy diferentes, lo mejor es medir lo único que importa: el software de trabajo, es decir, lo que el software producido significa para el usuario .
¿Cómo medir los entregables de software?
Existen varios enfoques:
Acerca de la productividad de la escritura estática frente a la dinámica
Tengo que confesar que personalmente soy un fanático de los lenguajes estáticamente tipados, porque en mi interior sé que es más confiable (años de codificación me lo demostraron).
Entonces, una cosa que estoy segura es que el lenguaje de tipo estático puede evitar muchos más errores / errores en el momento de la compilación (por ejemplo, errores tipográficos, falta de coincidencia en los tipos esperados, etc.) que los lenguajes de tipo no estático. Pero con toda objetividad, no me atrevería a generalizar esto abusivamente como una mayor productividad.
¿Tu arquitecto tiene razón?
Tal vez tal vez no.
Pero sus argumentos no parecen válidos: la ganancia de productividad del lenguaje tipado estáticamente proviene de un número significativo de errores que el compilador detecta por adelantado.
En consecuencia, no es posible descubrir esta ganancia de productividad "más alta" mirando SLOC solo sin mirar el reprocesamiento requerido para lenguajes escritos dinámicamente. Entonces su comparación no puede ser justa.
El argumento de circunstancias comparables tampoco es válido. Algunos lenguajes de tipo dinámico permiten algunas construcciones de nivel superior que requieren menos código que hacer lo mismo en uno de los lenguajes clásicos de tipo estático. Por lo tanto, podría necesitar menos tiempo, escribir menos código, pero agregar los mismos gastos generales de análisis, prueba y verificación. Por lo tanto, medir la productividad mediante el SLOC diluiría las ganancias potenciales de productividad, creando así un sesgo contra el lenguaje de tipo dinámico.
¿Algún estudio para apoyar esa afirmación?
Existen varios estudios académicos recientes sobre el tema. Aunque algunos de ellos ven una ventaja de la escritura estática, en general se limita a un propósito específico (documentación, reutilización de código o API mal documentados, etc.). La redacción prudente también se usa porque el IDE moderno ha reducido significativamente los riesgos relacionados con la escritura dinámica:
fuente
Aquí hay un contraejemplo para su arquitecto principal: Suponga que quiero escribir una jerarquía de tres clases, dos de las cuales se derivan de la tercera, implementando algunas funciones virtuales que define la clase base.
Si escribo estas tres clases en C ++, es bastante sencillo. Declaro las clases, uso virtual en los lugares correctos, y listo.
Si escribo estas tres clases en C, necesitaré agregar bastante código: necesito definir
struct
s para las tablas v, necesito agregar un puntero de tabla v a la clase base, necesito agregar código para los constructores para establecer realmente los punteros de la tabla v, necesito agregar código a los constructores para llamar realmente al constructor de la clase base, necesito agregar código para realizar la asignación de memoria explícitamente antes de llamar a un constructor (que C ++new
hace en un solo paso ), del mismo modo, necesito separar la destrucción de lafree()
llamada posterior , y así sucesivamente.El punto es que todas estas cosas adicionales son bastante insensatas. Puedo hacerlos muy rápido. Por lo tanto, no tardaré mucho más en escribir la versión C de lo que necesito para escribir la versión C ++. Sin embargo, he producido muchas más líneas de código C que código C ++. Tanto es así, que parecería haber sido más productivo en C en términos de SLOC.
Cualquier idioma que requiera una cierta cantidad de código repetitivo parecerá más productivo en términos de SLOC que un idioma que no requiera la misma cantidad de código repetitivo.
Verá, el argumento SLOC es tan fundamentalmente defectuoso, que en realidad lo vería al revés: tomaría la afirmación "los programadores tienden a producir más SLOC en lenguajes estáticos" que significa: "parece que los lenguajes estáticos requieren más código repetitivo, y así reducir la productividad ".
fuente
Yo seré el contrario.
Hacemos un seguimiento de SLoC en nuestro trabajo (aunque no lo usamos directamente en las decisiones de personal), y he tenido personas que discuten lo que la mayoría de la gente dice en sus respuestas. En efecto, "LoC no importa porque la tecnología X nos permite hacer más con menos código" o "Mejores desarrolladores escriben mejor, código más corto, por lo que no escriben más que nadie". En mi experiencia (aunque no tengo ningún número difícil para respaldar estas cosas), estas objeciones simplemente no son correctas. En mi propio tiempo, he visto una correlación clara tanto en la velocidad como en la calidad de la producción de código para nuestros desarrolladores, en comparación con todas las otras mediciones significativas de su "competencia" general como ingeniero. Para dar algunos contraejemplos a los tipos de argumentos presentados anteriormente:
Esa última parte es mi resumen general, por cierto. Lo que he encontrado es que, independientemente de la pila tecnológica o el tipo de proyecto, la mayoría de los desarrolladores tienen su propio ritmo, que es el ritmo al que operan. Si un lenguaje tiene muchas características que hacen que el código de los desarrolladores sea más efectivo, entonces eso es una gran ayuda para el negocio, pero eso no significa que escribirán menos código como resultado. En cambio, obtienen funciones más rápidamente y pasan rápidamente a un nuevo código. Una vez más, el resultado final es que la tasa a la que codifican depende principalmente de su habilidad y menos de su pila de tecnología. De hecho, debido a esto, generalmente esperaría que la tecnología apunte más a la velocidad a la que se desarrollan los tickets y las características que a la velocidad a la que las personas codifican.
Dicho esto, ni la tasa de escritura de códigos ni la tasa de cierre de tickets es una medida perfecta de productividad, por lo que no tomamos decisiones de personal directamente sobre la base de SLoC. En cambio, es parte del proceso, y las evaluaciones de los empleados se realizan utilizando tantos puntos de datos como sea posible. Sin embargo, diría que su arquitecto ciertamente no está loco.
Una excepción
La única excepción con la que estoy de acuerdo es la posibilidad del código de placa de caldera. Si hay una gran cantidad de copiar y pegar de una clase (o lo que sea) a otra para ponerlo en funcionamiento, entonces eso obviamente va a sesgar las métricas. Esto también es cierto si tiene herramientas que pueden generar automáticamente grandes cantidades de código para usted. Sin embargo, creo que a menudo serán la excepción y no la regla. Si sus desarrolladores pasan algún tiempo copiando el código de la placa de caldera para comenzar, entonces está utilizando el conjunto de tecnología incorrecto. Si realmente están escribiendo el código, incluso si es bastante repetitivo, entonces espero que esto distorsione cualquier medida solo una pequeña cantidad: al escribir código, la mayoría de las veces estamos limitados por la rapidez con la que podemos pensar en el problema. de lo rápido que podemos escribir. Incluso al escribir código relativamente repetitivo,
Obviamente, todo lo anterior se basa en mi propia experiencia personal. Su kilometraje puede variar, y obviamente estoy en minoría. Siéntase libre de estar en desacuerdo. En resumen, sin embargo:
Creo que la tasa de codificación depende más de la rapidez con la que puede pensar en sus problemas que cualquier otra cosa. Como resultado, descubrí que la tasa de codificación es una medida decente de la productividad, incluso entre conjuntos tecnológicos, con solo algunas excepciones posibles.
fuente
Aunque me estoy subiendo al carro. Creo que hay que destacar el impacto en el comportamiento de los programadores.
El uso de SLOC como medida productiva tiene un efecto tóxico en la moral del programador. En el momento en que cualquier ingeniero de su equipo / empresa se da cuenta de que se miden en SLOC, suceden varias cosas:
No puedo enfatizar lo suficiente lo corrosivo que es diseñar la moral, como lo he visto suceder dos veces en 2 compañías diferentes. Independientemente de los casos de uso aparentemente válidos que tenga para él, sostengo que es poco probable que valga la pena el impacto en su equipo / empresa, incluso si hay una pequeña posibilidad de que se descubra su uso. Aunque en algunos casos puede haber una correlación entre el número de líneas escritas y la cantidad de características útiles, fomenta todos los comportamientos incorrectos en sus programadores y envía el mensaje de que la calidad no es importante.
fuente
Generalmente no se considera una forma válida de medir la productividad. El código más pequeño generalmente es mejor que el código más grande, por lo que un desarrollador más productivo generalmente produce menos código. La productividad tiene su mayor éxito en la depuración; Los desarrolladores eficientes dedican poco tiempo a la depuración.
Los idiomas estáticamente tipados son más productivos (si controla todas las demás diferencias entre idiomas), porque cuando se usan con prudencia, reducen el tiempo de depuración, detectando errores en la fase de compilación, donde son más rápidos de corregir.
fuente
La única métrica que puede usar para comparar la productividad de los desarrolladores entre idiomas es una métrica que no compara el código entre los idiomas. Algunos lenguajes son notoriamente detallados (COBOL para el legado ganador), y otros requieren varios pasos para hacer algo que puede hacer en una línea de código (ensamblado vs. casi todo lo demás). Incluso si compara solo líneas de código activas (es decir, no cuente las declaraciones y solo cuente el código que tiene alguna acción involucrada), aún puede sesgar sus resultados.
Es posible que pueda argumentar a favor de las tasas de cambio. Es decir, se agregaron líneas de código que comparaban la pendiente de la productividad durante el mismo período de tiempo. Sin embargo, eso no tiene en cuenta los cambios negativos en las líneas de código. Por ejemplo, hereda un proyecto que tiene código de copiar y pegar en todas partes. Realiza algunas refactorizaciones rápidas y fáciles para reducir la cantidad de bloques de código repetidos; por definición, tiene una pendiente negativa.
Trabajé en un proyecto donde la infraestructura era muy frágil y las herramientas estaban desactualizadas. El proyecto se creó en Java con una aplicación de página única, pero se alojó en un contenedor de portlet sin ningún beneficio aparente. El tiempo que tardó en hacer incluso cambios simples fue ridículamente largo. Si tuviera que basar todas sus conclusiones en ese proyecto en particular, podría concluir que Java era malo o que las aplicaciones de una sola página eran malas. Tampoco son ciertas. El sistema que se suponía que el feo proyecto debía reemplazar se creó en C # y WebForms. Cuando presentamos el argumento comercial para ampliar la aplicación existente para manejar las necesidades de los clientes, nuestra productividad se disparó. ¿Eso significa que una aplicación de WebForms estrechamente acoplada es superior? Solo puede hacer esa conclusión para este caso particulary no se extiende al mundo en general. Y solo tiene sentido porque había una aplicación existente con madurez suficiente para extenderse.
Incluso comparar las tasas de resolución de elementos en el sistema de seguimiento de problemas es erróneo en el sentido de que está comparando las infraestructuras completas del proyecto entre sí. Las bibliotecas y los marcos utilizados pueden acelerar o ralentizar el progreso. Es posible que se encuentre en la fase de inicio con muy poca inercia que superar, donde el proyecto en el que está "mejor que" se encuentra en una fase de mantenimiento donde el número de tickets nuevos es relativamente bajo. Nunca se trata de comparar cosas similares.
fuente