《17》クラス(3)リファクタリング〈Python 2.x 版〉
実録:はじめてのプログラミング《記事一覧》
《17》クラス(3)リファクタリング
関連記事
今日の進捗
- Tutorial: Using the Python Interpreter
- Python.use(better) -- セミナー研修テキスト
- 逆ポーランド課題を「続・ひよ子のきもち」で公開
Comment | |
---|---|
本人:野中 | 今月の課題のゴールが見えて来たのでデザインパターンについても教えてもらいました。 |
担当:本間 | 来週からは福岡と東京で離れてしまうけど、メールを使えばペアプログラミングは続けられるので、そんなに心配しなくても(焦らなくても)いいからね。(^^) |
逆ポーランド課題(1)リファクタリング
まず「トークンを抽出する」箇所を、独立したクラス Parser に記述します。
class Parser(object): def scan(self, e): s = Value(e) if e in "+-*/": s = Op(e) return s
そのトークンが、四則演算子(を表わす文字列)なら、それをもとにクラス Op のインスタンスを生成します。それ以外は、数値(を表わす文字列)とみなして、それをもとにクラス Value のインスタンスを生成します。
次に「抽出したトークンに『固有』の処理」を、独立したクラス Value/Op に記述します。
class Value(Token): # ver.1b def eval(self, client): client.eval_Value(self) class Op(Token): # ver.1c def eval(self, client): client.eval_Op(self)
さらに「抽出したトークンに『共通』の処理」を、独立した抽象クラス Token に記述します。そして実際には、これらの具体的な処理を client に委ねます。
《Note》 これは「ダブルディスパッチ」と呼ばれる古典的な手法のひとつです。メッセージのやり取りを繰り返すことで「抽象的な問題を段階的に具体化しながら解決したい」ときに便利です。《ひよ子》□
class Token(object): # ver.1a def __init__(self, value): self.value = value def __str__(self): return str(self.value) def eval(self, client): raise NotImplementedError, ( "class %s: def eval(self, client)" % self.__class__.__name__)
raise 文を使って例外 NotImplementedError を生成することで、プログラマーへの注意を促します。試しに、クラス Op のメソッド eval をコメントにする(か、他のメソッド名に変更する)と、
>>> ex() >>> 3 4 + Traceback (most recent call last): ... NotImplementedError: class Op: def eval(self, client)
この出力結果から、クラス Op のメソッド eval が未定義であることが(プログラマーに)分かります。
何が問題か
メソッドの実現を見ると、その違いは「メソッドの名前」だけだと分かります。そこで、これらの違いだけを捨象して、さらにリファクタリングを進めます。
Tips:プログラム vs. プログラミング
例外を生成する目的のひとつは「プログラム〔product:成果〕が正しく機能しているか」を検証することと、もうひとつは「プログラミング〔process :過程〕が正しく機能しているか」ことを検証することです。前者は「利用者」に対するメッセージであり、後者は「開発者」に対するメッセージです。複数の利用者が関わるシステム(利用)環境、複数の開発者が関わるシステム(開発)環境にとって「どのような支援機能が望ましいか」これを機に再考してみてください。Oh 脳《053》プログラム(算譜)とプログラミング(作譜) - 続・ひよ子のきもち《ひよ子》□
Tips:抽象クラスの意義
「抽象」クラスの意義は、文法だけで規定する性質のものではありません。さらに、冗長な記述 abstract が不要になるので(Java/C# などのように)言語仕様そのものが「メタボリック症候群」に陥ることもありません。《ひよ子》□
読者への課題
変数を扱えるように拡張してください。たとえば、
a = 3 + 4
変数への代入を表わす式は、
3 4 + a =
このように記述するなど、いくつかの表現が考えられます。■