При реализации шаблона репозитория для моего проекта ASP.NET я столкнулся с некоторыми проблемами, на которых я не могу опустить голову. Поэтому у меня есть несколько вопросов о том, как правильно реализовать шаблон репозитория.
По моему опыту я считаю, что наличие классов/моделей без поведения только в моем приложении, рядом с их репозиториями, не является хорошим ООП. Но именно так я реализовал шаблон репозитория. Я просто делаю везде, где нужен экземпляр репозитория, для выполнения некоторых действий. Результатом этого подхода было то, что у всех моих классов домена не было поведения.
Они были просто объектами, содержащими данные без каких-либо методов. Мой учитель сказал мне, что я использую тонкие модели и что я должен стремиться делать толстые модели. В ответ на эту обратную связь я реализовал некоторую бизнес-логику в классах, но я столкнулся с некоторыми проблемами:
Сценарий:
В моем классе User
был список друзей с объектами пользователя в нем, чтобы представлять друзей определенного пользователя. При добавлении нового друга пользователю метод класса домена проверяет, существует ли "знакомый" в списке друзей. Если нет, он будет добавлен в список. Эти изменения необходимо отправить в базу данных для сохранения.
Я знаю, что это должно быть сделано в репозитории для каждого класса домена, но где вызовы методов репозитория принадлежат архитектуре приложения?
Сейчас я вызываю методы репозитория в самих методах класса домена, чтобы сохранить изменения в базе данных:
public void AddFriend(User friend)
{
foreach(User f in Friends)
{
if(f.Username == friend.Username)
{
throw new Exception(String.Format("{0} is already a friend.", friend.Username));
}
}
Friends.Add(friend);
userRepo.AddFriend(this.Id, friend.Id);
}
Это хороший подход, по какой-то причине я думаю, что нет. Что касается модульного тестирования, нам нужно с этим подходом использовать некоторую инъекцию зависимости, которая говорит мне, что это не независимый класс (хорошая проверяемая единица). Я прочитал несколько сообщений от людей, говорящих, что они используют дополнительный уровень обслуживания или что-то в этом роде. Я думаю, что здесь нужна такая абстракция, но как выглядит определенный слой обслуживания? Что в нем, какие методы и т.д.?
Я видел, как некоторые другие студенты использовали статические методы в классе домена, который обеспечивает такие функции, как добавление нового объекта, обновление объекта, удаление объекта и получение всех объектов.
Пример:
public class Tram
{
private static TramRepository Repo = new TramRepository(new DBTram());
public static void AddTram(int tramID, TramType type, int lineNr)
{
Tram tram = new Tram(tramID, type, TramStatus.depot, lineNr, true, null);
Repo.AddTram(tram);
}
public static List<Tram> GetAll()
{
Repo.GetAll();
}
}
Мне кажется странным, что метод добавляет новый объект в базу данных в классе домена, который является этим объектом. Также для метода GetAll() мне кажется странным иметь метод в самом классе, который получает все трамваи. Таким образом, трамвайный объект может получить все трамваи. Я думаю, что это странный способ реализации шаблона репозитория. Я прав?
Итак, какая абстракция нужна здесь? Должен ли быть дополнительный слой? Если да, то как выглядит этот слой? (Пример кода) Или я искал неправильное направление и есть ли другое решение, которое учитывает проблему модульного тестирования с шаблоном репозитория?
Эта проблема с архитектурой, с которой я сталкиваюсь каждый раз, убедилась, что мне нужно, чтобы она была отвечена.
Мне сложно объяснить эту проблему, но, надеюсь, вы это понимаете.