Processingで学ぶ 実践的プログラミング専門課程

第23回デザインパターン(1) Facade

導入

コードの作成途中で手に負えなくなって、コードを放り出してしまった経験がないでしょうか。恥ずかしながら私は、何度もそんな壁にぶち当たりました。コードの分量が増えると急に複雑度が増したように感じました。この複雑さを上手に取り扱うことは、古くからプログラマにとって共通の悩みだったようです。複雑なコードをいかに簡単に取り扱うかについて、様々な工夫・技法が提案されました。⁠構造化プログラミング」「オブジェクト指向プログラミング」がその代表格です。

今回から学習する「デザインパターン」はそのまた一歩先の工夫・技法です。デザインパターンを知り、使えるようになると、プログラマの視野が一気に開けます。今回から4回の予定で、最も簡単で学習しやすく、また役に立つデザインパターンを4つ選んで紹介します。

展開

デザインパターンとは

デザインパターンの目的

コードの規模が大きくなると、コードを書くことが困難になります。そこで問題を分割して取り扱いやすくするという分割統治法の考え方に至ります。

コードの分割は多くの場合、コードの働きを単位にします。分割されたコードにはその働きに応じた名称を与えます。この名称と働き、そしてそれらの組み合わせ方を共通理解したチーム内ではコードの分担作成が可能になり、協業が容易になります。一人で、あるいは少人数でコーディングしている場合でも同様です。さらには、コードが働きの単位に分割されているため、別のコードへの再利用もしやすくなるのです。

GoF(後述)は数多くのコードを書く中で、似たような仕組み・構造のコードに何度も取り組むことに気づいていました。それらの共通するコードのパターン23種類をまとめ、名前をつけてカタログ化し、自分たち以外のプログラマ同士でも広く共有しやすくまとめました。これがGoFによる「デザインパターン」です。

[デザインパターンの目的]
プログラマ同士で、コードの共有や再利用をしやすくすること。

GoFとは、経験豊富なプログラマであるErich Gamma, Richard Helm, Ralph Johnson, John Vlissidesの4人を指します。the Gang of Fourの頭文字をとってGoF(ゴフ)です。GoFによって書かれたデザインパターンのバイブルが『オブジェクト指向における再利用のためのデザインパターン』です。GoF本(ゴフぼん)と呼ばれます。この書籍はサンプルコードがC++で記述されています。Processingを学習する本連載の読者の皆さんが、デザインパターンを詳しく学習したいならば、結城浩氏による書籍『増補改訂版Java言語で学ぶデザインパターン入門』をお勧めします。

Java言語が浸透し始めた2002年頃、Robocodeというプログラミング・ゲームが盛んになりました。IBMがスポンサーとなり、世界大会が開催されました。このRobocodeのコンテストに参加する中で、たくさんの参加ロボットのコードを読むことができました。それらのロボットの中でも特に優れたものは、ほぼ例外なくデザインパターンを活用していました。デザインパターンが使われていることによって、彼らのコードは大変理解しやすいものでした。その一部を部品として容易に自分のロボットに再利用できたのです。

デザインパターンは図で読む

デザインパターンは、たくさんのコードを読み書きした先輩方の知恵の集積です。コードの構造の類似性をまとめて名前をつけたもので、その名前は特徴を大変よく表しています。それだけでも記憶しやすくまとめられているのですが、図を用いるとさらに理解や記憶を助けてくれます。コードの図示方法といえば、読者の皆さんはもう「ぴん」と来ていることでしょう。UMLを用いるのです。UMLの中でも、クラス図とシーケンス図がよく用いられています(UMLについては連載第18回から20回を参照してください⁠⁠。

Facade(ファサード)

GoF本に紹介されている23個のパターンの中で、最も分かりやすく実用的なパターンがこのFacadeだと私は考えています。デザインパターン学習のスタートは、このFacadeで始めましょう。

Facadeパターンの目的

Facadeパターンは、複雑になったコードを壁の向こうに隠します。壁の内部が見えずとも、用意された窓口に必要な処理を伝えれば、壁の向こうで必要な仕事をしてくれる仕組みです。Facadeとなるクラスには、複雑なコード群が行う仕事を代表する名前をつけた窓口メソッドを用意します。⁠窓口メソッド」は私独自の言葉です。GoF本やその他の解説書に表れない言葉で奇異に感じられるかもしれませんが、状況を良く表すので好んで使っています。

なお、Facade(fəsάːd)とは、フランス語由来の英単語で「⁠⁠建物の堂々とした)正面、前面」の意味があります。

[Facadeパターン]
複雑なコードを簡単に利用するための窓口となるメソッドがあり、この窓口メソッドを呼べば複雑な手順に煩わされずに目的の仕事ができる。

Facadeパターンのクラス図
画像

上図はFacadeパターンを用いたコードのクラス図の一例です。ClientクラスがClass0からClassNの数多くのクラスを上手に使って成り立っているとします。FacadeクラスがなければClientクラスはすべてのClassX(Xは0..N)クラスの働きやメソッド、そして呼出し順ルールを把握していなければなりません。

プログラマが一人で開発している場合や、そもそもClassXクラスの数が多くない場合にはFacadeクラスは必要ないかもしれません。コードの働きを把握するのが難しくないからです。しかし、ClassXのクラス数が少なくても、多くの前提知識を必要とするメソッドを複数持っていると、やはりClientクラスを書くプログラマには困難が増します。

また、開発者が複数いる場合には、これはもうFacadeクラスがあるとないでは開発効率が全く異なります。開発者が複数であるとは、Clientクラスが複数である場合です。Clientクラスが複数ある場合とは、例えば現在の多くのGUIを持つソフトウェアがそうであるように、目的のデータを操作するためにマウス、キーボード、音声等複数の手段がある場合です。Facadeに用意されたメソッドを呼べば、前提知識が多く必要な各ClassXクラスをすべて把握していなくても目的の仕事ができるのです。

例えば、⁠このクラスは図形描画システムに対するFacadeです」と言えば、デザインパターンを知るプログラマは、そのクラスが図形描画システムに数多く用意されたオブジェクト群を取り扱いやすくするための窓口をもつクラスであると理解するのです。

Facadeパターンを使う

それでは、Facadeパターンを具体的に利用してみます。

前回作成した健康管理アプリケーションのコードをリファクタリングして、Facadeパターンを適用しましょう。リファクタリングですから、機能改善はしません。コードの可読性や可搬性を高めます。⁠可搬性」とはportabilityの訳語で、ソフトウエアの世界では移植のしやすさを示します。デザインパターンを適用することでコードの部品性を際立たせますから、自然と可搬性が高まるのです。

前回のコードの多くは、メインとなるスケッチファイルHealthApp.pdeに集中していました。

連載第22回の演習解答例

Processingを使用していますから、主となるスケッチファイルにユーザインタフェイスオブジェクトを取り扱うコードと、コントローラが持つべきコードが共存できます。というより、スクラッチからコードを書き始めると自然とそのようなコードになります。ここで言う「スクラッチ」とは、ゼロからコードを書くことの意味です。

ユーザインタフェイスのコードをクラスUIにまとめる

HealthApp.pdeからユーザインタフェイスに関するコードを切り出して1つのクラスファイルUI.pdeにまとめましょう。そして、今後ユーザインタフェイスに関する操作はこのクラスUIを通して行うようにするのです。これによって、メインとなるスケッチファイルHealthApp.pdeのコードはぐっと減ります。クラスUIが、メインとなるスケッチファイルから見て、ディスプレイウインドウに表示される各種オブジェクト操作に対するFacadeになります。

//コードの概略を示すために、メソッド内部のコードは略します。
class UI{
  private PersonalData pd;
  UI(PersonalData obj){ }
  void drawManShape(){ }
  void drawWeightSign(){ }
  void drawWeightUpButton(){ }
  void drawWeightDownButton(){ } 
  void drawWeight(){ }
  void drawHeightSign(){ }
  void drawHeightUpButton(){ }
  void drawHeightDownButton(){ } 
  void drawHeight(){ }
  void drawBMI(){ }
  void drawCategory(){ }
  void mousePressed(){ } 
}
テストコードをクラスPersonalDataTestにまとめる

ついでですから、テストに関するコードも切り出してPersonalDataTest.pdeというクラスファイルにまとめましょう。すると、びっくりするぐらいにメインとなるファイルのコード量が減ります。クラスPersonalDataTestが、メインとなるスケッチファイルから見て、各種テストコードに対するFacadeになります。

//コードの概略を示すために、メソッド内部のコードは略します。
class PersonalDataTest{
  void testPersonalData(){ }
}

[作業]UI.pdePersonalDataTest.pdeを書きましょう。

以下にFacadeパターンを適用したコード例を示します。PersonalDataTestクラスを実行するためにDEBUG_MODE変数がtrueになっています。ユーザインタフェイスの動作を確認する場合はDEBUG_MODEfalseにしてから実行してください。

健康管理アプリにFacadeパターンを適用したコード例

メソッドをFacadeで隠蔽する

主となるスケッチファイルHealthApp_Facade.pdeから多くのコードを消せましたが、よく見ると、次のコード引用のようにユーザインタフェイスの各要素を配置するメソッドが残っています。

ユーザインタフェイスの各要素を配置するメソッド群
    ui.drawManShape();
    ui.drawWeightSign();
    ui.drawWeightUpButton();
    ui.drawWeightDownButton();
    ui.drawWeight();
    ui.drawHeightSign();
    ui.drawHeightUpButton();
    ui.drawHeightDownButton();
    ui.drawHeight();
    ui.drawBMI();
    ui.drawCategory();

メインになるスケッチファイル内で、これほど事細かに要素の配置メソッドが見えている必要はありません。⁠各要素を配置せよ!」と一言呪文があれば済むはずです。そこで、これらのメソッドをarrangeElementsというメソッドにまとめてしまいましょう。

ユーザインタフェイスの描く要素を配置するためのメソッド群をまとめて呼ぶメソッド
    ui.arrangeElements();

こうすることで、Facadeパターンの真価が発揮されます。整理されたHealthApp_Facade.pdeは、もともと244行ありましたがリファクタリング後は35行になりました演習問題解答例のファイルを参照してください⁠⁠。コード量は14%になっていて、どちらのコードが把握しやすいかといえば、圧倒的に後者です。これがデザインパターンを利用したリファクタリングの効果です。

今回の演習はこのarrangeElementsを書くこととします。とても簡単です。問題を考えるための演習ではなく、デザインパターンの効果を感じるための演習になります。

演習

演習1(難易度:very easy)

健康管理アプリのユーザインタフェイスの各要素を配置するメソッドarrangeElementsを書き、HealthApp_Facade.pdeのコードをさらにシンプルにしましょう。

まとめ

  • デザインパターンとは何かを学びました。
  • Facadeの使い方を学びました。

学習の確認

それぞれの項目で、Aを選択できなければ、本文や演習にもう一度取り組みましょう。

  1. デザインパターンの目的とメリットが理解できましたか?
    1. 理解できた。気持ちよく納得した。
    2. 理解できた。しかし、今ひとつスッキリしない。
    3. 理解できない。
  2. Facadeを使えるようになりましたか?
    1. 使えるようになった。自分のプログラミングにも活用できそうだ。
    2. 本文の例を理解することはできたが、自分のプログラミングに活用できる気がしない。
    3. 本文の例が理解できない。

参考文献

  • 『増補改訂版Java言語で学ぶデザインパターン入門』⁠結城浩 著、ソフトバンククリエイティブ)
    • 誰もが認める最も分かりやすいデザインパターン入門書。本来は原典(GoF本)を勧めるべきところですが、本書は別格。
  • 『オブジェクト指向における再利用のためのデザインパターン』⁠Eric Gamma 著、ソフトバンククリエイティブ
    • デザインパターンの原典。別称『GoF本』サンプルコードがC++で書かれているため、ProcessingやJava言語のユーザにはハンディがあります。しかし結城浩氏の入門書を読みこなした後ならば本書にあたる価値があります。
  • 『Java デザインパターン徹底攻略』⁠日立ソフトウェアエンジニアリング⁠株⁠インターネットビジネス部 著、技術評論社
    • 流石の日立。前掲のGoF本の解説書で、サンプルはJava言語。絶版であることが惜しまれます。強く再版を望みます。
  • 『Robocodeで学ぶ 一歩先のJavaプログラミング』⁠平田敦 著、カットシステム
    • Robocodeを使ったJava言語の学習書です。デザインパターンの活用にも言及します。

演習解答

  1. 大きな変更ではありません。UI.pdearrengeElementsメソッドを作り、その中にHealthApp.pde_Facade.pdeにあったユーザインタフェイス関係のメソッドを移動すれば終了です。ui.drawManShape()と呼んでいたところは、drawManShape()としましょう。ui.がついていても、Processingは問題なく実行してくれますが、格好がよくありません。

おすすめ記事

記事・ニュース一覧