「設定」画面を付け加えると、リクエストハンドラがもう 1 つ増えることになる。「BG をリファクタリングする」で書いたように、BG の画面の構成要素には共通部分が多い。当然、それを作るハンドラにも共通部分が多くなる。新しいハンドラを作る前に「コピペプログラミング」に陥らないよう、共通部分のくくり出しを行おう。
今回のお題は「リクエストハンドラから共通部分をくくり出す」だ。
リクエストハンドラから共通部分をくくり出す
今回のリファクタリング対象は、google.appengine.ext.webapp.RequestHandler
を共通の親クラスに持つ、2 つのリクエストハンドラ・クラスだ。
(google.appengine.ext.webapp.RequestHandler) +--- MainHandler +--- PostViewHandler
リファクタリングの方針としては以下の 2 通りのものが考えられる。
- 共通部分を、
google.appengine.ext.webapp.RequestHandler
を継承する中間クラスに移動し、各リクエストハンドラはこの中間クラスを継承する。 - 共通部分を別クラスや関数として独立させ、各リクエストハンドラから利用する。
前者は「継承」によるリファクタリングで、後者は「移譲」によるリファクタリングだ。どちらにも一長一短はあるが、今回はリファクタリングの主眼は実装の整理なので、「移譲」を使ってみる。一般的に言って、継承階層の中間にクラスを挟み込む方法は、制御の流れをわかりにくくするので、デバッグしづらくなる(BG 程度の規模ならあまり影響はないが)。また、単体テストという観点から言っても(BG ではやってないけど)、インスタンス化しづらい(できないことも多い)中間クラスは避けた方が良い。
責務分析
上述の 2 つのリクエストハンドラは、GET リクエストに対応する get
メソッドのみを実装しており、どちらのクラスでもそれは Atom フィードを取得、解析し、その内容をもとに画面に表示する情報を組み上げるようになっている。
- 画面の共通エリア(アプリ固有情報)を作成する。
- リクエスト情報からフィードを取得するためのパラメータを取り出す。
- フィードを取得し、解析を行う。
- フィードのデータから画面(ビュー)に固有の内容を組み立てる。
- テンプレートをロードし、画面表示を生成する。
このうち、3. はすでに外部クラス(feed.core.AtomFeed
等)に移譲されている。また、5. はもともとテンプレートエンジン(Django)の役割だ。
残りの 3 つのうち、リクエストハンドラごとに異なるのは 2. のパラメータ取り出しと 4. の固有の表示内容の組み立てだ。言い換えると、1. の共通エリアのための情報の作成が共通部分としてくくり出せる責務になる。また、リファクタリング後に行う「設定」画面の追加では、ログイン/ログアウトの仕組みを組み込むことになるが、これも 1. にふくまれると言って良い。
リファクタリングの実際
util.py
今回のリファクタリングで追加したモジュール。以下の 2 つの関数が定義されている。
関数名 | 機能 |
---|---|
fill_appinfo(appinfo) |
アプリ固有情報を作成する。引数には info.AppInfo のインスタンスがわたされることを想定している。 |
render_template(handler, filename) |
google.appengine.ext.webapp.template.render を呼び出す。関数というよりマクロ。 |
main.py
__init__
で行っていたアプリ情報の作成が util.fill_appinfo
に移ったので、__init__
は削除した。また retieve
は util.fill_appinfo
にあわせて名前を fill_viewinfo
に変更した。
postview.py
main.py と同様の変更なので、説明は省略。
関連リンク
- Copy And Paste Programming (c2.com)
- 移譲 (Wikipedia:ja)
- Blogger Glass (GAE アプリ)
0 件のコメント:
コメントを投稿