なんと、カスタムWebは動かないので、INTER-Mediatorでは利用できません。Directoryのアカウントでのログイン機能もありません。ESSはサポートはしますが、ドライバが非対応ということはちょっと簡単ではなさそう。その他諸々いろんなチェックポイントがあります。Canada.」と書かれている。ことではいさようならとは行きません。AWSでどうやって日本からのアクセスを切るのかいなと思いつつ、AWSにログインして、リージョンを「バージニア北部」にします。Marcketplaceを選択してFileMakerで検索すれば、あらあらちゃんと出て来ますね。規模の小さいのを選ぶと、ちゃんと値段もわかります。この「時間課金」というのはAWSでの一般的な課金方法です。FileMaker社からライセンスを買わなくても、時間課金ができるとは言え、よく見てください。最低の構成でも1時間が1ドル強、上がっても1.229ドル/時間。要するにアマゾンの費用に比べてFileMakerのライセンス料が異様に高いのです。月間30×24=720時間として、732ドル、ということで、月間7〜8万ほどかかります。こちらを選ぶ人は少ないでしょう。FileMakerからライセンスを買って使ってください。その場合、AMIの選択肢が違います。ライセンスを自分で持っている(BYOL)人向けのAMIがあったりします。ここで、「お金を払っても試して見るか」と腹をくくったのですが、よく見ると、15日はフリーライセンスということで、Amazon側のEC2使用料のみで、15日は使えます。いうわけで、なぜ日本では「入手できない」となっているのか?AWSは全世界に共通のサービスをしているのだから、昔の代理店ビジネスのようなことは最初からできるわけがないことは明白なのにどういうことでしょうね。いうことで、操作等より詳細を知りたい方は、インストール後に出て来たヘルプのページをご覧いただくと早いでしょう。8にプロジェクトを変えたところで、あるプロジェクトで、PlistBuddyでバージョン番号をアップしていたのがあるのですが、スクリプトが引き継がれなくなったので、今風のやり方はないかと思って検索したら、agvtoolがあるなということで、使い方を考えてみました。Toolの略だそうです。調べたり、結構詳しいmanを見て考えました。素直な使い方はどんなのだろうか?Xcodeのプロジェクト1つだけの場合と、別のプロジェクトを組み込んだ場合で考えて見ました。使い方の前に、ここでいうVersioningとは、XcodeのプロジェクトのGeneralの設定にある「バージョン」と「ビルド」です。英語版しか今はないので画面通りに記述すると、IndentityのカテゴリにあるVersionとBuildです。このうち、Finderで表示されるいわゆるバージョンはここのVersionですが、Buildは一般には参照できません。Finderのバージョン表記に出てくる場合もありますが、それはさらにこれらとは別のバージョン表記です。バージョンに関する情報はアプリケーションバンドルのInfo.plistに記述されますが、次のような関係にあります。非表示Xcodeでの設定VersionInfo.plistに設定するBuildInfo.plistのキーCFBundleShortVersionStringCFBundleGetInfoStringCFBundleVersionFinderの情報ウインドウに見えるバージョンには、Info.plistに長いバージョンつまり、CFBundleGetInfoStringがあればそれを表示しなければ短いバージョンつまり、CFBundleShortVersionStringを表示します。Finderウインドウをカラム表示にした時に右端に表示されるアイコン下の属性は、常に短いバージョンつまりCFBundleShortVersionStringが表示されます。Storeアプリで、短いバージョンすなわちCFBundleShortVersionStringが見えていますが、iTunesでは見えていません。表の最初の3行は一般ユーザーの目に触れるところで、最後の2行はXcodeやInfo.plistの世界です。ここではCFBundleShortVersionStringがバージョンで、CFBundleVersionがビルドであるということを認識してください。どっちもキーのキーワードにVersionとあり、一見するとCFBundleVersionがバージョン番号のように思えてしまうところが引っかかるところかと思います。以下、「バージョン」と「ビルド」としてそれぞれの設定を参照します。Settingsには多数の設定項目があります。そこのVersioningのカテゴリを見てください。Generic」を選択します。Versionに何か数字を入れてください。この数字はビルド番号の初期値となります。キー名に「Version」とありますが、このキーはビルドの値をおぼえておくために使われています。その他のキーを見るとPrefixやSuffixなどがあり、ビルド番号を構築する時にこれらの文字列を前後につけることができるようになっています。他のプロジェクトを読み込んでいないプロジェクトまず、単純なプロジェクト、つまり、他のプロジェクトを読み込んでいないようなプロジェクトを考えます。この場合、ターゲットは通常は1つであるので、アプリケーションのバージョンはそのターゲットを1箇所変えるだけです。そのために、わざわざコマンドを動かすよりかは、Xcodeの画面上で手作業で変えた方がいいでしょう。いうことで、バージョンについては自動化の必要はないと考えました。ビルドの方は、本当にビルドをした時、あるいはProductメニューからArchiveを選んでアーカイブを作った時など、ある程度自動的に設定をしたいと考えるでしょう。Schemeを選択します。左側のBuildやArchiveの設定に、以下のようなスクリプトを追加します。Schemeを選択してシートが出てきます。BuildあるいはArchiveのPre-actionsないしはPost-actionsを選択します。最初は何もないと思われます。Actionを選択すると、以下のような画面になります。fromのところで、アプリケーションのターゲットを選択しておきます。-allこれでCloseをクリックします。上記の場合だと、command+Bでビルドすると、ビルドの番号がアップするはずです。Versionの値を取り出してアップして、「ビルド」の枠に設定します。現在、ビルドの枠に見えている数字がアップするのではありません。ちなみに、このagvtoolは、プロジェクトのルートをカレントにして動くようになっており、引数でプロジェクトのディレクトリを設定するようになっていません。そこで、ビルド時に作成される環境変数のPROJECT_DIRを利用してカレントディレクトリを移動し、コマンドを入力しています。agvtoolの引数はプロジェクトや値に関わらず、常にこの通りです。プロジェクトを読み込んでいるプロジェクトプロジェクトを分けていて、あるプロジェクトで統合している場合、まず、ビルド番号は前に示したような方法で、各プロジェクトに設定するしかないと思われます。ビルドの数はプロジェクトごとに違うでしょうから、それはそれでいいかと思います。バージョンの方は、以下のように一気にまとめて設定ができるようになっています。new-marketing-version」に続いてバージョン番号を指定します。このマーケティングバージョンというのが、「バージョン」になるということです。5.1ここで、読み込んでいるプロジェクトのInfo.plistも設定されることをメッセージで確認しましょう。いくつか試してみた限りでは、読み込んだプロジェクト側にバージョン番号が反映される場合と反映されない場合がありました。以前から読み込みをしてあったプロジェクトは全てに反映されるのに、新たに作ったプロジェクトはだめでした。-allの呼び出しをPre-actionsに設定すると、読み込み側のプロジェクトのビルドがキャンセルされることも見られたので、その場合はPost-actions側に設定することでビルドは全部流れるようになりました。この辺りは、理由が分かれば追記しようと思います。何れにしても、agvtoolのパラーメータは多数ありますが、ここで紹介したように、next-versionのものをプロジェクトにスクリプトとして仕組むことと、バージョンの設定のためにnew-marcketing-versionを使うことで概ねのことは賄えると思います。3を利用するように変換した時の自動変換結果については、こちらに記述しました。10にして、一部、赤いエラーが出たところなどを直すことになります。それらについてまとめておきます。署名ができない!実は、この問題に最後まで苦しみました。署名に関するプロジェクトの設定をあれこれいじってもエラーが出て完了しませんでした。エラーのログをよく見ると、こんなメッセージが見えました。1しかし、リソースフォークをいじった記憶もありません。overflowのサイトに答えがありました。画像なんかにはアプリケーションが勝手にリソースをつけていたりすることがあるので、それを消せばいいということでした。リソース等は署名対象外にしないといけないというのは、最近ルールとして増えたのかもしれません。-rc」、これでエラーがなくなりました。このコマンドは、リソースフォークやFinder情報などのファイルの付加情報を消します。-cで消す、-rでサブディレクトリをすべてさらいます。ファイルそのものは消しません。拡張情報の処理コマンドです。変換されない箇所が残るパターンNSURLをURLは自動的に変換してくれると思ったのですが、以下のようなパターンの場合は、自動変換してくれず、手動で書き換えました。NSを消すだけですが、AnyObjectはAnyにするなどを知っておかないと作業は面倒になります。完了時のクロージャーはもしかすると、キーワードなしで、閉じかっこの次に記述しておけば変換してくれたのかもしれませんが、これは想像です。以下のようなプログラムがあるとします。いずれも、返り値のあるメソッド呼び出しであり、インスタンス生成です。unused」などというメッセージで警告となります。返り値が使われていないというのです。以下のサンプルはさておき、返り値の不要な場合は時々あります。いちいち変数を定義すると、今度はその変数が使われていないと言った警告が出ます。(ちなみに、おなじみの定数「NSUTF8StringEncoding」は、「String.Encoding.utf8」のように、よりスッキリした記述に変わっています。続いてステートメントを記述します。空代入のようなことをするということです。これも、返り値があるのに忘れているようなミスを防ぐためということになっていますが、ちょっとやりすぎな気もしますね。8でのコンバートをする時に、定義定数がない状態でのコードが変更されます。したがって、#if等で変数が定義されているかどうかを確認するような場合、ELSE側だけが変換されました。変換されない方は手作業で変更するしかありません。9まではAppDelegateクラスのapplication(_:didFinishLaunchingWithOptions:)メソッドに、例えば以下のようなプログラムを書いていました。変数applicationはメソッドの第1引数です。nil)application.registerUserNotificationSettings(settings)記述方法が以下のように大きく変わります。NotificationフレームワークのUNが頭文字)クラスのインスタンスをcurrentメソッドで得て、requestAuthorizationメソッドで機能の利用を要求します。引数は定数(.badgeがホーム画面のアプリケーションのアイコンにつけるバッヂの許可で、他に.soundなどの定数がある)の配列を指定します。処理完了時に実行されるクロージャーが続きます。許可の可否に応じて処理をすることができますが、何も書かなくても動作はします。in}ちなみにrequestAuthorizationは2つの引数を持つので、次のような記述が可能です。こちらは定義通りです。Closure)ので、上記の書き方となります。in})なお、処理完了時のクロージャーに何も処理がない場合の一番短い書き方は、これではないかと思われます。in}openURLがdeprecatedになったUPApplicationクラスのopenURLメソッドがdeprecatedになり、openを使うようにと警告が出てきます。最初の引数にURLを指定するのは同じですが、optionsと完了時のクロージャーも記述します。それまで、openURLを使っていたのなら、おそらく当初は増えた引数は何も指定しないでOKでしょう。options:の後にnilを指定したらエラーになります。中身が空のDictionaryを指定するのが手軽だと思います。最後のクロージャーは閉じかっこの後に記述します。何も処理がない場合でも、引数並びは評価されるためnilは指定できません。いう記述でもいいでしょう。in}NSRangeとRangeの変換は相変わらずできないこれ不便ですよね。文字列処理だけしていればRangeだけしか出ないのかもしれませんが、UITextFieldDelegateのメソッドなんかは文字列の変更箇所がNSRangeでやってくるので、Stringに対しての処理をしたい場合は、それをRangeに変更したいわけです。NSStringで処理ということもありますが、せっかくSwiftなのだからStringで処理をしたいわけです。9の時には、自分で変換メソッドを作っていました。3にはないらしく、index関数を利用して改めて作り直しました。extensiondでStringクラスにメソッドを追加して変換しています。以前のメソッドよりもだいぶんシンプルに短く書いていますが、それは自分自身のSwiftの知識が増えたからかもしれません。いった明示的なキャストをする必要があります。8.0が正式に出ました。あるアプリケーションのプロジェクトをコンバートした時に自動的に書き換えられた結果をもとにどのような変更があったのかを記録しておきます。3でdeprecatedになるという警告の箇所は、警告が出ないように変更した結果です。それ以前のバージョンのSwiftで作られたソースでは、もっと様々な変更の必要があると思います。9.3のままの状態でコンパイルが通るようにしてみました。クラスそのものが変更されたもの以下のクラスについて、名前が変更されています。9.3)の場合の記述で、矢印の右側の記述に自動的に変換されたことを示しています。NSの付いたクラス名が付いていないものに変わってきています。おなじみのNSURLやNSErrorが、配列や文字列ど同様NSのないクラス名に変更されています。クラスの機能については大きくは変わっていないようです。NSURLSession及びその名前で始まるNSURLSessionTaskも含めて、頭の「NS」はなくなっていますが、今日現在、ドキュメンテーション中に「NSURLSession」が残っていたりします。最後のURLSession.AuthChallengeDispositionは列挙型です。NSUserDefaults→UserDefaultsNSError→ErrorNSURL→URLNSBundle→BundleNSURLSession→URLSessionNSURLCredential→URLCredentialNSURLAuthenticationChallenge→URLAuthenticationChallengeNSURLSessionAuthChallengeDisposition→URLSession.AuthChallengeDispositionAnyObject→Anyインスタンスを得るメソッドがシンプルなプロパティに「UIApplication.sharedApplication()」などは頻繁に記述していたのですが、Applicationという単語の重なりがなんか重い感じがしていましたが、「UIApplication.shared」のように、長いスタティックメソッドが短いプロパティに変更されました。コードがかなりスッキリします。Dispatch関連のAPIをクラスにラップしたものです。4から関数としてサポートしているものもあり、要するにやっとクラスとして使えるようにAPIを整えたという状況のようです。最後のUIColorクラスは、いくつかの色のオブジェクトを得るスタティックメソッドが用意されていましたが、これもColorの重複があったものの、redやgreen、blackといったプロパティで得られるようになりました。従来の3種類から、open、public、internal、fileprivate、privateの5段階に変更されました。3より導入されたものです。従来のprivateは、全部fileprivateに変更されてしまいます。省略時にinternalになるのは変更ありません。2.xではprivateによるアクセス制限はクラス単位ではなくファイル単位でした。したがって、1ファイルに2つのクラスを定義した場合、privateなプロパティでも別のクラスからアクセスができました。3ではファイル単位でのfileprivateと、クラス単位のprivateに分離しました。従来のprivateが現在のfileprivateになったということで、こうした変換を行なったのでしょう。publicとopenについては、元のpublicは現在はopenに対応します。3ではpublicはサブクラス化やoverrideできないという制約が付きます。3ではカンマで区切ったそれぞれの代入文にletが必要になりました。yのletは今までは不要だったのですが、これが入るようになります。print(a,b)}UIKitのAPIの変更メソッド名やプロパティ名などがあちらこちらで変わります。読みやすくはなります。UIViewControllerのshowViewController(_:sender:)、dismissViewControllerAnimated(_:completion:)、presentViewController(_:animated:completion:)の各メソッドが、show(_:sender:)、dismiss(animated:completion:)present(_:animated:completion:)へと極めて短くなりました。最初の引数にはキーワードをつけないということで統一されていて、最初のキーワードは関数名に組み込まれていましたが、状況によっては引数のキーワードとして使うようになりました。dismissのように通常のメソッドでも、最初の引数にキーワードが付くことがあります。UINavigationControllerクラスではpopViewControllerAnimated()がpopViewController(animated:)にはなるなど変化はあるものの、大きな変化のないクラスもあります。UIViewクラスのhidden、userInteractionEnabledプロパティはisHidden、isUserInteractionEnableとなりました。Boolean型のプロパティのインタフェースを「is+属性名」としたということで、この部分はJavaなどのルールに即したということでしょう。プロパティ名にあった「URL」はほぼ「url」で置き換えられており、URLで始まるプロパティもurlで始まるようになっています。定数についても、以前は.Badgeのように頭文字は大文字でしたが、.bridgeのようにドットの次は小文字になりました。Objective-Cで作ったクラスを入れていたのですが、そのクラスの定数も同様に頭文字が小文字になったので、この処理はブリッジ部分での変更であることが確かです。結果的に、クラス以外の頭文字は小文字というルールが浸透した感じです。メソッドだったものもプロパティとして扱えるものは、プロパティになりました。UIViewControllerクラスでは、supportedInterfaceOrientationsメソッドがあり、それをオーバーライドして返り値をプログラムで記述することで、自分で作っているビューコントローラでの挙動を変更できました。これが、supportedInterfaceOrientationsプロパティに変わります。値を返すように記述することで、プログラムがゲッターとして機能します。ように引数指定なしのクロージャのように記述するだけで変わりません。記述が必要になりました。3@escapingが追加されるクロージャーの引数定義WKWebViewのデリゲートメソッドの部分では、引数のクロージャーを持つものがありますが、メソッド定義の記述に@escapingが加わりました。9)ではこの@escapingはない状態で定義されていました。このアノテーションを追加することで、引数に設定されたクロージャーがメソッド実行後に消えてなくなってしないように保持をします。このクロージャー自体をlazyで指定したプロパティで使う場合や、あるいは配列にlazyプロパティを指定してさらにmapメソッドを適用することで、mapメソッドのクロージャーの適用を配列の要素を取得する時点で行うことができるのですが、そのmapメソッドの引数にクロージャーを指定するような場合に、@escapingで保持を指定するということになっています。8とはあまり関係ありませんが、配列に対するlazyプロパティについてはブログ等でほとんど見られないので、ちょっと試して見ました。サンプルプログラムを見てください。配列mに対して、mapメソッドを直接ではなく、lazy.map()で適用します。(Function))」と出てくるように、特殊なコレクションです。このnをsubscriptによりアクセスすると、そのアクセスした時にmapメソッドを実行して結果を返します。202という値が得られます。メソッドの適用をlazyにするという仕組みと言えるでしょう。2.3の段階で警告も含めてクリアしているので、++演算やそれを使ったfotなどの警告となっていた記述は一切ない状態だったので、それほど時間がかからずに変更はできました。して違いが出たところは概ね自動的に変更してくれるので、それはそれでいいのですが、仔細に見ることで色々と新しい機能も理解できるようになります。バインディングとイベント処理の記述ここまでのところで、ロバストネス図を出発点として、Webアプリケーション向けに設計図を作成するための表記方法を検討してきた。バウンダリーを詳細化して、必要な要素に分解してダイアグラムに記述することや、処理をコントローラーという大きな単位でなく、処理ステップという小さな単位で術することで、具体的な設計情報をダイアグラムに入れることができることを示した。続いて、クライアントサイトでのバウンダリーとエンティティの関係をバインディングという視点で見た時にどのように記述するかを検討し、そこから、イベントのハンドリングを記載する方法を検討する。Web、すなわちHTMLでのユーザーインタフェースコンポーネント、つまり、ユーザーからの応答を受け付けるコンポーネントは、さほど種類は多くはない。ここではまず、テキストフィールド(INPUTタグでtype属性がtext)と、ボタン(BUTTONタグ)の2種類のコンポーネントを考える。ボタンを押すと、何か文字列がテキストフィールドに入るといったごく単純なプログラムを作りたいとしたら、ロバストネス図的には次のようになるだろう。今回は処理のステップまでは考えないので、コントロールは丸い矢印線のアイコンで記述することにする。ここで、バインディングの実装が入るとどうなるかを検討する。バインディングを一般的に記述すると、変数とコンポーネントの値が連動することと言える。ここでのコンポーネントは、テキストフィールドやあるいはHTMLの場合はノード(タグ要素)そのものも示す。コンポーネントの値を得るには変数を参照することで可能となり、コンポーネントの値を変更するには変数に代入するということで実現する。変数がコンポーネントに成り代って存在することであり、変数とコンポーネントの状態の管理は、全てが自動的に、つまりはフレームワーク側で行うことが期待されてる仕組みである。タグによって動作が違う点の吸収など、実装上は様々なことを検討する必要があるが、ここではバウンダリーの値と変数の値が連動する点に集中することにする。前のロバストネス図を、テキストフィールドに対する変数があるとすれば、変数に代入すれば、その値がテキストフィールドに反映するという流れを次のように記述できる。これでは一方向だけの処理である。現実には、変数とテキストフィールドの双方向のやりとりが発生していて連動しているのだが、ここで、ステレオタイプを利用した表記を導入する。点線矢印にbindingというステレオタイプを記述することにした。本来は鏃を両側に記述したいのであるが、クラス図の点線矢印は依存関係を示すものなので、双方向という記述はできなくなっている。ここでの点線は依存ではないのだが、処理の流れに実線を利用しているので、ここでは依存の矢印で代用し、ステレオタイプをつけることにする。bindingは双方向であることが前提なので、鏃が片方でも誤解をすることはあまりないと考える。テキストフィールドが2つあって、一方で値を変更すると、もう一方に自動的にその値が反映される状態を記述すると、一例はこのようになる。テキストフィールドごとに変数を確保したとしたら、テキストフィールド2向け変数が更新された時、Observer実装が機能して、あるコントロールの処理が機能し、その結果、別のテキストフィールドの変数に値が代入されるということを意味している。処理2への矢印にobservedというステレオタイプをつけたが、observerは処理2、observableなものはテキストフィールド2向け変数である。この記述は仮のものである。ここで、observer実装により変数の変更によって処理が実行される状態を次のように記述する。監視している処理2から、監視対象のテキストフィールド2向け変数に対して、点線矢印を引き、ステレオタイプとしてobservingと記述する。背後で様々なメカニズムを持つとしても、設計時に概念として知っておくべきことは、何が何を監視しているかということだ。処理2では、テキストフィールド2の変更がbinding-observingとたどることで、処理2が開始される。処理2はテキストフィールド2向けの変数の値を得て、テキストフィールド3向け変数にその値を代入し、テキストフィールド3の値が更新される。続いてイベント処理も同様に記述できることを示す。イベントは、HTMLのコンポーネントにおいては既定値で発生させることができるようになっている。フレームワークによってはモデルのコンポーネントで独自のイベントを発生するようものもあるが、ここではHTMLの標準の仕組みを考える。以下の図で、ボタン2に対して処理3から、やはり点線矢印が引かれており、event-clickというステレオタイプが記述されている。eventは固定のキーワードで、ダッシュの後に、イベント名(ここでは「click」)を記載し、つまりはボタン2でクリックイベントが発生すると、処理3が実施されることを明確に記述することができる。この図では、ボタン2のクリックにより、テキストフィールド3向け変数に値が代入されるので、テキストフィールド3の値が更新される。イベントやobserverの実装の記述を利用すれば、バインディングの処理そのものを記述することができる。システム設計上は、bindingというステレオタイプで線を引くだけでいいが、実装をするとなると、次の図のようになる。テキストフィールドからのいくつかのイベントを拾い、その結果を対応する変数に反映させる作業が必要になる。変数の変更があれば、observingしているコントロールに処理が移り、変数の値をテキストフィールドに反映させる作業が必要になる。この図を見ると、明らかにループしそうだ。テキストフィールドの変更結果が変数を更新し、その結果observerによりテキストフィールドを更新する。HTMLの場合、そこでイベントは発生しないので、無限ループにはならないが、処理に無駄が出る。これを回避する方法としては、変数の更新処理において、obeserverを動作させるものとさせないものを用意して、適切なメソッド呼び出し(あるいは引数設定)をするといった方法がある。何れにしても、バインディングについては、通常は図の上の表現でも良いが、これまでに検討してきた結果をもとに、その部分を詳細に記述することも可能である。クライアントサイドでの設計で必ず考慮すべきイベントの表記も含めて、JavaScriptレベルの実装に近づけるより詳細なダイアグラムの記述ができるようになってきたと言えるだろう。前回までで、バウンダリーを詳細化するところまでを記述したが、またまた時間が空いてしまった。サーバーが起動しなかったり、開発の作業に集中したりなどしていた。続いて、コントロールの中を詳細化する。実際に詳細化できるのかを検討する前に、なぜ詳細化しなければならないのかを改めて検討しておく。多くのフレームワークは、コントローラーという1つのクラスを作ることからチュートリアルが始まる結果、1つのクラスで作るものだと思い込んでいたり、あるいはクラスを複数用意するとしても、連携する手法は特にフレームワークで用意されていないなど、「巨大な1つのコントローラー」を用意する素地が、意図しなかったとしてもフレームワークがお膳立てしているという状況であるとも言えるだろう。最近、ある仕事で、ethnamというグリーが当初開発したethnaの後継というPHPのフレームワークを使う機会があった。このフレームワークは改めて、フレームワークの機能との対比を考えるときの題材の1つにする。このフレームワークの特徴は、コントローラーというクラスを作るのではなく、中心的なコントローラーに対応する決められた名前のメソッドがあるという点である。決められていることは、prepare、perform、preforwardという3つのメソッドが順番に呼び出されるということだ。prepareは結果次第でのちの作業をキャンセルできることから、バウンダリに近いところにあってデータの検証などを行う入力用ビューコントローラーと言える。最後のpreforwardは、出力の直前に呼び出されることから、出力用のビューコントローラーと言える。中間のperfomは、まさに、コントローラーとしての役割を持ち、ここでモデルへ働きかけるなどのビジネスロジックとのやりとりを記述することになる。これらのメソッドが保持されるクラスは決められた場所に作成するようになっているため、コントローラーの粒度はクラスよりもメソッドの方が適切だと言えるフレームワークである。コントローラーというクラスを作る話と、コントローラー相当のメソッドがあるという話は、設計の上では極めて大きな違いがある。抽象的な記述から、フレームワークにあった実装を行うという方針でもいいのだが、この方針だと属人的な実装テクニックや、あるいは「言わずもがな」なルールを読み解かないといけない場面が多そうだ。結果的に、大きな単位で何をすべきかは考えるのがモデルの1つの目的ではあるもの、コードの段階ではもっとも粒度の低い1つのステートメントを記述しなければならない。コントロールの中の粒度をより細かくして一度考えてみる必要があると思われる。フレームワークの機能との対比をする上では、やはり一度は細かな処理に分ける必要があると考える。次の図は、クラス図を元に、一覧と検索を持つようなWebページのモデルを記述したものである。astah*でクラス図を用意して、バウンダリーは大まかながら、主要なコンポーネントを抜き出して1画面を枠で囲う形式で記述した。モデルは、この段階では概略として記述し、コントロールの中の処理の1ステップずつをクラスで記述した。この図を描きながら考えたことは、まず、処理には順序があるということである。入力されるバウンダリーから、出力されるバウンダリーに向かっていけば判別つかなくもないが、図を明確にするには、処理の順序を矢印で示し、どちらが先なのかを記載する必要があるということだ。続いて、どうしても「分岐」は必要になる。前の図は、クラス図で適当に書いたものである。この点から、前の図にはないが、繰り返しや並行処理的なものを記述が必要になることは十分に可能性があるがある。ここまでに至るまでにすでにお気付きのように、コントロールの処理を詳細化したものは「フローチャート」なのである。UMLでフローチャートに近いものといえば、アクティビティ図である。前述のモデルをastah*のアクティビティ図で記述してみた。ほとんど同様な図が描かれているが、バウンダリーやエンティティのアイコンに接続された矢印が今ひとつうまく処理できていない。astah*でこの状態にするには、オブジェクトのオブジェクト名を空、ベースクラスをバウンダリーで使ったクラス名を選択することででき、その後に右クリックして、標準アイコンを選択するもこのようになってしまった。フローチャート部分は作りやすいが、astah*での作業は明らかにクラス図の方がみやすい図を作れる。この先、図をどうやって作成するかは問題だが、とりあえず、クラス図に戻り、バウンダリーの詳細化を行った。画面要素のキーあるいはフィールドの記述をコンポジションでバウンダリーに追加したが、「JavaScriptアラート」のような手法の指定もあるかもしれない。いう場合の記述はないと思われるので、点線矢印で適用先を記述した。このモデルから実装の方針をもう少し進めよう。バウンダリーの集合が3つあるが中央にある「エラー表示」はシンプルにJavaScriptのアラートを使うとしたら、「エラー表示画面作成」は、単にJavaScriptでwindows.alert(“...”);を実行することである。ページの中にJavaScriptでの記述が行えることになる。処理を行う必要はない。その画面を崩さずにアラート表示したのであれば、単にアラートの表示だけでもOKである。あとは、検索条件の検証ルールが与えられれば、実装はできそうである。残りのアクティビティを分類して見る。分類の基準は、順次実行するアクティビティであるという点になる。まとまって実行されるアクティビティのセットは少なくともある段階では同一のメソッドの連続したステートメントに記述されていることになるので、その点から分類をする。別の分類となり、図中ではそれぞれ分類2と分類4で囲った。分類4の中にある2つのアクティビティは、データ検索とビューの生成といった違うことを行なっている。あるのなら、さらに分類すべきであるとも考え、図中の分類3で囲った部分が抽出される。結果的に全部バラバラということにもなるが、分類4のみ2つのアクティビティからなるとも言える。ここで、まず、分類3の「条件を与えて顧客情報検索」であるが、データを扱っているので明らかにモデルに関わる機能である。いくつかある「画面生成」は明らかにビューに関わる機能である。図の右側に対応するコントロールを記述したが、それぞれ対応するオブジェクトを記述できることから、この図はロバストネス図をさらに詳細したものであるという点は明白である。実際に実装するとなると、分類3「条件を与えて顧客情報検索」はデータ処理が含まれており明らかにサーバーサイドの処理となる。2つの「画面生成」は、例えばPHPのフレームワークのCodeIgniterであれば、サーバーサイドで記述をする。これくらいの機能ものだと1つのコントローラークラスにまとめてしまってもさほどのコード量ではないと考えるかもしれない。ここで重要な点がある。それは分類1はクライアント、分類2〜4はサーバーサイドでの実装を行う点が、ある状況では決定づけられてしまうということだ。一般にはサーバーサイドのフレームワークの場合「画面生成」という処理から先は自動的に行われる。画面生成に必要な状況をコントローラーで作り出すのが開発作業である。そこで注目したいのは、考慮すべきクライアントとサーバーの切れ目である。エラーなしとなった場合、「条件を与えて顧客情報検索」に移行する場面がある。ここは矢印が1つだが、実際には、サーバー側にはPOSTメソッドの受け入れから、該当する処理が記述されたメソッドを呼び出すまでの処理(例えば「ルーティング」など)が入ることになる。これらは自動的にできないメソッドも多い。これらの検討結果を加えたモデルは次のとおりである。検索条件の入力はフォーム(HTMLのformタグ)で記述することにして、フォーム自体をサブシステムとして記述する。入力結果を検証した結果、サーバーへPOSTするのは、ブラウザが本来持っている機能である。POSTを受け入れるのフレームワークあるいはCGIとして持っている仕組みを利用できるので、これらは実装対象ではない。受け入れがなされて意図したメソッドが呼び出されるようにするための処置は必要であり、それはフレームワークごとに違っている。このように小規模なWebアプリケーションでもクライアントとサーバーの分離やフレームワークのサポートの有無を考慮しながら、実装ポイントを探るということが必要になる。従来のオブジェクト指向を基調としたモデルでは粒度が粗く、実装の具体的な手法までをモデルまで記述することはしなかった。言い換えれば、実装した結果の要約を逆解析するようなものであったとも言える。現実の開発でここまであるいはさらに細かい詳細化がモデルの段階で必要かどうかという議論はあるだろうが、その点は別にしてもWeb開発の学習やフレームワークの理解にはこうした手法が有効であると考える。