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
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
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
フロントエンドでDDDやってみた
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
ak2ie
July 03, 2022
Technology
95
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
フロントエンドでDDDやってみた
「#Webフロントエンド なんでもLT 会 #5」での発表内容です。
https://ncdc-dev.connpass.com/event/248156/
ak2ie
July 03, 2022
Transcript
20 slides
フロントエンドで DDDやってみた 2022/06/17
自己紹介 • 名前:ak2ie(あっきー) • システムエンジニア9年目 • 好きなもの:コーヒー、電車
DDD(ドメイン駆動設計)とは? • システムの対象領域(ドメイン)に焦点を当てた設定手法 • ValueObject、Entity、ドメインサービスを使ってドメインの知識を表現 • リポジトリ、アプリケーションサービス、ファクトリを用いてシステムを構成
DDD関連書籍 本家 実践的 入門
対象のプロジェクト • 自治体に納めた税金の使途を表示するサイト • 年収を入力すると、福祉や建築といった使途別に税額が表示される ※業務外のプロジェクトです
構成 • Nuxt(ver.2)、TypeScript • フォルダ構成 ◦ root ▪ components ▪
page ▪ plugins:DDD関連のコード ▪ store
ユビキタス言語 • 論理名と物理名を用語集としてまとめた • ドメイン知識を持った方は1,2名、チームメンバーは5名程度だったので、 大きなものは作らなかった
ValueObject • ドメイン固有の概念を値として表す • 「金額」や「税率」を ValueObjectとして定義 • 作成時の数値チェックや金額計算のミスを防止 export class
Price extends PrimitiveValueObject <number> { static create(value: number): Price { if (value < 0) { throw new Error('金額には0円以上を指定してください ') } return new Price(value) }
ValueObject • 加算:金額同士のみ public add(value: Price) { return Price.create(this.price +
value.price) } • 乗算:金額×税率 public times(value: TaxRate) { return Price.create(this.price * value.rate) }
Entity • 属性が変わっても変化しないもの • 「個人」をEntityとして定義 export class Person { private
salary: Price private homeType: HOME_TYPE }
ドメインサービス • ドメインに関する処理を行う • 年収から使途ごとの税額を計算する • 単体テストも書きやすい(Jestを使用)
ドメインサービス export class TaxService { /** * 一日当たりの税額算出 * @param
param * @returns 税額(単位 :円) */ public calcTax(param: { person: Person government : Government cofogCode : CofogCode }): Price | null { const taxAmount = this.calcAmountTax ({ person: param.person, government: param.government , })
ドメインのテスト const person = new Person({ salary: Price.create(10000000 ), homeType:
HOME_TYPE .SINGLE, }) const govFactory = new GovernmentFactory (wrapper.vm) const goverment = govFactory .Get() const service = new TaxService (wrapper.vm) expect( service.calcTax({ person, government: goverment , cofogCode: CofogCode .create({...}), }) ).toEqual(Price.create(((10000000 - 330000) * 0.06 * 2000) / 10000 / 365))
リポジトリ • StoreやAPIからのデータ取得はリポジトリを通して行うことで統一した export class HogeRepository { public GetStoreData(): Data
| null { const storeData = this.app.store?.getters['storeData'] } } export class HogeHogeRepository { public async GetAPIData(): Promise<APIResponse> { const apiResponse = await this.app.$axios.$get<APIResponse>(uri) } }
リポジトリの利用 • リポジトリ名の候補が効く
リポジトリの定義 declare module '@nuxt/types' { interface NuxtAppOptions { readonly $repositories:
<K extends keyof Repositories>(key: K) => ReturnType<Repositories[K]> } } declare module 'vue/types/vue' { interface Vue { readonly $repositories: <K extends keyof Repositories>(key: K) => ReturnType<Repositories[K]> } }
リポジトリの定義 export const repositories: Repositories = { cofog: CofogRepository, cofogData:
CofogDataRepository, budget: BudgetRepository, }
アプリケーションサービス • システムとして構成させるための処理 • APIへのリクエストなど
ファクトリ • リポジトリはファクトリを通して取得、使用するようにした • ファクトリを使うようにしたが、中身は少なかったので使う意味があまりな かったかも知れない export const apiRepositoryFactory =
{ get: (key: keyof Repositories) => repositories[key] }
まとめ • コード全体の見通しがよくなった • テスト対象範囲が狭くなり、テストが書きやすかった • コード量が多くなってしまった
More Decks by ak2ie
See All by ak2ie
DDDのエッセンスを取り入れたAIでの開発
ak2ie
1
320
Claude Codeはレガシー移行でどこまで使えるのか?
ak2ie
1
1.7k
SVG完全に理解してグラフ書いてみた
ak2ie
0
75
Go言語CLIツールで生産効率UPした話
ak2ie
0
140
Goではじめるバックエンド開発
ak2ie
0
96
Notion APIと学ぶNext.js
ak2ie
0
610
NestJSのはじめ方
ak2ie
0
180
初心者がシビックテックに参加してみた
ak2ie
0
140
Firebase についてとことん語りたい
ak2ie
0
140
Other Decks in Technology
See All in Technology
Agent Harnessはどう作る?事例から学ぶAI Agentの設計思想
sergicalsix
0
260
81天的 AI Agent 軟體開發團隊治理實務分享
regionbbs
0
150
2026 Apache Flink Community Checkpoint
rmetzger
0
230
Context Ontology Accelerator 入門 (業務データの意味を、AI エージェントに渡す)
inariku
PRO
3
630
[JAWS Festa 2026]一番いい仕事は、請求書に現れない / jawsfesta2026
sh_fk2
2
450
GCASアップデート(202607-202610)
techniczna
1
250
SREのためのFinOps入門
muziyoshiz
3
1.4k
PostgreSQL オプティマイザ統計の秘密
nori_shinoda
1
460
現場を動かすAIエージェント#2_製造業現場でのAI活用から見た、ハマる罠と実践知
kintotechdev
2
220
高品質と高スピードを支える品質のシフトレフトのアプローチ
goyoki
0
180
Active Directory と Entra ID のむむむな関係
murachiakira
PRO
4
1.8k
少ない人手 限られた予算 それでも守る 消せない・見つける・戻れる オールハザード型BCP on AWS / 20261107 Mitsutoshi Matsuo
shift_evolve
PRO
0
360
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
174
15k
Bash Introduction
62gerente
615
220k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.9k
How to Ace a Technical Interview
jacobian
280
24k
The Curse of the Amulet
leimatthew05
4
17k
The Language of Interfaces
destraynor
162
27k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
2
520
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
480
Measuring & Analyzing Core Web Vitals
bluesmoon
9
1.1k
The SEO Collaboration Effect
kristinabergwall1
1
620
Automating Front-end Workflow
addyosmani
1370
210k
sira's awesome portfolio website redesign presentation
elsirapls
0
500