SRP'yi izlerken, varlıkların doğrulanması ve kaydedilmesi ile nasıl başa çıkmalıyım?


10

Ben okuyordum Temiz Kodunu son zamanlarda KATI hakkında ve çeşitli çevrimiçi makaleler ve ben hiçbir şey bilmiyorum gibi ne kadar fazla okumak, daha hissediyorum.

Diyelim ki ASP.NET MVC 3 kullanarak bir web uygulaması inşa ediyorum. Diyelim ki böyle UsersControllerbir Createeylem ile bir var :

public class UsersController : Controller
{
    public ActionResult Create(CreateUserViewModel viewModel)
    {

    }
}

Bu eylem yönteminde, girilen veriler geçerliyse kullanıcıyı veritabanına kaydetmek istiyorum.

Şimdi, Tek Sorumluluk İlkesine göre, bir nesnenin tek bir sorumluluğu olmalı ve bu sorumluluk tamamen sınıf tarafından kapsüllenmelidir. Tüm hizmetleri bu sorumlulukla dar bir şekilde uyumlu olmalıdır. Doğrulama ve veritabanına kaydetme iki ayrı sorumluluk olduğundan, sanırım bunları böyle ele almak için ayrı bir sınıf oluşturmak gerekir:

public class UsersController : Controller
{
    private ICreateUserValidator validator;
    private IUserService service;

    public UsersController(ICreateUserValidator validator, IUserService service)
    {
        this.validator = validator;
        this.service= service;
    }

    public ActionResult Create(CreateUserViewModel viewModel)
    {
        ValidationResult result = validator.IsValid(viewModel);

        if (result.IsValid)
        {
            service.CreateUser(viewModel);
            return RedirectToAction("Index");
        }
        else
        {
            foreach (var errorMessage in result.ErrorMessages)
            {
                ModelState.AddModelError(String.Empty, errorMessage);
            }
            return View(viewModel);
        }
    }
}

Yani kılan bazı bana mantıklı, ama bu böyle sap şeyler doğru yol olduğuna tüm emin değilim. Örneğin CreateUserViewModel, IUserServicesınıfa geçersiz bir örnek iletmek tamamen mümkündür . Yerleşik DataAnnotations'ı kullanabileceğimi biliyorum, ama yeterli olmadığında ne olacak? ICreateUserValidatorAynı ada sahip başka bir kullanıcı olup olmadığını görmek için veritabanımı kontrol eden resim ...

Başka bir seçenek, IUserServiceböyle bir doğrulamaya dikkat etmektir:

public class UserService : IUserService
{
    private ICreateUserValidator validator;

    public UserService(ICreateUserValidator validator)
    {
        this.validator = validator;
    }

    public ValidationResult CreateUser(CreateUserViewModel viewModel)
    {
        var result = validator.IsValid(viewModel);

        if (result.IsValid)
        {
            // Save the user
        }

        return result;
    }
}

Ama burada Tek Sorumluluk İlkesini ihlal ettiğimi hissediyorum.

Böyle bir şeyle nasıl başa çıkmalıyım?


userSınıf doğrulamayı yapmamalı mı? SRP ya da değil, userörneğin neden geçerli olup olmadığını bilmemeli ve bunu belirlemek için başka bir şeye güvenmemeliyim. Sınıfın başka sorumlulukları nelerdir? Ayrıca, userdeğişiklikler değiştiğinde muhtemelen değişecektir, bu nedenle farklı bir sınıfa dış kaynak kullanımı yalnızca sıkıca bağlı bir sınıf yaratacaktır.
sebastiangeiger

Yanıtlar:


4

İkinci örneğinizde Tek Sorumluluk İlkesini ihlal ettiğinizi gerçekten sanmıyorum.

  • UserServiceSınıf değişikliği için tek bir neden vardır: Bir kullanıcı kaydetmek biçimini değiştirmek için bir ihtiyaç varsa.

  • ICreateUserValidatorBir kullanıcıyı doğrulamak biçimini değiştirmek için bir ihtiyaç varsa: sınıf değiştirmek için yalnızca bir nedeni vardır.

İlk uygulamanızın daha sezgisel olduğunu itiraf etmeliyim. Ancak doğrulama, kullanıcıyı oluşturan kuruluş tarafından yapılmalıdır. Doğrulamadan içerik oluşturucunun kendisi sorumlu olmamalıdır; sorumluluğu bir validator sınıfına devretmeyi tercih etmelidir (ikinci uygulamanızda olduğu gibi). Yani, ikinci tasarımın SRP'den yoksun olduğunu düşünmüyorum.


1
Tek Sorumluluk-Desen? Prensip, belki?
yannis

Evet, elbette :) Düzeltildi!
Güven

0

Bana göre ilk örnek gerçek SRP'ye "daha yakın"; işleri nasıl kablolayacağınızı ve ViewModel'den nasıl geçeceğinizi bilmek sizin durumunuzdaki Denetleyicinin sorumluluğundadır.

Tüm IsValid / ValidationMessage'ın ViewModel'in bir parçası olması daha anlamlı olmaz mıydı? MVVM ile uğraşmadım, ancak Sunucunun doğrudan sunumla ilgili olması nedeniyle böyle şeyleri işlemesinin iyi olduğu eski Model-View-Presenter deseni gibi görünüyor. ViewModel'iniz geçerliliğini kontrol ederse, UserService'in Create yöntemine geçersiz bir tane iletme şansı yoktur.


Her zaman ViewModels'ın çok fazla mantığı olmayan basit DTO'lar olması gerektiğini düşündüm. Bir ViewModel veritabanı kontrol gibi bir şey koymak gerekir emin değilim ...
Kristof Claes

Validasyonunuzun neye bağlı olduğuna bağlı; ViewModel yalnızca IsValidboolean ve ValidationMessagesdiziyi açığa çıkarıyorsa, yine de bir Validator sınıfını çağırabilir ve doğrulamanın nasıl uygulandığı konusunda endişelenmek zorunda kalmaz . Kontrolör ilk önce örneğin if (userViewModel.IsValid) { userService.Create(userViewModel); }ViewModel'in geçerli olup olmadığını bilmesini kontrol edebilir , ancak geçerli olduğunu nasıl bildiğini kontrol edemez.
Wayne Molina
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.