0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DRY原則とは?「同じコードを書かない」ための考え方

0
Posted at

DRY原則とは

DRY原則とは、Don't Repeat Yourself(同じことを繰り返すな)の略です。

ソフトウェア開発における設計原則のひとつで、「同じロジックや知識をコードの中で重複させない」という考え方です。2000年に出版された書籍『The Pragmatic Programmer』の中でAndy HuntとDave Thomasが提唱しました。

原文では以下のように定義されています。

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
(システム内のすべての知識は、単一で、明確で、権威ある表現を持たなければならない)

難しく聞こえますが、要するに「同じことを2箇所以上に書かないようにしよう」ということです。

なぜDRY原則が重要なのか

同じコードが複数箇所に存在すると、何が起きるでしょうか。

たとえば、消費税の計算ロジックがアプリ内の5箇所にコピーされていたとします。税率が変わったとき、5箇所すべてを修正しなければなりません。1箇所でも修正漏れがあれば、バグの原因になります。

DRY原則に従ってコードを書くことで、以下のようなメリットが得られます。

  • 修正箇所が1箇所で済む
  • バグが発生しにくくなる
  • コードが読みやすくなる
  • メンテナンスのコストが下がる

DRY原則に違反しているコードの例

まず、DRY原則に違反しているコードを見てみます。

# ユーザーの合計金額を計算する
user_total = 0
user_items.each do |item|
  user_total += item[:price] * item[:quantity]
end
puts "ユーザーの合計: #{user_total}円"

# 管理者の合計金額を計算する
admin_total = 0
admin_items.each do |item|
  admin_total += item[:price] * item[:quantity]
end
puts "管理者の合計: #{admin_total}円"

item[:price] * item[:quantity] を合計するロジックが2回登場しています。これがDRY原則の違反です。

もし「数量が0以下のアイテムを除外する」という仕様変更が入った場合、2箇所を修正する必要があります。修正漏れが起きれば、片方だけ動作が変わるバグになります。

DRY原則に従ったコードに直す

重複しているロジックをメソッドとして切り出します。

def calculate_total(items)
  total = 0
  items.each do |item|
    total += item[:price] * item[:quantity]
  end
  total
end

puts "ユーザーの合計: #{calculate_total(user_items)}円"
puts "管理者の合計: #{calculate_total(admin_items)}円"

合計を計算するロジックが calculate_total メソッドに集約されました。仕様変更があってもこのメソッドを1箇所修正するだけで済みます。

別の例:バリデーション処理

ユーザー入力のバリデーション処理でもDRY原則が役立ちます。

違反している例:

# 新規登録処理
if params[:name].nil? || params[:name].empty?
  puts "名前を入力してください"
end
if params[:email].nil? || params[:email].empty?
  puts "メールアドレスを入力してください"
end

# 更新処理
if params[:name].nil? || params[:name].empty?
  puts "名前を入力してください"
end
if params[:email].nil? || params[:email].empty?
  puts "メールアドレスを入力してください"
end

DRY原則に従った例:

def validate_presence(value, field_name)
  if value.nil? || value.empty?
    puts "#{field_name}を入力してください"
  end
end

# 新規登録処理でも更新処理でも同じメソッドを使う
validate_presence(params[:name], "名前")
validate_presence(params[:email], "メールアドレス")

「値が空かどうかチェックする」という知識が1箇所にまとまりました。

【重要】DRYにしすぎることへの注意

DRY原則は重要ですが、何でも共通化すれば良いわけではありません。

たとえば、たまたまコードが同じに見えるだけで、本質的に別のロジックを表している場合があります。そういった場合に無理に共通化すると、後から仕様が分かれたときに逆に複雑になることがあります。

コードが重複しているように見えても、以下の点を確認してみましょう。

  • 同じ「知識」や「ルール」を表しているか
  • 片方が変わったとき、もう片方も必ず同じように変わるか

両方に当てはまる場合は共通化を検討する、というのがひとつの判断基準になります。

まとめ

DRY原則(Don't Repeat Yourself)は、同じロジックや知識をコード内で重複させないという設計原則です。

重複を排除することで、修正箇所を1箇所にまとめられ、バグが生まれにくく、メンテナンスしやすいコードになります。ただし、たまたま似ているだけのコードを無理に共通化するのは逆効果になることもあるため、「同じ知識を表しているか」を意識して判断することが大切です。

コードを書くとき、「このロジック、前にも書いたな」と感じたらDRY原則を意識していきたいと思います。

0
0
0

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?