Processingで学ぶ 実践的プログラミング専門課程

第30回 リファクタリング(4) 委譲による継承の置き換え

この記事を読むのに必要な時間:およそ 3 分

導入

ビンゴゲームも盛り上がってきた頃,自分のカードのチェックがきちんとできていないぞという騒ぎが起ったとします。しかしながら,今回作成しているビンゴマシンにはリプレイ機能がありません。そのため,リプレイ機能がほしくなります。

というわけで,今回はまず,機能拡張から話を始めます。機能拡張はリファクタリングではありません。無事,機能拡張がうまくいったら,その時がリファクタリングの出番です。近い将来また別の機能がほしくなった時に,このコードを楽しくメンテナンスできるように,お行儀の良い,かぐわしい香りのするコードにしておきましょう。

展開

BingoProgressionクラスを継承する

BingoProgressionクラスは一方通行にビンゴ数列の要素を吐き出します。吐き出したあとは,もう後戻りできません。BingoMachineアプリケーションを再起動すると,新しいビンゴ数列を生成します。こうなると,「もう一度最初から数列を読み上げてくれ!」という要望に応えられません。そこで,もう一度最初からビンゴ数列の要素を取り出せるようにしましょう。アプリケーションとしては,Rボタンを押したら数列の最初に戻るようにします。現在何番目の要素を表示しているのか,ディスプレイウインドウに表示されていると親切ですね。

リプレイ機能付で親切なビンゴマシン

画像

例えばこのスクリーンショットは,「75個あるビンゴ数列の要素のうち,4番目の要素を表示中で,それは6である」という意味です。

このような外見で,Rキーを押すと先ほどと同じビンゴ数列を最初から表示してくれる,リプレイ機能付きの便利で親切なアプリケーションに変更してみます。

これを作業とします。そして作業については条件があります。

  1. BingoProgressionクラスを継承すること。

    BingoProgressionクラスを継承したRewindableBingoProgressionクラスを作成してください。このクラスに,数列の最初の要素から再度数列を取得するためのgoHeadメソッドを持たせてください。

  2. BingoProgressionクラスのソースコードには一切手を加えないこと。

    理不尽ですが,作業の課題ですからそのようにしてください。現実的な状況を想定するならば,BingoProgressionクラスのソースが公開されていない場合や契約上コードの変更が許されない場合だとしてください。

[作業] リプレイ機能付で親切なビンゴマシンを作成してください。作業の最初にテストコードを記述することを忘れないでください。

また、集合の要素の最初に戻る機能付きのIteratorインタフェイスを連載第24回で作ったようにRewindableBingoProgressionクラスに実装しても良いのですが,不要な機能が多く含まれますから今回は見送ります。「今必要ない機能は実装しない」というポリシーです。これは以前に話した,XPの原則であるYAGNI(You ain't gonna need it)というポリシーです。

リプレイ機能付きで親切なビンゴマシンのコード

作業により,目的のコードが完成しました。rかRがキー入力されると,ビンゴ数列の取得を最初の要素から再開するようになりました。

BingoProgressionクラスを継承しましたから,ビンゴ数列の作成はスーパークラスであるBingoProgressionクラス側で行われます。サブクラスであるRewindableBingoProgressionクラスにはビンゴ数列生成のコードはありません。

これは継承を利用する際のありがたさです。サブクラス側にcreateBingoProgressionというコードが全くなくても,スーパークラス側のその機能が利用できるからです。

継承の弊害

さて,便利な機能である継承ですが,弊害があります。今後,さらに継承によってクラスを拡張していく場合,多段階に渡るスーパークラスとサブクラスの関係が発生します。これはコードの見通しを悪くし,大変読みにくく理解しにくくなります。継承の利点である「スーパークラスで実装されているメソッドやフィールドは,サブクラスで再度宣言しなくても利用できる」ことが,「サブクラスのコードを見ただけでは,スーパークラスに実装されているメソッドやフィールドがはっきりしない」という欠点に転じるのです。

例えば,今回のRewindableBingoProgressionクラスは,内部でIteratorインタフェイスのメソッドを利用しています。その際,自分が実装したメソッドを利用しているのか,スーパークラスのメソッドを利用しているのか明示して区別しなければなりません。これはコードを読み書きする上での複雑さを増しています。

絶対に継承を利用したほうがわかりやすい,便利だ,と言えない場合には,極力継承は利用しないほうが無難です。肝心なのは,技術の適材適所です。

では,継承を使わずに,今回と同じ働きを持つコードを書くにはどうすればよいでしょうか。

そこでリファクタリング「委譲による継承の置き換え」の採用を検討します。

著者プロフィール

平田敦(ひらたあつし)

地方都市の公立工業高等学校教諭。趣味はプログラミングと日本の端っこ踏破旅行。やがては結城浩氏のような仕事をしたいと妄想している。

Twitter : @hirata_atsushi

コメント

コメントの記入