Yanonoblog!

こつこつと

デッドコード、YAGNI原則、マジックナンバーの概要

はじめに

本記事では「良いコード 悪いコードで学ぶ設計入門」で学んだ内容と別途気になって調べた内容や知識も含めアウトプットしています。

書籍ではJavaで説明されていたのですが本記事ではRubyに置き換えながら解説しています。

デッドコード

デッドコードとは

どんな条件であったとしても実行されることのないコードのことをデッドコード、または到達不能コードと呼びます。

例えば以下のコードは金額と数量の引数を受け取って合計金額を算出する関数ですが、

数量が0の場合は早期リターンしているのにその後のコードでは、同じ条件でconsole.log("数量は0です");で出力するコードが書かれています。

呼ばれることがないconsole.log("数量は0です");の部分をデッドコードといいます。

function calculateTotalPrice(price, quantity) {
  if (quantity === 0) {
    return 0;
  }

  if (quantity === 0) {
    console.log("数量は0です");
  }

  const totalPrice = price * quantity;
  return totalPrice;
}

const price = 10;
const quantity = 0;
const total = calculateTotalPrice(price, quantity);
console.log("合計金額:", total);
デッドコードの弊害

コードの可読性が低下します。コードの読み手がデッドコードの周辺を読むたびに、どういう条件で実行されるかを読み手に考えさせてしまいます。

なぜ実行されないようなコードが残っているのか、何か意図があるのではと、読み手を混乱させる場合があります。

これまで到達不能だったのが、なんらかの仕様変更によりデッドコード周辺のロジックが変わり、到達可能になることでバグを引き起こす可能性があります。

YAGNI原則

YAGNI原則とは

YAGNI原則(You Ain't Gonna Need It、必要ないものは作るな)は、ソフトウェア開発における設計原則の一つです。

不要な機能や機能拡張を避け、現時点で必要とされていないものを開発しない。実際に必要になったときにのみ実装せよ、という方針です。

実際の開発においても将来の仕様を予見し、ついつい先回りしてつくり込んでしまうことがあるでしょう。しかし、先回りで実装されたロジック

は、現実にはほとんど使われないばかりか、バグの原因になるなど悪魔化することが多いです。

不要な機能を作る弊害

YAGNI原則を守らず先回りしてつくることで予測が外れ使われなくなったロジックは、デッドコードになります。

先回りでつくられたロジックは仕様にないため可読性が低下し、読み手を混乱させます。

先回りでつくり込んだ分だけ時間が無駄になります。

今必要な機能だけをつくり、構造をシンプルにしましょう。

マジックナンバー

マジックナンバーとは

マジックナンバー(Magic Number)は、ソフトウェア開発において、プログラム内に直接値が埋め込まれた数値や定数のことを指します。

これらの数値は、その意味や目的が明示されず、単にコード中に現れる数値として使われるため、「魔法のような」存在としてマジックナンバーと呼ばれています。

マジックナンバーの特徴

マジックナンバーは、以下のような特徴を持ちます

  1. 直接数値が埋め込まれている:コード内に数値がそのまま書かれており、何を表しているのかは明示されていない場合があります。
  2. 意味が不明確:数値自体からはその目的や意味が分かりにくいため、コードの理解や保守性の低下を招く可能性があります。
  3. 変更の影響範囲が広いマジックナンバーが複数箇所に使用されている場合、その値を変更する際に全ての箇所を探し出して修正する必要があります。変更漏れや誤った修正が発生するとバグの原因となります。
def calculate_total_price(quantity)
  if quantity > 10
    discount_rate = 0.2 # マジックナンバー:割引率が直接コード内に埋め込まれている
    total_price = 1000 * quantity * (1 - discount_rate) # マジックナンバー:1000は商品の単価を表しているが、その意味が明示されていない
  elsif quantity > 5
    discount_rate = 0.1 # マジックナンバー:割引率が直接コード内に埋め込まれている
    total_price = 800 * quantity * (1 - discount_rate) # マジックナンバー:800は商品の単価を表しているが、その意味が明示されていない
  else
    total_price = 1000 * quantity # マジックナンバー:1000は商品の単価を表しているが、その意味が明示されていない
  end

  return total_price
end

マジックナンバーは避けるべきであり、代わりに意味を持つ定数や列挙型を使用することが推奨されます。

マジックナンバーを使わないコードに修正

修正されたコードでは、割引のしきい値や割引率、商品の単価などを定数として宣言しています。

マジックナンバーの代わりに意味を持つ定数を使用することで、コードの可読性や保守性が向上します。

DISCOUNT_THRESHOLD = 10
HIGH_DISCOUNT_RATE = 0.2
MID_DISCOUNT_RATE = 0.1
BASE_PRICE = 1000
MID_QUANTITY_THRESHOLD = 5
MID_PRICE = 800

def calculate_total_price(quantity)
  if quantity > DISCOUNT_THRESHOLD
    discount_rate = HIGH_DISCOUNT_RATE
    total_price = BASE_PRICE * quantity * (1 - discount_rate)
  elsif quantity > MID_QUANTITY_THRESHOLD
    discount_rate = MID_DISCOUNT_RATE
    total_price = MID_PRICE * quantity * (1 - discount_rate)
  else
    total_price = BASE_PRICE * quantity
  end

  return total_price
end

参考

続く…

コメント

本記事の内容は以上になります!

書籍の続きのアウトプットも随時更新したいと思います。


プログラミングスクールのご紹介 (卒業生より)

お世話になったプログラミングスクールであるRUNTEQです♪

https://runteq.jp/r/ohtFwbjW

こちらのリンクを経由すると1万円引きになります。

RUNTEQを通じて開発学習の末、受託開発企業をご紹介いただき、現在も双方とご縁があります。

もし、興味がありましたらお気軽にコメントか、TwitterのDMでお声掛けください。

https://twitter.com/outputky