Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
DRFを少しずつ オニオンアーキテクチャに寄せていく DjangoCongress JP 2025
Search
Nealle
February 21, 2025
Programming
1
48
DRFを少しずつ オニオンアーキテクチャに寄せていく DjangoCongress JP 2025
DjangoCongress JP 2025
https://djangocongress.jp/
Nealle
February 21, 2025
Tweet
Share
More Decks by Nealle
See All by Nealle
ナレッジイネイブリングにAIを活用してみる ゆるSRE勉強会 #9
nealle
0
26
ニーリー QAエンジニア紹介資料
nealle
0
90
SRE、開発、QAが協業して挑んだリリースプロセス改革@SRE Kaigi 2025
nealle
3
4.3k
テストをしないQAエンジニアは何をしているか?
nealle
0
140
事業成長を爆速で進めてきたプロダクトエンジニアたちの成功談・失敗談
nealle
3
1.5k
Nealle Company Deck
nealle
7
130k
AllStarSaaS_BootCamp2024_nealle
nealle
1
180
AI活用したくてもできなかった不動産SaaSの今とこれから
nealle
0
2.4k
信頼性とアジリティの両輪で進むスタートアップSRE
nealle
0
160
Other Decks in Programming
See All in Programming
SpringBoot3.4の構造化ログ #kanjava
irof
2
990
もう僕は OpenAPI を書きたくない
sgash708
5
1.6k
『GO』アプリ データ基盤のログ収集システムコスト削減
mot_techtalk
0
120
さいきょうのレイヤードアーキテクチャについて考えてみた
yahiru
3
750
Conform を推す - Advocating for Conform
mizoguchicoji
3
690
責務と認知負荷を整える! 抽象レベルを意識した関心の分離
yahiru
2
380
第3回 Snowflake 中部ユーザ会- dbt × Snowflake ハンズオン
hoto17296
4
370
XStateを用いた堅牢なReact Components設計~複雑なClient Stateをシンプルに~ @React Tokyo ミートアップ #2
kfurusho
1
900
コミュニティ駆動 AWS CDK ライブラリ「Open Constructs Library」 / community-cdk-library
gotok365
2
120
Domain-Driven Transformation
hschwentner
2
1.9k
ファインディLT_ポケモン対戦の定量的分析
fufufukakaka
0
710
社内フレームワークとその依存性解決 / in-house framework and its dependency management
vvakame
1
560
Featured
See All Featured
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
120k
It's Worth the Effort
3n
184
28k
Code Review Best Practice
trishagee
67
18k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
4
410
Facilitating Awesome Meetings
lara
52
6.2k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
30
2.2k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
160
15k
StorybookのUI Testing Handbookを読んだ
zakiyama
28
5.5k
Rebuilding a faster, lazier Slack
samanthasiow
80
8.8k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
4
330
Thoughts on Productivity
jonyablonski
69
4.5k
Mobile First: as difficult as doing things right
swwweet
223
9.3k
Transcript
DRFを少しずつ オニオンアーキテクチャに寄せていく NEALLE 2025.2.22 株式会社ニーリー 野呂 有我
2 氏名 所属 経歴 野呂 有我 / Yuga NORO 株式会社ニーリー
プラットフォーム本部 アーキテクチャチーム ・大学院時代に友人と楽譜販売サービスを立ち上げ ・その後、SIer企業に参画 ・副業としてニーリーでいくつかの開発に携わる ・フリーランスを経て、ニーリーへ 1|自己紹介
目次 1|自己紹介 2|プロダクト紹介 3|DRFについて 4|起こった問題 5|意思決定 3 6| 振り返り 7|
これからのこと
4 2|プロダクト紹介
5 3|Django DRFについて DRFは、超高速開発を可能にするPythonのWeb Framework Djangoのプラグインで、 View/Serializer/Modelの3つのパーツを組み合わせて、一瞬でAPIを構築できる 認証やユーザー管理、ファイルのアップロードに至るまで基本的には全て組込済み
6 弊社もその高速開発を利用し、機能をどんどん作り 急激なグロースを実現 • ・プロダクト開発人数が当初の 2人から20人以上にまで増加 • ・顧客も増え続け、機能開発のさらなる加速が必要になった 3|DRFについて
7 ・スタートアップは最初からそのサービスが成功するかどうかを知る術はない! ・できる限り少ないコストで、できるだけ早くサービスを、機能をリリースし続け、 結果として生き残ったサービスだけが「その先」を知ることができる! ・ 結果として「技術的な借入」が沢山ある状態に ・「借入」は「利息」を生み、開発速度が段々遅くなっていく 3|DRFについて
8 ・今あるコードベースを捨て、別の言語・別のFWに移行する ・今あるコードベースを少しずつ改善していく 我々は後者を選択した! こうなった時、取れる選択肢は2つ 3|DRFについて
9 ・開発を止めたくなかった(止められなかった) → 移行中は機能開発が止まってしまう ・移行にかかるリソースも開発に回したかった → 開発アジェンダは増えるばかり ・性能的な面などで問題が起こっているわけではなかった → Python/Django/DRFに問題があるわけではない!
3|DRFについて
10 4|起こった問題 では、その時どんな問題があったか? 1. 依存関係の複雑化 2. 業務ロジックの分散と技術的関心との密結合 3. キャッチアップ難度の増加
11 1. 依存関係の複雑化 4|起こった問題
12 4|起こった問題
13 1. 依存関係の複雑化 4|起こった問題
14 1. 依存関係の複雑化 4|起こった問題
15 1. 依存関係の複雑化 4|起こった問題
16 1. 依存関係の複雑化 どこを触っても全範囲に影響がある!!! 4|起こった問題
17 1. 依存関係の複雑化 ・影響範囲が読みきれず、本来は同じロジックを変更すれば良いものを、 コピーして別の場所に作り直す、ということが常態化 ・結果として、ほぼ同じことをやっている関数が大量に発生 ・ほぼ同じ画面の権限違いなどのために3重実装が行われる などが横行した 4|起こった問題
18 1. 依存関係の複雑化 さらに... ・プロジェクトを構成するアプリケーション(App)が 複数あるが、それらのほぼ全てが別のアプリケーションに 直接依存! ・関数もクラスもORMのModelもインポートし、 DBの値も 別のAppから書き換えている状態だった
4|起こった問題
19 2. 業務ロジックの分散と技術的関心との密結合 4|起こった問題
20 2. 業務ロジックの分散と技術的関心との密結合 4|起こった問題
21 2. 業務ロジックの分散と技術的関心との密結合 全ての層に業務ロジックが書かれている!!! 4|起こった問題
22 2. 業務ロジックの分散と技術的関心との密結合 4|起こった問題
23 2. 業務ロジックの分散と技術的関心との密結合 さらに、全ての層で永続化も行われている!!!!! 4|起こった問題
24 2. 業務ロジックの分散と技術的関心との密結合 ・自動テストは書かれていたが、全て実際のDBを使った統合テストに なっていた(ならざるを得なかった) ・DBの状態遷移が業務ロジックに含まれているため、影響範囲の特定が 非常に困難 ・ViewやSerializerに書かれた業務ロジックは、Viewの機能やSerializerの 機能と分離できないため、ロジック単体での再利用が不可能 4|起こった問題
25 2. 業務ロジックの分散と技術的関心との密結合 結果、ロジックを持ったViewやSerializerが大量に継承される ・自動テストは書かれていたが、全て実際のDBを使った統合テストに なっていた(ならざるを得なかった) ・DBの状態遷移が業務ロジックに含まれているため、影響範囲の特定が 非常に困難 ・ViewやSerializerに書かれた業務ロジックは、Viewの機能やSerializerの 機能と分離できないため、ロジック単体での再利用が不可能
4|起こった問題
26 3. キャッチアップ難度の増加 4|起こった問題
27 3. キャッチアップ難度の増加 ・…のような状態になったコードはキャッチアップコストが非常に高く、 技術者の参入難易度が増加した ・それでも平然と開発し、大きな障害も特に出さず、 変更障害率も低かったのは、本当にすごいと思う ・ただ、それでもコア領域の開発はかなり時間がかかるようになっており、 1項目のDBへの追加で3日などの工数がかかるまでになっていた (フロントエンドも含む)
4|起こった問題
28 4|起こった問題
29 5|意思決定 意思決定 ・ある日、決済会計領域の大規模な改修が決定 ・そこで今ある問題↓をその領域に持ち込まないためにどうすべきかを考えた 1. 依存関係の複雑化 2. 業務ロジックの分散と技術的関心との密結合 3.
キャッチアップ難度の増加
30 意思決定 依存関係の複雑化を食い止めるため以下のルールを策定 1. 別Appの関数への直接依存の禁止 2. 別Appのテーブルへの直接の書き込みの禁止 3. View/SerializerからDBへのアクセスを禁止 4.
SerializerはViewからのみ依存して良い 5. ViewはUrl.pyからのみ依存して良い 5|意思決定
31 意思決定 については、多分特に疑問はないはず 1. 別Appの関数への直接依存の禁止 2. 別Appのテーブルへの直接の書き込みの禁止 3. View/SerializerからDBへのアクセスを禁止 4.
SerializerはViewからのみ依存して良い 5. ViewはUrl.pyからのみ依存して良い 5|意思決定
32 意思決定 この「直接」については後からお話しします 1. 別Appの関数への直接依存の禁止 2. 別Appのテーブルへの直接の書き込みの禁止 3. View/SerializerからDBへのアクセスを禁止 4.
SerializerはViewからのみ依存して良い 5. ViewはUrl.pyからのみ依存して良い 5|意思決定
33 意思決定 業務ロジックの分散と技術的関心との密結合を食い止めるため 1. View/Serializer/Modelへの業務ロジック記載を禁止 2. Usecase層という、業務フローを組み立てる層を追加 3. Domain層という、業務ロジックを記載する層を追加 4.
Domain層からDBへの書き込みを禁止 5. DBの読み書きが許される Infrastructure層を追加 5|意思決定
34 意思決定 これにより、各レイヤーの分担と依存の方向は以下のように 5|意思決定
35 意思決定 これにより、各レイヤーの分担と依存の方向は以下のように 5|意思決定
36 意思決定 そう、これは一般的なオニオンアーキテクチャー 5|意思決定
37 意思決定 そう、これは一般的なオニオンアーキテクチャー これを実現するために、 APIViewとserializers.Serializer以外の使用を断念😭 5|意思決定
38 意思決定 そう、これは一般的なオニオンアーキテクチャー これを実現するために、 InjectorというDIコンテナ(のようなもの)を利用 https://github.com/python-injector/injector 5|意思決定
39 意思決定 一般的なオニオンアーキテクチャになったため、 新規参画者にも「この領域はオニオンアーキテクチャです」 と言えば大体伝わるようになり、 参画ハードルもグッと下がった! 5|意思決定
40 意思決定 一般的なオニオンアーキテクチャになったため、 新規参画者にも「この領域はオニオンアーキテクチャです」 と言えば大体伝わるようになり、 参画ハードルもグッと下がった! …が 5|意思決定
41 意思決定 ・今オニオンアーキテクチャ化しているのは この青い部分だけ ・その部分については見通しもよくなり、 参画ハードルも下がっていると信じている ・だが未だそうなっていない箇所の方が多い! apps/ ├── __init__.py
├── __pycache__ ├── business_crosscuing ├── cash_selement_common ├── client_analytics ├── client_manuals ├── core ├── core_system_link ├── coupon_page ├── customers ├── digital_cash_results ├── digital_cash_schedules ├── guarantees ├── libs ├── mypage ├── parkings ├── payments ├── platform ├── reservation_and_approval ├── selements └── users 5|意思決定
42 意思決定 ↓再掲 5|意思決定
43 意思決定 ・この問題があると、いくらApp1つ単位で依存関係を整理しても、 結局外からDBの値を書き換えられてしまう ・そこで、さらに「Internal API層」を定義 ・これはマイクロサービスであればRPC(Httpなど)に置き換わっているはずの部分 5|意思決定
44 意思決定 5|意思決定
45 意思決定 5|意思決定
46 意思決定 5|意思決定
47 6|振り返りと現状の整理 結果、どうだったか?
48 6|振り返りと現状の整理 導入中 ・DRFの持っている便利機能を大部分捨てる判断のため、 最初はメンバーの反応が気になった ・最初のAppへの導入中は、書く量の増加が目につき不安だった ・最初はもっと厳格にオニオンアーキテクチャを 導入する予定だったが、 必要性の薄そうな部分を少しずつ削って柔軟にした ・この判断も実は少し不安だった
49 6|振り返りと現状の整理 導入後 ・最初の導入プロジェクトに参加してくれたメンバーの反応は上々 だった(と思う) ・逆に考えることが減る ・レイヤーが増えることで変更がしやすくなる ・凝集度が高くなるため影響範囲の特定がとにかく簡単 ・というより、層ごとに単体テストがあるので、 影響範囲は勝手に特定される
50 6|振り返りと現状の整理 現時点での所感 ・この形がベストかはわからないが、既存の資産を捨てず、開発速 度も落とさずに(部分的にではるが)問題を解決できた ・もし、同じような課題を抱えている方や、 今後抱える方の問題解決の参考にしていただけたら幸い
51 これからのこと ・新しいApp領域を作成する場合にどんな規範に沿うか、 どんなアーキテクチャを採用するかは概ね決まった ・しかし、実際にはまだ最初に挙げた状態のままのAppが 沢山あり、そしてそれらの領域は大抵コア業務ドメイン ・ここから、まだ奔放な状態のAppについても オニオンに寄せていく予定 7|これからのこと
ニーリーではプロダクトエンジニア、 その他のポジションも積極採用中です! https://jobs.nealle.com/ We are hiring!!!
Thank you 53