검증은 어느 계층에 위치해야합니까?


18

Spring Boot를 사용하여 Rest API를 만들고 있으며 요청 입력의 유효성을 검사하기 위해 최대 절전 모드를 사용하고 있습니다.

그러나 업데이트 데이터를 확인해야 할 때와 같은 다른 종류의 유효성 검사도 필요합니다. 회사 ID가 존재하지 않으면 사용자 지정 예외를 throw하려고합니다.

이 유효성 검사가 서비스 계층 또는 컨트롤러 계층에 있어야합니까?

서비스 계층 :

 public Company update(Company entity) {
    if (entity.getId() == null || repository.findOne(entity.getId()) == null) {
        throw new ResourceNotFoundException("can not update un existence data with id : " 
            + entity.getId());
    }
    return repository.saveAndFlush(entity);
}

컨트롤러 레이어 :

public HttpEntity<CompanyResource> update(@Valid @RequestBody Company companyRequest) {
    Company company = companyService.getById(companyRequest.getId());
    Precondition.checkDataFound(company, 
        "Can't not find data with id : " + companyRequest.getId());

    // TODO : extract ignore properties to constant

    BeanUtils.copyProperties(companyRequest, company, "createdBy", "createdDate",
            "updatedBy", "updatedDate", "version", "markForDelete");
    Company updatedCompany = companyService.update(company);
    CompanyResource companyResource = companyAssembler.toResource(updatedCompany);
    return new ResponseEntity<CompanyResource>(companyResource, HttpStatus.OK);
}

답변:


8

컨트롤러 계층과 서비스 계층 모두 특정 인터페이스를 노출합니다. 인터페이스는 인터페이스 사용 방법에 대한 계약을 정의합니다. 계약은 일반적으로 어떤 인수 (및 그 유형과 값)가 예상되고 어떤 예외가 발생하며 어떤 부작용이 발생하는지 등을 의미합니다.

이제 유효성 검사는 기본적으로 컨트롤러 update () 메서드와 서비스 계층 update () 메서드 계약을 시행합니다. 둘 다 매우 유사한 계약을 가지고 있기 때문에 검증 (계약의 시행)도 공통적 일 경우 당연합니다.

이를 수행 할 수있는 한 가지 방법은이 계약의 유효성 검증을 분리하여 두 계층 모두에서 호출하는 것입니다. 이것은 일반적으로 가장 명확합니다. 각 클래스 / 방법은 자체 계약을 시행하지만 성능 (데이터베이스 액세스) 또는 기타 이유로 인해 실용적이지 않은 경우가 많습니다.

다른 가능성은 서비스 계층 계약에서 유효성 검증에 실패한 경우 동작을 명시 적으로 정의하면서이 유효성 검증을 서비스 계층에 위임하는 것입니다. 서비스 계층은 일반적으로 일부 일반 유효성 검사 오류 (또는 예외 발생)를 반환하고 컨트롤러 계층은 특정 방식으로 오류에 반응하기를 원할 것입니다.이 경우 수신 요청이 잘못되었다는 신호에 400 개의 잘못된 요청을 반환합니다.

이 디자인에서는 서비스 계층의 비즈니스 로직 (일반적이어야 함)과 컨트롤러 (통합 논리를 처리하는) 사이에 너무 많은 연결 위험이 있습니다.

어쨌든, 이것은 논란의 여지가있는 질문이며 100 명의 사람들이 100 개의 답변으로 대답 할 것입니다. 이것은 단지 내 취향입니다.


1

서비스 계층에서 입력을 확인해야합니다.

"ID를 찾을 수 없습니다"는 논리적 오류 조건입니다. 따라서 컨트롤러 레이어에서 던져 져야합니다.

이것은 다시 레이어 / 디자인에 달려 있습니다.
서비스 계층에서 수행 할 작업 및 컨트롤러 계층에서 예상되는 작업


대답은 질문에서 추가 설명을 요구해서는 안됩니다. 질문에 대한 설명이 필요한 경우 너무 명확하지 않은 경우에는 주석을 달고 종결 될 수 있도록 플래그를 지정해야합니다. 그렇습니다, 나는 당신이 그 행동들 중 어느 것으로도 명성이 없다는 것을 알고 있습니다.

"입력 확인"이 모호합니다. 예를 들어, 필수 속성을 필드에 입력하여 채워야 함을 나타낼 수도 있지만 예를 들어 한 필드 값이 다른 값보다 큰지 확인하는 복잡한 사용자 정의 속성을 넣을 수도 있습니다. IMHO, 비교 유효성 검사는 컨트롤러 계층보다 훨씬 많은 비즈니스 서비스 계층을 "냄새"냅니다.
JustAMartin

1

최대 절전 모드 유효성 검사는 데이터 무결성 을 검사 합니다. bbdd의 RuntimeExceptions을 피하기 위해. Constrains로 제어해야하는 것과 거의 동일한 유효성 검사 입니다. 비즈니스 계층 만 지속성 계층을 제공 해야하므로 비즈니스 계층에서 제공되는 데이터의 권리를 신뢰할 수도 있고 신뢰할 수도 있습니다.

DAO에 유효성 검사를 넣지 않습니다. 상위 계층의 유효한 데이터가 필요합니다. 오류가있는 경우, 내용을 숙지 할 책임을 bbdd에 위임합니다.

그런 다음 비즈니스 계층에서 유효성 검사가 제공됩니다. 모든 비즈니스 검증 은 데이터 의 무결성이 아니라 데이터의 일관성 을 유지하는 데 중점을 두었습니다 .

마지막으로 컨트롤 레이어에서 이전 유효성 검사를 수행합니다. 그러한 레이어에만 관련된 것들.

비즈니스 계층에 어떤 검증이 적용되는지 곧 알 수 있습니다. 가장 일반적인 ID 컨트롤입니다. 이것은 두 계층에서 쉽게 구현할 수 있습니다. 비즈니스 계층을 소비하는 많은 컨트롤러 또는 클라이언트가있는 경우 모든 곳에서 동일한 유효성 검사를 반복하는 대신 비즈니스 계층에 배치하는 것이 좋습니다.

때로는 컨트롤러에는 다른 외관에서 재현되지 않는 자체 규칙과 조건이 있습니다. 그런 다음 그러한 컨트롤러에 넣을 후보입니다.

당신이 무엇을 검증하고 있는지, 그리고 무엇이든 관계없이 모든 사람에게 적용하고 싶다면 생각하십시오. 또는 상황에 맞는 검증 인 경우 ( "특정 컨트롤 / 뷰 파사드에서만 발생하는 것을 검증하고 있습니다).


0

Java 상점에서는 의도적으로 웹 위젯 유효성 검증을 세 개의 개별 조작으로 분할했습니다.

  1. 기본 형식-숫자는 숫자 여야합니다. 날짜는 유효한 날짜 등이어야합니다. 일반적으로이 유효성 검증은 무료로 제공됩니다. 위젯 컨텐츠를 모델에 바인딩 할 때 웹 프레임 워크가이를 수행합니다.
  2. 단일 위젯 유효성 검사-날짜는 과거 여야합니다. 정수는 1과 100 사이 여야합니다. customerId는 데이터베이스 등에 존재해야합니다. 대부분의 경우 컨트롤러 계층에 속하지만 데이터 저장소의 지원이 필요할 수 있습니다.
  3. 교차 위젯 유효성 검사-체크 아웃 날짜는 체크인 날짜 이후 여야합니다. 사망일은 생년월일 이전 일 수 없습니다. 이것은 확실히 비즈니스 규칙 유효성 검사입니다. 우리는 이것을 컨트롤러 계층에도 넣는 경향이 있지만 재사용 할 수 있도록 비즈니스 유효성 검사기로 옮길 수도 있습니다.

레이어 1이 실패하면 2 또는 3을 확인하지 않습니다. 마찬가지로 1이 성공하고 2가 실패하면 3을 수행하지 않습니다. 그러면 가짜 오류 메시지가 생성되지 않습니다.

위젯 컨텐츠가 아닌 REST 호출의 값에 대해 요청하지만 동일한 원칙이 적용됩니다.


-1

컨트롤러가 없으므로 다른 옵션을 선택해야합니다. 분명히 탈취 규칙은 한 곳에 있어야하며, 이것이 당신의 결정에있어서 또 다른 제약입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.