再代入を避けたコードで品質アップ!簡単で効果的なコード改善テクニック

コードの品質を上げ、メンテナンスしやすいコードを書くためには「再代入を避ける」ことが重要です。

本記事では、再代入がもたらすデメリットと、それを避けるためのコード改善方法についてC#のサンプルコードで詳しく解説します。

紹介するテクニックは、C#に限らず他のプログラミング言語にも応用可能です。シンプルで効果的な改善を目指しましょう!

目次

再代入のデメリットとは?

プログラムで変数に再代入を行うと、コードの可読性が下がり、バグが発生しやすくなります。

特に複雑な処理やロジックの中で変数が複数回再代入されると、意図しない動作を引き起こしやすく、デバッグも難しくなります。

そこで、「再代入を避ける」ためのテクニックを取り入れることが、コードの保守性と品質を向上させる重要なポイントになります。

再代入を避けるための基本的なテクニック

再代入を避けるための基本的なテクニックとして、以下のような方針があります。

  • 定数化(readonlyまたはconst):値が変更されない変数には、readonlyやconstを使いましょう。
  • 計算や操作の結果を新しい変数に保持:処理の中で新たな値が必要な場合は、新しい変数を定義して使用するようにします。

特にC#では、readonlyを活用することで再代入を防ぎ、コードの意図を明確にすることができます。

悪い例と良い例のコード解説

以下に、RPGゲームのキャラクターが経験値を獲得し、レベルアップするコードの例を示します。

public class Character
{
    public int ExperiencePoints;
    public int Level;

    public void GainExperience(int points)
    {
        ExperiencePoints += points;
        if (ExperiencePoints >= 100)
        {
            ExperiencePoints -= 100;
            Level += 1;
        }
    }
}

この例では、ExperiencePointsが複数回再代入されており、経験値の変動が複雑で分かりにくいコードになっています。また、Levelも加算される度に再代入され、どの時点でレベルアップしたのか把握しづらくなっています。

public class Character
{
    private readonly int _levelUpThreshold = 100;
    public int ExperiencePoints { get; private set; }
    public int Level { get; private set; }

    public void GainExperience(int points)
    {
        int newExperience = ExperiencePoints + points;
        if (newExperience >= _levelUpThreshold)
        {
            Level += 1;
            ExperiencePoints = newExperience - _levelUpThreshold;
        }
        else
        {
            ExperiencePoints = newExperience;
        }
    }
}

このコードでは、再代入のリスクを減らすためにreadonlyフィールド(_levelUpThreshold)を使用しています。

また、GainExperienceメソッドでは新しい変数newExperienceを定義して計算を行い、元のExperiencePointsに再代入する回数を最小限にしています。

このように、コードの可読性と保守性が大幅に向上しています。

C#で再代入を防ぐ手法

C#では、変数に再代入を防ぐために、readonlyconst キーワードを使用できます。これらのキーワードを使うことで、コード内での値の変更を制限し、再代入を防ぐ効果があります。ここではそれぞれの特徴と使用例について解説します。

readonly キーワード

readonly キーワードは、フィールド(クラス内の変数)の初期化後に再代入されることを防ぐために使用されます。readonly フィールドは、クラスのコンストラクタ内または宣言時にのみ初期化が可能です。そのため、オブジェクトが生成された後はそのフィールドの値を変更できなくなり、再代入を防ぐことができます。

public class Character
{
    public readonly int MaxHealth; // 初期化後に変更できないフィールド

    public Character(int maxHealth)
    {
        MaxHealth = maxHealth; // コンストラクタ内でのみ初期化可能
    }

    public void DisplayHealth()
    {
        Console.WriteLine("Max Health: " + MaxHealth);
    }
}

この例では、MaxHealthreadonly フィールドであり、コンストラクタでのみ初期化されています。生成後にこの値を変更することはできないため、再代入のリスクを防ぐことができます。

特徴

  • クラスのコンストラクタ内または宣言時に初期化する必要があります。
  • 初期化後に再代入できないため、不変の値として利用でき、変更不可の定数値にしたい場合に便利です。
  • オブジェクトが生成されるたびに異なる値を持つことができるため、インスタンスごとに設定可能です。

const キーワード

const キーワードは、完全に不変の定数を宣言するために使用されます。const フィールドは、プログラムがコンパイルされるときに確定するため、値は変更不可です。

const はクラスのどのインスタンスにも共通であり、定数として利用できるため、クラス内で同一の固定値を参照する際に使用します。

public class GameSettings
{
    public const int MaxLevel = 100; // クラス全体で共通の定数

    public void DisplaySettings()
    {
        Console.WriteLine("Max Level: " + MaxLevel);
    }
}

この例では、MaxLevelconst フィールドであり、常に100という固定の値を持ちます。この値はプログラムが実行中に変更することができず、すべてのインスタンスで同じ値を共有します。

特徴

  • 宣言時にのみ初期化でき、値を変更することはできません。
  • クラス全体で共有されるため、複数のインスタンスで同じ定数を利用する場合に適しています。
  • readonly と異なり、インスタンスの生成に依存せず、クラス全体で一度設定された値を使用します。

readonlyconst の使い分け

  • const は、プログラム全体で一貫して変わらない固定値に使用します。例として、物理的な定数や構成設定など、どのインスタンスでも共通の値を保持する場合に便利です。
  • readonly は、インスタンスごとに異なる初期値を設定し、オブジェクト生成後に再代入を防ぎたいフィールドに使用します。例えば、キャラクターの最大HPのようにインスタンスごとに異なる値でありながら、生成後は変更させたくない場合に適しています。

まとめ

  • readonlyconst の違い
    const はクラス全体で共通の不変の値に、readonly はインスタンスごとに異なる初期値を設定でき、生成後は変更不可となる値に使用します。
  • 再代入を防ぐ効果
    readonlyconst を使うことで、意図しない再代入を防ぎ、コードの可読性と信頼性が向上します。
  • 使用場面に応じた使い分け
    プロジェクトでの設定値やインスタンス固有の値に応じて、readonlyconst を適切に使い分けることで、バグの防止やメンテナンス性の向上に貢献します。

再代入を防ぐことで、コードはより直感的で信頼性の高いものになります。readonlyconst を活用したコーディングは、長期的に見て保守やデバッグを容易にし、開発の質を上げるための基本的な手法です。

これらの小さな工夫が、大規模なプロジェクトや長期的な開発で大きな差を生み出します。日常の開発にぜひ取り入れて、堅牢なコードを目指していきましょう。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次