Должны ли несколько объектов уровня обслуживания совместно использовать DAO?
Вопрос
У меня есть класс Contact, который содержит объект PortalAccount .Когда я хочу создать "Учетную запись портала" для контакта, учетная запись создается удаленно в приложении портала с использованием soap / axis, а затем заполняется учетная запись portalAccount контакта и контакт сохраняется (локальная база данных содержит информацию об удаленной учетной записи, такую как идентификатор пользователя и имя пользователя и т.д.).
Итак, у меня есть класс сервиса PortalServiceImpl, который имеет методы для фактического создания пользователя на удаленном портале с учетом экземпляра Contact.
Учитывая всю эту информацию, мой вопрос тогда таков:должен ли PortalServiceImpl получать экземпляр объекта ContactDAO и фактически выполнять сохранение, или класс PortalServiceImpl должен просто создать удаленного пользователя, изменить переданный в Contact объект и позволить клиенту нести ответственность за сохранение?
Способ 1:
class ServiceFacadeImpl {
public void createPortalAccount(Contact contact) {
// here the contact is implicitly saved
this.portalService.createPortalAccount(contact);
}
}
Способ 2:
class ServiceFacadeImpl {
public void createPortalAccount(Contact contact) {
// here contact is implicitly modified
this.portalService.createPortalAccount(contact);
this.contactDAO.save(contact);
}
}
Оба метода кажутся мне неправильными.Метод 1 кажется неправильным, потому что PortalService создает удаленного пользователя И сохраняет контакт в базе данных (хотя и через интерфейс DAO).Метод 2 кажется неправильным, потому что я должен предположить, что PortalService изменяет Контакт, который я ему передаю.
У меня также есть ощущение, что я не вижу каких-то других недостатков, например, потенциально нерегулярной обработки транзакций.
(Кстати, я уже использовал оба метода и не хочу продолжать рефакторинг по бесконечному кругу.Просто здесь что-то кажется неправильным.)
Решение
Вы уверены, что это хорошая идея, что у вас есть разные идентификаторы контактов локально и удаленно?Мне это кажется неправильным, но, возможно, я просто не знаю вашего домена.
В моем приложении все новые контакты отправляются через веб-сервис на удаленный портал и сохраняются там.Итак, когда я сохраняю новый контакт локально, он отправляется на удаленный портал и сохраняется там.Может быть, вам нужно то же самое?
Если вышеприведенные мысли для вас неприемлемы, то я бы сделал это следующим образом:
class ServiceFacadeImpl {
public void CreatePortalAccountAndSaveContact(Contact contact) {
try
{
contact.portalAccount = this.portalService.createPortalAccount(contact);
this.contactDAO.save(contact);
}
catch(...)
{
// do cleanup, for example do you need to delete account from remote
// portal if it couldn't be saved locally?
// If yes, delete it from portal and set contact.portalAccount = null;
}
}
}
Некоторые могут сказать, что createportalaccount и Savecontact нарушают принцип единой ответственности, но imo в данной ситуации это абсолютно нормально, потому что, как я понимаю, вам нужно, чтобы эта операция была атомарной.Верно?
Или вы можете добавить к методу логический флаг, указывающий, хотите ли вы сохранить контакт.Но если вам всегда нужно сохранять контакт с PortalAccount сразу после получения его с удаленного портала - тогда логический флаг не нужен.
PS.Почему вы используете ключевое слово "this"?Является ли portalService закрытым участником?Если да, то, возможно, вам нужно пересмотреть свое соглашение об именовании и называть закрытых участников, например, с префиксом "_" (я думаю, что он самый популярный), как _portalService - тогда будет легко понять, что _portalService является закрытым участником.Извините за оффтопик.
Удачи.