600 likes | 796 Views
MVVM. 성배를 찾아서 – 표현과 논리의 분리. 공인석 @ gongdo ( 주 ) 휴즈플로우. 쌍쌍바 성배 이야기. Design. Development. MVVM. is not The Holy Grail!. 선문답 ?. WHAT’S. A COMPUTER. THIS?. FOR. TO COMPUTE. TO COMPUTE. TO USE. WHAT?. TO. COMPUTER PROGRAMS. WHAT?. Input. interaction. Processing. Output.
E N D
MVVM 성배를 찾아서– 표현과 논리의 분리 공인석 @gongdo (주)휴즈플로우
Design Development
MVVM is not The Holy Grail!
WHAT’S A COMPUTER THIS?
FOR TO COMPUTE TO COMPUTE TO USE WHAT?
TO COMPUTER PROGRAMS WHAT?
Input interaction Processing Output
InputProcessingOutput 입력로직 수행 표현 ======
입력로직 수행표현 Command Model(data+logic) View* =>=>=> *비주얼 표현이 목적인 애플리케이션인 경우
100만년 전 검색
Friend[]GetMyFriends() { returnnull;}
비주얼 개발 도구의 시대 앞면 뒷면 *조립 매뉴얼은 필수 silverlight 검색 검색 결과: 0건
본격 협업의 시대 앞면 뒷면 XAML
일반적인 UI 개발 패턴 우리는 어떻게 새로운 도구를 예전과 완벽하게 똑같이 사용하는가
View XAML Code-Behind Model Design, x:Name or Event Event Handlers, State, Operations Data, Services, Business Logic
XAML Code-behind void OnMyButtonClick(…) { MyButton.Content="Clicked!";} <Button Content="Click me" x:Name="MyButton" Click="OnMyButtonClick" /> XAML과 코드를 속박하는 것
디자인 구성 요소가 ‘문자열’ 로 코드와 강력하게 엮여 있음. • 디자이너가 디자인 구성 요소를 자유롭게 수정하기 어려움. • ‘표현’을 담당하는 View의 코드 비하인드에 ‘표현’과 직접적인 연관이 없는 코드가 섞이게 됨. • 디자인과 엮여 있어 ‘코드’ 부분만 따로 테스트할 수 없음. • 간단한 인터랙션도 ‘코드’를 거치지 않고서는 ‘표현’할 수 없어 디자이너의 역할이 제한됨. 코드 비하인드 방식의 문제
XAML <UserControl x:Class="MyPage"DataContext="{StaticResourceMyData}"> <TextBox Text="{Binding Path=MyText, Mode=TwoWay}"/> </UserControl> 속성의 변경과 데이터 반영
데이터가 변경되거나 입력이 변경될 때마다 불필요한 코드를 작성할 필요가 없음 • 코드로도 작성이 가능하지만 익스프레션 블렌드를 사용하는 것이 훨씬 더 효율적이고 원활한 협업이 가능 • 특히 ItemsContrl, ListBox의 ItemsSource속성에 ObservableCollection을 설정하면 매우 편리하게 컬렉션을 다룰 수 있음 데이터 바인딩
디자인 단계에서는 바인딩 한 속성에 어떤 값이 표시될지 직접 보면서 작업하는 것이 불가능 • 결국 이전 처럼 ‘임시값’을 설정하여 디자인을 마치고 다시 바인딩을 설정하게 되어 더욱 복잡도가 증가 • 여전히 ‘표현’이 목적인 컴포넌트가 비즈니스 로직 영역의 모델에 대해 의존적인 형태 단순 데이터 바인딩의 문제
Blend 블렌드 + ability 가능한 능력 Blendability
ViewModel도입! ViewModel과 Mock-up ViewModel을 사용한 Win-Win 전략
View XAML Code-Behind Model View-Model Design Zero~Least-code Data, Services, Business Logic Data, State, Operations DataBinding
if (DesignerProperties.IsInDesignTool == true) { // 디자인 모드용 Mock 데이터 설정 } else { // Runtime용 초기화 수행 } 디자이너를 위한 초기화
ViewModel View B VIEW C View A ViewModel:Model= 1:n?
ViewModel이 View에 대해 1:n 관계일 때 해당 ViewModel은 지속성persistency을 가져야 함 • ViewModel의 생성 시점이나 교체 시점 즉, 라이프 사이클을 관리할 필요가 있음 • 또한 ViewModel코드에 Mock 역할을 하는 코드를 넣는 것은 불합리 하므로 Mock 역할을 하는 클래스를 따로 관리할 필요가 있음 • 이에 따라 ViewModel을 ‘관리’하는 또 다른 기능이 필요 ViewModel의 스콥과 라이프 사이클 문제
Object management 간단한 Service-locator 사용
<Application …생략… xmlns:local="clr-namespace:PhotoSearch"> <Application.Resources> <local:ServiceLocatorx:Key="Locator“d:IsDataSource="True" /> <Application.Resources> </Application> 전역 ServiceLocator등록
<UserControl …생략… DataContext="{Binding Source={StaticResource Locator}, Path=PhotoSearchViewModel}"> </UserControl> 등록한 ServiceLocator사용
View B VIEW C View A ViewModel A ViewModel B Model
여전히 사용자의 명령에 대응하는 이벤트 처리를 코드 비하인드에서 수행 • 따라서 여전히 디자인 변경에 제약, 혹은 주의가 필요 • Zero-code 실현! ViewModel에 대한 불만
View XAML Code-Behind Model View-Model Design Zero~Least-code Data, Services, Business Logic Data, State, Operations DataBinding Commands
원래 커맨드 패턴은 애플리케이션 전역에 적용되는 ‘명령’에 적합(예를 들어 상단에 있는 메뉴와 같은 공통 명령) • MVVM과 커맨드 패턴을 조합할 때에는 ViewModel에 해당 View에서 수행할 명령을 등록하고 바인딩하여 사용하는 것이 편리함 • 기본적으로 실버라이트는 Button에서 파생된 컨트롤만 Command를 설정할 수 있음 • 그러나 InvokeCommandAction이라는 Behavior를 사용하여 버튼 외의 컨트롤에서도 명령을 실행 가능 Command Pattern
public ICommandSearchCommand { get; set; }속성은 형식으로 단순히 인터페이스만 선언해도 무방 • SearchCommand = new ActionCommand(e => Search(e));와 같이 실제 커맨드가 실행되었을 때 처리할 메서드를 등록 • 이 때, e는 CommandParameter로 전달된 오브젝트가 됨 • 버튼의 Command 속성에 위에서 선언한 Command를 바인딩하고 CommandParameter속성에 전달할 데이터를 바인딩 ViewModel과 Commanding