Заводская или сервисная схема или метод впрыска? - PullRequest
3 голосов
/ 19 февраля 2010

В настоящее время я думаю о том, с каким шаблоном мне следует решить следующую проблему.

У меня есть сущность с именем IdentificationRequest.Этот объект используется для идентификации Person по некоторым критериям.

public class IdentificationRequest
{
     public IdentificationCriteria Criteria;
     public Person IdentifiedPerson;

     protected internal virtual void RedirectToManualIdentification()
     {
        ChangeState(IdentificationRequestState.ManualIdentificationRequested);
     }

     public virtual void StartManualIdentification()
     {
        ChangeState(IdentificationRequestState.ManualIdentificationInProgress);
     }

     public virtual void AssignIdentifiedPerson(Person person)
     {
        identifiedPerson = person;
        ChangeState(IdentificationRequestState.IdentificationFinished);       
     }
}

public class IdentificationCriteria
{
     public string Name;
}

Это упрощенный пример.В действительности IdentificationRequest содержит гораздо больше информации, а также IdentificationCriteria.

Таким образом, в основном клиент создает IdentificationRequest со своим IdentificationCriteria, и тогда необходимо определить правильный Person,Для этого критерии должны быть переданы на уровень постоянства, чтобы проверить, есть ли человек в базе данных, соответствующий критериям.Если человек не может быть найден, необходимо взаимодействие с человеком, чтобы назначить правильный Person для запроса.

Для процесса идентификации я в настоящее время использую сервис.Как:

    public class IdentificationService : IIdentificationService
        {
            private readonly IPersonRepository personRepository ;
            private readonly IIdentificationRequestRepository identificationRequestRepository;

            public IdentificationService(IPersonRepository personRepository )
            {
                this.personRepository = personRepository ;
            }

            public bool IdentifyPerson(IdentificationRequest identificationRequest)
            {
                var matches = personRepository.FindByIdentificationCriteria(identificationRequest.Criteria);

                // some additional post analysis of the matches returned from the persistence layer
                var criteriaAnalyzer = new IdentificationCriteriaAnalyzer(identificationRequest.Criteria);
                var uniqueMatch = criteriaAnalyzer.TryIdentify(matches);

                if(uniqueMatch != null)
                {
                    identificationRequest.AssignIdentifiedPerson(uniqueMatch);
                    return true;
                }
                else
                {
                    identificationRequest.RedirectToManualIdentification();
                    return false;
                }            
            }
        }

Этот сервис является частью сборки домена.Теперь мой вопрос, является ли это правильным шаблоном для идентификации?Или я бы использовал фабрику, чтобы создать запрос идентификации, а затем напрямую попытаться идентифицировать его, например:

public class IdentificationRequestFactory
{
    private readonly IPersonRepository personRepository;

    public IdentificationRequestFactory(IPersonRepository personRepository)
    {
        this.personRepository = personRepository;
    }

    public IdentificationRequest Create(IdentificationCriteria identificationCriteria)
    {
        var request = new IdentificationRequest(identificationCriteria);

        var matches = personRepository.FindByIdentificationCriteria(identificationRequest.Criteria);
        var criteriaAnalyzer = new IdentificationCriteriaAnalyzer(identificationRequest.Criteria);
        var uniqueMatch = criteriaAnalyzer.TryIdentify(matches);

        if(uniqueMatch != null)
        {
            identificationRequest.AssignIdentifiedPerson(uniqueMatch);

        }
        else
        {
            identificationRequest.RedirectToManualIdentification();

        }

        return request;
    }
}

Таким образом, IdentificationRequest может быть создан только фабрикой, убедившись, чтопроцесс идентификации уже завершен, и запрос находится в допустимом состоянии.

Или вы позволите IdentificationRequest идентифицировать себя, выполнив инъекцию метода, например:

public class IdentificationRequest
{
    public IdentificationCriteria Criteria;
    public Person IdentifiedPerson;

    public void Identify(IPersonRepository personRepository)
    {
        // identification logic here
    }
}

В этом примересвязать процесс идентификации с запросом напрямую.

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

Спасибо заранее!

Обновление

Возможно, я не правильно понимаю шаблон команды, но какие преимущества я получу?получить это в этом случае?Правильна ли следующая реализация?

public class IdentificationCommandFactory
{
    private readonly IPersonRepository personRepository;

    public IdentificationCommandFactory(IPersonRepository personRepository)
    {

        this.personRepository = personRepository;
    }

    public IIdentificationCommand Create(IdentificationRequest identificationRequest)
    {
        var matches = personRepository.FindByIdentificationCriteria(identificationRequest);
        var criteriaAnalyzer = new IdentificationCriteriaAnalyzer(identificationRequest);
        var uniqueMatch = criteriaAnalyzer.TryIdentify(matches);

        if(uniqueMatch != null)
        {                
            return new AssignIdentifiedPersonCommand(identificationRequest, uniqueMatch);
        }
        else
        {                
            return new RedirectToManualIdentificationCommand(identificationRequest);
        }    
    }

}

public interface IIdentificationCommand
{
    void Execute();
}

public class RedirectToManualIdentificationCommand : IIdentificationCommand
{
    private readonly IdentificationRequest identificationRequest;

    public RedirectToManualIdentificationCommand(IdentificationRequest identificationRequest)
    {
        this.identificationRequest = identificationRequest;
    }

    public void Execute()
    {
        identificationRequest.RedirectToManualIdentification();
    }
}

public class AssignIdentifiedPersonCommand : IIdentificationCommand
{
    private readonly IdentificationRequest identificationRequest;
    private readonly Person personIdentified;

    public AssignIdentifiedPersonCommand(IdentificationRequest identificationRequest, Person personIdentified)
    {
        this.identificationRequest = identificationRequest;
        this.personIdentified = personIdentified;
    }

    public void Execute()
    {
        identificationRequest.AssignIdentifiedPerson(personIdentified);
    }
 }

Вызывающая сторона:

    var identificationCommandFactory = new IdentificationCommandFactory(personRepository);

    var command = identificationCommandFactory.Create(request);

    command.Execute();

Ответы [ 3 ]

5 голосов
/ 19 февраля 2010

Основная цель вашей разработки должна состоять в том, чтобы удовлетворить требования с помощью самого простого и самого чистого кода.(http://msdn.microsoft.com/en-us/magazine/cc163962.aspx)

С учетом вышесказанного, если у вас нет конкретной причины использовать один из этих шаблонов, остановитесь сейчас. Если нет особых причин для перехода к этой работе, вы просто пишете больше кода наНадежда на то, что это когда-нибудь будет полезно. Просто напишите, что работает. Рефакторируйте это позже, если возникнет такая необходимость.

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

0 голосов
/ 19 февраля 2010

Мне кажется, что вы должны использовать шаблон команды:
- http://www.dofactory.com/Patterns/PatternCommand.aspx
- http://c2.com/cgi/wiki?CommandPattern
- http://en.wikipedia.org/wiki/Command_pattern

Также ваш IdentificationRequest не делаетне похоже на класс сущностей , но я бы охарактеризовал ваш класс Person как сущность.
Часто Invoker в Командном шаблоне отправляет ответ получателю, указывая успех или неудачу, и вв случае успеха объект ответа может содержать идентифицированную личность.

0 голосов
/ 19 февраля 2010

И ваши типы IdentificationCriteria, и IdentificationCriteriaAnalyzer очень похожи на Спецификации , так что я бы посмотрел, имеет ли смысл их рефакторинг в этом направлении.

Мне кажется, что класс IdentificationRequest нарушает Принцип единой ответственности - почему у него есть поле / свойство Person?

API также может выиграть от лучшего разделения команд и запросов .

Так что я думаю, что лучшей моделью было бы определение интерфейса, который принимает IdentificationCriteria и возвращает какую-то Command . Такой интерфейс, по сути, будет Абстрактная фабрика .

public interface IIdentificationCommandFactory
{
    IIdentificationCommand Create(IdentificationCriteria spec);
}

При его реализации вы можете искать совпадения в своем хранилище, и на основе результата этого запроса и ваших других спецификаций (таких как IdentificationCriteriaAnalyzer) вы можете вернуть правильную реализацию IIdentificationCommand.

Затем вызывающая сторона попросит выполнить возвращенную команду.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...