¿TODO comenta con fechas límite?

51

Fondo

Estoy trabajando en un equipo que busca implementar implementaciones de tiempo de inactividad cero. Estamos planeando utilizar una estrategia de implementación azul / verde para lograr esto. Una de las cosas que me estoy dando cuenta al hacer la investigación es lo complicado que resulta hacer cambios en la base de datos. Una operación simple como cambiar el nombre de una columna puede tomar 3 ciclos de publicación completos hasta que se complete!

Me parece que al tener el lanzamiento completo de un cambio, llevar varios ciclos de lanzamiento, presenta un gran potencial de error humano. En el artículo vinculado se muestra que los cambios de código son necesarios para 2 versiones y una migración de base de datos para 3 versiones.

Lo que estoy buscando

Actualmente, si queremos recordar hacer algo, podemos crear un ticket en nuestro sistema de administración de problemas, lo que genera desorden y también puede ser trasladado a un sprint posterior o al backlog por la administración; o podemos crear un comentario TODO, que probablemente se olvidará por completo.

Lo que estoy buscando es una forma en la que un comentario de TODO puede tener una fecha límite en su contra, y nuestro sistema de Integración Continua (actualmente no decidido que usaremos) rechazará la compilación si esta fecha límite caducara.

Por ejemplo, si cambiamos el nombre de una columna, podríamos crear la migración inicial y luego dos comentarios TODO para asegurarnos de que se crean las dos migraciones restantes:

// TODO by v55: Create migration to move constraints to new column, remove references to old column in app
// TODO by v56: Create migration to drop old column

Esto parece bastante simple de implementar, pero me pregunto si ya existe algo así, porque no quiero reinventar la rueda.

Pensamientos adicionales

Siento que podría estar sufriendo el problema XY aquí, dado que las implementaciones continuas y las implementaciones en azul / verde se consideran una buena práctica, parece extraño que no pueda encontrar una solución para hacer que las actualizaciones de la base de datos sean menos dolorosas. Si crees que estoy investigando por completo algo incorrecto, ¡házmelo saber en un comentario! Dicho esto, el ejemplo de la base de datos que proporcioné es solo un ejemplo, y creo que TODO comentarios con fechas de vencimiento también serían útiles en otras situaciones, por lo que incluso si me estoy acercando a esta situación específica, realmente me gustaría responder a mi pregunta real también. Gracias!

EDITAR: Acabo de pensar en otra situación en la que esto podría ser útil. Si usa las Alternativas de funciones para activar partes de su aplicación cuando estén listas, debe tener cuidado de limpiarlas, de lo contrario podría terminar con Toggle Debt . Los comentarios con fechas límite podrían ser una buena manera de recordar esto.

    
pregunta Joshua Walsh 30.05.2017 - 02:12

7 respuestas

52

Esta pregunta es realmente dos preguntas en una.

Todo comentarios

De todas las formas de rastrear elementos de acción, esta es la peor. Los comentarios TODO son buenos durante el trabajo activo o como una forma de sugerir a un mantenedor, "aquí hay algo que tal vez podría mejorarse en el futuro". Pero si confía en los comentarios TODO para realizar el trabajo, está condenado al fracaso.

Qué hacer al respecto

Los comentarios de

TODO son básicamente deuda técnica, por lo que deben manejarse como cualquier otra deuda técnica. Puede abordarlos de inmediato, si tiene tiempo, o ponerlos en el registro para que puedan ser rastreados y priorizados.

En términos generales, y esto es totalmente cuestionado y abierto al debate, los comentarios de TODO podrían considerarse un olor de código. Si un comentario de TODO llega al punto de ser registrado en el control de versiones, debe preguntarse, ¿realmente va a seguir adelante ahora mismo? Si no, está bien. Solo sé honesto contigo mismo y ponlo en el registro.

La forma en que gestiona esta acumulación se reduce al proceso empresarial, a la política de la empresa y, quizás, a cierta autonomía personal. Pero aún necesita un seguimiento y un registro de prioridades para asegurarse de que suceda.

Cambios en la base de datos

Sí, los cambios en la base de datos son complicados con una política de tiempo de inactividad cero. Algunos trucos para ayudar a que sea menos doloroso:

Proceso posterior a la implementación

Cree un proceso posterior a la implementación que se ejecute como parte de la misma versión. Sin embargo quieres que funcione. En el último sistema en el que trabajé, diseñé un despliegue de 4 fases:

  1. scripts de base de datos preapp
  2. aplicaciones web
  3. scripts de base de datos de postapp
  4. scripts de la base de datos de la ventana de mantenimiento

La idea era que siempre que fuera posible, pondríamos la mayor cantidad posible de cambios a la base de datos en la etapa previa.

Postapp se reservó para los casos inusuales en los que necesitábamos realizar cambios de esquema incompatibles. En esos casos, la preapp haría un cambio suficiente para que el nuevo código de la aplicación fuera compatible (tal vez creando una vista temporal para la compatibilidad), y postapp limpiaría cualquier artefacto temporal.

La fase de la ventana de mantenimiento se reservó para los cambios que realmente requerían tiempo de inactividad o donde el riesgo o costo de una implementación en vivo no valía la pena. Por ejemplo, los scripts que cambian cantidades masivas de datos pueden necesitar bloquear una tabla completa.

Implementar con frecuencia

Si implementas nuevas versiones con la frecuencia suficiente, puedes llegar a un punto en el que llevar un cambio entre 2 o 3 versiones sea trivial. Los largos ciclos de lanzamiento amplifican el costo de los cambios en la base de datos.

    
respondido por el Brandon 30.05.2017 - 03:32
24

No utilice TODOs. Ya tienes una lista de TODO en tu proyecto. Se llama el rastreador de problemas.

Creo que el verdadero problema está en esta oración:

  

podemos crear un ticket en nuestro sistema de administración de problemas, lo que crea desorden y también puede ser trasladado a un sprint posterior o al backlog por la administración.

Si tu rastreador de problemas crea mucho desorden, encuentra maneras de solucionarlo. Tal vez un tipo especial / etiqueta que implica menos ceremonia. Tal vez sub-problemas. Tal vez menos ceremonia por completo. Realmente no podemos decirlo. Pero si su rastreador de problemas crea tanto trabajo, las personas prefieren formular una pregunta elaborada en un foro público en lugar de simplemente agregar ese problema, algo está muy mal.

Si su administración retrasa indebidamente la última parte de una tarea, tiene dos opciones:

  1. hable con su gerencia por qué es una mala idea.

  2. manejarlo como una sola tarea. Esta podría ser la solución estándar de oro. En un mundo perfecto, debería poder realizar los tres cambios necesarios en cada paso. Aplique uno a la rama maestra, deje que se construya y despliegue. Mientras tanto, aplique el segundo a la rama maestra, deje que se construya y despliegue, y así sucesivamente para que todo suceda en el mismo sprint, y si no lo hace, no se hace. Tal vez incluso algo automático tenga sentido donde se hace una implementación de manera lógica, pero en realidad se divide en 3.

respondido por el Jens Schauder 30.05.2017 - 07:47
9
  

Lo que estoy buscando es una forma en la que un comentario de TODO puede tener una fecha límite en su contra, y nuestro sistema de Integración Continua (actualmente no decidido que usaremos) rechazará la compilación si esta fecha límite caducara.

Lo que está pidiendo es factible si está dispuesto a hacer el trabajo y cumplirlo.

  

// TODO by v55: crea una migración para mover restricciones a una nueva columna, elimina las referencias a una columna antigua en la aplicación   // TODO by v56: Crear migración para eliminar una columna antigua

grep para //TODO by v55 cuando sea el momento de implementar v55. Deploy build ejecuta un script que hace eso como una prueba de integración.

Puedes vincular 55 con el seguimiento de tu versión o simplemente solicitarlo.

Se vuelve interesante si desea verificar // TODO by v54 cuando hace 55. En lugar de buscar el código base 55 veces, solo busque // TODO by. Luego filtre ese resultado de 1 a 55. Ahora 56 no disparará un fallo.

Puedes pensar "oh, no lo necesitaremos. Lo arreglaremos cada vez que tengamos el cheque". No. No, no lo harás.

    
respondido por el candied_orange 30.05.2017 - 02:43
4

Tuvimos un problema muy similar en nuestro equipo. Para resolver esto, escribimos una verificación de análisis estático que maneja estos TODO al verificar el problema de JIRA o el problema de Git al que hacen referencia. Nuestra compilación falla cuando el problema especificado se mueve más allá de la columna "En desarrollo".

Por lo tanto, podemos tener TODO cómodamente sin preocuparnos de que se olviden de ellos.

Creé una implementación de código abierto de esto, en Java. Sí, un descargo de responsabilidad es que escribí esto, pero como dije, es de código abierto y con licencia.

La herramienta se llama Westie y hay un ejemplo del comprobador de problemas de Jira en el archivo README.md. Vea también el GitIssueAnalyser.

Para evitar la auto-promoción si tiene más preguntas, envíeme un mensaje. Si decides usarlo y tienes alguna sugerencia, plantea cualquier problema en github.

    
respondido por el tjheslin1 30.05.2017 - 19:43
4

No hacer. Hazlo ahora.

TLDR: escriba (y pruebe) sus scripts de base de datos ahora, no más tarde; simplemente codifíquelos para que su ejecución esté supeditada a la versión de DB.

Ejemplo

Por ejemplo, imaginemos que desea cambiar el nombre de una columna de SSN a TaxID , un requisito común cuando se internacionaliza.

Para que esto suceda, quizás tengas temporalmente una columna TaxID y una columna SSN . Y mientras soporta ambas versiones, tendrá un activador para actualizar una de la otra. Pero no desea mantener ese desencadenante por tiempo indefinido, por lo que más adelante, cuando ya no se necesite la compatibilidad con versiones anteriores, querrá que se elimine ese desencadenante (y se elimine la columna SSN ). Vamos a codificar todo eso por adelantado sin necesidad de elementos de tareas pendientes.

En nuestro ejemplo, implementaremos la compilación 102 (que tiene la nueva columna) mientras mantenemos la compatibilidad con la compilación 101 (que no la tiene).

Aquí están los pasos.

1. Configurar la tabla de versiones

  1. Agregue una sola tabla llamada Configuration con dos columnas, Name y Value .

  2. Agregue una fila con Name de "TargetVersion" y configure Value a la versión de la nueva compilación que se implementará.

  3. Agregue una fila con un Name de "CompatibleWith" y configure Value al número de versión mínimo con el que la implementación debe ser compatible.

Inspeccione y actualice estas filas antes de cada implementación.

2. Modificar los scripts de implementación

  1. Agregue un script que cree una nueva columna de TaxID , lado a lado con SSN , y la complete de la columna SSN . Incluya este código en una declaración If que verifique TargetVersion; si la versión de destino es demasiado baja (es decir, aún no se necesita TaxID ), omita.

    SELECT @TargetVersion = TargetVersion FROM Configuration
    IF @TargetVersion < '102' THEN RETURN
    ALTER TABLE Customer ADD COLUMN taxID VarChar(12) NOT NULL
    UPDATE Customer SET TaxID = SSN
    
  2. Agregue un script que cree un desencadenante que rellene TaxID al insertar o actualizar SSN y viceversa. Incluya este código en una declaración If que verifique la versión de destino y la versión compatible; omitir si TargetVersion es demasiado bajo (no se necesita TaxID ) o si la versión de CompatibleWith es demasiado alta (no se necesita el campo SSN ).

    SELECT @TargetVersion  = TargetVersion,
           @CompatibleWith = CompatibleWith 
    FROM Configuration
    IF @TargetVersion  < '102' THEN RETURN
    IF @CompatibleWith > '101' THEN RETURN
    CREATE TRIGGER SSNAndTaxIDTrigger ON Customer etc.
    
  3. Agregue un script para eliminar la columna SSN . Inclúyalo en una declaración If que elimina la columna solo si la versión de CompatibleWith es lo suficientemente alta (ya no se necesita SSN ).

    SELECT @CompatibleWith = CompatibleWith FROM Configuration
    IF @CompatibleWith <= '101' THEN RETURN
    IF OBJECT_ID('SSNAndTaxIDTrigger') IS NOT NULL DROP TRIGGER SSNAndTaxIDTrigger
    IF EXISTS (SELECT * FROM syscolumns c JOIN sysobject o ON o.id = c.is WHERE o.Name = 'Custeomr' AND c.Name = 'SSN') BEGIN
        ALTER TABLE Customer DROP COLUMN SSN
    END
    

3. Pruebas

Asegúrese de probar su implementación con cualquier combinación de números de versión azul / verde que desee poder admitir en producción. Puede probar tan pronto como el código esté listo, manipulando la tabla Configuration en su entorno de control de calidad.

4. En tu libro de jugadas de implementación

Agregue un paso para que un ingeniero actualice las filas de la versión CompatibleWith y TargetVersion. Si está implementando en Blue, configure TargetVersion en el número de versión de Blue y la versión CompatibleWith en el número de versión de Green; revertirlos si está implementando Green.

Pitfalls

Está bien que sus scripts de implementación hagan referencia y se basen en los números de versión que se encuentran en esa tabla de base de datos. NO código de tiempo de ejecución.

Si comienza a escribir su código de tiempo de ejecución para inspeccionar los números de versión, está introduciendo un nuevo nivel de complejidad en su aplicación que podría potencialmente convertirse en un gran problema de mantenimiento. Cada ruta de ejecución de tiempo de ejecución debe ser probada; Si sigue adelante con estas condiciones, QA tendrá que armar una matriz del dolor para validarlas con todas y cada una. lanzamiento. Mi consejo es mantener las condiciones como éstas solo en los scripts de implementación.

El resultado de todo esto

Al final, deberías poder escribir todo el código por adelantado (y también probarlo) sin temor a que se ejecute demasiado pronto. Además, el código limpiará el desencadenante de compatibilidad con versiones anteriores cuando llegue el momento sin que tengas que preocuparte más por ello.

De esta manera, puedes escribir y probar todo el código por adelantado, cuando lo piensas, y no necesitas lidiar con esos desordenados comentarios de ToDo.

    
respondido por el John Wu 30.05.2017 - 20:59
1

Recibes un gran rechazo en tu idea TODO, pero personalmente no veo ningún problema con ella. Al final, la mejor (y más fácil) manera de asegurarse de que la migración entre en producción es fallando en una prueba de unidad si no lo hace. Literalmente, le llevará menos de un minuto apagar una función de migración vacía que lanza una excepción si la versión es 55 o más (o cualquiera que sean los requisitos).

Luego, si intenta liberarlo, terminará con una prueba fallida y alguien tendrá que convertir esa excepción en un código de migración real.

    
respondido por el Eternal21 02.06.2017 - 20:43
-2

Nadie parece estar centrado en la raíz de su queja, que es el hecho de que los cambios en la base de datos pueden llevar demasiados ciclos de lanzamiento. Quiere continuar con su programa de implementación azul / verde y la solución ya debería estar allí, pero a menos que me esté faltando algo, su descripción parece indicar que solo hay una base de datos compartida por ambos sistemas. No es un verdadero sistema azul / verde si ese es el caso. Dado que parece que la base de datos es el polo largo en la tienda de campaña, también debe duplicarse, de modo que no importa cuánto tiempo o cuántos ciclos de lanzamiento demande implementar los cambios de la base de datos en el sistema fuera de línea, no se activarán hasta que se completen. completamente probado En el sistema interino offline, los scripts pueden mantener la base de datos fuera de línea totalmente actualizada diariamente.

    
respondido por el mpiazza 30.05.2017 - 20:30

Lea otras preguntas en las etiquetas