役割分担

マークアップを使って記述したものは、次のようになります。

<Canvas
Width="50" Height="50" Top="10" Left="10"
Background="Red" />

これと同等の簡潔な表現ができるように、拡張したキャンバス ExCanvas を利用すると、分離コードは、次のようになります。

# catCanvas.py
ExCanvas(parent, Width=50, Height=50,
background="Red", Top=10, Left=10)

そこで、各実引数が、どのように処理されるかを考察します。


class ExCanvas(Canvas, ExPanel):
def __init__(self, parent,
background=None, Top=None, Left=None,
**args):

メソッド __init__ のヘッダー部に着目して、3つの視点から、それぞれの役割分担を検証します。
1)親クラス:引数並びにないキーワード引数 Width=/Height= は、そのまま引数 **args に保持されます。そして、これらの引数の処理をすべて、親クラス Canvas に委ねます。つまり、既存の Canvas を再利用することになります。
2)mix-in:引数並びにキーワード引数 background= を指定すると、位置引数 parent とともに、これらの引数の処理を、mix-in クラス ExPanel に委ねます。つまり、mix-in 操作を使って拡張することになります。
3)動的束縛:引数並びにキーワード引数 Top=/Left= を指定すると、これらの引数の処理を、任意のインスタンス parent に委ねます。つまり、動的束縛によって、実行時に確定する対象が、これらを適切に処理することになります。
《Note》これらの役割分担を設計の立場から検証すると(1)既存の機能継承(2)選択的な機能拡張(3)動的スキーマの適用に相当します。すべての(指定可能な)引数を網羅する必要がないので、処理の対象となる引数だけが明確になります。要求仕様の変更に伴って、新たな引数が必要になっても、既存のコードはその影響を受けません。すると、柔軟性/拡張性に優れた、見通しの良いコードを記述できるようになります。