PHP・⌒ ヾ(*´ー`) ポイ Rubyist is better than PHPer

このエントリーをはてなブックマークに追加

タイトルに惹かれて来た方には申し訳ないのですが、記事を全面的に改訂致しました。タイトルと中身の直接的な関係性はまったくありません。どうしても旧記事が見たい方はタイトルでGoogleにて検索していただくと、魚拓や派生記事が見つけられるかと思いますので、そちらをご覧ください。また、旧記事をご覧になった方には、不快感を与えてしまったことを深くお詫び申し上げます。

はじめに

まずはじめに、この記事を読んでくださりたい方のセグメントを記載いたします。

  • PHP言語(フレームワークなし)でHTML+CSS+PHPのサイトを構築されている方
  • CodeigniterなどのPHP言語用軽量フレームワークのみを用いて開発をされている方
  • 新しいウェブ系プロジェクトをはじめようとしているプロデューサー、経営層の方

逆に、読んでも無駄になる可能性の高い方のセグメントを記載いたします。

  • 「設定より規約」に準じることにより開発効率の向上を図っているフレームワークを利用されている方
  • 言語やフレームワークにとらわれず、技術選定を行い、開発をされている方

フレームワークとは

フレームワークというのは使わなくてもウェブサイトは構築できます。フレームワークを使うためにはフレームワークのドキュメントや仕様の熟知が必要です。そのためにはそれを熟知するための時間がかかります。にもかかわらず、なぜフレームワークが浸透しているのか。それは、フレームワークが開発速度を向上させるからです。

フレームワークとはツールボックスです。開発者が日常的に使うソースコードを再度自身で書き直す必要性がないよう(DRY思想)、それらがオープンソース・コミュニティに貢献するたくさんのエンジニアの方々の手によって開発されています。フレームワークは、同じ言語を用いるエンジニアがそれぞれ議論しながら作り上げた素晴らしいツールボックス、プロダクト、技術です。

一応、フレームワークについてWikipediaより引用いたします。

Web アプリケーションフレームワーク(ウェブアプリケーションフレームワーク、Web Application Framework)は、動的な ウェブサイトWebアプリケーションWebサービス開発をサポートするために設計されたアプリケーションフレームワークである。 フレームワークの目的は、Web開発で用いられる共通した作業に伴う労力を軽減することである。たとえば、多数のフレームワークがデータベースへのアクセスのためのライブラリや、テンプレートエンジン(→Webテンプレート)、セッション管理を提供し、コードの再利用を促進させるものもある。
http://ja.wikipedia.org/wiki/Webアプリケーションフレームワーク

フレームワークによる恩恵

フレームワークが提供している機能とその機能によって解決された課題を紹介していきます。今回は最近PHPで話題のフレームワークであるLaravelの提供機能を参考にしました。

RESTful Routing

フレームワークがない世界では、「index.php」や「about.php」など、各ページごとにファイルを作成していました。そして、それらのファイルでは、いずれのファイルでも、データベースに接続したり、毎回ほぼ同じHTMLのHEAD文を書いていたりしました。

それを、MVC構造という概念が変革しました。データはModelが扱う。ロジックはControllerが扱う。ビューのレンダリングはViewが扱うというものです。ここでもWikipediaから引用します。

MVC(Model View Controller モデル・ビュー・コントローラ)は、ユーザーインタフェースをもつアプリケーションソフトウェアを実装するためのデザインパターンである。
アプリケーションソフトウェアの内部データを、ユーザーが直接参照・編集する情報から分離する。そのためにアプリケーションソフトウェアを以下の3つの部分に分割する。
model: アプリケーションデータ、ビジネスルール、ロジック、関数
view: グラフや図などの任意の情報表現
controller: 入力を受け取りmodelとviewへの命令に変換する
http://ja.wikipedia.org/wiki/Model_View_Controller

MVCに分割されたことによって、URLとファイルが1対1の関連性を失いました。これにより、Routingが必要になりました。Routingによって、URLと複数のファイルを制御し、URLと出力を関連させることが可能になりました。RESTについても紹介したいところですが、長くなるため、Wikipedia:RESTを参考ください。

多くのフレームワークでは、Routingの規約を規定しました。それにより、それぞれのフレームワークにおいては、Routingの書き方が統一されました。また、個々人が書く必要が書くコード量が削減されました。

たとえば、下記のようにRoutingを書くことが出来ます。

Route::get('user/{id}', 'UserController@showProfile');

ファイル名を指定する必要などもなくなりました。また、GETアクセスかPOSTアクセスか、引数はあるのか、ないのか、といったコードを記載する必要もなくなりました。DRY思想に基づかないコードと比較すれば、数十行以上はコードの短縮が行えたはずです。

また、フィルター機能など、フレームワークのRouting機能はより便利になりました。

URLと出力結果を記載するルールを定めるという制限により、記載する必要があるコード量が圧倒的に削減、開発速度が向上しました。

Command Your Data

Ships with the amazing Eloquent ORM and a great migration system. Works great on MySQL, Postgres, SQL Server, and SQLite.

ORMとMigration systemというものが作られました。ORMとは、下記のようなものです。

オブジェクト関係マッピング(英: Object-relational mapping、O/RM、ORM)とは、データベースとオブジェクト指向プログラミング言語の間の非互換なデータを変換するプログラミング技法である。オブジェクト関連マッピングとも呼ぶ。実際には、オブジェクト指向言語から使える「仮想」オブジェクトデータベースを構築する手法である。
http://ja.wikipedia.org/wiki/オブジェクト関係マッピング

基本的にデータはMySQL、Postgres、SQLiteなどの「データベース」に保存することが多いです。しかし、データベースを直接プログラミング言語上で取り扱うことは容易ではありません。そのため、SQL文を用いて、データベースとのデータのやりとりを行ってきました。

一部、「SQL Injectionの仕組みと対策」から引用しています。

たとえば、ユーザの検索を行う場合は下記のようなコードです。

SELECT userID,userName from userTable where userID = 20060001;

ただし、userIDは可変ですので、その部分を変数化することがあります。変数化した部分をユーザのブラウザから受け取ることがあります。

ここで、下記のように書いてしまうと、まずいことが起きます。

渡された[データ1]をuserに代入する
sql = "SELECT userID,userName from userTable where userID = " + user + ";"
[SQL文「sql」の実行]

ユーザがSQL文の内容に介入出来てしまうのです。それにより、データを破壊したり、漏えいさせたりすることが可能です。これを防ぐためのコードを従来、多くのエンジニアが書いてきました。

しかし、ORMにより、ORMのコードの中でこれらのSQL文の生成を行うことで、SQLInjectionへの対策などのためのコードを書く量は大幅に削減されました。

また、それ以外にもたくさんの効果があります。たとえば、データベースサーバがMySQLから別のデータベース、たとえばPostgresに途中で仕様変更されたとしたらどうでしょうか?今までたくさん書いてきたSQL文の多くを書き換えないといけないのはほぼ間違いありません。

しかし、ORMがそれらのデータベースに対応、SQL文を抽象して書くようにしていれば、ORMがその差分を吸収し、発行するSQL文を変更してくれます。エンジニアは「データベースはMySQL」といった設定を記載するだけで済みます。これもまた、非常に大きな開発効率の向上につながります。

SQL文の抽象化のためには、「モデル」が使われています。たとえば、userをUsersテーブルからIDをもとに検索するのであれば、Laravelであればおそらく下記のようなコードになります。

$user = User::find(1);

SQL文を記載する必要はありません。また、データベースから帰ってくる値はUserクラスのオブジェクトとしてコードの中で取り扱うことが出来ます。そのため、Userクラスが保持しているメソッドなどを実行することが可能です。

少し話がそれますが、CakePHPフレームワーク2系では返り値はUserクラスのオブジェクトではありません。

$user = $this->User->find('first', array(
 'conditions' => array('User.id' => 1)

返り値はArray型として返されるため、Arrayクラスの持っている機能のみしか使うことが出来ません。これにより、Userを扱うControllerやViewなどでUserに関する定型化された処理を行いたい際に、工夫が必要になります。

この工夫を書かなくてよくなった。また、記載するコードの行数自体が少なくなった点などが、Laravelが「Ships with the amazing Eloquent ORM」と謳う要因のひとつでしょう。

 

「great migration system」については、データベースのスキーマをマイグレーションすることが出来るシステムを搭載している、ということでしょう。直訳ですが。

モデルクラスのコードが変更された場合、データベースのカラムの変更が行われることは少なくありません。データベースの変更にはSQL文を伴いますが、migration systemにより、データベースの変更もSQL文を用いず、Migrationのためのコードを書くことで、データベースの変更を行うことが出来ます。また、バージョンをさかのぼる(データベースの変更の履歴を巻き戻す)ことなども可能になりました。データベースエンジンの変更への対応なども、SQL文の抽象化による効果でより容易になりました。

また、複数人でプログラミングを行っている場合、データベースの変更をすべてドキュメントで管理し、変更があるたびにそれぞれがドキュメントを元にSQL文を発行するのも一般的でした。しかし、これもLaravelでは非常に効率化されています。最新のデータベースのスキーマにしたい場合、下記のワンコマンドでデータベースを最新の状態に変更することが可能です。

$ php artisan migrate

Composer Powered

LaravelではComposerに対応しています。(他フレームワークでも対応しているものは多いです)。Composerはライブラリの依存関係管理ツールです。ライブラリの依存関係を管理してくれるのはもちろん大きな機能であり、開発効率の向上につながるものです。

それ以外にも、ほかのエンジニアが書いたライブラリが使える、というメリットもあります。ライブラリの依存関係が管理されていなかった時代や、ライブラリの書き方などが統一されていなかった時代、ライブラリの置き場所が定まっていなかった時代では、ライブラリを検索し、導入し、用いることは簡単ではありませんでした。

しかし、今はComposerにより、ライブラリを探し、そのコードを読み、有用であればそれを利用することが出来ます。そのコードを書くはずだった時間を別のことに費やすことが出来ます。これによって、非常に大きな開発効率の向上を受けることができるようになりました。Composerについては別記事でも紹介させていただきました。

フレームワークの変遷

フレームワークが提供する機能は時代とともに増加、移り変わってきています。先ほどの例ではCakePHP2系ではORMによるfindの返り値がArrayでしたが、Laravelではオブジェクトになりました。また、CakePHPも3系ではオブジェクトに変更される予定です。

Composerやdb migration、ORMの機能、多くのものが移り変わり、より多くの機能がフレームワークによって提供されるようになりました。また、それによって、開発効率の向上が行われてきました。

フレームワークは特定のプログラミング言語で作られており、その言語の仕様に依存しています。そのため、新しいフレームワークなどでは、その言語の古いバージョンには対応していないケースが多いです。これはまた、フレームワークだけでなく、プログラミング言語も向上してきた、ということでしょう。

既存プロジェクトのフレームワークの変更

フレームワーク利用して開発したプロジェクトの場合、フレームワークの規則に従ってコードを書いています。そのため、フレームワークを変更することは容易ではありません。そのため、フレームワークを独自拡張したりすることもよく行われています。

フレームワークの変更は容易ではないことから、選定は慎重に行う必要があると考えます。開発効率を優先するのか、今持っている知識でそのまま使えることによる学習コストの低さを優先するのか、実行速度を優先するのか。それは人やプロジェクト次第かと思います。適切なものを選択する必要があるだろう、ということだけは確かであると思います。

今から始めるプロジェクトではどうすべきか

プロジェクトの性質やゴールなどにより十分に選定しましょう。もしかしたら、そもそも開発はする必要はなく、WordPressのカスタマイズだけで済むかもしれません。

数行しかコードを書く予定がないのであれば、フレームワークを使わないという選択肢もあります。

非常に多く書く必要性が目に見えている場合は、目先の学習コストという費用ではなく、将来的な開発効率のために、学習という投資を行い、開発する過程で効率にてその投資を回収するのが良いかと思います。

JavaScriptによるウェブサーバ、Node.jsなどは、WebSocket通信が非常に得意であり、リアルタイムにユーザ・クライアントと通信を行うのであれば、Node.jsを選定するのが良いという、プロダクトの性質上の選定も重要でしょう。

フレームワークや言語は安易な選定を行ってはならないものであると思います。安易な選定を行わないためには、現状枯れている(安定して動作している)フレームワークをそれぞれ触ってみる、ドキュメントを読んでみる、コードを読んでみるなどが必要でしょう。

フレームワーク選定の問題点

新しいプロジェクトに特化している組織である「スタートアップ」ではプロトタイプを作る速度が優先され、フレームワークを選定するための十分な時間が得られないことがあります。また、顧客の要望に応じてソフトウェアを開発、納品するスタイルの場合でも、顧客へは「人月」として請求し開発したソフトウェアを納品するスタイルが広く使われています。この場合でも、納品後は改善・保守しない場合、納品後も「人月」で請求する場合、開発効率は直接的に企業の利益には貢献しません。そのため、やはり、フレームワークを選定するための十分な時間が得られないことがあります。

フレームワークを選定することが実質的にできない、というのはエンジニア不足が嘆かれる昨今では、非常にもったいなく思います。ソフトウェアを開発する人・業界全体として、開発効率の向上のためにの将来的な投資、つまり、エンジニアの成長への投資を行っていく必要があると考えます。

結論

目先の開発速度ではなく、全体を通して適切なフレームワーク・言語を選定してほしい。また、フレームワークや言語、技術などを適切に選定するために、エンジニアに勉強する時間を与えて欲しいと思います。

なぜタイトルがRubyistとPHPerの比較だったのか

Ruby on Railsは「設定より規約」による開発速度向上のフレームワークの先駆けであり、毎年のようにメジャーアップデートが行われ、開発速度が向上していきました。しかしながら、受託開発ではRuby案件よりもPHP案件が非常に多く、PHP案件ではCakePHPやCodeigniterなどが主だって使われているという現状がありました。PHP言語とRuby言語のそれぞれのエンジニアの比較を行ったわけではありません。ウェブサービスの開発におけるフレームワーク利用のための学習コスト(アップデートへの追従など)への投資がRuby on RailsがPHP言語のフレームワークりも多い、というところに起因します。

また、内容が重複しますが、PHPがやはり非常にメジャーであり、それに起因した、「とりあえず」でのフレームワーク選定が多いように見かけられたことが記事記載のトリガーとなりました。

「Rubyist is better than PHPer」については、Ruby on Railsを利用するエンジニアがPHP言語の軽量フレームワークを利用するエンジニアよりも多くの学習コストを支払っている可能性は高いと考えての記載です。実際のところ、優れたPHPプログラマはRuby言語もPerl言語も書けるでしょうし、Rubyプログラマも同様にPHPも書ける。学習コストを支払っているかどうかのみが争点です。

「PHP・⌒ ヾ(*´ー`) ポイ」についても、古いバージョンのPHP言語のみを使うことは避けたほうがよいだろうと考えての記載です。PHP言語自体をポイする気持ちはありません。また、PHP5.3、5.4からは大きく言語自体が変わってきていると考えています。

最後に最近は安易にRuby on Railsを選定するスタートアップも多くなってきているため、それについても、どうなんだろうという個人的な感覚だけ記載して、本記事を終わりとさせて頂きたく思います。

ぜひ皆様もご意見をコメントにていただければと思います。

このエントリーをはてなブックマークに追加

コメントを残す