《35》リファクタリング:異なる条件式〈Python 2.x 版〉

実録:はじめてのプログラミング記事一覧
《35》リファクタリング:異なる条件式

《著》小粒ちゃん+α《監修》小泉ひよ子とタマゴ倶楽部
2009年3月3日(火)

今日の進捗

  • Language Reference: Numeric and Mathematical Modules; functools — Higher order functions and operations on callable objects
  • Python.use(better) -- セミナー研修テキスト
  • 連結リスト課題を「続・ひよ子のきもち」で公開
Comment
本人:野中 リファクタリングが大切なのは分かりますが全体が分かりにくくなってしまいます。
担当:伊藤/本間 。(^^)

何が問題か:異なる条件式

(前述した)2つのメソッド __delitem__/remove では、

    def __delitem__(self, key):
        ...
        while node:
            if n==key:
                ...
    def remove(self, value):
        ...
        while node:
            if node.item==value:
                ...

if に続く条件式が異なります。そこで、リファクタリングを実施して、これらの異なるコードの断片を抽出して、独立したメソッドを用意します。

リファクタリング:異なる条件式

新たなメソッドを抽出するときには、もとの局所変数を、新たに引数として再定義するのが基本です。ここでは、4つの局所変数 node/key/value/n が対象になります。
ただし、局所変数 key/value の違いは、各メソッドに固有の状況に対応するもので、それぞれに独立したものです。そのため、新たに引数として再定義するときには、これらをひとつで表現しても問題はありません。すると、

    def _removeNode_delitem_cond(self, node, key, n):
        return n==key
    def _removeNode_remove_cond(self, node, value, n):
        return node.item==value

各メソッドの引数は、3つだけ用意すればいいことになります。この抽出したメソッドを呼び出す側では、各メソッドの名前の一部(delitem/remove)が異なる状況だけを記述すればいいのが分かります。すると、

class myList(object):
    def removeNode(self, value, tag):
        ...
        while node:
            if eval("self._removeNode_%s_cond(node,value,n)"%tag):
                return self._removeNode_body(prev, node)
            ...

新たな引数 tag を導入するだけで、メソッドの名前をその状況に合わせて変化させられるようになります。つまり、呼び出すメソッドを実行時に確定させるのです。
《Note》局所変数 key/value の違いは捨象できるので、仮引数としては(その一方だけを採用して)同じ名前 value になっています。《りす》□

Tips

本格的なメタプログラミングについては、他の記事で紹介します。組み込み関数 eval は、その手段のひとつを提供します。《ひよ子》□

Last updated♪09/03/04