hginit - #ifdefs ridículo


8

Estaba leyendo la introducción mercurial de Joel Spolsky cuando me llamó la atención:

"Y ahora lo que hacen es esto: cada nueva característica está en un gran bloque #ifdef. Para que puedan trabajar en una sola troncal, mientras que los clientes nunca ven el nuevo código hasta que se depure, y francamente, eso es ridículo".

¿Por qué es esto tan ridículo de todos modos, no es esto, si nada más, simplemente más fácil de manejar? No es nada lujoso, pero hace el truco, al menos si ya estás "casado" con subversión.

¿Cuál es el inconveniente? Como que no entiendo el argumento.


no es ridículo cuando solo tienes uno o dos interruptores, pero he tenido que lidiar con enormes cadenas de grupos de ifdefs extrañamente interconectados y es una abominación tratar de comprender, y si tuvieras que lidiar con eso, también lo encuentra ridículo. ¿Crees que el código de plantilla de impulso complicado es difícil de leer ...
Cuál es el nombre del

Respuestas:


20

Creo que la respuesta se da en la siguiente oración:

Mantener el código estable y el de desarrollo separado es precisamente lo que se supone que el control del código fuente te permite hacer.

Al usar #ifdefbloques, está emulando la funcionalidad de un sistema de control de fuente con un preprocesador C. Es la herramienta incorrecta para el trabajo.

La desventaja es que probablemente termines duplicando una gran cantidad de código (piensa en las definiciones de funciones completas una vez dentro, una vez fuera de ellas #ifdef) o tienes un código ilegible (piensa en las #ifdeflíneas individuales que encierran una función, posiblemente repetidamente).

En la primera variante terminas arreglando errores dos veces (lo que no sería necesario si pudieras fusionar las correcciones de errores de la rama estable a la rama de desarrollo), mientras que en la segunda el objetivo original de separar las ramas estable y de desarrollo no se logró realmente .


2
+1: En los años 80 tuve un depurador que funcionaba en casi cualquier sistema UNIX que se te ocurra. Antes de la versión 4, el código estaba inundado #ifdefs. Juro que me hizo sangrar los ojos con solo mirarlo. Para la versión 4, fui a una arquitectura conectable usando archivos separados, y también comencé a usar RCS (¿o era SCCS?). La vida mejoró enormemente y las nuevas características fueron mucho más fáciles de desarrollar. (Pero chico, ¿alguna vez desearía tener git o hg en esos días?)
Peter Rowell el

¡Sé el infierno #ifdef por experiencia! Estoy de acuerdo en que debe evitarse como reemplazo del control de versiones.
Giorgio

3

Habiendo mantenido un código que era un nido de ratas de #ifdefs (aunque por diferentes razones), es ridículo; hace que el código sea mucho más difícil de leer y mucho más difícil de mantener, especialmente cuando se prueba en múltiples condiciones.


Sí, yo también hice esto y fue horrible.
desvío

1

Se supone que todo el código nuevo se puede escribir sin tocar el código existente. A menudo, la única forma de hacerlo es repitiéndote mucho. (un nuevo método para uno que es similar pero no exactamente el mismo, por ejemplo).

Una de las principales ventajas de VCS distribuido es que alienta al equipo a trabajar en su propia rama de características y no preocuparse de que su trabajo entre en conflicto con los demás. Esta estrategia niega esa ventaja.

A mí me parece ridículo, ya que parecen estar haciendo mal uso deliberado de las herramientas. Si va a hacer el cambio, seguramente vale la pena aprender a usarlos.


3
esto no se limita a DVCS
James

No, no asume eso. Incluso con lugares estratégicamente #ifdefs, puede tocar el código existente pero dejar intacta la versión anterior en un #else.
tdammers

1

#ifdefEl código ed no es ridículo, pero es triste y terrible. Y es (hoy) el diagnóstico para el desarrollador

Bueno, Joel seleccionó en "Subversion Re-education" The Bad Way (tm) de argumentación: creó una situación especial y degenerada con usuarios especialmente seleccionados y utilizó este caso de uso como justificación para la tesis "Subversion suxx"

El código de espagueti suxx más, el código inmanejable e ilegible es más peligroso, que pasar algún tiempo reeducando la "Fusión correcta" en Subversion - "¡Fusiona a menudo, imbéciles!" La fusión ramificada y bidireccional era posible y utilizable en Subversion <1.5, ahora (después de introducir mergeinfo) la fusión se volvió aún más fácil y cómoda . Una pequeña sobrecarga de monitoreo de árboles "interesantes" y fusiones de sincronización (a menudo !!!) es un precio justo para el desarrollador, que a cambio obtiene un código compacto, limpio y depurable.


1

Lo que está describiendo es en realidad un FeatureToggle , y puede haber buenas razones para usarlo en lugar de ramas de características. El problema es con el uso #ifdef. Sin una muy buena administración, pueden convertirse fácilmente en un gran desastre en toda la base de código.

Considera lo siguiente:

  1. ¿Cuándo eliminas un #ifdef? - ¿Está seguro de que no quedan compilaciones que aún excluyan esa característica? ¿Tampoco para ese cliente (bien pagado) para quien haces algunas compilaciones especiales?
  2. ¿Quién es responsable de eliminar el #ifdef? - ¿El desarrollador que hizo la función? ¿Estás seguro de que recordará 4 semanas más adelante para verificar que el interruptor no esté excluido en ninguna construcción y pueda retirarse de manera segura? ¿Estará seguro de que es seguro eliminar el #ifdef? ¿Qué pasa con esa otra tarea extremadamente urgente, no tiene prioridad sobre eliminar una miserable #ifdef?

Mi experiencia dice que tales #ifdefs estarán por siempre tirando basura.


1

Por experiencia (en un proyecto grande en una base de código de más de 600,000 líneas, que se mantuvo fuera de lanzamientos durante 3 años usando #ifdefs), mis argumentos en contra de usarlos serían:

  • Reducen la legibilidad del código, especialmente porque algunos IDE insisten en colocarlos al comienzo de la línea, ignorando el nivel de sangría.
  • Añaden complejidad, tanto a los desarrolladores que trabajan en la función segregada como a los desarrolladores que intentan solucionarlos.
  • Esa complejidad adicional ralentiza la productividad; en nuestro caso, estoy convencido de que agregó varios meses al proyecto.
  • Eliminarlos una vez que se lanza la función no es una tarea de costo cero; en nuestro caso, fue una tarea de una semana para que alguien revise y elimine todos los #ifdefmensajes de correo electrónico y resuelva los conflictos con el código que se agregó en #elseifs.

En general, fue un día glorioso cuando migramos a Mercurial: todavía tenemos una base de código enorme y demasiado compleja, pero al menos ahora podemos ramificar de manera eficiente.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.