클린 아키텍처 : 뷰 모델이란 무엇입니까?


13

밥 삼촌은 자신의 저서 인 '청결한 건축'에서 발표자가 자신이받은 데이터를 '모델보기'라고하는 무언가에 넣어야한다고 말합니다.

여기에 이미지 설명을 입력하십시오

이것은 VMVM (Model-View-ViewModel) 디자인 패턴의 'ViewModel'과 같은 것입니까, 아니면 단순한 데이터 전송 객체 (DTO)입니까?

단순한 DTO 가 아닌 경우 View와 어떤 관련이 있습니까? 뷰는 Observer 관계를 통해 뷰에서 업데이트를 받습니까?

로버트 마틴은 자신의 저서 23 장에서 다음과 같이 말하고 있기 때문에 MVVM의 ViewModel과 비슷하다고 생각합니다.

[발표자]의 업무는 응용 프로그램에서 데이터를 받아 프레젠테이션 용으로 서식을 지정하여보기가 화면으로 간단히 이동할 수 있도록하는 것입니다. 예를 들어, 응용 프로그램이 필드에 날짜를 표시하려면 발표자에게 날짜 개체를 전달합니다. 그러면 발표자는 해당 데이터를 적절한 문자열로 형식화 하고 View가 찾을 수 있는 View 모델이라는 간단한 데이터 구조에 배치 합니다.

이것은 뷰를 단순히 함수 인수로받는 것과는 달리 (DTO와 마찬가지로) View가 ViewModel에 연결되어 있음을 의미합니다.

당신이 이미지를 보면, 발표자가보기 모델을 사용하지만 때문에이 생각하는 또 다른 이유는 없는 보기를. 발표자는 출력 경계와 출력 데이터 DTO를 모두 사용 합니다 .

DTO도 아니고 MVVM의 ViewModel도 아닌 경우 그것이 무엇인지 자세히 설명하십시오.


답은 "의존"이라고 생각합니다. 웹 애플리케이션 인 경우 뷰 모델은 기본적으로 DTO입니다. 궁극적으로 HTML 문자열로 직렬화되기 때문입니다. 그렇지 않으면 뷰 모델은 뷰에 데이터를 표시하기위한 특수 객체 일뿐입니다.
Greg Burghardt

MVVM (WPF, 윈폼 응용 프로그램)에 ViewModel대한 래퍼입니다 Controller, Presenter그리고 ViewModel삼촌 밥의 청소 아키텍처이다.
Fabio

@Greg Burghardt-ViewModel이 특수한 데이터 구조 인 경우 View에 변경 사항이 어떻게 통보됩니까?
Fearnbuster

@ Fabio-MVVM 패턴에서 ViewModel이 다이어그램의 가장 왼쪽 그룹 내에있는 모든 구성 요소와 동일하다는 것을 정확하게 의미한다면? Bob 아저씨의 아키텍처에서 이것이 사실이라면 왜 컨트롤러와 발표자를 따로 나열합니까?
Fearnbuster

그는 입력 및 출력 핸들러를 다른 객체 / 클래스로 분리했다고 생각합니다. MVVM에서는 Controller-> ICommandPresenter-> 일 수 있습니다 data-binding mechanism.
Fabio

답변:


17

이것은 MVVM (Model-View-ViewModel) 디자인 패턴의 'ViewModel'과 동일한 것입니까?

아니.

이것이 이것입니다 :

여기에 이미지 설명을 입력하십시오

사이클이 있습니다. 밥 삼촌은 조심스럽게 사이클을 피하고 있습니다.

대신에 당신은 이것을 가지고 있습니다 :

여기에 이미지 설명을 입력하십시오

확실히 사이클이 없습니다. 그러나 뷰가 업데이트에 대해 어떻게 알고 있는지 궁금해합니다. 우리는 잠시 후에 그것에 도달 할 것입니다.

아니면 간단한 데이터 전송 개체 (DTO)입니까?

이전 페이지에서 Bob을 인용하려면 :

원하는 경우 기본 구조체 또는 간단한 데이터 전송 개체를 사용할 수 있습니다. 또는 해시 맵으로 묶거나 객체로 구성 할 수 있습니다.

클린 아키텍처 p207

당신이 원한다면, 물론.

그러나 나는 정말로 당신을 괴롭히는 것이 이것 이라고 의심 합니다 :

여기에 이미지 설명을 입력하십시오

UML에 대한이 작은 악용은 소스 코드 종속성의 방향과 제어 흐름의 방향을 대조합니다. 여기서 귀하의 질문에 대한 답변을 찾을 수 있습니다.

사용 관계에서 :

여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오

제어 흐름은 소스 코드 종속성과 같은 방향으로 진행됩니다.

구현 관계에서 :

여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오

제어 흐름은 일반적으로 소스 코드 종속성과 반대 방향으로 진행됩니다.

이것은 실제로 이것을보고 있음을 의미합니다.

여기에 이미지 설명을 입력하십시오

제어 흐름이 발표자에서보기로 전달되지 않는 것을 볼 수 있습니다.

어떻게 그렇게 될수 있니? 무슨 뜻인가요?

이것은 뷰에 자체 스레드가 있거나 (@Euphoric이 지적한 것처럼) 제어 흐름이 여기에 묘사되지 않은 다른 것에서 뷰로 들어오는 것을 의미합니다.

스레드가 동일한 경우 View는 View-Model을 읽을 준비가되었음을 알 수 있습니다. 그러나 그 경우이고보기가 GUI 인 경우 사용자가 DB를 기다리는 동안 화면을 움직일 때 화면을 다시 칠하는 데 어려움이 있습니다.

뷰에 자체 스레드가 있으면 자체 제어 흐름이 있습니다. 즉,이를 구현하려면 뷰에서 변경 사항을 확인하기 위해 뷰 모델을 폴링해야합니다.

발표자는보기가 존재한다는 것을 알지 못하고보기는 발표자가 존재한다는 것을 모르기 때문에 서로를 호출 할 수 없습니다. 그들은 서로에게 이벤트를 던질 수 없습니다. 일어날 수있는 모든 것은 발표자가 View-Model에 쓰고 View는 View-Model을 읽습니다. 그것이 느껴질 때마다.

이 다이어그램에 따르면 View와 Presenter가 공유하는 유일한 것은 View-Model에 대한 지식입니다. 그리고 그것은 단지 데이터 구조 일뿐입니다. 따라서 어떤 행동도 기대하지 마십시오.

그것은 불가능 해 보일 수도 있지만 View-Model이 복잡하더라도 작동하도록 만들 수 있습니다. 하나의 업데이트 된 필드는 변경 사항을 감지하기 위해 폴링해야 할 모든 뷰입니다.

물론 옵저버 패턴 사용을 주장하거나 프레임 워크 가이 문제를 숨길 수는 있지만 반드시 할 필요는 없다는 것을 이해하십시오.

제어 흐름을 보여주는 약간의 재미가 있습니다.

여기에 이미지 설명을 입력하십시오

이전에 정의한 방향에 따라 흐름이 진행되는 것을 볼 때마다 통화 반환이 표시됩니다. 그 트릭은 우리가보기에 도달하는 데 도움이되지 않습니다. 글쎄, 우리가 먼저 컨트롤러라고 부르는 것으로 돌아 가지 않는 한. 또는 디자인을 변경 하여보기에 도달 할 수도 있습니다. 그것은 또한 데이터 액세스와 인터페이스의 요요 문제 의 시작처럼 보이는 것을 수정합니다 .

여기서 유일하게 배울 점은 유스 케이스 인터랙 터가 발표자를 마지막으로 호출하는 한 원하는 순서대로 호출 할 수 있다는 것입니다.


응답자에게 감사드립니다. Clean Architecture에 대한 다양한 다른 질문에 대한 답변을 보았습니다. 예를 들어 뷰가 변경 사항이 있는지보기 위해 뷰 모델 내에서 뷰가 지속적으로 플래그를 확인하도록 제안하고 있습니까? 그런 다음 뷰가 전체 뷰 모델을 다시 표시해야합니까, 아니면 중첩 된 데이터 세트를 사용하여 변경된 데이터를 표시해야합니까?
Fearnbuster

뷰는 지속적으로 폴링 할 필요가 없습니다. 예를 들어 web 1.0은 사용자가 다시로드 할 때만 폴링합니다. 폴링은 사용자의 실제 요구를 고려해야하는 디자인 결정입니다. 나는 그것이 가능하다는 것을 말하고 있습니다. 업데이트 필드의 요점은 업데이트를 빠르게 감지하는 것입니다. 뷰 모델이 복잡한 경우에만 필요합니다. 발표자가 업데이트 중반 동안 뷰를 읽는 경우 발생하는 상황도 고려하십시오.
candied_orange

그래, 도와 줘서 고마워 이 아키텍처를 따르는 경우, 이것이 일반적으로 사용하는 기술입니까?
Fearnbuster

1
이 답변이 디자인 종속성과 런타임 종속성을 함께 그룹화한다는 큰 실수가 있다고 생각합니다. 둘은 다를 수 있습니다.
행복감

1
@Euphoric 왜 감사합니다. 소스 코드에 의존하지 않으면 런타임 참조를 사용할 수 없기 때문에 소스에 의존 할 수 없기 때문에 함께 묶습니다. 컬렉션처럼 참조를 유지하기 만하면됩니다. 그것이 실수라면 이해하고 싶습니다.
candied_orange

2

나는이 문제가 너무 혼란스럽고 Martin의 Clean Architecture와 MVVM을 오해한다고 생각하기 때문에 문제를 올바르게 설명하는 데 많은 텍스트와 시간이 필요합니다.

가장 먼저 알아야 할 것은 게시 한 다이어그램이 불완전하다는 것입니다. "비즈니스 로직"만 표시하지만 실제로 부품을 올바른 순서로 이동시키는 일종의 "오케 스트레이터"가 없습니다. 여기에 이미지 설명을 입력하십시오

오케 스트레이터 코드는 다음과 같이 간단합니다.

string Request(string request) // returns response
{
    Controller.Run(data);
    Presenter.Run();
    return View.Run();
}

Clean Architecture에 대한 그의 이야기 중 하나에서 Martin이 이것에 대해 이야기하는 것을 들었습니다.

지적해야 할 또 다른 사항은 사이클 부족에 대한 candied_orange의 발언이 잘못되었다는 것입니다. 예, 코드 아키텍처에는 사이클이 존재하지 않아야합니다. 그러나 런타임 인스턴스 간의주기는 일반적이며 종종 더 단순한 설계로 이어집니다.

MVVM의 경우입니다. MVVM에서 View는 ViewModel에 의존하며 ViewModel은 이벤트를 사용하여 View에 변경 사항을 알립니다. 이는 클래스 설계에서 View에서 Model 클래스로의 종속성 만 있지만 런타임 동안 View와 ViewModel 인스턴스간에 주기적 종속성이 있음을 의미합니다. 이 때문에 ViewModel은 자체 업데이트시기를 파악할 수있는 View 방법을 제공하므로 오케 스트레이터가 필요하지 않습니다. 그렇기 때문에이 다이어그램의 "알림"은 "직선"이 아닌 "고정"라인을 사용하는 이유입니다. 이는 ViewModel이 View에 의존하지 않고 ViewModel의 변경 사항을 관찰한다는 것을 의미합니다.

여기에 이미지 설명을 입력하십시오

Martin의 Clean Architecture에서 가져야 할 가장 중요한 것은 디자인 자체가 아니라 종속성을 처리하는 방법입니다. 그가 대화에서 결정적인 요점 중 하나는 경계가있을 때 경계를 가로 지르는 모든 코드 종속성이 단일 방향으로 교차한다는 것입니다. 다이어그램에서이 경계는 이중선으로 표시됩니다. 그리고이 인터페이스를 통해 의존성 반전 많이있다 ( InputBoundary, OutputBoundaryDataAccessInterface그 수정 코드 의존성 방향).

반대로 ViewModelClean Architecture는 논리가없는 단순한 DTO입니다. 이것은 <DS>태그에 의해 명확 해집니다 . 그리고 언제 논리를 실행할지 알 수 없기 때문에 이것이 orchestrator필요한 이유 입니다 View.

런타임 중에 다이어그램을 "평평하게"만들면 다음과 같이됩니다.

여기에 이미지 설명을 입력하십시오

따라서 런타임 동안 종속성은 "잘못된"방향이지만, 괜찮습니다.

그의 추론을 더 잘 이해하기 위해 Clean Architecture대한 그의 이야기를 보는 것이 좋습니다 .


"Orchestrator"는 발표자를 부르지 않아야합니다. 유스 케이스 인터랙 터가 그렇게합니다.
candied_orange

@candied_orange True, 그건 실수입니다.
Euphoric

답변 주셔서 감사합니다, 몇 가지 다른 의견을 얻는 것이 좋습니다. 두 사람의 대답을 모두 찬성했습니다. Robert Martin이 자신의 아키텍처 양식을 구현할 수있는 코드 기반이 있는지 알고 있습니까? 나는 그의 FitNess 프로젝트를 보았지만 나무의 숲을 볼 수 없었습니다. 또한 내가 게시 한 이미지가 Bob 삼촌이 항상 대화에서 사용하는 다이어그램이지만 실제로는 아키텍처가 어떻게 보일지에 대한 예일 뿐이라고 추측하는 것이 맞습니까? 종속성 흐름이 올바른 한 매우 다르게 보일 수 있습니까?
Fearnbuster

@Fearnbuster 마지막 ​​질문으로, 그렇습니다. 의존성 방향은 구조보다 중요합니다. "청결한 아키텍처", "양파 아키텍처"및 "16 각형 아키텍처"는 실제로 "종속성을 유지하십시오"와 동일한 아이디어를 구현 한 것으로 생각합니다.
Euphoric

@Euphoric 솔직히 말해서, 나는 그의 책의 다른 이미지 (8 장의 그림 8.2)에서 다르게 보이는 구조를 보여주기 때문에 그럴 가능성이 있다고 말할 것입니다. 이 다이어그램에서 Controller는 실제로 Interactor와 Presenter 사이의 중개인입니다. 인터랙 터에 대한 출력 경계도 없습니다. Interactor는 인터페이스를 통해 요청을 수신 한 다음 동일한 인터페이스를 통해 응답을 반환하는 것으로 보입니다 (저는 그렇게 작동하는 다른 메커니즘을 생각할 수 없으므로 간단한 함수 반환 값을 통해 수행한다고 가정합니다).
Fearnbuster
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.