2010-01-23 4 views
5

Когда вы пишете приложение, которое должно читать и работать с двумя версиями данных таким же образом, как лучше всего структурировать классы для представления этих данных. Я придумал три сценария:Каков предпочтительный способ хранения различных версий данных?

  1. Общих баз/Отдельные дети
  2. Союза Data
  3. отдельных структуры

Версия 1 Пример автомобили

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

Version 2 автомобиля

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

Common Base/Особые дети

С помощью этого метода есть базовый класс общих полей между двумя версиями данных и дочерним классом для каждой версии данных.

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; 
} 

Сильные

  • OOP Paradigm

Слабости

  • Существующие дочерние классы должны измениться, если новая версия выпущена, который удаляет общее поле
  • Данные для одного конца eptual unit разделяется между двумя определениями не из-за какого-либо деления, значимого для себя.

Союз данных

Здесь, автомобиль определяется как объединение полей автомобилей во всех версиях данных.

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 
} 

Сильные

  • Гм ... Все это в одном месте.

Слабости

  • Принудительный случай управляемый код.
  • Сложно поддерживать, когда удалена другая версия или унаследовано.
  • Трудно концептуализировать. Значения полей изменены в зависимости от версии.

Четкие структуры

Здесь структуры не имеют отношения к ООП друг с другом.Однако интерфейсы могут быть реализованы обоими классами, если/когда код ожидает их обработки одинаковым образом.

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; 
} 

Сильные

  • прямолинейный подход
  • Простота в обслуживании, если новая версия добавляется или удаляется наследство.

Слабости

  • Это анти-модель.

Есть ли лучший способ, о котором я не думал? Вероятно, очевидно, что я предпочитаю последнюю методологию, но первая лучше?

ответ

1

Почему третий вариант, различные структуры для каждой версии, плохая идея или анти-шаблон?

Если две версии структур данных используются в общем приложении/модуле - им придется реализовать один и тот же интерфейс. Период. Невозможно написать два разных модуля приложения для обработки двух разных версий структуры данных. Тот факт, что базовая модель данных чрезвычайно отличается, не имеет значения. В конце концов, целью написания объектов является достижение практического уровня инкапсуляции.

Поскольку вы продолжаете писать код таким образом, вы должны в конечном итоге найти места, где код в обоих классах подобен или избыточен. Если вы переместите эти общие части кода из разных классов версий, вы, возможно, в конечном итоге закончите с классами версий, которые не только реализуют один и тот же интерфейс, но также могут реализовать тот же базовый/абстрактный класс. Вуала, вы нашли свой путь к своему «первому» варианту.

Я думаю, что это лучший путь в среде с постоянно меняющимися данными. Это требует некоторого усердия и «заглядывания» на старый код, но стоит преимуществ четкости кода и многоразовых компонентов.

Другая мысль: в вашем примере базовый класс - «Автомобиль». На мой взгляд, вряд ли когда-либо окажется, что базовый класс настолько «близок» к его наследникам. Более реалистичным набором базовых классов или интерфейсов может быть «Версия для печати», «Модернизация», «OptionContainer» и т. Д. Как раз из моего опыта, YMMV.

+0

Ну, может быть, я сказал, что последний вариант был анти-шаблоном, поскольку он не использует базовый класс для двух представлений «того же» концептуального объекта. «вряд ли получится, что базовый класс так близок к его наследникам» - Да, я просто пытался придумать короткий пример, чтобы продемонстрировать методологии. Итак, я должен понять, что вы будете отстаивать третий вариант и что это будет морфировать до первого, если необходимо, в виде кода приложения? –

+0

Да, это было смущающе кратким изложением моего (длинного) ответа. –

+0

Я полностью согласен. –

1

использовать второй подход и улучшить его с помощью интерфейсов. помните, что вы можете реализовать несколько «версий» интерфейсов, что дает вам возможность обратной совместимости! я надеюсь, что вы получите то, что я хотел сказать;)

1

Переход по следующему требованию:

приложение, которое нужно читать и работать с двумя версиями данных таким же образом

Я бы сказал, что самое главное, что вы производите всю логику через уровень абстракции данных, так что ни одна из ваших логических систем не будет заботиться о том, используете ли вы версии 1, 2 или n данных ,

Один из способов сделать это состоит в том, чтобы иметь только один класс данных, то есть наиболее «зашифрованную» версию данных. В принципе, это было бы MoonRoofType, но не HasMoonRoof, так как это можно сделать.У этого класса также не должно быть никаких устаревших свойств, так как уровень абстракции данных зависит от того, какие значения по умолчанию должны быть.

В конце концов, у вас будет приложение, которое вообще не заботится о версиях данных.

Что касается уровня абстракции данных, вы можете или не хотите иметь классы данных для каждой версии. Скорее всего, все, что вам понадобится, - это один класс для каждой версии структуры данных с методами Save и Load для хранения/создания экземпляров данных, используемых вашей логикой приложения.

Смежные вопросы