Python.use(better, follow=”K&R”) リファクタリング 6/10

Previous|6/10|Next
Python.use(better, follow=”K&R”) # for novice 記事一覧

改訂♪2008/10/03

リファクタリング:クラス固有の処理

[Python]何が問題か?


#------ before --------------------------------
class HashTable:
def __getitem__(self, key):
e = self._detect(key)
if e:
return e[key] # NOTICE !!
else:
raise KeyError, key

class Tnode(BinTree):
def __getitem__(self, key):
e = self._detect(key)
if e:
return e.count # NOTICE !!
else:
raise KeyError, key

2つクラス HashTable/Tnode において、メソッド __getitem__ の本体を見ると、その違いは return に続く箇所だけだと分かります。そこで、これらの異なるコードの断片から共通する構造を抽出して、それを再利用可能とするために、リファクタリングを履行します。

[Python]ある解決法

リファクタリングを履行すると、次のように、コードの見通しが良くなり、その保守も容易になります。


共通する処理(テンプレート)_toget と、クラスごとに固有の処理(名前は同じでも、本体が異なる)_valueItem とを分割統治します。


class eXdict:
def _valueItem(self, e, key): raise NotImplementedError

メソッド _valueItem が例外 NotImplementedError を生成します。これは、子孫クラスにおいて、このメソッドを再定義する必要があることを意味します。


class HashTable(eXdict):
def _valueItem(self, e, key): return e[key]

演算子 e[key] を適用して得られるものをリターン値とします。


class Tnode(BinTree):
def _valueItem(self, e, key): return e.count

インスタンス属性 e.count を参照して得られるものをリターン値とします。


# cz_08.py -------------------------------------------- after ---
class eXdict:
def _toget(self, key, func):
e = self._detect(key)
if e:
return self._valueItem(e, key)
else:
return eval("self._%s(key)"%func)

リファクタリング後のメソッド _toget は、以前の __getitem__ に取って代わるもので、return に続く箇所を、先に定義したメソッド呼び出し _valueItem に統一しています。


Previous|6/10|Next