home link download back number special issue

HMDT - Special Issue / Sketch BP / Sketch に見る MVC アーキテクチャ


- Case Study -

Sketch に見る MVC アーキテクチャ

MVC (Model-View-Controller) アーキテクチャとは何か

MVC アーキテクチャってのは、アプリケーションを作るときのひとつのモデルなんだ。そんな新しい概念じゃなくて、けっこう昔から提唱されているんだよね。Cocoa は、かなりこのモデルに基礎を置いている、っていえるんだ。

このアーキテクチャでは、アプリケーションを作るためのクラスを 3 つに分けるんだ。それが Model と View と Controller なんだ。簡単に説明すると、Model は、データを確保しておくところ、View は、ユーザに見せるところ、Controller は、それをつなぐとこ、って感じだ。Cocoa でいうと、AppKit の多く、NSView を継承しているクラスは View としてとらえることができるんだ。Controller に当たるのは NSWindowController とか、NSApplication の delgate になるクラスだね。それらをつなぐのが、Interface Builder の役割。

じゃ、Sketch の中で、それらがどう割り当てられるのか、見てみよう。


Sketch に見る Model

Sketch では、Model はきっちりと切り分けられているんだ。それは、Model のソースコードが別のディレクトリに入れられていることからも分かるよ。Sketch/DocumentModel.subproj の中に入れられているソースコードがそれにあたる。

主なクラスを見てみると、、、


SKTGraphic

Sketch はドロー系アプリケーションだから、できあがるドキュメントは、ドローオブジェクトの集合なわけだ。そのドローオブジェクトを現すのが、この SKTGraphic クラスだ。これ自体は抽象クラスの扱いで、実際はこれを継承したクラスのインスタンスが作られるんだ。

このクラスのヘッダをはこんな感じ。

Sketch/DocumentMoel.subproj/SKTGraphic.h
@interface SKTGraphic : NSObject <NSCopying> {
    @private
    SKTDrawDocument *_document;
    NSRect _bounds;
    NSRect _origBounds;
    float _lineWidth;
    NSColor *_fillColor;
    NSColor *_strokeColor;
    struct __gFlags {
        unsigned int drawsFill:1;
        unsigned int drawsStroke:1;
        unsigned int manipulatingBounds:1;
        unsigned int _pad:29;
    } _gFlags;
}

_bounds、_origBounds、_lineWidth、_fillColor、strokeColor などが、ドローオブジェクトの属性だね。これらを保持しているのが、Model としての SKTGraphic の役割だ。

SKTGraphic を継承しているクラスは、

  • SKTRectangle
  • SKTCircle
  • SKTLine
  • SKTTextArea
  • SKTImage

とかだね。


SKTDrawDocument

Sketch を使うと、ドローオブジェクトをどんどん描いていくわけだから、どこかにドローオブジェクトの集合を取り扱うクラスがあるはずだ。それが SKTDocument クラスだ。そのヘッダを見ると、

Sketch/DocumentMoel.subproj/SKTDrawDocument.h
@interface SKTDrawDocument : NSDocument {
    @private
    NSMutableArray *_graphics;
}

配列を 1 つ持っている。ここに SKTGraphic を、どんどん入れていくんだ。この配列にアクセスするためのメソッドとして、次のようなものが用意されているんだ。

Sketch/DocumentMoel.subproj/SKTDrawDocument.m
- (NSArray *)graphics;
- (void)setGraphics:(NSArray *)graphics;

- (void)invalidateGraphic:(SKTGraphic *)graphic;

- (void)insertGraphic:(SKTGraphic *)graphic atIndex:(unsigned)index;
- (void)removeGraphicAtIndex:(unsigned)index;
- (void)removeGraphic:(SKTGraphic *)graphic;
- (void)moveGraphic:(SKTGraphic *)graphic toIndex:(unsigned)newIndex;

配列に SKTGraphic を挿入したり、削除したりするアクセッサだ。これが Model としての SKTDrawDocument の役割ね。


Sketch に見る View

Sketch には、SKTGraphicView という NSView を継承したクラスがあるんだ。これが、アプリケーションのメインのビューになる。その仕事は、

  • ドローオブジェクトを表示すること
  • ユーザからのマウス入力を受け付けて、ドローオブジェクトを作ること

とかだ。ユーザに Model を表示し、ユーザからの入力を受け付ける、っていうところは、まさに View としての役割だね。

View と Model を切り離すために、SKTGraphicView は Model への直接の参照は持っていないんだ。持っているのは(後述する)Controller への参照だ。

Sketch/SKTGraphicView.h
@interface SKTGraphicView : NSView {
    @private
    IBOutlet SKTDrawWindowController *controller;
    ...
}

Model からドローオブジェクトを取り出したり、ユーザが作ったドローオブジェクトを Model に加えるには、Controller を経由して Model にアクセスするんだ。メソッド drawDocument がそれを提供してるんだ。

Sketch/SKTGraphicView.m
- (SKTDrawDocument *)drawDocument {
    return [[self drawWindowController] document];
}

これが、Sketch の主要な View だ。


Sketch に見る Controller

Controller としては SKTDrawWindowController がある。これは NSWindowController を継承しているんだ。メインのウィンドウの Controller で、SKTGraphicView と SKTDocument を結びつける役割をしているんだ。

Sketch/SKTDrawWindowController.h
@interface SKTDrawWindowController : NSWindowController {
    @private
    IBOutlet SKTGraphicView *graphicView;
    ...
}

上のように、SKTGraphicView への参照を持っているんだ。SKTDocument へは document メソッドを介してアクセスするんだ(ドキュメントベースアプリケーションを参照)。

他にも Controller として SKTInspectorController、SKTToolPaletteController、SKTGridPanelController がある。これらも SKTGraphicView への参照を持っていたり、Notification を使ったりして、View とやりとりするんだ。


Sketch に見る MVC の関係

じゃ、MVC それぞれのクラスの関係を、ユーザから見てみよう。

ユーザが直接いじるのは、つまりマウスやキーボードからの入力を受け付けるのは、View だ。Sketch だと SKTGraphicView がこれを受け付ける。

ユーザの入力として、たとえばドローオブジェクトを作る、という動作を考えてみる。SKTGraphicView はユーザのマウスの動きを解析して、Model である SKTGraphic を作る。そして Controller である SKTDrawWindowController から、Model である SKTDrawDocument の参照を取り出して、作ったオブジェクトを格納する、っていう流れだね。


Home | Link | Download | Back Number | Speciall Issue

Sketch BP

mailto: mkino@xd5.so-net.ne.jp

HMDT