Qt가 모델 / 뷰 용어를 오용하는 이유는 무엇입니까?


104

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

Qt MVC를 설명하는 그림

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

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

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

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

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


1
MFC는 CDoc 및 CView를 사용하여 2 파트 모델 / 뷰 GUI에 대한 표준을 설정했습니다. 특정 MVC가 '올바른'이유가 없습니다
Martin Beckett

@Martin B : MFC를 살펴볼 것입니다. 그러나 MVC 모델이 다르더라도 용어가 일관성이 있어야한다고 생각하고 유효한 주장을 제시했다고 생각합니다. 왜 사용 된 용어가이 특정 경우에 일관성이 없는지. 그들은 단순히 View와 Controller를 결합했다고 말하지만 나는 그것이 단지 명백한 오해의 소지가 있다고 생각합니다. 모든 애플리케이션 특정 로직 (프레젠테이션 또는 모델 로직)을 Model이라는 하나의 객체에 넣어야하는 MVC 모델은 없다고 생각합니다.
gorn

1
@Martin B : 또한 qt 용어 아래에서 모든 모델은 모델 구조와 관련이없는 공통 API를 가지고 있지만 일반 컨트롤러 구조와 관련된 모든 것은 모델이라고 부르는 것이 옳지 않다는 표시입니다. 올바른 MVC 모델이 하나 있다고 말하는 것은 아니지만 MVC 모델이라고 할 수 있다는 의미는 아닙니다. 어쩌면 MFC에도 결함이 있고 그것을 볼 수는 있지만 Qt가 올바르게 사용하는 데 더 관심이 있습니다. 내가 사용하지 않을 MFC입니다. MFC 모델 / 뷰 분리를 설명하는 좋은 링크가 있습니까?
gorn

1
MVC 용어는 만장일치로 동의하지 않으므로 귀하의 질문은 논증으로 간주 될 수 있습니다. 그러나 많은 사람들이 Martin Fowler ( martinfowler.com/eaaDev/index.html ) 의 훌륭한 작업에 동의 할 것 입니다. 일반적으로 컨트롤러는 사용자 입력을 처리하며 이러한 의미에서 Qt 위젯은 뷰와 컨트롤러를 가장 확실하게 결합합니다.
Arnold Spence 2011

1
나는 MVC에 많은 풍미가 있다는 것을 이해하지만 그것이 MVC가 될 수 있다는 것을 의미하지는 않습니다. Qt는 선을 넘었고 몇 가지 이유를 제시했습니다. Martin Fowler는 다양한 유형의 MVC를 설명하지만 둘 다 Qt가 MVC를 발음하는 것과 유사하지 않습니다. 가장 유사한 것은 martinfowler.com/eaaDev/PresentationModel.html 이지만 이것은 Presentation Model = Controller (사용자 상호 작용) 부분과 Model (데이터 로직)을 구분합니다. 따라서 MVC에 대한 정확한 정의는 없지만 Qt는 MVC를 따르지 않습니다. 그러한 정의에 대한 링크를 제공 할 수 있다면 그렇게하십시오.
gorn apr

답변:


78

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

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

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

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

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

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

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

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


2
델리게이트가 신호를 통해 뷰를 업데이트하는 모델에 입력을 수신하고 전송하기 때문에 델리게이트가 Qt의 컨트롤러라고 말할 수 있습니다.
Peregring-lk 2016

82

짧은 답변

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 모델은 다양한 뷰 유형을 지원할 수 있습니다.
smerlin

3
@smerlin : 나는 그것이 옳다고 생각하지 않는다. QListView와 QTreeView는 모두 QAbstractItemView 인터페이스 만 필요로합니다. 즉, 그 사용자 지정 하위 클래스 또는 QStandardItemModel과 같은 구체적인 클래스가 둘 다에 대한 요구 사항을 충족해야합니다. 나무를 운전하고 하나의 모델을 나열 할 수 있습니다.
jdi

1
@jdi : 데이터가 목록과 트리 인 경우가 있습니다 ... 예를 들어 파일 시스템을 트리로 표시하거나 모든 파일을 목록으로 표시 할 수 있습니다. Qts 모델은 제대로 허용하지 않습니다. 트리 뷰를 지원하는 QAbstractItemModel 구현은 루트 디렉토리의 모든 파일 / 디렉토리를 목록으로 표시 할 수만 있지만 모든 파일을 목록으로 표시 할 수는 없습니다. 그리고 트리 데이터를 목록으로 표시하는 것이 유용 할 수 없다고 말하지 마십시오. 예를 들어 파일을 목록으로 표시하면 파일 크기가 가장 큰 파일을 찾기 위해 쉽게 정렬 할 수 있지만 트리보기에서는이를 허용하지 않습니다.
smerlin

1
말했다 즉, 프록시 모델은 (는 수정 이후보기보다 뭔가 어떻게 데이터가되어 보기에 속해야 따라서)합니다. 내 긴 대답을 읽으면 : "big" View클래스에서 기본 모델로 트리 모델을 갖고 파일 시스템 목록보기에서 사용되는 프록시 모델을 추가해야합니다. 말씀하신대로 : 동일한 데이터에 대해 두 개의 모델이 없어야합니다. 못! (그러나 프록시 모델은 별도의 모델로 간주되지 않습니다.)
leemes

1
@SamPinkus의 존재 때문 전혀없는 명확한 또는 이 질문에. 또한의 다른 구현이 있으며 QAbstractItemModel, 그중 일부는 MVC의 의미에서 모델이고 일부는 그렇지 않습니다.
leemes 2014 년

12

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

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


나는 귀하의 요점을보고 기본적으로 Qt가 MVC에 더 친숙하지 않은 이유를 묻고 싶지만 Qt 문서에서 사용되는 MVC 용어가 MVC가 일반적으로 사용되는 것과 다를 때 수행하기가 매우 어렵습니다 (질문에서 설명했듯이). 그리고 널리 사용되는 용어가 있고 누군가가 그것을 다른 세계와 매우 다르게 사용할 때, 나는 그것이 쓸모 없을뿐만 아니라 명백한 잘못이고 혼란 스럽다고 생각하는 경향이 있습니다 (그 혼란으로 인해 처음에 질문을했습니다. 장소). 어딘가에서 논의되거나 설명되는 이러한 것들에 대한 링크가 있으면 매우 관심이 있습니다. 감사합니다
gorn

Qt 문서가 왜 MVC에 대해 말하는 방식에 대해 말할 수 없습니다. 나는 오래 전에 Trolltech를 떠났고 떠난 이후 문서에 대해 수행 된 일부 작업에 의아해합니다. (내 블로그에서는 가끔 그것에 대해 약간
외침을합니다

Qt에서 MVC 용어가 어떻게 합의되었는지에 대한 통찰력이 있습니까? 코드를 작성하는 동안 또는 나중에 문서화 과정에서 사용 되었습니까?
gorn

Trolltech에서 근무하는 동안 Qt 문서에서 "MVC"라는 단어를 사용하지 않았습니다. 일반적으로 거기에있는 것을 문서화하는 것이 가장 좋다고 생각합니다. 그러나 과도하게 보면 누가 그 텍스트를 추가했는지 확인하고 그 사람을 직접 추가 할 수 있습니다.
arnt

1
다른 댓글입니다. 우리는 Qt (Trollech가 3 인 회사 였을 때)의 설계 및 초기 구현 문구에서 MVC에 대해 논의했으며 MVC를 "적절하게"사용하는 GUI 툴킷을 평가했지만 그 이름을 기억할 수 없습니다. 우리의 의견은 그 툴킷이 사용하기 끔찍했고 MVC가 그 이유 중 상당 부분이라고 생각했습니다.
arnt

3

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


2

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

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


QAbstractModelItem 클래스에 동의하지만이 문제가 없어도 MVC의 이름이 잘못되었다고 생각합니다. 그들의 용어가 정확하다고 생각하는 이유를 설명해 주시겠습니까? 나는 왜 나의 세 가지 주장 중 어느 것도 옳지 않은지 듣고 싶습니다.
gorn

0

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

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

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

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

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

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

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