Facadeパターン

デザインパターン【C#】:Facade 04_フォルダー構成を工夫する

前回までのレクチャーで、ファサードクラス(MachineFacadeクラス)の作成が完了しました。クライアント側のコードから確認してみると、「MachineFacade.」と入力した際のインテリセンスには、BacklightOffやFanSpin、PowerOffといった、ファサードが公開しているメソッドだけが一覧表示されるようになっています。クライアントから見ると非常にシンプルで使いやすい状態になっていることがわかります(図1)。

図1 MachineFacade.と入力した際のインテリセンス。ファサードが公開するメソッドのみが表示される

実際にこのとき画面に表示されているファサードクラスの中身を確認すると、次のように、サブシステム内の各クラス(Fan、Power など)への呼び出しをファサードの中に隠蔽し、クライアントにはシンプルなメソッド群だけを公開する、という作りになっています。

public static class MachineFacade
{
    // BacklightOff / BoxExternalTemperature / BoxInternalTemperature /
    // CameraTake なども同様の要領で定義されている(インテリセンス一覧より)
 
    public static FanEntity FanSpin(int fanId)
    {
        return new Fan().GetSpin(fanId);
    }
 
    public static void FanStart(int fanId)
    {
        new Fan().Start(fanId);
    }
 
    public static void FanStop(int fanId)
    {
        new Fan().Stop(fanId);
    }
 
    public static void PowerOn()
    {
        new Power().On();
    }
 
    public static void PowerOff()
    {
        new Power().Off();
    }
}

 

 

FanSpinやFanStart、PowerOnといったメソッドの内部では、サブシステムのFanクラスやPowerクラスを直接newして呼び出しています。クライアント側はこれらのサブシステムのクラスを意識することなく、ファサード経由でまとめて操作できるというわけです。

ファサード以外のクラスも見えてしまっている

ただし、ファサードクラスに用意されているメソッドだけがクライアントから見えているわけではありません。試しに「Machine.」まで入力してインテリセンスを見てみると、Box、Camera、Fan、FanEntity、MachineFacade、Power、UIというように、ファサード以外のクラスもクライアント側から普通に見えてしまっていることがわかります(図2)。

図2 「Machine.」まで入力した際のインテリセンス。ファサード以外のクラスもすべて表示されてしまっている

本来、クライアントが直接呼び出す必要のないクラスやメソッドは、できるだけ見えないようにしておいたほうが、クライアント側の実装はしやすくなります。使わなくてよいクラスまでパブリックに公開されていると、それだけ選択肢が増えてしまい、「結局どれを使えばいいのか」と迷う原因になってしまうためです。クラスやメソッドは、極力必要のないものは公開しないようにするのが望ましいといえます。

次回以降のレクチャーでは、こうした不要なクラスにアクセス修飾子を設定し、クライアントから見えないようにしていきます。ただし、その作業に入る前に、本レクチャーではまずフォルダー構成を整理しておきたいと思います。

現状のフォルダー構成の問題点

現時点のソリューションエクスプローラーを確認すると、Box.cs、Camera.cs、Fan.cs、FanEntity.cs、MachineFacade.cs、Power.csが、すべて同じ階層(プロジェクト直下)にザラザラと並んでいます(図3)。

図3 整理前のMachineプロジェクト。ファサードを含むすべてのクラスが同じ階層に並んでいる

この状態だと、ファサードクラスであるMachineFacade.csが他の多くのクラスに埋もれてしまい、「このサブシステムにはファサードが用意されている」ということが、ソリューションエクスプローラーをひと目見ただけでは伝わってきません。フォルダー構成についても、もう少し工夫したほうがよさそうです。

Objectsフォルダーを作成する

そこで、ファサード以外のクラスをまとめて格納するための専用フォルダーを作成します。Machineプロジェクトを右クリックし、「追加」を選択します(図4)。

図4 Machineプロジェクトを右クリックして表示されるコンテキストメニュー。「追加」からフォルダーを作成する

「追加」から新しいフォルダーを作成すると、フォルダー名を入力できる状態になります。ここでは「Objects」という名前を付けています(図5)。なお、このフォルダー名は必ずしも「Objects」である必要はなく、実際に格納するオブジェクトの性質に合わせて、自由な名前に変更してもらって構いません。

図5 作成したフォルダーの名前を入力しているところ。ここでは「Objects」と名付けている

ファサード以外のクラスをフォルダーへ移動する

Objectsフォルダーを作成したら、Box.cs、Camera.cs、Fan.cs、FanEntity.cs、Power.csをドラッグ&ドロップでObjectsフォルダーの中へ移動します。MachineFacade.csだけは、そのままプロジェクト直下に残しておきます。移動が完了した直後のプロジェクト直下は、Objectsフォルダーと MachineFacade.cs の2つだけになります(図6)。

図6 サブシステムのクラスをすべてObjectsフォルダーへ移動した直後の状態

Objectsフォルダーを展開してみると、その中にBox.cs、Camera.cs、Fan.cs、FanEntity.cs、Power.csが収まっており、MachineFacade.csだけがフォルダーの外(プロジェクト直下)に置かれている状態になっていることが確認できます(図7)。

図7 Objectsフォルダーを展開した状態。サブシステムのクラス群がフォルダー内にまとまっている

フォルダーを閉じた状態で確認する

最後に、Objectsフォルダーを閉じた状態で確認してみます(図8)。プロジェクト直下にはObjectsフォルダーとMachineFacade.csの2つだけが並ぶ、非常にすっきりとした見た目になりました。

図8 Objectsフォルダーを閉じた状態。プロジェクト直下にはファサードだけが直置きされている

この状態であれば、ソリューションエクスプローラーをパッと見ただけで、「このサブシステムにはファサードが用意されている」「呼び出すときはこのファサード経由で呼べばよい」ということが一目で伝わるようになります。

なお、Objectsフォルダーの中身をさらに用途ごとに2個・3個、あるいはそれ以上のフォルダーに分割しても、まったく問題ありません。重要なのは、フォルダーに入れずプロジェクト直下に直置きするクラスは、ファサードだけに絞っておくという点です。直置きされているものがファサードだけであれば、それだけファサードの存在が目立ち、サブシステムの入り口がどこかがひと目で伝わるようになります。

まとめ

本レクチャーでは、実際にアクセス修飾子を変更してクラスを非公開にしていく作業に入る前段階として、フォルダー構成を整理しました。ファサード以外のクラスをObjectsフォルダーへ集約し、ファサードクラスだけをプロジェクト直下に残すことで、「このサブシステムの入り口はどこか」が一目でわかるようになります。次回以降のレクチャーでは、いよいよ各クラスのアクセス修飾子を変更し、クライアントから見えるクラス・メソッドを必要最小限に絞り込んでいきます。

C#

■非公開コース「C#14新機能」プレゼント:
非公開コース「C#14新機能」(80分)をご覧になりたい方は
こちらからURLとパスワードを発行していますので、ご覧になってみてください。
非公開コース「C#14新機能」を観る

参考にした書籍

実戦で役立つ C#プログラミングのイディオム/定石&パターン
プログラミングC# 第8版

オブジェクト指向
ジャイルソフトウェア開発の奥義 第2版 オブジェクト指向開発の神髄と匠の技
  すばらしい本です。オブジェクト指向が詰まっています。

オブジェクト脳のつくり方―Java・UML・EJBをマスターするための究極の基礎講座
  サンプルコードはjavaですが,最初にオブジェクト指向に目覚めるのに最適な本です。

Head Firstオブジェクト指向分析設計 ―頭とからだで覚えるオブジェクト指向の基本
  マンガみたいな感じで読めて,オブジェクト指向について学べます。  

Clean Code アジャイルソフトウェア達人の技
Clean Architecture 達人に学ぶソフトウェアの構造と設計
Adaptive Code ~ C#実践開発手法
.NETのエンタープライズアプリケーションアーキテクチャ
実装パターン
  廃盤のため異常に高くなりすぎなので,様子を見た方がいい気がします。一万円のボリュームがあるかどうかは微妙です。

オブジェクト指向でなぜつくるのか
レガシーコード改善ガイド
リファクタリング 既存のコードを安全に改善する

デザインパターン
オブジェクト指向における再利用のためのデザインパターン
オブジェクト指向のこころ
Head Firstデザインパターン ―頭とからだで覚えるデザインパターンの基本

ドメイン駆動開発
エリック・エヴァンスのドメイン駆動設計
実践ドメイン駆動設計
ドメイン駆動
現場で役立つシステム設計の原則
エンタープライズアプリケーションアーキテクチャパターン