チームでSymfony2を半年使って感じたメリット・デメリット[PHP][Symfony2]
この記事はSymfony Advent Calendar 2014 19日目の記事です。
はじめに
今年新卒として配属されてからエンジニア4人のチームで半年ほどSymfony2を使って開発をしてきて、Symfony2で良かった(メリット)と感じた所や、こういう時辛いねー(デメリット)と感じた所がいくつか見えてきたので、まとめようと思います!
使おうかどうか迷っている人などの参考になればと思います。
メリット
まずはメリットから。良い所がたくさんありました!
部品の再利用性が高い
Symfony2は本当に疎結合に徹底した思想だなと感じました。 Symfony2はいわゆる「フルスタックフレームワーク」のイメージが強いですが、その他のプロダクトにもぶちこめるほどのパーツ単位のものが組み合わさってフルスタックな形を実現しています。
なので、そういったSymfony2が提供しているコンポーネントのごく一部を組み合わせて作成した機能なら例えSymfony2を使っていない他のプロダクトでもその機能を移植可能な時もあったりします。
そういった再利用性が高いのはとても素晴らしいメリットだなと感じました。
利用者が多いが故に神Bundleが転がっている
有名なフレームワークなだけあって、とても強力なプラグイン的ポジションのBundleが既に豊富に作成、公開されています。
これらを用いることで不要な車輪の再発明は抑えられ、開発スピードを上げることができますし、利用者も多いので枯れ方も良い感じになっています。
Symfony2 - The 30 Most Useful Symfony Bundles - Qiita
や
Discover 2450 bundles for Symfony2 | KnpBundles
を見ると使えそうなBundleがゴロゴロしているので、ニーズに合わせてがんがん使ってみると良いと思います。
個人的なお気に入りは doctrine/DoctrineMigrationsBundle · GitHub で、デフォルトのDoctrineの提供するマイグレーション機能をより便利にしてくれる素晴らしいBundleなので、是非使ってみてください。
あと、Advent Calendar 16日目に公開されていた
[Symfony] AliceBundleで自動テストのfixtureをyml化しよう | karakaram-blog
にて紹介されていたAliceBundleも使っています。便利なので上記記事を読みながら是非使ってみてください!
ファンクショナルテストが書きやすい
Symfony2はデフォルトでクローラー等込み込みのテスト用Clientを提供してくれています。 これを用いることによって割と素直にファンクショナルテストを書くことができます。
詳しくは以下が参考になると思います。
型がしっかりついているので追いやすい
Symfony2に従っていくと、自然とほんのりJavaの匂いを感じる型が意識されたコードになっていきます。
PHPの動的な型を生かしつつ型の恩恵も自然と受けられるようになっていくので良いです。
PhpStormを使っているとジャンプ機能など更に型の恩恵を受けやすくなっていくので一石二鳥といったところでしょうか。
フレームワークのソースが読みやすい
プロダクトの規模もクラス数も尋常じゃないですが、型+PhpStormのおかげもあってか「なにしてるんだここ...」とか「処理が追えない...」みたいな詰まり方はこの半年ではそこまで多くない印象でした。コード自体もしっかりと保守されているのが伝わります。
これは使いはじめる前までとは印象がかなり違った部分だなぁと思っていて、使うまでは「Symfony2は巨大すぎてどこで何が起きているかまるでわからなくなりそうだ...」みたいなイメージだったのですがそうでもなくて良かったです。
イベントが多く用意されているので差し込みやすい(知らないときつい)
Symfony2の使わないとなかなか知られざる超強力な武器だなと感じた点として、EventListener
層が確立されている点が挙げられます。
request
やresponse
やException
といった様々なイベントが用意されていて、それらが起きたことを検知してほげほげ処理ができる機構が備わっています。
これがとても便利で、いろんなところにフックポイントが存在するので、例えばユーザ認証といったものをいちいちControllerに書くのではなく、Controllerに達する前のEventで処理してしまうのです。
こうすると再利用性は高いですしController内は汚れず綺麗。素晴らしいですね!
また貫通してきた全例外をひっつかまえる、なんてこともEventListenerで簡単に行えるので、ログを残したりメールを飛ばしたりしてから死んでもらう、みたいなのも一箇所に集約できるので各例外発生ポイントで無理に例外をcatchすることもなくスッキリできます。
この辺りにイベント周りの情報が掲載されています。
フォームの構成を自由にカスタマイズし易い(出したいものだけを出したりできる。)
Symfony2ではType
という簡単に言うとフォームに載せる要素の選別を行うクラスがあります。
ここで柔軟に出し分けを行うことができるので、「テーブルのこのカラムは出したくない」といったニーズに簡単に答えられます。
また、実際に描画をする際にも、フォームのラベルだけを表示したり、エラーだけ表示したり、といった様に表示するものを小分けにもできるので、デザインの調整なども可能です。
そこまで凝ったviewを作るようなプロダクトではなかったのも有るかもしれませんが、シンプルに使えるのでなかなか使い心地は良かったです。
プロファイラーの助けがあるためデバッグし易い
Symfony2はプロファイラーというデバッグツールがついていて、これが非常に使い勝手が良かったです。
投げられるクエリやクエリ数もわかりますし、そのクエリのexplainなども画面上から簡単に確認できます。
また、2.4以降からはFormの情報もProfilerに乗るようになり、どんなinputだったかだったりどんなバリデーションにひっかかったとかもすぐわかります。
エラーログもProfilerから確認できるので、いちいちログをあさらなくても大丈夫だったりしてとても気が利いていました。
Symfony2のアップデートスケジュールがしっかりしている。
機能面ではないのですが、実践登用する上でのメリットになるなぁと強く感じたのがサポート期間です。
使ってたのにいきなり仕様が大変更されたつらい!みたいな状態になると笑えませんよね。
そこでSymfony2はサポート期間をはっきりと明記しています。
上記リンクのリリースプロセスを初めから考慮出来るので計画的なアップデートを行うことが可能です。
この手厚いフォローは業務で使うとなると嬉しいのではないかなぁと感じました。
Bundleも含めカスタマイズをし易い(Symfonyがデフォルトで用意している)
完成品に見えるBundleも、実は継承して一部だけ上書き、みたいな芸当ができます。
便利な機能をあやかりつつここだけはプロダクトにfitさせたい、みたいなこともできて便利です。
バンドルの継承を使って既存のバンドルのパーツを上書きする方法 | Symfony2日本語ドキュメント
DQL使っているので、保守性は高い
少し癖があって(癖というかMySQLに慣れていると〜がない!つらいみたいな)ハマったりしますが、DQLで書いておけばもしDB変えるとなっても大丈夫なので、強くはなります。
Bundleという概念があるため依存関係を把握し易い(相互依存は明らかにおかしいと判断できる)
Bundleをいくつか組み合わせてアプリケーションを作っていくので、自然と基底Bundleみたいなのを作りたくなってきます。(共有できる再利用性の高いものをいれておくBundleとか)
たとえば汎用的なAというBundleの中で、Aを用いて機能を作っていっているBというBundleが使われていると、相互依存となって、使われ方がおかしいのがすぐ分かります。
レビュー時なども、ファイルのuseを見れば依存関係がまずいことになっていないかはすぐにわかります。
こういったように依存関係のピラミッドが見えやすくなっている構成は間違いを生みにくいメリットになるなぁと感じました。
コンテナを利用していることで依存性の解消が簡単
Symfony2はサービスコンテナを提供してくれていて、クラス間の依存関係をよしなに解消してくれてから取り出すことが可能になっています。
このようにコンテナを利用すると自然とDIするというレールに乗っかってくるので、差し替えが非常にしやすくなりテスト時など助かります。
DIしていく思想に慣れるとだいぶ使いやすくていいなぁと思いました。
PhpStormとの連携がイケてる
これはSymfony2というよりPhpStormの話になりそうですが、とにかくSymfony2とPhpStormの相性が抜群に良いです。
Symfony2を書くときは確実にPhpStormを使う方が幸せになれると思います。(賢いジャンプ機能やサービスコンテナ、twig、Symfony2の提供するコマンドの補完等々幅広くサポートが効いています)
コードリーディングの時だけでもいいので使ってみると便利さが伝わるかと思います。
デメリット
次につらみ成分の紹介です。そこはこうすれば上手く立ち回れるよっていうのがあれば教えていただけたら助かります!
レールがないぶん、外注する時のルールを伝えるのが大変(自由にできすぎる)
Symfony2は「部品置いておいたから後は好きに使って」と言ったイメージで、かなり自由に作ることができます。
その分、チーム開発の際はメンバー内のルールが固まってこないと、色々な記法で書かれた色々が点在する形になってカオスになってきてしまいます。
なので走りながらでもいいと思うのでチームでの共通認識を持ってレールを敷いていく必要ががあるなぁと感じました。
また、これがデメリットとして顕著にでたのが外注時で、ちゃんと依頼を投げる前にレールを敷いて置かないと好き勝手にかかれたSymfony2プロダクトができてしまいます。(もちろんコーダーのスキルにもよりますが)
散らばらないように、いくつかSymfony2から出されたレールの敷き方の選択肢から、チームで1つの解答をしておく必要があると思いました。
共通部品が出来上がるまではコード書く量が多い
中盤以降は再利用が出来る所が増えてきてスピードが乗ってきた(というか普通は落ち始めるところがあまり変わらない)のですが、やはりいかんせん初期はSymfony2が提供してくれている便利なコンポーネント群の存在に気が付かなかったり、型を意識した結果ファイル/クラス/コード量が増えて実装に時間がかかる、といったフェイズがありました。
また、Symfony2が採用しているDoctrineは薄めのORMを積んでいて、それが薄いためテーブル内レコード数のカウントも手実装をしなくてはなりません。
このあたりも実装してしまえば次からは早いのですが初期のコストとしてかかってきて少しつらいねーという話がでました。
管理画面を自作せざるを得ない
今回携わったプロダクトの性質上、というのもあったかもしれませんが管理画面は結局自作する方向になりました。
sonata-project/SonataAdminBundle · GitHub という管理画面作成用のBundleもあったのですが、学習コスト及び変更時につらみがありそうだ、というところで使用する選択をとりませんでした。
もう少し取り回しの良い軽いAdminBundleがあればいいなぁと感じました。(とはいえ主観ですしSonataをゴリゴリ使ってもいないので説得力にかけます)
interfaceでの型縛りのため、実体が見えづらい
思想上interfaceをよく使うのですが、これを使うようになると確かに利用者側はそのinterfaceだけ知っていれば良いのでより疎結合な良い感じに実装することが出来るのですが、PhpStormでジャンプした時にInterfaceに飛んでしまう、といった様に実体が良くも悪くも隠れてしまって開発効率が落ちます。
interfaceをimplementsしているものから見たい実体を選んで飛びなおすことはできるのですがやはり手間取りました。
キャッシュ問題にはまりやすい
Symfony2あるあるのハマりどころとしてあげられるのが「キャッシュ問題」だとおもいました。
設定にもよりますが何から何までキャッシュして動かすので、ソースコードを修正したり設定ファイルを修正したりしてもそのままでは動作が変わりません。
なのでそういった変更の度にキャッシュが絡んできてしまいたまに思わぬ落とし穴にハマってしまったりしました。
とはいえでその作成される巨大キャッシュのおかげでフルスタックの中ではパフォーマンスが良いフレームワークとなっているので、仕方ないとは思っています。
テンプレートのカスタマイズがちょっと辛い
Symfony2はデフォルトのテンプレートを提供してくれています。
そのデフォルトのテンプレートの一部を修正してcssを当てはめたりということが可能です。
フォームのレンダリングのカスタマイズ方法 | Symfony2日本語ドキュメント
一部分を割とシンプルに拡張できてとても素晴しいのですが、そのデフォルトのテンプレートはSymfony2のバージョンに依存します。
つまりバージョンを上げると、仕様がゴリッと変わっていることもあります。
仕様が変わっているところに対して古いバージョンのテンプレートにもとづいて拡張した部分があるとすると、その部分は仕様変更に追従できずバグってしまいます。
そのためメンテナンスコストがかかりはじめてしまい少し辛そうに思いました。
おわりに
色々箇条書きでガーッと書いてみましたが、使用感は個人的にはとても良かったです!
これからも引き続き使っていって見たいと思います。