MVC에서 컨트롤러 클래스에 개인용, 액션이 아닌 기능을 갖는 것이 모범 사례로 간주됩니까?


10

때때로 컨트롤러 클래스의 액션 함수는 모델에서 뷰로의 데이터 흐름을 간단히 제어하기위한 많은 코드 줄로 인해 거대하고 불쾌해질 수 있습니다. 어떤 시점에서이 거대한 기능들은 좋은 코드의 기본 원칙을 완전히 잃어 버립니다.

이러한 거대한 액션 함수를 컨트롤러 클래스에서 더 작은 개인 함수로 나누는 것이 좋은 방법으로 간주됩니까? 아니면 그러한 최적화가 필요하다면 모델에 추가해야합니까?

나는 컨트롤러에서 더 작은 함수를 프라이빗으로 사용하여 동작과 관련이 있다고 투표하지만 모델이 거대하고 덩어리가 될 수있는 동안 컨트롤러가 간단해야한다는 주장을 들었습니다. 어느 것이 가장 선호되는 방법인지 궁금합니다.

답변:


16

가장 좋은 유추는 아니지만 스파이더 웹에 대해 생각하는 것과 같은 방식으로 컨트롤러에 대해 생각하십시오. 그것의 유일한 임무는 거미 (기본 레이어)가 소화하도록 파리 (요청)를 잡는 것입니다. 웹은 더 작거나 큰 파리 (모델)를 붙잡고 잡을 수 있습니다. 거미의 웹 역할은 먹이를 소화시키는 것이 아니라,이 목적으로 사용될 수 있습니다. 웹이 얇고 깨끗할수록 거미가 더 쉽게 살 수 있습니다.

MVC 응용 프로그램에 다소 동일한 논리를 적용 할 수 있습니다. 설명하는 거대하고 불쾌한 함수는 모델의 동작 일 가능성이 높으며 모델에 속해야합니다 (모델은 뷰에 표시되는 객체 만이 아니라는 점에 유의하십시오). 모델의 동작이 변경되면 모델을 처리하는 컨트롤러가 아니라 변경해야하는 모델입니다.

또한 컨트롤러에서 개인 메서드로 유지하면 컨트롤러가 복잡해지고 유지 관리가 어려워집니다. 또한 개발에 참여한 다른 사람들이 프로젝트에서 이전에 해왔 던 것을 보았 기 때문에 같은 일을하려는 유혹을 받기 때문에 나쁜 습관을 길러줍니다.


창의적인 비유로 +1 :) 흥미로운 지적입니다. 특히 나쁜 습관의 형성에. 감사합니다.
David '대머리 생강'

8

내가 줄 수있는 가장 좋은 대답은 로버트 마틴 (Robert Martin)의 위대한 책에서 "클린 코드 (Clean Code)"를 인용하는 것입니다.

함수의 첫 번째 규칙은 작아야한다는 것입니다. 두 번째 규칙은 그것들보다 작아야한다는 것입니다.

더 잘 말할 수 없습니다. 같은 책에서 또 다른 큰 인용문이 적용됩니다.

함수는 한 가지 일을해야합니다. 그들은 잘해야합니다. 그들은 그것을해야합니다.

코드를 더 많은 함수로 분할 할 때 코드의 가독성을 크게 향상시킬 수있는 의미있는 이름을 해당 함수에 제공해야합니다. 말할 것도없이, 클래스 외부에서 사용하도록 의도되지 않은 모든 함수는 전용이어야하므로 상속을 통해 코드를 쉽게 재사용 할 수 있습니다.

컨트롤러에 기능이 너무 많으면 아마도 너무 많은 기능을 수행한다는 표시입니다. 그런 다음 여러 독립적 인 조각으로 나누거나 다른 답변에서 언급 한 것처럼 일부 기능을 모델로 이동하려고 할 수 있습니다. 또한 뷰에 약간의 논리가 허용되는 비 클래식 MVC 풍미를 따르는 경우 적합 할 때마다 일부 함수를 배치 할 수 있습니다.


1
비즈니스 로직을 뷰에 넣는 것이 "비 클래식 MVC"라고 생각하지 않습니다. 단지 "나쁜 MVC"입니다. 분명히보기에는 기본 제어 구조가 필요하지만 도메인 / 비즈니스 문제가 아닌 사용자 / UI 문제와 일치해야합니다. 뷰 의 실제 기능 은 꽤 끔찍합니다.
Aaronaught

1
@Aaronaught 나는 "일부 논리"로 모호했다. 내가 생각했던 것은 예를 들어 Backbone.js 라이브러리이다. 고전적인 MVC에서는 이것이 컨트롤러의 역할입니다. 그러나 UI가 바뀔 때마다 View와 Controller를 모두 조정해야하므로 실용적이지 않을 수 있습니다. UI 처리기 함수를 View에 배치하면 View 만 조정하면됩니다. 그건 내 주관적인 관점 일뿐입니다. 뭔가 빠졌습니까?
Dmitri Zaitsev

1
클라이언트 측에서 무언가가 전달되었다고해서 그것이 논리적으로 뷰의 일부라는 것을 의미하지는 않습니다. 뷰에서의 데이터 바인딩은 확실하지만 Backbone은 그 자체가 MV * 프레임 워크 (MVC 종류, MVP 종류, 그다지 중요하지 않음)이므로 클라이언트 측 스크립트를 적절히 구성해야합니다. 그렇지 않으면, 당신은 해킹입니다.
Aaronaught

0

MVC에서는 컨트롤러가 가능한 "얇은"모델인지 확인하고 모델이 최대한 바보인지 확인합니다.

필요한 논리 및 도우미 함수는 별도의 독립형 도우미 클래스에 배치됩니다. 내 테스트도 훨씬 쉬워집니다 (테스트 중입니다. right ?? : D) 컨트롤러 테스트는 컨트롤러의 인스턴스를 만들려고 할 때 HTTP 컨텍스트와 가짜에 대해 생각해야 할 때마다 매우 어렵습니다. http 이것과 저것 그리고 그것의 고통, 그러나 그것의 고의적 인 고통. 컨트롤러는 HTTP와 웹에 밀접하게 연결되어 있기 때문에 모든 것이 필요합니다. 웹 앱의 진입 점입니다.

논리 및 도우미 기능은 웹과 관련이 없습니다. 그들은 전적으로 환경에 구애받지 않습니다 (또는 있어야합니다). 그것만으로는 그들이 같은 장소에 속해 있지 않다고 말할 수 있습니다. 또한 모든 응용 프로그램 논리를 웹이나 특정 웹 구현에 밀접하게 연결하면 절대로 사용할 수 없습니다.

우리는 모든 mvc 모델, 실제 db 엔터티가 아닌 모든 데이터베이스 엔터티, 저장소, 도우미 클래스 및 별도의 독립형 dll의 논리를 사용하여 MVC 사이트를 개발했습니다. 우리는 오직 하나의 웹 사이트 만 가지고 있지만 어쨌든 이렇게했습니다.

몇 달 전에 우리는 몇몇 프린지 시스템과 관련된 몇 가지 데스크탑 앱을 만들라는 요청을 받았습니다. 테스트 된 모든 코드를 쉽게 재사용 할 수 있으므로 쉽게 수행 할 수 있습니다. 코드를 웹 프로젝트에 넣거나 컨트롤러에 넣었다면 결코 그렇게 할 수 없었을 것입니다.


2
MVC의 모델은 멍청 하지 않은 유일한 레이어입니다 . 스마트가 모델에없고 컨트롤러에 없으면 스마트 뷰는 어디에 있습니까? 컨트롤러도 테스트하기 어렵지 않아야합니다. DI와 가짜 / 모의를 사용하여 유닛 테스트를 용이하게하는 기능은 다른 프레임 워크에 비해 MVC의 장점 중 하나입니다. 대부분의 컨트롤러 테스트는 5 줄 미만입니다.
Aaronaught

논리가있는 모델에 침투하는 대신 논리가있는 "헬퍼"클래스를 사용합니다. 어떤 종류의 논리를 모델에 넣겠습니까? 자체로드 및 저장 방법을 알고 있습니까? 나는 가짜 / 스터 빙이 쉽지만 동의하지만 컨트롤러를 강화하기위한 변명은 아닙니다.
우주인

이 답변이 의미가 있다고 생각하지만 잘못 표기되어 있습니다. 또는 다른 용어 일 수 있습니다.
Simon Whitehead

3
"Helper"클래스는 아키텍처 요소가 아닙니다. 그것들은 M, V 또는 C의 일부입니다. 확실하지 않다면, 그 도우미는 응집력 이 없습니다 . "helper"라는 단어는 또한 "handle", "do", "perform"및 두려운 Manager로 순위가 매겨집니다 .
Aaronaught

@SimonWhitehead : 대부분의 답변은 의미가 있지만 많은 것이 맞지 않습니다. 불행히도 이것은 "모델"의 의미에 대한 오해를 조장하거나 중요한 비즈니스 로직을 외부에 두는 것을 권장합니다. 나는 거대한 "도움말"로 MVC 사이트를 유지 관리하는 것에 대한 모호한 즐거움을 겪었습니다.
Aaronaught

-2

Dmitri Zaitsev와 우주인의 훌륭한 답변 외에도 다음이 PHP에도 유효한지 모르겠습니다. 자동 테스트 가능성이 없기 때문에 개인 메소드를 피해야합니다.

예, 메타 프로그래밍 또는 의존성 주입을 사용하여 개인 메소드를 테스트 할 수도 있지만 코드의 가독성에 큰 영향을 미치므로 그렇게하지 않아야합니다.

항상 KISS 원칙을 기억하십시오. 간단하고 어리석게 유지하십시오.


5
하지 MVC의 아키텍처와 아무 상관이없는 민간 방법을 피하기위한 좋은 이유, 그리고. 비공개 메소드를 테스트 하려고 시도 하지 마십시오 . 공개 메소드 에 대한 테스트를 수행해야합니다 . 그것들을 다룰 수 없다면, 그것은 당신의 수업이 너무 복잡해서 리팩터링되어야한다는 신호입니다. 그것은 당신이 개인적인 방법을 가져서는 안된다는 것을 의미하지는 않습니다.
Aaronaught
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.