「動く」より「壊れない」の方が難しいと知った話
新人エンジニアの頃、私はこう思っていました。
「コードは動けば完成」
・画面が表示される。
・DBに保存される。
・エラーが出ない。
それだけで実装完了だと思っていました。
しかし実務を経験していく中で この考え方は完全に崩れます。
実際の開発で重要なのは動くことではなく壊れないことでした。
今回はなぜ「動く」より「壊れない」の方が難しいのかを、実務で感じたことを交えながら書いてみます。
新人の頃の私は「動いた瞬間」に満足していた
例えばユーザー登録機能を作ります。
@PostMapping("/users")
public void register(UserDto dto){
User user = new User();
user.setName(dto.getName());
user.setEmail(dto.getEmail());
userRepository.save(user);
}
きちんとこの内容で保存される。
OK、完成
新人の頃は本気でそう思っていました。
しかし実務では このコードを見ると色々気になります。
・バリデーションは?
・重複登録は?
・例外時は?
・トランザクションは?
・ログは?
当時の私はいや、動いてるじゃん…と思っていました。
でも実務では動くことは最低条件でしかありませんでした。
実務では「壊れ方」が重要だった
あるとき、実際にこんなことがありました。
ユーザー登録と同時に ポイント付与処理を追加したときです。
userRepository.save(user);
pointService.addPoint(user);
ローカルでは正常に動きます。しかし本番で障害が起きました。
ユーザー登録成功
↓
ポイント付与失敗
結果
登録はされている
でもポイントはない
という状態になりました。つまりデータ不整合です。
新人の頃の私は動けばOKと思っていました。
でも実務では失敗したときにどう壊れるかの方が重要でした。
「動くコード」は意外と簡単
正直な話、動くだけなら意外とできます。検索すればサンプルもあります。AIもコードを書いてくれます。でも難しいのは安全に動き続けることです。
例えば実務ではこういう問題が起きます。
・大量アクセス
・想定外入力
・同時更新
・通信失敗
・DB障害
つまり現実は想像以上に壊れるということです。
壊れないコードとは何か
実務をやっていて思うのは壊れないコードとは異常系を考えたコードです。
例えばこれ。
sendMail(user.getEmail());
一見普通です。でもメールアドレスがnullなら落ちます。そこで実務ではこう考えます。
if(user.getEmail() != null){
sendMail(user.getEmail());
}
新人の頃はそんなデータ来ないでしょと思っていました。
でも実務では普通に来ます。むしろ想定外は必ず起きる前提で設計します。
「壊れない」は設計の話になる
新人の頃は設計 = 面倒なルールだと思っていました。しかし今思うと設計 = 壊れにくくする技術でした。
例えばレイヤー構造。
Controller
↓
Service
↓
Repository
新人の頃は**なぜこんなに分けるの?**と思っていました。
でも実務では変更時の影響範囲を小さくするために必要でした。
つまり設計は未来の障害を減らすためのものだったのです。
本当に怖いのは「壊れるコード」
実務で一番怖いのはエラーが出るコードではありません。
本当に怖いのは一見正常に見える壊れ方です。
例えばデータが一部だけ保存されるとか特定条件だけ壊れるです。
こういう不具合は気づくのが遅いので危険です。
新人の頃はエラーが出なければOKと思っていました。
でも実務では静かに壊れる方が何倍も怖いと知りました。
個人的な気づき
一番大きかった気づきはこれです。
コードは「成功」より「失敗」を設計するということです。
新人の頃は「成功パターン」しか考えていませんでした。
しかし実務では
・失敗時
・異常系
・障害時
を考える時間の方が長いです。つまり、壊れないコードとは失敗を前提にしたコードなんだと思います。
まとめ
新人の頃は動くコード = 良いコードだと思っていました。
しかし実務を経験して分かったのは動くことは最低条件だということです。
本当に難しいのは
「壊れにくい」・「安全」・「変更に強い」
コードを書くことでした。
もし新人の頃の自分に
一言アドバイスするならこう言います。
動いた瞬間はゴールではない
そこがスタート