Monthly Archives: April 2020

[続開発プロセス#12] FileMakerによるアプリケーション

ここまでに設計を進めてきたアプリケーションの設計図は以下の通りですが、途中でモックアップを作るときにHTMLを使ったので、それをいきなりFileMakerに切り替えるのは若干無理があると思われるかもしません。しかしながら、モックアップを作る意義は、何をしたいのかを明確にすることであり、ここまでの設計で必要な仕組みが概ね抽出できているということが重要です。クラス図にあるPickingUpとMemoListを見ることで、必要な仕組みを思い出せるはずです。ですが、やはりFileMakerは大きく違う環境です。実際にFileMakerで開発をする方々は早い段階で、FileMakerでどうすればうまく実現できるか、言い換えればFileMakerにおける制約を考慮し実現可能な設計を模索するはずです。もちろん、最初からやればいいのではと思われるところですが、以前にも書いたように、環境を固定してしまうことで、本来やりたい要求を制限し、視野の狭い発想になりがちであるため、まずは必要な仕組みや機能を抽出した上で、どのように実装環境に適応するのかを考えるべきです。

FileMakerで実装する場合、以下の設計図だと、データベースはもちろん問題なく実現可能なところですが、レイアウトに2つのTOからの展開をする方法を検討する必要があります。FileMakerではウインドウ全体を占めるレイアウトには、1つのTOしか設定できません。そのため、同一ウインドウ内に2つの「リスト」を展開するには、それぞれをポータルで展開するか、設計をもう少し変更する必要があります。今回のアプリケーションではポータルで展開する方法でもできそうですが、実際にはポータルでは制約が多くあることから避けたいと考えます。後からの設計変更に対応できない場合が出そうな気がするからです。そこで、今回は、メモのリストをレイアウトに割り当てることにします。そうなると、カテゴリの選択は、別のウインドウに出すとか、別のレイアウトにして切り替えるなどのアイデアが思いつきますが、ここではメモのリストのヘッダ部分で、分類をポップアップメニューで選択して、その選択結果を検索条件としてメモのリストを絞り込むと言うことにしました。カテゴリの一覧は制限がありますが、ポップアップメニューであればそれに近いと言うことで、このような実装にします。また、FileMakerの場合、ページネーションを入れる必要は薄いと思われるのでページネーションは不要とします。日付時刻の入力は、FileMakerの機能が利用できるので、コンポーネント群の利用は不要と考えます。こうした決定をまずはメモとして書き込んでおきました。

FileMakerでの一番大きな制約は、開発言語で使われるようなスタイルのクラス定義ができないことです。そして、レイアウトをベースに画面を構築することになりますが、リレーションシップでのTOや値一覧など、FileMaker特有のオブジェクトがあり、それらを適切に設計する必要があります。

ここでは1つのレイアウトにメモを一覧することを基調としているので、メモの内容をボディパートに配置し、リスト表示にして一覧できるようにすることが基本です。以下の図はレイアウトの設計をしたところです。LayoutからBodyPart以下の内容は特に説明は不要でしょう。これらは、MemoのTOとバインドすることで、表示と編集が可能になります。自動化されるところはこれ以上は記述する必要はないでしょう。ここで、メモの中にある大分類のポップアップメニュー(MajorCategorySelect)と、小分類のポップアップメニュー(MinorCategorySelect)です。ポップアップメニューの設定結果はフィールドに保存されるのでMemoと言うTOと結びつきますが、一方、選択肢を構築しなければなりません。そのために値一覧(ステレオタイプがValue List)をそれぞれアサインする必要があります。大小どちらの分類も、categoryテーブルを元にしたTOを割り当てますが、大分類はもちろん小分類を省いたものですし、小分類は現在選択されている大分類に応じた選択肢が出ている必要があります。ただし、レイアウトを検討している段階では、そこのTOにどんなデータが出て欲しいかと言うことをまずは明確にすることが必要です。よってTOとValu List、そしてコメントだけを記載しました。ヘッダパートはボタンが2つとポップアップメニューが2つです。このポップアップメニューは、メモの検索条件を与えるためのものであり、Memoの1レコードとは独立しています。従って、Value ListやTOも別途与える必要があります。なお、実際には何かフィールドをアサインしないとポップアップメニューは構築できないので、こちらはグローバルフィールドを定義することにします。

レイアウトとしてのモデルが作成できれば、それとデータベースを合体させて、さらに必要な定義を検討します。以下の図はこれまでの作業を合わせたものですが、クラス図で記述する場合、テーブルとTOはスーパークラス/サブクラスの関係で記述するのが良いでしょう。そのデータベースですが、いくつかフィールドを追加しています。memoテーブルのalways1は文字通り、計算結果で常に1を値として持ちます。また、categoryテーブルでは大分類なら1を返す計算フィールドを定義しておきます。他にmemoテーブルではヘッダ部のポップアップの値を受けるためのグローバルフィールドを定義しました。ここで、TO同士のリレーションシップも線で結んでおき、その時の条件をメモで記述しました。大分類は、is_parentが1のものに絞り込む必要がありますし、小分類は大分類で選択されている項目の値とparent_idが同じものに絞り込むことで現在の大分類に応じた小分類の一覧が表示されます。TOのMemoはレイアウトに割り当てられ、レイアウト上のオブジェクトとバインドされるので、それらも線を引いて表現をしました。

ここまでくれば、あとは実装です。ただ、本当にこれでいいのかと思うところもあるかと思いますので、完全ではありませんが、作ったデータベースをダウンロードできるようにしておきます。

今回のアプリケーションだと、メモの側に見える分類は、ポップアップメニューによって、項目名が見えているので、テーブル同士のmemoとcategory間に参照関係は、TOの中には明確には見えていません。値一覧を通じて間接的な関係しかありません。ER図での関係と、TOの関係すなわちFileMakerデータベースのリレーションシップは、微妙に違うと言うか、視点の違いが読み取れます。言い換えれば、FileMakerでは値一覧をリレーションシップを用いて定義をしているのですが、汎用的な設計には値一覧のような存在は顕在化していないと言うことにもなります。

実際、FileMakerで、このようなモデルベースの開発をするかと言うと、おそらくほとんどの方はやっていないとおっしゃるでしょう。最後の図のような関係は、FileMakerの様々な画面で確認は可能ですが、それらの画面で定義した様々なオブジェクトの間の関係は、頭の中で統合しているのではないでしょうか。そうして実際の開発できる方、あるいは迷いながら開発する方も含めて、FileMakerでは「試行錯誤しながら完成に近く」と言うことが可能です。結果的にこのような設計を示しましたが、ざっくりと設計してあとは動きを見ながら調整すると言うことになるでしょう。これは、FileMakerが汎用言語による開発との違いでよく語られる点ではありますが、それが可能なのは、FileMaker自体、設定できるものに制約が大きくあり、自由度が低いことから、限られた要素のコントロールしかできず、それによって逆に見通しがよくなると言うことがあるのです。もちろん、限られたコントロールでもアプリケーションが作れるほどの仕組みがあるから実用に耐えられるのです。

汎用言語で散々作ったものが設計が悪いとなって修正するのは非常に骨が折れる仕事であることはよく言われていますが、FileMakerではどうでしょうか? 実は複雑なスキーマ、大量のスクリプトによる処理が絡んでくると、FileMakerでも見通しは悪くなります。汎用言語での開発だと、設計をあらかじめしておくことで問題点を先に洗い出すことが行われます。一方、FileMakerの場合はあまりこうした設計を重視せず、むしろ試行錯誤ができる点を頼りに進めることはよくありますが、結果としてある程度作ったあたりから特定の機能が得られなかったり、ちょっとした改変が難しかったりと言うことにもなりがちです。FileMakerだからと言って設計をきちんと行わないと、汎用言語で開発する場合と同じようなことは起こると言えるでしょう。

それでもFileMakerでは試行錯誤はやってもいいとは思います。しかしながら、試行錯誤をしっぱなしでは良くありません。試行錯誤した結果を設計という俯瞰した見方の情報として、ドキュメントなり、あるいはリレーションシップの構造やスクリプトへのコメントなどをで残すことによって、改善させる方法はいくらでもあります。そしてもちろん、要求を最初にきちんと揃えることの重要性は言うまでもなく、その点からもFileMakerで作る場合でもドメインモデルから一般的な設計を作って、そこからFileMakerの制約と向き合うという設計方法は意味があると考えます。

次回は、INTER-Mediatorを使った場合の設計を考えます。

[続開発プロセス#11] MVCパターンベースのWebアプリケーション

これまでの流れで、要求から設計を進めてきました。先にデータベースのスキーマを考える点では、SQLデータベースを使う的なことが早めに決まっているような流れになっていますが、GUIのモックアップから必要な機能を出して設計としてまとめるということをやってきました。ただし、原則としては開発環境の制約に関係なく、要求を元にした必要かつ実現可能性があるような汎用的な設計までができました。ここから、実際に実装が可能な設計を検討します。まず、このような例の場合一番わかりやすい、MVCあるいはMVC2パターンを検討します。

MVCパターンでの制約は、まずは文字通り、モデルとビューを分離して、コントローラーでそれらを統合するという構成にするということがあります。これは制約というより、一種の設計方針として認識されてており、制約という何かできなくなるような「縛り」というよりも、設計を進めやすくする「方針」のような捉え方をされている方も多いと思います。

そして、多くの場合は、HTMLのテンプレートをベースに、クライアントに送り出すHTMLコードを生成します。HTMLがビューであるという見方と、ビューによって生成されたものという見方があり、フレームワークによってその辺りの位置付けは微妙に違っているかと思います。また、テンプレート処理を行うのがサーバー側かクライアント側なのかという点も制約は異なると思われます。ここでは、サーバーサイドで完結するタイプのフレームワークを使っているとしましょう。

主要な制約としてはこのくらいではないかと考えられます。それ以外は、通常は開発言語で記述をするので、自由度は高くなります。巨大なクラスを作っても、小さなクラスに分けても、動くと言えば動きます。

まずは、モデルの抽出です。本質的には、MemoList、PickingUpのクラスで必要な機能が抽出されているので、それを受け付けるという処理を考慮し、テーブルとして用意するmemoとcategoryにそれぞれモデルを割り当てるのが素直な方法と考えられます。CategoryModelの最後の2つのメソッドは、ポップアップメニューの選択肢を構築するためのデータ取得のメソッドになります。

続いてコントローラーとして、MemoListController、CategoryListControllerを導入します。ここで、レイヤー構造となるような大きな区分をパッケージで分類しておきました。UI側の要求をコントローラーで捌き、データベースとのやりとりをモデルによって処理しやすい形式に整えるといった典型的な設計になります。ですが、これは、単にクライアントからの処理が関係しそうな箇所を繋いだだけであって、意図が正しいかを検討しなければなりません。

WebのMVCフレームワークの1つの大きな制約は、クライアントサイドではHTML/JSの世界であり、それがサーバー側でPHPなりJavaなり、異なる世界が展開されていることです。その橋渡しは、テンプレート処理ですが、テンプレート処理はページ構築時に全てを構築することにフォーカスしがちです。

しかしながら、ページを提示後の様々な処理にどう対応するかを、ページのテンプレートの段階で検討しておき、対処をしなければなりません。その後に、HTMLの部分的な要素をテンプレート処理して得ることもあるかもしれませんが、一方、単にJSONで送って返ってくるようなWeb API的な動作が欲しい場合もあるでしょう。

そこで、ここでまず、次の図のようにHTMLのテンプレートを設計します。ページ内の要素に適当に名前をつけてテンプレートそのものをモデルとして記述してみます。事実上、1つのクラスは1つのタグ要素に対応するものに近いレベルで記述しましたが、動作上必要な要素だけが抽出されています。なお、クラス名はタグ名でもいいような気もしますが、ここではそれらしい名前を記述しました。ルートはPageTemplateあり、これがbodyタグと考えても良いでしょう。モックアップの左側にあるカテゴリのボタンが並ぶ部分はCategoryBox、右側でメモの一覧が見えている領域はMemoListとしました。Memoの1行ごとにMemoLineがあり、メモの文字列はMemoTextです。このモデリングは、比較的細かく考えた方が良いでしょう。とは言え、これを書くのは結構面倒なのは確かです。できるエンジニアはこれを頭の中でさっさとやってしまうわけですが、今は開発プロセスの検討をしているので、あえて書いてみました。メモの文字列を表示するinputタグはMemoTextクラスに相当しますが、入力された文字列はvalue属性で得られます。これはブラウザ側の標準機能であるので、ここではprivateの記号で記述しましたが、スコープの意味ではなく、ここでは既定義されているという意味合いでマイナス記号を使いました。

テンプレートの要素をよく見て、その要素が何らかの応答をしなければならない場合には、HTMLelementステレオタイプのクラスはメソッドを記述することにしました。前の図のように、MemoListは書き換えればデータベースへ反映しなければなりません。そういうことで、MemoLineの子要素は全て、update()メソッドを持つ必要があります。update()メソッドのスペックとしては、書き直したら、どこかのタイミングでサーバーに修正データを送り、データベースを更新する必要があるということです。一方、CategoryBox以下のボタンでは、ボタンをクリックすることで、メモ一覧を新たにする必要があり、その意味で、updateMemoList()メソッドの定義があります。さらにこれだけで十分ということではなく、カテゴリが階層化されていて、大分類を変更したら小分類の選択肢が変化するという仕組みが必要になります。つまり、大分類のポップアップメニューを選択すると、小分類のリストをどこかから取ってきて、選択肢を入れ替える必要があります。実装方法はいろいろありますが、この小分類の更新を行うためにMemo_MajourCategoryクラスに、updateMinorCategory()メソッドを定義します。こうして、ページの初期状態をテンプレートとして記述するのはもちろんですが、それがページとして展開された結果を想定して、表示後に必要とする機能をモデルに組み込むことを行います。なお、UI Componentステレオタイプのものは、ここでは詳細設計対象外とします。

テンプレートから元のクラスを検討しましょう。次の図は、テンプレート処理した結果をクライアント側に展開しました。ここで、Webアプリケーションとしての制約があります。クライアントとサーバーの間はHTTP通信によってのみコミュニケーションを取ることができるということは実は大きな制約です。MVC系フレームワークを使う場合、もちろん通信はURLによって柔軟に作り分けることができるのですが、機能を組み込むときに最初に考えることは、それぞれの通信処理でテンプレートを使うかどうかです。ページ全体を生成するときにはテンプレートを利用するのは当然ですが、一方、修正したデータをデータベースに反映する作業はテンプレートを使わなくても良いでしょう。以前だと、サーバーの通信後に常にページ更新をしていたので、それは常にテンプレートを使っていたということになりますが、AJAXを出すまでもなく、現在の仕組みでは単にWeb API的な通信の実装はそれほど難しいことではありません。

ここで、まず、ページを表示するときには、テンプレートをベースに、初期的なメモの表示ルールを適用して、ページ全体を表示します。そのためのメソッドを、MemoListControllerにgetMemoListPage()メソッドとして定義するとします。テンプレートを利用したHTML生成を行って返すことを示すためにTemplatingというステレオタイプをつけておきました。そして、このメモリストでは左側の小分類を押して表示するボタンや、全部のメモを表示するボタンは、同じようにgetMemoListPage()メソッドを使ってページを書き直すのが効率的な設計ではないかと考えられます。この「ページを全部書き直す」作業は、基本的にはHTML上のリンクであり、そのリンクがサーバー側のメソッドを呼び出すので、コントローラーに直接つないでしまっています。ページネーションはコンポーネントとして利用すことにしていましたが、このページネーションも、getMemoListPage()メソッドを使ってページ全体を書き換えるのが1つの方法です(できればリスト部分だけを更新したいですが)。ここの実装はこの設計では細かくは追いませんが、方針としてはMemoListControllerにつながることで進めることにします。

一方、メモの文字列や日付時刻、そして分類の選択肢は、変更をすると、その結果をデータベースに書き直したいわけです。ただし、その作業は、自動的には行えず、要素上で発生したイベントに応じてクライアント側のプログラムを呼び出し、そしてサーバーに要求を伝える必要があります。そのために、クライアントサイドにEditingSupportというクラスを用意しました。もちろん、inputタグ要素の種類に応じて適切なイベントによってこのクラスのメソッドが呼び出されるように、実現可能性を加味した設計にしなければなりません。そして、EditingSupportでは、サーバー側のMemoListControllerにあるupdateMemo()メソッドを適切なパラメータで呼び出すように作ります。こうして、要素の変更からそれがデータベースまで更新される流れがクラス図上で明確に現れてきました。大分類のポップアップメニューを選択した場合、小分類の選択肢を更新するという作業には、ここではPopupUpdateSupportクラスを用意しました。

大分類を示すMemo_MajourCategoryからコールされるのですが、一方でMemo_MinorCategoryのポップアップメニューの選択肢をコントロールできないといけません。select側あるいはoption側のどちらでもいいので適切な参照が必要になり、あらかじめ参照を配列等に記録するか、呼び出し時に更新する要素を指定するなどの方策が必要になります。詳細はここでは省きますが、いずれにしても、JavaScriptで実装すべき内容が、独立したクラスで明確になりました。クラス図なのでクラスで書きましたが、実装じは単に関数でも大きな違いはないと思われます。

ここまで設計を進めれば、MVCフレームワークだと概ねどのフレームワークでも、似たような作業で実装を進めることができるでしょう。フレームワーク特有の事情がある場合は、もちろん、それも考慮して設計を進めます。通常はオブジェクト指向プログラミング環境ですので、クラス図で作った設計との親和性が高いのは当然のことと思われます。

現実の設計では、ここでのコントローラのように、テンプレート処理をしたりしなかったり、あるいは更新処理を受付たり、部分的なHTMLを生成したりと、メソッドによって様々な動作を設計することになります。ここではコントローラーにまとめて書きましたが、むしろメソッドごとに1つのエンティティとして記述した方がわかりやすいかもしれません。フレームワークを利用する場合には、テンプレート処理でスマートにページ生成ができることが強調されますが、ページ表示後の動作についてはそれ以上にたくさんの解決すべき問題を生み出します。フレームワークを使うことで簡素化される面はいろいろあるかとは思いますが、テンプレート処理後の動作を詳細に検討するという作業を、試行錯誤でやっている人は多いのではないかと思います。このように、モデルベースで考えてみれば、どんな仕組みをクライアントとサーバーに持たせるかは全体を見ながら検討できるわけで、より良い側面は多々あります。特に、うまく設計できないで悩んでいるなら、まずはモデルとして設計することは強くお勧めできます。

次回は、同じ設計を別の環境に適用することを考えてみます。

[IM] INTER-MediatorでFileMakerを使うときの注意

FileMakerは、テーブル、TO、レイアウトといったオブジェクトを利用する。Web共有からテーブルを直接指定はできない。また、TOも指定できない。指定できるのはレイアウトのみである。レイアウトが事実上のテーブルに相当するエンティティとなる。したがって、定義ファイルのnameキー、viewキー、tableキーには、レイアウト名を指定する。たまたま、同じ名前のテーブルやTOがあっても、FileMakerのWebアクセス時に実際に利用するのはその名前のレイアウトである。

フィールドのタイプで、日時の記録用に「日付」「時刻」「タイムスタンプ」の3つがある。Web経由では、「月/日/年 時:分:秒」のフォーマットにしなければならない。また、日付フィールドに時刻を含む文字列を入力したり、時刻フィールドに日付を含む文字列を入力すると、エラーになり処理は何もなされない。その「日付等の書式エラー」の番号が500なので、余計なことを考えてしまいそうだが、この500はFileMakerが規定したエラー番号である。

[続開発プロセス#10] UIの大枠から機能を検討する

少し間が空きましたが、開発プロセスの中で、まずはUIのモックアップを中心に要求を固めて、そこから設計に入る場合に、まず、データベースのスキーマから入る方法があるというのを説明しました。レイヤー構造で構築する場合、データは低い位置にあるので先に決めるという点に意義はないとは思いますが、一方で、あらゆる状況を加味したデータベース設計ができるのかという問題もあります。ですが、ここでは先に決めるという流れでプロセスを追っています。

データベース設計ができれば、そこに対してどんな仕組みをかぶせることで動くアプリケーションができるのかということを考えます。UIの設計から、まずは目に見える機能を取り出し、それをどのように構成するのが良いのかを考えます。ここで、「機能の一覧」を書き出すことが1つの方針としてはあり得るのですが、その機能をある程度分類しないと、構成が定まりません。そこで、メモのページ全体をMemoPoageとして、それらが、メモ一覧を示すMemoListと、左側のカテゴリ一覧を示すPickingUpの2つのクラスのコンポジションであるという見方をします。まず、目に見える範囲を狭めて、開発単位となるブロックを見つけるということです。ここで、一覧だと、1行のコンポーネントが複数あるようなことを示さないといけないのかと言えば、これは経験則的には不要だと考えます。ここで「リスト」と言ってしまうことで自明だからです。言い換えれば、1行の要素が繰り返されるということ自体は、そのクラスが持っているという見方をして、過剰に細かくは書かない方が設計は素直で読みやすくなるということです。データベースのテーブルを記述する場合に、クラス図では1つのボックスしか書かないのと同じ理由です。しかしながら、何らかの定義はどこかにあるわけですので、その点も書きたい場合はメモを追加するか、あるいはクラス名の意味をどこかに記載すればいいでしょう。なお、このようなクラス図からオブジェクトを図を想像できるかどうかということは、ダイアグラムの理解には重要なポイントであることは間違いないのですが、設計上どうすればいいかを詳細に決めると多分面倒なだけになりますし、大雑把にするとチーム内でコミュニケーションが中途半端になる可能性があります。機会があればこれは検討したいテーマです。こうして作成したのが以下のクラス図です。

緑色の3つのボックスがUIのブロックを1つのクラスとして記述したものです。中身は、ボタンや編集など、ほぼ、ページ上でのイベントに対応するもの、そしてそのリスト自体を生成するためのものが記載されているだけなので、細かくは説明しません。それぞれ、どのテーブルを利用するかで2つのテーブルに線を引きました。また、MemoListは、ページネーションと日付時刻のピッカーを、別に用意されているUIのコンポーネントを使うことにします。ここでは、MemoList上にある要素とは別のもの(ここでのページネーション)や、要素の動作を補助する必要があるものを(ここでの日付時刻ピッカー)抽出します。ただ、このUI Componentsは、実装先によって実態は異なると思われます。ここではまだ実装を加味しないということで進めてきましたが、実際にはこのように実装先の状況が徐々に現れることになります。プロセス的にはまず設計をして、実装に関わることを検討しようということを書いていますが、線引きは明確にはできないと思います。ここで重要なことは要素として抽出しながらも、一定の範囲で実装を意識したという点をメモにするか、きちんと意識しておくことです。

ここまでの設計の図を見る限りは、明白にレイヤー構造です。このような簡単なアプリケーションなら、もう実装は簡単にできると言っても良いでしょう。手慣れた方ならここまで図にしなくても、頭の中で設計ができてしまっており、自身の知識を持ってすればすぐに実装の作業ができるはずです。こういう状態を「スキルがある」ということになるかと思います。そのような状態の効率良さは当然ながらあるわけで、その結果「設計は不要」という考えにもつながるでしょう。設計不要論については今回は扱わないつもりですが、設計の行為を体系的に記述するため、ここで終わらずにさらに設計の検討を進めるのが一連の記事の目的です。よって、まだ続きます。次は、実装環境の制約を加味した設計を作っていきます。