Подтвердить что ты не робот

Как уровень сервиса вписывается в мою реализацию репозитория?

Я создал класс модели POCO и класс репозитория, который обрабатывает постоянство. Поскольку POCO не может получить доступ к репозиторию, в репозитории существует множество задач бизнес-логики, которые не кажутся правильными. Из того, что я прочитал, похоже, что мне нужен уровень сервиса, который находится между потребителями пользовательского интерфейса и уровнем репозитория. Я не уверен в том, как именно он должен работать...

В дополнение к служебному уровню, должен ли быть также отдельный уровень бизнес-логики, или это роль уровня обслуживания?

Должна ли быть одна служба в репозитории?

Является ли сервисный уровень единственным способом, которым пользовательский интерфейс может экземпляр объектов модели или репозиторий предоставляет экземпляр новой модели службе?

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

Может ли модель, репозиторий и пользовательский интерфейс совершать вызовы на уровне сервиса, или это просто для пользовательского интерфейса?

Предполагается ли, что сервисный уровень является всеми статическими методами?

Каким будет типичный способ вызова уровня сервиса из пользовательского интерфейса?

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

Вот пример кода для существующих слоев:

public class GiftCertificateModel
{
    public int GiftCerticiateId {get;set;}
    public string Code {get;set;}
    public decimal Amount {get;set;}
    public DateTime ExpirationDate {get;set;}

    public bool IsValidCode(){}
}


public class GiftCertificateRepository
{
    //only way to access database
    public GiftCertificateModel GetById(int GiftCertificateId) { }
    public List<GiftCertificateModel> GetMany() { }
    public void Save(GiftCertificateModel gc) { }
    public string GetNewUniqueCode() { //code has to be checked in db }

    public GiftCertificateModel CreateNew()
    {
        GiftCertificateModel gc = new GiftCertificateModel();
        gc.Code = GetNewUniqueCode();
        return gc;
    }              
}

UPDATE: В настоящее время я использую веб-формы и классический ADO.NET. Я надеюсь, что в скором времени вы перейдете на MVC и EF4.

ОБНОВЛЕНИЕ: Большое спасибо @Lester за его великое объяснение. Теперь я понимаю, что мне нужно добавить сервисный уровень для каждого из моих репозиториев. Этот уровень будет ТОЛЬКО способом, с помощью которого пользовательский интерфейс или другие службы могут связываться с репозиторием и будут содержать любые проверки, которые не подходят для объекта домена (например, - проверки, которые должны вызывать репо)

public class GiftCertificateService()
{

    public void Redeem(string code, decimal amount)
    {
        GiftCertificate gc = new GiftCertificate();
        if (!gc.IsValidCode(code))
        {
            throw new ArgumentException("Invalid code");
        }

        if (amount <= 0 || GetRemainingBalance(code) < amount)
        {
            throw new ArgumentException("Invalid amount");
        }

        GiftCertificateRepository gcRepo = new GiftCertificateRepository();
        gcRepo.Redeem(code, amount);
    }

    public decimal GetRemainingBalance(string code)
    {
        GiftCertificate gc = new GiftCertificate();            
        if (!gc.IsValidCode(code))
        {
            throw new ArgumentException("Invalid code");
        }

        GiftCertificateRepository gcRepo = new GiftCertificateRepository();
        gcRepo.GetRemainingBalance(code);
    }

    public SaveNewGC(GiftCertificate gc)
    {
        //validates the gc and calls the repo save method
        //updates the objects new db ID
    }

}

Вопросы

  • Я добавляю те же (и, возможно, больше) свойства к службе, как у меня на моей модели (количество, код и т.д.), или я предлагаю только методы, которые принимают объекты GiftCertificate и прямые параметры?

  • Создать экземпляр по умолчанию объекта GiftCertificate при вызове конструктора службы или просто создать новые по мере необходимости (например, для методов проверки в службе, которые должны вызывать методы проверки в сущности? Кроме того, тот же вопрос о создании экземпляра репозитория по умолчанию...?

  • Я знаю, что я раскрываю функциональность репо через службу, также я также выставляю методы из объекта (например, IsValidCode и т.д.)?

  • Это нормально для пользовательского интерфейса, чтобы просто создать новый объект GiftCertificate напрямую, не проходя через службу (например, - для вызова методов проверки параметров из объекта). Если нет, как обеспечить его соблюдение?

  • На уровне пользовательского интерфейса, когда я хочу создать новый подарочный сертификат, я могу вызвать валидации модели/услуги (например, IsValidExpirationDate и т.д.) непосредственно из уровня пользовательского интерфейса или сначала увлажнить объект, а затем передать он должен быть проверен, а затем возвратить какое-то подтверждение валидации обратно в пользовательский интерфейс?

Кроме того, если я хочу переустановить из уровня пользовательского интерфейса, я сначала вызываю методы проверки модели/службы из пользовательского интерфейса, чтобы дать пользователю обратную связь, а затем вызвать метод Redeem, который будет повторять те же проверки снова внутри?

Пример вызова службы для выполнения операции Redeem из пользовательского интерфейса:

string redeemCode = RedeemCodeTextBox.Text;

GiftCertificateService gcService = new GiftCertificateService();
GiftCertificate gc = new GiftCertificate(); //do this to call validation methods (should be through service somehow?)

if (!gc.IsValid(redeemCode))
{
    //give error back to user
}

if (gcService.GetRemainingBalance(redeemCode) < amount)
{
    //give error back to user
}

//if no errors
gcService.Redeem(code,amount);

Пример создания нового подарочного сертификата из пользовательского интерфейса:

GiftCertificateService gcService = new GiftCertificateService();
GiftCertificate gc = new GiftCertificate();

if (!gc.IsValidExpDate(inputExpDate))
{
    //give error to user..
}

//if no errors...
gc.Code = gcService.GetNewCode();
gc.Amount = 10M;
gc.ExpirationDate = inputExpDate;
gcService.SaveNewGC(gc);
//method updates the gc with the new id...

Что-то кажется неправильным в отношении того, как создаются GC и как разделяются проверки между сущностью/службой. Пользователь/потребитель не должен беспокоиться о том, какие валидации в каком месте... совет?

4b9b3361

Ответ 1

Посмотрите S # arp Architeture. Он похож на архитектурную инфраструктуру лучших практик для создания приложений ASP.NET MVC. Общий шаблон структуры должен иметь 1 репозиторий на сущность, который отвечает только за доступ к данным и 1 услугу на репозиторий, которая отвечает только за бизнес-логику и связь между контроллерами и службами.

Чтобы ответить на ваши вопросы на основе S # arp Architeture:

Помимо уровня обслуживания, должен быть также отдельный уровень бизнес-логики, или это роль уровня обслуживания?

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

Должен ли быть один сервисный уровень для каждого хранилища?

Да - должна быть одна служба для каждого репозитория (не один уровень обслуживания для каждого репозитория, но я предполагаю, что вы имели в виду это).

Является ли сервисный уровень единственным способом, которым пользовательский интерфейс может экземпляр объектов модели или репозиторий предоставляет экземпляр новой модели службе?

Репозитории и службы могут возвращать единый объект, коллекцию объектов или объекты передачи данных (DTO) по мере необходимости. Контроллеры передадут эти значения статическому конструкторному методу в модели, которая вернет экземпляр модели.

ex Использование DTO:

GiftCertificateModel.CreateGiftCertificate(int GiftCerticiateId, string Code, decimal Amount, DateTime ExpirationDate)

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

Модели проверяют значения на уровне поля ex. убедитесь, что ввод действителен, проверяя требуемые поля, возраст или диапазоны дат и т.д. Сервисы должны выполнять любую проверку, требующую проверки за пределами значения модели ex. Проверка того, что подарочный сертификат еще не был выкуплен, проверка свойств магазина для подарочного сертификата).

Могут ли модель, репозиторий и пользовательский интерфейс совершать вызовы на уровне службы или это просто для пользовательского интерфейса?

Контроллеры и другие службы должны быть единственными, кто делает вызовы на уровне сервиса. Услуги должны быть единственными, кто делает вызовы в репозитории.

Предполагается ли, что сервисный уровень является всеми статическими методами?

Они могут быть, но их проще поддерживать и расширять, если они не являются. Изменения в сущностях и добавление/удаление подклассов легче изменить, если есть 1 служба на сущность/подкласс.

Каким будет типичный способ вызова уровня обслуживания из пользовательского интерфейса?

Некоторые примеры контроллеров, вызывающих сервисный уровень:

giftCertificateService.GetEntity(giftCertificateId); (which in turn is just a call to the giftCertificateRepository.GetEntity(giftCertificateId)

giftCertificateService.Redeem(giftCertificate);

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

Уже ответил выше.

UPDATE

Поскольку вы используете WebForms, может быть немного сложнее понять некоторые из концепций, но все, о чем я упомянул, применимо, поскольку то, что я описываю, является общей парадигмой MVC. ADO.NET для доступа к данным не имеет значения, поскольку доступ к данным развязан через репозитории.

Добавляю ли я те же (и, возможно, больше) свойства к службе, как у меня на моей модели (количество, код и т.д.), или я предлагаю только методы, которые принимают объекты GiftCertificate и прямые параметры?

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

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

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

Я знаю, что я раскрываю функциональность репо через службу, также я также выставляю методы из объекта (например, IsValidCode и т.д.)?

Не слишком уверен, что вы имеете в виду здесь. Если службы возвращают объекты, то эти методы на объектах уже отображаются. Если они возвращают DTO, то это означает, что вас интересует только определенная информация.

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

. Пользовательский интерфейс позволяет просто создать новый объект GiftCertificate напрямую, не проходя через службу (например, - для вызова методов проверки параметров из объекта). Если нет, как обеспечить его соблюдение?

На уровне пользовательского интерфейса, когда я хочу создать новый подарочный сертификат, я могу вызвать валидации модели/услуги (например, IsValidExpirationDate и т.д.) непосредственно из слоя пользовательского интерфейса или сначала увлажнить объект, а затем передать он должен быть проверен, а затем возвратить какое-то подтверждение валидации обратно в пользовательский интерфейс?

Для этих двух вопросов можно перейти по сценарию:

Пользователь вводит информацию для создания нового сертификата и отправляет его. Существует проверка на уровне поля, поэтому, если текстовое поле является нулевым или если сумма доллара отрицательна, она выдает ошибку проверки. Предполагая, что все поля действительны, контроллер вызовет службу gcService.Save(gc).

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

Наконец, служба вызывает gcRepository.Save(gc).

Ответ 2

  • Вам не нужно создавать репозиторий на сущность, см. здесь для более,

    Обычно каждый определяет репозиторий за совокупность в домене. То есть: мы не имеют репозитория на сущность! Если мы рассмотрим простую запись заказа системы, заказ на организацию может быть корень совокупности заказов. Таким образом, мы будет иметь репозиторий заказов.

  • Должна ли быть одна служба на репозиторий? → Не всегда, поскольку вы можете использовать несколько репозиториев в одной службе.

  • Служба создает экземпляр модели, репозиторий никогда не будет взаимодействовать с Model, на самом деле он возвращает Entity, модель которой будет использоваться впоследствии.

  • Обработка ввода/диапазона и т.д. проверка правильности на уровне пользовательского интерфейса (вы можете использовать javascript или любую другую библиотеку) и позволить службам обрабатывать только бизнес-аспекты. Вы можете получить преимущества Атрибутов, которые будут делать то же самое.

  • UI- > Service- > Repository, если репозиторий вызывает услугу, чем thr должен быть чем-то неправильным IMO.


Вы изменяете код,

  • Разделите модель и хранилища.

    public class GiftCertificateModel
    {
    }
    public class GiftCertificateRepository
    {
       //Remove Model related code from here, and just put ONLY database specific code here, (no business logic also). Common methods would be Get, GetById, Insert, Update etc. 
    
        Since essence of Repository is to have common CRUD logic at one place soyou don't have to write entity specific code. 
        You will create entity specific repository in rare cases, also by deriving base repository.
    
    }
    
    public class GiftCertificateService()
    {
        //Create Model instance here
        // Use repository to fill the model (Mapper)
    
    }
    

Ответ 3

Вы можете создать службу под названием GiftCertificateService.

Таким образом вы будете координировать любую задачу, не относящуюся к ответственности GiftCertificateModel, в нее. (Не путать с сервисом WCF).

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

Затем служба будет вызывать методы на модели, использовать репозиторий, создавать транзакции и т.д.

Например, (на основе кода примера, который вы указали):

public class GiftCertificateService 
{
   public void CreateCertificate() 
   {
      //Do whatever needs to create a certificate.
      GiftCertificateRepository gcRepo = new GiftCertificateRepository();
      GiftCertificateModel gc = gcRepo.CreateNew();
      gc.Amount = 10.00M;
      gc.ExpirationDate = DateTime.Today.AddMonths(12);
      gc.Notes = "Test GC";
      gcRepo.Save(gc);
   }
}

Пользовательский интерфейс вызовет метод CreateCertificate (передача аргументов и т.д.), и метод также может вернуть что-то.

ПРИМЕЧАНИЕ. Если вы хотите, чтобы класс работал с пользовательским интерфейсом, тогда создайте класс контроллера (если вы делаете MVC) или класс презентатора (если вы делаете MVVM и не хотите помещать все в ViewModel ) и используйте службу GiftCertificateService из этого класса.