WHERE句を忘れただけなのに

※前にいた会社での実話を元にしています（細かい部分は変えています）
※「こうはなったらアカン」という反面教師として読んでくださいやで…

# 初出社ワイ
ワイ「HTMLコーダーの無職やめ太郎です！」
ワイ「今日からよろしくお願いしますやで！」

社長「おう、よろしくな」
社長「ほな早速・・・**PHPでバックエンドの開発を頼むわ、一人で**」

ワイ「ファッ！？」
ワイ「でもワイ、バックエンドの経験ないですよ・・・？」
ワイ「ちょっとはPHPできますけど・・・」

社長「ﾁｮｯﾄﾃﾞｷﾙ？」
社長「ほな大丈夫やないか」

ワイ「いや、ちゃいます」
ワイ「初心者レベルってことですがな」

社長「ほな大丈夫とちゃうか」

ワイ「そうですわ」
ワイ「いわゆる完全に理解したレベルってことですわ」

社長「完全に！？」
社長「ほな大丈夫やないか」

ワイ「なんでそうなりますねん」
ワイ「とにかく、一人バックエンドは無理ですって・・・」

社長「おい・・・」
社長「リスク取らな、リターンも得られへんで！？」

ワイ「（ウシジマくんで見たやつや・・・！）」
ワイ「わ、分かりましたやで・・・！」

# 要件説明
社長「ほな、今回やってもらう仕事を説明していくで」
社長「既存のサイトに、ある機能を追加して欲しいねん」
社長「その機能とは、**メモ機能**や」
社長「ユーザー1人につき3件まで、ちょっとしたメモを残すことができる・・・」
社長「そういったシンプルな機能や」

ワイ「分かりました」
ワイ「でもワイ、SQLとか書いたことないんですが・・・」

社長「大丈夫や！リスク取ってこ！」

ワイ「（リスク大好きやな・・・）」
ワイ「はい！」

社長「ほなまず、テーブル設計から頼むわ」

# ワイのテーブル設計
ワイ「テーブル設計なんて、したことないで」

> 「ユーザー1人につき3件まで、ちょっとしたメモを残すことができる」

ワイ「っていうてたから・・・」

|メモID|ユーザID|メモ内容|
|-|-|-|
|1|1|ユーザー1のメモ1|
|2|1|ユーザー1のメモ2|
|3|1|ユーザー1のメモ3|
|1|2|ユーザー2のメモ1|
|2|2|ユーザー2のメモ2|
|3|2|ユーザー2のメモ3|
|1|3|ユーザー3のメモ1|
|2|3|ユーザー3のメモ2|
|3|3|ユーザー3のメモ3|

ワイ「↑こんな感じでええか！」
ワイ「メモIDがユニークじゃないけど」
ワイ「ユーザIDとメモIDを組み合わせることでユニークキーになるから大丈夫や！」
ワイ「**複合主キー**ってやつやな！」
ワイ「へへっ、ワイも少しは知ってんねん」

# テーブル設計のレビュー
ワイ「社長、テーブル設計できましたやで！」
ワイ「レビューお願いしまs」

社長「**LGTM！**」
社長「さっそく実装頼むわ！」
社長「ちなみに、**納期は今日中や！**」

ワイ「ファッ！？」
ワイ「が、頑張りますやで・・・」

# 実装
ワイ「よーし、初めてのバックエンド、頑張るで・・・」

**〜12時間経過〜**

ワイ「よっしゃ、メモの追加機能と更新機能は完成したで！」
ワイ「疲れで頭がクラクラしてきたわ・・・」
ワイ「でも、あとは**削除機能**だけや・・・！」
ワイ「レッドブル飲んで、頑張ってコード書くで！」
ワイ「**レッドブルコード**が大事って言うしな！」

社長「（いやそれ**リーダブルコード**やろ・・・）」
社長「（まぁええか）」

ワイ「削除機能は、SQLでいうと`DELETE`文やな！」
ワイ「メモテーブルから、指定したIDのメモを削除できればいいから」
ワイ「例えばメモIDが1のやつを削除したい場合には・・・」

```sql
DELETE FROM table_memo WHERE MemoId = 1
```

ワイ「↑こうやな！」
ワイ「実装していくで〜！」

# 完成→動作確認してみる
ワイ「よっしゃ、削除機能も完成や！」
ワイ「ほな、実際にユーザーとしてログインして、メモ機能を試してみるで！」
ワイ「登録・更新・削除！」
ワイ「登録・更新・削除！」
ワイ「ヨシ！」

# 社長に提出
ワイ「社長！」
ワイ「メモ機能、完成しました！」
ワイ「コードレビューお願いしまs」

社長「**LGTM！**」

ワイ「あ、ありがとうございますやで」

# テスターさんによるテスト
テスターさん「登録・更新・削除！」
テスターさん「登録・更新・削除！」
テスターさん「あれっ！？メモが消えた！？」

ワイ「え！？」
ワイ「何か問題ありました！？」

テスターさん「大丈夫です！」
テスターさん「私のやり方が変だっただけだと思います！」
テスターさん「PCから操作したり、スマホから操作しちゃったりしてたんで」

ワイ「そ、そうでっか・・・」
ワイ「（でも、それって普通の操作では・・・？）」

# 結局、テスト通過
テスターさん「登録・更新・削除！」
テスターさん「登録・更新・削除！」
テスターさん「ヨシ！」

社長「ヨシ！」
社長「リリースや！」

# クライアント様からクレームが来た
社長「やめ太郎・・・やってくれたな・・・」
社長「**メモが消えてなくなる**不具合が出とるらしいで・・・」

ワイ「す、すんまへん・・・」
ワイ「すぐ確認しますやで・・・」

# 削除機能のコードを調べてみる

ワイ「あれ・・・もしかして・・・」
ワイ「アカン・・・とんでもなく大事なことを忘れとったわ・・・」
ワイ「`WHERE`句の条件が足りてへんやんけ・・・」

```sql
DELETE FROM table_memo WHERE MemoId = 1
```

ワイ「↑こんな感じでSQL文を書くと・・・」
ワイ「**全ユーザーのメモ1が消えてまう**やないかい」
ワイ「太郎さんがメモ1を削除したら、次郎さんのメモ1も、三郎さんのメモ1も消えてまうやんけ・・・！」

```sql
DELETE FROM table_memo WHERE MemoId = 1 AND UserId = 1
```

ワイ「↑こんな感じで、ユーザーIDも条件に指定せなアカンかったんや・・・！」
ワイ「アカン、ワイの**レッドブルコード**のせいで」
ワイ「データさんが**翼を授かって**飛んでいってもうたんや・・・！」
ワイ「言うててもしゃあない、早速修正や！」

# 修正完了
ワイ「社長！修正しましたやで！」
ワイ「コードレビューお願いしまs」

社長「**LGTM！**」
社長「リリースや！」

# 陳謝

ワイ「すんませんでしたやで・・・」

社長「大丈夫や！誰にでもミスはあんねん！」

ワイ「（それを分かっているなら、何故コードレビューをしないんや・・・）」

社長「今回は、ほとんどのユーザーさんが使う前に気づけたし」
社長「問題なしや！」

ワイ「そ、そうでっか・・・？」

# 今回の反省点

- ワイの知識不足
- 人員不足
- レビュー体制不足
- レッドブルコード、データに翼を授ける
- 「納期短し、急げよテスター」状態になっていた
- そもそもテストケース不足
- 自動テストもしていない
- メモIDをユニークにして、単独の主キーにしていれば起こらなかった？
- 「メモID」という名前が良くない（ユニークな主キーに見える）
- 物理削除ではなく論理削除にしていれば、最悪でも復活できてよかった？
- 小泉進◯郎「リスクを取ると、リスクが大きくなります」

# 新しい記事もよろしくやで
- [6歳娘「パパ、条件によって変わる型を作りたいの」](https://qiita.com/Yametaro/items/9b2f0ab2037450004816)

# Zennにも記事を書いてみましたやで
- [独り言形式で綴る「OGP & SSR」](https://zenn.dev/tokumoto/articles/0098b3e850676f)

# noteも書いてますやで

- [ワイ「三角関数って、要らなくね？」](https://note.com/yametaro/n/n4ad2f07cde72)