もともとPHPをメインにWEBアプリケーションの開発をしておりましたが、転職を機にRubyの世界に足を踏み入れました。
約1年ほどRubyの世界に浸ってみて、「PHPだったらこうだったのに」というのを__N番煎じだ!__とか言われないようにピックアップしてみます。
忙しい人向けのまとめ
- アプリケーションサーバーは言語が持つか、言語で実装されるかの違いだ、PHP書いてるやつは取り敢えずphp-fpmを触りなさい
- Rackと聞いたらPSR-7を思い浮かべなさい、Rackはそれにちょっとばかり実装を足したものだ
- RubyはThreadが使えるけど、IO関連の処理にしか効果はない
- オープンクラスは素晴らしい
- オペレーターメソッド/オペレーターオーバーロードは素晴らしい
- メソッドの関数化を覚えておくと、Ruby書いてる気持ちになれる
- IDEはPHPのほうが優れているので、Rubyの言語機能とのトレードオフと割り切るべし
- PHPで言うインターフェースは無いよ
アプリケーションサーバー
WEBアプリケーションエンジニアとして、PHPからRubyの世界にスキルチェンジをすると大抵のエンジニアはアプリケーションサーバーという存在に驚きを覚えるそうです。
しかし、ここで驚きを覚えるようではPHPのことを理解していなかったと言われても仕方ありません。
PHPの場合は、言語自身がアプリケーションサーバーという概念に相当するもの(php-fpmですね)を所持しています。
PHPでは言語自身が持っている、RubyではRuby自身で実装されていると認識しておけばよいでしょう。
一応、PHPにもPHP自身で実装されたアプリケーションサーバーは存在しています。
Rackインターフェース
RubyではRackというWEBサーバーとアプリケーションのインターフェース(正確にはインターフェースだけではないが、それは詳しく知りたい人が調べて下さい。)が存在しており、Ruby製のアプリケーションサーバーは殆どがRackのインターフェース仕様に沿って作成されています。
PHPでは言語自身がアプリケーションサーバー相当のモジュールを含んでいるため、このようなインターフェースはあまり目立つことはありませんでした。
しかし、最近PSR-7というHTTPとのインターフェースはこんなふうに実装しようという規約が登場し、PHP自身でアプリケーションサーバーを実装する機運が高まっています。
Rubyにスキルチェンジした時に、PSR-7を抑えておけば、「Rack?あぁ、PSR-7みたいなやつね」といった感じにすんなり概要を掴むことが出来るでしょう。
Thread
PHPでは、threadという概念を気にすることがありません。
PHPでは特別なことをしない限り、threadを扱うようなコードを書くことが出来ないためです。
PHPで処理を並行に走らせたい場合はプロセスをフォークすることになりますね。
一方でRubyではthreadを扱うコードを書くことが出来ます。
Rubyのthreadは通常、GILというロックがかかっており、threadを複数利用したからといって処理を並行に走らせることは出来ません。
しかし、Rubyのthreadには__IOに関する操作を行った場合に、GILを開放する__という条件があり、
IOに関する処理の場合は、並行かつ省メモリに処理を走らせることが可能になります。
IOに関係のない処理であれば、PHPと同じようにプロセスをフォークすることになります。
Rubyでは並行処理を行いたい時、その処理がIOに関連するならthreadを使えば省メモリで済む!ということを覚えておくと何かと便利です。
オープンクラス
これは、Rubyで僕が最も気に入った機能です。
Rubyでは既に定義済みのクラスと同じクラスを作成すると、その定義済みにクラスに機能を追加・変更することが可能なのです!
素晴らしい!!
何が素晴らしいかというと、PHPではComposerを利用してライブラリをインストールすると思うのですが、これらのライブラリにバグがあり、直ぐに修正したい時、下記のようて手順を踏むと思います。
- ライブラリのリポジトリを自分のところにforkして修正
-
composer.json
の問題のあったライブラリのインストール先をforkしたリポジトリに変更 - 再インストール
- 本家のほうへプルリク出す
面倒ですね。
Rubyの場合は、オープンクラスでライブラリも修正出来るので、問題の発生しているクラスと同名のクラスを作成し、修正を加えるだけで済みます。
ちなみに、refineという機能を利用すれば、クラスの拡張・変更を部分的に行うことも出来るので、グローバルに変更出来るの気持ち悪い!という方でも安心です。
PHPからRubyへ鞍替えした暁には、あの面倒な手順とおさらばですね。
オペレーターメソッド/オペレーターオーバーロード
Rubyではメソッドとして定義することが可能なオペレーターが存在しています。
メソッドなので、当然オーバーライドして機能を書き換えることも可能です。
これは、特定のオブジェクトのドメインに対して、理解し易い記述を可能にすることが出来ます。
例えば、RubyではActiveSupport
というライブラリを利用すると下記のような日付の加算、減算処理が出来るようになります。
require 'active_support'
Date.new(2016, 1, 1) + 2.days # => 2016/1/3
Date.new(2016, 1, 1) - 1.month # => 2015/12/1
なんて分かりやすいコードだろう!
PHPだと、DateTime
とかDateInterval
など色々持ち出さないといけないというのに…
(Rubyの外部ライブラリの機能とPHPの標準ライブラリの機能を比較するのはフェアでは無いかもしれないが、それでもRubyの記述の簡潔さはPHPには真似できません。)
日付にかかわらず、体重や身長など数字に関するオブジェクト等にオペレーターメソッドを定義するのはコードの可読性を大きく向上させますし、
オペレーターを上書きすることで、shellのパイプ演算のようなことを実現することも出来ます。
PHPだと文字による表現に頼りきりですが、Rubyでは記号も含めて可読性の表現を考えることが出来るようになります。
メソッドの関数化
Rubyでは自身の持つインスタンスメソッドを:[method name].to_proc
としたり、
クラスメソッド(PHPでいうスタティックメソッド)をClass.method([method name]).to_proc
とすることで、プロックオブジェクト(PHPでいうところの無名関数)として取り出すことが出来ます。
覚えておくと、Rubyでコードを書く幅がとてつもなく広がります。
RubyMineはPhpStormほど親切ではない
ここまでいいところばかり書いてきたので、気に入らない点を書いておきましょう。
PHPで開発するなら、PhpStromという強力なIDEが存在していますが、
Rubyでは同系列の製品にあたるRubyMineがPhpStormほど強力ではありません。
Docコメントを書いても、補完が効くわけでもなく、もともとの補完の機能もなんだか弱い…
これはRubyの高度な言語機能によって、払う対価だと思って諦めるしかありません。
PHPで言うインターフェースがない
この話をしたら、Rubyはダックタイピングだからと言われましたが、「このオブジェクトはこのメソッドを実装するべきだ」という警告が欲しいのですよね。
モジュールのインクルードあたりで実現出来そうな気もしているのですが…
ということで、PHPからRubyに鞍替えするときに知っていれば怖いものなしな点について、独断と偏見でピックアップしてみました。
きっと、この記事を読んだならばRubyに対する恐怖は消え、
「PHPでもRubyでもどんと来い」
と言えるようになっているでしょう!