安全なリリースのために心がけていること

こんにちは。会員事業部の高田です。今回は安全にリリースをするために、アプリケーションエンジニアとして心がけていることについて書きます。

クックパッドではなるべく早くユーザーに価値を届けることを大切にしているため、1 日に何度も安全にリリースできるしくみや、リリース後に発生したエラーにすぐに気付けるしくみがあります。しかし、アプリケーションレイヤーの問題はアプリケーションエンジニアが気をつけなければいけません。私個人としては、少し気をつければ防げた問題を起こしてユーザーや会社に迷惑をかけてしまった経験があるため、注意深くなっています。

プロジェクトの大きさや目的はさまざまあり、早くリリースして検証したい施策などもあると思います。今回は慎重にリリースしたいプロジェクトの例として、有料会員の解約の前に特定のユーザーにのみクーポンを配布するという架空のプロジェクトを元にお話します。

1. 準備

リスクを洗い出す

まずは、避けるべきケースについて、ユーザーへの不利益や会社への不利益などの観点から洗い出します。

  • 文言に誤りがありユーザーの信頼を失う
  • クーポンが使えない
  • 解約したいのに解約できない
  • 対象でないユーザーにクーポンが配布される

早い段階でリスクについて考えておくと、リスクを避けるための行動の漏れを防ぎやすくなります。私は最近はプロジェクトが開始した段階で、GitHub Enterprise に専用のレポジトリをつくり、最初の issue として「リスクの洗い出し」を登録しています*1

ダブルチェック体制をつくる

開発者とは別の視点で動作確認をすることで、問題を事前に防ぐことができます。

体制が整っていればさほど気にすることはないですが、初めてのメンバーとプロジェクトを進める場合やメンバーが一人の場合には、スケジュールから漏れてしまわないよう、そもそも「ダブルチェックを行う」ということを理解してもらうこと、「ダブルチェックを行う人」を明確にしておくことが大切です。

ダブルチェックをする際のチェックリストをつくるには、洗い出してあるリスクが役に立ちます。

2. 開発中

テストを書くことやレビューをすること、実際に動かして動作確認することは当然ですが、もう一つ心がけたいのは本番環境で動作確認できないところを減らすことです。

私は本番環境での動作確認がしにくく省略してしまったためにバグを発生させてしまった経験があり、今では「本番環境で動作確認できないところにはバグがある」と思っておくくらいがいいと考えています。

今回の例だと、実際にクーポンを使えることや退会できることを確認したいものです。本番環境で対象ユーザになることが難しければ、Chankoのような対象ユーザを管理しやすいライブラリを使うのもよいですし、単にテストユーザ用の条件分岐を追加するのもよいでしょう。

3. リリース前

リリース日は慌てないようにします。リリース予定時間の前後にミーティングが入っていたり、翌日リリース予定の別タスクを抱えていたりするような場合は、ワーストケースが発生しても早めに気づいて対応する余裕があるか考えてみます。余裕がないようであれば、責任をもって関係者に相談して余裕をもつようにします。

4. リリース後

本番環境での動作確認だけでなく、リスクのある事象が発生していないかを確認します。

  • 退会するユーザがリリース前と比べて増えたり減ったりしていないか
  • クーポンが実際に使われているか
  • アクセスログを見て、対象でないユーザがクーポン配布ページに進んでいるということがないか

など、確認できることはいろいろあると思います。

まとめ

私が失敗を通して学んだことを元に、安全にリリースするためにこころがけていることについて書きました。

はじめに触れたとおり、プロジェクトの特徴はさまざまなので、ここで書いたような手順がまったく必要ない場合も、もっと慎重にしなければいけない場合もあると思います。そのような場合でも、考えるきっかけとしてなにかの参考になれば幸いです。

*1:プロジェクトの目的や有効性などについては十分議論されていることを前提としています

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/