Evitar la compilación de código obsoleto después de llegar a una fecha límite [cerrado]

68

En mi equipo hemos estado limpiando muchas cosas viejas en un gran proyecto monolítico (clases completas, métodos, etc.).

Durante esas tareas de limpieza, me preguntaba si hay algún tipo de anotación o biblioteca más elegante que la habitual @Deprecated. Esto @FancyDeprecateddebería evitar que la compilación del proyecto tenga éxito si no ha limpiado el código antiguo no utilizado después de que haya pasado una fecha en particular.

He estado buscando en Internet y no encontré nada que tenga las capacidades que se describen a continuación:

  • debe ser una anotación, o algo similar, para colocar en el código que está destinado a eliminar antes de una fecha en particular
  • antes de esa fecha, el código se compilará y todo funcionará normalmente
  • después de esa fecha, el código no se compilará y le dará un mensaje advirtiéndole sobre el problema

Creo que estoy buscando un unicornio ... ¿Existe alguna tecnología similar para algún lenguaje de programa?

Como plan, estoy pensando en la posibilidad de hacer la magia con algunas pruebas unitarias del código que se pretende eliminar que comienzan a fallar en la "fecha límite". ¿Qué piensas sobre esto? ¿Alguna mejor idea?

Arcones
fuente
168
La desaprobación se realiza para una versión , no una fecha . Si desea que las personas dejen de usar funciones obsoletas, publique una versión sin ellas. Eso llamará su atención, y siempre pueden retroceder si aún no pueden hacerlo. Mucha gente está atrapada en versiones antiguas. Romper su programa no es el camino a seguir.
isanae
44
El plan B suena sólido. Con las ventajas adicionales que puede poner comentarios en la prueba unitaria de por qué está en desuso. Agregar el comentario al código fuente no ayudaría a la legibilidad en un gran monolito
dwana
53
Eso suena como un unicornio realmente malvado. Tiene un poco de software que se compila bien, pasa todas las pruebas y lo ha enviado a un cliente. Entonces, un día, revisa el software nuevamente y no se compilará, incluso en la misma plataforma de desarrollo. Ahora se ve obligado a modificar el código que previamente pasó las pruebas formales, o hacer ataques malvados como retroceder el reloj de la computadora.
Simon B
66
Hágalo @ Deprecated_RemoveMe_2018_06_01 y luego, en 2018-06-01, elimine la anotación en sí. ¡Voila, todo tu código usando la anotación ya no se compilará! (porque no se encuentra la anotación)
usuario253751
65
Años después, un desarrollador recién contratado preguntará: ¿por qué el tiempo en el servidor de compilación está configurado para enero de 2016? Y el tipo que está allí durante 10 años le dirá que es necesario o la construcción se rompe en lugares aleatorios. Suspiro.
Wilbert

Respuestas:

62

No creo que esta sea una característica útil cuando realmente prohíbe la compilación. Cuando al 01/06/2018 no se compilarán grandes partes del código que compiló el día anterior, su equipo eliminará rápidamente esa anotación nuevamente, el código se limpió o no.

Sin embargo, puede agregar alguna anotación personalizada al código como

@Deprecated_after_2018_07_31

y crea una pequeña herramienta para escanear esas anotaciones. (Un trazador de líneas simple en grep lo hará, si no desea utilizar la reflexión). En otros lenguajes además de Java, se puede utilizar un comentario estandarizado adecuado para "grepping" o una definición de preprocesador.

Luego ejecute esa herramienta poco antes o después de la fecha en particular, y si aún encuentra esa anotación, recuerde al equipo que limpie esas partes del código con urgencia.

Doc Brown
fuente
9
@Bergi: hey, este es solo un ejemplo, OP puede usar versiones o etiquetas de fecha, lo que prefieran en su control.
Doc Brown
44
No veo ninguna ventaja en hacer esto solo usando las características de desuso normales y mirando la salida del compilador en la fecha específica. Parece un mal uso del tiempo del desarrollador para volver a implementar algo que ya existe. Incluso si ya tiene un montón de advertencias (que valdría la pena limpiar), seguramente puede hacer que el compilador escupe todas las advertencias en un archivo de texto y luego grep o lo busque.
jpmc26
44
@jpaugh Recomiendo no hundir horas (nota, tiempo = dinero) en la creación de nuevas herramientas para realizar tareas que ya puede hacer de manera eficiente con las herramientas existentes, sean cuales sean esas herramientas.
jpmc26
3
@ jpmc26: veo dos ventajas (pequeñas): no recibir toneladas de advertencias de desaprobación (lo que introduciría un riesgo de pasar por alto las más importantes) y la posibilidad de introducir diferentes criterios de desaprobación (fechas, versiones, lo que sea) para diferentes secciones de código. Además, el OP solicitó explícitamente desaprobar el acoplamiento con una fecha.
Doc Brown
77
Haría +1 si solo usaras la orden AAAA-MM-DD para la fecha en tu ejemplo, porque solo he visto que la orden ambigua ?? - ?? - AAAA causa dolor y malentendidos.
mtraceur
284

Esto constituiría una característica conocida como bomba de tiempo . NO CREES BOMBAS DE TIEMPO.

El código, no importa cuán bien lo estructura y documenta, se convertirá en una caja negra casi mítica mal entendida si vive más allá de cierta edad. Lo último que alguien necesita en el futuro es otro extraño modo de falla que los tome por sorpresa, en el peor momento posible y sin un remedio obvio. No hay absolutamente ninguna excusa para producir intencionalmente tal problema.

Míralo de esta manera: si estás organizado y conoces la base de tu código lo suficiente como para que te preocupe la obsolescencia y la sigas, entonces no necesitas un mecanismo dentro del código que te lo recuerde. Si no lo está, es probable que tampoco esté actualizado sobre otros aspectos de la base del código y que probablemente no pueda responder a la alarma de manera oportuna y correcta. En otras palabras, las bombas de tiempo no sirven para nada. ¡Solo di no!

Kilian Foth
fuente
74
+1 Esto te morderá. Meses después. Un viernes, justo cuando intentas hacer un despliegue de emergencia. Y es un fin de semana largo, por lo que todas las personas que saben algo al respecto están fuera de la oficina. No lo hagas
Roger Lipscombe
3
De acuerdo. La obsolescencia es un problema de organización, no un problema de codificación. Todavía podría conectar una Apple] [y escribir BASIC, nada me detiene. Pero, ¿me gustaría ?
19
La solución correcta, siguiendo su dirección "organizada y consciente", es generar un error en su sistema de seguimiento de errores, diciendo "Eliminar <tal y tal>", con un plazo sugerido en los comentarios. Y luego, en 6 meses, cuando se produce una revisión de errores para averiguar qué errores deben corregirse en la próxima versión, si ese plazo es inminente, dices "es hora de hacer esto". Es gestión básica de proyectos.
Lightness compite con Monica el
1
De hecho, si su calendario de lanzamiento es lo suficientemente predecible, solo hágalo ahora.
Lightness compite con Monica el
13
Consulte el comentario de isanae para obtener una alternativa: " Si desea que las personas dejen de usar funciones obsoletas, publique una versión sin ellas. Eso atraerá su atención y siempre pueden retroceder si aún no pueden hacerlo " .
Stevoisiak
70

En C # usaría el ObsoleteAttributede la siguiente manera:

  • En la versión 1, envía la función. Un método, clase, lo que sea.
  • En la versión 2, envía una función mejor destinada a reemplazar la función original. Pones un atributo Obsoleto en la función, lo configuras como "advertencia" y le das un mensaje que dice "Esta función está en desuso. Utiliza la mejor función en su lugar. En la versión 3 de esta biblioteca, que se lanzará en tal o cual una fecha, el uso de esta función será un error ". Ahora los usuarios de la función aún pueden usarla, pero tienen tiempo para actualizar su código para usar la nueva función.
  • En la versión 3, actualiza el atributo para que sea un error en lugar de una advertencia, y actualiza el mensaje para decir "Esta característica está en desuso. Utilice la mejor función en su lugar. En la versión 4 de esta biblioteca, que se lanzará en tal o cual una fecha, esta característica arrojará ". Los usuarios que no prestaron atención a su advertencia anterior aún reciben un mensaje útil que les dice cómo solucionar el problema, y ​​deben solucionarlo, porque ahora su código no se compila.
  • En la versión 4, cambia la función para que arroje alguna excepción fatal y cambia el mensaje para decir que la función se eliminará por completo en la próxima versión.
  • En la versión 5, eliminas la característica por completo, y si los usuarios se quejan, bueno, les diste tres ciclos de lanzamiento de advertencia justa, y siempre pueden seguir usando la versión 2 si se sienten fuertemente al respecto.

La idea aquí es hacer un cambio radical lo más sencillo posible para los usuarios afectados, y garantizar que puedan seguir utilizando la función para al menos una versión de la biblioteca.

Eric Lippert
fuente
2
Creo que este es el enfoque correcto, pero cambiaría una cosa ... que sería intercambiar "si los usuarios se quejan" por "cuando los usuarios se quejan"
Liath
10
Extraer el cuerpo al mismo tiempo que cambiar a un error parece extraño. Una de las ventajas de la versión de error de obsoleto es que permite que el código creado con versiones anteriores continúe funcionando mientras evita que el código recién compilado lo use. Por lo tanto, sigue siendo compatible con ABI, mientras rompe deliberadamente la compatibilidad de API. Por supuesto, en un mundo perfecto, tendría versiones de estilo semver, etc., de modo que nunca ejecutaría el nuevo código con una aplicación compilada previamente, pero muchos proyectos nunca alcanzan ese ideal.
Kevin Cathcart
@KevinCathcart: Ese es un buen punto; tal vez otra etapa allí está justificada! Actualizaré el texto.
Eric Lippert
1
En realidad, si está haciendo SemVer, puede pasar directamente de desaprobado en la versión XY0 (cualquier desaprobación debe ser una versión menor) para eliminarlo por completo en X + 1.0.0. Diría que es bueno esperar un poco más (¿a X + 2.0.0?), Pero este proceso de cinco pasos probablemente está dorando el lirio. El siguiente paso después de la "advertencia" debería ser un "error fatal" (porque la característica en desuso se reemplaza con el código generador de errores). Dado libfoo.so.2y libfoo.so.3pueden coexistir entre sí muy bien, su aguas abajo puede seguir usando la antigua biblioteca hasta que son activados por encima.
Monty Harder
@MontyHarder: Claro. La secuencia exacta de eventos puede ser determinada por las necesidades del desarrollador y su comunidad de usuarios. Sin embargo, el punto más importante es que debería haber una política bien pensada para tratar este tipo de problemas de versiones que se comunique claramente a las partes interesadas.
Eric Lippert el
24

Has entendido mal lo que significa "obsoleto". En desuso significa:

ser utilizable pero considerado obsoleto y mejor evitarlo, generalmente porque ha sido reemplazado.

Diccionarios Oxford

Por definición, una característica obsoleta aún se compilará.

Está buscando eliminar la función en una fecha específica. Esta bien. La forma de hacerlo es eliminarlo en esa fecha .

Hasta entonces, márquelo como obsoleto, obsoleto o como lo llame su lenguaje de programación. En el mensaje, incluya la fecha en que se eliminará y lo que lo reemplaza. Esto generará advertencias, lo que indica que otros desarrolladores deben evitar el uso nuevo y reemplazar el uso antiguo siempre que sea posible. Esos desarrolladores lo cumplirán o lo ignorarán, y alguien tendrá que lidiar con las consecuencias de eso cuando se elimine. (Dependiendo de la situación, puede ser usted o los desarrolladores que lo usen).

jpmc26
fuente
Interesado en lo que el votante no está de acuerdo.
jpmc26
2
+1. Si usa JIRA para un desarrollo ágil, cree una tarea y póngala en un sprint futuro; adaptarse a cualquier otra herramienta de gestión de proyectos y metodología que siga. Esto se resuelve mejor con métodos no técnicos.
Mateo leyó el
1
Y también asegúrese de que la Clase / Lib permanezca en la documentación como depreciada y / o eliminada en la versión Xx
Phil M
12

No olvide que debe conservar la capacidad de compilar y depurar versiones anteriores del código para admitir versiones del software que ya se han lanzado. El sabotaje de una compilación después de una fecha determinada significa que también corre el riesgo de evitar realizar trabajos de mantenimiento y soporte legítimos en el futuro.

Además, parece una solución trivial para retrasar el reloj de mi máquina un año o dos antes de compilar.

Recuerde, "obsoleto" es una advertencia de que algo desaparecerá en el futuro. Cuando desee evitar a la fuerza que las personas usen esa API, simplemente elimine el código asociado . No tiene sentido dejar código en la base de código si algún mecanismo lo deja inutilizable. Eliminar el código le proporciona las comprobaciones en tiempo de compilación que está buscando y no tiene una solución trivial.

Editar: veo que se refiere al "código antiguo no utilizado" en su pregunta. Si el código realmente no se usa , no tiene sentido desaprobarlo. Solo bórralo.

bta
fuente
La mejor respuesta con diferencia, quizás enfatice que eliminar el código es la mejor manera de resolver el problema antes en su respuesta. Puede ser fácil desplazarse más allá de la pared de respuestas de texto
Clint
6

Nunca antes había visto una característica así: una anotación que comienza a tener efecto después de una fecha en particular.

El @Deprecatedpuede ser suficiente, sin embargo. Capture advertencias en CI y haga que se niegue a aceptar la compilación si hay alguna presente. Esto cambia la responsabilidad del compilador a su canal de compilación, pero tiene la ventaja de que puede (semi) modificar fácilmente el canal de compilación agregando pasos adicionales.

Tenga en cuenta que esta respuesta no resuelve completamente su problema (por ejemplo, las compilaciones locales en las máquinas de los desarrolladores seguirían teniendo éxito, aunque con advertencias) y asume que tiene una tubería CI configurada y en funcionamiento.

Mael
fuente
4

Estás buscando calendarios o listas de tareas pendientes .

Otra alternativa es usar advertencias de compilación personalizadas o mensajes de compilación, si logra tener pocas o ninguna advertencia en su base de código. Si tiene demasiadas advertencias, deberá dedicar un esfuerzo adicional (¿aproximadamente 15 minutos?) Y deberá recoger la advertencia del compilador en el informe de compilación que entrega su integración continua en cada compilación.

Los recordatorios de que el código necesita ser reparado son buenos y necesarios. A veces, estos recordatorios tienen plazos estrictos en el mundo real, por lo que también puede ser necesario ponerlos en un temporizador.

El objetivo es recordar continuamente a las personas que el problema existe y necesita ser solucionado dentro de un período de tiempo dado, una característica que simplemente rompe la compilación en un momento específico no solo no lo hace, sino que esa característica es en sí misma un problema que necesita arreglarse dentro de un plazo determinado.

Peter
fuente
1
De acuerdo. Pero si existe un problema y necesita ser solucionado dentro de un período de tiempo determinado, entonces debe convertirse en la principal prioridad de alguien en el momento adecuado. Recuerdo que en una reunión mi gerente me dio una "máxima prioridad" y luego dijo: " Esta es su prioridad número uno" (algo diferente). Mi supervisor dijo: "¡No puede tener dos prioridades número uno!" El gerente se sobresaltó. Supongo que pensó que ... podría. Planear que algo se arregle "en el momento adecuado" es quedarse sin tiempo.
3

Una forma de pensar en esto es lo que quieres decir con hora / fecha . Las computadoras no saben cuáles son estos conceptos: tienen que ser programados de alguna manera. Es bastante común representar tiempos en el formato UNIX de "segundos desde la época", y es común alimentar un valor particular en un programa a través de llamadas al sistema operativo. Sin embargo, no importa cuán común sea este uso, es importante tener en cuenta que no es el momento "real": es solo una representación lógica.

Como otros han señalado, si hiciste una "fecha límite" usando este mecanismo, es trivial alimentarlo en un momento diferente y romper esa "fecha límite". Lo mismo ocurre con mecanismos más elaborados, como solicitar un servidor NTP (incluso a través de una conexión "segura", ya que podemos sustituir nuestros propios certificados, autoridades de certificación o incluso parchear las bibliotecas de cifrado). Al principio puede parecer que esas personas tienen la culpa de trabajar alrededor de su mecanismo, pero puede ser el caso de que se haga automáticamente y por buenas razones . Por ejemplo, es una buena idea tener compilaciones reproducibles , y las herramientas para ayudarlo podrían restablecer / interceptar automáticamente tales llamadas de sistema no deterministas. libfaketime hace exactamente eso,establece todas las marcas de tiempo del archivo en 1970-01-01 00:00:01, la función de grabación / reproducción de Qemu falsifica toda interacción de hardware, etc.

Esto es similar a la ley de Goodhart : si hace que el comportamiento de un programa dependa del tiempo lógico, entonces el tiempo lógico deja de ser una buena medida del tiempo "real". En otras palabras, las personas generalmente no se meterán con el reloj del sistema, pero lo harán si les das una razón.

Hay otras representaciones lógicas del tiempo: una de ellas es la versión del software (ya sea su aplicación o alguna dependencia). Esta es una representación más deseable para una "fecha límite" que, por ejemplo, el tiempo UNIX, ya que es más específica para lo que le interesa (cambiar conjuntos de características / API) y, por lo tanto, es menos probable que pisotee las preocupaciones ortogonales (por ejemplo, jugar con el tiempo UNIX para evitar su fecha límite podría terminar rompiendo archivos de registro, trabajos cron, cachés, etc.).

Como han dicho otros, si controlas la biblioteca y quieres "impulsar" este cambio, puedes impulsar una nueva versión que desaproveche las características (provocando advertencias, para ayudar a los consumidores a encontrar y actualizar su uso), entonces otra nueva versión que elimine el características por completo. Si lo desea, puede publicarlos inmediatamente uno después del otro, ya que (de nuevo) las versiones son simplemente una representación lógica del tiempo, no necesitan estar relacionadas con el tiempo "real". Las versiones semánticas pueden ayudar aquí.

El modelo alternativo es "tirar" del cambio. Esto es como su "plan B": agregue una prueba a la aplicación consumidora, que verifica que la versión de esta dependencia sea al menos el nuevo valor. Como de costumbre, rojo / verde / refactor para propagar este cambio a través de la base de código. Esto puede ser más apropiado si la funcionalidad no es "mala" o "incorrecta", sino simplemente "una mala opción para este caso de uso".

Una pregunta importante con el enfoque "pull" es si la versión de dependencia cuenta o no como una "unidad" ( de funcionalidad ) y, por lo tanto, merece ser probada; o si se trata solo de un detalle de implementación "privada", que solo debe ejercerse como parte de las pruebas de unidad ( de funcionalidad ) reales . Yo diría: si la distinción entre las versiones de la dependencia realmente cuenta como una característica de su aplicación, entonces haga la prueba (por ejemplo, verifique que la versión de Python sea> = 3.x). Si no, entonces noagregue la prueba (ya que será frágil, poco informativa y demasiado restrictiva); si controlas la biblioteca, ve por la ruta "push". Si no controla la biblioteca, simplemente use la versión que se le proporcione: si sus pruebas pasan, entonces no vale la pena restringirse; si no pasan, ¡esa es tu "fecha límite" allí mismo!

Existe otro enfoque, si desea desalentar ciertos usos de las características de una dependencia (por ejemplo, llamar a ciertas funciones que no funcionan bien con el resto de su código), especialmente si no controla la dependencia: prohíba sus estándares de codificación / desaliente el uso de estas funciones y agregue comprobaciones para ellas a su linter.

Cada uno de estos será aplicable en diferentes circunstancias.

Warbo
fuente
1

Usted administra esto a nivel de paquete o biblioteca. Usted controla un paquete y controla su visibilidad. Eres libre de retraer la visibilidad. He visto esto internamente en grandes empresas y solo tiene sentido en culturas que respetan la propiedad de los paquetes, incluso si los paquetes son de código abierto o de uso gratuito.

Esto siempre es complicado porque los equipos de clientes simplemente no quieren cambiar nada, por lo que a menudo necesita algunas rondas de la lista blanca solo mientras trabaja con los clientes específicos para acordar una fecha límite para migrar, posiblemente ofreciéndoles soporte.

djechlin
fuente
Me gusta la parte de soporte. Todos los cambios son más suaves, más agradables y probablemente con menos dificultades si las personas que los promueven ofrecen apoyo. Eso es en parte un efecto psicológico: el buen apoyo es cooperativo; se toma en serio a todos los involucrados. Por el contrario, los cambios impuestos desde arriba sin involucrar a los involucrados los hacen sentir ignorados y poco cooperativos. (Aunque la amabilidad debe combinarse con un impulso implacable para lograr los cambios).
Peter - Restablece a Monica el
1

Un requisito es introducir una noción de tiempo en la compilación. En C, C ++, u otros lenguajes / construir sistemas que utilizan un preprocesador C-como 1 , se podría introducir un sello de tiempo a través define para el preprocesador en tiempo de compilación: CPPFLAGS=-DTIMESTAMP()=$(date '+%s'). Esto probablemente sucedería en un archivo MAKE.

En el código, uno compararía ese token y causaría un error si se acaba el tiempo. Tenga en cuenta que el uso de una macro de función detecta el caso que alguien no definió TIMESTAMP.

#if TIMESTAMP() == 0 || TIMESTAMP() > 1520616626
#   error "The time for this feature has run out, sorry"
#endif

Alternativamente, uno podría simplemente "definir" el código en cuestión cuando haya llegado el momento. Eso permitiría compilar el programa, siempre que nadie lo use. Digamos que tenemos un encabezado que define una api, "api.h", y no permitimos llamar old()después de un cierto tiempo:

//...
void new1();
void new2();
#if TIMESTAMP() < 1520616626
   void old();
#endif
//...

Una construcción similar probablemente eliminaría old()el cuerpo de la función de algún archivo fuente.

Por supuesto, esto no es infalible; uno simplemente puede definir un viejo TIMESTAMPen caso de la construcción de emergencia del viernes por la noche mencionada en otra parte. Pero eso es, creo, bastante ventajoso.

Obviamente, esto solo funciona cuando la biblioteca se vuelve a compilar; después de eso, el código obsoleto simplemente ya no existe en la biblioteca. Sin embargo, no evitaría que el código del cliente se vincule a binarios obsoletos.


1 C # solo admite la definición simple de símbolos de preprocesador, sin valores numéricos, lo que hace que esta estrategia no sea viable.

Peter - Restablece a Monica
fuente
También vale la pena señalar que esta definición de preprocesador forzará TIMESTAMPa que se recompile todo el código que se usa en cada compilación. También incapacitará herramientas como ccache. Esto significa que el tiempo de compilación típico para compilaciones incrementales aumentará significativamente dependiendo de la cantidad de código base afectada por las características desaprobadas de esta manera.
mindriot
@mindriot Ese es un aspecto interesante. Sin embargo, supongo que eso es cierto con cada método que introduce una noción de tiempo en el código: el OP dijo explícitamente "después de que una fecha en particular haya pasado". Sin embargo, uno podría manejar el aspecto del tiempo en el sistema de compilación y dejar el código solo, cierto. Pero el OP pidió explícitamente "algo puesto en el código". Mi solución tiene la ventaja de ser independiente de cualquier método de compilación en particular. Se puede engañar, pero hay que atenderlo de una forma u otra.
Peter - Restablece a Monica el
Estás absolutamente en lo correcto. Su solución aquí es esencialmente la única que proporciona una solución práctica a la pregunta real del OP . Sin embargo, me pareció importante señalar la desventaja. Dependerá del OP evaluar los pros y los contras. Creo que incluso se podría lograr un punto medio saludable, por ejemplo, dividiendo el TIMESTAMPvalor por, digamos, 86400, para obtener una granularidad diaria y, por lo tanto, menos recompilaciones.
mindriot
0

En Visual Studio, puede configurar una secuencia de comandos previa a la compilación que arroje un error después de una fecha determinada. Esto evitará la compilación. Aquí hay un script que arroja un error a partir del 12 de marzo de 2018 ( tomado de aquí ):

@ECHO OFF

SET CutOffDate=2018-03-12

REM These indexes assume %DATE% is in format:
REM   Abr MM/DD/YYYY - ex. Sun 01/25/2015
SET TodayYear=%DATE:~10,4%
SET TodayMonth=%DATE:~4,2%
SET TodayDay=%DATE:~7,2%

REM Construct today's date to be in the same format as the CutOffDate.
REM Since the format is a comparable string, it will evaluate date orders.
IF %TodayYear%-%TodayMonth%-%TodayDay% GTR %CutOffDate% (
    ECHO Today is after the cut-off date.
    REM throw an error to prevent compilation
    EXIT /B 2
) ELSE (
    ECHO Today is on or before the cut-off date.
)

Asegúrese de leer las otras respuestas en esta página antes de usar este script.

usuario2023861
fuente
-1

Entiendo el objetivo de lo que estás tratando de hacer. Pero como otros han mencionado, el sistema / compilador de compilación probablemente no sea el lugar adecuado para hacer cumplir esto. Sugeriría que la capa más natural para hacer cumplir esta política es la SCM o las variables de entorno.

Si hace lo último, básicamente agregue un indicador de característica que marque una ejecución previa a la eliminación. Cada vez que construya la clase en desuso o llame a un método en desuso, verifique el indicador de función. Simplemente defina una única función estática assertPreDeprecated()y agregue esto a cada ruta de código obsoleta. Si está configurado, ignore las llamadas de aserción. Si no es lanzar una excepción. Una vez que la fecha pase, desactive el indicador de función en el entorno de tiempo de ejecución. Cualquier llamada obsoleta al código que permanezca aparecerá en los registros de tiempo de ejecución.

Para una solución basada en SCM, supondré que estás usando git y git-flow. (Si no, la lógica es fácilmente adaptable a otros VCS). Crea una nueva sucursal postDeprecated. En esa rama, elimine todo el código obsoleto y comience a trabajar para eliminar cualquier referencia hasta que se compile. Cualquier cambio normal continúa haciendo en la masterrama. Mantenga fusionando cualquier cambio que no son obsoletas relacionadas con el código de masternuevo en postDeprecatedreducir al mínimo los retos de integración.

Después de que finalice la fecha de desaprobación, cree una nueva preDeprecatedrama desde master. Luego fusionarse postDeprecatednuevamente master. Suponiendo que su lanzamiento se salga de la mastersucursal, ahora debería estar utilizando la sucursal posterior a la desaprobación después de la fecha. Si hay una emergencia, o no puede entregar resultados a tiempo, siempre puede retroceder preDeprecatedy hacer los cambios necesarios en esa rama.

usuario79126
fuente
77
Ese enfoque suena como una pesadilla logística. Si comienza a mantener ramas paralelas casi duplicadas, terminará pasando todo su tiempo haciéndolo. Desperdicio total.
Lightness compite con Monica el
66
No puedo aceptar que mantener ramificaciones paralelas, usar una simplemente para eliminar funciones obsoletas de muchas versiones antes de que realmente desee eliminarlas del producto, sea de alguna manera "el estándar de la industria". Cuál es el propósito de eso? Sí, un VCS puede realizar automáticamente algunas fusiones, pero una fusión debe realizarse con el ojo del desarrollador para resolver conflictos lógicos (¿y qué sucede cuando se produce un conflicto que ni siquiera se puede resolver léxicamente?). Tener un sistema de compilación que se fusiona arbitrariamente todos los días, es simplemente ... inútil. Elimine la función cuando sea hora de eliminarla.
Lightness compite con Monica el
3
Porque hay una buena razón para mantener las ramas de lanzamiento (backport parches importantes). No hay una buena razón para mantener una rama de "algo que podría hacer en el futuro". Es sobrecarga, sin beneficio. Simple como eso.
Lightness compite con Monica el
44
¿Dónde lo conseguí? Literalmente es la definición de deprecación. Desprecias algo que podrías eliminar en el futuro. Por lo tanto, no hay falsedad, no se mueven los postes de gol, y ciertamente no se inventa nada solo "para ganar la discusión". ¡Esto no es "un caso de uso de libros de texto de ramificación SCM" en ninguna organización para la que quiero trabajar! Supongo que tendremos que aceptar no estar de acuerdo. ¡Ten una buena tarde!
Lightness compite con Monica el
2
@lightness: hay muchas razones por las cuales el código oficialmente despreciable no es solo una "cosa que podríamos hacer cada vez que lo encontremos". Tal vez el código en desuso utiliza una biblioteca, donde se está eliminando el soporte oficial. Tal vez el código en desuso es IP cuya licencia caduca después de una fecha fija. Tal vez después de la fecha dada, hay nuevas regulaciones y el código no cumple. Su solución está muy bien si vive en una torre de marfil. Pero las organizaciones del mundo real se enfrentan a este tipo de situaciones todo el tiempo. El software necesita satisfacer las necesidades del negocio, no al revés.
user79126