第1章 Composite パターン 3/5, IronPython
‖記事一覧‖ C#.use(better, IronPython=”WPF”)《IronPython2.6》
# IronPython で学ぶ WPF プログラミングの世界
Composite パターンには、いくつの効能があります。ここでは、if/else に象徴される典型的なハードコーディングの問題点を回避するとともに、動的な問題解決が可能になる事例を紹介します。
2a)機能の実現:Composite
Composite::Composite では、複合オブジェクト(合成要素)に固有のプロトコルを規定します。
## -------------------- # Composite::Component class FileSystem: def __init__(self, name=None): self.name = name self.size = 0 self.items = [] def total(self): return reduce( lambda acc, e: acc + e.total(), self.items, self.size) def changed(self, client): client.update( self.branch(self, 0), "%d bytes"%self.total())
def branch(self, parent, indent): s = [] for child in parent.items: s.append("%s+-- %s"%(" "*4*indent, child.name)) if self._isdir(child): s.append(" [%d]\n"%child.total()) s.append(self.branch(child, indent+1)) else: s.append(" [%d]\n"%child.size) return "".join(s)
parent を頂点とする部分木に含まれる情報を、文字列で表現します。部分木を構成する各要素 e によって、適切に処理します。
各要素 e | 処理 |
---|---|
フォルダー | それを頂点とする部分木に含まれる情報を文字列で表現します |
ファイル | そのサイズ(数値)を文字列で表現します |
各 child が、フォルダーかファイルかを判定する必要があるので、コードが複雑になります。Composite パターンを導入すると、この問題を回避して、冗長な if/else の呪縛から解放されるだけでなく、動的な問題解決が可能になります。
《Tips》メンテナンスの悪夢: ハードコーディングの典型である if/else が醜悪なのは、要求仕様の変更に対して脆弱さを露呈することです。そのため、西暦二千年問題と同じ病巣を抱え、メンテナンスの悪夢が蘇ります。この例題では、木構造の文字列表現を提供する場面に登場するだけです。しかし、実際のアプリケーション開発では、提供される機能と同等の if/else が散在することになります。すると、新たなサービスを提供したいときに、これらの散在する箇所をすべて洗い出す必要に駆られ、西暦二千年問題が再燃します。□
def _isdir(self, node): return len(node.items)
node を頂点とする部分木が、子要素 node.items を含むなら、フォルダーと見なします。それ以外なら、ファイルと見なします。
Composite パターンを導入する前に
古典的な Composite パターンを導入する前の状態を示したのが、サンプルファイル dirComposite.py です。
具体的な WPF コントロール(Button/TextBox/Label)に関する情報は、マークアップを使って dirComposite.xaml ファイルの中に封じ込めてあるので、分離コードでは、WPF コントロールに依存しない部分だけを記述するように努めます。
複合オブジェクトは、単一オブジェクトの集合体です。ここでは、FileSystem が、複合/単一オブジェクトを区別せずに、一様に扱います。集合体に含まれる要素 items が空なら、それを単一オブジェクトと見なします。つまり、空要素ならファイルと見なし、それ以外ならフォルダーと見なします。
》こちらに移動中です《
↑TOP