設計の健全性をそこなうさまざまな悪魔たち
ソフトウェア設計における悪習や問題点について、本章ではさまざまなケースを取り上げている。それぞれの問題に共通するのは、可読性や保守性を損ない、バグの温床となることである。以下、それぞれの問題点とその対策について述べる。
デッドコード
デッドコードとは、どんな条件でも決して実行されないコードのことである。これが残ると、可読性が低下し、将来的なバグの原因になり得る。
問題点
- 読み手に「このコードはどのような条件で実行されるのか?」と考えさせてしまう。
- 実行されないコードの意図を読み取る必要が生じる。
- 仕様変更により到達可能になると、適切にメンテナンスされていないコードがバグを引き起こす。
対策
- デッドコードは見つけ次第削除する。
- GitHub などのバージョン管理システムを活用し、削除に対する不安を軽減する。
デッドコードは、見つけたら積極的に削除すべきだが、長期間使われていないコードの判断は難しい。そのため、デッドコード検出ツールを活用するとよい。
YAGNI 原則
YAGNI (You Aren’t Going to Need It) の原則とは、「今必要でないものは実装しない」という考え方である。
問題点
- 先回りで作られたロジックは複雑化し、可読性を低下させる。
- 結局ほとんど使われないことが多く、デッドコードになる。
- 実装の手間が無駄になる。
対策
- 今必要な機能だけを作り、構造をシンプルに保つ。
- 仕様にない実装を追加することと、拡張可能な設計を行うことを混同しない。
ついついやってしまいがちなので、常に意識しておくべきポイントだろう。
マジックナンバー
コード内に直接記述された意図不明な数値(マジックナンバー)は可読性を大きく損なう。
問題点
- 実装者本人しか意図を理解できない。
- 同じ数値が異なる意味で使われる可能性がある。
- 重複コードが発生しやすい。
対策
- 定数として定義する。
-
ZERO
,ONE
などの自明なものを定義しないよう注意する。
文字列型執着
文字列に複数の値を詰め込んで管理する設計は、可読性や保守性を大きく損なう。
問題点
- 意味がわかりにくくなる。
- ロジックが無駄に複雑化する。
- クラスや変数の追加を避けることで、負債が蓄積する。
対策
- 意味の異なる値は別の変数やクラスで管理する。
- 適切なデータ構造を採用する。
グローバル変数
どこからでもアクセス可能なグローバル変数は便利だが、管理が難しくバグの原因になりやすい。
問題点
- どこで値が変更されたのか把握しづらい。
- 影響範囲が広がり、修正が困難になる。
- 排他制御が必要になる場合がある。
対策
- 影響範囲を最小化するように設計する。
- 無関係なロジックからアクセスできないようにする。
- グローバル変数を使用する場合は、その必要性をしっかり検討する。
Singleton の設定情報など、例外的に許容されるケースもあるが、意図が明確であることが重要である。
null 問題
null を多用するとバグの原因になりやすく、扱いを誤ると設計が破綻する。
問題点
- null は「未設定状態」ではなく「未初期化状態」を意味するため、誤用されやすい。
- null を前提としたコードは、予期せぬエラーを引き起こす。
対策
- null を返さない・渡さない設計にする。
- Value Object などを利用して、未設定状態を適切に表現する。
今まで意図的に null を使ってきたが、設計としては誤りだった可能性がある。null 安全を意識した設計を心がけたい。
例外の握り潰し
例外をキャッチして何も処理をしないことは、バグの温床となる。
問題点
- エラーが発生しても外部から検知できなくなる。
- 内部的にデータが壊れていても気づけない。
対策
- 例外を適切に処理し、異常が発生したことを検知できるようにする。
- 最低限ログを記録する。
設計秩序を破壊するメタプログラミング
Reflection などのメタプログラミング機能は便利だが、使い方を誤ると設計の一貫性を破壊する。
問題点
- private や final などの保護が無効化される。
- 静的解析が機能しなくなる。
対策
- 可能な限り使用を避け、解析用途に限定する。
- クラスのインスタンス化やメソッド呼び出しに文字列を使わない。
技術駆動パッケージング
技術的な観点でパッケージングすると、可読性が低下し、凝集度が下がる。
問題点
- クラス間の関連が分かりづらくなる。
- 低凝集な構造になり、管理が難しくなる。
対策
- ビジネス概念に基づいてパッケージを構成する。
- フレームワークのデフォルト構造に引っ張られないよう注意する。
まとめ
本章では、設計を損なうさまざまな悪習について述べた。どれも共通するのは、「コードの可読性と保守性を高める」という視点を持つことが重要であるという点である。具体例を参考にしながら、日々の開発でより良い設計を意識していきたい。