$30 off During Our Annual Pro Sale. View Details »

社内共通ルールを値オブジェクトにして社内ライブラリとして運用してみた話

 社内共通ルールを値オブジェクトにして社内ライブラリとして運用してみた話

# Object-Oriented Conference 2024

2024/03/24 16:30〜 Track E(共1-304)ショートセッション(20分)

## 概要

社内共通ルールを値オブジェクトにして社内ライブラリとして運用してみた話

レバテックは現在、フリーランス・派遣・就転職、新卒の各領域を軸に様々なサービス・事業を展開しています。

これらシステムで共通となるルールがいくつか存在しています。
例えば、「メールアドレス」「電話番号」「生年月日」などのValidationであったり、振る舞いに関するルールです。

レバテックではこれらのルールを各システムが保持しており、ルールの分散とルールの不一致により、何件ものシステム障害を起こしていました。
このシステム障害の原因として、ルールの分散とルールの不一致もあるが、共通ルールが存在しておらず、どのルールが正なのかもわからず、システム障害を恒久的に防ぐことが難しくなっていました。

そこで、レバテックにおける共通ドメインライブラリとしてドメインオブジェクトや値オブジェクトを管理するライブラリを作成し、共通ルールをライブラリとして実現しました。
このライブラリはNPMのプライベートパッケージとして作成し、TypeScriptで記述されたドキュメント生成ツールであるtypedocを活用して、社内共通ルールを一元管理できるようにしたものです。

これにより障害発生を大きく削減することができ、また、今まで暗黙知になっていた共通ルールもこのライブラリにどんどん実装され、たくさんのドメイン知識を貯めることができました。
本セッションではこのライブラリ作成に至った経緯、ライブラリの概要、現在の活用状況、今後の活用についてお話しさせていただきます。

Tech Leverages

March 24, 2024
Tweet

More Decks by Tech Leverages

Other Decks in Technology

Transcript

  1. | © Leverages inc. 2 • 所属: ◦ レバテック CTO室 テックリード

    • 経歴: ◦ 2019年4月 大手Web企業 新卒入社 ◦ 2021年1月 レバレジーズ株式会社 中途入社 • 業務: ◦ システム戦略作り / アーキテクト / 採用 / 技術広報 ◦ R&D(最近はTiDBの導入検証を進めています) • 趣味: ◦ お酒・ゴルフ 自己紹介 Introduction かわうそ @_syoryu89
  2. | © Leverages inc. 11 • 本日、割愛させていただくこと ◦ システムとしての根本的な課題の内容 ◦ サブシステムやマイクロサービスの仕様

    ◦ 値オブジェクトのルール内容の公開 • 参考資料 ◦ プロダクトを伸ばし続けるために技術的負債と改めて向き合ってみた。 ◦ 「日本を、IT先進国に。」に向けて、レバテックCTO室を設立。 ◦ マイクロサービス化を中心においた技術刷新とその狙い 事前にお伝えしておきたいこと 事前共有
  3. | © 2023 Levtech Co., Ltd. 13 | © 2023 Levtech Co.,

    Ltd. 13 日本を、 IT先進国に。 日本を、どこよりも進んだ IT技術を持つ国にする。 そして、ここで生まれた IT人材や組織の力が、 世界中のすべての課題を、 解決する。 それが、レバテックが 叶えたい未来です。 VISION
  4. | © 2023 Levtech Co., Ltd. 14 | © 2023 Levtech Co.,

    Ltd. 14 事業ポートフォリオ Product エージェント プログラミング スクール コンテンツ メディア プラット フォーム ダイレクト リクルーティング ITエンジニア・クリエイターの フリーランス・転職・就職・教育の すべてを備える採用プラットフォーム エージェントを中心に、求人媒体、 プログラミング教育まで IT専門職のキャリアを厚くサポート。
  5. | © 2023 Levtech Co., Ltd. 16 | © 2023 Levtech Co.,

    Ltd. 16 • レバテックは中規模なシステム ◦ GitHubのリポジトリ数は”224” • 技術スタック ◦ ”TypeScript”がメイン ◦ PHPのシステムが一部あり • ”技術的負債”は絶賛解消中 ◦ 密結合なシステム ◦ 非構造化データ ◦ マスタデータの分散 ◦ … システムの現状 2. 当時のシステム事情 プロダクトを伸ばし続けるために技術的負債と改めて向き合ってみた。
  6. | © 2023 Levtech Co., Ltd. 17 | © 2023 Levtech Co.,

    Ltd. 17 レバテック(サービス)の大まかな仕組み 2. 当時のシステム事情
  7. | © 2023 Levtech Co., Ltd. 18 | © 2023 Levtech Co.,

    Ltd. 18 レバテック(サービス)の大まかな仕組み 2. 当時のシステム事情 エンジニアと企業をマッチング
  8. | © 2023 Levtech Co., Ltd. 19 | © 2023 Levtech Co.,

    Ltd. 19 レバテック(サービス)の大まかな仕組み 2. 当時のシステム事情
  9. | © 2023 Levtech Co., Ltd. 20 | © 2023 Levtech Co.,

    Ltd. 20 レバテック(サービス)の大まかな仕組み 2. 当時のシステム事情 集める=会員登録 → コアドメイン
  10. | © 2023 Levtech Co., Ltd. 21 | © 2023 Levtech Co.,

    Ltd. 21 • レバテックにおいて「登録」という機能はなくてはならないもの ◦ この機能が停止するとサービスとしての価値提供が難しくなる • 「登録」のプロセスにおいて重要な情報を取得している ◦ 名前、生年月日、メールアドレス、電話番号などの個人情報 • 各システムに連携できないと、ユーザーに価値提供ができない ◦ 登録情報をなんとしても”確実”にすべてのシステムに連携をしたい 会員登録 = コアドメイン 2. 当時のシステム事情
  11. | © 2023 Levtech Co., Ltd. 22 | © 2023 Levtech Co.,

    Ltd. 22 登録に関わるシステムの概要 2. 当時のシステム事情
  12. | © 2023 Levtech Co., Ltd. 23 | © 2023 Levtech Co.,

    Ltd. 23 登録に関わるシステムの概要 2. 当時のシステム事情 会員登録だけで10個以上のシステムが関わる
  13. | © 2023 Levtech Co., Ltd. 24 | © 2023 Levtech Co.,

    Ltd. 24 • 会員登録だけで”10個以上”のシステムが関わる ◦ 各システム / サブシステム / マイクロサービス / etc. • 営業支援システムとの連携 ◦ 末端のシステムでもあり、ユーザー・業務への影響もかなり大きい • そもそもの設計が良くない(小声...) ◦ いわゆる「分散されたモノリス」みたいな状態に近い 会員登録だけでも関わるシステムが多い... 2. 当時のシステム事情
  14. | © 2023 Levtech Co., Ltd. 25 | © 2023 Levtech Co.,

    Ltd. 25 どんな問題が発生したかというと... 分散されたシステムはしんどい...笑
  15. | © 2023 Levtech Co., Ltd. 26 | © 2023 Levtech Co.,

    Ltd. 26 • 1つでもルール(Validation)を変更するとシステム障害になる ◦ 例えば: ▪ とあるシステムでValidationのライブラリを変更 ▪ 変更時、デフォルトの設定のままでリリース ▪ システム連携間でドメインパート部分で予期せぬエラーが発生... • 正しいルールに修正したいが、正解となるドキュメントが存在しない ◦ 例えば: ▪ AシステムはXルールだけど、BシステムはYルールです ◦ さらに: ▪ 各システムを見てみると”すでに”ルールが違うところを発見することも... どんな問題が発生したか 2. 当時のシステム事情
  16. | © 2023 Levtech Co., Ltd. 27 | © 2023 Levtech Co.,

    Ltd. 27 • 1つでもルール(Validation)を変更するとシステム障害になる ◦ 例えば: ▪ とあるシステムでValidationのライブラリを変更 ▪ 変更時、デフォルトの設定のままでリリース ▪ システム連携間でドメインパート部分で予期せぬエラーが発生... • 正しいルールに修正したいが、正解となるドキュメントが存在しない ◦ 例えば: ▪ AシステムはXルールだけど、BシステムはYルールです ◦ さらに: ▪ 各システムを見てみると”すでに”ルールが違うところを発見することも... どんな問題が発生したか 2. 当時のシステム事情
  17. | © 2023 Levtech Co., Ltd. 28 | © 2023 Levtech Co.,

    Ltd. 28 • 1つでもルール(Validation)を変更するとシステム障害になる ◦ 例えば: ▪ とあるシステムでValidationのライブラリを変更 ▪ 変更時、デフォルトの設定のままでリリース ▪ システム連携間でドメインパート部分で予期せぬエラーが発生... • 正しいルールに修正したいが、正解となるドキュメントが存在しない ◦ 例えば: ▪ AシステムはXルールだけど、BシステムはYルールです ◦ さらに: ▪ 各システムを見てみると”すでに”ルールが違うところを発見することも... どんな問題が発生したか 2. 当時のシステム事情 ルールを策定して統一しよう! そのルールをライブラリとして配布しよう!
  18. | © 2023 Levtech Co., Ltd. 29 | © 2023 Levtech Co.,

    Ltd. 29 • 1つでもルール(Validation)を変更するとシステム障害になる ◦ 例えば: ▪ とあるシステムでValidationのライブラリを変更 ▪ 変更時、デフォルトの設定のままでリリース ▪ システム連携間でドメインパート部分で予期せぬエラーが発生... • 正しいルールに修正したいが、正解となるドキュメントが存在しない ◦ 例えば: ▪ AシステムはXルールだけど、BシステムはYルールです ◦ さらに: ▪ 各システムを見てみると”すでに”ルールが違うところを発見することも... どんな問題が発生したか 2. 当時のシステム事情
  19. | © 2023 Levtech Co., Ltd. 30 | © 2023 Levtech Co.,

    Ltd. 30 • 1つでもルール(Validation)を変更するとシステム障害になる ◦ 例えば: ▪ とあるシステムでValidationのライブラリを変更 ▪ 変更時、デフォルトの設定のままでリリース ▪ システム連携間でドメインパート部分で予期せぬエラーが発生... • 正しいルールに修正したいが、正解となるドキュメントが存在しない ◦ 例えば: ▪ AシステムはXルールだけど、BシステムはYルールです ◦ さらに: ▪ 各システムを見てみると”すでに”ルールが違うところを発見することも... どんな問題が発生したか 2. 当時のシステム事情 そのルール(ライブラリ)をドキュメント化しよう!
  20. | © Leverages inc. 31 • レバテックにおいて”会員登録”は重要な機能 ◦ 重要な情報を取しており、すべてのシステムに”確実”に連携する必要がある • 会員登録だけで”10個以上”のシステムが関わる

    ◦ 根本的な問題はさておき... • 登録情報のルールを一部変更するとシステム障害になってしまう ◦ 正解となるドキュメントも存在しない... • そこで、ルール策定・統一しよう! ◦ 社内ライブラリを作成して実現して、ルール(ライブラリ)をドキュメント化しよう! ここまでのまとめ 2. 当時のシステム事情
  21. | © Leverages inc. 33 • 初期段階でルール化(=値オブジェクト)にするスコープ ◦ 登録に関わる情報 ▪ 「メールアドレス」「電話番号」「生年月日」「姓名」「姓名かな」「姓名カナ」

    • ”ルールの策定と統一”を最優先で進めました ◦ 理想のルールも定義できたが、まずはルールの策定と統一を優先 • 値オブジェクトを独自ルールにする場合、どのシステムに合わせるか ◦ 基本的には連携において「末端のシステム」に合わせる ▪ 理想のルールを合わせるにも独自ルールが多かったため • 登録におけるシステム連携間の統合テストを作成 ◦ 本日は割愛 進める前の準備と前提の整理 3. ルール策定・統一に向けて行ったこと
  22. | © Leverages inc. 35 2.1. 値オブジェクトのルール策定 2.2. 値オブジェクトのライブラリ化 2.3. 値オブジェクトのドキュメント化

    2.4. 値オブジェクトのルール統一 ※ ルールを値オブジェクトに実装 ※ 「メールアドレス」に絞ってます 手順 3. ルール策定・統一に向けて行ったこと
  23. | © Leverages inc. 36 2.1. 値オブジェクトのルール策定 2.2. 値オブジェクトのライブラリ化 2.3. 値オブジェクトのドキュメント化

    2.4. 値オブジェクトのルール統一 ※ ルールを値オブジェクトに実装 ※ 「メールアドレス」に絞ってます 手順 3. ルール策定・統一に向けて行ったこと
  24. | © Leverages inc. 37 • 一般的な「メールアドレス」のルールはどうなるべきなのか? ◦ メールアドレスの国際基準「RFC」 ▪ RFCはIETFによる技術仕様の保存、公開形式

    ◦ メールアドレスに関連する文書に当たるのが「RFC5321」「RFC5322」 ▪ 「RFC5321」 • Simple Mail Transfer Protocol(SMTP)に関連するもの • メールの送信に関する基本的なプロトコルを規定 • Last updated 2020-01-21 ▪ 「RFC5322」 • Internet Message Format(メールのフォーマット)に関するもの • メールメッセージの構造やヘッダー形式などを定義 • Last updated 2020-01-21 「メールアドレス」におけるルール策定 - 一般化できるか? 2.1. 値オブジェクトのルール策定
  25. | © Leverages inc. 38 • TypeScriptで普及しているライブラリ「zod」をみてみると... ◦ まさかのIssue(Discussionsも)発見w ▪ RFC:

    Refactoring transformers and Zod 3 ▪ What is RFC No of the email validator? ◦ 少し読み解いてみると... ▪ RFCは実用上は不十分 ▪ それを補完するUASG-28が存在 ▪ UASG-28を実現するには、プログラミング言語に応じて違う • 参考 → ZodのメールバリデーションはRFCのどこまで準拠している? • (zodでこんな話が出ることは、他のライブラリも厳しいのでは?笑) 世の中のライブラリは「RFC」に対応しているのか? 2.1. 値オブジェクトのルール策定
  26. | © Leverages inc. 39 • TypeScriptで普及しているライブラリ「zod」をみてみると... ◦ まさかのIssue(Discussionsも)発見w ▪ RFC:

    Refactoring transformers and Zod 3 ▪ What is RFC No of the email validator? ◦ 少し読み解いてみると... ▪ RFCは実用上は不十分 ▪ それを補完するUASG-28が存在 ▪ UASG-28を実現するには、プログラミング言語に応じて違う • 参考 → ZodのメールバリデーションはRFCのどこまで準拠している? • (zodでこんな話が出ることは、他のライブラリも厳しいのでは?笑) 世の中のライブラリは「RFC」に対応しているのか? 2.1. 値オブジェクトのルール策定 一般化できなかった(オワタw)
  27. | © Leverages inc. 40 • 一般的なルールに当てはめるのは諦めました... ◦ 最新のメンテナンスが実行できていないシステムがあるため ▪ Last

    updated 2020-01-21よりも古い状態もいくつか存在 ◦ 世の中のライブラリが「メールアドレス」も対応しきれていない ▪ TypeScriptで普及しているライブラリ「zod」もその一例 ▪ UASG-28を実現するには、プログラミング言語に応じて違う • 「メールアドレス」を利用しているすべてのシステムを調査して策定 ▪ 調査対象: • 最大文字列長・最小文字列長・正規表現 ▪ 方針 • 「末端のシステム」のルールに合わせる(られるようにする) 「メールアドレス」におけるルール策定 - 独自ルールの策定 2.1. 値オブジェクトのルール策定
  28. | © Leverages inc. 41 • 策定したルールは値オブジェクトで扱う ◦ Stringなどのプリミティブ型としては扱わない ▪ 振る舞いなどを持つためにオブジェクトで表現

    • Validationはどこでやるのか? ◦ コンストラクタで行う ▪ ルールから逸脱した値オブジェクトを生成させないため • 例外をthrowした場合はどのような挙動にするか? ◦ Result型など値を返さない ▪ ルールから逸脱したまま、処理を継続させないため 「メールアドレス」における実際のモデリング 2.1. 値オブジェクトのルール策定
  29. | © Leverages inc. 42 2.1. 値オブジェクトのルール策定 2.2. 値オブジェクトのライブラリ化 2.3. 値オブジェクトのドキュメント化

    2.4. 値オブジェクトのルール統一 ※ ルール=値オブジェクト ※ 「メールアドレス」に絞ってます 手順 3. ルール策定・統一に向けて行ったこと
  30. | © Leverages inc. 43 • TypeScriptを利用してnpmパッケージを作成 ◦ Bundlerとしてtsupを利用 ◦ (最近はtsupを利用することが多いですね)

    • 値オブジェクトは基底クラスを設けて汎用化 ◦ structural subtypingを回避するため ◦ Validation発生時にThrowさせたいため • 単体テストを作成してルールを担保する ◦ ”メールアドレスのValidation仕様=単体テストの結果” ライブラリ化に向けてやったこと 2.2. 値オブジェクトのライブラリ化
  31. | © Leverages inc. 44 • 構造的部分型(Structural Subtyping) ◦ TypeScriptで採用されている定義 ◦

    シグネチャが等しければ置換可能 • 構造的部分型の回避 ◦ 値オブジェクトは同一性を構造で判断しない ◦ 値オブジェクトに名前を与えること(Branded Types)で回避 • Validation実行時はThrowさせる ◦ ルール統一が目的なので、ルールから逸脱した値は許容しない 値オブジェクトは基底クラスを設けて汎用化 2.2. 値オブジェクトのライブラリ化
  32. | © Leverages inc. 45 メールアドレス(値オブジェクト)の一例 2.2. 値オブジェクトのライブラリ化 値オブジェクトの基底クラス • Validationはコンストラクタで行う

    • 例外をthrowした場合は値は返さない • tryValidメソッドを実装側に強制させる メールアドレスの値オブジェクト • Branded Types用の名前を与える • 策定したルールからValidationを実装
  33. | © Leverages inc. 46 メールアドレス(値オブジェクト)の一例 - フロントエンド 2.2. 値オブジェクトのライブラリ化 フロントエンドの場合の注意

    • Throwするとユーザー体験に影響あり • ライブラリに合わせてValidationを実装 フロントエンド側にも導入しています • 値オブジェクトはTypeScriptのみで実装 • どんな環境でも導入は可能
  34. | © Leverages inc. 48 2.1. 値オブジェクトのルール策定 2.2. 値オブジェクトのライブラリ化 2.3. 値オブジェクトのドキュメント化

    2.4. 値オブジェクトのルール統一 ※ ルール=値オブジェクト ※ 「メールアドレス」に絞ってます 手順 3. ルール策定・統一に向けて行ったこと
  35. | © Leverages inc. 49 • TypeDocを利用 ◦ TypeScript製 ◦ ドキュメント生成ツール

    • 特徴 ◦ コードの型情報を読み取ってくれる ◦ TSDocのアノテーションに対応 ◦ プラグイン拡張可能 ▪ UIのテーマ変更など ドキュメント化 2.3. 値オブジェクトのドキュメント化
  36. | © Leverages inc. 51 2.1. 値オブジェクトのルール策定 2.2. 値オブジェクトのパッケージ化 2.3. 値オブジェクトのライブラリ化

    2.4. 値オブジェクトのルール統一 ※ ルール=値オブジェクト ※ 「メールアドレス」に絞ってます 手順 3. ルール策定・統一に向けて行ったこと
  37. | © Leverages inc. 52 • ルール違反している過去データのリペア ◦ 現在、存在しているデータを連携する可能性があるので、データリペアを実施 ▪ ※

    一度、登録したデータを使わない場合はリペア不要 • ルール反映の順序を考慮 ◦ 連携先のシステムで障害となってしまうため ◦ 「末端のシステム」に合わせてルールを作成したので「先端のシステム」から反映 • 再連携できる仕組みの構築 ◦ 再連携できる仕組みがあると、障害発生時にも業務への影響を小さくできました ▪ 登録→システム連携間で障害発生→データリペア→再連携実行→連携完了 ルール統一(反映)に向けて行ったこと 2.4. 値オブジェクトのルール統一
  38. | © Leverages inc. 56 • 社内共通ルール(ライブラリ)化されたもの ◦ 登録情報:メールアドレス、電話番号、生年月日、姓名、姓名かな、姓名カナ ◦ その他:パスワード、適格請求書発行事業者の登録番号など

    • 障害発生も劇的に削減できました ◦ 安定版のリリースと各システムに反映できたのが2023年8月 ▪ それ以降、不正なフォーマットのメールアドレス起因の障害は0件 • ドメイン知識を集めるプロセスが構築できた ◦ ルール策定・統一しようという動きによりこのルールを共通化しようという流れ 社内共通ルール(ライブラリ)の現在 3. ルール策定・統一に向けて行ったこと
  39. | © Leverages inc. 57 • 実際の値オブジェクトにより近づけたい ◦ Validationぐらいしかモデリングができていない ◦ 業務ルール等を反映していきたい

    • 値オブジェクトだけでなくドメインオブジェクトも進めていきたい ◦ 重複した業務ルールはたくさんあるので一元管理できるようにしたい ▪ 特に登録のプロセスにはたくさんのルールが存在 • なにより根本的な問題の解決を進めていきたい ◦ 分散されたシステムの密結合を取り除いていかないと...笑 社内共通ルール(ライブラリ)の課題と今後 3. ルール策定・統一に向けて行ったこと
  40. | © Leverages inc. 59 • ルール策定・統一の背景 ◦ 登録情報のルールを一部の変更するとシステム障害になってしまう ◦ その手段として「ルールを策定・統一」することにしました

    ◦ その実現方法として「ライブラリ化及びドキュメント化」を行いました • ルール策定・統一までの流れ ◦ 値オブジェクトのルール策定→ライブラリ化→ドキュメント化→ルール統一 ▪ 「一般化されたルール」にするのか or 「独自ルール」にするのか ▪ 基底クラスと単体テストを活用 ▪ TypeDocの活用によりドキュメント化を自動化 ▪ 再連携できる仕組みの構築しておくと進めやすい • 結果、障害発生も劇的に削減できました ◦ ドメイン知識を集めるプロセスも構築できた 今日のまとめ 4. まとめ
  41. | © Leverages inc. 63 • 🔥レバテック開発部 テックブログ🔥 ◦ https://zenn.dev/p/levtech •

    Leverages Tech Blog ◦ https://tech.leverages.jp/ • Speaker Deck ◦ https://speakerdeck.com/leveragestech • LevTech MeetUp(仮) ◦ TS/テスト/アーキテクト/分散システム など 情報発信中です!!! 宣伝