新規サービス・ハコベルをPHP/CodeIgniterからRuby on Railsに移行しました


こんにちは、ハコベルの開発を担当している蟻塚です。

2015年12月ハコベル正式リリースの少し前に、PHP/CodeIgniterからRuby on RailsのWAFの移行を行ったのでその際の話を書かせていただきます。
個人的にこっそり調査1ヶ月、業務時間フルで1ヶ月、延べ2ヶ月程度でメイン部分を移行して、その後1ヶ月で残タスクを消化といったスケジュール感でした。

経緯

もともとラクスルでは、シンプルなサイトはPHP/CodeIgniterで作っており、ハコベルもそれに則って作られていました。
私はベータリリース後間もない2015年9月頃にハコベルチームに参加しました。

それ以前はフルタイムでハコベルにコミットしているエンジニアは0人で、入れ替わりでいろんなエンジニアさんに手伝って頂いていました。
これは今でも変わらないのですが、ラクスルだけでもエンジニアの人数が圧倒的に足りておらず、なかなか新規事業のために人を割けないという事情によるものです。ちなみにハコベルチームは最近やっと増員されてエンジニア2人になりました(笑)

そういう事情もあって、僕が参加した頃のハコベルにはいくつか問題がありました。

  • 複数人で開発していたため、設計方針に一貫性が欠ける部分があった
  • コントローラーにロジックが書かれがちだった
  • CodeIgniter自体はシンプルだが機能が少なかった。O/Rマッパー等が標準でないのが辛かった。
  • 一部のライブラリが安全性の低い作りで、不具合を誘発しやすかった
  • テストコードが一切なかった

プロジェクトに参加した当初は郷にいっては郷に従おうと思っていたのですが、
日々の運用の中で、メンテナンスに苦労する点が多々あり、フレームワーク自体への不満もけっこうありました。

また私が参加したタイミングもちょうどよく、

  • ベータ版の運用試験中で機能追加等の要求が低かった
  • まだ機能自体が少なく書き直しが現実的なコストで実現できそうだった

等々あって、参加して1ヶ月くらいで、思い切って書き直しを検討することにしました。

-> % bin/rake stats
+----------------------+-------+-------+---------+---------+-----+-------+
| Name                 | Lines |   LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Controllers          |  2678 |  2256 |      72 |     335 |   4 |     4 |
| Helpers              |   110 |    97 |       0 |      14 |   0 |     4 |
| Models               |  2583 |  2023 |      47 |     282 |   6 |     5 |
| Mailers              |   235 |   188 |       5 |      30 |   6 |     4 |
| Javascripts          |    16 |     0 |       0 |       0 |   0 |     0 |
| Libraries            |     0 |     0 |       0 |       0 |   0 |     0 |
| Controller tests     |  1180 |   961 |      61 |       2 |   0 |   478 |
| Helper tests         |     0 |     0 |       0 |       0 |   0 |     0 |
| Model tests          |   385 |   272 |      28 |       0 |   0 |     0 |
| Mailer tests         |   115 |    88 |       5 |      15 |   3 |     3 |
| Integration tests    |     0 |     0 |       0 |       0 |   0 |     0 |
+----------------------+-------+-------+---------+---------+-----+-------+
| Total                |  7302 |  5885 |     218 |     678 |   3 |     6 |
+----------------------+-------+-------+---------+---------+-----+-------+

※リリース時点でのstatsは上記の通りでそれほど大規模ではなかったのが幸いでした。

プロジェクト開始まで

とりあえずまず賛同してくれそうな人を見つけようと思い、CTOの泉に相談しました。
CTOは言語に関しては、多様性を認める方針だったのであっさりOKしてくれました(笑)

その流れで、他のエンジニアだったり、ビジネスサイドに提案をしました。
弊社の場合、そういった部分に寛容なところもあって、OKがもらえました。

ただ、期間に関しては多少無理して、1ヶ月でやり切ると言いました。
数ヶ月も開発止めるとなると、それが本当に必要であったとしても、普通は決断できないので、多少無理は必要だと思います。
(といいつつ延べ2ヶ月ぐらいはかかりましたが..笑)

なぜRailsを選んだのか

  • 社内でPHPのフレームワークが2種類使われていたので、WAFを変更するならPHP以外にしたかった
  • ラクスルでの経験からハコベルのようなサイトでは負荷や速度の問題がほとんど発生しなさそうだった
  • 生産性が高いことが重要だった
  • ここ1,2年の間は10人以下での開発が想定されていた

深い理由はなく、生産性やコミュニティが活発だという点でRailsにしました。最近だと、scalaを採用しているところもよく聞きますが、scalaを選んで短期間で書き変える知見がなかったので、確実性のあるWAFにしました。

進めるにあたって注意したこと

移行にかける期間が長くなればなるほど不都合があるので、ミニマムで移行してしまうことを最重要視しました。

javascriptの構成変更しなかった

railsのasset pipelineは一切使いませんでした。javascriptの構成変更は、移行が完了してから、ちょっとずつ行うようにしました。

DBのスキーマ変更をしなかった

timestampのカラム名がcreated_atとは違う名前でしたし、サロゲートキーが貼られていないテーブル等がありましたが、ほぼそのままで移行しきりました。
一部サローゲートキーがないと動作がおかしくなった箇所があったのでそこは修正を入れましたが、スキーマもなるべくそのままで移行しました。
※落ち着いてからカラム名を変更したり、単数形のテーブル名を複数形にしたりしました。

バッチや、一部ドメインはしばらくPHPで動かして後々に移行した

DBスキーマをほぼ変更しなかったので、メインのコードはRubyで動かして、あまり重要でないバッチや、一部サブドメインのコードはPHPのままで運用していました。
メインサイトの移行後、1ヶ月ぐらいかけて順々に移行しました。

移行以外のタスクは徹底的にやらない

移行以外のタスクは徹底的に断るようにしました。もちろん重要なものはやるべきですが、それほど重要でないと判断されるものは徹底的にやらないようにしました。

移行の際にネックになったこと

思ったよりネックになる点はありませんでした。

1点、スキーマをそのままdumpしてDBを作りなおすと、複合PKやmysqlのset型を使っている箇所でDB上のスキーマが変わってしまっていたため、
schema.rbを諦め、schema_formatを:sqlにしてSQLで管理するようにしました。

    # config/application.rb
    config.active_record.schema_format = :sql

テーブル名が複数形ではなかったり、PKがidではなかったりというのは、ActiveRecord側の設定でカバーできました。

終わりに

技術的に難しい部分はそれほどなく、正直根性が一番重要でした(笑)。

書き直しがベストな判断かどうかは、プロジェクトの状況次第ではあると思いますが、
今回の移行はこの先のメンテナンス性も考えると良かったと思います。

ちなみに一番良かったことは、非常に個人的な理由ですが、日々コードを書くのがより楽しくなった、ことですね。

自分自身nanapiさんのRails移行の記事を見てずっと狙っていたので、移行をお悩みの方の一助になれば幸いです。