2010-01-23 10 views
5

Cuando está escribiendo una aplicación que necesita leer y trabaja con dos versiones de datos de la misma manera, ¿cuál es la mejor manera de estructurar sus clases para representar esos datos? He llegado con tres escenarios:¿Cuál es la forma preferida de almacenar diferentes versiones de datos?

  1. Common Base/Niños específicos
  2. Unión de Datos
  3. estructuras distintas

Versión 1 Ejemplo de coches

byte DoorCount 
int Color 
byte HasMoonroof 
byte HasSpoiler 
float EngineSize 
byte CylinderCount 

Versión 2 coches

byte DoorCount 
int Color 
enum:int MoonRoofType 
enum:int TrunkAccessories 
enum:int EngineType 

Common Base/Niños específicos

Con este método, no es una clase base de los campos comunes entre las dos versiones de los datos y una clase secundaria para cada versión de los datos.

class Car { 
    byte DoorCount; 
    int Color; 
} 

class CarVersion1 : Car { 
    byte HasMoonroof; 
    byte HasSpoiler; 
    float EngineSize; 
    byte CylinderCount; 
} 

class CarVersion2 : Car { 
    int MoonRoofType; 
    int TrunkAccessories; 
    int EngineType; 
} 

fuertes

  • POO Paradigma

debilidades

  • existente clases niño tendrá que cambiar si una nueva versión es liberada que elimina un campo común
  • Datos para una conc La unidad ética se divide entre dos definiciones, no debido a ninguna división significativa para sí misma.

Unión de Datos

Aquí, un coche se define como la unión de los campos de coches en todas las versiones de los datos.

class Car { 
    CarVersion version; 
    byte DoorCount; 
    int Color; 
    int MoonRoofType;  //boolean if Version 1 
    int TrunkAccessories; //boolean if Version 1 
    int EngineType;  //CylinderCount if Version 1 
    float EngineSize;  //Not used if Version2 
} 

fuertes

  • Um ... todo está en un solo lugar.

debilidades

  • código de caja impulsado forzado.
  • Difícil de mantener cuando se lanza otra versión o se elimina la herencia.
  • Difícil de conceptualizar. El significado de los campos cambió según la versión.

estructuras distintas

Aquí las estructuras de programación orientada a objetos no tienen ninguna relación entre sí.Sin embargo, ambas clases pueden implementar interfaces si/cuando el código espera tratarlas de la misma manera.

class CarVersion1 { 
    byte DoorCount; 
    int Color; 
    byte HasMoonroof; 
    byte HasSpoiler; 
    float EngineSize; 
    byte CylinderCount; 
} 

class CarVersion2 { 
    byte DoorCount; 
    int Color; 
    int MoonRoofType; 
    int TrunkAccessories; 
    int EngineType; 
} 

fuertes

  • enfoque directo
  • fácil de mantener si se añade una nueva versión o se retira legado.

debilidades

  • Es un anti-patrón.

¿Hay alguna otra manera mejor en la que no haya pensado? Probablemente sea obvio que estoy a favor de la última metodología, pero ¿es la primera mejor?

Respuesta

1

¿Por qué es la tercera opción, estructuras distintas para cada versión, una mala idea o antipatrón?

Si las dos versiones de estructuras de datos se usan en una aplicación/módulo común, deberán implementar la misma interfaz. Período. Definitivamente es insostenible escribir dos módulos de aplicación diferentes para manejar dos versiones diferentes de la estructura de datos. El hecho de que el modelo de datos subyacente sea extremadamente diferente debería ser irrelevante. Después de todo, el objetivo de escribir objetos es lograr un nivel práctico de encapsulación.

A medida que continúe escribiendo código de esta manera, eventualmente encontrará lugares donde el código en ambas clases sea similar o redundante. Si mueve estas piezas comunes de código de las distintas clases de versión, puede terminar con clases de versión que no solo implementen la misma interfaz, sino que también puedan implementar la misma clase base/abstracta. Voila, has encontrado tu camino hacia tu "primera" opción.

Creo que este es el mejor camino en un entorno con datos en constante evolución. Requiere cierta diligencia y "mirar hacia atrás" en el código anterior, pero vale la pena los beneficios de la claridad del código y los componentes reutilizables.

Otro pensamiento: en su ejemplo, la clase base es "Coche". En mi opinión, casi nunca resulta que la clase base esté tan "cerca" de sus herederos. Un conjunto más realista de clases de base o interfaces podría ser "Versionable", "Actualizable", "OptionContainer", etc. Simplemente hablando desde mi experiencia, YMMV.

+0

Bueno, tal vez dije que la última opción era un antipatrón porque no usa una clase base para dos representaciones del "mismo" objeto conceptual. "difícilmente resulta que la clase base esté tan cerca de sus herederos" - Sí, simplemente estaba tratando de idear un pequeño ejemplo para demostrar las metodologías. Entonces, ¿debo entender que recomendaría la tercera opción y que eso cambiaría a la primera si fuera necesario a medida que se escribía el código de la aplicación? –

+0

Sí, ese fue un resumen vergonzosamente breve de mi (larga) respuesta. –

+0

Estoy totalmente de acuerdo. –

1

utilizan el segundo enfoque y lo mejoran con las interfaces. recuerde que puede implementar múltiples "versiones" de interfaces que le otorgan la capacidad de compatibilidad con versiones anteriores. espero que usted obtendrá lo que quería decir;)

1

El ir en el siguiente requisito:

una aplicación que necesita para leer y trabajar con dos versiones de los datos de la misma manera

Diría que lo más importante es canalizar toda la lógica a través de una capa de abstracción de datos, de modo que ninguna de sus lógicas tenga que importar si está usando la versión 1, 2 o n de los datos .

Una forma de hacer esto es tener solo una clase de datos, que es la versión más "pulida" de los datos. Básicamente, tendría MoonRoofType, pero no HasMoonRoof, ya que eso se puede deducir.Esta clase tampoco debería tener propiedades obsoletas, ya que depende de la capa de abstracción de datos decidir cuáles deberían ser los valores predeterminados.

Al final, tendrá una aplicación que no se preocupa por las versiones de datos en absoluto.

En cuanto a la capa de abstracción de datos, es posible que desee o no tener clases de datos para cada versión. Lo más probable es que lo único que necesite es una clase para cada versión de la estructura de datos con los métodos Save y Load para almacenar/crear las instancias de datos utilizadas por la lógica de su aplicación.

Cuestiones relacionadas