基礎から学ぶC#入門 90日コース | 制御構文・メソッド - Day 17:メソッドの分割

Web APP 90日で身につけるC#
スポンサーリンク
スポンサーリンク

Day 17 のゴールと全体像

Day 17 では、メソッドを「ただ書く」段階から一歩進んで、きれいに分割して設計する力を身につけていきます。 テーマは次の 4 つです。

  • 1つのメソッドに処理を書きすぎない
  • メソッド名
  • 単一責任の考え方
  • 再利用可能な処理

ここからは、「動けばいいコード」ではなく、「読みやすくて直しやすいコード」を意識していきます。

1つのメソッドに処理を書きすぎない

ありがちな「全部 Main に書いてしまう」パターン

初心者の方が最初によくやってしまうのが、すべての処理を Main メソッドに詰め込む書き方です。

例えば、簡易プロフィール入力プログラムを、あえて「悪い例」として書いてみます。

using System;

class Program
{
    static void Main(string[] args)
    {
        // 名前入力
        Console.WriteLine("名前を入力してください:");
        string name = Console.ReadLine();

        // 年齢入力
        Console.WriteLine("年齢を入力してください:");
        int age = int.Parse(Console.ReadLine());

        // 職業入力
        Console.WriteLine("職業を入力してください:");
        string job = Console.ReadLine();

        // 趣味入力
        Console.WriteLine("趣味を入力してください:");
        string hobby = Console.ReadLine();

        // 表示
        Console.WriteLine("=== プロフィール ===");
        Console.WriteLine($"名前:{name}");
        Console.WriteLine($"年齢:{age}");
        Console.WriteLine($"職業:{job}");
        Console.WriteLine($"趣味:{hobby}");

        // 年齢によるメッセージ
        if (age < 20)
        {
            Console.WriteLine("まだまだこれからですね!");
        }
        else if (age < 40)
        {
            Console.WriteLine("脂が乗ってきましたね!");
        }
        else
        {
            Console.WriteLine("経験豊富ですね!");
        }

        Console.ReadLine();
    }
}
C#

一見すると分かりやすいですが、

  • 入力
  • 表示
  • メッセージ判定

が全部 Main に詰め込まれていて、役割がごちゃ混ぜになっています。 このまま機能を増やしていくと、すぐに「どこを直せばいいか分からない」状態になります。

メソッドで処理を分割する

「役割ごとにメソッドを分ける」という発想

さきほどのコードを、「役割ごとにメソッドに分ける」ことを考えてみます。

  • 入力する処理
  • 表示する処理
  • 年齢メッセージを決める処理

を、それぞれ別のメソッドにしてみます。

using System;

class Program
{
    // プロフィール情報をまとめるための型がまだないので、
    // ここでは個別の値を扱う形で分割していきます。

    // 名前を入力するメソッド
    static string InputName()
    {
        Console.WriteLine("名前を入力してください:");
        return Console.ReadLine();
    }

    // 年齢を入力するメソッド
    static int InputAge()
    {
        Console.WriteLine("年齢を入力してください:");
        return int.Parse(Console.ReadLine());
    }

    // 職業を入力するメソッド
    static string InputJob()
    {
        Console.WriteLine("職業を入力してください:");
        return Console.ReadLine();
    }

    // 趣味を入力するメソッド
    static string InputHobby()
    {
        Console.WriteLine("趣味を入力してください:");
        return Console.ReadLine();
    }

    // プロフィールを表示するメソッド
    static void ShowProfile(string name, int age, string job, string hobby)
    {
        Console.WriteLine("=== プロフィール ===");
        Console.WriteLine($"名前:{name}");
        Console.WriteLine($"年齢:{age}");
        Console.WriteLine($"職業:{job}");
        Console.WriteLine($"趣味:{hobby}");
    }

    // 年齢に応じたメッセージを返すメソッド
    static string GetAgeMessage(int age)
    {
        if (age < 20)
        {
            return "まだまだこれからですね!";
        }
        else if (age < 40)
        {
            return "脂が乗ってきましたね!";
        }
        else
        {
            return "経験豊富ですね!";
        }
    }

    static void Main(string[] args)
    {
        // 入力部分
        string name = InputName();
        int age = InputAge();
        string job = InputJob();
        string hobby = InputHobby();

        // 表示部分
        ShowProfile(name, age, job, hobby);

        // 年齢メッセージ表示
        string message = GetAgeMessage(age);
        Console.WriteLine(message);

        Console.ReadLine();
    }
}
C#

ここで押さえておきたいポイント

  • Main は「流れを組み立てる場所」として、高レベルな処理だけを書いています。
  • 入力・表示・メッセージ判定は、それぞれ専用のメソッドに分かれています。
  • どのメソッドが何をしているか、名前から分かるようになっています。

これが、「1つのメソッドに処理を書きすぎない」という考え方の具体例です。

メソッド名と単一責任の考え方

単一責任とは

単一責任とは、

1つのメソッドは、1つのはっきりした役割だけを持つ

という考え方です。

  • 入力するメソッドは「入力だけ」
  • 表示するメソッドは「表示だけ」
  • 判定するメソッドは「判定だけ」

というように、役割を分けていきます。

メソッド名は「何をするか」が分かるように

メソッド名は、そのメソッドの責任を表す名前にすることが大切です。

  • InputName → 名前を入力する
  • ShowProfile → プロフィールを表示する
  • GetAgeMessage → 年齢に応じたメッセージを取得する

このように、

  • 「動詞 + 目的語」
  • 「何をするか」が一目で分かる

名前にしておくと、コードを読む人(未来の自分も含めて)が理解しやすくなります。

再利用可能な処理を意識する

「また使いそうだな」と思ったらメソッドにする

メソッド分割のコツは、

「この処理、また別のところでも使いそうだな」

と思ったら、迷わずメソッドに切り出すことです。

例えば、区切り線を表示する処理は、いろいろな場面で使えます。

static void PrintSeparator()
{
    Console.WriteLine("================================");
}
C#

これを使うと、どんなプログラムでも簡単に見やすくできます。

static void Main(string[] args)
{
    PrintSeparator();
    Console.WriteLine("メニュー");
    PrintSeparator();

    Console.ReadLine();
}
C#

「再利用できるか?」を分割の判断材料にする

  • 何度も同じようなコードを書いている
  • 別の画面や別の機能でも同じ処理が必要になりそう

というときは、

  • その処理をメソッドにする
  • 引数と戻り値を使って汎用的にする

ことを意識すると、再利用可能な部品として育っていきます。

練習テンプレート:メソッド分割の型

入力・処理・表示を分ける基本テンプレート

using System;

class Program
{
    // 入力を担当するメソッド
    static int InputNumber()
    {
        Console.WriteLine("整数を入力してください:");
        return int.Parse(Console.ReadLine());
    }

    // 処理(ここでは 2 倍にする)を担当するメソッド
    static int DoubleNumber(int value)
    {
        return value * 2;
    }

    // 表示を担当するメソッド
    static void ShowResult(int original, int doubled)
    {
        Console.WriteLine($"元の値:{original}");
        Console.WriteLine($"2倍の値:{doubled}");
    }

    static void Main(string[] args)
    {
        int n = InputNumber();          // 入力
        int d = DoubleNumber(n);        // 処理
        ShowResult(n, d);               // 表示

        Console.ReadLine();
    }
}
C#

このテンプレートをベースに、

  • 処理部分を「合計」「平均」「判定」などに変えてみる
  • 入力を複数にしてみる
  • 表示内容を増やしてみる

といった練習をすると、「メソッドを役割ごとに分ける」感覚が自然に身についていきます。

Day 17 のまとめ

Day 17 では、

  • 1つのメソッドに処理を書きすぎない
  • メソッド名で「何をするか」を表現する
  • 単一責任の考え方(1メソッド1役割)
  • 再利用可能な処理をメソッドとして切り出す

という 4 つの視点から、メソッドの分割と設計を学びました。

これまで学んできた制御構文やメソッドを、「どう組み立てるか」というレベルで考え始めると、 コードはぐっと読みやすく、直しやすくなります。

ぜひ、

  • 既に書いたコードを見直して、「ここはメソッドに分けられないか?」と考えてみる
  • メソッド名を「何をするか」が分かる名前に整えてみる
  • 入力・処理・表示を分けるテンプレートを、自分なりにアレンジしてみる

といった練習を通して、「設計を意識したメソッド分割」の感覚を育てていってください。


Day 17 電卓課題のゴール

Day 17 の課題では、電卓プログラムをメソッドに分割することで、

  • 1つのメソッドに処理を書きすぎない
  • メソッド名で役割をはっきりさせる
  • 単一責任の考え方
  • 再利用可能な処理

を体で覚えていくことを目指します。

ここでは、電卓の基本機能を次の 4 つのメソッドに分割します。

  • Add():足し算
  • Subtract():引き算
  • Multiply():掛け算
  • Divide():割り算

電卓を「1つの巨大メソッド」で書いた場合

まずは、あえて「悪い例」として、すべての処理を Main に詰め込んだ電卓をイメージしてみます。

using System;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("1つ目の数値を入力してください:");
        double a = double.Parse(Console.ReadLine());

        Console.WriteLine("2つ目の数値を入力してください:");
        double b = double.Parse(Console.ReadLine());

        Console.WriteLine("演算を選んでください(+ - * /):");
        string op = Console.ReadLine();

        double result = 0;

        if (op == "+")
        {
            result = a + b;
        }
        else if (op == "-")
        {
            result = a - b;
        }
        else if (op == "*")
        {
            result = a * b;
        }
        else if (op == "/")
        {
            if (b == 0)
            {
                Console.WriteLine("0 で割ることはできません。");
                Console.ReadLine();
                return;
            }
            result = a / b;
        }
        else
        {
            Console.WriteLine("不正な演算子です。");
            Console.ReadLine();
            return;
        }

        Console.WriteLine($"結果:{result}");
        Console.ReadLine();
    }
}
C#

一見すると動きますが、

  • 入力
  • 演算の選択
  • 計算処理
  • エラー処理

が全部 Main に詰め込まれていて、役割がごちゃ混ぜになっています。 機能を増やしていくと、すぐに「どこを直せばいいか分からない」状態になります。

電卓をメソッドに分割する方針

単一責任で考える

電卓の処理を、次のように役割ごとに分けて考えます。

  • 計算する責任:足し算・引き算・掛け算・割り算
  • 入力する責任:数値や演算子を入力してもらう
  • 表示する責任:結果やメッセージを表示する

このうち、今回の課題では特に「計算する責任」を 4 つのメソッドに分割します。

  • Add(double a, double b)
  • Subtract(double a, double b)
  • Multiply(double a, double b)
  • Divide(double a, double b)

それぞれが「1つの計算だけ」を担当するようにします。

計算メソッドを定義する

Add:足し算メソッド

// 2つの数値の足し算を行うメソッド
static double Add(double a, double b)
{
    // a + b の結果をそのまま返します
    return a + b;
}
C#

Subtract:引き算メソッド

// 2つの数値の引き算を行うメソッド
static double Subtract(double a, double b)
{
    // a - b の結果を返します
    return a - b;
}
C#

Multiply:掛け算メソッド

// 2つの数値の掛け算を行うメソッド
static double Multiply(double a, double b)
{
    // a * b の結果を返します
    return a * b;
}
C#

Divide:割り算メソッド(0割りチェック付き)

割り算は「0 で割る」という危険があるので、少しだけ慎重に書きます。

// 2つの数値の割り算を行うメソッド
static double Divide(double a, double b)
{
    if (b == 0)
    {
        // 0 で割ろうとした場合は、メッセージを表示して 0 を返します
        Console.WriteLine("0 で割ることはできません。結果は 0 とします。");
        return 0;
    }

    return a / b;
}
C#

ここでの重要ポイント:

  • 各メソッドは「1つの計算だけ」を担当しています。
  • メソッド名から「何をするか」がはっきり分かります。
  • Divide だけは、割り算の責任に加えて「安全性の確保」という責任も持っていますが、 それも「割り算を安全に行う」という 1 つの目的にまとまっています。

電卓のメイン処理を「組み立てる」

メソッドを部品として使う

計算メソッドを定義したら、Main では「部品を組み合わせる」ことに集中できます。

using System;

class Program
{
    // 足し算
    static double Add(double a, double b)
    {
        return a + b;
    }

    // 引き算
    static double Subtract(double a, double b)
    {
        return a - b;
    }

    // 掛け算
    static double Multiply(double a, double b)
    {
        return a * b;
    }

    // 割り算(0割りチェック付き)
    static double Divide(double a, double b)
    {
        if (b == 0)
        {
            Console.WriteLine("0 で割ることはできません。結果は 0 とします。");
            return 0;
        }

        return a / b;
    }

    static void Main(string[] args)
    {
        // 数値入力
        Console.WriteLine("1つ目の数値を入力してください:");
        double a = double.Parse(Console.ReadLine());

        Console.WriteLine("2つ目の数値を入力してください:");
        double b = double.Parse(Console.ReadLine());

        // 演算子入力
        Console.WriteLine("演算を選んでください(+ - * /):");
        string op = Console.ReadLine();

        double result;

        // 演算子に応じて、対応するメソッドを呼び出します
        if (op == "+")
        {
            result = Add(a, b);          // 足し算メソッドを呼び出し
        }
        else if (op == "-")
        {
            result = Subtract(a, b);     // 引き算メソッドを呼び出し
        }
        else if (op == "*")
        {
            result = Multiply(a, b);     // 掛け算メソッドを呼び出し
        }
        else if (op == "/")
        {
            result = Divide(a, b);       // 割り算メソッドを呼び出し
        }
        else
        {
            Console.WriteLine("不正な演算子です。+ - * / のいずれかを入力してください。");
            Console.ReadLine();
            return;
        }

        // 結果表示
        Console.WriteLine($"結果:{result}");
        Console.ReadLine();
    }
}
C#

ここで押さえておきたいポイント

  • Main は「電卓の流れ」を書くだけで、計算の中身はメソッドに任せています。
  • 各計算メソッドは「単一責任」で、1つの演算だけを担当しています。
  • メソッド名が分かりやすいので、コードを読むときに「何をしているか」がすぐに分かります。

単一責任と再利用性の関係

「責任がはっきりしているほど、再利用しやすい」

  • Add は「2つの数値を足す」だけ
  • Subtract は「2つの数値を引く」だけ
  • Multiply は「2つの数値を掛ける」だけ
  • Divide は「2つの数値を安全に割る」だけ

というように、責任がはっきりしているメソッドは、

  • 別のプログラムでもそのまま使える
  • テストしやすい
  • バグが出たときに「どこを疑えばいいか」が分かりやすい

というメリットがあります。

例えば、将来「複雑な数式計算プログラム」を作るときにも、 この 4 つのメソッドはそのまま部品として再利用できます。

練習テンプレート:電卓メソッドを拡張してみる

べき乗や剰余を追加してみる

課題をさらに発展させて、

  • Power():べき乗(a の b 乗)
  • Mod():剰余(a を b で割った余り)

などを追加してみるのも良い練習になります。

// a の b 乗を計算するメソッド
static double Power(double a, double b)
{
    return Math.Pow(a, b); // Math.Pow は C# 標準のべき乗関数です
}

// a を b で割った余りを返すメソッド
static double Mod(double a, double b)
{
    if (b == 0)
    {
        Console.WriteLine("0 で割ることはできません。結果は 0 とします。");
        return 0;
    }

    return a % b;
}
C#

Main 側で、

  • 演算子に ^% を追加する
  • 対応するメソッドを呼び出す

という形で拡張していくと、

「メソッドを部品として増やしながら、電卓を育てていく」

感覚が身についていきます。

Day 17 電卓課題のまとめ

この課題では、電卓を次の 4 つのメソッドに分割しました。

  • Add()
  • Subtract()
  • Multiply()
  • Divide()

その過程で、

  • 1つのメソッドに処理を書きすぎない
  • メソッド名で「何をするか」を表現する
  • 単一責任の考え方(1メソッド1役割)
  • 再利用可能な処理をメソッドとして切り出す

という Day 17 のテーマを、具体的なコードとして体験しました。

ぜひ、

  • 自分で演算を追加してみる(べき乗、剰余、絶対値など)
  • 入力部分や表示部分もメソッドに分けてみる
  • 「この処理は別のプログラムでも使えそうか?」と考えながらメソッドを設計してみる

といった練習を通して、「メソッドを分割して設計する力」を少しずつ育てていってください。

タイトルとURLをコピーしました