《35》リファクタリング:異なる条件式〈Python 3.0 版〉
実録:はじめてのプログラミング《記事一覧》
《35》リファクタリング:異なる条件式
《著》小粒ちゃん+α《監修》小泉ひよ子とタマゴ倶楽部
第3版♪2009/02/28 ● 2009年3月3日(火)
■ 概要
(条件式だけを対象に)異なるコードの断片から、新たなメソッドを抽出します。
リファクタリングが困難なときには「組み込み関数 eval を利用できないか」を検討します。 すると、新たなメソッドを抽出して、より洗練されたコードを記述できるようになります。
■ 関連記事
何が問題か:異なる条件式
(前述した)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 は、各メソッドに固有で相互に独立しています。そのため、これらの違いを捨象して、新たな仮引数の名前を(どちらか一方の)同じ value に統一できます。すると、
def _removeNode_delitem_cond(self, node, key, n): return n==key def _removeNode_remove_cond(self, node, value, n): return node.item==value
各メソッドの引数は(4つではなく)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 を導入して(その状況に合わせて)メソッドの名前を変化させます。つまり、呼び出すメソッド _removeNode_delitem_cond/_removeNode_remove_cond は、実行時に確定します。