🔖

独自型で値の渡し間違いを防止すること

2022/07/18に公開

要約

独自型を引数にすることで、値の渡し間違いを防止することができる。

課題

以下のAddメソッドはプリミティブ型 int を引数としている。

    class Money
    {
        public int Amount { get; set; }
        public Currency Currency { get; set; }
        
        public Money(int amount, Currency currency)
        {
            Amount = amount;
            Currency = currency;
        }

        // プリミティブ型 int を引数とする加算メソッド
        public int Add(int amount)
        {
            return Amount + amount;
        }
    }

    enum Currency
    {
        JPY,
        USD,
    }

このAddメソッドの実装は良くない。
というのも、このメソッドは int 型であれば何でもコンパイルを通してしまう。
例えば、全然通貨量とは異なるチケットの枚数を加算しようとしても、コンパイルエラーにならない。

    var money = new Money(100, Currency.JPY);
    var ticketCnt = 3;
    money.Add(ticketCnt); // int 型であれば何でもコンパイルに通ってしまう

解決

こうした事態は、加算メソッドの引数を独自型、ここではMoney型にすることで解消できる。

    class Money
    {
	// 略
	
	// Money 型を引数に変更
        public Money Add(Money added)
        {
            if (!Currency.Equals(added.Currency))
            {
                throw new ArgumentException("通貨単位が異なります。");
            }
            return new Money(Amount + added.Amount, Currency);
        }
    }

これにより、元々コンパイルを許していたコードをコンパイルエラーにできる。

    var money = new Money(100, Currency.JPY);
    
    var ticketCnt = 3;
    money.Add(ticketCnt); // コンパイルエラーになる
    
    var added = new Money(200, Currency.JPY);
    money.Add(added); // 正しいコード

結論

プリミティブ型が引数だと値の渡し間違いが生じやすい。
引数を独自型にすることで、この種の誤りを防止することができる。

ただし、独自型にすることで、メモリを食うようになったり、わざわざ定義することが煩雑だというデメリットもある。
このデメリットとの兼ね合いにはなる。

参考資料

仙場大也『良いコード/悪いコードで学ぶ設計入門―保守しやすい 成長し続けるコードの書き方』技術評論社,2022,p. 31-32.

Discussion