この記事はSymfony Advent Calendar JP 2011の24日目の記事です。

速いペースでマイナーバージョンアップされるSymfony2

Symfony2は、2011年7月に2.0がリリースされて以降、概ね月に1回のペースでメンテナンスリリースをしています。私自身が開発に携わっている案件でも、何度かこのようなメンテナンスリリースによるSymfony2本体のバージョンアップを行いましたが、直接的な問題はほぼ発生していません。フレームワークの更新というと、マイナーバージョンアップでさえ事前に変更点をしっかり調査し、適用しても問題がないという調査・判断が必要でした。Symfony2でももちろん事前に変更内容を調査することは必要ですが、Symfony2側で後方互換性が維持されるルールが導入されており、上手く機能しているようです。

この「後方互換性を維持するルール」の中心となるのが「@apiアノテーション」です。簡単に説明すると、@apiアノテーションのつけられたメソッドは、Symfony2のマイナーバージョン間において、シグニチャや振る舞いが変更されないことが保証されています。

このルールによって後方互換の維持対象となるものを、Symfonyでは「ステーブルAPI」と呼んでいます。たとえばSymfony公式サイトの「The technological benefits of Symfony in 6 easy lessons」のページには、次のような記述があります。

4. Stable and sustainable

Developed by Sensio Labs, major versions of Symfony are all supported for 3 years by the company. And even for life as far as security-related issues are concerned. For even greater stability, the minor versions of Symfony 2.0’s contract and interface are also guaranteed and compatibility between all minor versions will be ensured on the API defined by the public interfaces.

The technological benefits of Symfony in 6 easy lessons - Symfony

ドキュメントにもステーブルAPIを説明したページがあります。日本Symfonyユーザー会で翻訳したページから引用します。

  • 名前空間とクラス名は変更されません。
  • メソッド名は変更されません。
  • メソッドのシグネチャ(引数と戻り値の型)は変更されません。
  • メソッドの振る舞いの意味は変更されません。
Symfony2 ステーブル API | 日本Symfonyユーザー会

@apiアノテーションの例

実際にSymfony2のコードで@apiアノテーションがつけられている例を見てみましょう。たとえばHttpKernelコンポーネントのKernelInterfaceでは、次のようになっています。

<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier 
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Bundle;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * The Kernel is the heart of the Symfony system.
 *
 * It manages an environment made of bundles.
 *
 * @author Fabien Potencier 
 *
 * @api
 */
interface KernelInterface extends HttpKernelInterface, \Serializable
{
    /**
     * Returns an array of bundles to registers.
     *
     * @return array An array of bundle instances.
     *
     * @api
     */
    function registerBundles();

    // **snip**

    /**
     * Gets the log directory.
     *
     * @return string The log directory
     *
     * @api
     */
    function getLogDir();
}

クラスの先頭と、すべてのメソッドに@apiがつけられています。つまり、名前空間やインターフェイスの名前、KernelInterfaceで公開されるすべてのメソッドの名前とその振る舞いが、マイナーバージョンでは変更されない、ということです。

実際に開発者はどうしているのか

@apiアノテーションをつけたからといって、自動的に後方互換性の維持機能が働くというものではありません。これは単なるコメントですから、人間がそれを見て適切に扱う必要が(現時点では)あります。

GitHubを開発リポジトリしているSymfonyでは、バグフィックスや機能追加のリクエストをPull Requestという形で送信しますが、Pull Requestを送る際に後方互換性が維持されているかどうかを次のようなテンプレートによって明示するルールとなっています。

Bug fix: [yes|no]
Feature addition: [yes|no]
Backwards compatibility break: [yes|no]
Symfony2 tests pass: [yes|no]
Fixes the following tickets: [comma separated list of tickets fixed by the PR]
パッチの投稿 | Symfony2日本語ドキュメント

このようなテンプレートにより、Pull Requestの送信者による事前の後方互換性チェックと、レビュー担当によるチェックがもれなく行われやすいようになってきています。

まとめ

Symfony2のコアコードでは@apiアノテーションが導入され、ステーブルAPIというルールが設けられました。これを目印とすることで高い後方互換性を維持したままメンテナンスが行われています。

開発しているアプリケーションのコードから、Symfonyコンポーネントやバンドルの機能を呼び出して利用する場合、ステーブルAPIのみに依存する(@apiアノテーションがつけられているものを使う)ようにしておけば、Symfony本体のバージョンアップに対応しやすくなるでしょう。

参考