そのフラグ変数、追加するのちょっと待った!
この記事では、プログラミングに関する知識やテクニックを共有しています。
いま、以下のようなLoaderクラスを考えます。このLoaderクラスは、サーバからデータを取得する機能を持っているとします。
class Loader {
// ロード中かを表すフラグ
bool isLoading
// ロードが完了しているかを表すフラグ
bool isLoaded
// ロードを開始するメソッド
func load() {
// Something to do.
}
}
ロード処理の進行状況を知るためにisLoading変数とisLoaded変数を持っています。
もう既にむむっと思う方もいるかもしれません。しかし、世の中にはこのようなプログラムが実在するのです。
さて、このLoaderクラスが取り得る状態の数は、
isLoading=false, isLoaded=false
isLoading=true, isLoaded=false
isLoading=false, isLoaded=true
isLoading=true, isLoaded=true
の4通りがあります(2 × 2 = 4通り)。まだこのくらいなら状態管理できそうですね。
ここで新しい仕様が追加されることになりました。
ロード処理が何らかの原因で失敗してしまうことがありました。そこで、エラー終了したかを知るためにisFailed変数を追加することになりました。
class Loader {
// ロード中かを表すフラグ
bool isLoading
// ロードが正常に完了しているかを表すフラグ
bool isLoaded
// ロードがエラー終了したかを表すフラグ
bool isFailed
// ロードを開始するメソッド
func load() {
// Something to do.
}
}
このときLoaderクラスが取り得る状態の数は、
2 × 2 × 2 = 8通り
となります。先程の状態数から2倍になってしまいました!
クラスにフラグ変数を1つ追加すると、そのクラスの取り得る状態の数は2倍になることを意識してください。
状態数が増えると、それだけ管理が難しくなっていきます。つまりバグを生みやすくなります。
ここでLoaderクラスが取り得る状態のパターンを見てみます。
isLoading=false, isLoaded=false, isFailed=false
isLoading=true, isLoaded=false, isFailed=false
isLoading=false, isLoaded=true, isFailed=false
isLoading=false, isLoaded=false, isFailed=true
isLoading=true, isLoaded=true, isFailed=false
isLoading=true, isLoaded=false, isFailed=true
isLoading=false, isLoaded=true, isFailed=true
isLoading=true, isLoaded=true, isFailed=true
そもそも上記の5,6,7,8の状態は起こりえないことを開発者は分かっています。
例えば、ロード中(isLoading=true)とロード完了(isLoaded=true)は同時には成り立ちません。正常終了(isLoaded=true)と異常終了(isFailed=true)も同時には成り立ちません。
このように開発者が分かっていても、プログラム上起きる可能性があるとき、意図せずバグを埋め込んでしまうことがあります。
例)フラグのリセットし忘れなど
バグを生まないためにも、できる限り可能性は潰しておきたいところです。
さて、上記のような同時に起こりえない事象を扱うときはenumを使うと便利です。
enum State {
// 初期状態
INIT,
// ロード中
LOADING,
// ロードが正常終了した
LOADED,
// ロードが異常終了した
FAILED
}
class Loader {
// 状態変数
State state = State.INIT
// ロードを開始するメソッド
func load() {
// Something to do.
}
}
enum Stateを使うことで、Loaderクラスが取り得る状態数は4通りに限定されます。
フラグ変数を安直に追加する前に、扱う事象を観察し、enumなどでリファクタリングできないか、検討してみてください。
この記事が気に入ったらサポートをしてみませんか?