知っている人も多いと思うが、DRY原則というものがある。
Don't Repeat Yourselfの頭文字をとった言葉で、簡単に言うと「同じことを繰り返すな」という意味。
例を出してみる。
public class Person
{
public string FirstName { set; get; } = "";
public string LastName { set; get; } = "";
public string FullName { set; get; } = "";
}
上記のようなPerson
クラスのインスタンスを作成するとしよう。
var haruki = new Person();
haruki.FirlstName = "Haruki";
haruki.LastName = "Yachizaki";
haruki.FullName = "Yachizaki Haruki";
Console.Write(haruki.FullName);
// 結果 -> Yachizaki Haruki
FullNameを出力すると、"Yachizaki Haruki"となる。
上記のクラスには問題がある。
それは、FirstName
とLastName
を設定して、FullName
の設定が漏れていた場合に、FullName
が出力されないという問題だ。
var haruki = new Person();
haruki.FirstName = "Haruki";
haruki.LastName = "Yachizaki";
// haruki.FullName の設定を忘れている
Console.Write(haruki.FullName);
// 結果 -> ""(空白)
// PersonクラスのFullNameのデフォルト値が表示される
設定されるべき値を設定していなかったのだから当然の挙動だが、そもそも一般的にFullName
はFirstName
とLastName
さえ分れば求められるにも関わらず、個別に設定しなければならない方がおかしいと言えるだろう。FullName
の設定を繰り返しているとも言える。
そこで、FullName
を修正し、以下のようにしてみる。
public class Person
{
public string FirstName { set; get; } = "";
public string LastName { set; get; } = "";
public string FullName => $"{LastName} {FirstName}";
}
FullName
は個別に設定するのではなく、FirstName
とLastName
を組み合わせて返すように変更する。
すると、
var haruki = new Person();
haruki.FirstName = "Haruki";
haruki.LastName = "Yachizaki";
// haruki.FullName は設定しない(setterを持たないのでそもそもできない)
Console.Write(haruki.FullName);
// 結果 -> Yachizaki Haruki
となる。
他のプロパティから求められるプロパティは個別に用意しないという考え方では、DB設計などでも用いられる。DB設計においては、主にパフォーマンスの面から冗長なフィールドを用意することもあるが(価格
と税率
と税込み価格
を持っておくなど)、プログラミングのソースコードにおいてはそこまで意識することは少ないと言えると思う(※ぱっと例が思いつかないが、冗長な実装をした方がいいケースもきっとあると思う)。
プロパティが増えれば増えるほど管理しなければいけない情報が増え、バグの元になる。
メリット
デメリット
DRY原則とよく似た考え方に、OAOO(Once And Only Once:ただ一度だけ書く)がある。
例を示す。下記のようなコードがあるとする。
var message1 = "あけましておめでとうございます";
var message2 = "今年もよろしくお願いします。";
var newMessage1 = "";
var newMessage2 = ""+
const string Dot = "。";
if (message1.EndsWith(Dot))
newMessage1 = message1;
else
newMessage1 = message1 + Dot;
if (message2.EndsWith(Dot))
newMessage2 = message2;
else
newMessage2 = message2 + Dot;
Console.Write(newMessage1 + newMessage2);
// 結果 -> あけましておめでとうございます。今年もよろしくお願いします。
上記コードは2つのメッセージを連結して出力するが、各メッセージが読点(。
)で終わっていなければ付け足した後に連結するということをしている。
この、「読点がなければ付け足す」という処理はmessage1
に対して行うかmessage2
に対して行うかだけの違いだが、2回に渡って書かれている。
これにOAOOを当てはめると、以下のようにできる。
// 以下のメソッドを用意
static string AppendDotIfNeeded(string message)
{
const string Dot = "。";
// nullチェックは省略
if (message.EndsWith(Dot))
return message;
else
return message + Dot;
}
// メソッドを用意すると以下のように書ける
var message1 = "あけましておめでとうございます";
var message2 = "今年もよろしくお願いします。";
var message1EndsWithDot = AppendDotIfNeeded(message1);
var message2EndsWithDot = AppendDotIfNeeded(message2);
Console.Write(newMessage1 + newMessage2);
// 結果 -> あけましておめでとうございます。今年もよろしくお願いします。
「読点がなければ付け足す」という処理をメソッドに抽出したことで流用できるようになった。
DRYはシステム全体での重複を(排除すべきところでは)排除しようという考え方、OAOOはあくまでソースコード上において、同じような内容はまとめようという考え方だと理解している。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント