4月17日に、社内で第1回リファクタリング講座を開催しました。今回は、カルテットの同僚Mさんが実際に実務で取り組んでいる機能実装に対して、同じ機能要件で私が再実装を行い、その実装を見比べながら、いくつかの設計ポイントを解説しました。

状況

同僚のMさんは、プログラマーとして経験も十分にあり、Symfony2やAngularのコードを書き、テストも実装できるスキルの持ち主です。

対象となったアプリケーションは、バックエンドにはSymfony2を使ったREST API、フロントエンドにはAngularJSである程度の機能をSPAとして実装しているものです。RESTでやりとりする部分は、データの形が決まればあまり問題になることはありません。こういった部分はフレームワークのサポートも厚く、道具の使い方を知れば作り方に大きな差は出ません。しかし、登録されたデータを元にちょっと込み入ったロジックの入るバッチスクリプトとなると、フレームワークが提供してくれるのは、それを実行する入り口くらいしかありません。その先の処理の設計は、モロに実装者の腕が試されます。何らかの設計の型を持っていないと、どのようなクラスを作っていったら良いのか、実際Mさんも途方にくれてしまっていたそうです。

今回の取り上げた元々のMさんのコードは、1つのバッチ機能に対してインターフェイスや抽象クラス、複数の処理実行クラスに分割され、それぞれにテストも記述され、動きとしては一応要求を満たすものでした。しかし、コードの初見の印象は、「分かりにくい」。そこで、

  • なぜ分かりにくいのか
  • なぜ分かりにくく作ってしまったのか
  • どういう視点を持てば、分かりやすくなるように最初から自分で作れるか

という点を取り上げました。

具体例

少し具体的に内容を紹介します。Mさんが作っていた処理は、日別のレコードと月単位の集計情報を1つの出力形式で出力するという処理でした。PDFの月単位の帳票で日別の明細もあるようなものを想像していただければだいたい合っています。日別のレコードには種類があって、種類ごとにちょっと違う出力を行う必要がありました。

この処理で、Mさんの実装のクラス構造は、下の図のようでした。

Mさんのクラス構造

このようにクラス図にすると、おお!オブジェクト指向だ、と思ってしまうかしれませんが、作っている目的に対してちょっと大げさな構造にも見えます。また、各クラスのコードには、いくつかのprivateメソッドがあり、クラスの目的とはちょっと違う、補助的な仕事が実装されていました。

これに対して、私は次のような実装を示しました。

再実装したクラス構造

あまりオブジェクト指向を感じられない図になっているかもしれません。しかしここには、次のような視点が際立つように意図的にしてあります。

  • 処理したいデータの構造にあったフローはどれか
  • 処理の目的を補助する道具は何か

コードの実例とともに、Mさんにはこの2つの視点を意識するようアドバイスしました。

効果

1時間ほどのリファクタリング講座をやった後のその日の午後、Mさんのコードにはすぐに変化があらわれました。私の実装で提供した道具となっているクラスを早速使うようにし、自分の実装する処理のフローとの切り分けができるようになっていました。その後もMさんのコードをレビューしていますが、基本的な構造はすぐに押さえられるようになったので、現在は次のステップとしてより使いやすいオブジェクトValueObjectとして作ったりするところを意識しつつ、本来やらなければならない処理に注力しています。

おわりに

コードの設計やリファクタリングで、よくパターンや原則が活用されます。しかし、パターンや原則の根底には、共通した良い設計のための視点があります。この視点だけであらゆる個別状況に対処できるわけではありませんが、少なくとも問題をどう捉えると設計を導きやすいのかが分かるようになります。長期的にみて、このような視点を身につけておくことこそがモデリングや設計力を伸ばすキーだと私は考えています。各企業でメンターとして教える側の立場にある方々の参考になればと思います。