Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Code Smellsの Primitive Obsession に気を付けて設計する/Des...

kirimaru
July 07, 2021

Code Smellsの Primitive Obsession に気を付けて設計する/Designing-with-Code-Smells-Primitive-Obsession

リーダブルコード LT会 - vol.2 #readablelt
での登壇資料。

kirimaru

July 07, 2021
Tweet

More Decks by kirimaru

Other Decks in Technology

Transcript

  1. 例えば、年度 public class 年度{ private final String value; public 年度(String

    value){ this.value = value; } } 単純に型をラップするだけでも 意図を表現できます。
  2. 例えば、年度 public class 年度{ // 2021等の4桁のみを許容する private final String value;

    public 年度(String value){ if (value.length != 4){ throw new RuntimeException(“4桁以外”); } this.value = value; } } // もし、日付を文字列で管理していたら…? // ISO8601基本形式? 20210627T112445+0900 // ISO8601拡張形式? 2021-06-27T11:24:45+09:00 // 独自形式? 2021/06/27 11:24:45 // もっと独自形式? 2021/06/27|11:24:45 型としての制約をつけると より表現ができます。
  3. 例えば、年度 public class 年度{ private final String value; public 年度(String

    value){ if (value.length != 4){ throw new RuntimeException(“4桁以外”); } this.value = value; } // 2021 -> 21 public String toShortYear() { return this.value.substring(2); }   // 年度をLocalDateTimeへ変換する public LocalDateTime toLocalDateTime(){ return LocalDateTime.of( Integer.parseInt(value), 1, 1, 0, 0 ); } } 制約を満たしている状態でイン スタンスを生成しているので、 Nullチェック等は不要です。
  4. 例えば、ISBN 欠落しがちな仕様を 型で表現することが できます (ISBNは10桁か13桁) public class Isbn { private

    final String isbn; public Isbn(String code) { // 10桁か13桁かチェック String len = code.length(); if (!(len == 10 || len == 13)) { throw new RuntimeException("エラー"); } String isbn1 = convert10to13(code); if (!”978”.equals(isbn1.substring(0, 3))) { throw new RuntimeException( “2段目バーコードを読み込んだ疑いあり” ); } this.isbn = isbn1; } }
  5. 例えば、ISBN 欠落しがちな仕様を 型で表現することが できます (10桁は13桁に変換する) public class Isbn { private

    final String isbn; public Isbn(String code) { String len = code.length(); if (!(len == 10 || len == 13)) { throw new RuntimeException("エラー"); } // 10桁から13桁に変換する(省略) // 13桁ならそのまま String isbn1 = convert10to13(code); if (!”978”.equals(isbn1.substring(0, 3))) { throw new RuntimeException( “2段目バーコードを読み込んだ疑いあり” ); } this.isbn = isbn1; } }
  6. 例えば、ISBN 欠落しがちな仕様を 型で表現することが できます (ISBNは978はじまり) public class Isbn { private

    final String isbn; public Isbn(String code) { String len = code.length(); if (!(len == 10 || len == 13)) { throw new RuntimeException("エラー"); } String isbn1 = convert10to13(code); // 本当にISBNか。 if (!”978”.equals(isbn1.substring(0, 3))) { throw new RuntimeException( “2段目バーコードを読み込んだ疑いあり” ); } this.isbn = isbn1; } }
  7. 例えば、 山札・手札・場札 public class UnoGame{ List<札> 山札; List<札> 手札; List<札>

    場札; } public class 札{ String value; } 基本型のListを使っています。 これでは、表現を増やすのが 難しいです。
  8. 例えば、 山札・手札・場札 public class UnoGame{ 手札 手札; 山札 山札; 場札

    場札; } public class 札 { String value; } public class 手札{ List<札> value; } public class 山札{ List<札> value; } public class 場札{ List<札> value; } 型がついたことにより、表現の 幅が広がりました。 また、操作するドメインが変わ り、メソッドがより適切な位置に 配備される可能性があります。
  9. 話すこと / 話さないこと • Code Smells • Primitive Obsession •

    Java • Primitive Obsession が有効ではない個所 (私もわからない) 詰めなおしは推奨されないので、 べき論が分からない 話すこと 話さないこと