Какова правильная степень абстракции от уровня данных?

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

Вариант 1. Первый и более простой (но, возможно, более связанный с базой данных) двухуровневый подход. В этом подходе сопоставители данных извлекают данные из базы данных и создают бизнес-объекты.

Примерная схема рабочего процесса:

UserEntity <= UserMapper => Database

Вариант 2. Второй и более гибкий (но, возможно, излишний) подход — это трехуровневый подход. В этом подходе у нас есть ТРЕТИЙ объект, работа которого заключается исключительно в том, чтобы обращаться к базе данных и возвращать массив данных в Data Mapper, который затем создает объект.

Грубая схема:

UserEntity <= UserMapper <= UserDataRetriever => Database

Очевидно, что преимущество первого варианта заключается в том, что его проще и, следовательно, быстрее создать. Преимущество второго варианта заключается в том, что проще изменить мои методы сохранения, так как мне нужно будет только изменить подключение моего DataRetriever к БД (и связанные запросы).

Поскольку этот сайт будет очень быстро расти, я хотел бы выбрать наиболее гибкий вариант, не вдаваясь в область антипаттернов.

Что лучше?


person johnnietheblack    schedule 14.03.2012    source источник


Ответы (2)


Я бы использовал следующее:

Entity <=> Repository pattern <=> DataSource

Репозиторий будет выполнять сопоставление (или использовать внутренний слой сопоставления).

Сам репозиторий может использовать ванильный ADO.NET и сопоставитель OR/M, веб-сервис или что-то еще.

person jgauffin    schedule 15.03.2012
comment
Спасибо за ответ - в этом случае репо знает о разговоре с БД? Это набор классов, каждый из которых создан для сущности? Я тоже сам поищу больше информации об этом... - person johnnietheblack; 15.03.2012
comment
Это набор классов, созданных для каждого корня и его агрегатов. то есть один для Order + OrderLines + OrderHistory и т. д. - person jgauffin; 15.03.2012

Что ж, диаграмма для Варианта 2 будет немного сложнее:

UserEntity <= UserMapper <= UserDataEntity <= UserDataRetriever => Database

UserMapper пришлось бы отображать один тип в другой, следовательно, UserDataEntity. Концептуально неудобно отображать напрямую из UserDataRetriever в UserEntity. Возможно, вы подразумеваете следующую диаграмму для второго варианта:

UserEntity <= UserMapper <= [list of arrays] <= UserDataRetriever => Database

В любом случае, Вариант 1 здесь отличается тем, что UserMapper включает в себя следующие функции: [list of arrays]/UserDataEntity <= UserDataRetriever.

Ни один из вариантов по своей сути не лучше. Это зависит от количества сущностей и от того, насколько легко сопоставить уровни сохраняемости и домена.

Вместо этого вы можете попробовать Вариант 1.5: ваш основной подход — это Вариант 1. В то же время вы разрабатываете UserMapper с отдельными и четко определенными методами для а) извлечения данных и б) сопоставления данных. Таким образом, вы начнете экономить и сможете легко реорганизовать эти методы в отдельные классы в будущем, если это необходимо.

person Yuriy Zubarev    schedule 15.03.2012
comment
Да, вы правы насчет добавления UserDataRetriever — я не включил его в пример, но определенно его использовал. И да, он возвращает набор массивов данных. Я мог бы сделать тот вариант 1,5, который вы предложили. Мне нравится возможность легкого рефакторинга :) - person johnnietheblack; 15.03.2012