MVC와 함께 서비스 계층 사용


13

컨트롤러가 너무 뚱뚱해지고 모델 인스턴스화가 더해지기 시작하면 서비스 계층을 사용할 수 있습니다.

  • 서비스 클래스 내부의 논리를 래핑하면 한두 가지 방법으로 많은 서비스를 얻을 수 있습니다. 이것은 코드 냄새처럼 느껴집니다. 이것에 관한 모범 사례?

  • 서비스가 모델을 인스턴스화 할 수 있습니까?

  • 서비스가 모델을 인스턴스화하면 서비스를 단위 테스트 할 수 없습니다. 통합 테스트로만 커버 할 수 있습니까?

답변:


25

'SOLID'에서 'I'는 인터페이스 분리를 ​​나타냅니다. 이 원칙의 전체 아이디어는 큰 인터페이스를 더 작은 모듈로 분할하는 것입니다. MVC 서비스에서는 일반적으로 컨트롤러가 의존하는 인터페이스가 있습니다. 컨트롤러가 해당 서비스의 구체적인 구현에 대해 알기를 원하지 않습니다. 따라서 한두 가지 방법으로 여러 서비스를 제공하는 것이 좋습니다.

일반적으로 서비스는 큰 응용 프로그램 또는 도메인 모델의 작은 응용 프로그램에서 직접 DTO를 반환합니다. DTO는 일반적으로 더 많은 작업을 의미하지만 우려를 더 잘 분리합니다. 일반적인 흐름은 다음과 같습니다.

  • 컨트롤러 호출 서비스
  • 서비스가 개체를 반환합니다 (DTO, 도메인 모델 또는 다른 것)
  • 컨트롤러가 DTO / 도메인 모델을 뷰 모델에 매핑

매핑은 수동으로 수행 할 수 있지만 대부분의 개발자는 배관 코드 작성을 좋아하지 않고 매우 게으 르기 때문에 Automapper와 같은 자동 매핑 프레임 워크를 선호합니다.

http://en.wikipedia.org/wiki/Interface_segregation_principle

https://github.com/AutoMapper/AutoMapper

DTO 및 도메인 모델 사용과 관련하여 stackoverflow에 대한 여러 토론 중 하나 : https : //.com/questions/2680071/dto-or-domain-model-object-in-the-view-layer


1
여기 자동 매퍼를 사용하는 데주의를 기울여야합니다. uglybugger.org/software/post/…
Daniel Little

AutoMapper에는 단위 매핑 기능이 내장되어있어 모든 매핑 루틴을 한 줄로 확인할 수 있습니다. 이 게시물의 저자는 언급하지 않았습니다.
CodeART

그러나 그는 그것에 대해 알고 그것을 사용했습니다. 코멘트는 이것에 조금 들어갑니다.
Daniel Little

2
하나 또는 두 개의 메소드 만있는 많은 클래스는 일반적으로 응집력이 없음을 의미합니다. 서비스 계층 (있는 경우)은 대부분의 논리가 모델에 있으므로 얇아 야합니다. 속성 백에 불과한 바보 같은 객체에 뷰를 바인딩하는 것은 오히려 의미가없는 것 같습니다. MVC의 모델은 빈혈이 아닌 리치 도메인 모델이어야합니다. martinfowler.com/bliki/AnemicDomainModel.html
Andy

3

MVC에서 모델은 DTO 또는 관리자 / 서비스 집합이 아니라 응용 프로그램이 모델링하는 개념을 나타냅니다. 이것을 전체 도메인 또는 상태와 행동을 포함한 비즈니스 로직으로 생각할 수 있습니다. 이제 컨트롤러의 목적이 좀 더 명확 해졌다는 것을 알았습니다. 작업은 단순히 명령을 모델로 변환하고 결과를 다시 뷰로 변환하는 것입니다. 이것은 일반적으로 MVC의 모델과 다르지만 종종 혼동되는 ViewModel의 형태로 수행됩니다.

잘 정의 된 모델이없는 경우 해당 로직의 대부분이 이제 컨트롤러 자체에있는 지점에 도달했을 수 있습니다. 이 시점에서 컨트롤러 크기를 줄이기 위해이 논리를 관리자 또는 서비스 개체로 다시 가져 오기 시작할 수 있습니다. 이러한 서비스는 일반적으로 DTO / Entity와 같은 개체에서 반환 및 작동합니다. 그런 다음 컨트롤러는 이러한 서비스와 뷰 모델 간의 매핑 계층이됩니다. 매핑에 대한 몇 가지 유용한 팁을 보려면이 기사를 살펴보십시오. 친구는 친구가 AutoMapper를 사용하지 못하게 합니다.

귀하의 질문에 관해서는, 첫 번째 질문은 귀하의 응용 프로그램에 달려 있습니다. 컨트롤러에서 로직을 제거한 후에는 더 분명 해져야하는 방식으로 리팩토링을 수행해야합니다. 테스트에 관해서는 서비스 내부에서 모델을 인스턴스화하는 데 문제가 없지만 테스트가 어렵다는 것을 발견하면 단일 책임으로 서비스를 더 작은 부분으로 나눌 필요가 있다는 신호 일 것입니다.


3

컨트롤러는 비즈니스 로직이 발생하는 모델에 대한 호출 만 포함해야하며 이러한 호출을 기반으로 뷰에 데이터를 할당합니다 (정보 또는 오류 메시지). 따라서 컨트롤러가 여전히 복잡한 경우 매우 복잡한 페이지에서도 컨트롤러는 매우 작습니다. 매우 커짐에 따라 해당 페이지를 더 많은 페이지로 확장해야한다고 생각해야합니다.

여전히 모델은 상당히 클 수 있습니다 ... 내가 찾은 솔루션에는 컨트롤러에 변수가있어로드 할 모델과 특정 작업에 대해 특정 모델을로드하는 것을 알려줍니다.

다음과 같이 모델 뷰 컨트롤러 모델을 깨끗하게 준수하십시오.

  • 보기 : 데이터를 표시합니다
  • 컨트롤러 : 사용자 입력을 수집하고 요청 된 데이터를 모델에 요청한 후 다시보기로 보냅니다.
  • 모델 : 데이터베이스와 상호 작용하고 정보를 준비하기위한 논리적 조치를 수행합니다.

-1

하나 이상의 컨트롤러가 수행해야 할 수도 있고 컨트롤러의 일부가 될 정도로 구체적이지 않은 로직을 수행하는 데 도움이되는 서비스가 컨트롤러가 너무 커서 읽기가 너무 어려워지는 것을 막습니다. .

나는 "모델 (bussiness logic이 발생한 곳)"이라고 말했을 때 개인적으로 'aaa'에 동의하지 않습니다. 그것이 컨트롤러를 가지고있는 모든 이유이기 때문에, 제 생각에 모델은 간단한 데이터 추상화자가되어야 컨트롤러가 필요한 작업을 수행 할 수 있습니다. 다시 서비스가 데이터 추상화 작업에 관여해서는 안됩니다 ...

그냥 요 ..


1
모델이 dto 인 경우 빈혈 도메인 모델 antipattern martinfowler.com/bliki/AnemicDomainModel.html
Andy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.