FileMaker案件の見積もり手法

FileMakerでのシステム開発を行っている方々は、発注されたシステムの価格設定に苦慮されていると思います。当然ながら、どれくらいの開発作業がかかるのかを、開発前に予測して見積もるわけです。そして、開発前に、いただく費用を決めて、顧客に開発費用を提示します。もちろん、準委任契約の場合、見積もりと現実に乖離が発生、すなわち見積もった作業量でシステムが完成しなかった場合、それ以上の作業分は原則としてお客さんが負担するわけですが、費用の上積みはなかなか交渉がタフになる可能性があります。したがって、見積もりを大きく外すのはいろいろなことを困難にします。ましてや請負契約となると、見積もりの正確さが業務の成否を左右すると言っても過言ではありません。

システム開発作業は、小さなステップの積み上げなので、そのステップを正確に数えれば費用見積もりは可能ではないかと思いがちですが、全ての作業を機械的に正確な時間で進められるわけではなく、失敗やあるいは手順上の問題で出戻って作業をやり直す部分などもあります。また、単に手を動かせば良いだけではなく、テストもやらないといけません。そうした一連の作業を結果的に「何時間かけたか」ということが開発コストに直結するわけです。それを見積もるためには、小さな作業の積み重ねといった正確さを追求する方法では限界があります。しかし、勘と経験だけで「150万だ!」などと決めるのも危ういです。つまり、ある程度のルールに基づいて導出する見積もり金額というものがあり、そのときに持ち出すルールがそれなりにシンプルというところです。言い換えれば、開発前に予測可能なことで、それほど大量に項目出しをしなくても済むような手法が求められています。

以前から筆者は経験上、いろんな方法で見積をしてきましたが、それなりに良い結果を得ている手法に集約できてきたので、その方法を紹介したいと思います。概ね、大きく外さない感じにできるところまで来たというところです。

開発前に4つの要素に注目する

まず、開発の作業を4つの要素でそれぞれ予測を行います。最初の1つは「設計」であり、これはあえてFileMakerを触る前の作業を全て含めることにします。顧客の話を聞くなどの要求獲得や要求分析、そして実際のどんなテーブルを用意して、どんなフィールドを用意するのかということを決定する「設計作業」が1つの要素です。見積もりを行う段階ですでに、設計作業のプロセスには入っているのが一般的でしょう。そして、情報収集後、ドメイン分析あるいはER図に相当するものが確定するまでの時間を考えます。「そんなことは作りながら考える」という方もおられるかと思います。それは作成開始後にどれくらいの時間を使うかを考えて、時間で検討します。一般にはシンプルなものでも最低5時間くらいかかると思います。複雑なものになると20時間、顧客とのやり取りのためにドキュメントをしっかり作らないといけないとなると30時間といった値になると思われます。ただ、この「設計作業」はFileMakerとは離れた部分ですので、ここでの時間数については大まかに紹介する程度にしたいと思います。

そして、残り3つの作業ですが「テーブル数」「追加レイアウト」「重い作業」という3つの観点で数値化します。最初のものは良いとして、残り2つはなんじゃコラと思われるかもしれませんが、それはすぐに説明します。

設計作業を行えば、FileMakerに向かってテーブルを用意し、フィールドを定義紙というお馴染みの作業になります。しかし、一般にはテーブル1つについて、それを一覧表示したり、全フィールドあるいは一部のフィールドを表示したり、変更可能にしたりという基本的なレイアウトのセットも作ることになります。このテーブルの作成やその後の管理、それを取り巻く基本的なレイアウトを管理する作業を考えます。この作業を1つのテーブルに対して行う作業量を、ここでは「単位」と呼ぶことにします。もちろん、簡単なテーブルだと10分で終わるよと言うかもしれませんし、大量に計算フィールドがあるとなると時間はかなりかかりそうです。しかしながら、見積もりを平準化してできるように、「1テーブルの作成管理タスク」を「1単位」としてこの後の作業を見積もります。1つの言い方としては、小さな作業の数々を「1テーブルの作成管理タスク」としてまとめているということです。

その上で、先にこの1単位の時間数を決めないといけません。自分自身は「1単位=3時間」くらいが適切かと考えています。いや、4時間などもっと長くてもいいように思います。テーブル一つで何時間もかかるかと言うと、実はかかると言えます。まず、基本的なテストつまり実装結果の検証まで含めて開発作業は進められるので、その点を加味してください。開発途中でフィールドを増やす、あるいは値一覧との連携が増えるなど、小さな作業ながらも途中で色々と作業は増えていくと考えられます。また、簡単なナビゲーションを作るような仕事もここに含めると考えていただければ、大体そんなものかと考えていただけるかと思います。また、スタッフの経験や能力によっても変動があっても良いでしょう。ともかく、1テーブルの作成管理タスクを1単位として考えると言うのが見積もり作業の基本であると考えます。そして、テーブル数が積算見積もりの1つの重要な項になります。

時間のかかるレイアウトを特定する

「追加レイアウト」については、レイアウトをどれくらい作るのかを識別します。ここで、ごく基本的な参照や検索、入力、編集を行うレイアウトのようなものは、「テーブル数」の側に作業は含むと考え、それら基本的なレイアウト以外のレイアウトを特定します。伝票入力のレイアウトがあって、特に変わった作りをしないのであれば、その入力レイアウトは1テーブルの作成管理タスク内のものとします。しかしながら、それに加えて印刷用のレイアウトを別に作ったり、あるいは複数の印刷用レイアウトを作るなど、基本的なレイアウト以外にどれくらいのレイアウトを作るのかを計算します。したがって、単なる入力レイアウトと言えども複雑な処理が絡むのであれば、それもカウントします。集計のレイアウトを作る場合も「追加レイアウト」になるでしょう。ともかく、レイアウトについては設計ができていれば概ね列挙することは可能ですし、その中で時間のかかりそうなものとそうでないものを見極めるのはそんなに難しいことはありません。

この時、レイアウト1つ1つに仮の名前をつけて識別するようにして、各レイアウトに対する見積もりを先ほどの「1テーブルの作成管理タスク」の1単位の「単位」で数値化します。そこそこ楽ちんなものでも、やはりテストを考えればそれなりに時間はかかりますし、綺麗なレイアウトを作るとなるとそれなりに大変です。集計のレイアウトを完成させるには元データも必要だったりします。そう言うことを考えて、例えば「顧客別月間売り上げ一覧レイアウトは2単位」などと決めて行き積算します。伝票に対する印刷用レイアウトは1単位というとちょっと多すぎる気もするものの、最低1単位でカウントするのが良いと思います。ただ、あまりに小さなものやコピペで量産できるものがあれば、「レイアウト群」で何単位を考えるとか、最小0.5あるいは0.25単位で考えても良いかもしれません。しかし、最初に指摘したように、細かい分類分析をして加算するのは限界があるので、あまり刻まない方が時間もかからなく、見積もりには適しているのではないかと思います。

時間のかかる実装作業を特定する

「重い作業」は文字通り、そのような作業です。これも、追加レイアウトと同様に、発見し、それぞれ識別可能な名前を付けて単位数を割り当てます。例えば、伝票入力するとしても、数万件の商品マスターから選択して入力するとしたら、そうした「入力のサポート」を実装することを求められます。例えばそれを1単位とするわけですが、その場合「入力サポートレイアウト」として追加レイアウトに1単位、「重い作業」に加えて1単位といった具合でも構いませんし、レイアウトは省略して「重い作業」に2単位でも構いません。あるいは、リレーションシップが複雑な場合や、ルックアップの処理が複雑な場合もあります。そうしたリレーションシップのTO結合を設定するのも1単位の重い処理としてカウントするのも良いでしょう。ともかく、時間がかかりそうな作業を、テストまで行うのにどれくらいの手間がかかるのかを「単位」を手がかりにカウントします。

外部との連携はまさに重い処理の典型と言えるでしょう。単にCSVファイルから読むだけならいいのですが、例えば、複数のファイルを読んで一部は読み込み後に処理を行うだとか、重複を消したいなど色々な作業が入ります。APIをコールしてそこからデータを取り出しテーブルに展開といった作業は場合によっては2単位、3単位と増えるでしょう。タイマー動作のサーバサイドスクリプト、JavaScriptプログラミングが関わるWebビューアを使ったビジュアルなど、重い作業は色々あります。最終的な統合テストについても、例えばユーザ立ち合いで行うなどの作業が発生するとしたら、統合テストそのものも重い作業です。一般には、設計がしっかりしていれば、統合テストを含めてのテーブルと追加レイアウト等の「単位」なのですが、状況によってはそれも分離しましょう。

この重い作業は、おそらく1以下はあまりないと思います。むしろ、上限はなく、5や10くらいまで上がるような場合もあるかもしれません。一般には他のシステムとの連携部分で、1〜3単位になるくらいではないかと思われます。

単位を積算する

以上のように「設計作業」「テーブル数」「追加レイアウト」「重い作業」の4つを考えて最終的な見積もり作業量を算出します。追加レイアウトと重い作業は、数式化するとシグマとかややこしそうですが、リストアップして1つ1つに単位数を割り当てるということです。もちろん、これはuが均一としていますが、数人にタスクを割り振るときには、それぞれの担当者ごとに合計単位数を求めて、各自のu値をかけた後に加算する必要があります。

D = 設計にかかる時間数
u = 1単位の時間数
T = テーブル数
Li = 追加レイアウトの単位数(i = 1..n)
Ti = 重い作業の単位数(i = 1..n)

見積もり時間数 = D + (T + ΣLi + ΣTi) × u

こうして算出することで、実際に「作ってみないとわからない」と思いがちな開発作業時間が算出されます。

そして、重要なことは、振り返りを行うことです。業務が終わった後に、ピックアップしきれなかった追加レイアウトや重い作業にどんなものがあったのかということを改めて考えてみるのは、次の業務への改善になると考えます。

なお、この手法、ローコードツールへは十分に適用可能と考えます。もちろん、その領域の言葉で色々説明することになるとは思いますが、データベースをシンプルに捉えてその上にUIを構築するという点ではローコードツールは共通点が多いと考えます。皆さんが利用されているツール上での見積もり手法として、改良するのも良いでしょう。

[開発プロセス#13] アプリケーション全体を改めて記述する(2)

前回の続きである。前回はユーザーインタフェース要素、つまり、HTMLで記述できる要素は、仮想的に変数とバインドされているという仕組みの考えた上で、ユーザーインタフェース要素と、処理の記述の分離ができていることを説明した。その時の図を利用して、続きを説明しよう。

ここで処理は、分類1から5までに分けて記述をした。このうち、分類3と4がサーバーで他はクライアント側の処理として実装するのが効率良いと考えたとする。「分類2」は、最初に検索フォームを表示する仕組みを記述しているので、特にギミックがないのであればスタティックなHTMLを表示するだけになる。この図では、HTMLの表示には、その要素のHTML記述をテンプレートとして、それを元に画面を構成して表示するという記述で統一することにする。

「分類1」は、フォームに入力された検索条件を元に検索を行い、その結果を画面に表示するまでの、残りの分類を全て通ることになる。分類1については、以前に考えた基準に従って、「やるべき処理」をボックスにして記述をしたが、ここでまず、違和感が出てくる。やはり、ここでは、ボックス間の矢印は「次の処理」を示すことになり、ボックスによって矢印による処理の段取りが変わってくる。であれば、同じ矢印で示すのはどうかと考える。このボックスと矢印の記述の意味を検討して改良することは次のステップで進めることにする。

「入力内容検証」となっているが、設計であるのなら、どのような検証を行うのかを記述すべきであることは明白である。ここでは、OCL等を利用した記述を行うのが順当と考える。

入力に問題がなければ、その値を持ってサーバーからデータを取りに行く。ここで、分類1から分類4にかけては、要するにサーバに対してHTTPのリクエストをPOSTメソッドで行うというごく一般的なCGIの仕組みを利用することになる。「サーバーへPOSTメソッド」から「POST受け入れ」までの処理は、時代によって記述方法が違っていた。古くから行われているのは、FORMタグ要素のSUBMITボタンを利用することで、POSTメソッドをサーバーに投げるということだ。そして、PHPを利用していれば、「POST受け入れ」は自動的に処理されて、分類4は言語要素というか、Apache等のWebサーバーとの連携の中で処理がなされて、POSTメソッドに含まれるパラメータが変数に設定されて、プログラムのファイルの1行目からが実行されるということになっていた。分類5については、PHPを使うのであれば、echoコマンド等で出力した結果をバッファに蓄え、クライアントに送り返す。ここはリクエスト-レスポンスの関係を分離4の部分が担う。その意味では、分類4の部分は、よほどのことがない限り、自分で作ることはないと言えるだろう。分類3がサーバーサイドでの処理の部分である。

なお、FORMタグを使って検索条件を送り込み、その結果を表示するとしたら、分類5の「検索結果表画面生成」はサーバー側の処理となる。それをブラウザはそのまま表示すればいいからだ。しかしここで、分類1〜分類4までの流れをAJAXで実装したとする。そうすれば、おそらく、サーバーから受ける分類5のインプットの部分は、JSONなどの純粋なデータのみになると考えられる。そのデータを、クライアント側が保持する一覧表のテンプレートと合成して、実際にページとして表示される。これは、モダンなJavaScriptプレームワークに共通した仕組みであると言える。

これまでに検討した記述方法で全体像を記述してみたが、前述の通り、ボックスと矢印の部分の違和感を払拭することが必要であると考える。また、バインドしている事実が明白であれば、たとえば、フォームないの「名前」と「名前:検索条件」と記述した変数とのステレオタイプがbindingの関係は明白なので、この関係は1つのオブジェクトで記述しても良いだろう。また、ボックスと矢印がどの変数をアクセスするのかをより詳細に記述することにより、ユーザーインタフェースと処理プロセスの間の同時存在必要性も見えてきて、モジュール分離の指針にもなると考えられる。これらの点を引き続いて考えて行くことにする。

[開発プロセス#12] アプリケーション全体を改めて記述する

開発プロセスの検討を継続的にブログの記事にしてきたが、前の書き込みから3ヶ月が空いてしまった。しかも、#11はフレームワークの機能との分離を目指すことを書いたが、ちょっと順序を間違えたかもしれない。これまでのところで、Webアプリケーションの設計図を描くということを目指しているのだが、ユーザーインタフェース要素と処理の明確な分離がまず1つの目標であった。そして、ユーザーインタフェースは概念的な意味での変数にバインドしているという状況を記述するものであった。その間を、使用しているデータ(あるいはモデル)をある程度意識しながら、「処理の流れ」を記述することを検討していた。

Webアプリケーションとして、検索フォームがあって、その結果を一覧表示するようなものを検討してきたが、ここまでの検討の結果を利用して、図をさらに詳細に描いて見たのが以下の図である。図がだいぶんと大きくなってきた。また、書きながら問題点も出てきているが、まずは、図が何を示しているか、あるいは図が何を表現できているのかをまずは説明しよう。

まず、図の左側には、<<user interface>>というステレオタイプが記述されたサブシステムによる3つの「画面」が縦に並んでいる。「フォーム」と「一覧表」の2つだが、エラーメッセージ用にダイアログボックスが表示されるとすると、ダイアログボックスは「フォーム」の一部であるとも見ることができる。以前に説明したように、「フォーム」では、検索条件を入力するテキストフィールドがあり、「検索条件入力画面」というバウンダリーは、「名前」などのテキストフィールドから構成される。また「検索」ボタンをクリックするとデータベースから検索を行い、その結果を一覧表示に表示されることを期待する。エラーメッセージを表示する「JavaScriptアラート」は、メッセージとOKボタンの処理から構成される。

「一覧表」画面も、同様に「検索結果表示画面」というバウンダリーに代表されるが、名前や住所などのエンティティを表示する。「一覧表」の中の記述だけでは、一覧表になっているということが不明確である点は何らかの検討が必要と考える。

バウンダリーの要素としてはテキストフィールドやチェックボックスなどがあり、図では「検索条件入力画面」のコンポジションの1つである「名前」や「住所」などのように、具体的な定義が記述されている。Web開発ではその要素を参照して…というプログラムを書くか、あるいはフォームの仕組みを利用してサーバーにサブミットすることで終わりとなるが、ここでクライアントサイドの動作の詳細を検討するために、バウンダリーの要素は変数とバインドしていることにする。図では<<binding>>というステレオタイプで記述しており、「名前:検索条件」がその一例である。こうすれば、画面上の要素の設定や取得は、変数に対して行うという処理で一貫性が出てくる。しかしながら、実際にはそこまでの動作をやるとしたら、何らかのフレームワークを使うだろう。ここではフレームワークを取り入れた設計を先々では考慮したいので、あえてバウンダリーの要素を変数にバインドするという記述を行うことにする。

一方、「検索結果表示画面」バウンダリーについてはどうだろうか? 変数とは言え、単一のフィールドなら変数でいいとしても、データベースへのクエリーで得られたものであれば、結果的にはレコードという1つの集まりとなり、それらがさらに配列等で複数存在する結果を記録できなければならない。図では「レコード」、および「レコードセット」と表現している。一覧表にデータを表示するとなると、バウンダリーの要素(図では一覧表サブシステムのコンポジション「名前」など)は、テキストフィールドにしてもいいのだが、通常はTDタグ要素や、あるいはその中のP/DIV/SPANなどのタグに値として設定することになるだろう。テキストフィールドの場合には、変数とのバインディングということは考えやすいが、編集不可能なタグ要素についても、その要素と変数がバインディングしていると考えることが必要と考える。ただし、通常は、変数に値を代入すれば、それが要素に出てくると言った、変数→要素という一方向のものである。しかしながら、ある同一のレコードの、同一のフィールドの値が、テキストフィールドとDIVタグ要素に表示されているとする。単にHTMLだけの実現ではテキストフィールドの値を変えても、DIVタグ要素の値は変わらない。しかしながら、同一の変数、あるいは変数間の同期を実現しているのであれば、テキストフィールドを変更すると同時にDIVタグの表示が変わるということが実現可能となる。結果的に、データベースから取り出した値を有効に使うにはレコードをオブジェクト、レコードセットを配列で扱うことになるが、それらをオブザーバブル(Observerパターンを適用して、変更結果を他のオブジェクトに伝達する仕組みを持つもの)にする必要があるという議論に到達できるのである。一覧の表示に変数という媒介を考える必要はないと言ってしまえばそれまでだが、バインディングを通じてバウンダリーと背後の処理が連携するという仕組みは、MVVMパターンが持つ大きな特徴の1つでもある。その点でのバインディングを基調とした抽象化はフレームワークを単なるテンプレートエンジン以上の価値があるものへと押し上げたこの10年近くのフロントエンドの発展を支える重要な概念となった。

図の説明はまだまだ尽きないので、続きは次回に説明する。

[開発プロセス#11] フレームワーク機能と実装する機能の記述

少し間が空いたが、ここからは、次の記事までの時間がかかる領域に入る。

これまでのところで、Webアプリケーションやスマホアプリケーションなど、クライアントとサーバーに分離しつつ、全体で統合された動きを期待する場合の、UIを司るクライアントサイドでの設計内容記述を、一般的なクラス図から拡張子、バインディングやイベント監視といった特有の機能や、あるいは役割よりも手順を記述したり、UIの要素を分離するなどの詳細化をおこなうことで、1つのダイアグラムにより多くの情報を含めることを意図した記述方法を検討してきた。

引き続いてこれまでに記述してきたようなダイアグラム上で、フレームワークの機能と実装すべき機能の分離を明確に記述することを目標に記述方法を検討する。ある特定の機能について、当然ながら、まずは次のような分類ができる。

  • A: フレームワークに頼らず全て実装する
  • B: フレームワークに一部頼って実装する
  • C: 全機能をフレームワークに頼る

Bについては、当然ながら、割合や実装手段としてファンクションコールなのか、コールバックなのかなど様々なパターンが考えられる。Cについては、例えば、設定や指定されたメソッドの組み込みにより、本来の処理の流れの中には明示的に記述されない物も含めることにする。したがって、「何も書かない」わけではなく、何かを書くものの、その機能が必要とされる段階では何も記述しない、あるいはそれに等しいような機能を指すことにする。

まずは、これらABCを次のような記法で記述することにする。

 

figs

フレームワーク機能については、ステレオタイプの<<framework>>を付与することにする。Bについては、コールバックの場合はフレームワーク機能への矢印は逆になる。また、Bについては、Proc1′ + feature1 = Proc1になり、Cについてはfeature1とProc1での結果が同一であることが期待される。

こうしたルールのもと、フレームワークの機能を1つのモジュール的に示して、設計の上でどのようにフレームワークの機能を利用するのかを明示的に示す方針のもと、いくつかサンプルとしての設計を進めてみることにする。

[開発プロセス#10] バインディングとイベント処理の記述

ここまでのところで、ロバストネス図を出発点として、Webアプリケーション向けに設計図を作成するための表記方法を検討してきた。バウンダリーを詳細化して、必要な要素に分解してダイアグラムに記述することや、処理をコントローラーという大きな単位でなく、処理ステップという小さな単位で術することで、具体的な設計情報をダイアグラムに入れることができることを示した。続いて、クライアントサイトでのバウンダリーとエンティティの関係をバインディングという視点で見た時にどのように記述するかを検討し、そこから、イベントのハンドリングを記載する方法を検討する。

Web、すなわちHTMLでのユーザーインタフェースコンポーネント、つまり、ユーザーからの応答を受け付けるコンポーネントは、さほど種類は多くはない。ここではまず、テキストフィールド(INPUTタグでtype属性がtext)と、ボタン(BUTTONタグ)の2種類のコンポーネントを考える。例えば、ボタンを押すと、何か文字列がテキストフィールドに入るといったごく単純なプログラムを作りたいとしたら、ロバストネス図的には次のようになるだろう。今回は処理のステップまでは考えないので、コントロールは丸い矢印線のアイコンで記述することにする。

step1

ここで、バインディングの実装が入るとどうなるかを検討する。バインディングを一般的に記述すると、変数とコンポーネントの値が連動することと言える。ここでのコンポーネントは、テキストフィールドやあるいはHTMLの場合はノード(タグ要素)そのものも示す。そして、コンポーネントの値を得るには変数を参照することで可能となり、コンポーネントの値を変更するには変数に代入するということで実現する。つまり、変数がコンポーネントに成り代って存在することであり、変数とコンポーネントの状態の管理は、全てが自動的に、つまりはフレームワーク側で行うことが期待されてる仕組みである。タグによって動作が違う点の吸収など、実装上は様々なことを検討する必要があるが、ここではバウンダリーの値と変数の値が連動する点に集中することにする。前のロバストネス図を、テキストフィールドに対する変数があるとすれば、変数に代入すれば、その値がテキストフィールドに反映するという流れを次のように記述できる。

step2

しかしこれでは一方向だけの処理である。現実には、変数とテキストフィールドの双方向のやりとりが発生していて連動しているのだが、ここで、ステレオタイプを利用した表記を導入する。点線矢印にbindingというステレオタイプを記述することにした。本来は鏃を両側に記述したいのであるが、クラス図の点線矢印は依存関係を示すものなので、双方向という記述はできなくなっている。もちろん、ここでの点線は依存ではないのだが、処理の流れに実線を利用しているので、ここでは依存の矢印で代用し、ステレオタイプをつけることにする。なお、bindingは双方向であることが前提なので、鏃が片方でも誤解をすることはあまりないと考える。

step3

テキストフィールドが2つあって、一方で値を変更すると、もう一方に自動的にその値が反映される状態を記述すると、一例はこのようになる。テキストフィールドごとに変数を確保したとしたら、テキストフィールド2向け変数が更新された時、Observer実装が機能して、あるコントロールの処理が機能し、その結果、別のテキストフィールドの変数に値が代入されるということを意味している。処理2への矢印にobservedというステレオタイプをつけたが、observerは処理2、observableなものはテキストフィールド2向け変数である。ただ、この記述は仮のものである。

step4

ここで、observer実装により変数の変更によって処理が実行される状態を次のように記述する。つまり、監視している処理2から、監視対象のテキストフィールド2向け変数に対して、点線矢印を引き、ステレオタイプとしてobservingと記述する。背後で様々なメカニズムを持つとしても、設計時に概念として知っておくべきことは、何が何を監視しているかということだ。処理2では、テキストフィールド2の変更がbinding-observingとたどることで、処理2が開始される。処理2はテキストフィールド2向けの変数の値を得て、テキストフィールド3向け変数にその値を代入し、テキストフィールド3の値が更新される。

step5

続いてイベント処理も同様に記述できることを示す。イベントは、HTMLのコンポーネントにおいては既定値で発生させることができるようになっている。フレームワークによってはモデルのコンポーネントで独自のイベントを発生するようものもあるが、ここではHTMLの標準の仕組みを考える。以下の図で、ボタン2に対して処理3から、やはり点線矢印が引かれており、event-clickというステレオタイプが記述されている。eventは固定のキーワードで、ダッシュの後に、イベント名(ここでは「click」)を記載し、つまりはボタン2でクリックイベントが発生すると、処理3が実施されることを明確に記述することができる。この図では、ボタン2のクリックにより、テキストフィールド3向け変数に値が代入されるので、テキストフィールド3の値が更新される。

step6

イベントやobserverの実装の記述を利用すれば、バインディングの処理そのものを記述することができる。システム設計上は、bindingというステレオタイプで線を引くだけでいいが、実装をするとなると、次の図のようになる。つまり、テキストフィールドからのいくつかのイベントを拾い、その結果を対応する変数に反映させる作業が必要になる。一方、変数の変更があれば、observingしているコントロールに処理が移り、変数の値をテキストフィールドに反映させる作業が必要になる。この図を見ると、明らかにループしそうだ。テキストフィールドの変更結果が変数を更新し、その結果observerによりテキストフィールドを更新する。ただ、HTMLの場合、そこでイベントは発生しないので、無限ループにはならないが、処理に無駄が出る。これを回避する方法としては、変数の更新処理において、obeserverを動作させるものとさせないものを用意して、適切なメソッド呼び出し(あるいは引数設定)をするといった方法がある。何れにしても、バインディングについては、通常は図の上の表現でも良いが、これまでに検討してきた結果をもとに、その部分を詳細に記述することも可能である。

step7

クライアントサイドでの設計で必ず考慮すべきイベントの表記も含めて、JavaScriptレベルの実装に近づけるより詳細なダイアグラムの記述ができるようになってきたと言えるだろう。

[開発プロセス#9] コントロールの処理の詳細化

前回までで、バウンダリーを詳細化するところまでを記述したが、またまた時間が空いてしまった。サーバーが起動しなかったり、開発の作業に集中したりなどしていた。

さて、続いて、コントロールの中を詳細化する。実際に詳細化できるのかを検討する前に、なぜ詳細化しなければならないのかを改めて検討しておく。多くのフレームワークは、コントローラーという1つのクラスを作ることからチュートリアルが始まる結果、1つのクラスで作るものだと思い込んでいたり、あるいはクラスを複数用意するとしても、連携する手法は特にフレームワークで用意されていないなど、「巨大な1つのコントローラー」を用意する素地が、意図しなかったとしてもフレームワークがお膳立てしているという状況であるとも言えるだろう。一方、最近、ある仕事で、ethnamというグリーが当初開発したethnaの後継というPHPのフレームワークを使う機会があった。このフレームワークは改めて、フレームワークの機能との対比を考えるときの題材の1つにする。このフレームワークの特徴は、コントローラーというクラスを作るのではなく、中心的なコントローラーに対応する決められた名前のメソッドがあるという点である。決められていることは、prepare、perform、preforwardという3つのメソッドが順番に呼び出されるということだ。prepareは結果次第でのちの作業をキャンセルできることから、バウンダリに近いところにあってデータの検証などを行う入力用ビューコントローラーと言える。一方、最後のpreforwardは、出力の直前に呼び出されることから、出力用のビューコントローラーと言える。中間のperfomは、まさに、コントローラーとしての役割を持ち、ここでモデルへ働きかけるなどのビジネスロジックとのやりとりを記述することになる。これらのメソッドが保持されるクラスは決められた場所に作成するようになっているため、コントローラーの粒度はクラスよりもメソッドの方が適切だと言えるフレームワークである。コントローラーというクラスを作る話と、コントローラー相当のメソッドがあるという話は、設計の上では極めて大きな違いがある。抽象的な記述から、フレームワークにあった実装を行うという方針でもいいのだが、この方針だと属人的な実装テクニックや、あるいは「言わずもがな」なルールを読み解かないといけない場面が多そうだ。結果的に、大きな単位で何をすべきかは考えるのがモデルの1つの目的ではあるもの、コードの段階ではもっとも粒度の低い1つのステートメントを記述しなければならない。ならば、コントロールの中の粒度をより細かくして一度考えてみる必要があると思われる。また、フレームワークの機能との対比をする上では、やはり一度は細かな処理に分ける必要があると考える。

まず、次の図は、クラス図を元に、一覧と検索を持つようなWebページのモデルを記述したものである。astah*でクラス図を用意して、バウンダリーは大まかながら、主要なコンポーネントを抜き出して1画面を枠で囲う形式で記述した。モデルは、この段階では概略として記述し、コントロールの中の処理の1ステップずつをクラスで記述した。

クラス図0

この図を描きながら考えたことは、まず、処理には順序があるということである。入力されるバウンダリーから、出力されるバウンダリーに向かっていけば判別つかなくもないが、図を明確にするには、処理の順序を矢印で示し、どちらが先なのかを記載する必要があるということだ。

続いて、どうしても「分岐」は必要になる。前の図は、クラス図で適当に書いたものである。この点から、前の図にはないが、繰り返しや並行処理的なものを記述が必要になることは十分に可能性があるがある。

ここまでに至るまでにすでにお気付きのように、コントロールの処理を詳細化したものは「フローチャート」なのである。もっとも、UMLでフローチャートに近いものといえば、アクティビティ図である。前述のモデルをastah*のアクティビティ図で記述してみた。ほとんど同様な図が描かれているが、バウンダリーやエンティティのアイコンに接続された矢印が今ひとつうまく処理できていない。astah*でこの状態にするには、オブジェクトのオブジェクト名を空、ベースクラスをバウンダリーで使ったクラス名を選択することででき、その後に右クリックして、標準アイコンを選択するもこのようになってしまった。フローチャート部分は作りやすいが、astah*での作業は明らかにクラス図の方がみやすい図を作れる。

アクティビティ図0

この先、図をどうやって作成するかは問題だが、とりあえず、クラス図に戻り、バウンダリーの詳細化を行った。画面要素のキーあるいはフィールドの記述をコンポジションでバウンダリーに追加したが、「JavaScriptアラート」のような手法の指定もあるかもしれない。特にこういう場合の記述はないと思われるので、点線矢印で適用先を記述した。

クラス図0_0

このモデルから実装の方針をもう少し進めよう。バウンダリーの集合が3つあるが中央にある「エラー表示」はシンプルにJavaScriptのアラートを使うとしたら、「エラー表示画面作成」は、単にJavaScriptでwindows.alert(“…”);を実行することである。また、検索ボタンを押した時には検索条件はクライアント側にあるのだから、赤線枠で囲った部分は「検索条件入力画面」のページの中にJavaScriptでの記述が行えることになる。また、そうなれば、エラー表示に伴う「OKボタン」のクリックによる「検索条件入力画面生成」の処理を行う必要はない。その画面を崩さずにアラート表示したのであれば、単にアラートの表示だけでもOKである。結果的に、「エラー表示」は「検索条件入力画面」の一部となった。あとは、検索条件の検証ルールが与えられれば、実装はできそうである。

クラス図0_0_0

残りのアクティビティを分類して見る。分類の基準は、順次実行するアクティビティであるという点になる。つまり、まとまって実行されるアクティビティのセットは少なくともある段階では同一のメソッドの連続したステートメントに記述されていることになるので、その点から分類をする。そうなると、「検索条件入力画面生成」が1つ、さらに「条件を与えて顧客情報検索」「検索結果表示画面生成」が別の分類となり、図中ではそれぞれ分類2と分類4で囲った。分類4の中にある2つのアクティビティは、データ検索とビューの生成といった違うことを行なっている。そうであるのなら、さらに分類すべきであるとも考え、図中の分類3で囲った部分が抽出される。結果的に全部バラバラということにもなるが、分類4のみ2つのアクティビティからなるとも言える。

ここで、まず、分類3の「条件を与えて顧客情報検索」であるが、データを扱っているので明らかにモデルに関わる機能である。そして、いくつかある「画面生成」は明らかにビューに関わる機能である。図の右側に対応するコントロールを記述したが、それぞれ対応するオブジェクトを記述できることから、この図はロバストネス図をさらに詳細したものであるという点は明白である。

実際に実装するとなると、分類3「条件を与えて顧客情報検索」はデータ処理が含まれており明らかにサーバーサイドの処理となる。2つの「画面生成」は、例えばPHPのフレームワークのCodeIgniterであれば、サーバーサイドで記述をする。これくらいの機能ものだと1つのコントローラークラスにまとめてしまってもさほどのコード量ではないと考えるかもしれない。

ここで重要な点がある。それは分類1はクライアント、分類2〜4はサーバーサイドでの実装を行う点が、ある状況では決定づけられてしまうということだ。一般にはサーバーサイドのフレームワークの場合「画面生成」という処理から先は自動的に行われる。画面生成に必要な状況をコントローラーで作り出すのが開発作業である。そこで注目したいのは、考慮すべきクライアントとサーバーの切れ目である。画面生成はどちらかといえば、フレームワークでほぼ自動化されいているので、考慮対象外である。一方、「入力内容検証」後にエラーなしとなった場合、「条件を与えて顧客情報検索」に移行する場面がある。ここは矢印が1つだが、実際には、サーバー側にはPOSTメソッドの受け入れから、該当する処理が記述されたメソッドを呼び出すまでの処理(例えば「ルーティング」など)が入ることになる。これらは自動的にできないメソッドも多い。

これらの検討結果を加えたモデルは次のとおりである。まず、検索条件の入力はフォーム(HTMLのformタグ)で記述することにして、フォーム自体をサブシステムとして記述する。入力結果を検証した結果、サーバーへPOSTするのは、ブラウザが本来持っている機能である。また、POSTを受け入れるのフレームワークあるいはCGIとして持っている仕組みを利用できるので、これらは実装対象ではない。ただし、正しく受け入れがなされて意図したメソッドが呼び出されるようにするための処置は必要であり、それはフレームワークごとに違っている。

クラス図0_0_0

このように小規模なWebアプリケーションでもクライアントとサーバーの分離やフレームワークのサポートの有無を考慮しながら、実装ポイントを探るということが必要になる。従来のオブジェクト指向を基調としたモデルでは粒度が粗く、実装の具体的な手法までをモデルまで記述することはしなかった。言い換えれば、実装した結果の要約を逆解析するようなものであったとも言える。現実の開発でここまであるいはさらに細かい詳細化がモデルの段階で必要かどうかという議論はあるだろうが、その点は別にしてもWeb開発の学習やフレームワークの理解にはこうした手法が有効であると考える。

[開発プロセス#8] 画面要素に関するモデル記述の試案

前回より少し間が空いてしまった。また、タグをきちんとつけていなかったのを直した。

ロバストネス図やコラボレーション図を作るとき、バウンダリー、コントロール、エンティティの3種類に分類することは、図の中の各要素の役割を考える上で必要かつ多すぎない点から、やりやすい方法ではある。しかしながら、1つの問題は、バウンダリーの表現力が低いことである。「一覧画面」や「何か操作をする」という大まかな1つのアイコンがあるのがよく見られる作図結果である。この記述をまずは詳細化できないかを考えてみる。ここでは、モデルとして、クエリー結果の一覧があり、その一覧の中に各行に対するボタンがあり、その一覧とは別にテキストフィールドやボタンなどのフォーム要素が並んでいるような状況を考える。フォーム要素は、一覧に対する検索条件を当たるものや、あるいは一覧にレコードを追加するものなのが考えられるが、動作は違うものの要素としての構成は同じようなものと見ることができる。

まず、これらのすべての要素を含むWebページが、コントロールから生成されたことを明確に示す必要がある。一方、ページ内部のコンポーネントのうち、単に表示するようなものについては、そこからコントロールを呼び出されることはないので、図の中で特別な記述は不要である。一方、ボタンなどのフォーム要素や、あるいはイベントを受け付ける要素については、それぞれが別々の動きをするので、その点が記述できなければならない。ICONIXの手法を解説したダグ・ローゼンバーグらの書籍『ユースケース入門 ユーザマニュアルからプログラムを作る』では、次の図のような記述を行なっている。つまり、バウンダリーの中で、特別な動作を行うような要素もやはりバウンダリーであるが、画面全体は画面の一部の集約(コンポジション)としている。図中の点線枠に入っている部分が、1つの画面を構成するバウンダリー群となる。なお、一覧表示の各行に「詳細表示」ボタンがあるとすれば、UML的記述をするには多重度の記述を行うことで、複数存在することが示すことができる。この点は書籍には明示されていない。

画面要素を分離

ここで、実際に開発をする場合に必要な情報が込められているかどうかを検討する。この図にない要素としては、ページが一覧と検索領域に分かれていることや、一覧にどんなフィールドが表示されるのかといったような内容である。これらを含めて記述するとしたら、次の図が得られる。画面の領域を、「一覧表示」と「検索条件入力領域」の2つのサブシステムで表現し、それらのサブシステムは「一覧表示画面」の集約であるとした。一覧表示は、通常は「ヘッダ」「内容」「フッタ」の3つの領域を持つのは、HTMLの定義からも明確である。一覧表示のサブシステムはこの3つの要素が常にあるものとして最初から配置されているとする。「内容」については、繰り返されるのであるが、UML上での一般的な表現はないので、repatingというステレオタイプを付与することにする。この場合は、一覧のないように「名前」と「住所」フィールドが配置され、それぞれの行には該当するレコードに対応する「詳細表示」ボタンが組み込まれることを意味する。

画面要素を分離_0

このようにUMLの記述を拡張することで、画面構成も含めたモデルの記述ができるようになる。しかしながら、画面を構成する要素については、その実物を想像しやすいようなアイコンにすべきと考える。

[開発プロセス#7] 開発対象システムのモデル記述

システム開発でモデルを作成することにより、これから作るシステムが要求に合致したものであるのかといった側面の検討だけではなく、効率の良い実装が可能であるのかといった側面や、予想される改変や拡張に対して実現可能性やその効率性、テストのしやすさなど、実装に直結すること以上に利用できる。しかしながら、その作成するモデルは、様々な手法がある。要求の記述という点ではユースケース図とユースケース記述が出発点にはなるが、データベース主体の開発だと、ここでER図の作成を主体にすることが多い。データベースの構造は対象ドメインの状況を記述できるようになっている必要があるのだが、その結果、全てがデータベースの設計結果であるスキーマに集約されているという見方をしてしまいがちである。ある作業を、スキーマで解決するか、あるいは実装するプログラムで解決するかはもちろん考えるのではあるが、では「ここの処理はプログラムで」というアイデアはER図やクラス図では不明確である。メモを残すなどの工夫が必要になる。

一方、Webシステムではワイアフレームといったざっくりとした画面のデザインをもとに、画面遷移を定義することで、システムの全体像を示そうとする。しかしながら、画面デザインが反映するのは、システムへの実装以前にドメインに対して実施される分析をもとにして作成されるビジネスモデルであり、実装に直結したER図等のモデルからのズレが生じする場合もある。しかしながら、HTMLでの動的なユーザーインタフェース作成機能は限られていたので、例えばチェックボックスであればどういう動作をすべきかということを逐一記述しなくても、半ば「常識的な判断」で進めることであまり大きなブレは発生しなかった。さらに、結果的にビジネスモデルとER図で記述されるスキーマとはあまり変わらないことお多いので、HTMLのモックアップが「設計」として扱うのは、デザイン主体の開発会社では頻繁に見られる方法である。

このように、ある程度のスキルや、ワークフローができてくると、途中を省略する傾向は強く、単一の会社でそれが回っている間は特に問題視はされないだろう。しかしながら、Webの世界は変化が激しい。特にここ5年くらいの時期はクライアントサイドの作り込みの度合いが高くなり、ユーザーインタフェースは複雑化している。その結果、Webのクライアントサイドは多階層的な機能分離を図る必要が出るなど、スマホのクライアントのネイティブアプリケーションに近い構造になっている。

こうした状況が変わってきた時、ワークフローを見直す必要があると考える。今までの知見や常識として暗黙知的に取り扱っていた知識だけでは、新しい問題に対する解法がない可能性が高く、最適な設計ができなかったり、チーム内での意識の疎通が悪くなる。そのために、本来的な詳細なモデルを記述するということが必要なのである。そこを出発点にして、省略やあるいは詳細化をするとしても、Webシステムのモデル記述の手法を一定のレベルで確立する必要があると考える。

UML自体の汎用性は高く、その点では有用性も高いのは事実である。しかしながら、UMLやその周辺手法を使ってWebシステムの記述をするにあたり、次の点に対して何らかの解決策が必要と考える。

  1. 詳細化するとき、明確なルールは特にない
  2. クラス図を主体にすると、オブジェクト指向が前提となる
  3. ボックスがクラスやオブジェクトで、呼び出しが矢印線的な切り分けによる分かりやすさはあるが、処理の記述では呼び出し線に名称を書くことになり、図を見やすく作ることが困難になりがちである

まず、1の詳細化についてである。作成したモデルと、使用するフレームワークの提供機能を比較検討して、実装箇所を特定するには、極端に言えば、プログラムの1行レベルまでを、モデル内の1つの要素として記述することも必要とされる。また、ロバストネス図やシーケンス図では「画面」を1つの要素として扱うが、実際に処理の流れを追う場合、ボタン1つ1つは原則として異なる動作をするので、ボタン1つ1つを要素として表したいということになる。このための指針が費用である。

2つ目のオブジェクト指向である点は、Javaのプログラムだけを作るような場合には確かに有効ではあるが、HTML、CSS、JavaScriptが絡む世界では必ずしもオブジェクト指向ではない。つまり、クラスやオブジェクトを1つの単位として考える場面は実装時にはあるかもしれないが、分析時にはどちらかと言えば、より細かい単位での要素を記述したい。最終的にはメソッドが集まってクラスになるとしても、対象としたのはメソッドであり、その中でどんな処理をしたいかということである。

3つ目は、コミュニケーション図でオブジェクトからオブジェクトに線を引き、線に添えてメッセージ呼び出しを記述する。この方法は実体あるいは実体化可能なものはボックスであり、メッセージは矢印線であるという明確な分類があるものの、簡単なモデルでも、オブジェクトとメッセージを見やすく配置するのはかなり大変である。ましてや、複雑なモデルだとなおさらである。ここではメッセージの記述が作図作業を煩雑にしている点は明白であり、それに代わる表記方法を検討すべきであると考える。

これらの懸案をまずは見える範囲での解決を行った上で、Webシステムのモデルを記述することにする。まず、1〜3に対する提案を次回より行う。

 

[開発プロセス#6] Webクライアントの機能モデルのパターン

前回はWebクライアントがMVVMパターンによる機能分類での説明が可能であることを考察しましたが、もう1つ忘れてはならないのが、PACすなわちPresentaion Abstraction Controlというアーキテクチャパターンだ。F.ブッシュマン他の『ソフトウェアアーキテクチャ ソフトウェア開発のためのパターン体系』(POSA本)では、1つのコンポーネントの内部構造として、可視化を行うPresentation、データモデルの維持管理を行うAbstraction、そして、PresentationやAbstractionとやりとりをしつつ、PACのコンポーネントの外部とのやりとりを行うControlの3つの要素を持つと定義されている。そして、その1つのコンポーネントをエージェントとして、システムとしてはエージェントの階層構造を持つとしている。以下の図は前回の記事で示したものと同じものである。

MVVM Client-Side

これを、PACでの分類で考えれば、[入力項目1、入力データ1]、[入力項目2、入力データ2]は、それぞれエージェントとであり、その中でのPresentationとAbstractionコンポーネントであると捉えることができる。ただし、Controlを明確に分類するのは難しいと考えるが、いずれのコンポーネントも、バインディングという仕組みをControlとして持つと考えられ、入力が発生したことを別のエージェントに伝達するという構造として捉えることができる。そして、それらの上位のエージェントとして、[エラー表示、NULL、入力値検証]といったPACエージェントがあり、さらに、その上位に[NULL, NULL, 送信]というPACエージェントあるいは単なるオブジェクトがあるという見方もできる。こうした見方をすれば、Webクライアントの動作はPACパターンでの識別による記述も可能であると考えられる。

今回は短いが、以上である。

[開発プロセス#5] Webクライアントのパターン

前回はWebアプリケーションのモデリングを、ロバストネス図で行うことによって、MVCを基調とした考え方と大きな違いはないという点を考えました。もっとも、「感覚的にそうである」と言ってしまえばすぐに結論に至りますし、厳密な意味で同等あるいは同様であるということを証明するまでも至っていません。言えたことは、ロバストネス図で記述する内容が、Webアプリケーションの動作や構造を明らかにする上で検討することと、概ね共通しているという点くらいかと思います。

その議論の続きで、Webクライアント側のシステム設計を進めるにはどうすればいいかを考えます。Webクライアント、つまりJavaScriptとHTML、そしてCSSで表現可能な世界では、今でも簡易的あるいは補助的なプログラム作成が可能な程度で、本体はサーバーであるような印象を持つ人も少なくはないと思います。古い時代、確かに大掛かりなプログラムを動かす環境としては、ブラウザーは貧弱でした。しかしながら、10年ほど前、2007〜2008年くらいの時期にブラウザーのメーカーがJavaScriptの動作環境を飛躍的に効率化した頃から、世界は大きく変わり始め、jQueryによってDOMベースのプログラミングが一気に普及しました。DOMのAPIは昔からありますが、APIを使ってまとまったプログラムを書くのは比較的に難し買ったのですが、jQueryは簡素化された書き方で、クライアントサイドのプログラミングの機会を広げました。さらに、2009年にはAnglarJSの前身である<anglar/>がリリースされ、その後にBackbone.js、KnockoutJS、Ember.jsなどと本格的なフレームワークがリリースされました。当初は、サーバーサイドのMCVとクライアントサイトのMVCという考え方もあったのですが、サーバーとクライアントの本質的な違いに気づくのに時間がかかりませんでした。

ネットワークサービスではデータの共有が1つの重要な機能です。そうした仕組みはサーバー上でRDBあるいはNoSQL等を使って実現することになり、永続的に利用出来る仕組みは必ずサーバー側に構築されることになります。したがって、データベースを効果的に使うための「モデル」というレイヤーのプログラム群を構築したり、データ処理に直結するビジネスロジックは、サーバーサイドで実行されるのが素直な役割分担でしょう。一方、ユーザーインタフェースは結果的にクライアントのブラウザー側で実現されていることです。UXの向上を掲げるプロジェクトが一般的になり、Webのユーザーインタフェースでも、高いレベルの要求が発生しました。つまり、高いデザイン性とスムーズな応答が求められるようになり、ボタンを押せばサーバーを呼び出すというやり方を越えるべく、AJAXによりブラウザー画面の更新以外にも通信を行い、サーバーのやりとりの結果で画面の一部を更新するといった処理が必要になりました。つまり、クライアント側では高度なユーザーインタフェースをサポートするのが主要な目的であることがはっきりしてきたのです。

もちろん、MVCでも高度なユーザーインタフェースの管理は可能です。しかしながら、具体的にどうすれば高度なユーザーインタフェースを構築できるかを考えてみましょう。ユーザーインタフェースで入力した結果をJavaScriptのプログラムで処理をしたいとまずは考えます。加えて、ユーザーインタフェース要素で発生したイベントの処理を効率良く処理したいというニーズもあります。こうした主要なニーズ分解して考えれば、そのニーズに合致するアーキテクチャパターンはM-V-VMであると言えるでしょう。MVVMは.NET Frameworkの中にあるWindows Presentation Framework向けのアーキテクチャとして、MicrosoftのJohn Gossmanによって提唱されたものですが、Flashの対抗として出されたブラウザー拡張機能のSilverlight上でのアプリケーション開発が中心的な話題になっていたと思われます。

MVVMでは、Model、View、ViewModelをコンポーネントして、アーキテクチャが定義されています。しかしながら、この3つのコンポーネントよりも重要なのが、それらのコンポーネント間のつながりです。まず、ビューとビューモデルの間は、バインディングによって結合されていることが挙げられます。バインディグとは、例えばテキストフィールドがページ上に表示されているとして、そのテキストフィールドの中の文字列(つまり、コンポーネントの値)が、何らかのエンティティ(例えば変数や配列の要素、オブジェクトのプロパティなど)と論理的に結合されていて、大局的にはコンポーネントとの値とエンティティの値は、一方が変わると自動的他方にも伝達されて、常に同じ値になるということです。言い換えれば、ビュー階層にあるコンポーネントの変化は、自動的にビューモデルは知ることができるという意味にもなります。一方、モデルは、MVCのモデルと同様な意味を持つとされますが、サーバーサイドではシステム全体のエンティティに関連するものの、クライアントサイドでは、現在のビューにおいて扱うべきモデルに一般には限定されると考えられます。そのモデルはデータベースと関係させるかどうかについては様々な議論があり、今後検討します。まず、MVVMモデルにおけるモデルは、オブザーバーパターンを利用して、モデル内での変化がビューモデルに伝達されるという仕組みを持ちます。この「ビュー階層の要素のバインディング」と「オブザーバーで監視されたモデル」というのがクライアントサイドに要求される、基本的なアーキテクチャと言えます。これらの処理の実現は、JavaScriptでスクラッチから行うのはかなり重いものです。そのため、様々なフレームワークがありますが、JavaScriptのフレームワークは最近出てきたフレームワークも含めて、MVVMパターンを基調としていると考えるのが妥当だと考えます。

MVVM

現実にはフレームワークを使うことになるのですが、フレームワークを特定しないで、クライアントサイドの動作をロバストネス図の表記を使ってコミュニケーション図で記述してみました。例えば、入力項目がいくつかあり、それらのデータが揃うとサーバーにそのデータを送信するという状況を考えます。このような動作のUX的な良し悪しがありますが、ここではバインディグとオブザーバーによって、モデルビューに相当するコントロールオブジェクトにうまく処理が渡ることは確かなようで、それがダイアグラムで表現できていると言えるでしょう。

MVVM Client-Side

ここで議論があるのは、最後の「送信」でしょう。言い換えれば、サーバー側はモデルなのか、モデルビューの通信先なのかという点があります。ビューモデルが、モデルとビューの仲介であるという定義に従えば、サーバーに送るのはモデルの役割になります。しかしながら、それはモデルなのでしょうか?サーバーサイドにあるデータベースを、クライアントサイドで抽象化してみているのが、クライアントサイドのモデルという考え方もできるので、だとしたら、「送信」はモデルの1つに定義するのが的確かもしれません。

ここでアーキテクチャパターンが必ずしもすべてを表現できるものではないという考え方に立つこともできるでしょう。MVVMはクライアントの処理すべてを記述できるでしょうか? 例えば、ページを表示後、ある特定のclass属性を持つ要素の設定をプログラムで変更するような仕組みはBootstrapなどフレームワークの動作としては代表的です。その仕組みは明らかにモデルではないとしたら、モデルビューではないとしたら、どうなるでしょうか? この点を考えても、アーキテクチャーのベースはMVVMであることにより、高度なユーザーインタフェース構築の援助にはなるものの、全ての要素を、ビューとモデルとビューモデルに割り当てるのは無理がありそうです。

しかしながら、ロバストネス図を利用すれば、バウンダリやエンティティでないものは、なんでもコントロールオブジェクトとして定義しておくことができるので、コントロールの一部はビューモデルであるとしても、ビューモデル以外の仕組みも記述できます。MVVMを基調としつつも、ダイアグラムの自由度を利用することで、多彩な処理のモデル化が可能であると言えます。

ちなみに、MVVMの仕組みがあれば、「送信」ボタンは不要になりそうです。しかしながら、その種の「従来と違う」ユーザーインタフェースは不人気です。ボタンが不要でも、ボタンをつけることを要求されることになるでしょう。OS Xでは当初より「確定」ボタンがないにもかかわらず、Webページにはサブミットボタンがないのは気持ち悪いと考える人が多いようです。現状で、送信ボタンのないユーザーインタフェースで受け入れられるようにするには、テキストフィールドの隣などに、「未送信」「送信済み」などとフィードバックの情報を表示するなどの工夫が必要です。