Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Code Smellsの Primitive Obsession に気を付けて設計する/Des...
Search
kirimaru
July 07, 2021
Technology
3.9k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Code Smellsの Primitive Obsession に気を付けて設計する/Designing-with-Code-Smells-Primitive-Obsession
リーダブルコード LT会 - vol.2 #readablelt
での登壇資料。
kirimaru
July 07, 2021
More Decks by kirimaru
See All by kirimaru
早くAPI作るならFastAPI がオススメ
hirotokirimaru
1
140
DDD(ドメイン駆動設計)を知らない人に知ったつもりさせる/Introduce_DDD_to_unfamiliar_individuals
hirotokirimaru
0
400
例示! Spring Bootで作られた REST APIのテストコード/ Testing-Example-for-a-REST-API-created-with-Spring-Boot
hirotokirimaru
2
2.3k
一緒に使うことが多い値は別クラスにしよう(Data Clumps)/data_clumps_is_useful
hirotokirimaru
0
840
Backlogが好きな話。/i_like_backlog
hirotokirimaru
0
190
私が好きなポートアンドアダプターを紹介する/I-like-hexagonal-architecture.pdf
hirotokirimaru
1
1.4k
名付けのためにクラス図を元に会話しよう/Let's-use-class-diagram-to-communicate-with-client
hirotokirimaru
0
700
FCCを推す/My favorite software architecture is FCC
hirotokirimaru
0
300
我々はなぜオブジェクト指向やDDD等のアーキテクチャを学ぶのか/Why_we_learn_ObjectOriented_and_DDD_Architecture
hirotokirimaru
1
1.2k
Other Decks in Technology
See All in Technology
AI活用の現在地、 ちゃんと見えてますか?/XPfest-2026
visional_engineering_and_design
0
170
Webとヘルスデータ
yukukotani
1
200
module Synths; end
asonas
1
130
GoにおけるFFIのこれまでとこれから
goccy
4
1.4k
AIとペアプロを始める。人とのペアプロをやめる。ペアプロの良さを改めて知る。もっと好きになった。 / Rediscovering Pair Programming
honyanya
1
300
【視聴者参加型!】AWSセキュリティアンチパターンクイズ
syoshie
0
460
コーディングエージェントでM5Stack系の開発を少し試した時の話 / M5 Japan Tour 2026 Autumn 東京
you
PRO
0
100
Redmine 7.0で私が開発した新機能の狙いと背景
vividtone
1
130
現場に行くだけでは足りない——プロダクトエンジニアが業務の流れを捉える観点と、その鍛え方
takumiengineering
0
350
SQL文一行も書けない人事がCortexもろもろを使って人事業務を楽にしてみる
ponponmikankan
1
170
作品が生態系になった ─ Mini Tokyo 3D から世界へ
nagix
0
140
Snowflakeのコスト最適化を支えるアーキテクチャ設計
ktatsuya
0
1.1k
Featured
See All Featured
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
730
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
450
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
Making the Leap to Tech Lead
cromwellryan
135
10k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
490
The Cult of Friendly URLs
andyhume
79
7k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
69
65k
Building Applications with DynamoDB
mza
96
7.2k
SEO for Brand Visibility & Recognition
aleyda
0
4.7k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
490
Java REST API Framework Comparison - PWX 2021
mraible
34
9.7k
Test your architecture with Archunit
thirion
2
2.4k
Transcript
Code Smellsの Primitive Obsession に気を付けて設計する リーダブルコード LT会 - vol.2 #readablelt
20210707 きり丸(水上 皓登)@nainaistar
※ Javaのソースコードで例示します。 また、今回の話は型の話をするので、 Python等の動的型付言語では メリットが薄いかもしれません
名前:きり丸(水上 皓登) twitter:nainaistar GitHub:hirotoKirimaru ブログ:きり丸の技術日記 https://nainaistar.hatenablog.com/ 3 リファクタリングの 正解がわからない
良いコードとは?
良いコードとは悪くないコード
悪くないコードにするには、 Code Smellsに気を付けたらいい
Primitive Obsessionとは (基本データ型の執着) 言語に用意されているデータ型しか使わないことを指します。 用意されているデータ型だけしか使用していると、 どんなデータが入るか表現できません。 コードを読む際に、業務知識が必要になるコードもあります。 自分たちが作成した型を用意することで、 よりプログラムの表現力を高めることができます。
例えば、年度 現在は、西暦2021年度です。 下2桁の21年度だけ表現することもあります。 令和3年度とも言います。R3と表現するかもしれません。 今年度の期間という表現をした場合は、 学校であれば「2021/04/01-2022/03/31」ですし、 6月が期末の会社であれば「2021/07/01-2022/06/30」です。
例えば、年度 public class 年度{ private final String value; public 年度(String
value){ this.value = value; } } 単純に型をラップするだけでも 意図を表現できます。
例えば、年度 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 型としての制約をつけると より表現ができます。
例えば、年度 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チェック等は不要です。
例えば、ISBN ISBNは本を一意に特定するためのIDです。 仕様: • ISBNは10桁か13桁 • 10桁から13桁に変換できるロジックがある ◦ アプリ上は13桁で管理したいので、10桁は13桁に変換する •
ISBNは978, または979で始まる(現状の日本国内は978のみ) ◦ 192は書籍JANコードの2段目を意味する
例えば、ISBN ISBNは本を一意に特定するためのIDです。 仕様: • ISBNは10桁か13桁 • 10桁から13桁に変換できるロジックがある ◦ アプリ上は13桁で管理したいので、10桁は13桁に変換する •
ISBNは978, または979で始まる(現状の日本国内は978のみ) ◦ 192は書籍JANコードの2段目を意味する
例えば、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; } }
例えば、ISBN ISBNは本を一意に特定するためのIDです。 仕様: • ISBNは10桁か13桁 • 10桁から13桁に変換できるロジックがある ◦ アプリ上は13桁で管理したいので、10桁は13桁に変換する •
ISBNは978, または979で始まる(現状の日本国内は978のみ) ◦ 192は書籍JANコードの2段目を意味する
例えば、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; } }
例えば、ISBN ISBNは本を一意に特定するためのIDです。 仕様: • ISBNは10桁か13桁 • 10桁から13桁に変換できるロジックがある ◦ アプリ上は13桁で管理したいので、10桁は13桁に変換する •
ISBNは978, または979で始まる(現状の日本国内は978のみ) ◦ 192は書籍JANコードの2段目を意味する
例えば、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; } }
例えば、山札・手札・場札 UNOを例にします。 今までの例から、札という型に変換することは思いつくでしょう。 しかし、山札・手札・場札等の配列の表現は 次のコードになっていないでしょうか。
例えば、 山札・手札・場札 public class UnoGame{ List<札> 山札; List<札> 手札; List<札>
場札; } public class 札{ String value; } 基本型のListを使っています。 これでは、表現を増やすのが 難しいです。
例えば、 山札・手札・場札 public class UnoGame{ 手札 手札; 山札 山札; 場札
場札; } public class 札 { String value; } public class 手札{ List<札> value; } public class 山札{ List<札> value; } public class 場札{ List<札> value; } 型がついたことにより、表現の 幅が広がりました。 また、操作するドメインが変わ り、メソッドがより適切な位置に 配備される可能性があります。
まとめ 業務知識でコードを読むのではなく、 コードに業務知識を表現させると可読性が上がります。 また、できる限り本物に近いデータを使用する必要があり、 異常データを防ぎやすくなるので、 異常検知が早くなる可能性があります。 データマッピングだけの型ではなく、 業務を表現した型を作ることで、 Code SmellsのPrimitive
Obsessionを回避してみませんか?
Appendix
ブログ 基本型以外を使って設計レベルアップ! (Primitive ObsessionとFCC)
話すこと / 話さないこと • Code Smells • Primitive Obsession •
Java • Primitive Obsession が有効ではない個所 (私もわからない) 詰めなおしは推奨されないので、 べき論が分からない 話すこと 話さないこと
対象者 / 非対象者 • リファクタリングをしたいけど、 ヒントが分からない人 • リファクタリングに興味が無い人 • 動的型付言語
対象者 非対象者
登壇を見た人への期待するアクション • Code Smellsに興味を持つ • 型を作ることをやってみる アクション