Отделение уровня обслуживания от уровня проверки

В настоящее время у меня есть сервисный слой на основе статьиПроверка с помощью сервисного уровня с сайта ASP.NET.

В соответствии сэтот Ответ: это плохой подход, потому что логика обслуживания смешана с логикой валидации, которая нарушает принцип единой ответственности.

Мне действительно нравится альтернатива, которая предоставляется, но во время перефакторинга моего кода я столкнулся с проблемой, которую не могу решить.

Рассмотрим следующий интерфейс сервиса:

interface IPurchaseOrderService
{
    void CreatePurchaseOrder(string partNumber, string supplierName);
}

со следующей конкретной реализацией, основанной на связанном ответе:

public class PurchaseOrderService : IPurchaseOrderService
{
    public void CreatePurchaseOrder(string partNumber, string supplierName)
    {
        var po = new PurchaseOrder
        {
            Part = PartsRepository.FirstOrDefault(p => p.Number == partNumber),
            Supplier = SupplierRepository.FirstOrDefault(p => p.Name == supplierName),
            // Other properties omitted for brevity...
        };

        validationProvider.Validate(po);
        purchaseOrderRepository.Add(po);
        unitOfWork.Savechanges();
    }
}

PurchaseOrder объект, который передается в валидатор, также требует двух других объектов,Part а такжеSupplier (позволять'Предположим для этого примера, что PO имеет только одну часть).

ОбаPart а такжеSupplier объекты могут быть нулевыми, если данные, предоставленные пользователем, не соответствуют объектам в базе данных, которые требуют, чтобы валидатор выдал исключение.

У меня проблема в том, что на этом этапе валидатор потерял контекстную информацию (номер детали и имя поставщика), поэтому не может сообщить точную ошибку пользователю. Лучшая ошибка, которую я могу предоставить, - "Заказ на поставку должен иметь связанную часть " что не имеет смысла для пользователя, потому что он предоставил номер детали (он просто не существует в базе данных).

Используя класс обслуживания из статьи ASP.NET, я делаю что-то вроде этого:

public void CreatePurchaseOrder(string partNumber, string supplierName)
{
    var part = PartsRepository.FirstOrDefault(p => p.Number == partNumber);
    if (part == null)
    {
        validationDictionary.AddError("", 
            string.Format("Part number {0} does not exist.", partNumber);
    }

    var supplier = SupplierRepository.FirstOrDefault(p => p.Name == supplierName);
    if (supplier == null)
    {
        validationDictionary.AddError("",
            string.Format("Supplier named {0} does not exist.", supplierName);
    }

    var po = new PurchaseOrder
    {
        Part = part,
        Supplier = supplier,
    };

    purchaseOrderRepository.Add(po);
    unitOfWork.Savechanges();
}

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

Есть ли способ получить лучшее из обоих миров? Могу ли я отделить уровень обслуживания от уровня проверки, в то же время предоставляя информацию об ошибках того же уровня?

Ответы на вопрос(1)

Ваш ответ на вопрос