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

複雑なドメインに挑む.pdf

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on. →
Avatar for Yuki Sakai Yuki Sakai
September 04, 2025

 複雑なドメインに挑む.pdf

Avatar for Yuki Sakai

Yuki Sakai

September 04, 2025

More Decks by Yuki Sakai

Other Decks in Programming

Transcript

  1. 5 © LayerX Inc. • 各企業が⾃由にワークフローを設計可能 • 故にビジネスロジックがとても複雑 • 加えて、UX

    を重視した結果、クライアントサイドに ビジネスロジックが集中 バクラク申請‧経費精算とは 「経費精算や様々な稟議を⾏う SaaS」 バクラク申請‧経費精算の難しさ
  2. 6 © LayerX Inc. バクラク申請‧経費精算とは • 各企業が⾃由にワークフローを設計可能 • 故にビジネスロジックがとても複雑 •

    加えて、UX を重視した結果、クライアントサイドに ビジネスロジックが集中 「経費精算や様々な稟議を⾏う SaaS」 バクラク申請‧経費精算の難しさ → 今⽇はそのごく⼀部を話します
  3. 8 © LayerX Inc. フィールドの⼊⼒⽅法をどう表すか 複雑なドメインに向き合う • ⾦額フィールドにはさまざまな⼊⼒⽅法が存在 ◦ ⼿動⼊⼒、OCRによる⾃動⼊⼒、サジェストからの

    ⼊⼒、変更不可の⾃動⼊⼒ • ⼊⼒⼿段によってその後の挙動が異なる ◦ システムによって固定値が⼊⼒される場合、ユー ザーは変更することができない → あなたならどのように実現しますか? ⾦額の⼊⼒を例に考えてみましょう
  4. 9 © LayerX Inc. 機能要件 フィールドの⼊⼒⽅法をどう表すか ⼿動⼊⼒ OCRによる⾃動⼊⼒ システムによる固定値⼊⼒ •

    ⼊⼒⽅法は3種類 ◦ ⼿動⼊⼒ ◦ OCRによる⾃動⼊⼒ ◦ システムによる固定値⼊⼒ • ⼊⼒⽅法でテキストフィールドのデザインを変えたい • 「システムによる固定値⼊⼒」の場合、 ユーザー⼊⼒は受け付けない ⾦額⼊⼒のサンプル
  5. 10 © LayerX Inc. ⼊⼒⽅法ごとのフラグを持たせる? フィールドの⼊⼒⽅法をどう表すか class PaymentAmountField extends StatelessWidget

    { const PaymentAmountField({ required this.amount, required this.isFilledBySystem, required this.isFilledByOCR, super.key, }); final int amount; final bool isFilledBySystem; final bool isFilledByOCR; @override Widget build(BuildContext context) { return SampleTextField( amount: amount, isFixed: isFilledBySystem, borderColor: isFilledByOCR ? Colors.grey : Colors.purple, showIcon: isFilledByOCR, ); } }
  6. 11 © LayerX Inc. ⼊⼒⽅法ごとのフラグを持たせる? フィールドの⼊⼒⽅法をどう表すか class PaymentAmountField extends StatelessWidget

    { const PaymentAmountField({ required this.amount, required this.isFilledBySystem, required this.isFilledByOCR, super.key, }); final int amount; final bool isFilledBySystem; final bool isFilledByOCR; @override Widget build(BuildContext context) { return SampleTextField( amount: amount, isFixed: isFilledBySystem, borderColor: isFilledByOCR ? Colors.grey : Colors.purple, showIcon: isFilledByOCR, ); } } • isFilledBySystem と isFilledByOCR が ともにtrueだったら? • ⼊⼒⽅法が増えたら? • ⼊⼒値がamount以外を持つようになったら? • ⼊⼒⽅法による仕様の違いがさらに複雑になった ら? • ⼊⼒⽅法とUI仕様が密すぎない?
  7. 13 © LayerX Inc. Sealedとは フィールドの⼊⼒⽅法をどう表すか • 列挙可能なサブタイプの集合を定義する • switch

    によるパターンマッチングで網羅性保証される • アプリケーション固有のドメイン状態を型レベルで表現することに使われる
  8. 14 © LayerX Inc. • ⼊⼒⽅法を表すSealedクラスを定義 • amountは抽象クラスで定義 • ⼊⼒⽅法ごとに具象クラスを作成

    ⼊⼒⽅法をSealedクラスを定義 Sealedクラスを使う sealed class InputValue { const InputValue({required this.amount}); final int amount; } class ManualValue extends InputValue { const ManualValue({required super.amount}); } class OcrCompletedValue extends InputValue { const OcrCompletedValue({required super.amount}); } class SystemFixedValue extends InputValue { const SystemFixedValue({required super.amount}); }
  9. 15 © LayerX Inc. UIをSealedクラスを⽤いた形に更新 Sealedクラスを使う class PaymentAmountField extends StatelessWidget

    { const PaymentAmountField({ required this.inputValue, super.key, }); final InputValue inputValue; @override Widget build(BuildContext context) { return SampleTextField( amount: inputValue.amount, isFixed: inputValue.isFixed, borderColor: inputValue.borderColor, showIcon: inputValue.showIcon, ); } } extension on InputValue { bool get isFixed => switch (this) { ManualValue() => false, OcrCompletedValue() => false, SystemFixedValue() => true, }; bool get showIcon => switch (this) { ManualValue() => false, OcrCompletedValue() => true, SystemFixedValue() => false, }; Color get borderColor => switch (this) { ManualValue() => Colors.blue, OcrCompletedValue() => Colors.grey, SystemFixedValue() => Colors.grey, }; } わかりやすやのためにor句は未使⽤です
  10. 16 © LayerX Inc. • 型による制約で無効な状態を防ぐことができる ◦ 例えば isFilledBySystem と

    isFilledByOCR が両方trueになることがなくなる • ⼊⼒⽅法の表現と仕様を分離 • 型によるパターンマッチングを使うことができるので、⼊⼒⽅法の増減に気づきやすい ◦ コンパイラが指摘してくれる Sealedクラスにより得られる恩恵 Sealedクラスを使う
  11. 17 © LayerX Inc. これは序の⼝ フィールドの⼊⼒⽅法をどう表すか • ユーザーによるフォームカスタマイズ • フィールドAの⼊⼒状態により、フィールドBの表⽰‧⾮表⽰が切り替わる

    • フィールドAの⼊⼒状態により、フィールドBのバリデーションが変化する • APIによる⾮同期バリデーション • 多くの申請種別、明細種別 • 下書き保存、申請後の修正 他にもまだまだ強敵がいます
  12. 19 © LayerX Inc. • 経験豊富なテックリードやEMも「過去⼀難しい」と感じるドメイン • 若⼿の内からこのしたドメインに挑戦できるのは⼤きな成⻑機会 • ドメインの複雑さの裏には多くのユーザーペインが多く存在

    ◦ ユーザーインパクトが⼤きく、価値提供に繋がりやすい ◦ LayerXではアウトカムを重視しており、チームとしてユーザー体験にフォーカスできている なぜ⾯⽩い? 20代で複雑なドメインに取り組む⾯⽩さ