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
ak2ie
July 03, 2022
Technology
92
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
More Decks by ak2ie
See All by ak2ie
DDDのエッセンスを取り入れたAIでの開発
ak2ie
1
310
Claude Codeはレガシー移行でどこまで使えるのか?
ak2ie
1
1.7k
SVG完全に理解してグラフ書いてみた
ak2ie
0
73
Go言語CLIツールで生産効率UPした話
ak2ie
0
130
Goではじめるバックエンド開発
ak2ie
0
92
Notion APIと学ぶNext.js
ak2ie
0
600
NestJSのはじめ方
ak2ie
0
170
初心者がシビックテックに参加してみた
ak2ie
0
140
Firebase についてとことん語りたい
ak2ie
0
130
Other Decks in Technology
See All in Technology
AI × アーキテクト 第1・2章|生成AIの課題とアーキテクトの素養
daidaidai
0
170
Benchmarking Disaggregated Serving on vLLM + Dynamo with a Real Coding-Agent Workload
nttcom
1
190
S3 Filesで挑む! 八戸せんべい汁の食べ頃問題
usanchuu
0
100
継続的なAIコスト最適化
bgpat
1
340
Browser Spec: Testing Hotwire with Ruby
takahashim
1
120
Running Kotlin + Quarkus with Lambda
nealle
1
3.7k
ストレスなくAIと付き合いたい!こんなときどうしてる?
namiki64
3
520
go-sqletch
moznion
0
140
今さら理解するウェブフォントver.2026
takanorip
3
790
Temporal 最高!でも改めて「日付」について調べたら人類の負債すぎる件
riyaamemiya
0
150
AI導入は済んだ。次は統制を作り替える番だ_AI×開発組織 Summit 2026
techtekt
PRO
0
220
ブラウザとサーバーから考えるAI時代のフロントエンド監視
shogo4131
3
940
Featured
See All Featured
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
Being A Developer After 40
akosma
92
590k
KATA
mclloyd
PRO
35
16k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
710
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
74
43k
Building the Perfect Custom Keyboard
takai
2
910
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
33
5.2k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Building Applications with DynamoDB
mza
96
7.2k
Site-Speed That Sticks
csswizardry
13
1.6k
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
500
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
280
Transcript
フロントエンドで 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] }
まとめ • コード全体の見通しがよくなった • テスト対象範囲が狭くなり、テストが書きやすかった • コード量が多くなってしまった