きり丸の技術日記

技術検証したり、資格等をここに残していきます。

基本型以外を使って設計レベルアップ!(Primitive ObsessionとFCC)

いいコードとは、悪くないコードのことを指すと考えています。

そして、悪くないコードを目指していくには、Code Smellsに注目すると改善できます。

今回の記事では、Code SmellsのなかのPrimitive Obsession(基本データ型の執着)に注目します。

Primitive Obsession(基本データ型の執着)とは

用意されているデータ型しか使わないことを指します。Javaだとintやlong等をプリミティブ型と言いますが、そのプリミティブ型とは異なります。

用意されているデータ型だけだと、どんなデータが入りうるかわかりません。ですので、自分たちが作成した型を用意することで、より表現力を高めることができます。

具体的な例

例えば、本にはISBNという全世界共通で本を一意に特定できるIDがあります。ですので、Book型にはString型でISBN型を持たせるとします。

public Book{
  private String isbn;
}

この時、ISBNはどんなデータが入りうるでしょうか。全世界共通で本を一意に特定できるIDということで、採番ルールやどんなデータ型なのかも定められています。しかし、現状のコードはString型であることしか語ってくれません。まずは、ラップしただけのISBN型を作りましょう。

public Book{
  private Isbn isbn;
}
public Isbn{
  private String value;
}

これでISBN型というものが表現できました。しかし、現状ではあまり価値はありません。なぜなら、データが表現しきれていないからです。

詳しい制約は省きますが、ISBN型は10桁、13桁以外はありえません。ですので、10桁や13桁以外のデータでISBNを生成しようとしたらエラーとなるようにし ましょう。

public Isbn {
  private String value;
  Isbn(String value){
    if (!(code.length() == 10 || code.length() == 13)) {
      throw new RuntimeException("ISBNの桁数が正しくない");
    }

    this.value = value;
  }
}

このように、言語が用意した基本型ではなく、自分たちが用意したデータ型を使用することで、どんなデータが入りうるかが表現できるようになります。

型があることで、表現の幅が広がります。動的型付言語であればわかりませんが、静的型付言語であれば型で表現するメリットは大きいので、ぜひ利用してください。

コレクション型もラップする(FCC, First Collection Class)

ListやMap等もラップした型を作ったほうが伝えやすいです。このコレクション型をラップする方法はFCC(First Collection Class)とも言われています。

例えば、カードゲームのUNOをListのまま表現するとこうなります。


public class UnoGame{
  List<Card> cardList1;
  List<Card> cardList2;
  List<Card> cardList3;
}
自分の番の時、「カードリスト1」から「カードリスト3」に重ねられるカードがあるとき、「カードリスト1」から1枚を選んで「カードリスト3」に重ねます。
もし、「カードリスト3」に重ねられないとき、「カードリスト2」から1枚を「カードリスト1」に加えます。

こちらは分かりやすいでしょうか。カードリスト1とか3とか、非常にわかりづらいですね。変数名をわかりやすくしても、変数名は噓をつくこともできるので、限界があります。

ですので、カードリスト1等々をラップした型を作成します。

public class UnoGame{
  手札 cardList1;
  山札 cardList2;
  場札 cardList3;
}
public class 手札{
  List<Card> list;
}
public class 山札{
  List<Card> list;
}
public class 場札{
  List<Card> list;
}
自分の番の時、「手札」から「場札」に重ねられるカードがあるとき、「手札」から1枚を選んで「場札」に重ねます。
もし、「場札」に重ねられないとき、「山札」から1枚を「手札」に加えます。

非常にわかりやすくなっているのではないでしょうか。このように表現できると、「カードリストを捨てる」といった表現では気づけなかったことに気づけます。「山札を捨てる」「手札を捨てる」「場札を捨てる」と表現をしたときに、「手札を捨てる」以外の表現に違和感を感じられるのではないでしょうか。コーディングやリーディングでのヒントを与えられるのは大きいです。

ソースコード

ISBN.java github.com

終わりに

コードが仕様を伝えられるようになると、可読性が上がるので非常に強いです。

まぁ、余計なコードを管理しなければならないので、嫌いな人は嫌いかもしれませんが…。

型を意識的に作ろうと思わないと絶対に作らないので、ぜひ覚えていってほしいです。


この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

参考

Primitive Obsession refactoring.guru

f:id:nainaistar:20210306230927p:plain