2015.03.09

PHP標準フレームワークのガイドラインの効果


はじめに

こんにちは。次世代システム研究室のT.Tです。
前回に引き続き、現在開発しているサーバーサイドの標準フレームワークについてご紹介したいと思います。
今回は、標準フレームワークのガイドライン的なところについてご紹介したいと思いますが、現在ベトナムラボとの共同開発で利用されていて、そこでの業務を最適化する側面が強いため、その内容と合わせてご紹介したいと思います。

RFCモデルについて

RFCモデルは次世代システム研究室でベトナムラボとの共同開発用のプロジェクトモデルとして構築されたもので、現在の開発プロジェクトもそれをベースに進められています。
詳細については「アジャイルなオフショア開発」という発表をしましたベトナムとのオフショア開発ではRFCモデルがフィットした話に紹介されているので、ここでは本ブログで取り扱う部分だけ搔い摘んでご紹介します。

RFCモデルの概要
  • 日本側で機能仕様をざっくり取りまとめてベトナム側に伝える
  • ベトナム側では詳細設計とコーディング、単体テスト、結合テストを担当、実施
  • 結合テスト完了後に日本側でコードレビューを実施して、不備があればベトナム側で修正(この時点で全体の95%程度の完成度)
  • ベトナム側での修正が完了したら日本側でリリース品質になるまで作り込む(残り5%)

プロジェクト開始直後の状況

まず、標準フレームワークで各API共通で利用するコントローラを実装して、その内部でセッション管理やリクエストの正常性チェック、トランザクション管理、ポストデータの受け取り、処理結果のレスポンス等の機能を提供することで、各APIのコントローラでは各APIに特化した機能だけを実装すれば良い状態にしました。

コントローラの実装以外はMVCモデルやFuelPHPの標準的な実装で済むため、以下のコントローラの実装例だけを渡して開発を開始してもらいました。
<?php

namespace Api;

class Controller_Skeleton extends \Controller_Api
{
    protected static $session_ignore_requests = array('create');

    protected function index()
    {
        \Log::info('index called');
        $this->data = array('result' => 'success');
    }

    protected function create()
    {
        \Log::info('create called');
        $user = \Model_User::createUser($this->params['name']);
        $user->save();
    }

    protected function update()
    {
        \Log::info('update called');
        $user = \Model_User::find($this->user_id);
        $user->name = $this->params['name'];
        $user->save();
    }

    protected function delete()
    {
        \Log::info('delete called');
        $user = \Model_User::find($this->user_id);
        $user->delete();
    }
}

最初にレビューしたコード

自分はベトナムラボのメンバーの開発スキル的なところは全然把握しておらず、この時点で初めてベトナムラボのメンバーが実際に書くコードを見るので、ドキドキしながら全体に目を通しました。
結果としては、想像していたよりは大分良く書けているという印象で、コードを見るだけでわかる機能的な不具合は2件で、機能仕様を満たすという意味ではほぼ出来ていました。

しかし、コントローラにモデルで書くべき処理が書かれている等、コード品質は低く、その兼ね合いもあって単体テストもほぼ皆無の状態でした。

事情が許せばコード品質も満足いく程度に修正してもらった上で受け入れたかったのですが、いったんはこの状態で受け入れて、気をつけるべき点をまとめて次回以降はコード品質も上げてもらう方針で進めていくことにしました。
受け入れ後、コントローラの処理をモデルに移行したり、単体テストを追加したりして、修正した分量でいうと全体の40%〜50%程度になったかと思います。
残り5%からは程遠い状況です(動くようにする修正だけであれば5%〜10%くらいで済んだと思いますが、そこを目指しているわけではないので)。

受け入れ目標の提示

次回以降の改善を狙って、コード品質を上げるための受け入れ目標を提示して、その指針に沿って受け入れ後に修正したコードも合わせて見てもらうようにしました。

提示した受け入れ目標
  • コントローラの処理
    • モデルのpropertyは直接使わない、paramsとモデルのメソッドからの戻り値だけを利用する
    • モデルの処理は書かない
    • 遅延評価する
    • コントローラでの処理に必要なデータはモデルかコントローラに保持し続ける(select => save => selectという処理は原則やらない)
  • モデルの処理
    • モデル内の処理中に整合性のエラーが発生したら例外を投げる
  • 単体テスト
    • 自分が書いたモデルのメソッドの単体テストを書く
    • 単体テストが全部成功する
    • DBのデータを参照するテストは不要(結合テストで対応するため)
  • 結合テスト
    • APIにリクエストを投げて正常系とエラー系が一通り動作する
遅延評価について
  • ユーザー入力チェック
    • コントローラではparamsのチェックせずに、save時のvalidationでまとめて処理する
  • モデルのproperty間の整合性チェック
    • Observerでチェックして、不整合があれば例外を投げる
  • DBの同じテーブル内のレコードの整合性チェック
    • テーブルにunique制約等を付けて、save時にDBで整合性をチェックする
  • DBのテーブル間での整合性チェック
    • DBの参照制約は利用しない
    • アプリケーションで整合性をチェックする

開発プロジェクトの近況

現在の開発プロジェクトでベトナムラボとの共同開発を開始してから1ヶ月半程が過ぎました。
回を重ねるごとに受け入れ時点のコード品質含めた全体の品質が上がってきているように感じます。
それに伴い受け入れ後の改修工数も削減されてきて、感覚的には全体の10%〜20%くらいにまで減らせているように感じます。

まとめ

実際RFCモデルの開発プロジェクトを担当するまでは、コードレビューの工数やベトナム側での修正量が多くなるだろうとの予想はしていましたが、受け入れ後の修正量の多さは予想以上のものがありました。
今回簡単なガイドライン(受け入れ目標等)を導入したり、それに沿って書かれた具体的なコードを共有してプロジェクトを進めたところ、飛躍的な改善に繋がったのではないかと思っています。

前回紹介したような標準フレームワークの仕組み的な整備だけでなく、このようなガイドラインの導入によっても開発効率向上、品質向上を達成でき、色々な視点から改善を進めていくことの重要性を改めて感じました。

引き続き、色々な視点から標準フレームワークを改善していきたいと思います。




次世代システム研究室では、アプリケーション開発や設計を行うアーキテクトを募集しています。アプリケーション開発者の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ 募集職種一覧 からご応募をお願いします。

皆さんのご応募をお待ちしています。