《17》クラス(3)リファクタリング〈Python 2.x 版〉

実録:はじめてのプログラミング記事一覧
《17》クラス(3)リファクタリング

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

今日の進捗

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 =

このように記述するなど、いくつかの表現が考えられます。■

Last updated♪09/03/09