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

一緒に使うことが多い値は別クラスにしよう(Data Clumps)/data_clumps_is_useful

kirimaru
August 24, 2022

一緒に使うことが多い値は別クラスにしよう(Data Clumps)/data_clumps_is_useful

【LT登壇7名決定!】リーダブルコード LT会 - vol.4 #readablelt
https://rakus.connpass.com/event/253650/

kirimaru

August 24, 2022
Tweet

More Decks by kirimaru

Other Decks in Technology

Transcript

  1. 例えば、 期間(日付) public class サブスクリプション { String id; LocalDate contractStartDate;

    LocalDate contractEndDate; int qty; BigDecimal price; } サブスクリプション のモデル。 契約開始日、契約終了日 を持っています。
  2. 例えば、 期間(日付) public class サブスクリプション { String id; 期間 contractTerm;

    int qty; BigDecimal price; } public record 期間( LocalDate start, LocalDate end ){ } ちょっとすっきり。 契約の開始日ではなく、 開始日、終了日と 単語を短縮できるのも好き。
  3. 例えば、 期間(時刻) public class 取引時間 { String id; String startTime;

    String endTime; public isBusinessTime(LocalDateTime now) { // いい感じの処理 } } Stringの”0900”と”1500” を元に、 いい感じに処理する
  4. 例えば、 期間(時刻) public class 取引時間 { String id; String startTime;

    int straightHours; public isBusinessTime(LocalDateTime now) { // いい感じの処理 } } 終了時刻はすぐにわからない が、日付を跨ぐ場合には優し いかもしれない
  5. DBの複合キー public class 企業 { String 企業ID; } public class

    契約 { String 企業ID; String 契約ID; } public class 販売 { String 企業ID; String 契約ID; String 販売ID; } public class 仕入 { String 企業ID; String 契約ID; String 販売ID; String 仕入ID; } 適切な例が思い浮かばず…
  6. DBの複合キー public class 販売主キー { String 企業ID; String 契約ID; String

    販売ID; } public class 仕入 { String 企業ID; String 契約ID; String 販売ID; String 仕入ID;  # パラメータが一つにまとまる public boolean salesEquals(販売主キー id) { return (this.企業ID.equals(id.企業ID) && this.契約ID.equals(id.契約ID) && this.販売ID.equals(id.販売ID)) } } 販売の複合主キーとして、親 のIDをすべて持つ前提
  7. 例えば、 期間(日付) public class 販売 { String id; 期間 salesTerm;

    int qty; BigDecimal price; } public record 期間( LocalDate start, LocalDate end ){ } Javaの構造。
  8. 例えば、 期間(日付) CREATE TABLE 販売 ( id VARCHAR(13) PRIMARY KEY,

    start_date TIMESTAMP, end_date TIMESTAMP, qty INTEGER, price INTEGER, ); DBの構造。
  9. 例えば、 期間(日付) CREATE TABLE 販売 ( id VARCHAR(13) PRIMARY KEY,

    term_id VARCHAR(13), qty INTEGER, price INTEGER, ); CREATE TABLE 期間 ( id VARCHAR(13) PRIMARY KEY, start_date TIMESTAMP, end_date TIMESTAMP, ) わざわざ ここまでする必要はない。
  10. 例えば、 期間(時刻) CREATE TABLE 取引時間 ( id VARCHAR(13) PRIMARY KEY,

    start_time VARCHAR(4), end_time VARCHAR(4), ); CREATE TABLE 取引時間 ( id VARCHAR(13) PRIMARY KEY, start_time VARCHAR(4), straight_hours INTEGER ); モデリングの結果、 DBの構造を変えること自体は 良いこと
  11. 例えば、 期間(日付) public class サブスクリプション { 期間 contractTerm; LocalDate cancelDate;

    public boolean isCancelable{ // 期間クラスの開始日を使用する。 // 別クラスの属性を欲しがるという意味のCode Smells // Feature Envy // が起きかねない return this.contractTerm.start .isAfter(cancelDate) } } 解約日 という概念を追加。
  12. 例えば、 期間(日付) public class サブスクリプション { 期間 contractTerm; LocalDate cancelDate;

    } ↓ public class サブスクリプション { LocalDate contractStartDate; LocalDate contractEndDate; LocalDate cancelDate; public boolean cancelable?(){ return     // 期間クラスに // 解約可能かどうか判断メソッドを作ってもいい // 作らなくてもいい new 期間(contractStartDate, cancelDate) .noProration() } } 使いづらかったら、 データ構造をフラットに するのはあり。
  13. 他にも • 期間 ◦ 開始日 と 終了日 ◦ 開始時間 と

    継続時間 • 行列 ◦ X と Y と Z ▪ 加算・減算・内積・外積 等々
  14. 例えば • ページング ◦ 現在ページ数 と 最大ページ数 と ページサイズ ◦

    ソート ▪ キー と 優先度 と 順番(ASC, DESC) と Nullableの扱い • LIMIT, OFFSETをまとめたRowBounds
  15. 話すこと / 話さないこと • Code Smells • Primitive Obsession •

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