Studyplus Engineering Blog

スタディプラスの開発者が発信するブログ

少人数で複数のマイクロサービスの開発を行うための弊社の開発事情

こんにちは、サーバーサイドエンジニアの山田です。

昨年の11月に入社して以降、Studyplusアプリのバックエンドとそれに付随するいくつかのマイクロサービスの開発に関わってきました。今回はその中で感じたサーバーサイドチームの開発環境のいいところや改善したい点をいくつか紹介したいと思います。

背景

わたしが所属するStudyplus事業部のサーバーサイドチームでは、10ほどのマイクロサービスの開発を4人のサーバーサイドエンジニアが担当しています。その中で一番改修が多いのはStudyplusアプリのバックエンドとなるRailsアプリケーションになりますが、それ以外のサービスもたまに改修を入れていくことになります。わたしの場合は入社して約半年で7個ほどのサービスの改修に関わりました。

それらのサービス開発に関わった結果、新しく入ったメンバーが早く立ち上がりやすい環境だと感じたので、そのあたりの観点を中心にチームの開発環境について紹介していきます。

ローカル環境編

docker-composeによる環境構築

どのサービスもdocker-composeでローカル環境を構築できるようになっており、環境構築に時間を取られることが少ないです。これによって、あるサービスにちょっとした改修を入れたいだけなのに環境構築に時間が取られるといったことを避けることができています。

開発環境のDBに接続して開発

ローカルでアプリケーションを動かす時に時間を取られやすい作業にデータの準備があると思います。 弊チームでは以下のように開発者個人のローカルのアプリケーションから開発環境のDBに接続して開発を行う方法をとっています。

f:id:yshunske:20200608113144p:plain

例えばRailsの場合はseeds.rbで初期データを準備する方法がありますが、seedのメンテナンスが手間で中途半端になってしまうことも多いと思います。

この方法のメリットとして以下のような点が挙げられます。

  • seedのメンテが不要
  • seedでカバーできない(or 準備コストが高い)ような特定の条件を確認するためのデータのバリエーションについても初めてローカルの環境を起動してすぐに使える
  • ローカル環境での確認後に開発環境で確認するといった場合に2度同じデータを作成する手間が省ける

一方で以下のようなデメリットもありますが、現状は問題にはなっておらずデメリットよりメリットの方が大きいと感じています。

  • DBのスキーマ変更を行う場合に別の開発者と競合してしまう可能性がある
  • みなが使うDBなので試しにスキーマを変更したいという場合にやり辛い

開発環境DBでやりづらい開発の場合は以下のような方法で回避することが多いです。

  • ローカル環境ではテストコード上での確認のみを行い、残りは開発環境へのdeploy後に確認する
  • 開発環境のDBをコピーしてそこに接続して開発

CI/CD編

テストコードとCircleCI

サーバーサイドチームが担当している全てのリポジトリにテストコードがあり、プルリクエストはCircleCI上のテストと二人以上のレビューが通らないとmasterブランチへマージできないようにしています。 これにより初めて修正を行うリポジトリでもテストコードで動作を確認しつつ自信を持って改修をしていくことができています。

デプロイ方法の統一

デプロイは以下のようにslackからデプロイする方法で統一されています。そのため個別の手順を覚えたりする手間が省けています。

f:id:yshunske:20200608113447p:plain

アプリケーション編

開発言語とフレームワーク

バックエンドは基本的にRubyとRailsが使われています(一部はGoなど別の言語を使用)。言語とフレームワークが揃っていることで学習コストを抑えて開発を行えています。 詳しくは後述しますが、フロントエンドはこのあたりに課題を抱えています。

Railsアプリケーションのレイヤー

Railsアプリケーション上で他のマイクロサービスと連携する処理は gateways というレイヤーを設けてそこに集約しています。

下のようなイメージです。

# Railsの app以下のディレクトリ
.
├── assets
├── controllers
├── gateways <- ここに他のマイクロサービスと連携する処理を集約している
├── helpers
・
・
・

他サービスとの連携は処理を追いづらいことが多いですが、異なるRailsアプリでも同じ構成をとることで処理が追いやすくなっています。

インフラ編

AnsibleとTerraformによるIaC

弊社のインフラの多くは、AnsibleとTerraformでコード化して管理しています。新しい仕組みの導入や大きな変更はSREチームが担当しますが、アプリケーションの変更に伴うちょっとした修正はサーバーサイドチームのメンバーも修正を行います。その際、AnsibleやTerraformのコードを修正してSREチームのレビューを受けてから反映しています。

これにより以下のようなメリットがあると感じています。

  • アプリケーションを開発するサーバーサイドのメンバーもインフラ構成や設定を把握しやすくなる
  • 作業がSREチームのみに集中することを避けられている
  • SREチームのコードレビューを受けることで一定の質を保って修正が行える

改善したいところ

ここまでは良いと感じている点を挙げてきましたが、改善したい点もいくつか紹介します。

フロントエンドの技術スタックが統一されていない

弊社の体制上、Webのフロントエンドが得意なエンジニアは、スマホアプリではなくWebのサービスであるStudyplus for Schoolを開発している部署に集まっています。そのためStudyplus事業部が担当するWeb画面を持ったサービスはサーバーサイドチームのメンバーがメンテナンスしています。

そのような体制ではありますが、使っているサービスによってJavaScriptのフレームワークは以下のように各種フレームワークが使われています。

  • Vue.js
  • React
  • AngularJS(Angularではない)
  • jQuery

これらをサーバーサイドエンジニアがメンテナンスしているためコストが上がってしまっており、ある程度は技術スタックを揃えていく必要があると感じています。

Ruby、Railsのバージョン

現状は各サービスで使っているRuby、Railsのバージョンがそれぞれ以下となっており、最新のバージョンに追従できていない状態です。

  • Ruby: 2.5系 or 2.6系
  • Rails: 5.2系

これがすぐに問題となるわけではありませんが、最新のバージョンからの差が大きくなるほどバージョンを上げるコストが上がっていきます。また、最新の機能や改善された機能の恩恵を受けられないというデメリットもあり、近いうちにバージョンを上げていきたいと考えています。

また、バージョンを上げていく作業は今後も発生し続けるため、なるべくコストを抑えつつ新バージョンに追従していく仕組みや体制を考えていきたいです。

まとめ

サーバーサイドチームが担当するサービスで共通することを中心に開発事情を紹介しました。個人的には複数のサービスで技術スタックや開発のフローが統一されている点が現状のチーム体制を考えると効率的だと感じて気に入っている点です。

新しいサービスにJOINして開発を開始するまでに必要な要素は、ドメイン知識など多岐にわたると思います。その中でもサービスを横断して統一されていることが多いとその一部を把握する時間をショートカットできるので立ち上がりが早くなると思います。

一方、そのマイクロサービスに適した個別のやり方を選択することも必要なので、開発の体制とバランスを取りながらより価値を発揮しやすい環境にしていきたいところです。