はじめに
カルテットで開発しているサービスLisketは、2014年始めにSymfony2ベースに置き換えて以来、3年間Symfonyを使い続けています。この記事では、カルテットで3年間育てたSymfonyプロジェクトの現状の数値や、現場で感じている課題などを整理してみました。Symfonyに限らず、同じようなプロジェクトの悩みを抱えている方々と、苦労しているポイントを分かち合えれば幸いです。
プロジェクトの規模
LisketのメインのSymfonyアプリケーション、バックエンドのアプリケーション、および自社開発の独立コンポーネントを合わせたプロジェクトの規模は、2016年12月の時点で以下のとおりです。
- ソースコード行数
- PHP:38万行 (*1)
- JavaScript:6万行+α
- Symfonyバンドルの数:37(メインアプリ)、11(バックエンドアプリ)、+α
- 独立コンポーネントの数:21(PHP)
- MySQLテーブルの数:158(メインアプリ)、85(バックエンドアプリ)
- テストの数:3658(メインアプリ)、 1280(バックエンドアプリ)、+α(独立コンポーネント)
- CircleCIでのPRのビルド時間:33分前後(2並列、メインアプリ)、12分前後(1並列、バックエンドアプリ)
- CircleCIでのmasterビルド(デプロイ込み)実行時間:1時間前後(2並列、メインアプリ)、15分前後(1並列、バックエンドアプリ)
その他の参考数値
- PHPのバージョンは7(メインアプリ)
- 2016年12月での開発チームメンバー数は7名(1チーム構成)
- CircleCIは5インスタンスのみ契約
業務アプリケーションで膨大なユースケースがあるプロジェクトと比べたらまだまだですが、全貌を把握するにはそれなりに腰を据える必要があるくらいの規模にはなっています。
(*1) 外部APIをラップするクラス群を作っていたりと、やたらとコード行数が膨らんでいるものも含まれています。
達成できていること
いくつか抱えている困難は後述しますが、現時点でクリアできていることもたくさんあります。
- ユニットテスト/機能テストを書くこと
- こまめなリリース(数日〜1週間間隔)
- 機能の適切な設計(コンポーネント分割、クラス設計)
これらの達成には、開発メンバーの技術的努力の成果も大いにあると思いますが、それとは別に、Symfonyの持つテストの書きやすさ、クラス設計の自由さなどが後押ししてくれたとも思います。
したがって、やや自慢気に聞こえるかもしれませんが、カルテットの開発部は「テストを書く文化を作る!」段階はとっくの昔にクリアできているんです。今はそこから3周くらい先のステージにいて、さまざまな壁にぶつかっているという状況なのです。
課題
現状感じている課題は、主に以下の点です。
- CI・テストの実行に時間がかかる
- コードの行数が多い
- バージョンアップ
それぞれどのような内容か、および対策として取り組んでいることを説明します。
CI・テストの実行に時間がかかる
数字に顕著にあらわれていますが、CircleCIでのCIのビルド、およびテストの実行にかなりの時間がかかっています。composerでのパッケージインストール、npmでのパッケージインストール、アセットのビルドにも時間がかかっています。
アプリケーションの継続的なリリース、機能の変更、コードのリファクタリングやライブラリのバージョンアップなどを安心して行っていくために自動テストはなくてはならないので、テストを書ける機能にはできるだけテストを書いています。しかし、その反動として、テストの実行時間が長くなってしまっています。
この問題の対策としては、PHP、JavaScriptともに独立して切り出せる部分は単独のリポジトリにして、そちらでできるだけテストを行うようにし、メインのSymfonyアプリケーション側のテストを増やさないといったことをしています。
また、Symfonyアプリケーションではアセットのビルド(assetic:dump)に時間がかかる問題についても、脱Asseticを目指して、一部はJavaScriptのエコシステム(webpack)側で実行する方法などに取り組んでいます(参考1 参考2)。
コードの行数が多い
これはSymfonyを利用していることと直接的な関係はありませんが、PHPのコードの量がかなり多くなっており、簡単には全貌を把握できません。開発メンバー全員がソースコードのすべてをくまなく把握するということは無理な量になっています。
Lisketは1つのサービスに機能追加などを行って成長させていくスタイルのプロダクトなので、コードの量が増えていくのは仕方ないといえます。したがって、これに対抗する手段としては、とにかくメンテナンス性の高いコードを常に書く、書き直していくという活動が重要と考えています。このために、プログラミング言語の進化やモダンなアプローチなどを常に取り入れながら、より洗練されたコードにしていく意識を持っておくことも大事ですね。
バージョンアップ
3年前の開発開始から、何度かSymfonyのバージョンアップを行ってきました。Symfony公式では先日3.2がリリースされましたが、Lisketで使っているのはまだバージョン2系です。SymfonyおよびComposerエコシステムを利用したプロジェクトは、一般的にはバージョンアップを行いやすいと思います。しかし、Lisketでは利用している外部ライブラリがかなりの数になっており、個々のバージョンアップが微妙にさまざまな箇所に影響しあうため、バージョンを上げようにも上げられなかったりと難しい状況になっています。
また、LisketのPHPはバージョン7に切り替え済みですが、利用しているパッケージのいくつかでは、まだPHP 7の機能に対応していないということもあります(特にReturn type declarationに絡むものが多いです)。
この問題の対策はなかなか進んでいません。多少期間をとって、メンバー全員で一気にバージョンアップとテスト、コードの書き直しなどの作業を行う以外に方法は無いのかもしれませんね。
まとめ
カルテットのSymfonyプロジェクトの現状についてまとめてみました。
約3年間開発を続けてきて、いくつかの問題点もありますが、複雑な要件・サービス全体にまたがるような機能要件に対しても比較的エレガントに解決(*2)できています。特に最近では、メンバー全員がSymfonyに慣れてきたことと、サービスの根本に関わるような変更などは一段落したこともあり、ビジネスの問題を解決する本質的な課題に注力できるようになっています。
今後は、今よりもさらに高いレベルで問題解決ができるように、技術力・設計力をチーム全体で磨きつつ、技術の負債を増やさない地道な改善も続けていきます。
この記事を読まれた同じような問題と格闘している方、独自に取り組まれた工夫のアイデアなどありましたら、是非お寄せください。
- (*2) LisketでのSymfony活用例紹介