Heroku Review Appsで「使える」レビュー環境構築

こんにちは。grooves エンジニアの福井(@bary822)です。普段はCrowd Agentを開発しています。

今回はCrowd Agentのリリースフローが抱えていたボトルネックををHeroku Review Appsを使って解決した方法をご紹介します。

似たような課題をお持ちの方に解決のヒントを与えることができればと思いながらこの記事を書いています。

リリースフローのボトルネック

Crowd Agentではスクラム開発を採用しています。

スクラムでは開発者はPO(Product Owner)が定義する受け入れ条件を満たす機能を実装することを期待されていますが、Crowd Agentでは「POデモ」と呼ばれる受け入れチェックによりこれが正しく実現されていることを担保しています。

f:id:grooves:20200915175947j:plain

実はここにボトルネックが存在します。それはStagingが1つしかないことです。

複数の機能開発が並行して進んだ場合、POデモも機能毎に実行する必要がありますが、一度に使えるStaging環境は1つのみです。既にStagingが使われていた場合、他の開発者はPOデモが終わるのを待たなければなりません。

f:id:grooves:20200915175830j:plain

また、POが多忙でPOデモに使うことの出来る時間が限られていることもあり、デモが終わる度にStagingにデプロイし直すことも現実的ではありませんでした。

作って壊せる検証環境

このボトルネックを解消するためにHeroku Review Appsを利用することにしました。

ご存知の方も多いかと思いますのでここではHeroku Review Appsについての詳細を書きませんが、いわゆる「作って壊せる検証環境」を構築できるものです。

GitHubとHerokuを連携させることにより、Pull Requestが作成/更新されたイベントをHerokuに通知し、予め定義したフローに沿って自動的にアプリケーションがデプロイされることができます。

Heroku Review Appsを導入することでStagingの空き待ち時間を無くし、同時に複数の機能をPOデモできる環境を構築することに成功しました。

f:id:grooves:20200915175836j:plain

これによりボトルネックは解消され、開発された機能がスムーズに本番環境にリリースされる状態をつくることができました。

と、ここまで流暢に書いてきましたが、実はこれが実現されるまでにはいくつもの困難がありました。

独自サブ-サブドメイン使えない問題

Herokuではデプロイされたアプリケーションに自動的にドメインが付与されます。例えば、crowd-agent.herokuapp.com のようなものです。 Heroku Review Appsでは、サブドメイン部(crowd-agentに当たる部分)を任意の値に変更することができますが、サブ-サブドメイン部(*.crowd-agent)は指定することができません。

Crowd Agentではユーザーの属性によってログイン後のドメインを分けていたため、サブ-サブドメイン部を任意の値にコントロールし、同じアプリケーションにルーティングさせる必要がありました。

f:id:grooves:20200915175843j:plain

公式ドキュメントを読み進めていくと、どうやら独自ドメインを使うと解決できることがわかりました。

*.herokuapp.comは内部的に*.herokudns.comというドメインへのCNAMEレコードをもっているため、同様に独自ドメインからもCNAMEレコードを作成して紐付けるというものです。 確かに独自ドメインであればサブ-サブドメインのレコードも自由に設定することができます。

f:id:grooves:20200915175850j:plain

これはHerokuの設定ファイルである app.jsonpostdeployエントリにDNS登録作業を行なうスクリプト実行コマンドを指定することでデプロイ語に自動的にすることができます。

app.json

"postdeploy": "bin/rails heroku:review_apps_setup"

lib/tasks/heroku.rake

aws_client = Aws::Route53::Client.new(access_key_id: AWS_ACCESS_KEY, secret_access_key: AWS_SECRET_ACCESS_KEY)
heroku_client = PlatformAPI.connect_oauth(HEROKU_API_TOKEN)

hostname = "pr-#{heroku_app_name}.crowd-agent-review.com"

 domains = [nil, :admin, :agent, :company].map do |subdomain|
   hostname_with_subdomain = subdomain.present? ? [subdomain, hostname].join('.') : hostname

   # Heroku上にドメインを作成
   heroku_client.domain.create(heroku_app_name, hostname: hostname_with_subdomain)
   heroku_cname = heroku_client.domain.info(heroku_app_name, hostname_with_subdomain)['cname']

   # Route53用の設定を定義
   config = {
     hosted_zone_id: '/hostedzone/XXXXXXXX, # crowd-agent-review.com
     change_batch: {
       changes: [
         action: 'CREATE',
         resource_record_set: {
           name: hostname_with_subdomain, type: 'CNAME', ttl: 3600, resource_records: [{ value: heroku_cname }]
         }
        ],
        comment: "Review environment host for branch #{branch}"
      }
    }

    # Route53にレコードを作成
    aws_client.change_resource_record_sets(config)

    [subdomain || 'root', hostname_with_subdomain]
 end

 hash = {}
 domains.each { |item| hash[:"APP_#{item[0].upcase}_DOMAIN"] = item[1] }

 # Herokuにドメインを登録
 heroku_client.config_var.update(heroku_app_name, **hash)

 puts "App is successfully built!"

動作が遅すぎて使い物にならない問題

無事にドメインが設定され、ようやくブラウザから操作できるようになったReview Appsですが、実はあまり活用されていませんでした。なぜなら動作が遅すぎて全く使い物にならなかったからです。

どのくらい遅かったかと言うと、レンダリングするまでに30秒近くかかるページもあるほどでした。これでは開発者もPOも使ってくれません。

どこにボトルネックがあるかは明確でした。App - DB間のレイテンシです。

初期構成では実装コストを下げるために、Staging環境で利用しているDBをReview Appと共有していました。 しかし、Heroku上のAppはUS(Virginia)リージョンに、Staging DBはTokyoリージョンに配置されています。

動作が遅くなっていた原因は、この通信に大きなレイテンシが発生していることでした。

一旦整理すると、初期構成の全体像は以下のようになります。

f:id:grooves:20200915180014j:plain

HerokuのAppがVirginiaリージョンに配置されていることは以下のコマンドで確認しました。

# Herokuの認証情報はあらかじめexportしておく
$ curl -n -X GET https://api.heroku.com/regions/us -H "Accept: application/vnd.heroku+json; version=3"
{
  "country":"United States",
  "created_at":"2012-11-21T20:44:16Z",
  "description":"United States",
  "id":"59accabd-516d-4f0e-83e6-6e37577XXXX",
  "locale":"Virginia",
  "name":"us",
  "private_capable":false,
  "provider":{
    "name":"amazon-web-services",
    "region":"us-east-1"
  },
  "updated_at":"2016-08-09T22:03:28Z"
}

これを解決するために、まずはAppをTokyoリージョンに移せないか検討しましたが、コスト(お金)の面から難しいことがわかりました。

Review AppsをUS以外のリージョンで使うためには、Private Spacesという有料の機能を使う必要があります。今回の場合、レイテンシ解消で得られる恩恵は$1000/月(2020年9月現在)という価格を下回っていると判断し、導入を見送ることにしました。

この代替案として、DBをUS(Virginia)リージョンに移すことを検討しました。 Staging DBを共有するのではなく、全Review Appsで共通の専用DBをVirgniaリージョンに設置するというものです。

f:id:grooves:20200915180018j:plain

これによりレイテンシは改善され、ページがレンダリングされる時間は1/10まで短縮されました!

また毎デプロイ後、自動的にDBのテーブルセットアップやテスト用データの作成を行なうようにしました。これでデプロイ後すぐにPOデモを依頼することが可能になりました。

app.json

"postdeploy": "bin/rails heroku:review_apps_setup && bin/rails db:migrate db:seed"

まとめ

今回はHeroku Review Appsを使ったリリースフロー上のボトルネック解消方法、また導入時に私達が直面した問題とその解決方法の一例も併せてご紹介しました。

現在Heroku Review Appsは開発からリリースまでのリードタイムを減少させる有効なツールとして、私達の開発になくてはならない存在となっています。

個人的には開発チームを支援するツールの導入・作成は大好物なので、このタスクに携わることができて大変嬉しく思っています。

最後に、Crowd Agent開発チームではアプリ開発に強みを持つエンジニアとインフラ技術に強みを持つエンジニアを募集しています。

開発メンバーは全員フルリモート勤務となりますので、都市部以外にお住まいの方、また都市部から地方への移住を検討している方からの応募も大歓迎です!

みなさまのエントリーお待ちしています!

jobs.forkwell.com

jobs.forkwell.com

grooves のオンボーディング(開発チーム編)

こんにちは!grooves の開発チームでエンジニアリングマネージャーをしている吉永です。

ひさしぶりの開発ブログ更新ですが、今回は grooves の開発チームのオンボーディングプロセスをご紹介します。タイトルに「開発チーム編」と銘打っているのは、grooves のオープン社内報にて、ほぼ同時期に採用していたデザイナーのオンボーディングの様子をご紹介しているからです。よろしければ是非そちらもご一読いただけると幸いです。

前提

ここでのオンボーディングとは、新たに採用した人材を職場に配置し、組織の一員として定着させ、戦力化させるまでの一連の受け入れプロセスのことを指しています。 良いエンジニアを採用するのは一苦労ですが、オンボーディングでつまづいてしまうと、採用の苦労も報われなくなってしまいます。私たちは、採用とオンボーディングを地続きで考えるようにしています。

今年はコロナウイルスというイレギュラーな事態が発生し、採用やオンボーディングにも大きな影響がありました。具体的には、そのプロセスのほとんどを、オンラインで完結しなければならなくなりました。もともと grooves の開発チームはフルリモートでの環境を整えていましたが、採用面接や入社直後はオフィスに出社して実施していたため、全てオンラインで実施するということは新たなチャレンジとなりました。

この前提を踏まえて、実際にオンボーディングで取り組んでいることをいくつか紹介します。

オンボーディングのゴール

grooves ではスクラム開発を採用しています。オンボーディングのゴールは、

「スクラムの開発チームのメンバーとして、成果に貢献できる状態」

を目指すようにしています。期日は入社時点のスキル次第で微調整します。「2つ先のスプリントからスクラムに加わってみましょう」といった具合ですね。プロダクトオーナーも、いつから戦力化するか考慮して少し先のスプリント計画を立てています。 このゴールから逆算してオンボーディングのプログラムを組み立てていきます。

入社直後〜入社後二週間

会社、事業、プロダクト、チームを知り、自分のことを知ってもらうための期間です。

  • 自己紹介のページを書いてもらう
  • 会社のルールを知る研修
  • 事業を理解し、各部署の役割を知る研修
  • オンラインランチ・歓迎会

このような全社共通のメニューを行いつつ、開発チーム固有のメニューとして以下のようなことを行っています。

  • 課題図書( Team Geek や SCRUM BOOT CAMP THE BOOK など)を読む
  • スクラムについての研修
  • プロダクトについての研修
  • チームメンバーとのデイリー1on1
  • 今月頑張ったことと、来月頑張りたいことを共有する場(お互いを知る会)に参加

メンバーとの1on1や、お互いを知る会への参加は、メンバーそれぞれがどういう価値観を持っているのか、相互理解を深めることができる取り組みです。こういったことを行いながら開発環境を整え、プロダクトのコードを読み進めてもらっています。

入社二週間〜入社後二ヶ月

スクラムに加わるための準備期間です。いきなりスクラムのメンバーに加えてしまうと、見積もりや計画が不安定になってしまいます。新入社員の方には、スプリントバックログとは別の開発を担当してもらうことで、スクラム開発の見通しを維持しつつ、開発に慣れてもらいます。

  • 開発チームは、プロダクトの理解度を高める助けになりそうな開発項目を、バックログからピックアップし、着手可能な状態にする
  • 新入社員の方は開発に着手し、見積もり(ストーリーポイント)のイメージをつかんでもらう。
  • チームのレビューを通す前に、スクラムマスターが事前レビューを行い、Pull Request の基準を知ってもらう。

このような準備期間を経て、いよいよスクラムチームのメンバーとして開発に携わってもらうことになります。

スクラム開発へ

準備期間の中で、ドメイン知識や、スクラム開発のフローについては一定理解した状態が実現できています。しかし、いざスクラムチームに入ってみると勝手が違ったり、スプリントゴール達成のプレッシャーに晒されたりと、ギャップを感じる部分はあるようです。以下は最近入社した方から実際にいただいた意見です。

  • 実際やってみると、実作業をする上で十分なコードの理解ができていなかった
  • スクラムのイベントの目的を、十分理解できていなかった
  • チームメンバーに、どこまで頼っていいかわからなかった
  • 見積もりの感覚がチームと合わないことがある

オンボーディングの内容を見直して、こういったギャップをひとつひとつ取り除いていきたい、と考えています。

リモートで働くチームが大切にしていること

私たちのチームは、リモートを前提として設計されています。チームで円滑にコミュニケーションし、協業するために大切にしていることがいくつかあります。

  • Do
    • HRT(Humility 謙虚、Respect 尊敬、Trust 信頼)を大事に
    • アウトプットし、アウトプットを可視化する
    • ドキュメントに残す
    • 自分の意見をはっきりと発信する
    • リモートで働く利点を最大化する
    • チームとしての成果を意識する
  • Don’t
    • チャットでの即応答などは求めない
    • チームに遠慮はしない
    • ローカル(オフライン)の環境をリモートで再現しようとしない

オンボーディングの時点からこれらを身に付けてもらうように、スクラムイベントの会議や1on1などの場を使い、意識し行動を促すようにしています。

以上です。

最後にgrooves ではソフトウェアエンジニアを絶賛募集中です。興味を持っていただけたら是非こちらのForkwellの求人からエントリーいただけると幸いです。

イベント当日にパネリストが来れない!急遽リモート先から登壇してもらった方法

こんにちは。株式会社grooves Forkwell事業部の赤川です。

つい先日、私たちが主催したイベントでちょっとしたハプニングがありました。
そのイベントのコンテンツに、福岡から東京に飛行機で来て頂くまつもとりーさんによるパネルディスカッションがあったのですが、イベント当日の朝に急遽東京に行けなくなってしまった、という連絡がありました。
過去に、リモートでの登壇発表は何度か見たことがありましたが、リモートでのパネルディスカッションは見たことがありません。
その時点でのイベント参加登録者数は90名を超えていました。
主催者である私としては、直ちに、中止にするか、実行するか、実行するならどうやるのか、を判断する必要がありました。

本日は、このシチュエーションを Zoom を使ったリモートパネルディスカッションによって乗り切った経験をご紹介します。
同じ環境を用意すれば、誰でもリモートでのパネルディスカッションを成立させることができますので、

  • 私と同じシチュエーションに遭遇するかもしれない方
  • 遠隔地の登壇者による双方向性のイベントを企画している方
  • 2会場以上での同時イベントを企画している方

にお役に立てていただければ幸いです。

目次

  • 実際に使った機材の構成図と解説
  • 最小限の機材での構成図
  • 準備時のチェックリスト
  • おわりに

実際に使った機材の構成図

f:id:redribabarn:20181011190304p:plain

実際のイベント模様

f:id:redribabarn:20181011140207p:plain

  • 自分たちでも驚くほど、スムーズなコミュニケーションができました。
  • 参加者アンケートの結果は、中継に関する不満が一切なく、イベントの満足度も満足以上が90%以上となりました。よかった!

構成図の解説

Zoom がおすすめな理由

  • Zoom を用いると、一つのパソコンで、画面共有とカメラ中継の両方を行うことができ、会場の雰囲気とスライドを同時に伝えることが可能です。
  • ただし有料会員でないと40分で中継が終了してしまいます。リモートワークする際に Zoom マジ最高なので会社に頼むなどして有料会員になっておくといいでしょう。
  • Hangouts 等を用いる場合は、スライド共有用のパソコンと会場中継用のパソコン(またはスマートフォン)を用意すると良いでしょう(設定は後述)

クリアな音声を届けよう

  • 会場の音声をリモート登壇者へ届けるために、会場スピーカーの近くに会場音声用マイクを置きました(Bluetooth のマイクだと設置位置の自由度が高くて良いです。私のおすすめは Jabra SPEAK 510 です)。
    • 会場音声用マイクがスピーカーに近いほど、参加者と同じ情報を同じ品質でリモート登壇者が聞ける状態になります。
    • マイクの音声をラインで取れたらベターでしたがその設備はありませんでした。
  • リモート登壇者の音声は、プロジェクター・ミキサーを通じ、会場のスピーカーから流しました。
    • このときのボリュームが、会場マイクからのボリュームと同じになるように揃えました。
    • プロジェクターからラインでミキサーにつなげない場合は以下の選択もあります。
      • パソコンから音声ジャックを通して、直接ミキサーにつなぐ方法(スマートフォンのZoomアプリからミキサーにつないでもOKです)。
      • パソコンから出る音を登壇者マイクで拾う方法(これはできれば避けたい)。
  • リモート登壇者には、ヘッドセットを使ってもらいました。
    • 会場側が受け取る音声がクリアになります。音声は大事です。

会場の雰囲気をリモート登壇者に伝えよう

  • 会場の様子を中継するためのカメラを用意しました。
    • これにより、登壇者が会場のフィードバックを得ながら進行できるようになり、自分も参加している感、当事者意識を感じることができます。
    • 相手からのフィードバックがないと、声が届いているのか不安になるのは、リモートあるあるですよね。

リモート登壇者の表情を会場に伝えよう

  • Zoom だと画面共有時にも常にリモート登壇者の表情が画面に出せるので、より一体感がでます。
  • プロジェクターへの投影方法はミラーリングを用いました。
    • ミラーリングを用いると、リモート登壇者を窓枠から表示する設定が少し簡単になります。
    • ファシリテーターがスクリーンを見ながらコントロールする必要がなくなるため、進行がスムーズになります。

通信トラブルに備えよう

  • Zoom を中継するパソコンはなるべく有線LANを用いるとよいです。
    • 参加者が無線LANを利用すると通信速度が落ちる可能性があります。
  • 今回の会場は有線がなかったので、無線が不安定な場合に備えて、映像中継を切り、音声のみを配信することも想定していました。
    • 映像中継を切った場合にも発表できるよう、事前にスライドを共有してもらい、会場側でスライドを手送りできるようにしていました。

反省点

  • 音が反響する会場だったので、リモート登壇者が少し聞こえにくかったようです。
  • 通常の会場より、タイムキーパーによる意思疎通が難しかったです。
    • チャットを活用して時間を連絡できたらよかったかもしれません。
  • こればっかりは仕方がないのですが、懇親会を楽しみにしていた方には申し訳なかったです。
    • リモート中継を決定した時点で、すぐにその旨を connpass を通じて参加者へ送信しましたが、それに気づけない方もいらっしゃったので他の方法も模索したいです。

最小限の機材での構成図

f:id:redribabarn:20181011190319p:plain

プチ解説

  • Zoom から出た音声を登壇者マイクで無理やり拾う方法です。
  • 会場の音声、映像はスマートフォンで中継します。
    • その際、スマートフォンから音声が出ないようにしておきます。
  • この構成の場合、Zoom ではなく、Hangouts や Appear.in でも大丈夫です(品質は Zoom が一番だと思います)。

この方法のデメリット

  • リモート登壇者が受け取る音声がクリアではなくなります。
  • リモート登壇者が、自分の話した声が自分にかえってきてしまうので、話しにくくなります。
  • 機材の相性や通信状況によっては、ハウリングが起こりうる設定です。必ずテストしてください。

こんな方法も…

f:id:redribabarn:20181011191933p:plain

準備時のチェックリスト

上記の方法をいつでも実行できるように、イベント前に確認しておくべきことをリスト化しました。

  • 模式図にある機材は揃っているか?
  • パソコンから出る音声(リモート登壇者の声)を会場から流すことができるか?その方法は?
  • 登壇者用マイクの本数は?(大きな会場だと2本以上ないと難しい)
  • 登壇者用マイクの音声を、ミキサーからラインで出力することができるか?
    • その際、登壇者のパソコン位置につなぐための十分な長さのケーブルはあるか?
  • 中継用のパソコンを有線LANにつなぐことは可能か?
    • その際、登壇者のパソコン位置につなぐための十分な長さのケーブルはあるか?
  • 登壇者の発表資料を事前に中継パソコンに収集しているか?

おわりに

今回のイベントは、エンジニアの方々にアウトプットの重要性を伝えることがテーマのイベントでした。
その中で、登壇者のkwappaさんが、自分の仕事の具体的な経験を抽象化し、一般化して社会みんなが使えるようにアウトプットするとよい、という発表をされておりました
それはいい!と思ったので、早速、自分のイベントでのトラブル経験をアウトプットしてみました。

参考になりましたら、ツイート、はてぶなどをお願いします。
また、赤川のこれまでのアウトプットはこちらにまとまっていますので、興味ある方はぜひご覧ください。

本当に良いエンジニアはいないのか?企業が採用に苦戦する本質とは

こんにちは。grooves にて Forkwell の事業責任者を務めている、赤川と申します。

この数ヶ月、 grooves では全事業部で積極的にエンジニアの採用活動を行ってきました。
当初は応募獲得に苦戦するだろうと思っていたのですが、結果は真逆で、あまりにも魅力的な方ばかりから応募いただけるので、採用に迷うことのほうが多いという結果になりました。

結果的に当初の予定より人員計画を増やすことになったのですが、それでもこの人と働きたいと思った方全員を採用できる状況ではなく、私たちとしてもぜひ一緒に働きたいと思っている方で、grooves を第一志望です、と言ってくれる方に対して採用枠の充足を理由にお断りしなければならないのは、非常に辛いことでした。

世の中には素晴らしいエンジニアがたくさんいるということを、改めて認識しています。

一方で、grooves が運営する Forkwell の元には、良いエンジニアが採用できないので支援してほしいという連絡が毎日届いています。
どの会社も、採用にはかなり苦戦していらっしゃるようです。

この差はなんなのでしょうか。

市場にはこんなに良いエンジニアがいるのに、どうして採用できない企業がこんなにいるのでしょうか。

私の意見は、魅力的なエンジニアに選ばれる企業が圧倒的に少ない、です。

選ばれないのは、差別化できるほどの魅力が足りないから

求人票を作る際に、STPを採用することは有効な手段の一つです。

STPとは、
適切な切り口で市場やユーザーを細かく分類して(セグメンテーション)、
分類した市場の中で狙う層を絞って(ターゲティング)、
その層に刺さる魅力で差別化する(ポジショニング)、
というマーケティングの基本的な考え方です。

STPを使うことで、自分たちの個性に合った方に自社を選んでもらいやすくできるのですが、そもそもポジショニングできるだけの魅力がないことが、多くの企業の課題になっているように思います。

この魅力づくりがないまま、採用ステップに進むから苦戦するのです。

魅力が足りない企業ほど、魅せ方にこだわりがち

魅力がある企業であれば、それを100%伝えることができれば、解決です。

Forkwell はエンジニアが選ぶべきかどうか正しく判断できるよう、なるべく詳しく求人に掲載していただくよう取り組んでいます。
しかし、10の魅力を10で表現することはできても、2の魅力を10に見せることはできません。

多くの採用広告では、このレートが100%からずれてしまうので、不幸が起きていると考えます。
このレートは、100%がいいのです。
50%であれば、まだ自分たちの会社が採用できないだけで済むのですが、150%にしてしまうと、入社した方が確実に不幸になります。これだけは絶対に避けなければなりません。

grooves はどうしているか?

結局、自社の魅力を底上げすることが一番です。

当たり前の給与

正直、大手企業やメガベンチャーと比較すると、届いていません。
それでも、事業の成長に伴って社員の給与は毎年平均10%で上がってきており、2018年は念願の賞与を導入することもできました(とはいえ、まだ年1ヶ月分を給与に上乗せできるレベルですが)。
ユーザーに価値を提供できれば会社が儲かる。会社が儲かった分はちゃんと社員に還元される。だからもっとユーザーに価値を届けようと頑張れる。そういうサイクルを目指して少しずつ積み上げてきました。もちろん、大手企業と並ぶには、高い生産性を実現しながら、よりユーザーに価値を届ける必要があることも理解しています。

最も大事なビジョン

私たちが何を目指したいのか、ぶれないビジョンを掲げています。
わざわざ大企業を断ってまで grooves に挑戦したいと思えるほど価値あるものを掲げなければいけません(少なくとも私はそう信じています)。
また、お飾りのビジョンには何の意味もありませんから、自ら実践する必要があります。groovesでは、 ワークシフトインフラを創るというビジョンに便乗して(ダジャレじゃないです)、様々な試みをしてきました。年初に話題にしていただいた記事もその1つです。

tech.grooves.com

他にも、フレックスやリモートワークは当たり前として、最近ではタイでのワーケーションにチャレンジする社員まで現れました。

www.wantedly.com

サービスがビジョンに沿っていることは大前提として、私たち自身でビジョンを体現することも、ビジョンの形骸化を防ぐために必要だと思っています。

チームの理想に近づける努力

ビジョンの中で働き方への取り組みを書きましたが、それだけではなく、チームとして理想の開発文化を作りあげていくということも大事です。

エンジニア自身が、「こんな組織にしたい」を言語化し、それに向けてどんな取り組みをしているのか発信していく。それに共感した人が集まり、理想とする開発環境ができていく。
その結果として、見積もりはみんなでする、テストを書く、PRをマージするにはプロジェクトで決められた人数以上のレビューが必要、ドキュメントを残す、gem などのライブラリは常に最新版を使うといったチームにとって当たり前の文化ができてきました。

Rails 5 リリース日に Forkwell を Rails 5にアップグレードしたのも、話題作りの意図もありますが、社内をエンジニアにとって刺激的な環境にすることで、働くこと自体も楽しんでもらいたいと思ったからです。

魅力が整ったら採用へ

こういった取り組みをした上で、エンジニアであれば Forkwell や開発ブログを通じて、ビジネスサイドであれば Wantedly などを通じて、伝達率100%を意識して発信しています。

grooves では、今年の2月から3月までに Forkwell Scout を使って20通のスカウトを送り、9名の素晴らしいエンジニアと面談することができました。スパムのようにスカウトを送らなくとも、良い出会いを作ることはできるのです。

現実的にはビジネスである以上、何かをする前に全てが揃うということはないので、今ある手持ちの魅力だけで戦うことにはなるのですが、魅力づくりに手を付けなければジリ貧が続くことを意識して改善を続けています。

まとめ

記事タイトルの「本当に良いエンジニアはいないのか?」という問に対しては、明確に「いる」とこたえます。
良いエンジニアに選ばれる企業が少ない、というのが私の見解です。

それを踏まえて、

  • 自社の魅力をあげよう
  • 伝達率を100%にしよう

という主張を行い、そのために grooves が行っているアプローチを書きました。

本記事が皆さんのよりよいエンジニア採用のきっかけになれば幸いです。

採用に苦戦しているポジションも

実はいま、最も採用に苦労しているのがデザインも好きなフロントエンドエンジニアです。
もし grooves に興味をお持ちいただけるようでしたら、ぜひ以下のリンク先からエントリーしてください。

jobs.forkwell.com

Forkwell のインフラをコード化するためにやったこと

ここ最近は既存のインフラを片っ端からコード化していた @sinsoku です。

やっとコード化が一段落したので、インフラ周りでやってきたことを技術ブログにまとめました。

作業をする前の状況

Forkwell のインフラ環境は2016年夏頃に「第1回 インフラがコード化されていないのはヤバい!」議論が起き、タスクの優先度が上がりました。 このときは @ta1kt0me が頑張ってくれて、既存 EC2 インスタンスを Ansible で作れるようにしてくれました。

しかし、弊社では AWS の ALB、EC2、RDS、ElastiCache、...など、いくつものサービスを使っています。 この AWS リソースはコード化されておらず、手作業で作っていました。

2017年12月末

サーバを Ruby 2.5.0 に上げる話が挙がり、そのとき「第2回 インフラが(以下略」の議論が起きました。

  • 不要そうな AWS リソースがあるけど、消すのが怖い
    • どこかで使われているかも...
  • 既存の設定にした意図が残っていない
    • デフォルト値と異なる箇所が分からない
  • コード化されていないのでレビューできない

といった課題は前々からありましたし、2017年も終わろうとしているのにまだ Immutable Infrastructure になっていないのも微妙です。

f:id:sinsoku:20180119104029p:plain

そこで、この機に AWS リソースもコード化する方針を立てて、対応することにしました。

Terraform の導入

AWS リソースをコード管理できるツールは AWS CloudFormationTerraform、Ansibleといくつか選択肢があります。

ただ、将来的には GitHub Organization などもコードで管理したいこともあって、Terraform を選択しました。*1

staging 環境のリソースをインポートする

いきなり production 環境のリソースを管理するのは怖いので、まずは staging 環境のリソースを管理することにしました。

  • terraforming
  • terraform import の機能
  • terraform state の機能

を駆使し、terraform.tfstate を作っていきます。

EC2 インスタンスをインポートする例

まずは既存のインスタンスを全部 ec2_instances.tf に出力します。

$ terraforming ec2 > ec2_instances.tf

次に、今回は管理対象外である production 環境の設定を頑張って削除します。

$ vim ec2_instances.tf

インポートをする前なので、 Terraform にはインスタンスの追加として認識されています。

$ terraform plan
.
.
.
Plan: xx to add, 0 to change, 0 to destroy.

1つずつ心をこめて import していきます。

$ terraform import aws_instance.web i-12345678

対応が終わったら、祈りながら plan を実行します。

$ terraform plan
No changes. Infrastructure is up-to-date.

上手くインポートできれば差分が出ない状態になります。

Terraform のディレクトリ構成

インフラの設定を1つのディレクトリで管理すると plan の実行に時間がかかったり、 *.tfstate が壊れた時のリスクが大きいため、ディレクトリを複数に分けました。

./infra
  app/                    # Forkwell のVPC, EC2, ElastiCache, ...
    .terraform/
    backend.tf
    main.tf
    vpc.tf
    ...
  auto_bundle_update/     # CodeBuild を使った自動bundle update設定
  users/                  # IAM 関係
  s3_buckets/             # S3 バケット設定
  metric_alarms/          # CloudWatch のアラーム関係

このディレクトリ構成が良いのかは自信ないですが、コード化さえできれば後からリファクタリングできるので、とりあえずこれで進めました。

ちなみに、他ディレクトリの値は terraform_remote_state を使って参照する作戦です。

セキュリティグループのテスト

セキュリティグループの設定はミスるとサービスが動かなくなったり、特定の機能がエラーになって非常に危険です。 このため、不要そうな設定であっても消しづらく、残ってしまいがちです。

そこで、既存のセキュリティグループに対するテストコードを書きました。

RSpec.describe 'staging' do
  let(:bastion_ip) { '123.456.789.1' }
  let(:bastion_user) { 'ec2-user' }
  let(:bastion) { Net::SSH::Proxy::Command.new("ssh #{bastion_user}@#{bastion_ip} -W %h:%p") }

  def mysql_config
    {
      host: '127.0.0.1',
      username: 'root',
      password: ENV['STAGING_DATABASE_PASSWORD'],
      database: 'forkwell_staging'
    }
  end

  describe 'in app server' do
    let(:server_ip) { '123.456.789.2' }
    let(:server_user) { 'forkwell' }
    let(:server) { Net::SSH::Gateway.new(server_ip, server_user, proxy: bastion) }

    it 'connects to MySQL server' do
      server.open(ENV['STAGING_DATABASE_HOST'], 3306) do |port|
        client = Mysql2::Client.new(mysql_config.merge(port: port))
        results = client.query("SELECT VERSION();")
        expect(results).to include("VERSION()" => "5.6.34-log")
      end
    end

    it 'connects to Redis server' do
      server.open(ENV['STAGING_REDIS_HOST'], 6379) do |port|
        redis = Redis.new(url: "redis://127.0.0.1:#{port}")
        expect(redis.info['redis_version']).to eq '2.8.6'
      end
    end
  end
end

このテストにより、全ての EC2 インスタンスで疎通確認するのが簡単になり、セキュリティグループを編集しやすくなります。

今後やっていくこと

今回は(staging環境の)既存リソースをコード化することを重視していたため、Terraform の変数や属性は使いませんでした。 やっとインポート作業が一段落したので、これからは少しずつリファクタリングしていきたいと思っています。

そして、メンバー全員が Terraform に慣れてきたら production 環境のコード化も進めていきたいですね。

(半分くらい) Immutable Infrastructure な環境で働きたい人

インフラ環境も改善されつつある弊社では一緒に働きたい方を募集しています!
興味ある方は下記URLからエントリーお願いします!

jobs.forkwell.com

*1:あと HashiCorp 社が好きだったり、Terraform の名前がカッコいい、といった個人的な好みも選定に影響しています

なぜ grooves はフレックスでの深夜勤務を認めることができなかったか?

昨日 2月末に株式会社groovesを退職します を発表したエンジニアのマネージャーを務めている(2018年1月時点)赤川です。

本記事の前半では、なぜ彼が望む「フレックスでの深夜勤務」を用意できなかったかを紹介し、後半では彼と共にプロダクト開発に携わってきた立場から、彼の推薦文を書きます。

なぜこの記事を書くのか?

  • フレックス制度の導入を検討している会社の参考にしてほしい
  • エンジニアの成長・キャリアアップを応援する Forkwell を運営している会社が、自社のエンジニアのキャリアアップや転職を応援しないのは嘘になるので、感謝をこめて送り出したい

今回の経緯

まず、今回の件について、彼とどのように会話を進めてきたかを紹介します。

  • 2017年8月 1on1 MTG で、自身の生産性をあげるためにフレックスを導入したいと伝えられる。フレックスについて調査開始。
  • 10月 エンジニアチームに、深夜時間以外でのフレックスを試験的に導入する(コアタイムは14:00-18:00に設定、月初・週初は対象外)
  • 11月 フレックスを試験導入から本導入へ移行(同上)
  • 12月 彼に退職したいと伝えられる。その際、フリーランスは可能かと正式に相談される
  • 同月 フリーランスの条件を提示する

これ以前にも、火〜金はリモートするかどうかを個人で判断できるようにするなど、エンジニアの自由度を広げていました(詳細は HOW GROOVES REMOTE WORKS を見てください)。

どのような文脈で進めたか?

grooves は「ワーク・シフトインフラを創る」をビジョンに掲げている企業です。 簡単に言うと、新しい働き方・流れを世の中に提示し、そのインフラを作ることを目指しています。もちろん、Forkwell もその大本のビジョンの元で運営されています。

「ワーク・シフトインフラを創る」をビジョンに掲げる以上、私たち自身も率先して新しい働き方をしていく必要があります。

そのため、リモートワークやフレックス制度などについては、会社全体で挑戦していく風土があります。

これまでも、個人のライフステージの変化に合わせて

  • 結婚を機に大阪に引っ越す社員のために、大阪にリモートオフィスを借りる
  • エンジニアだけでなく、全社でリモートワークを導入する

といった挑戦をしてきました。

今回のケースのように、全ての要望を実現できるわけではないですが、会社全体の生産性を上げるためであれば、実験する土壌はある会社です。

そんな風土をもつ grooves が、なぜ深夜のフレックスだけは導入することができなかったのでしょうか?

フレックス制度で、深夜の勤務を認めることができなかった理由

まず、フレックス制度に関して社労士などを通じて調べたことを記載します。
(なお、私自身は法律家ではないので、間違いがあるかもしれません。本文を鵜呑みにせず、社労士などにも確認してください。)

  • フレックスタイム制とは、必ず勤務すべき時間帯(コアタイム)を遵守したうえで、労働者が各自の始業時刻と終業時刻を原則として自由に決められる制度。
  • 1日の労働時間規制に代えて、清算期間における労働時間の合計によって勤務時間・時間外労働の有無が判断される。
  • フレックスでも勤務した時間はきちんと管理しなければいけない
  • 深夜帯に勤務した場合(22:00-5:00 が対象)は深夜割増賃金で支払わなければいけない

これが何を意味しているかというと、

  • もし全く同じ能力の人がいるとして、同じ労働時間・同じバリューだけを発揮している場合でも、個人の判断で深夜帯に働いた人だけが、給与を多くもらえることになる
  • 深夜勤務を認めたとしても、稼働時間を細かく申請してもらうことが必要となる

といった、難しさが生じることがわかりました。

これに対応するためには、深夜割増賃金まで見込み給与に含む等の制度に変更する必要があります。

さらに問題なのは、勤務時間の登録の義務付けは引き続き必要となるため、それを「10分遅れてもSlackで連絡すれば問題ない雰囲気」といえるかというと、管理されている感はでてしまいます。何より手間です。

そのため、法律に目をつぶる以外で、深夜帯に個人の裁量で働ける仕組みを見つけることができませんでした。

フリーランスなら解決するのか?

そこで出たのがフリーランス(業務委託)という選択肢です。 ここではまず、正社員とフリーランスの違いについて記述します。

正社員 業務委託
契約 雇われる者が雇い主に対して労務を従うことを約束し、雇主がその対価として報酬を支払うことを約束することによって成立する契約 一事業主として特定の仕事を処理することを目的として行なわれる契約
社会保険 あり(雇用保険、厚生年金、健康保険、労働保険 等) なし
その他社会保障 労働基準法に準ずる
最低賃金、有給休暇の有無、産休育休の有無 等など
最低賃金や有給休暇など、労働に関する法令が適用なし
雇用期間 基本は無期雇用 有期契約(1~3ヶ月契約にしているケースが多い)
時間・勤務地の拘束 労働基準法及び就業規則に準ずる 時間的拘束、勤務地の拘束はできない(双方の内規的な取り決めは実際のところするケースが多いが、企業から厳密に指定するのは違法
税金 年末調整の対応のみで確定申告の必要なし 確定申告が必要
給与の支払い方法 会社側で給与計算=>支払い 本人から請求書=>支払い
交通費 実費支給 基本は特に支給なし ※
小口精算 実費支給 基本は特に支給なし ※
勤怠管理 必要 必要なし

※ 会社主導の遠隔地の場合は、双方協議で負担する場合あり

他にも、フリーランスには以下の特徴があります。

  • リスクがある分、正社員より手取り額が高くなる可能性が高い
  • 受発注関係になるため、成果物でのみ評価され、人事考課は関係ない
  • ストックオプションを行使する際に、税金の徴収額が大きくなる

フリーランスなら、彼が望む働き方に近づけそうです。

本人にとっては、grooves で活躍してきた実績もあるため、初めての会社と比較すれば打ち切りリスクも少なくなります。
grooves としては実質的な支払い額が増えますが、制度変更よりは少ない投資で済みます。
他社に転職してしまうリスクは増えますが、何もしなければそのリスクは一層高まったでしょう。

結果的に彼は、このまま grooves で正社員を継続するメリットはないと判断し、今回の結論にいたりました。(もちろんフレックスだけが全ての理由ではないです。)

今回、grooves でフリーランスという選択肢が残っている上で、彼がWeb上で退職を表明したのは、広く世の中に自分の可能性を問うためです。

繰り返しになりますが、エンジニアの成長・キャリアアップを応援する Forkwell が、自社のエンジニアのキャリアアップや転職を応援しないのは嘘になりますから、寂しい気持ちはあるものの、ぜひ応援したいと思います。

推薦文

マネージャーの立場から見た、彼の長所は、

  • 圧倒的な実装スピード
  • ロジックに関する的確なレビュー
  • 高い問題意識と自主性
    • 彼の問題意識をきっかけに、形成された開発文化が多々あります
      • PRへのレビューは24時間以内に2人以上(ユーザーに早く価値を届ける、手戻りまでの期間を短縮するなどの意図)
      • エラーはすぐ確認する 等
    • この問題意識の高さは、コードや開発環境だけでなく、会社の制度にも波及します
  • 社外活動に積極的で、エンジニア界内での認知度・つながりが多い

です。

一方で、彼が苦手とするのは、

  • よそ見をしがち 
  • 興味のない分野でパフォーマンスがわかりやすく落ちる
  • 忖度

などがあり、言われたとおりにだけ働くタイプではありません。
「えっ?いまそれやってるの?」ということもあります。そういったことからアイディアを生み出すのが彼の魅力でもあるのですが。

すでに多くの会社からオファーが来ているようですが、我こそはという会社は、引き続きぜひ声をかけてあげてください

エンジニアを募集しています。

Forkwell では Rails エンジニアを募集しています。 今回、良くも悪くも私たちがどのような会社かが表に出ましたので、このような私たちを良いと思える人にこそ、ぜひ遊びにきてほしいです。

jobs.forkwell.com

となりの事業部の Crowd Agent でも Rails エンジニアを募集しています。

jobs.forkwell.com

また、自分からエントリーするのは恥ずかしい、と思われた方は、ぜひ Forkwell Scout に登録してください。

jobs.forkwell.com

皆さんのプロフィールを一人ひとりじっくり拝見し、興味を持った方にはこちらからお声がけさせていただきます。

引き続き、エンジニアの成長・キャリアアップを応援するサービスとして努力してまいりますので、 grooves をよろしくお願いします。

ユーザーニーズを把握する「UXリサーチ集中講座」に参加しました

みなさまこんにちは。 デザイナーの 711fumi です。

2017/11/18にユーザーニーズを把握する「UXリサーチ集中講座」 に参加させていただきました。 いろいろな学びがあったので、感じたことをいくつかご紹介できればと思います。

講座概要

講師は樽本 徹也さん。 UXリサーチャ/ユーザビリティエンジニアとして幅広い製品のUX/UI開発に携わり、UXに関する講演や書籍の執筆もされています。

この講座では、UXリサーチで必須となる「3大手法」を、ワークショップを通じてわかりやすく解説してもらえます。

3大手法

  • ユーザーインタビュー:「師匠と弟子」モデルに基づいたインタビュー
  • ペルソナ:複数のユーザーを合成して作り出す仮想のユーザー像
  • ジャーニーマップ:ペルソナの行動や感情の変化を時系列に図式化

内容については前回参加された方のレポートを見ていただけるとわかりやすいです(まるなげ) UXリサーチ集中講座 参加レポート

ペルソナ考えたり(絵がうまいのうらやま) f:id:blog_711fumi:20171118144146j:plain

ジャーニーマップ作ったり(温泉&ビール含めてトレランです) f:id:blog_711fumi:20171118175302j:plain

デザイナーとしての学び

イノベーションはユーザーテストから生まれない

プロダクトを実際に操作してもらいユーザーを観察する「ユーザーテスト」を行い、その結果を元に改善するという手法はよく行われています。 これは現在のプロダクトの機能を改善するという目的には繋がるのですが、そもそも「プロダクトがユーザーのやりたい/解決したいに沿っているか」は検証しづらい部分があります。
(数値分析なんかも同じかなと)

そこで今回学んだような「ユーザーリサーチ」を行い真のユーザーニーズを探ることが、プロダクトそのものの価値を検討する、より良い価値を提供するためのアイディアを考える際に有用なのかなと感じました。

また講座の中で「ユーザーの意見を集めるな、ユーザーの体験(UX)を集めろ」という話がありました。 「ユーザーのプロダクトに対する意見」ではなく「ユーザーの体験」から汲み取れる真のニーズから発想をスタートさせることが、プロダクトを大きく成長させるために重要そうです。

インタビュイーは聞かれたことしか答えない

インタビュイーは聞かれた事に対して「相手が欲しがっているのはこのくらいの情報だろうな」と考え要約して答えを返してくれます。 しかし我々が集めたいのはユーザーの体験なので、どんどんワードを捕まえて深掘り(質問)していく必要があります。 これが難しい…

講座ではユーザーの体験を引き出すコツみたいなものも教えていただいたのですが、特に印象に残ったのが「時間軸にそって質問する」というテクニックでした。
ユーザーが質問に答えてくれた時、「その前はどうだったのか」「その後どうしたのか」を質問することで、ユーザーがプロダクトに関わっている間(更にその前後も)の体験をズルズル引き出すことができますね。
ある行動の前後を掘り下げることで、「なぜその行動に至ったのか」「その行動がどう影響したのか」などの背景も引き出しやすくなるように思いました。

組織の認識を揃えるツールである

この講座ではペルソナやジャーニーマップなどのアウトプットの作成方法が学べるのですが、そういった見える形で「組織(プロダクト)の立ち返るべき情報」が存在しているというのはとても意味のあることではないかと思いました。
プロダクト(私の場合だとWebサービス)を日々運用していると、常にチームは「やるべきこと/やらないこと」の判断を求められます。
細かな機能改善から今後の開発方針まで「ほんとうに必要か」「今やるのか」「誰を喜ばせたいのか」などをリソースやビジネス状況を見比べつつ判断していかなければなりません。

しかし今回学んだような調査〜整理をおこない、私達のプロダクトが「いつ・誰の・何を」解決すべきなのかをはっきりさせておくことができれば、日々の判断での誤り(一貫性のなさ)や判断の難しさを減らすことに大きく役立つのではないかと感じています。

参考記事: UXデザインのために作成される主要な資料一覧

まとめ

書籍などでUX調査が必要という知識は得られても「どのようにやればよいのか」「何を意識しておこなうべきか」などを体感できる機会というのはなかなかありません。 今回ワークショップという形で、様々な業種職種の方と一緒に体験できたことは本当に貴重な経験になりました。

あとは自分のプロダクト開発に適応させるだけ!(それがむずかしい

おまけ

とかいろいろ書いていますが、私自身まだUXリサーチ初心者です(*´σー`)エヘヘ 一緒にgroovesのプロダクトを成長させてくれる人募集してます!

デザイナー
https://www.wantedly.com/projects/164427

エンジニア
https://jobs.forkwell.com/grooves#jobs