バグを生みにくい実装2022/09/16山田悠之介
View Slide
目次1. バグを未然に防ぐ2. 読みやすいコードを書く2
1. バグを未然に防ぐ3
バグには種類があるバグはその発生原因によって分類ができます。『組込みソフトウェア開発における品質向上の勧め バグ管理手法編』は IPA による組込みソフトウェアについての文献ですが、Web アプリケーションにも共通する部分が多いです。この文献には「バグの区分」があります。今回は実装について触れます。4
バグの区分(実装区分の一部)ロジックの誤り条件の誤り、演算の誤り、などインターフェースの誤りnon null な引数に null を渡す、呼び出す関数を間違える、などタイミングの誤り処理を書く場所が違うエラーチェックの誤りエラーチェックをしない、後処理が適切でない機能の欠如仕様と実装が異なる 5
バグの区分(実装区分の一部)防ぎやすいものと防ぎづらいものがあります機能の欠如実装者が既存仕様や既存実装、新規仕様を正確に理解するタイミングの誤り理解した処理の流れを正確にコードに落とし込むこれらを防ぐのは属人的で、比較的難しいです。インターフェースの誤り例えば関数の型を厳密に付けることで、自分やその関数を利用する他の実装者もバグを防げます。 6
型についてanyは論外ですライブラリの型がanyを含む場合そのまま使わないstringは改善の余地があります日付 →DateURL →URL種類が有限 → Literal types種類は有限ではないが規則がある → Template literal typesnumberも同様です7
「エラーチェックの誤り」JavaScript の例外は非検査例外なので例外処理を忘れがちです。例外を投げるのはやめましょう。以下のようにすることでエラーチェックを強制できます。type Data =| {value: Value;error: undefined;}| {value: undefined;error: Error;};8
「ロジックの誤り」簡単に防げるものもあります。==,!=ではなく===,!==を使うisNaN()ではなくNumber.isNaN()を使うif 文の{}を省略しないデフォルトパラメータを使うx ?? yのような処理を何回も書くのは良くない返り値の型を書くコンポーネントは JSX スタイルで使う9
正規表現を避ける正規表現は強力ですが問題も多いです。正しいか分かりづらいパフォーマンスが悪くなることがある別の方法がある場合は避けたほうが良いです。数値形式の場合isNaN()を使えないか日付形式の場合はDate、URL 形式はURLのコンストラクタでパースするstartsWith,includes,endsWithなどで代用できないか10
Falsy に注意する特に""に注意が必要です。新フォーム定義では Falsy な値によるバグがいくつか出ました。if(str)ではなくif(str !== undefined)やif(str !== "")ではないか考え直しましょう。numberの場合もNaNはダメだが0は OK か、など考えましょう。11
2. 読みやすいコードを書く12
どんなに気をつけてもバグは生まれる1 人でどんなに気をつけてもバグる時はバグります。もし、あなたのコードがバグっていたとしても読みやすいコード、読みやすい PR ならレビューで発覚する可能性があります。もし、発覚せずにマージされたとしても読みやすければ将来調査、修正がしやすいです。もし、バグっていなかったとしても、今後何回も読まれます。読みやすければ将来の自分や他の開発者の生産性を上げます。(逆にそうでない場合、他人の生産性を下げることになります)13
読みやすいコードを書く読みやすい名前を付ける例えばidは分かりづらいコメントを書くオプショナル引数はどういう時に必要なのか処理の場合、なぜそうしたのか、逆になぜ別の方法にしなかったのか書く関数を分ける一度に 1 つのことをするpure な関数はテストしやすい14
読みやすいコードを書く読みやすいテストを書くテストは振る舞いの説明ですコミットを分ける一度に 1 つのことをするこれらの多くは『リーダブルコード』にも書かれています。15
無駄な処理をしない不必要な処理をしていると、それを読んだ人は「もっと簡単な方法があるのになぜそうしないのだろう」と考えてしまいます。必要十分な処理を書きましょう。三項演算子を減らす返り値を使わない場合mapではなくforEachuseState,useEffectを減らすstate と effect は React のライフサイクルで特別なもの16
ネストしないネストしたコードは読みづらいです。early return する必要なら関数に切り出す三項演算子を使わないif 文のネストのほうがマシですコールバックを使わないthenではなくasync,awaitを使いましょう17
正解はない読みやすいコードを書くためのポイントは限りがないです。どのようなコードが読みやすいか、どうしたら自分のコードが分かりやすくなるか考える続ける必要があります。例えば PR を出す前にもっと良いやり方がないか何回も(1 回ではない)考えましょう。18
参考『組込みソフトウェア開発における品質向上の勧め バグ管理手法編』https://www.ipa.go.jp/sec/publish/tn12-005.html『リーダブルコード』『Airbnb JavaScript Style Guide』https://github.com/airbnb/javascript19