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

TypeScriptでモジュラーモノリスやってみた

 TypeScriptでモジュラーモノリスやってみた

kansai.ts #9 で発表した内容です。

https://kansaits.connpass.com/event/338795/

morimorikochan

January 24, 2025
Tweet

More Decks by morimorikochan

Other Decks in Technology

Transcript

  1. 典型的なレイヤードアーキテクチャはこんな感じ 技術的関⼼によって 分割されてる Controller 層 🐿モジュラーモノリスとは? Order Controller Service 層

    Order Service Repository 層 Order Repository User Controller User Service User Repository Company Controller Company Service Company Repository 参考: Mark Richards Neal Ford 著 島⽥ 浩⼆ 訳 ソフトウェアアーキテクチャの基礎
  2. モジュラーモノリスはこんな感じ ドメインによって分割されてる Order ドメイン 🐿モジュラーモノリスとは? Order Controller Order Service Order

    Repository User ドメイン User Controller User Service User Repository Company ドメ イン Company Controller Company Service Company Repository 参考: Mark Richards Neal Ford 著 島⽥ 浩⼆ 訳 ソフトウェアアーキテクチャの基礎
  3. つらみ1. ファイル多すぎ問題 システムで扱うドメインの範囲が 広がっていくと、技術で分割され たディレクトリ配下のファイルが 肥⼤化する • 例えば特定のControllerに関 連するRepositoryをたどりに くい

    ◦ 複数のディレクトリをま たぐので 🤨なんで新規PJで採⽤した? repository/ company-repository user-repository notification-repository coupon-repository coupon-issue-repository campaign-repository campaign-entry-repository order-repository reservation-repository reservation-cancel-repository これに加えてテストコードも...
  4. 特定の機能だけ独⾃のディレクトリ構成にしたいが、レイヤーの原則を守る ために悩んでしまう‧無理な構成になる (1つのドメインがどんどん複雑になりやすく、こういった機会が多い案件 つらみ3. ⼀部だけ特例的な構成にしにくい 🤨なんで新規PJで採⽤した? Service 層 Order Service

    Repository 層 Order Repository User Service User Repository Company Service Company Repository 出典: Mark Richards Neal Ford 著 島⽥ 浩⼆ 訳 ソフトウェアアーキテクチャの基礎 Order Quotation Calculator ここでいい んかな❓
  5. 👀なんでモジュラーモノリス • つらみを解決できるから ◦ レビューしやすい点 ◦ モジュール内で特例的な 実装を取りやすい点 • モノリスと違ってDynamoDB

    と相性が良い • もしマイクロサービスにする と、開発チームは1つのみなの でチーム単位とサービス単位 が合わない Order ドメイン Order Controller Order Service Order Repository User ドメイン User Controller User Service User Repository Company ドメ イン Company Controller Company Service Company Repository 出典: Mark Richards Neal Ford 著 島⽥ 浩⼆ 訳 ソフトウェアアーキテク
  6. 📦具体的にどんなの? • 階層構造のモジュラーモノリス ◦ 特定のモジュールが肥⼤化した場合に分割しやすいように ◦ Djangoを参考に ◦ 1つのモジュール内はController→Service→Repositoryで構成 ▪

    +DI(Inversify) • serverless-expressで記述されていて、AWS Lambda上で動作 (Lambdalith) • Nest.jsは使ってない ◦ Lambdaのコールドスタート時に時間がかかる • データベースはDynamoDB ◦ RDBと⽐較すると割とテーブルごとに独⽴している ◦ モジュールを跨いだテーブル同⼠の依存が少なく、モジュラーモノ リスの弱点をカバー
  7. order/ // モジュール handler/ api-user.ts // エンドユーザーのルーティング api-admin.ts // 管理者のルーティング

    batch.ts // バッチ実⾏エントリーポイント service/ create-order.ts export-orders.ts order-repository.ts order.ts 📦具体的にどんなの? こんな感じ→
  8. order/ // モジュール handler/ api-user.ts // エンドユーザーのルーティング api-admin.ts // 管理者のルーティング

    batch.ts // バッチ実⾏エントリーポイント service/ create-order.ts export-orders.ts order-repository.ts order.ts order-quotation-calculator/ // ⼦モジュール service/ calculate-quotation.ts quotation.ts 📦具体的にどんなの? こんな感じ→
  9. 💪どうだった? • 実は運⽤して1ヶ⽉も経ってない • 構築して思ったこと ◦ つらみは解消できそう ◦ 実装時に⼀定の設計スキルが必要になる ▪

    思考停⽌で実装できるものではない。 ▪ モジュールに切り出すか常に⾒極める必要がある ▪ その点では技術ベースのレイヤードアーキテクチャは楽 ◦ モジュール内はある程度散らかっていても保守性への影響は少ない ◦ モジュールの境界をちゃんと決めないとモジュール間の依存関係が 複雑になって保守性が⼤きく下がりそう... ▪ Shopifyのブログでも強く⾔及されている
  10. 🤬課題: モジュールの境界をどう定義し制約するか Linterを使う • eslintを使っていれば no-restricted-pathsが使え ない🥺 • biomeだと useImportRestrictionsが

    使える! Order ドメイン Order Controller Order Service Order Repository User ドメイン User Controller User Service User Repository Company ドメ イン Company Controller Company Service Company Repository
  11. 🤬課題: モジュールの境界をどう定義し制約するか // 親ディレクトリ のファイル はなんでも importできる import { exportedValue

    as e1 } from "./../exportedValue"; // 同じディレクトリのファイルはなんでも importできる import { exportedValue as e2 } from "./exportedValue"; // 子ディレクトリは index.tsだけ import { exportedValue as e3 } from "./fuga"; import { exportedValue as e4 } from "./fuga/exportedValue"; //ERROR
  12. • レイヤードアーキテクチャ(技術ベース)のつらみは解消できそ う • 課題もある ◦ 実装時に⼀定の設計スキルが必要になる ◦ モジュールの境界をどう定義し制約するか ▪

    biomeだとuseImportRestrictions が今の所良さそう • 感想 ◦ 何年後かに答え合わせでまた登壇できるといいな 📚結論‧感想