MVC : 비즈니스 로직을 어디에 넣을까요? [닫은]


81

우선, 나는 이것에 대한 많은 질문을 보았지만 그 뒤에 충분한 추론이 없습니다. 내 질문이 충분하지 않아 제거해야하는 경우 이해하겠습니다.

나는 한 번 봐 촬영 한 예를 들어, 과 45+는 대답 그는 꽤 논리적 소리 모델에서 비즈니스 로직을 넣어 당신을 조언 말한다을 투표했다.

그러나 내 첫 번째 대규모 프로젝트는 컨트롤러에서 모든 BL을 완전히 사용하여 수행했습니다. 왜냐하면 이러한 사항에 의문을 제기하지 않았고 AccountController양식 인증이있는 MVC를 선택하면 자동으로 추가되는 방법을 살펴 보았 기 때문입니다 . 모든 방법은 BL로 꽤 채워져 있습니다. 아니면 추가 할 수있는 최소한의 코드 일 수도 있고 제가 간과하고있는 것일까 요?

유튜브의 한 사람이 그의 모델에 모든 논리를 담아 그가 옳은지 물었고 처음에는 그렇지 않았습니다! 그런 다음 나는 그가 옳다고 생각하기 시작했습니다!?

결국, 비즈니스 로직은 어디에 두어야할까요? 모델 클래스에 있다면 컨트롤러에있는 메소드에서 얼마나 많은 코드가 정상으로 간주되어야합니까? 컨트롤러의 모델에서 일부 메서드를 호출 한 다음 뷰로 돌아가는 한 줄?


1
비즈니스 로직은 컨트롤러에 들어갑니다. 모델 로직은 모델에 들어갑니다. 모델 로직은 모델을 구체적으로 / 오직 처리하는 것입니다. Setters / getters / properties / adders / removers, etc.
crush

1
@crush : 동의하지 않습니다. . 내가 읽은 것처럼 - 비즈니스 로직 "A 모델 객체는 응용 프로그램의 데이터를 보유" "와"컨트롤러 관계를 모델 객체와 뷰 객체를 서로. "
ChiefTwoPencils

@BobbyDigital-소스에 대한 링크를 제공 할 수 있습니까? :)
Andrius Naruševičius

물론 The Big Nerd Ranch Guide 의 적절한 MVC 사용에 대한 설명에 있지만 불행히도이를 확인하려면 책을 구입해야합니다.
ChiefTwoPencils

나는 C # 책에서 이것을 확인하려고 시도했지만 asp.net에서 비즈니스 로직은 최상위 계층이 UI, 중간이 컨트롤러, 하단이 db 인 중간 계층에 있습니다. 그러나 그들은 MVC에 대해 구체적으로 / 명시 적으로 말하는 것이 아닙니다. 이것은 프로그래머를위한 C # 에서 온 것입니다. :)
ChiefTwoPencils

답변:


54

몇 가지 이유로 모델에 도메인 로직을 넣는 것을 선호합니다.

  1. 모델에는 UI 코드가 없어야하므로 테스트하기가 더 쉽습니다. 가능할 때마다 UI 코드를 작성하기 전에 완전히 작동하는 (완전한 테스트 범위를 의미하는) 모델을 갖고 싶습니다. 컨트롤러는 모델이 올바른 일을하고 있다고 믿고 UI 문제 만 처리 할 수 ​​있습니다.

  2. 컨트롤러에 도메인 로직을 넣는 경우 다른 앱간에 또는 다른 컨트롤러간에 공유하기가 쉽지 않습니다.


2
예, #2컨트롤러간에 공유하기가 어려웠 기 때문에 정말 마음에 듭니다 (정적 방법을 사용해야 함)!
Andrius Naruševičius

네 @ AndriusNaruševičius, 그러지 마세요. 다른 컨트롤러에 의존하지 말고 컨트롤러에 종속성을 주입해야합니다.
Mark Walsh

이 답변은 ASP.Net MVC "모델"(MVVM 패턴의 일부)과 관련이없는 "도메인 모델"(고전적인 MVC 패턴의 M 부분)에 대해 이야기한다고 생각합니다.
Alexei Levenkov 2011

1
그래서 ... 여러 모델에 의존하는 논리를 어디에 두나요?
Kolob Canyon

1
@Ferrucio 그것은 나쁜 해결책입니다. 생성 될 다른 개체에 의존하는 개체를 만드는 "종속성 지옥"에있게됩니다. 불필요하거나 사용하지 않는 데이터가 이유없이 전달되기 때문에 잘못된 솔루션입니다. 함수가 작업을 수행하는 데 필요한 것만 취하기를 원합니다. 그렇지 않으면 코드가 매우 빠르게 불명확 해집니다. 더 나은 솔루션은 최소한의 구성 만 취하는 비즈니스 논리 클래스를 만드는 것입니다 (또는 더 나은 방법은 종속성 주입을 사용하여 구성하는 것입니다). 이렇게하면 비즈니스 로직을 수행하기 위해 관련되지 않은 여러 개체를 가져 오지 않아도됩니다.
Kolob Canyon

43

나는 내 모델을 속성과 비즈니스 로직없이 깨끗하게 유지하는 것을 좋아합니다. 나는 항상 컨트롤러에 종속성을 주입하는 것이 좋다고 생각하며 이러한 종속성에는 내 모델에서 수행하는 논리가 포함되어 있습니다. 가능한 경우 단일 책임 원칙을 고수하는 것을 좋아하며 수많은 방법을 가진 모델이 매우 빠르게 부풀어 오르는 것을 발견했습니다. 둘 다 장점과 단점이 있습니다. 많은 종속성을 주입하면 오버 헤드가 발생하지만 격리 된 상태에서 테스트 할 수 있고 클래스를 단순하게 유지하고 결국 더 간결한 컨트롤러를 갖게됩니다. 내 논리는 클래스의 구성원으로 모델에 실제로 존재하지 않지만 여전히 비즈니스 논리입니다. Httpcontext와 같은 것을 조롱하는 것은 약간 악몽이고 불필요하기 때문에 컨트롤러에 비즈니스 로직을 정의하지 않는 경향이 있습니다.


5
+1은 완전히 동의합니다. 모델의 책임을 최소한으로 유지하는 것을 좋아하는 사람은 나 뿐이라고 생각했습니다!
Lee

1
물론, 그는 내 로그인 컨트롤러에 대한 요점이다 gist.github.com/markwalsh-liverpool/8fb361a9df0dcf034caf은
마크 월시

1
따라서 모델이나 컨트롤러에 로직을 넣지 않으면 어디에 넣을까요?
niico 2011 년

1
컨트롤러의 생성자에 인수를 어떻게 전달합니까? 컨트롤러의 초기화는 일반적으로 무대 뒤에서 이루어지지 않습니까?
제프

1
나는 의존성 주입을 사용합니다.
Mark Walsh

23

비즈니스 로직은 문제의 도메인이 간다 속하는 문제 도메인과 모든에 속하는 모델 MVC한다.

컨트롤러는 뷰와 모델에보기 뒷면에서 모델로부터 데이터를 전달하는 책임을 져야한다. 따라서 컨트롤러는 사용자가 상호 작용하는 것과 프로그램이 문제의 상태를 모델링하고 저장하는 방법 사이의 다리 역할을합니다. 배관 , 말하자면.

여기서 핵심은 비즈니스 로직과 배관 로직의 차이입니다. 제 생각에는 자동 생성 된 계정 컨트롤러가하는 일은 실제로 비즈니스 로직이 아니라 대부분 배관 작업입니다. 배관 논리가 반드시 짧지는 않으므로 인위적인 제한을 부과 할 필요가 없습니다 (예 : "컨트롤러에서 최대 X 호출 수").


나는이 모든 것에 동의합니다. 그러나 EF를 사용하여 모델에서 클래스를 구성하는 방법에서 많은 혼란이 발생한다고 생각합니다. IE : 부분 클래스를 사용하고 다른 C # 파일에서 논리를 작성합니까? EF 용 파일 하나와 논리 용 파일 하나?
S1r-Lanzelot

13

우리 팀은 웹 양식 (asp.net)에서 mvc로 옮겼을 때 많은 연구를 수행했으며 다음 구조를 생각해 냈습니다. 나에 따르면 응용 프로그램이 얼마나 크거나 작은 지에 대한 것이 아닙니다. 코드를 깨끗하고 명확하게 유지하는 것입니다.

DAL 프로젝트

AccountsDAL.cs --- > Calls SP or any ORM if ur using any

BLL 프로젝트

AccountsBLL.cs ---> Calls DAL

WebProject

Model
    AccountsModel --- > Contains properties And call BLL
Controllers
    IndexController ---> Calls Models and returns View
Views
    Index

컨트롤러 는 모델과 뷰 사이에 전달되는 데이터를 담당해야합니다. 그 외에는 불필요한 코드가 없어야합니다. 예를 들어 로깅하는 경우 컨트롤러가 아닌 모델 수준에서 수행해야합니다.


13

이 주제에 대해 약간의 혼란이있는 것 같습니다. 대부분 사람들은 MVC 패턴을 N 계층 아키텍처와 혼동하는 경향이 있습니다. 현실은 두 가지 접근 방식을 함께 사용할 수 있지만 하나는 다른 접근 방식에 의존하지 않으며 둘 다 필요하지 않습니다.

N 계층 아키텍처는 애플리케이션을 여러 계층으로 분리하는 것과 관련이 있습니다. 간단한 예는 애플리케이션이 프레젠테이션 계층, 비즈니스 논리 계층 및 데이터 액세스 계층으로 분할되는 경우입니다.

MVC는 애플리케이션의 표현 레이어를 다루는 디자인 패턴입니다. 프레젠테이션 계층에서 비즈니스 로직과 데이터 액세스 로직을 분리하지 않고도 MVC 접근 방식에 따라 애플리케이션을 설계 할 수 있으므로 단일 계층 설계로 끝납니다.

결과적으로 애플리케이션을 계층으로 분리하지 않고 MVC 접근 방식을 따르는 경우 비즈니스 규칙 및 데이터 액세스 논리의 비트가 나머지 논리와 혼합 된 모델,보기 및 컨트롤러로 끝납니다.

정의에 따라 N 계층 아키텍처에서 프레젠테이션 계층은 비즈니스 논리 계층과 만 통신 할 수 있어야하므로 MVC 구성 요소 중 하나가 비즈니스 논리 계층과 만 통신 할 수 있어야합니다.

프리젠 테이션을 포함하지 않고 따라서 프리젠 테이션 계층이 아닌 애플리케이션을 빌드하는 경우 MVC 패턴에 대해 걱정할 필요가 없습니다. 그러나 프레젠테이션 레이어가 포함되어 있지 않더라도 애플리케이션을 여러 계층으로 분할하여 N 계층 설계를 따를 수 있습니다.


8

일반적으로 비즈니스 로직은 MVC 플레이어에 있어서는 안됩니다. 컨트롤러 작업에 의해서만 소비 되어야합니다 .

많은 사람들이 언급했듯이 비즈니스 로직을 클라이언트에 구애받지 않는 재사용 가능한 구성 요소 집합으로 호스팅하는 라이브러리를 만드는 것이 가장 좋습니다.

이렇게하면 소프트웨어의 재사용 성, 호환성, 확장 성 및 테스트 가능성이 크게 향상됩니다. 또한 특정 프레임 워크 기능에 대한 의존도를 줄여 최신 / 다른 기술로 쉽게 마이그레이션 할 수 있습니다.

비즈니스 로직을 독립형 어셈블리 (또는 어셈블리)로 추상화하는 것은 수년 동안 우리에게 많은 도움이되었습니다. 그런 다음 비즈니스 논리는 거의 모든 .NET 기술 (ASP.NET MVC / API / Core, WPF, Win Forms, WCF, UWP, WF, Console 등)에서 사용할 수 있습니다.

또한 .NET MVC 프레임 워크에 대한 종속성을 줄이기 위해 비즈니스 규칙 및 유효성 검사 논리를 처리하는 중간 계층을 선호합니다. 예를 들어, 우리는 .NET MVC 유효성 검사 도우미를 사용하지 않고 대신 자체적으로 의존합니다. 이는 모든 .NET 기술에서 비즈니스 로직을 쉽게 사용할 수있는 또 다른 요소입니다.

이러한 방식으로 중간 계층을 논리적으로 설계함으로써이 물리적 아키텍처를 쉽게 달성 할 수있었습니다.

여기에 이미지 설명 입력

Peasy.NET 으로 작성되었으며 수년 에 걸쳐 우리에게 많은 도움이되었습니다. 사실 우리는 그것을 오픈 소스로 결정했습니다.

중간 계층이 어떻게 생겼는지 궁금한 사람이 있다면 다음 은 클라이언트에 구애받지 않는 비즈니스 계층 의 샘플 입니다. 또한 여러 .NET 클라이언트 (ASP.NET MVC, Web Api 및 WPF)의 소비를 보여줍니다.

이것이 누군가를 돕기를 바랍니다!


대부분 논리를 재사용 할 필요가 없습니다. 웹 API에 ASP.NET Core MVC를 사용하기로 결정했다면 WPF 또는 WinForms에서 해당 비즈니스 논리를 사용하고 싶지 않습니다. 클라이언트는 어쨌든 서버와 통신하기 때문입니다. 비즈니스 로직과 특히 데이터베이스 액세스 로직을 클라이언트 측에 배치하는 것은 좋지 않습니다.
Konrad

더 많은 계층을 추가할수록 유지 관리 및 테스트 가능성이 감소합니다. 결국 통합 테스트는 더 중요합니다.
Konrad

8

비즈니스 로직 모델 뷰 또는 컨트롤러에 들어가면 안됩니다 . 별도의 비즈니스 로직 레이어 가 있어야합니다 . 이 레이어의 유일한 목적은 비즈니스 로직을 처리하는 것입니다. 이것은 SOLID 와 더 일치 합니다.

비즈니스 로직을 MV 또는 C에 넣으면 테스트 / 재사용이 어려운 코드가됩니다.

모델에 논리를 넣는 것은 어떻습니까?

그것은 나쁜 해결책입니다.

개체가 개체에 의존 하는 종속성 지옥 에있게됩니다. 여기에 이미지 설명 입력

죽은 단순한 함수가 있더라도이를 호출하려면 모든 종속성을 충족해야합니다.

또한 불필요 하고 사용하지 않는 데이터가 이유없이 전달 될 수 있습니다. 이것은 또한 얼마나 나쁜지에 따라 성능에 영향을 미칠 수 있습니다.

또한 간단한 함수를 테스트하기 위해 여러 개체를 모의해야하기 때문에 단위 테스트가 a **에서 고통 스럽다는 점을 언급해야합니다.

적용 가능한 클린 코드의 원칙

  1. 클래스 / 함수는 작업을 완료하는 데 필요한 것만 취합니다.
  2. 함수는 가능한 경우 3 개 이하의 매개 변수를 가져야합니다.
  3. 클래스 / 함수 / 변수 이름을 지능적으로 지정 (Microsoft 표준에 따름)
  4. 비즈니스 논리를 모델보기 또는 컨트롤러에 연결하지 마십시오.

컨트롤러

컨트롤러에서 종속성 주입을 사용하여 비즈니스 논리 계층삽입 할 수 있어야합니다 . 컨트롤러가 정보를 비즈니스 논리 계층으로 라우팅하는 데만 사용되는지 확인하십시오. 컨트롤러에는 비즈니스 로직이 직접 포함되어서는 안됩니다. 모든 유효성 검사 IValidatable는 모델에서 처리해야합니다 . 모든 비즈니스 로직은 별도의 레이어로 라우팅되어야합니다.


여기서 제가 일하는 곳은 비즈니스 계층이 있고 저는 그것이없는 것을 원했습니다. 비즈니스 계층은 순전히 엉망이고 논리는 모델에 있어야합니다.
Mateus Felipe

@MateusFelipe 그렇다면 여러 모델 (예 : 결제 및 제품)을 필요로하는 로직을 어디에 넣습니까? PaymentProduct인스턴스 변수 가있는 새 모델을 생성 합니까? 그 물건의 이름은 무엇입니까? 모델이 뷰에서 사용되지 않으면 더 이상 모델이 아닙니다. 별도 레이어의 일부입니다. 이상적으로, 당신이 만드는 수업은 지불 및 제품에서 필요한 것만 가져와야합니다. productName및 만 필요한 경우 price전체 객체가 아닌 두 매개 변수 만 가져와야합니다.
Kolob Canyon

4

내가 가진 일반적인 대답은 비즈니스 로직이 일반적으로 두 가지 범주에 적합하다는 것입니다.

객체 지향 비즈니스 로직 : 일반적으로 리포지토리로 주입되는 객체 (모델에서)로 모델링됩니다.

절차 적 비즈니스 로직 : 컨트롤러에 삽입 할 수있는 인터페이스가있는 서비스로 이동합니다.

컨트롤러 로직 : 명령을 수신하고 모델 / 서비스로 전달하는 방법과 그 결과가 뷰로 전달되는 방법 을 제어 하는 로직입니다 .

컨트롤러에는 비즈니스 로직 이 없어야 합니다. 이는 사용자 인터페이스가 비즈니스 로직을 처리하는 모델에 입력을 전달하는 방식 을 제어 하기위한 설계 패턴의 매우 특정한 부분입니다 (또는 문제가 본질적으로 절차적일 경우 서비스).


2

나는 내 모델도 깨끗하게 유지하는 것을 좋아합니다 (참조 : @Mark Walsh). 컨트롤러에 내장 된 로직을 재사용 할 수 없다는 문제는 종속성 주입을 통해 쉽게 극복 할 수 있으며, 너무 많을 것이라고 생각되면 인터페이스를 통해 비즈니스 / 도메인 로직을 노출하고 컨트롤러의 파사드 패턴을 사용합니다. 이렇게하면 필요한 기능을 얻을 수 있지만 컨트롤러와 모델을 모두 멋지고 깔끔하게 유지할 수 있습니다.


1

나는 또한 모델을 깨끗하게 유지하는 것을 선호합니다. MVC 컨트롤러는 전화를 걸 때만 사용해야하며 깨끗하게 유지해야합니다. 따라서 재사용 가능성, 민감도 및 관련성에 따라 비즈니스 로직을 작성할 수 있습니다.

1. WebApi 컨트롤러 : webapi 컨트롤러 사용의 장점은 나중에 다른 장치에 서비스로 노출하여 코드를 재사용 할 수 있다는 것입니다.

2. BAL / Common commonent : 특정 용도가 있고 api로 노출 될 수없는 로직이 있으며,이 클래스에서 푸시 할 수 있습니다.

3. 리포지토리 : 모든 데이터베이스 관련 쿼리가 리포지토리에 추가됩니다. 모든 기능 (CRUD 작업) 또는 각 테이블에 대한 특정 저장소를 구현할 일반 저장소가있을 수 있습니다. 수행 할 작업에 따라.


1

ahanusa가 작성한 것처럼 비즈니스 로직을 별도의 DLL 또는 별도의 디렉토리에 넣어야합니다.
나는 종종 비즈니스 로직을 수행하는 클래스를 넣는 동일한 수준의 모델 및 컨트롤러에서 Logics라는 디렉토리를 사용합니다.
이런 식으로 모델과 컨트롤러를 모두 청소했습니다.


0

MVC에 대한 질문이라는 것을 알고 있지만 제가 제공하는 예제 (Web API)가 유용 할 것이라고 생각합니다.

저는 첫 번째 웹 API를 개발 중이며 다른 응용 프로그램의 비즈니스 논리를 재사용하고 있습니다. 구체적으로 말하자면 외부 DLL에서 가져 오므로 내 API는 SAP 솔루션과 "대화"하고 PO에서 요청을 받고 응답을 다시 보내는 데만 사용됩니다.

내 로직 (이미 구현 됨)을 컨트롤러에 어떻게 넣을 수 있습니까? 나는 그것을 필요로하지 않는다. 내 컨트롤러는 요청을 수신하고 유효성을 검사하며 데이터를 다시 보내기위한 응답을 작성합니다.

저는 ViewModel 클래스로 작업하고 있으며 그들이 가지고 있어야하는 것은 TransferObjects (외부 DLL에서 온)에서 정보를 읽고 ViewModel로 변환하기위한 매핑 함수뿐입니다.

비즈니스 로직을 포함하는 내 애플리케이션 (이 경우 Web API)이 마음에 들지 않습니다. 이러한 방식으로 재사용 성이 손실 될 것이라고 생각합니다.

내 비즈니스 로직을 컨트롤러에 주입하는 종속성으로 취급하고 있습니다.

단위 테스트 가능한 솔루션을 제공하기 위해 레거시에서 많은 리팩토링을 수행했으며이 솔루션을 제공하기 위해 많은 인터페이스를 만들고 레거시에 일부 디자인 패턴을 구현해야했습니다.

내 관점에서 비즈니스 계층은 응용 프로그램과 분리되어 있어야하며 다른 클래스 라이브러리에 있어야합니다. 따라서 응용 프로그램에서 실제 분리 개념을 구현하게됩니다.

물론 CORE (비즈니스)가 애플리케이션 (API / WebSite) 이면 비즈니스 규칙이 MVC 클래스에 구현됩니다. 그러나 미래에 새로운 앱을 개발하고 싶고 일부 비즈니스 규칙이 동일하다면 두 애플리케이션에서 구현 된 동일한 로직을 유지하는 데 많은 문제가 발생할 것입니다.

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