LoginSignup
89
49

More than 1 year has passed since last update.

何故foreachを使ってはいけないか?

Last updated at Posted at 2023-02-22

Linqを使った方がミスが起きにくい

  • 結論から言えば、foreachを使わずにLinqで代替すると、コードがより人間の言語に近くなり、仕様に基づいてコードを記述する際のミスが抑えられます。

  • プログラミングを行う際、プログラマは意識せずに人間が考えた仕様を、マシンが理解出来るように翻訳してプログラムを記述しています。プログラム言語がより人間の言語に近づくことによって、この翻訳作業でのミスを減らすことが出来ます。

ループ系ステートメントを使った時とLinqを使った時の違いを比べてみる

  • 例えば、以下のような仕様があったとします。
価格のリストから一番高い価格をコンソールに表示する。
  • ループ系のforeachステートメントを使った場合は、以下のようなコードになります。
var priceList = new int { 100, 200, 300 };

var maxPrice = 0; 

foreach(var price in priceList)
{
    if (maxPrice < price)
    {
        maxPrice = price;
    }
}

Console.WriteLine(maxPrice);
  • プログラマ歴の長い方は、こういったコードを何度も書いてきたのではないでしょうか?(実際に私も書いていました)

  • これに対して、Linqを使った場合は以下の通りになります。

var priceList = new int { 100, 200, 300 };

Console.WriteLine(priceList.Max());
  • この記述の短さで全く同じ結果が得られるわけですから、直観的にLinqを使うメリットを感じることが出来るはずです。ただ、Linqを使うことには、それ以上の意味があります。

  • 先ほど書いたコードをためしに「直訳」してみます。直訳した結果はコメントで右側にかいていきます。

var priceList = new int[] { 100, 200, 300 };

var maxPrice = 0; // 変数:最大価格にゼロを代入します。

foreach(var price in priceList) // 価格リストの要素をひとつづつ取り出します。
{
    if (maxPrice < price) // 取り出した価格が変数:最大価格より大きい場合
    {
        maxPrice = price; // 変数:最大価格に取り出した価格の値を代入します。
    }
}

Console.WriteLine(maxPrice); // 変数:最大価格をコンソールに出力します。
  • あらためてコードを「直訳」してみると、最初に定義された「価格のリストから一番高い価格をコンソールに表示する」という仕様をプログラマがプログラミング言語に「翻訳」していることが分かります。

  • それではLinqを使ったコードを直訳してみましょう。

var priceList = new int[] { 100, 200, 300 };

Console.WriteLine(priceList.Max()); // コンソールに「価格リストの中の最大の値」を出力します。

  • どうでしょうか?コードの直訳が最初に定義した「価格のリストから一番高い価格をコンソールに表示する。」という仕様とほぼ一致しています。この書き方であれば、「仕様」を元にそのまま「コード」を記述すればよいだけなので、ミスをする可能性はほぼありません。

  • これはコードを文法やステートメントレベルで「仕様」に近づけるアプローチであって、実際にはこれに加えて変数やクラス、メソッドの「ネーミングの的確さ」が必須になってきますが、ネーミングについてはそれだけで膨大な記述が必要になるため、ここでは触れません。

コメントはどうなるか?という疑問について

  • 「わざわざコード上で仕様を表現しなくても、コードに直接コメントを書けばよいのでは?」という意見もありますが、個人的にコメントは次善の策であって、本筋は今回紹介した「コードのそのもので仕様を表現出来る」方が望ましいと思っています。

  • というのも、コメントに詳細な仕様を書き込んだときに何かのきっかけで仕様が変わった場合、常に「設計書」、「コメント」、「コード」の三か所をメンテナンスしなくてはならなくなるからです。

  • シンプルに「メンテナンスする対象が増える≒部品点数が増える」と思っていただいてもいいと思います。工業製品においては同じ機能が得られるなら、部品点数が少ない方が優れていると考えますが、これはシステムにおいても同じと言えるでしょう。

  • とはいえ、実際にはコードだけで表現出来ないこともあるので、その場合は自分も積極にコメントを書いています。しかし、その場合も可能な限りコードで仕様を表現出来るように考えた上で、なるべく簡素にコメントを書くことにしています。

結論

  • 最後に結論です。

    • コードを「直訳」してその結果が「仕様」に近ければ近いほど、それだけバグが少なく堅牢なシステムに近づきます。

    • 具体的には、ループはなるべくLinqを使って記述します。そうすれば自然とそのコードは「仕様」に近づきます。

    • 「これならコメントは詳しく書かなくても大丈夫だな」と言えるよう、コーディング自体を工夫していきましょう(もちろんこれはすごく難易度が高いことですが)。

  • システム開発は日進月歩。更に素晴らしいアプローチが生まれることを期待して、本稿を締めたいと思います。最後までお読みいただき感謝です。

89
49
5

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
89
49