読者です 読者をやめる 読者になる 読者になる

uzullaがブログ

uzullaがブログです。

PHPのオレオレスタックの話

ここ半年くらい、PHPのオレオレスタックを見直しています。
まあ、こういうのは本来日々見直していく物なんですけど、新年だし。

ちょっと前までは

・WAF:Limonade
・テンプレートエンジン:素PHP+Limonade+オレオレヘルパ
・DBまわり:PDO+オレオレORM
・テスト:Selenium(ウッ頭が…
・ライブラリ管理:秘伝のZIP、require_once地獄

という、お客さんの都合もあって「5.1.6でもうごくやで!」スタックだったのですが

最近は

・WAF:Slim
・テンプレートエンジン:Twig+オレオレヘルパ
・DBまわり:PDO+illuminate/Eloquent
・テスト:PHPUnit
・ライブラリ管理:Composer

という感じで「5.3ってレガシ〜」スタックになりました。*1

あと、バリデータとか、スクレイパーとか、標準関数で秘伝のタレ関数を作るよりも、ありもののライブラリをつかうようにしています。*2

なんで変えたの?

古いから、以外の説明いらない気もしますが、以下が理由です。

・関数ベースの設計はいい加減つらくなってきた
・セキュリティ対応の手間が面倒くさい感じに
・namespaceのこと一切かんがえてないのダサい
・まったく、本当にまったくテスタブルでない
・とにかくPHP5.4以降にいきたい、Arrayの省略記法とかTraitとかArrayの省略記法とかあるし。

なんで「(有名フレームワーク)」つかわないの?

固有名詞を挙げることは差し控えますが…。まあ、「オールインワン!一個で全部はいってる!」というのが嫌なお年頃なのです。厨二病みたいなものです。
甘そうとか調和がとれた感じのWAFは単純に今好みではないってやつです。

汎用性を出す為に、作法がややこしいのが嫌で(無駄な反抗心が厨二病)、あとは過去からのコードがやっぱ厳しい感じの書き方が散見され、まああとは俺が読めないほど高度である(これが本音では)。*3

後、機能追加は大体良い事だとおもいますが、さらにコードがでかくなって読めなっていくのはつらい。

話変わるようですが、PHPはもっとモダンに。

まだまだ非モダンな所は山ほどありますが、5.4くらいまでに解決された事もけっこうあります。

・開発に無駄にウェブサーバーがいらなくなった(ビルトインサーバー)
・Composerでライブラリが圧倒的に使いやすくなった
・Composerのおかげか(観測範囲の)まともなライブラリが超ふえた
・PDOのバグが(見た感じ)(ほぼ)潰れた
・namespaceが導入されて、コードが見やすくなった、オートロード最高
・タイプヒンティングとか始まってきた(まだあんまつかってない)
・Traitが、汎用機能を作る時に別の親をもつクラス対応が楽だ

つまり、いくらか簡単便利になってきた、快感です。
元がひどかったので、ちょっと簡単便利になるだけですごいうれしい!!便利!!

モダンを保っていくにはどうすればよいのか?

さて、ここが本題かもしれません。

最近Composerでライブラリ管理ができるので、バージョンロックがしやすくなりました。今自分は意図的にZipとかPearを排除しています。

ところでライブラリを使うということは、それに依存するということです、まあ当然ですね。止めない限りつかいつづける事になります。

ご存じの通り、「秘伝のタレを100年つかうやで!」というのが冗談でもなんでもないのがPHPです、すごい安定性(?)だ。10年程度は笑い話にもなりません。

じゃあ、今ZIPでダウンロードしたライブラリ(と、そのバージョン)、10年後もつかえるか?バックアップするのか?正直しんどい。

頑張って追従すればいいじゃん

別の言語を引き合いにだしてもしかたないんですけど、ご存じの通り某世界で一番人気のあるWAFは定期的にメジャーバージョンアップがかかって、都度結構な阿鼻叫喚(なのか、もう慣れたから快感の声なのかわかりませんが)があります。

PHPで話をあんまり聞かないのは、ライブラリをバージョンアップしていく、という心がけがないのか…多分俺からみえないだけできっとがんばってるんだろ!って思ってるけどどうなんだろうね?って感じです。


まあ、話戻しますけど、平たく言って、WAFのバージョンアップを用意も無しにやると人が2〜3人死ぬわけです。
PHPのバージョンアップも同様に人が死にますね*4

といいつつも、バージョンアップせず秘伝のタレをつかいつづけるのは現実的な選択肢です。
私もよくわからん人から投げられたアプリは「ああ、これは小手先ではもうダメだ、延命だけしましょう*5」と*6なる事もしばしばあります。


しかし、そういう「放置」をするにしても、まあいつかはクリティカルなことになって、誰かがババをひくだけです。ズルズル付き合ってたらクリティカルな奴キター!みたいな。


予想外かもしれませんが、お客さんやウェブサービスは誰かが殺さないと割と死なない程度に長生き健康な感じであり、長期間どう付き合っていくかはちょっと前から成熟しつつあるウェブ開発の課題ですよね。

話ずれますけど、何故バージョンアップするのか?

「バージョンアップなんてしなくても良いのでは?」というご意見も割と非常に頻繁に良く頂きます。使える所までWindowsXPを使い続けたい、しごくもっともな感覚です。

一言で万人(お客様)に改修を納得させられるような言葉をだれかお持ちでしょうか。
ところでそのお言葉、おいくらでお売りいただけますでしょうか?


・セキュリティが
・OSのサポートが
PHPのサポートが
・ブラウザのバージョンアップが
・IEのバージョンアップが

ここらへんは、まあギリギリ通じる事もありますね。
そして、私が直す事も無理感が演出できそうです。
しかし「そんなのどうでもいい」っていわれたらまあ無理ですね。


・バグが

ライブラリがバグっててなおさなきゃいけないのは、たま〜にありますね。
「ライブラリ選定したのお前だろ!お前のプログラムのバグだろ!」というご意見もある意味もっともな感じもします。
プロプライエタリ*7なやつだと、「これはベンダーがなおさないとなおらない」という逃げ道がとれることがあります。


・改修、バグ修正、機能追加が大変
・そんな古いライブラリだれも使い方わからない
・つくった人しか直し方が判らなくなる

このあたりは「えっ、今後も貴方がやるからいいでしょ?」といわれる事が多いですね。
しかしお客様、私がこのサービスと添い遂げられる保障はどこに入っているのでしょうか。明日にも私がいなくなるかもしれないじゃないですか。

「私、しばらくお暇を頂きたく思います、理由は入院です」というのが通らなかった経験のある人間からすると、やはりそこらへんの感覚の違いみたいなものがあります。会社であっても担当がかわったら話にならんのですよ。
大手SIerみたいなのは、そう言う人間性を抹消 属人性を抹消する所にめっちゃカネかけてるのでよいですが、そういう(実)人月200万の世界と比較されたらつらい。


「作った物の面倒は最後まで見る」とてもよいお言葉です。
しかし私も営利でやっております故、どうしてもミスマッチしたりしてきたらまじどうしようもないですし、そうなったら困るのは、結局恨まれる私とお客様と丸投げされた次のエンジニアです。Lose-Lose-Loseで一人増えてる始末。

私は「あいつ逃げやがった!」と恨まれ、ババをひかされたエンジニアは途方に暮れるしかなく、進捗しない物を前にお客様がお困りになります。
なので、どうしようもないコードにならないように、比較的鮮度を保った状態にしておく事は重要なのです!!


…などという演説を打ってみたいですが、恐らく「そうだね(笑顔)」の一言でおわりますので残念ですね。


ただ、さらにがんばって説明してお客さんがキレると、もしかすると賞賛の言葉をいただけるかもしれません。

「お前なんざ取り替えがいくらででもきくんだ!」

どうでしょう?もの凄く魅力的な言葉です。
私の作業が他のエンジニアと取り替えができる、つまり私のコードは誰にも読めるコード。すごい賞賛です。


まあ、現実として15年前のCGIも価値を届けていますし、(放置で)事もたりることが多いので、諸々のバージョンアップが必要になるかは割と確率論でしかなく、「ほんとか!保障できんのか!?」といわれたときに理系であれば即答できないのは仕方がn(以下略)

話がめっちゃずれた、もどしましょう。

追従するにはどうするか

大体の場合、バージョンアップでつらいのが「ぶっこわれているのか誰もジャッジできない状態になる」のと、「バージョンアップとかしらんし、やりたきゃ保守費用範囲でやれ!ぶっ壊れてたらおこ!」という、我々の狭い常識からは遠い、平均的なお客様です。

前者はテストが完璧なら、ぶっこわれているかはかなりの確率で気付く事ができます。
後者は前者が完璧なら(作業コストについて以外は)訴訟が回避しやすくなります。
保守費用をたんまりもらってCIをまわしつづける、というのもまあそんな悪くない。


つまりテストをぶんまわしまくれば、ドンドン改造しても壊れていない事を担保できるはずので、将来的が最高です。まあ、こんなのは常識ですよね(完璧なテストが書けるかどうかはさておくとして)。

だもんで、マットウな人はもう「覚悟完了」とかいいつつ超テスト書いて超ぶんまわしてCIだ!って世界になってるっぽいわけですが、ゆるふわPHPだとまだそういう機運はごく一部なのは皆様のご想像の通りです。

まあ、PHPerですから、期待されているのはラピッドに安く上げてナンボみたいな所はあるわけですよ。重厚長大、安全第一とかそういうのはジャヴァーとかにまかせる!

「この機能三日でつくってください、PHPでいいです」
「…三日だとテストとかできないんですけど」
「あっ、そんなのうごけばいいんですよ〜〜(笑顔」
「そうっすか…(まあこれ1ヶ月くらいしかつかわれないだろ」

「あのサービス、あと10年はまわしますんで!(力強い笑顔)あっ!このスーパー機能実装してください!今回は倍の日数6日で!」
「(死んだ」

という現実。

自動テストとかの部分を工数にいれると、どうしてもお客様は「いいからうごくように作ってよ、なんでテストがいるの?ブラウザで確認、エクセルに羅列!」とカジュアルに削られますし、「それは君の手抜きのためだろ」と言われた事もリアルに有ります。

実際には、テストはコードの価値を高めるという事で、Win-winの筈なんですが、目の前に確定されたお金と未来の不確定のお金であれは、前者を確保するのはビジネスとしてみれば堅実だといえるかもしれません。
まあ「シレっとのせとけ」というのがベストアンサーな感じもありますが、なかなか昨今の出精値引き、徹夜進行ではそこまで価値を上乗せしづらいですね…。


さて、また話を戻しますが、テストをやるってのはもう手放しに良いことですが、それでもデカいバージョンアップやると半人殺しくらいになります。なのでもっと差分を小さいバージョンアップして欲しいですよね。

でもフルスタックのフレームワークだと、そういうのってむずかしいんですよね。
バージョンは有る状態を指し示すわけですが、「ここのクリティカルな機能だけ最新版に」というのは、バージョンが振られたソフトウェアでは不可能に近いと思います。(ちぇ、CherryPick?)

Perl的な解決策

そこで、Perl的な文脈だと、疎結合にして、ステップだけでは無く、細かいモジュールでバージョンアップしていく方策があります。

Perlで有名なWAFというと、Mojolicousや、Amon2があります、後者は日本発のWAFですね。
Mojoはわりと他の大フレームワークと同じような思想ですが、Amon2は変わっていて、なんというかAmon2というWAFは概念上の存在であり、実在していません(いいすぎ)。

Amon2は細かいライブラリの寄せ集めたものをWAFのような形にくみ上げたスゴ腕が考えたベストプラクティス、だと私は思っています。

他のPerlライブラリ(モジュール)もわりとそういう思想になっているものが多くあります。CPAN最高!


なので、細かい部品はわりとガンガン書き換わっていますが、最初にAmon2を「くみ上げた時」から先においては、それぞれのライブラリをバラバラにバージョンアップし続ける事がバージョンアップになります。
ここで機能単位で上げていくのはテストする範囲が限定できますし、着実に歩を進めることができてとても良い。

あと、最悪追従するかを部分で選択できるのもよいですね。
たとえば、セキュリティ系の部分とか、ルーターの部分とか、インターフェイスがかわっていなければドンドンあげたいし、DBの部分でどうしてもロジック上簡単に移行できない所は、とりあえずバージョンを維持する、という事もできる。

このスタイルは個人的にとても感銘をうけております。
そういう概念上の存在、「非実在性WAF」みたいなのは個人的にかなりよいな、と思って居ます。


「これしかないんだ!これが最高なんだ!」というスタイルは、今日も明日も明後日もこれをつかうことが総コスト的に低い、というのがあるんですが、メジャーバージョンが上がったら結構死にます。

あと、パーツバラバラだと、今回はこれとこれとこれだけつかうわ〜、とできるのも最高です。ハヤリを取り入れたり捨てたりが柔軟にできるのがオシャレですね、バッチとか書きやすい!

他にも、一枚岩で融合的になっていると「ここの機能ちょっとかえたいんだよなー」とWAFに手をいれることは非常にダルくなります。WAFに手をいれるとか!?みたいなのありますが、やっぱあるじゃん。

元日にULしたSlimのMockとか本当はもっと良い感じにしたかったけど、なんかめっちゃ色々Slim本体に手をいれないと解決できない感じで、(俺では)ああならざるをえなかった*8


そこらへん、疎結合がんばってるなと思うのはZend Framework 2なんですが、あれは…なんというか…文字数が多い…w

また、LaravelってやつがあたらしめでDIつかいまくりでやったろうぜ!みたいなノリなのかなって思ってますが*9。あれがもうちょっとバラバラになってくれないかなあ…などと猟奇的な事を考えたりもしています。*10


バラバラであることのよさはやっぱりテスト性の良さにつながりますね、上のもテストの為の悩みだったので。モノシリックだとモックとか作るのが本当にめんどうくさい。
内部的にはバラしてあるんだけど、やっぱり外部から手を突っ込むことまでは考えて居ないのでつらいですね。(そこらへんZF2は考えてるけど…文字が長(略))


欠点も勿論あります、学習が大変です。
「それしかない」という理由でPerlだとみんな○○モジュールの使い方しってるよね、ってなるけど、WAFとかだとドキュメントが統一的にまとまってないと、結構つらい。
なので、これも逆説的に(ある程度腕がないといけないという)属人性がでちゃう感じですよね。


まあここらへんが今日のエントリの最大の穴というか、オチがつくところであり。
厨二っぽい、しょうもない一個人が正月にダラダラ書いた雑文である、ということで一つ。

まとめ

つまり何が言いたいかっていうと、そろそろPHPにもSQL::Makerみたいなやつと、Router::Boomみたいな良い物がでてほしい(小学生並みな感想)、そういうのが広まって欲しいですね。


ちょっと前まではMechanizeみたいなのがほしい〜って思ってましたけど、Goutte、Gazzeleあたりがあったのでなんとかなりそうになりました。
が、やっぱルーターの良い感じのがまだみつかってない。Slimだとpimpleと組み合わせる、みたいな例があるけど、あれはルーターではない…。


ORMも、なんだかんだ数だけは色々あるけど、しんじゃった奴(ActiveRecordとか)や奇特なやつ(RedBeanとか)が多すぎたり、設計が古くさかったりして選びづらい。
結局つかわれてて、テストされてて、信頼できるやつは、フルスタックの奴の中に埋め込まれたやつか、でっかいやつしかなくて、ダルいので単体でもっと出てきて欲しい。

つよいこころで

とりあえず、個人的にはPHP5.3以下のレガシー案件はできるだけ請けない感じにしてこうかな、と思っています。(が、現実的には無理そう)

後、「テストとかいらないです〜〜前日にボクがポチポチするから!!」みたいな案件も本音を言えば減らしたい*11
しかしお客さんから見たらテストって単なる値上げなので、通りづらいのですよねー。


2013はレガシー案件と丸投げ案件に苦しめられて、エンジニア的な楽しさが少なかったのと、
どうにもPHPが不当にいじめられている気分がさらに深まって(まあ、理由も理解できるんですけど)とても寂しいし、
かといってPHPJavaにしていく!みたいな個人的には理解できない方向にもあまり行きたくなく、
色んな言語からパクりつつ、PHPっぽく、ザーっとかいてババーン!みたいなのをもうちょっと良い感じにやって、楽しい感じになりたいですね。


あ、あと、PHPの勉強会にいきたい。


以上です。

パーフェクトPHP (PERFECT SERIES 3)

パーフェクトPHP (PERFECT SERIES 3)

*1:実際5.4以下だとうごかないか、書き直し必須なスタックです

*2:タレをつかったほうが工数少ない事の方が多い気もしますが、まあ…

*3:中身なんてどうでもいいタイプの人にはどうでもいいですが、必要に迫られる事あるじゃないですか…

*4:だからこそ俺はPHPを最新版を使い続けるべきだとおもうのだが「後1年つかえるから〜〜」という理由で新規で5.3を入れる人は苦行好きなのかと…

*5:見積もりと見合わないので

*6: throw spoon

*7:か、それとの差異が一般人にはわからない程度に誤認するほど有名なOSS

*8:$app->post()でパラメタ取ってくるまわりとか、php://input周りから取るか$_POSTにフォールバックするかみたいな…、あとミドルウェアのCSRFDefenderが…(まあこれだけなら書き直しても良いのだが)

*9:今のスタックも、LaravelのORMだけつかっています

*10:なんでLaravelをつかっていないかというと、結構凝っていて、前のスタックからの乗り換え(学習)が大変な感じだったので

*11:1年たったらFA宣言!みたいな契約ならいいけど、「フリーランスつかえない!」とか増田あたりでいわれちゃいそう