新規事業立ち上げ時に、自分のミスで売り上げを飛ばした話

# はじめに
## なぜ書こうと思ったのか
[本番環境でやらかしちゃった人 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/yarakashi-production) を楽しく読ませて頂いており、
楽しい(ある意味面白い)気持ちや、胃がキリキリするような感覚や、色んな感情が渦巻きました。
(書いてくださってる方々ありがとうございます！)

そこで、AdventCalendarの記事ほどのインパクトはないですが、
自分も本番環境でやらかしたことを、自戒の意味も込めて書こうと思い立ちました。
あまり詳細には書いておらず、技術的な要素はほぼ出てきませんが、ご了承ください。

# 背景
## いつの出来事か
数年前に、自社のWEBサービスを展開している企業にて、バックエンドエンジニアをしていた時代です。
新規事業としてECサービスが立ち上がることとなり、その事業にエンジニアとしてジョイン、
リリースはしたものの、まだ新規事業ということもあり、日々かなり忙しく働いている中での出来事になります。
また、赤字状態だったため、早く黒字化する、1円でも多く稼ぐといった意識が
事業メンバー全体にかなり浸透していた時代でもあったと思います。

## 当時のプロジェクト体制
全体の事業メンバーとしては10名ちょっとくらい。
立ち上がったばかりの事業で赤字状態、人件費をあまりかけれなかったこともあり、
メイン担当のエンジニアとしてはバックエンドエンジニア1名(これが自分)/フロントエンドエンジニア１名の状態でした。
(バックエンドエンジニアの方は他にもいましたが、複数プロジェクトを見ている方だったため、稼働率でいえばあまりなかった状態です。)

# 何が起きたのか
一言で言うと、決済処理に外部の決済サービスのAPIを使っていましたが、自分の実装ミスでこのAPIの使い方が間違っており、
特定条件下で商品を購入するとエラーが発生、購入出来ないといったバグを発生させてしまいました。

# バグの発覚
当時エラーを検知する仕組みとして、 プログラム内で `Exception` を補足した場合に
アラートメールを飛ばすといった簡単な仕組みを導入していました。
(今考えるとイケてないですが・・・。)

その為、夜間の時間帯にアラートメールが飛んできて、発覚しました。

# エラーの原因
## システム側
当時決済サービスのAPIへのリクエストとして、下記なようなものを送信していました。
(あくまでサンプルです)

```json
{
  "token": "abcedfghijklmnopqrstu"  // 購入者・カード情報を表すトークン情報
  "price": 25000,                   // 商品の価格
  "title": "商品名A"                 // タイトル(当時はここに商品名を記述)
  "description":  "商品名Aの説明文"  // 説明情報(当時はここに商品の説明文を記述)
}
```

今回エラーとなった原因となるのが、 `title` , `description` の部分です。
当時の自分は経験不足からか考慮が足りず、ユーザーが複数商品買った場合は、
深く考えずに下記のように、 `title` , `description` に `商品名` `商品の説明文` をそれぞれ連結した内容で入れていました。

```json
{
  "title": "商品名A/商品名B/商品名C",
  "description": "商品名Aの説明文/商品名Bの説明文/商品名Cの説明文"
}
```
察しのいい方だと、どうゆう場合にエラーになるか、既にわかったのではないでしょうか・・・・。


## エラー条件
エラーとなった操作としては、ユーザーが一定以上の商品(数十商品)を一度に購入すると、 
決済サービスAPIの `title` , `description` の最大長を超えてしまい、エラーとして返却されるといったものでした。
(今考えても本当に情けないです・・・)

先ほど記載しましたが、事業として赤字状態で早く黒字化する、1円でも多く稼ぐといったフェーズだった為、
大型の決済(数十万円くらい)を飛ばした自身としてのダメージ、ショックも大きく、当時かなり落ち込んだ覚えがあります。

# 対応方法
普通に `title` , `description` で送信する文字列に対して、
特定文字数以上だった場合に特定文字数まででまるめる処理を入れただけです。
また、それを気に、後回しになっていて導入できていなかった(メンテナンスが止まっていた)
テストの自動化も行うようになりました。

# 振り返り
## なぜ起きてしまったのか
下記の点があげられるかと思います。

### テスト不足
単純に自分のテスト足りていませんでした。
言い訳になってしまいますが、扱っている商材が比較的変わっており、平均商品単価として `30,000円` 近くするものだった為、
数十商品を一度に購入されるケースを自身として考慮/確認できていなかったです。
(恐らく購入頂いた方は何かしらの業者の方かと思います。)

### ドキュメントの確認不足
決済サービス側で提供頂いているAPIの、ドキュメントの確認不足もあると思っています。
もちろんある程度は読み込んでいましたが、最大長等といった部分はちょっと見て読み飛ばしてしまっていたため、
あらゆるケースを想定すべきだったと今でも反省しています。

### 集中力不足
これも完全に言い訳で、新規事業ということで仕方ない部分だと思いますが、
度重なる仕様変更は日常茶飯事、かなり多忙だったこともあり、個人的にかなり疲弊してしまい、
コーディングが雑になってしまっていたと思います。

### 不具合を事前に検出出来る体制がなかった
バックエンドエンジニアとしてフル稼働しているのがほぼ自分一人の体制だった為、
相互のコードレビューを行なっておりませんでした。
また、単体テストの自動化等も行えていなかったことが原因だと思います。

# 対処について
当然ですがCI/CDを構築して自動テストを回す、また相互レビューを実施するのが一番かと思います。
また、リリース時のレギュレーションについて、定義するのも大切なことなのかなと思います。

# 最後に
CI/CD等があるおかげで、ここ最近本番環境でやらかしてはいないですが、油断すると痛い目を見るのがシステム開発だと思います。
その為、自戒の意味を込めて、この記事を書かせて頂きました。
数年前の出来事なのに、今でも鮮明に思い出せます・・・。
(当時の事業メンバーの方、本当に申し訳ございませんでした。)

このケースを通じて、テストの重要さ・レビューの大切さが身に染みてわかりました。
新規事業だと、一刻も早い黒字化の為にクオリティよりも納期(スピード)を優先してしまいがちですが、
スピードを優先させすぎた結果、起きた事象だと思います。
(もちろん自分自身のスキル不足も大きいですが。)

エンジニアの方であれば、内容は違えど本番環境でやらかしたことがある方は結構な割合存在しているかと思います。
自分自身このケース以外に、新卒の時代にGitのリモートリポジトリ自体を消してしまったり、思い出深い失敗事例があります。
(当時Gitって何？って状態でした・・・。そんなやつがDelete権限持ってたのがそもそも謎ですが・・・。)

表現はアレですが、やらかしたことは仕方ないので、大きく反省しつつ、繰り返さないための仕組みが大切だと思います。
やらかした時こそ、前を向いて頑張りましょう！
手作業だとどうしてもミスは発生する為、可能な限り自動化していきたいものです！

読んで頂き、ありがとうございました！！

# 共に働くWebエンジニアを募集しています!
不動産SHOPナカジツでは自社サービスを作っていく仲間を募集しています。
詳しくは[Wantedly](https://www.wantedly.com/projects/134741)からお問い合わせください。
お待ちしております！