8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

グレンジAdvent Calendar 2019

Day 22

【C#】バグを生みづらくする値型、列挙型のルール付け

Posted at

グレンジ Advent Calendar 2019 22日目を担当させていただきます ぐっち と申します。
新卒一年目で現在グレンジでUnityを用いてゲーム開発を行っています。

◆ 背景

エラーも出ず意図したメソッドもちゃんと通っているのになぜか挙動がおかしくなる。。。
とコードを追う時間を要してしまうことが多々ありました。
そこで原因の1つとなっているのが デフォルト値であったり初期化時のミス です。
今回はそういったことを回避するための自分のいるチームでもあるルールの1つを紹介します。

◆ 0は有効な値にし、不正値は -1 と統一する

.NETによるデフォルトの初期化は 全て「0」に設定 されます。
明示的に初期値を設定していない限り基本的に0スタートとなるので、例えばカウント処理を行いたい場合などインスタンス化しちゃえばそこから意図通りカウントアップしてくれます。
列挙型も同じで、値を明示的に指定しなければ0から始まり次の項目に行く毎にインクリメントされます。

では、以下の場合はどうでしょう?

Weekday.cs
public enum Weekday {
    Sunday = 1,
    Monday = 2,
    Tuesday = 3,
    Wednesday = 4,
    Thursday = 5,
    Friday = 6,
    Saturday = 7,
}

private Weekday weekday = new Weekday();

このような書き方をした場合、weekdayの初期値はどうなるでしょうか?
答えは、 無効な値(バグの原因) となります。理由は簡単、0の定義がないからです。
この場合は極端な例で、無効な値なのですぐに気づくことができます。
単純な話、これを解決する方法として 0を未初期化の値(入っていても問題ない更新可能な値) としていれておきます。

Weekday.cs
public enum Weekday {
    None = 0,
    Sunday = 1,
    Monday = 2,
    Tuesday = 3,
    Wednesday = 4,
    Thursday = 5,
    Friday = 6,
    Saturday = 7,
}

private Weekday weekday = new Weekday();

無事、weekdayには0が入り、有効な値となります。
ここで問題となってくるのが、 例外処理 です。
何かが問題で正常に処理が行われなかった時は例外の値を入れエラーを出したいです。
ではWeekdayの例外の値とはどれでしょうか?
Noneにしますか?した場合これは 未初期化の値(入っていても問題ない更新可能な値) として入れているため、エラーとはならずただただ値を待ち続け意図しない結果になるでしょう(関係ない場所でnullエラーとなり根本原因が解決できなかったり...など)

そこで、新たな値「 不正値 」を用意します。

Weekday.cs
public enum Weekday {
    Invalid = -1,
    None = 0,
    Sunday = 1,
    Monday = 2,
    Tuesday = 3,
    Wednesday = 4,
    Thursday = 5,
    Friday = 6,
    Saturday = 7,
}

private Weekday weekday = new Weekday();

こうすることで、
・-1なら例外処理をする
・0なら初期値もしくは初期化されてない値だから初期化されるのを待つ
・それ以外なら正常に使用できる値

として分類することができ、それぞれに適した処理を行うことができます。

◆ まとめ

・0はデフォルトで設定される値のため、有効な値として使用する
・不正値、初期値(または未初期化値)、正常値と分ける(混ぜて使わない)
・可能な限り全てのオブジェクトに対する0をデフォルト値(未初期化値)として扱う

これをするだけで初期値による不具合や設定された値によってバグが追いづらくなるといったことはかなり減らすことができると思います。
しかし、完全ではありません。enumへのフラグ付けやビット演算などさらに色々な工夫をすることもできるので、クライアントエンジニアとしてこれからもエラーのリスクを最小化できる方法を追求していきたいと思います。

参考

More Effective C# 6.0/7.0

8
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?