SRP를 따를 때 엔터티의 유효성 검사 및 저장을 어떻게 처리해야합니까?


10

내가 읽어 봤는데 클린 코드 최근 SOLID에 대한 다양한 온라인 기사를, 나는 아무것도 몰라처럼 더 나는 그것에 대해 읽고, 더 느낌.

나는이의 내가 ASP.NET MVC 3하자 말을 사용하여 웹 응용 프로그램을 짓고 있어요 가정 해 봅시다 UsersControllerCreate같은 조치 :

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

    }
}

해당 조치 방법에서 입력 한 데이터가 유효한 경우 사용자를 데이터베이스에 저장하려고합니다.

이제 단일 책임 원칙에 따르면, 개체는 단일 책임을 가져야하며, 그 책임은 전적으로 클래스에 의해 캡슐화되어야합니다. 모든 서비스는 그 책임과 좁게 조정되어야합니다. 데이터베이스에 대한 유효성 검사 및 저장은 두 가지 별도의 책임이기 때문에 다음과 같이 처리하기 위해 클래스를 분리해야합니다.

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);
        }
    }
}

즉하게 어떤 나에게 의미하지만 문제는이 같은 핸들 물건에 대한 권리 방법이라고 모두 확인에 아니에요. 의 잘못된 인스턴스를 전달하기 위해, 예를 들어 전적으로 가능하다 CreateUserViewModel받는 IUserService클래스입니다. 내장 DataAnnotations를 사용할 수 있다는 것을 알고 있지만 충분하지 않은 경우는 무엇입니까? 내 ICreateUserValidator이름이 동일한 다른 사용자가 있는지 데이터베이스를 확인한 이미지 ...

다른 옵션은 IUserService다음과 같이 유효성 검사를 처리 하도록하는 것입니다.

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;
    }
}

그러나 저는 여기서 단일 책임 원칙을 위반하고 있다고 생각합니다.

이런 식으로 어떻게 처리해야합니까?


user클래스가 유효성 검사를 처리 하지 않아야 합니까? SRP 여부, user인스턴스가 유효한지 여부를 알 수없는 이유를 알지 못하고 그것을 결정하기 위해 다른 것에 의존합니다. 반에는 어떤 다른 책임이 있습니까? 또한 user변경시 유효성 검사가 변경 될 수 있으므로 다른 클래스에 아웃소싱하면 밀접하게 연결된 클래스 만 생성됩니다.
sebastiangeiger

답변:


4

두 번째 예에서 단일 책임 원칙을 위반한다고 생각하지 않습니다.

  • UserService클래스는 변화에 단 하나의 이유가있다 : 당신이 사용자를 저장하는 방식을 변경할 필요가있을 경우.

  • ICreateUserValidator사용자를 확인하는 방식을 변경할 필요가있는 경우 : 클래스는 변경할 수있는 단 하나의 이유가있다.

첫 번째 구현이 더 직관적이라는 것을 인정해야합니다. 그러나 유효성 검사는 사용자를 만드는 엔터티에서 수행해야합니다. 제작자 자체는 유효성 검사를 책임지지 않아야합니다. 오히려 (두 번째 구현에서와 같이) 검증 자 클래스에 책임을 위임해야합니다. 따라서 두 번째 디자인에 SRP가 부족하다고 생각하지 않습니다.


1
단일 책임 패턴? 아마도 원리?
yannis

예, 물론 :) 수정했습니다!
Guven November

0

첫 번째 예는 실제 SRP와 "가까운"것 같습니다. 사물을 연결하는 방법과 ViewModel을 전달하는 방법을 아는 것은 컨트롤러의 책임입니다.

전체 IsValid / ValidationMessages를 ViewModel 자체의 일부로 만드는 것이 더 합리적이지 않습니까? MVVM을 다루지 않았지만 프레젠터가 프리젠 테이션과 직접 관련되어 있기 때문에 발표자가 그와 같은 일을 처리하는 것이 좋았던 구 모델 뷰-프레젠터 패턴처럼 보입니다. ViewModel이 유효성을 자체적으로 확인할 수 있으면 유효하지 않은 것을 UserService의 Create 메소드에 전달할 기회가 없습니다.


나는 항상 ViewModels가 너무 많은 논리가없는 간단한 DTO 여야한다고 생각했습니다. 나는 뷰 모델의 데이터베이스를 확인해 볼 같은 것을 넣어하는 경우는 내가 ... 잘 모르겠어요
크리스토프 Claes가

나는 그것이 당신의 검증이 수반하는 것에 달려 있다고 생각합니다. ViewModel이 IsValid부울 및 ValidationMessages배열 만 노출하는 경우 Validator 클래스를 계속 호출 할 수 있으며 유효성 검사 구현 방법대해 걱정할 필요가 없습니다 . 컨트롤러는 첫 번째 예를 확인할 수 있습니다 if (userViewModel.IsValid) { userService.Create(userViewModel); }기본적으로 뷰 모델이 알아야 할 경우 가 유효을,하지만 어떻게 그것을 알고는 유효합니다.
Wayne Molina
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.