¿Cómo se mantienen las enormes bibliotecas de código abierto mientras se tiene un código alejado de las prácticas de "código limpio"?

80

Todavía no tengo experiencia para escribir código de alta calidad, así que leí libros que abordan el tema, como Clean Code de Robert C. Martin, y sigo revisando el código de bibliotecas conocidas para mejorar mis habilidades.

Aunque muchas bibliotecas de código abierto se han mantenido durante años, lo que significa que es muy poco probable que no estén en el camino correcto, encontré que el código en muchas de ellas está lejos de los principios abordados para escribir código limpio, por ejemplo, métodos que contienen Cientos de líneas de código.

Entonces mi pregunta es: ¿Están los principios del código limpio demasiado restringidos y podemos prescindir de ellos en muchas bibliotecas como estas? Si no, ¿cómo se mantienen las bibliotecas enormes sin considerar muchos de estos principios?

Agradecería cualquier breve aclaración. Pido disculpas si la pregunta parece ser tonta de un chico novato.

EDITAR

Consulte este ejemplo en la biblioteca Butterknife , una de las bibliotecas más conocidas de la comunidad de Android.

Islam Salah
fuente
71
Estás sufriendo de una muestra sesgada. Dices que compruebas el código de las bibliotecas "conocidas". Bueno, las bibliotecas que colapsaron por su propio peso porque no estaban siguiendo las mejores prácticas no son "bien conocidas", desaparecieron en la oscuridad.
Jörg W Mittag
3
¿Ha verificado, por ejemplo, las fuentes de Linux?
Restablecer a Monica - M. Schröder
55
La medida principal para el valor de una pieza de software no es qué tan "limpio" es el código, sino qué tan bien cumple alguna tarea en particular. Mientras que a algunas personas les gusta escribir software por el simple hecho de escribir algo, para la mayoría de las personas, el código es solo un medio para un fin.
whatsisname
3
Nadie está en desacuerdo contigo. La pregunta es cómo mantener un código pobre durante años. ¿Por qué no se ha limpiado durante tantas iteraciones de evolución?
Islam Salah
13
La premisa de la pregunta (que los proyectos de código abierto mantenidos durante mucho tiempo deben adherirse inherentemente a la noción de mejores prácticas de un autor en particular) es completamente falsa y no sé de dónde la sacó. ¿Podría ampliar la premisa de su pregunta, por favor?
ligereza corre en órbita el

Respuestas:

84

Buena respuesta aquí ya, pero permítanme decir una palabra sobre su ejemplo de navaja : aunque no tengo idea de lo que hace el código, a primera vista, no me parece realmente imposible de mantener. Las variables y los nombres de los métodos parecen elegirse deliberadamente, el código está correctamente sangrado y formateado, tiene algunos comentarios y los métodos largos al menos muestran cierta estructura de bloques.

Sí, de ninguna manera sigue las reglas de "código limpio" del tío Bob, y algunos de los métodos son demasiado largos (probablemente toda la clase). Pero mirando el código todavía veo suficiente estructura para que puedan "limpiarse" fácilmente extrayendo esos bloques en métodos por sí mismos (con un bajo riesgo de introducir errores al usar herramientas de refactorización).

El verdadero problema con dicho código es que agregar un bloque y otro bloque y otro bloque funciona hasta cierto punto, a veces durante años. Pero cada día el código se hace más difícil de evolucionar un poco, y lleva un poco más de tiempo modificarlo y probarlo. Y cuando realmente tiene que cambiar algo que no se puede resolver "agregando otro bloque", pero que requiere reestructuración, entonces deseará que alguien haya comenzado a limpiar el código más temprano.

Doc Brown
fuente
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
yannis
158

Los principios establecidos en el "Código Limpio" no siempre son generalmente acordados. La mayor parte es de sentido común, pero algunas de las opiniones del autor son bastante controvertidas y no son compartidas por todos.

En particular, la preferencia por métodos cortos no está de acuerdo con todos. Si el código en un método más largo no se repite en otro lugar, extraer parte de él en un método separado (para que obtenga varios métodos más cortos) aumenta la complejidad general, ya que estos métodos ahora son visibles para otros métodos que no deberían importarles. Por lo tanto, es una compensación, no una mejora objetiva.

El consejo en el libro también está orientado (como todos los consejos) a un tipo particular de software: aplicaciones empresariales. Otros tipos de software, como los juegos o los sistemas operativos, tienen restricciones diferentes que el software empresarial, por lo que hay diferentes patrones y principios de diseño en juego.

El lenguaje también es un factor: Clean Code asume Java o un lenguaje similar; si usa C o Lisp, muchos de los consejos no se aplican.

En resumen, el libro es una opinión de personas individuales sobre una clase particular de software. No se aplicará en todas partes.

En cuanto a los proyectos de código abierto, la calidad del código varía de abismal a brillante. Después de todo, cualquiera puede publicar su código como código abierto. Pero si observa un proyecto de código abierto maduro y exitoso con múltiples contribuyentes, puede estar bastante seguro de que se han decidido conscientemente por un estilo que les funcione. Si este estilo está en contradicción con alguna opinión o pauta, entonces (para decirlo sin rodeos) es la pauta la que es incorrecta o irrelevante, ya que el código de trabajo prevalece sobre las opiniones.

JacquesB
fuente
18
+1 para "orientado a un tipo particular de software". Esto se puede extender a la mayoría de los libros sobre este y otros temas similares. Tome todo lo que lee con un grano de sal, puede estar sesgado por el momento en que está escrito, el entorno objetivo, la metodología de desarrollo y todo tipo de otros factores.
Reginald Blue
16
Seguir ese libro produce estrictamente lo que muchos llaman "código basura".
Frank Hileman
16
@FrankHileman: siguiendo ninguna de las recomendaciones de ese libro aún más.
Doc Brown
55
@ jpmc26 - Su respuesta vinculada pertenece a un campo con el que estoy íntimamente familiarizado, la programación científica. Recientemente recibí un artículo de la lista de deseos, que consistía en hacer que el modelo gravitacional utilizado en varias simulaciones del Centro Espacial Johnson fuera relativamente correcto. Contando comentarios y líneas en blanco, el código que escribí que calcula la perturbación relativista a la gravedad newtoniana tiene 145 líneas de largo, y todo está en una función. Normalmente me estremecería ver que yo mismo escribí una función que tiene 45 líneas de largo, y mucho menos 145. Pero no en este caso. ...
David Hammen
12
... La función en cuestión implementa una ecuación única, la ecuación X en el diario Y, por lo que definitivamente sigue la regla de un solo propósito. (Que la ecuación cubre un cuarto de página está en los detalles.) No hay un lugar significativo para dividir esta función en partes, y no hay una razón significativa para hacerlo. Los comentarios, ¿qué tío Bob desprecia? Son absolutamente necesarios en este caso, y esto es típico en la programación científica. Si bien es bueno ver las referencias de revistas relevantes en la documentación de TeX del modelo, también es bueno verlas en la implementación.
David Hammen
34

Resumen

Como JacquesB escribe, no todos están de acuerdo con el "Código Limpio" de Robert C. Martin.

Es probable que los proyectos de código abierto que descubriste que "violan" los principios que esperabas simplemente tengan otros principios.

Mi perspectiva

Superviso varias bases de códigos que se adhieren mucho a los principios de Robert C. Martin. Sin embargo, no afirmo realmente que tengan razón , solo puedo decir que funcionan bien para nosotros , y que "nosotros" es de hecho una combinación de al menos

  • El alcance y la arquitectura de nuestros productos,
  • las expectativas del mercado objetivo / cliente,
  • cuánto tiempo se mantienen los productos,
  • la metodología de desarrollo que usamos,
  • la estructura organizativa de nuestra empresa y
  • Los hábitos, opiniones y experiencia pasada de nuestros desarrolladores.

Básicamente, esto se reduce a: cada equipo (ya sea una empresa, un departamento o un proyecto de código abierto) es único. Tendrán diferentes prioridades y diferentes puntos de vista, y por supuesto harán diferentes compensaciones. Estas compensaciones, y el estilo de código que dan como resultado, son en gran medida una cuestión de gustos y no se puede demostrar que sean "incorrectas" o "correctas". Los equipos solo pueden decir "hacemos esto porque funciona para nosotros" o "deberíamos cambiar esto porque no funciona para nosotros".

Dicho esto, creo que para poder mantener con éxito grandes bases de código durante años, cada equipo debe acordar un conjunto de convenciones de código que consideren adecuadas para los aspectos mencionados anteriormente. Eso puede significar adoptar prácticas de Robert C. Martin, de otro autor, o inventar las suyas propias; puede significar escribirlos formalmente o documentarlos "por ejemplo". Pero deberían existir.

Ejemplo

Considere la práctica de "dividir el código de un método largo en varios métodos privados".

Robert C. Martin dice que este estilo permite limitar el contenido de cada método a un nivel de abstracción - como un ejemplo simplificado, un método público probablemente sólo representan todas las llamadas a métodos privados como verifyInput(...), loadDataFromHardDisk(...), transformDataToJson(...)y, por último sendJsonToClient(...), y estos métodos tendría Los detalles de implementación.

  • A algunas personas les gusta esto porque los lectores pueden obtener una visión general rápida de los pasos de alto nivel y pueden elegir sobre qué detalles quieren leer.
  • A algunas personas no les gusta porque cuando quieres conocer todos los detalles, tienes que saltar en la clase para seguir el flujo de ejecución (esto es a lo que JacquesB probablemente se refiere cuando escribe sobre agregar complejidad).

La lección es: todos tienen razón, porque tienen derecho a tener una opinión.

Jens Bannmann
fuente
13

De hecho, muchas bibliotecas de código abierto padecen prácticas de codificación objetivamente pobres y son mantenidas con dificultad por un pequeño grupo de contribuyentes a largo plazo que pueden lidiar con la escasa legibilidad porque están muy familiarizados con las partes del código que mantienen con mayor frecuencia. . Refactorizar el código para mejorar la legibilidad después del hecho es a menudo un esfuerzo hercúleo porque todos necesitan estar en la misma página, no es divertido y no paga porque no se implementan nuevas características.

Como han dicho otros, cualquier libro sobre código limpio que indique algo contiene necesariamente consejos que no están universalmente acordados. En particular, casi cualquier regla puede seguirse con celo excesivo, reemplazando un problema de legibilidad por otro.

Personalmente, evito crear funciones con nombre si no tengo un buen nombre para ellas. Y un buen nombre debe ser corto y describir fielmente lo que la función hace al mundo exterior. Esto también está relacionado con el intento de tener la menor cantidad posible de argumentos de función y sin datos de escritura global. Tratar de reducir una función muy compleja en funciones más pequeñas a menudo da como resultado listas de argumentos muy largas cuando la función era realmente compleja. Crear y mantener un código legible es un ejercicio de equilibrio entre reglas de sentido común mutuamente conflictivas. Leer libros es bueno, pero solo la experiencia le enseñará cómo encontrar falsa complejidad , que es donde se obtienen las ganancias reales de legibilidad.

Kafein
fuente
2
Yo agregaría: simplemente porque algo es de "código abierto" no significa que cualquiera sea un contribuyente. A menudo, muchos proyectos de código abierto son mantenidos por camarillas, para bien o para mal, que aíslan su proyecto de otros contribuyentes, y, a menos que se bifurque, nadie más contribuye. Si no se bifurca, ya sea porque nadie necesita modificarlo o porque nadie puede entender cómo hacerlo, entonces el estilo convencional del código probablemente no cambiará.
can-ned_food
7

La mayoría de los proyectos de código abierto están mal administrados. Obviamente, hay excepciones a eso, pero encontrará mucha basura en el mundo de código abierto.

Esta no es una crítica de todos los propietarios / gerentes de proyectos de los que estoy hablando, es simplemente una cuestión de tiempo utilizado. Estas personas tienen mejores cosas que hacer con su tiempo, como su trabajo remunerado real.

Al principio, el código es el trabajo de una persona y probablemente sea pequeño. Y el código pequeño no necesita estar limpio. O más bien, el esfuerzo necesario para limpiar el código es mayor que el beneficio.

A medida que pasa el tiempo, el código es más un montón de parches de muchas personas diferentes. Los redactores de parches no sienten la propiedad del código, solo quieren que se agregue esta característica o que se solucione este error de la manera más fácil posible.

El propietario no tiene tiempo para limpiar las cosas y a nadie más le importa.

Y el código se está haciendo grande. Y feo.

A medida que se vuelve cada vez más difícil encontrar el código, las personas comienzan a agregar funciones en el lugar equivocado. Y en lugar de corregir errores, agregan soluciones a otros lugares en el código.

En este punto no es solo que a las personas no les importa, ya no se atreven a limpiar ya que tienen miedo de romper cosas.

He tenido personas que describen las bases del código como "castigo cruel e inusual".

Mis experiencias personales no son tan malas, pero he visto algunas cosas muy extrañas.

Stig Hemmer
fuente
23
Si elimina las palabras "abrir" y "fuente" en esta respuesta, seguirá siendo igual de cierto.
Stephen M. Webb
Yo diría que esto es igualmente cierto para el software de código cerrado.
Mark Rotteveel
3

Me parece que me preguntas cómo funcionan estas cosas si nadie hace lo que se supone que debe hacer. Y si funciona, ¿por qué se supone que debemos estar haciendo estas cosas ?

La respuesta, en mi humilde opinión, es que funciona "lo suficientemente bueno" , también conocida como la filosofía " peor es mejor " . Básicamente, a pesar de la historia rocosa entre el código abierto y Bill Gates, ambos adoptaron de hecho la misma idea, que a la mayoría de las personas les importan las características, no los errores .

Por supuesto, esto también nos lleva a la " normalización de la desviación " que lleva a situaciones como heartbleed , donde, precisamente, como si para responder a su pregunta, una masiva cubierto pila de espagueti de código fuente abierto llamado OpenSSL fue " sin limpiar " para algo así como diez años , terminando con una falla de seguridad masiva que afecta a miles de millones de personas .

La solución fue inventar un sistema completamente nuevo llamado LibreSSL , que iba a usar código limpio y , por supuesto, casi nadie lo usa .

Entonces, ¿cómo se mantienen los grandes proyectos de código abierto mal codificados? La respuesta está en la pregunta. Muchos de ellos no se mantienen limpios. Son parcheados al azar por miles de personas diferentes para cubrir casos de uso en varias máquinas extrañas y situaciones en las que los desarrolladores nunca tendrán acceso para probar. El código funciona "suficientemente bien" hasta que no funciona , cuando todos entran en pánico y deciden tirar dinero al problema .

Entonces, ¿por qué molestarse en hacer algo "de la manera correcta " si nadie más lo hace?

La respuesta es que no deberías. O lo haces o no , y el mundo sigue girando independientemente, porque la naturaleza humana no cambia en la escala de la vida humana . Personalmente, solo trato de escribir código limpio porque me gusta cómo se siente al hacerlo.

don brillante
fuente
1
Tantos enlaces ... a primera vista, pensé que esta respuesta podría haber sido mezclada con publicidad flotante o que era una página de Wikipedia.
Jonny Henly
2

Lo que constituye un buen código depende del contexto, y los libros clásicos que lo guían son, si no demasiado viejos para hablar de código abierto, al menos parte de una tradición que libra la guerra interminable contra las bases de códigos internas malas. Por lo tanto, es fácil pasar por alto el hecho de que las bibliotecas tienen objetivos completamente diferentes, y están escritas en consecuencia. Considere los siguientes problemas, sin ningún orden en particular:

  • Cuando importo una biblioteca, o desde una biblioteca, probablemente no soy lo suficientemente experto en su estructura interna para saber exactamente qué pequeña fracción de su kit de herramientas necesito para lo que sea que esté trabajando, a menos que esté copiando La respuesta de Stack Exchange me dijo que hiciera. Así que empiezo a escribir from A import(si está en Python, por ejemplo) y veo qué aparece. Pero eso significa que lo que veo en la lista debe reflejar las tareas lógicas que tendré que pedir prestado, y eso es lo que tiene que estar en la base de código. Innumerables métodos de ayuda que lo hacen más corto me confundirán.
  • Las bibliotecas están ahí para el programador más inexperto que intenta usar algún algoritmo del que la mayoría de la gente solo ha oído hablar vagamente. Necesitan documentación externa, y eso debe reflejar con precisión el código, lo que no puede hacer si seguimos refactorizando todo para hacer felices a los adherentes de método corto y hacer una cosa.
  • Cada método de biblioteca que la gente toma prestada podría romper el código en todo el mundo con consecuencias desastrosas si se elimina o incluso se renombra. Claro, desearía que sklearn corrigiera el error tipográfico en Calinski-Harabasz , pero eso podría causar otro incidente en la plataforma izquierda . De hecho, en mi experiencia, el mayor problema con la evolución de la biblioteca es cuando se esfuerzan demasiado por adoptar una nueva "mejora" de buen código para estructurar todo.
  • Los comentarios internos son en gran medida un mal necesario en el mejor de los casos, por todo tipo de razones que no necesito regurgitar (aunque esos puntos exageran un poco). Un buen comentario dice por qué funciona el código, no cómo. Pero las bibliotecas saben que sus lectores son programadores competentes que no podrían, por ejemplo, escribir álgebra lineal para salir de una bolsa de papel. En otras palabras, todo necesita comentarios sobre: ​​¡por qué funciona! (OK, esa es otra exageración). Entonces, es por eso que ves una línea de firma, un bloque de comentarios de 100 líneas, 1 línea de código que literalmente podría haber ido a la línea de la firma (si el idioma lo permite, por supuesto).
  • Supongamos que actualiza algo en Github y espera para ver si su código será aceptado. Debe quedar claro por qué funciona el cambio de código. Sé por experiencia que la refactorización para hacer que el campamento esté más limpio como parte de un compromiso funcional a menudo significa mucho ahorro de línea, reordenamiento y cambio de nombre, lo que dificulta el trabajo de su revisor sin salario y causa otros problemas antes mencionados.

Estoy seguro de que las personas con más experiencia que yo pueden mencionar otros puntos.

JG
fuente
Sobre la primera viñeta. Por eso tienes métodos públicos / privados. Expone una API pública que internamente llama métodos privados o internos. La segunda viñeta también es inexacta. No veo ninguna razón por la que no pueda tener documentación sobre un método público corto y luego llamar a muchos pequeños.
FCin
@FCin Ese es un enfoque viable, siempre y cuando los mantenedores recuerden usar siempre la palabra clave correcta frente a cada método a medida que van y vienen. O simplemente podrían hacer algo más fácil y menos propenso a errores.
JG
En lenguajes como C #, Java (del que suele hablar el tío Bob), los modificadores de acceso son la herramienta más básica utilizada para escribir cualquier código realmente. Usar la palabra clave correcta es parte de escribir cualquier código.
FCin
@FCin Se hacen explícitos con menos frecuencia en algunos otros lenguajes, pero he trabajado incluso en bases de código internas de C # donde las personas no necesariamente usaban los modificadores que deberían tener.
JG
Es por eso que deberían leer el libro del tío Bob :)
FCen
2

Ya hay muchas buenas respuestas: quiero dar la perspectiva de un mantenedor de código abierto.

Mi perspectiva

Soy el mantenedor de muchos de estos proyectos con un código menos que excelente. En algún momento, incluso se me impide mejorar dicho código debido a problemas de compatibilidad, ya que las bibliotecas se descargan millones de veces cada semana.

Hace que el mantenimiento sea más difícil: como miembro principal de Node.js, hay partes del código que me temo que debo tocar, pero hay mucho trabajo por hacer independientemente y las personas usan la plataforma con éxito y la disfrutan. Lo más importante es que funciona.

En código legible

Cuando tu dices:

Encontré que el código en muchos de ellos está lejos de los principios dirigidos a escribir código limpio, por ejemplo, métodos que contienen cientos de líneas de código.

Las líneas de código no son una gran medida de lo legible que es. En el estudio que vinculé con el kernel de Linux se analizó y una encuesta de programadores encontró un código "regular" (código que la gente espera básicamente) y un código consistente mejor que el código "limpio" en la comprensión. Esto también se alinea con mi experiencia personal.

Algunos proyectos de código abierto no son muy acogedores

Linus "famoso" dijo que Linux no debería tener un depurador incorporado porque las personas que usan depuradores no son lo suficientemente buenas como para trabajar en Linux y no quiere atraer a más de ellos.

Personalmente, estoy totalmente en desacuerdo con su postura allí, pero también es algo que la gente hace.

Benjamin Gruenbaum
fuente
1

El software de código abierto no significa necesariamente que haya varios autores involucrados. Cuando un software (o unidad de software) está escrito por un solo autor, las funciones largas aparecen con frecuencia.

Esto proviene de la naturaleza del proceso de desarrollo. Un método simple se extiende con el tiempo, se agregan nuevas características y se corrigen errores.

Los métodos largos reducen severamente la comprensión de la funcionalidad para nuevos autores. Sin embargo, con un solo autor esto rara vez es un problema y el problema tiende a pasarse por alto. Otra naturaleza del código abierto es el hecho de que una gran cantidad de software no se desarrolla activamente, por lo tanto, no hay trabajo de refactorización que, por ejemplo, divida los métodos complejos en múltiples métodos simples.

No ha mostrado ningún ejemplo, pero, según tengo entendido, esto a menudo también está relacionado con el lenguaje de desarrollo. Algunos idiomas aplican reglas estrictas de linting desde el principio y pruebas de unidades pesadas (o incluso TDD). Tanto las pruebas de linting como las de unidad generalmente evitan ese problema (es difícil probar de manera unitaria los métodos complejos / largos).

En general, es más difícil limpiar el código si el software es desarrollado por un solo autor y otros colaboradores solo solucionan problemas pequeños.

Sulthan
fuente