¿Cuál es el equilibrio correcto entre la consistencia del código y la mejora del código?

52

Recientemente tuve una discusión con un colega sobre el estilo del código. Estaba argumentando que su uso de las API y los patrones generales que está utilizando deberían ser lo más similares posible al código circundante, si no al conjunto de códigos, como lo haría con la apariencia del código (posicionamiento de llaves, mayúsculas, etc.) . Por ejemplo, si estuviera agregando un método a una clase DAO en C #, intentaría usar LINQ cuando sea apropiado para ayudar a que mi código esté limpio y sea fácil de mantener, incluso si ninguno de los otros métodos en esa clase lo estuviera usando. Sin embargo, mi colega argumentaría que no debería usarlo en esa instancia porque estaría en contra del estilo existente de esa clase y, por lo tanto, sería más difícil de entender.

Al principio encontré su posición bastante extrema, pero después de pensarlo un poco, comienzo a ver su punto. Con el ejemplo hipotético de LINQ, ¿quizás esta clase no lo contiene porque mis colegas no están familiarizados con LINQ? Si es así, ¿no sería más fácil mantener mi código para mis colegas desarrolladores si no lo usara? Por otro lado, si realmente creo que usar una técnica de este tipo resultaría en un código más limpio, ¿no debería usarlo incluso si difiere drásticamente del código circundante?

Creo que lo esencial del argumento de mi colega es que si todos implementamos una funcionalidad similar en una base de código de diferentes maneras, y cada uno de nosotros piensa que nuestra forma es "la mejor", entonces al final el código en su totalidad Simplemente se vuelve más difícil de entender. Sin embargo, en este momento sigo pensando que si seguimos ciegamente el código existente demasiado, la calidad se irá ralentizando con el tiempo.

Entonces, ¿en qué medida los patrones forman parte del estilo del código y dónde debemos trazar la línea entre mantenernos constantes y realizar mejoras?

    
pregunta Robert Johnson 15.03.2013 - 08:55

9 respuestas

53

Para dar una respuesta más general:

En un caso como este, tiene dos "mejores prácticas" de programación que se oponen entre sí: la coherencia del código es importante, pero también lo es elegir el mejor método posible para realizar su tarea. No hay una respuesta correcta a este dilema; Depende de un par de factores:

  • ¿Qué tan beneficiosa es la forma "correcta"?

    • A veces, las nuevas y mejores prácticas recomendadas aumentarán dramáticamente el rendimiento, eliminarán errores, serán mucho más fáciles de programar, etc. En ese caso, me inclinaría por utilizar el nuevo método. Por otra parte , la "forma correcta" puede ser poco más que el azúcar sintáctica, o un método idiomático acordado para hacer algo que no es realmente superior. En ese caso, la coherencia del código es probablemente más importante.
  • ¿Qué tan grande sería la incoherencia de un problema?

    • ¿Qué tan interconectado está el nuevo código con el código heredado? ¿Es tu nuevo código parte de una biblioteca? ¿Crea un objeto que se pasa a muchas partes del programa? En casos como estos, la consistencia es muy importante. El uso de una nueva API, o una nueva forma de hacer las cosas en general, puede crear resultados sutilmente diferentes que rompan los supuestos en otras partes de su programa. Por otra parte, , si está escribiendo un fragmento de código bastante aislado, es menos probable que la inconsistencia sea un problema.
    • ¿Qué tan grande y qué tan maduro es su código base? ¿Cuántos desarrolladores necesitan entenderlo y trabajar en ello? Los estándares acordados y consistentes son mucho más importantes para proyectos más grandes.
    • ¿Es necesario que el código se ejecute en entornos más antiguos que pueden no ser compatibles con las funciones más recientes?

En función del balance de estos problemas, debe tomar la decisión correcta sobre qué ruta tomar. Personalmente veo poco valor en la consistencia por el bien de la coherencia, y preferiría usar los mejores y más recientes métodos a menos que haya un costo significativo para hacerlo.

Por supuesto, hay una tercera opción: reescribir el código existente para que use los mejores métodos y sea consistente. Hay ocasiones en que esto es necesario, pero conlleva un alto costo.

    
respondido por el user82096 15.03.2013 - 10:17
26

Mantener la coherencia tiene poco valor en mi perspectiva; Hacer mejoras continuamente es una necesidad.

La posición de su colega realmente impide la innovación. El argumento de consistencia lo lleva a una situación en la que puede usar, por ejemplo, LINQ solo si migra el código all para usar LINQ. Y bueno, no tenemos tiempo para esto, ¿verdad?

Prefiero tener inconsistencias donde algunos códigos aún están haciendo foreach sobre ArrayLists y otras partes usan LINQ en IEnumerable<T> , en lugar de seguir la forma más antigua de hacer las cosas hasta el final de los tiempos.

Es responsabilidad de sus colegas mantenerse relevante y aprender nuevas formas de hacer las cosas.

    
respondido por el Joppe 15.03.2013 - 09:59
8

La consistencia de la API es muy importante, tanto para las API públicas como para las internas.

La consistencia del formato de código es importante, y lo ideal es que se aplique mediante una herramienta de formato automático con las mismas reglas de formato para todos. Hace que vivir con una base de código controlada por versión compartida sea más fácil.

Las convenciones de nomenclatura deben ser coherentes, también para cosas como variables locales, etc.

Las herramientas de análisis estático se deben utilizar para imponer otras convenciones y buenas prácticas (pero no sigas ciegamente los valores predeterminados de ninguna herramienta de este tipo, los valores predeterminados pueden a veces ser insanos), aunque si algo lo exige, no temas. para desactivar temporalmente algunas verificaciones (generalmente con una directiva dentro de un comentario), si puede justificarlo.

Lo que sucede dentro de las funciones / métodos , aparte de lo que se menciona anteriormente, no tiene por qué ser coherente de ninguna manera, siempre y cuando sea un buen código por sí solo . Bien, comprensible, well comentó el código es muy importante, pero después de eso, si el compilador y las herramientas de análisis estático creen que es un código consistente, es lo suficientemente consistente.

Acerca de las nuevas características de idioma como LINQ (bueno, eso no es exactamente nuevo), lo único que debe considerarse es si habrá una nueva versión suficiente de idioma / bibliotecas en uso everywhere se utilizará el código? En caso de duda, apéguese a las características que se sabe que son compatibles. Por supuesto, esto no le impide impulsar una actualización de la versión en todo el sistema, por lo que puede comenzar a usar las nuevas cosas agradables.

Y todos los desarrolladores que trabajan con código deben mantenerse actualizados, por lo que cualquier desarrollador de .NET debe conocer LINQ, y si no lo hacen, deben verse obligados a aprender, por su propio bien (nunca se sabe cuándo buscará para un nuevo trabajo en este negocio, por una razón u otra).

    
respondido por el hyde 15.03.2013 - 09:20
5

La respuesta a esto es simple.

La consistencia es de suma importancia.

pero viene con una advertencia ...

Es probable que tú y tu compañero de trabajo estén obsesionados con el tipo de consistencia incorrecto

Las implementaciones son desechables. Se pueden revisar por completo con diversos grados de facilidad, dependiendo de la calidad y la amplitud del conjunto de pruebas. Preocupándose por cosas como "¿Debería ser esto una propiedad?", "¿No debería el código delgado usar LINQ en lugar de una construcción de nivel inferior?" Es de dudoso valor. Es muy difícil vincular las mediciones al valor de la consistencia en el nivel de implementación. Una pregunta mucho mejor que hacer en este nivel es "¿Funciona este código como se anuncia?". La consistencia de la implementación de TL; DR es donde las "pequeñas mentes" tienen su hobgoblin.

¿Por qué la consistencia no es tan importante aquí? Las implementaciones suelen tener un pequeño número de contribuyentes. La mayoría de los métodos están escritos y nunca se vuelven a tocar. Del código restante, el número de métodos que tienen dos contribuyentes es casi seguro que la mayoría. Este patrón continúa ad infinitum . En este contexto, la coherencia no es tan importante. Si la vida útil del código es bastante pequeña ( unos pocos años ), las ganancias de la consistencia agresiva probablemente no sean un factor importante.

Esto no quiere decir que debas volverte loco en tus implementaciones. Más bien, es decir que un diseño agradable, limpio y simple será órdenes de magnitud más valioso para su hipotético mantenedor futuro que el método tonto de consistencia de placa de caldera por método. Esto nos lleva al punto real ...

Las API no son desechables.

Se trata de todos los niveles de código de API, servicios web, SDK, etc. Estos deben, deben, DEBEN ser coherentes. Las ganancias de productividad de esta variedad de consistencia son enormes por varias razones:

Pruebas de integración:

Si mantiene su API consistente, puede crear conjuntos de pruebas de integración. Esto permite a los desarrolladores intercambiar libremente los detalles de la implementación y lograr una validación inmediata. ¿Quieres cambiar tu mierda de compañeros de trabajo a LINQ? ¿Se ejecutan las pruebas de integración? También proporciona validación cuando se prepara para ir a producción. Debido a que las computadoras son rápidas, una sola computadora portátil puede realizar el trabajo de mil probadores que ejecutan tareas mundanas. Es equivalente a aumentar considerablemente el número de empleados de su organización.

Productividad

Cuando las API son consistentes, puedes hacer conjeturas sobre cómo usar una API simplemente siguiendo lo que has aprendido sobre el uso de otras partes de la API. Esto se debe a que la API ofrece una "apariencia" natural y coherente. Significa que su cliente dedica menos tiempo a revisar la documentación. La incorporación es más fácil y más barata. Se hacen menos preguntas a las personas que desarrollaron la API. La consistencia hace que todos sean ganadores

¿Por qué es importante la coherencia en este escenario? Porque las API tienen exactamente el problema opuesto de las implementaciones. El número de personas que los utilizan suele ser mucho mayor que el número de personas que contribuyen a sus implementaciones. Se multiplican las pequeñas ganancias de una pequeña consistencia y se amortizan los costos de mantener esa consistencia.

Conclusión

La consistencia es costosa. En su cara disminuye la productividad. Limita a los desarrolladores y les hace la vida más difícil. Coloca limitaciones en las formas en que pueden resolver un problema, a veces obligándolos a resolverlo de una manera no óptima. A menudo, esto se debe a razones que no comprenden, están mal concebidas o no están al tanto de (contratos, políticas organizativas más grandes o políticas interorganizacionales).

Raymond Hettinger hizo algunos puntos excelentes en su charla sobre Pycon 2015 con respecto al uso de la guía de estilo PEP8 para los equipos de programadores de Python. Demostró que la obsesión por la coherencia estilística en una pieza de código hizo que los revisores de códigos no entendieran la lógica seria y los defectos de diseño. Su hipótesis puede resumirse ya que es fácil encontrar inconsistencias estilísticas; determinar la calidad real de una pieza de código es difícil

El punto aquí es crítico. Identifique dónde es importante la consistencia y protéjala agresivamente. Donde no es importante no pierdas tu tiempo. Si no puede proporcionar una manera objetiva de medir el valor de la consistencia (en los casos anteriores, "personal efectivo", costo en función de la productividad) y no puede demostrar que los rendimientos son sustanciales, entonces es probable que esté haciendo un mal servicio. su organización.

    
respondido por el nsfyn55 02.05.2015 - 16:03
4
  

¿No estás familiarizado con LINQ? Si es así, ¿no sería más fácil mantener mi código para mis colegas desarrolladores si no lo usara?

El lenguaje C # todavía está evolucionando. Si las personas no aprendieran los cambios de C # 1, se estarían perdiendo:

  • Genéricos
  • parciales
  • métodos anónimos
  • iteradores
  • tipos anulables
  • Propiedades automáticas
  • tipos anónimos
  • Métodos de extensión
  • Ling
  • Lambdas
  • Métodos asíncronos

Esto es solo una pequeña selección de características comunes que se encuentran en el artículo de Wikipedia. El punto que estoy haciendo es que si los desarrolladores no aprenden, el código base se quedará en un vacío. Uno esperaría que sus desarrolladores mejoren continuamente y la base de código evolucione, con el respaldo de un conjunto de pruebas completo. ¿Recuerdas lo malo que era con .NET 1 para implementar las propiedades manualmente?

Linq hace la vida más fácil. Úsalo donde puedas. Podría motivar a los miembros de su equipo.

  

Entonces, ¿en qué medida los patrones forman parte del estilo del código y dónde debemos trazar la línea entre mantenernos constantes y realizar mejoras?

Las mejoras son graduales. Para mí, no tiene sentido mantener un código de estilo antiguo que sea menos legible y potencialmente menos mantenible. Los miembros de su equipo deberían al menos poder averiguar qué está pasando, incluso si no pueden escribirlo.

    
respondido por el Sam 15.03.2013 - 09:18
3

Debes ser consistente, pero no necesariamente con el código antiguo. Es decir, su equipo debe ponerse de acuerdo sobre la forma correcta de hacer algo y usarlo cada vez que se escriba un nuevo código o se realicen cambios sustanciales.

De esa manera, usted obtiene la mayoría de los beneficios de la consistencia (en particular, no importará quién escriba el código), pero aún puede mejorar si el equipo ve un beneficio claro al hacer las cosas de otra manera.

En un mundo ideal, reescribiríamos todos los códigos antiguos para adaptarnos a la nueva forma correcta. Si bien esto no es económicamente viable, debería tener sentido técnico (o de lo contrario, la nueva forma no es la mejor), y su plan a largo plazo debería ser actualizarlo. Si eso no vale la pena, no te molestes con la nueva forma. Dicho de otra manera, debe haber una clara ventaja en la nueva forma de considerar declararla como la correcta.

    
respondido por el meriton 15.03.2013 - 14:10
1

Creo que es importante seguir un código estilo en un proyecto, por ejemplo. convenciones de nomenclatura, sangrías, etc.

No estoy de acuerdo con que deba limitarse al uso de nuevas construcciones de lenguaje o patrones de diseño simplemente porque sus colegas no los entienden o porque no se han utilizado en el proyecto anteriormente.

Por supuesto, estas cosas deben tener buenas razones para usarlas, por ejemplo. rendimiento o brevedad, si corresponde.

    
respondido por el ozz 15.03.2013 - 11:20
0

Tendría mucho cuidado a ciegas siguiendo los patrones de diseño actuales. Por supuesto, cuando no hay un inconveniente apreciable, siempre se debe intentar seguir patrones similares en la base del código.

Sin embargo, es demasiado fácil entrar en circunstancias en las que la mayoría de los desarrolladores sienten que es una "práctica recomendada" seguir los malos patrones existentes que conducen a situaciones en las que los desarrolladores buenos están escribiendo código incorrecto e inigualable.

Por otro lado, la consistencia es importante. Cuando se trata de bases de código enormes, es extremadamente útil intentar seguir patrones similares para que, aunque los desarrolladores no hayan leído cada pulgada de la base de código, sepan qué esperar.

Por lo tanto, creo que es mejor establecer y actualizar pautas sobre los patrones que los desarrolladores deben seguir si pueden. De esta manera, cualquier código nuevo es consistente con otro código nuevo.

    
respondido por el user606723 15.03.2013 - 19:16
-1

Tenemos reuniones técnicas regulares, bastante informales, que cualquiera de nosotros puede organizar. Si encontramos una nueva técnica la presentamos en la reunión. En general, tiene una buena idea de qué tan bien la idea es aceptada y entendida por sus colegas. Esto le ayuda a decidir si es aconsejable incluirlo en su código, ayuda a otros a descifrarlo si lo hace y también establece a la persona 'ir a' si otros necesitan ayuda con ese estilo. Si nadie reinventara la rueda, todavía estaríamos arrastrando cosas alrededor de los registros.

    
respondido por el Ant 15.03.2013 - 17:26

Lea otras preguntas en las etiquetas