Diseño: Cómo evitar romper la compatibilidad con versiones anteriores debido a cambios en la base de datos

7

Este es mi escenario, tengo esta interfaz:

public interface hitTheDataBase
{
    public void insertMe(String [] values);
    public void modifyMe(String [] values);
    public DataTable selectMe();
}

Y tengo estas dos clases que implementan la interfaz:

public Class hitSqlServer implements hitTheDatabase
{
    public void insertMe(String [] values)
    {
         executes insert into table_in_sqlServerBD (col1, col2) values(values[0], values[1])
    }
    public void modifyMe(String [] values)
    {
         executes update table_in_sqlServerBD set col1 = values[0], col2 =  values[1] where rowid = values[3]
    }

    public DataTable selectMe()
    {
         executes select col1, col2 from table_in_sqlServerBD
    }
}

public Class hitSqLite implements hitTheDatabase
{
    public void insertMe(String [] values)
    {
         executes insert into table_in_sqLite (col1, col2) values(values[0], values[1])
    }
    public void modifyMe(String [] values)
    {
         executes update table_in_sqlLite set col1 = values[0], col2 =  values[1] where rowid = values[3]
    }

    public DataTable selectMe()
    {
         executes select col1, col2 from table_in_sqLite
    }
}

Esto es parte de una aplicación beta que se ejecuta en los entornos de prueba y producción (!), pero se actualizará con regularidad debido a correcciones de errores no relacionadas con las operaciones de la base de datos. Las actualizaciones se realizan simplemente mediante la desinstalación y la reinstalación.

Ahora, tengo un nuevo requisito para una situación de esquina muy específica que requerirá que se agregue una nueva columna "col3" a la tabla, y tendré que insertar, seleccionar y actualizar los valores en esa columna también. El problema es que no quiero interrumpir la compatibilidad con las bases de datos existentes donde el software ya se está ejecutando.

Estaba pensando en codificar una tercera clase que implementa la interfaz HitTheDataBase, una clase auxiliar para verificar si existe "col3", y hacer algo como:

hitTheDataBase hitMe = !helperclass.col3Exists() ? new hitSqlServer() : new hitSqlServerWithCol3();

¿Es este un buen enfoque? Me parece bien, excepto porque tendré que modificar el código en las clases que usan las que "llegan a la base de datos". También tendré que comprobar constantemente si existe el valor de col3 para mostrarlo en la GUI y permitir que el usuario lo modifique.

    
pregunta Broken_Window 10.03.2016 - 21:35

3 respuestas

10

Cuando se implementan las actualizaciones de software, ¿hay alguna razón por la que no pueda actualizar su esquema también? Un cambio en el software que requiere un cambio en el esquema de la base de datos implica que el esquema debería cambiar en el sistema de destino.

La compatibilidad con versiones anteriores de un esquema de base de datos suele ser algo que se debe evitar, y piratear la Capa de acceso a datos para admitir múltiples versiones de esquema se siente como un olor a diseño.

Una solución más limpia es garantizar que su código siempre se ejecute en la versión del esquema para el que se escribió ese código. Esto no solo hará que el código sea más fácil de escribir, y mantendrá el código limpio, sino que también hará que el código sea más fácil de probar. Podría incluir scripts de migración como parte de su proceso de instalación / desinstalación para la actualización, así como la reversión.

¿Su esquema incluye algún tipo de tabla de versiones? Si no es así, debe agregar una tabla de versión de esquema lo antes posible. El control de versiones del esquema es vital para las actualizaciones y reversiones.

Durante un período de tiempo más largo, es probable que termine con una gran cantidad de scripts de actualización de esquema que deberán ejecutarse en un orden específico durante la instalación / desinstalación. Un mecanismo de control de versiones de esquema es clave para asegurarse de que las actualizaciones y retrocesos del esquema se ejecuten sin problemas.

Por otra parte, si no tiene un mecanismo para mantener su esquema en línea con su versión de software, su Capa de acceso a datos puede explotar en complejidad a medida que se enfrenta a un número creciente de "hacks" para preservar la compatibilidad hacia atrás; y se verá sobrecargado con una sobrecarga cada vez mayor de las pruebas de regresión cada vez que cambie algo en su esquema.

    
respondido por el Ben Cottrell 10.03.2016 - 23:37
1

Esto es lo que sucede si el esquema de su base de datos no coincide con una versión de la aplicación. Cualquier aplicación que obtenga el nuevo código col3, debe tener la base de datos actualizada junto con él.

Si vas a tener la molestia de comprobar si existe una columna en una tabla, simplemente créala durante la actualización a la versión más reciente.

    
respondido por el JeffO 10.03.2016 - 23:39
1

Yo diría que no.

Este tipo de [interminable] "si, pero, tal vez, a menos que, excepto que" la lógica solo lo lleve a la locura y, lo que es más importante, ralentice su aplicación, porque todas estas "verificaciones" se realizan en ejecución -hora.

Le sugeriría a versioning sus cambios de esquema y almacenaría esa versión [número] en algún lugar de la base de datos (como parte de su progreso de actualización).

Cree una versión de su clase de acceso a datos para cada versión de base de datos.

En tiempo de ejecución, consulte la base de datos para la versión del esquema y cree una instancia de la clase "correcta" basada en eso.

    
respondido por el Phill W. 11.03.2016 - 13:03

Lea otras preguntas en las etiquetas