[model-view-controller] Qt가 모델 / 뷰 용어를 오용하는 이유는 무엇입니까?

모델 / 뷰 컨트롤과 함께 Qt에서 사용되는 용어에 결함이 있다고 생각합니다. 에 자신의 설명 페이지 그들이보기 및 컨트롤러를 통합하고 다음과 같은 사진을주고있다 의해 MV에 MVC를 단순화하는 것이, 상태 :

Qt MVC를 설명하는 그림

하지만 제 생각에는 그들이 사물의 역할을 잘못 명명했다고 생각합니다.

  1. 병합 된 컨트롤러가있는 뷰라고 부르는 것은 사실 뷰 전용입니다.
  2. 그들이 모델이라고 부르는 것은 사실 컨트롤러입니다.
  3. 정말로 모델을 갖고 싶다면 “데이터”가있는 어딘가에있을 것입니다.

앱에서 Qt 모델 / 뷰 구성 요소를 사용하는 일반적이고 건전한 방법에 대해 이야기하고 있습니다. 이유는 다음과 같습니다.

  1. 이것은 일반적으로 객체에 특정한 컨트롤러 로직을 추가하지 않고 그대로 사용되는 Qt 구성 요소입니다)
  2. 모델과 관련이없는 rowCount, columnCount, data 등과 같은 여러 Qt 메서드를 구현해야하기 때문에 이것은 모델이 아닙니다. 실제로 컨트롤러에는 일반적인 모델 방법이 있습니다. 물론 여기에서 컨트롤러 모델 로직을 모두 구현할 수 있지만 먼저 코드 디자인이 상당히 나쁘고 두 번째로 컨트롤러와 뷰가 아닌 컨트롤러와 모델을 병합합니다.
  3. 이유 2에서 언급했듯이 모델 논리를 분리하려면 그림의 파란색 상자가 아니라 점선 “데이터”상자 (물론 실제 데이터와 통신)입니다.

Qt의 용어가 잘못되었거나 이해하지 못하는 것은 나뿐입니까? (BTW : 그것이 학문적 질문이 아닌 이유는 내가 그들의 이름에 따라 내 프로젝트를 코딩하기 시작했고, 곧 코드가 분명히 옳지 않다는 것을 알게 되었기 때문입니다. 그들이 모델이라고 부르는 것에 모델 로직을 넣지 마십시오)



답변

Qt의 이름이 오해의 소지가 있다는 데 동의합니다. 그러나 제 생각에 문제는 Qt만의 문제가 아니라 UI를 구현할 때 관심사 분리 원칙을 고수 할 수있는 모든 프레임 워크에서 공유됩니다 . 누군가 그런 프레임 워크를 생각해 내고 “사물”을 분리 할 수있는 좋은 방법을 찾았을 때, 그들은 항상 “모델”이라고 부르는 모듈과 “보기”라고 부르는 다른 모듈을 가져야한다는 의무감을 느낍니다. 수년 동안 나는 다음 프레임 워크로 작업했습니다.

  • MFC
  • Qt
  • 그네
  • SWT
  • MVVM을 사용하는 WPF

이러한 프레임 워크에서 “모델”과 “보기”라는 용어가 사용되는 방식과 “보기”, “모델”및 “컨트롤러”(있는 경우)의 클래스가 갖는 책임을 비교하면 매우 큰 차이가 있음을 알 수 있습니다. 다른 개념과 용어를 비교하는 것은 확실히 유용 할 것입니다. 따라서 한 프레임 워크에서 다른 프레임 워크로 전환하는 사람들이 제정신을 유지할 수있는 기회를 가지지 만 많은 작업과 연구가 필요합니다. 좋은 읽기는 Martin Fowler의 개요 입니다.

MVC 패턴이 어떻게 생겼는지에 대한 아이디어가 너무 많기 때문에 어느 것이 맞습니까? 제 생각에는 MVC를 “올바르게”구현해야하는 방법을 알고 싶을 때 MVC를 발명 한 사람들을 찾아야합니다. 에서 원래 스몰 토크 용지 는 말합니다 :

보기는 해당 애플리케이션에 할당 된 비트 맵 디스플레이 부분에 대한 그래픽 및 / 또는 텍스트 출력을 관리합니다. 컨트롤러는 사용자의 마우스 및 키보드 입력을 해석하여 모델 및 / 또는보기를 적절하게 변경하도록 명령합니다. 마지막으로 모델은 애플리케이션 도메인의 동작과 데이터를 관리하고, 상태에 대한 정보 요청에 응답하고 (일반적으로보기에서) 상태를 변경하라는 명령에 응답합니다 (일반적으로 컨트롤러에서).

이에 비추어 귀하의 세 가지 주요 관심사에 대해 다음과 같이 대답하겠습니다.

  1. 실제로 Qt 구성 요소는 “그래픽 […] 출력을 관리”하고 “마우스 및 키보드 입력을 해석”하므로 위의 정의와 관련하여 실제로 병합 된보기 및 컨트롤러라고 할 수 있습니다.
  2. 본인은 귀하가 컨트롤러와 모델을 병합해야한다는 데 동의합니다 (위의 정의와 관련하여).
  3. 다시 동의합니다. 모델은 애플리케이션 도메인 의 데이터 만 관리해야 합니다 . 이것이 그들이 “데이터”라고 부르는 것입니다. 예를 들어 행과 열을 처리하는 것은 일반적으로 애플리케이션 도메인과 관련이 없습니다.

그것은 우리를 어디로 떠나는가? 제 생각에는 “모델”과 “보기”라는 용어가 사용될 때 Qt가 실제로 무엇을 의미하는지 파악하고 Qt로 프로그래밍하는 동안 용어를 사용하는 것이 가장 좋습니다. 계속 신경 쓰이는 경우 속도가 느려지고 Qt에서 설정하는 방식이 우아한 디자인을 허용합니다. 이는 “잘못된”명명 규칙보다 무게가 더 큽니다.


답변

짧은 답변

Qt의 MVC는 하나의 데이터 구조 에만 적용됩니다 . MVC에 대해 이야기 할 때 응용 프로그램이 당신에 대해 생각 안 QAbstractItemModelQListView.

전체 프로그램을위한 MVC 아키텍처를 원한다면 Qt는 그렇게 “거대한”모델 / 뷰 프레임 워크를 가지고 있지 않습니다. 그러나 프로그램의 각 목록 / 데이터 트리에 대해 실제로 보기 내에 컨트롤러 가있는 Qt MVC 접근 방식을 사용할 수 있습니다. 데이터 내 또는 모델의 외부이고; 이것은 사용중인 모델 유형에 따라 다릅니다 (자신의 모델 하위 클래스 : 모델 내부에있을 수 있음; 예 : QSqlTableModel : 모델 외부 (하지만 내부에 캐시 됨)). 모델과 뷰를 결합하려면 비즈니스 로직 을 구현하는 자체 클래스를 사용하세요 .


긴 대답

Qt의 모델 / 뷰 접근 방식 및 용어 :

Qt는 모델에 대한 간단한 보기 를 제공합니다 . 그들은이 컨트롤러 무엇 대부분의 경우 컨트롤러 “컨트롤”뭔가를 편집하고 항목을하는 이동, 선택 : 내장을. 즉, 사용자 입력 (마우스 클릭 및 이동)을 해석하고 모델에 적절한 명령을 제공합니다.

Qt의 모델 은 실제로 기본 데이터가있는 모델입니다. 물론 추상 모델은 데이터를 보유하지 않습니다. Qt는 데이터를 저장하는 방법을 모르기 때문입니다. 그러나 당신은 하위 클래스에 데이터 컨테이너를 추가하고 데이터에 액세스 모델 인터페이스를 만들어 사용자의 요구에 QAbstractItemModel을 확장합니다. 사실, 저는 여러분이 이것을 좋아하지 않는다고 가정합니다. 문제는 모델을 프로그래밍해야 한다는 입니다. 따라서 데이터 구조에서 데이터에 액세스하고 수정하는 방법이 있습니다.

MVC 용어에서 모델은 데이터로직을 모두 포함합니다 . Qt에서 비즈니스 로직의 일부를 모델 내부에 포함할지 아니면 외부에 배치하여 자체적으로 “보기”가되는지는 사용자에게 달려 있습니다. 논리가 의미하는 바가 명확하지도 않습니다. 항목을 선택하고, 이름을 바꾸고, 이동합니까? => 이미 구현되었습니다. 그들과 함께 계산을합니까? => 모델 하위 클래스 외부 또는 내부에 넣으십시오. 파일에서 데이터를 저장하거나로드합니까? => 모델 하위 클래스 안에 넣으십시오.


내 개인적인 의견 :

좋은 제공하는 것은 매우 어렵다 프로그래머에 일반적인 MV (C) 시스템을. 대부분의 경우 모델이 단순하기 때문에 (예 : 문자열 목록 만) Qt는 바로 사용할 수있는 QStringListModel도 제공합니다. 그러나 데이터가 문자열보다 복잡한 경우 Qt 모델 / 뷰 인터페이스를 통해 데이터를 표현하는 방법은 사용자에게 달려 있습니다. 예를 들어, 3 개의 필드 (이름, 나이, 성별을 가진 사람)가있는 구조체가있는 경우 3 개의 필드를 3 개의 다른 열 또는 3 개의 다른 역할에 할당 할 수 있습니다. 나는 두 가지 접근 방식을 모두 싫어합니다.

Qt의 모델 / 뷰 프레임 워크는 간단한 데이터 구조 를 표시하려는 경우에만 유용하다고 생각합니다 . 데이터가 사용자 정의 유형 이거나 트리 또는 목록 (예 : 그래프)에 구조화되지 않은 경우 처리가 어려워집니다 . 대부분의 경우 목록으로 충분하며 어떤 경우에도 모델은 하나의 항목 만 보유해야합니다. 특히 다른 속성 (한 클래스의 한 인스턴스)을 가진 단일 항목을 모델링하려는 경우 Qt의 모델 / 뷰 프레임 워크는 사용자 인터페이스에서 논리를 분리하는 올바른 방법이 아닙니다.

요약하자면 Qt의 모델 / 뷰 프레임 워크는 Qt의 뷰어 위젯 중 하나에서 데이터를 보는 경우에만 유용하다고 생각 합니다 . 애플리케이션의 설정과 같이 하나의 항목 만 포함하는 모델에 대한 자체 뷰어를 작성하려고하거나 데이터가 인쇄 가능한 유형이 아닌 경우에는 완전히 쓸모가 없습니다.


(더 큰) 애플리케이션에서 Qt 모델 / 뷰를 어떻게 사용 했습니까?

나는 한때 (팀에서) 데이터를 관리하기 위해 여러 Qt 모델을 사용하는 애플리케이션을 작성했습니다. 우리는 DataRole각기 다른 모델 하위 클래스에 대해 서로 다른 사용자 정의 유형 인 실제 데이터를 보관 하기 위해를 만들기로 결정했습니다 . 우리는 Model모든 다른 Qt 모델을 보유 하는 외부 모델 클래스를 만들었습니다 . 또한 View.NET 내부의 모델에 연결된 창 (위젯)을 보유 하는 외부 뷰 클래스를 만들었습니다 Model. 따라서이 접근 방식은 우리 자신의 필요에 맞게 확장 된 Qt MVC입니다. 둘 다 ModelView클래스 자체는 Qt MVC와 관련이 없습니다.

논리를 어디에 넣었 습니까? 소스 모델에서 데이터를 읽고 (변경된 경우) 결과를 대상 모델에 기록하여 데이터에 대한 실제 계산을 수행하는 클래스를 만들었습니다. Qt의 관점에서 볼 때이 로직 클래스는 모델에 “연결”되기 때문에 뷰가됩니다 (사용자의 경우 “뷰”가 아니라 애플리케이션의 비즈니스 로직 부분에 대한 “뷰”).

컨트롤러 는 어디에 있습니까 ? 원래 MVC 용어에서 컨트롤러는 사용자 입력 (마우스 및 키보드)을 해석하고 모델에 명령을 제공하여 요청 된 작업을 수행합니다. Qt 뷰는 항목 이름 변경 및 이동과 같은 사용자 입력을 이미 해석하므로 필요하지 않았습니다. 그러나 우리에게 필요한 것은 Qt 뷰를 넘어서는 사용자 상호 작용의 해석이었습니다.


답변

용어는 옳고 그름이 아니며 유용하거나 쓸모가 없습니다.

질문을 약간 변경하고 Qt가 MVC에 더 친숙하지 않은 이유를 물어볼 수 있습니다. 이에 대한 대답은 초기 Qt 개발자가 GUI 응용 프로그램에서 V를 C에서 분리하면 V와 C가 모두 나쁘다고 믿습니다. QWidget의 디자인은 마우스 입력 인터 퍼 레이션을 픽셀 출력 결정과 밀접하게 연결하는 것을 간단하게 만들려고 노력하고 있으며, 이것이 MVC로가는 길이 아닌지 알 수 있습니다.


답변

모델의 기능은 정보 요청에 응답하고, 나는 아무것도의 잘못이 같은 방법 정의에 있다고 생각 rowCount, columnCount모델은 데이터 소스에 대한 래퍼의 어떤 종류의 생각 등 I을 (상관없이 그것은 SQL 테이블하거나 배열 것입니다) , 표준 형식으로 데이터를 제공하므로 데이터 소스 구조에 따라 메서드를 정의해야합니다.


답변

나는 그들의 용어가 정확하다고 믿는다 … 실제 응용 프로그램에서는 추상화 수준에 따라 모델,보기 및 컨트롤러 사이의 경계를 모호하게 만드는 것이 매우 쉬울 수 있습니다. 한 수준의보기가 더 높은 수준의 모델 일 수 있습니다.

QAbstractModelItem 클래스에서 혼란이 발생한다고 생각합니다. 이 클래스는 모델 항목이 아니라 모델에 대한 인터페이스입니다. 뷰 클래스가 모델과 인터페이스하도록하려면 모델에 대한 일반적인 추상 인터페이스를 만들어야했습니다. 그러나 모델은 단일 항목, 항목 목록, 항목의 2 차원 이상의 테이블 등이 될 수 있습니다. 따라서 그들의 인터페이스는 이러한 모든 모델 변형을 지원해야합니다. 물론 이것은 모델 항목을 상당히 복잡하게 만들고 실제 모델과 함께 작동하도록 만드는 글루 코드는 은유를 약간 확장하는 것처럼 보입니다.


답변

제 생각에는 … 그들이 모델이라고 부르는 것은 사실 컨트롤러뿐입니다.

아니, 그들의 “모델”은 확실히 컨트롤러가 아닙니다.

컨트롤러는 모델을 수정하는 (따라서 뷰를 간접적으로 수정하는) 사용자에게 표시되는 컨트롤의 일부입니다. 예를 들어, “삭제”버튼은 컨트롤러의 일부입니다.

많은 사람들이 “컨트롤러가 모델을 수정한다”와 같은 것을보고 이것이 “deleteRow ()”메소드와 같은 모델의 변형 함수를 의미한다고 생각하기 때문에 종종 혼란이 있다고 생각합니다. 그러나 클래식 MVC에서 컨트롤러는 특히 사용자 인터페이스 부분입니다. 모델을 변경하는 메서드는 단순히 모델의 일부입니다.

MVC가 발명 된 이래로 컨트롤러와 뷰의 구분이 점점 더 심해졌습니다. 텍스트 상자를 생각해보십시오. 둘 다 일부 텍스트를 표시하고 편집 할 수 있습니다. 그렇다면보기 또는 컨트롤러입니까? 대답은 둘 다의 일부라는 것입니다. 1960 년대에 텔레타이프 작업을했을 때 구별이 더 명확 해졌습니다. 생각해보세요. ed그렇다고 당시 사용자에게 더 좋았다는 의미는 아닙니다!

QAbstractItemModel이 일반적으로 모델보다 높은 수준이라는 것은 사실입니다. 예를 들어, 항목의 배경색 (기술적으로 브러시)을 가질 수 있으며 이는 확실히보기에 가까운 속성입니다! 따라서 QAbstractItemModel이 뷰와 더 비슷하고 데이터가 모델이라는 주장이 있습니다. 진실은보기와 모델의 고전적인 의미 사이에 있다는 것입니다. 그러나 나는 그것이 어떻게 컨트롤러인지 볼 수 없습니다. 그것을 사용하는 QT 위젯이라면.


답변