「レガシーをぶっつぶせ」レポート

レガシー化したSWに苦戦していたところ、ぴったりなセミナーを見つけたので反射的に参加しました。
参加してみて「こんな集いを求めていた」と心底思いました。
https://genbade-ddd.connpass.com/event/127494/

※3会場構成で発表は2会場で同時進行、1会場はハンズオン
※セミナー定員260人のところ倍近くの500人が申し込むなど、
 かなりの人が反応したことに驚きつつ納得していました。
 (規模と回数の拡大を心より望んでおります。)
 (そして、国内のSW設計における
  熱量が上がることを願っています。)

13:00~13:10
 オープニング
 (株式会社チームボックス 安西さん)

 オープニングとして、今回この場を設けていただいた経緯についての説明からスタートしました。

経済産業省の「DXレポート」

DX
=デジタル・トランスフォーメーション
将来の成長、競争力強化のために、新たなデジタル技術を活用して新たなビジネス・モデルを創出・ 柔軟に改変する

経済産業省の「DXレポート」によると、2025年以降レガシーシステムが年間12兆円の損失(東京オリンピック4回分)の技術的負債を生むとされている。

https://www.meti.go.jp/shingikai/mono_info_service/digital_transformation/20180907_report.html

 レガシーシステムに対しては、ドメインのスコープで改修する際の負債としては考えたことがありましたが、日本全体での負債として考えたことはなかったので、とても衝撃的でした。ましてや、それが年単位でオリンピックを4回開催できるレベルとは。。。
 この話を最初に聞くことで、「レガシーコードとの格闘は至上命題」なのだと認識を変えることができました。

「システムのブラックボックス化」「変更容易性の低下」という問題
 ・ちゃんと設計しよう
  →変化に強い設計をするべき
   →そのひとつとしてドメイン駆動設計を取り上げる
 ・問題解決のためには現場のドロドロ感を1つずつ解決していく
  →そして日本をちょっとずつ変えていきたい
 ・そのためには現場のドロドロ感を共有していきたい

 オープニングの話をお聞きしながら、本当にこんな場が欲しかったと心の中で激しく同意しておりました。特に、レガシーシステムを抱えているのは、世の中の一部だけで自分の職場がその中に含まれているのだと、今までそう考えていました。でも、主催者の方々、登壇者の方々、そしてたくさんの参加者を目の当たりにして、これだけの人が同じように苦しみながらレガシーシステムと向き合っているのだなと心強く感じました。

13:10~13:50
 ソフトウェアの核心にある複雑さに立ち向かう
 (株式会社ギルドワークス 増田さん)

 さっそく増田さんの講演がスタート。増田さんの著書は拝見したことがあったのですが、直接講演をお聞きするのは初めてでした。時間が足りなくなるほど熱いお話をお聞きすることができて、かなり触発されました。

対照的な3つのプロジェクト
・素早く最初の一歩を踏み出したSW
・ドメインロジックの設計と改良を重視したプロジェクト
・ドメインモデルに基づくえたープライズシステムの開発

 3つとも最終的には動くシステムの開発には成功しているが、ドメインロジックの設計と改良を重視しないとレガシーなシステムとなってしまう。
 レガシーシステムにしないためには、ドメインロジックの設計をしっかりと行い、「進化と成長を続けるソフトウェアの開発を続けていく」べきである。
 そのためには、核心となる部分を見定め、核心でないところで楽をすることが大切。
 新規に開発したシステムでも一年くらい経過しただけですぐにレガシーシステムになってしまう。だから継続して取り組むことが重要になる。

 No More Legacy!
レガシーはもうたくさんだ!

このフレーズがみんなの同意を表しているようですごく気に入りました。

ソフトウェアの変更容易性
変更容易性の向上は
・開発コスト
・運用コスト
・性能改善
・開発スピード
・使用性改善
全てにプラスになる。

逆に、変更容易性の劣化は、すべてのブレーキとして働く。
ドメイン駆動設計はSWの変更を楽で安全にする設計技法
<複雑さの核心はどこか?>
ドメイン=ユーザの活動。ビジネスそのもの。(複雑さの源泉)
ドメインロジック=ドメインのSW表現。コードの一部。
         (複雑さの核心)

<複雑さ(ドメインロジック)をどこに書くか>
ドメイン層に記述し、アプリケーション層が使う。
SWが複雑となる理由
ドメインロジックをもっと限定的に考える
 → ビジネスルール(事実データを使った計算/判定)

SWが複雑となる理由は、ビジネスルールを適用する条件分岐による
→ 関心の分離による工夫

→ モジュール構造の工夫

 ※ビジネスルールを考えると扱うデータ数が膨大となる
  が、データ数の増加は面倒だが複雑ではない。
  条件分岐の方が複雑で問題化しやすい。
ビジネスルールを中心に考える
  → ビジネスルールの記述を隔離する(ドメイン層の形成)
    → トランザクションスクリプト
      ビジネスルールの条件分岐が断片化/重複化すると
      変更が困難となる。→ 隔離する

条件分岐を把握できていれば、変更時に影響範囲の特定ができる。
→ 自信をもって変更を加えられる。

ドメインロジックをもっと限定的に考える
 → 計算モデル

計算モデルを単純にする
計算モデルを考える際は、入出力層の構造は意識的に考えない
(画面やデータ構造に計算ロジックが引きずられるのを避ける)

型思考
ビジネスルールを記述する部品。
ビジネスルールに登場する値を分類する。
値の型ごとに有効な値の範囲を定義する。

(オブジェクト指向の基礎としての型)
型=値の範囲の定義と操作の定義(カプセル化)
ポリモーフィズム=オーバーロード、ジェネリクス、サブタイピング
継承=親の特性をこの型が引き継いで利用する
ビジネスルールを構成する3つの要素
Fact
  事実の表現(数値、日付、場所、名称....)
Rule
  Factを使った計算や判定のロジック(大小比較、一致/不一致)
Goal
  知りたいこと(計算結果、判定結果)
現場で複雑さと闘う
深いモデルを探求する
★ビジネスルールの中核を見定め、中核に集中する
★ビジネスルール全体の関係を俯瞰的に整理する
エヴァンス本の読み方
エヴァンス本には複雑さとの闘い方が書かれている
・全体像を把握するくらいに浅く読む、
・問題に向き合うときに詳しく読む
・第三部に闘い方が書かれている

闘い方
 もやもやしているものを強引でもいいから言語化する

14:00~14:40
 レガシーシステムからモダンな環境への移行
 (ヤフー 清水さん)

レガシーシステムの概要
- 歴史が長い
- アドオンを繰り返して拡張されてきた
- 元の処理ルートを生かしたまま新規機能を追加
- 歴史を重ねることで処理の重複、ルートの分岐
 (既存ルートには手を加えたくない)
- 問題
  - 冗長モノリシック
  - 密結合
  - データベースと密接

※「伸びしろ」しかない
DDD実践
- CTOから「モダンな環境にシフトせよ」との指示
  - 当初の議論
    - 言語シフト
    - サーバーレス
    - マイクロサービス
  - そもそも何のためにモダン化するのか(Why)
    - 改修コストが高い
    - 影響範囲大
    - 改善に消極的になりやすい
      -> 改善が進まない
      -> ビジネス案件への対応に時間がかかる
- どうやってモダン化するか(How)
  - 今後のビジネスは?(読めない)
    -> 変化に強い、改善しやすいシステム
      -> DDDでやってみよう(それが我々のモダン化)
- 取り組み
  - セミナーで情報収集
    - DDD
    - マイクロサービス
    - アジャイル
- 業務分析
  - ヒアリング
  - 運用経験(課題が多い場所等の洗い出し)
- ドメイン分割モデリング(具体化)
  - 図の作成
  - ホワイトボードに書き出し
  ※当たり前のことだが泥臭くやることが重要
- アーキテクチャ検討
  - 図の作成
  - ホワイトボードに書き出し
  ※当たり前のことだが泥臭くやることが重要
- ドメイン設計/モデリング
  - ドメイン分割
    - 変更要因で分割
    - 変更頻度で分割
    - オーナーシップをとれる粒度
    - ビジネス、運用面の観点で分割する方が保守しやすい
    - どこまで分割するか?
     =重要なものは厳格に、重要でないものはざっくり
      ※重要になってきたときに厳格に再定義する
教訓
- Why(改善の必要性)を考えた結果のDDDという選択
- 方法論は体系的に学ぶ
- 運用フェイズに移ってから改善しようと思えるかが
  改善の活性化につながる
現場の声(思わぬメリット、大変さ)
- IF仕様が自然と整備されていく
- 認識の齟齬が減る
- 独立性を意識→ドキュメント化、見易さを意識(swagger活用)
  - 詳細設計はシンプルになる
  - 分割してみると大したことない
- 後からリファクタリング前提
(処理のリファクタリングよりも独立性(大枠)のFixを優先する)
- コストはそれなりにかかる
  - 再設計になるので開発コストが増す
  - 分割することでコストは必然的に増える
- ドメイン毎に適切なコスト感を意識する
  - 改善するドメインの選定などに必要な情報となる
  - 経営層にはレガシーさの問題についてなかなか認識して
   もらえない
   → コスト感に置き換えて説明すると良い
今後の展開
- エンジニア発信の施策を推進
  - データ、AIの利用
- プロセス、組織のモダン化
  - 企画~開発まで独立して動けるチーム作り
- DDDはリリースしてから(1stができてから)が本番
質問
- 改善時のどのような作戦で臨んだか
 レガシーはレガシーで置いておいて新規にモデルを整えた

14:50~15:30
 設計人材を育てるために DDD をどう使うべきか?
(レヴィ 萩原さん)

- 設計って大事(新規開発でも、レガシーでも)
  - 設計できる人がたくさんいれば大きな絵ができる
   設計の話ができる
  - 複雑さにどう立ち向かうか
- 設計をなんとかする
  - システムモデリングツール「Balus」
    - ツール開発、コンサル
     ※ツールだけでは使い手を選ぶ
  - Balusも複雑化
    「敵は強い、強すぎる」
     →みんなで闘う
  - 設計と実装は似ているようで違う
  (実装ができても設計ができるとは限らない)
  - 設計とは
   抽象度を切替ながら検討するプロセス自体のこと
   このArtをどうやって伝えるか
  - ドメインモデル
    - 利用者の関心ごととシステム内のモデルが
     ダイレクトにつながっている
 ドメインモデルの議論
- 責務の分割と組合せ<-設計の基礎となる力
  -> ドメインモデルで考えることが役立つ
    プロパティではなくメソッド(動詞)を中心に考える
全体が連動する
- 設計は一方通行ではない
 トップダウンで決まると美しいが、
 設計はトレードオフをしながらバランス取ることが重要
コミュニケーション
- 師匠の問いかけ力が重要
よかったこと
- ドメインモデル上で議論
 設計に引きずられない、理解が深まる
- 別の視点との行き来
- 継続的なコミュニケーション
 モブ設計的に考え方が継承されていく
うまくいかなかったこと
- 実装とドメインモデルの距離が遠い
- 時間変化についての議論が漏れがち
- ValueObjectがうまく作れない。
問題点
- 設計力をどう測るか
実施した所感
- レビュー中心のやり方だとできあがったものベースになりがち
- トレードオフ中の議論が重要と感じた

15:40~16:20
 DeliveryとQualityを両立させるために
 僕らがやったこと
 〜トラベルシステムの技術全面刷新〜
(ヤフー 関口さん)

システムの刷新を行うことになった
- 良いものを作りたい
- 制約(予算、期間)は満たしたい
- 設計(Q)
- 登り方(QとD)
- 非エンジニアの同意と承認の工夫(D)
刷新の進め方
- ビジネスロジックの抽出
- ドメイン単位で分割
問題
- WebとAPIの乖離
  - 複数のAPIから呼ばれる処理が出現
  → WebとAPIの間にOrchestration層を追加
    ※アダプタ(ジョイント)の位置づけ?
- データ定義が荒れている
  → Integration層(中間層)を挿入
   → DBの種類の違い、異なる専門性のDBを独立できる
コンポーネントの分割
1. インプット
  - エヴァンス本で自己学習
  - DDDワークショップ
2. 対象コンポーネントとメンバーを決定
  - 対象=予約
  ※DDDでは期限内にアウトプットを出すことが重要
3. 関心毎の各自理解
4. チームの言語基盤を作る
5. 骨格を説明する
 日本語で説明ができるかどうかが重要
6. モデルと実装を紐づける
 - 役に立つ部品を見つけ出すことが重要
登り方の工夫
- 一括全面刷新はやらない
  - 製造コストは少ない
  - 品質的リスク
  - 工期的なリスク
- 段階的な刷新
  - スモールスタートで刷新
  - 平行稼働して検証
  - 問題がなければ現行サービスを削除
  - OrchestrationとIntegrationで現行システムと刷新システムの
   組み合わせを制御
- 検証
  - システム視点
    - 機能落ち
    - 障害がないこと
    - メトリクス
    - パフォーマンス
  - 保守性視点
    - 開発効率は向上しているか
    - 運用フローは問題ないか
問題
  - 暗中模索
    - 判らないことが多い
    - 言語

    - 対策
     - 中心的に進める人と壁打ちする人の選択
     - 中心的=作業者
     - 壁打ち=スキルセットが同等かそれ以上
     (案件は持たない、
      質問にそこそこ適格に答えてくれる)
- 仕様書の消失
  - 正解がわからない
  - 対策
    - ソースコードから仕様を掘り起こす
- 新しいことをやりたい欲求対策
  - こらえる

今後
    - きれいを維持する
        - きれいを維持するWGを作る(開発ヘルプデスク)
        - ガイドラインを制定
            - サービス
            - レイヤー
            - 言語
            - パッケージ構成
    - 対応コストを減らす
        - 選択と集中
            - 開発効率の向上につながるかという観点で判断
            - 過去の実績から効率向上が見込めるものは取り入れる

- 最終的にシステムに組織をあわせたい
    - システムにあった組織に再編成
        - 特定のコンポーネントが一人しかしらいない状態は避ける

非エンジニアの同意と承認の工夫
- ビジネスメリットで語るべき
    - サービスKPIで語る
- 実績値で語る
    - 実際にリリースした結果で語る
        (開発効率の向上など)
- スモールスタートとしてまったく同じ機能追加を
    2パターンで実施し、比較
    - ビジネスメリットと一般論でゴリ押し
    - スモールスタートして効果検証することを前提条件にする

- 計測した結果
    - o全行程で工数減少
    - oリグレッションテストの減少
    - o工期の短縮(人員が独立して作業に集中)
    - x詳細設計の増加
    - x単体テストの増加

16:30~17:10
 実録!LOHACOにおけるDDDと
 CleanなArchitecture

https://speakerdeck.com/askul/ddd-and-clean-architecture-at-lohaco

- Lohaco
    - レガシーシステム化(モノリシック)
    - 刷新する際にDDDとCleanArchtectureを導入
    - 7年前からサービスを開始
- レガシーは感謝するべきもの
    - ストラングラーアプリケーションパターン
        サービス分割してモノリシックから脱却
        小さいサービスからモダンに
- 複雑なのはドメインそのもの、ユーザの活動やビジネス
 → 設計でこの複雑さを扱わなくてはいけない
- 複雑さをコントロールしたい
 → ドメインモデリングしよう
- ドメイン分析
- ユビキタス言語
- コンテキストマップ
- コンテキストマップからサービス分割
- 境界づけられたコンテキストの統合
    - ドメイン知識をどこまで公開するべきか悩む
    - ユビキタス言語のブレにより手戻りが生じた
    - コンテキストが蜜結合 → ドメイン分析の見直し
- 教訓とメリット
    - DDDは開発当初から実施する必要がある
    - ドメインモデルの理解が進む、コードが語り始める
    - 即効性のあるプラクティスはどんな現場でも有効
- 実践
    -> CleanArchtecture
        - 依存は外から内へ
            - レイヤーを分割
    - Mavenのマルチ~
        - サブモジュール間の依存関係を制御
- 結果
    - 依存関係に制限をつけることでアーキテクチャ違反があると
        コンパイラが怒ってくれる
    - レイヤー単位で単体テストが書けるようになった
    - レイヤーの制限をざっくり作ってしまった

    - DDDの中から即効性のあるプラクティスを導入すると良い
        - ValueObject
        - 腐敗防止層の導入
「レガシーは明日モダンにはならない」

17:20~18:00
 ビジネスルールの複雑さに立ち向かう実践技法

https://www.slideshare.net/masuda220/ss-144958278

- ドメイン駆動設計で作る理由
 進化と成長を続けるSWを手に入れる
 変更を容易にする
- ソフトウェアの核心にある複雑さに立ち向かう
- ビジネスルールに立ち向かう4象限
    - 4象限は相互に依存する
        -> 行き来して視野を広げながら深堀する
            -> 良い設計をするためには必要になる
                -> 行き来し、徐々に4つの象限を広げていく
- ビジネスルールを「型」を使って記述する
    - Fact
        値の範囲を定義
    - Rule
        値を使ったロジックを定義
    - Goal
        知りたいこと(計算結果、判定結果)の表現手段

- 値オブジェクトのカタログ
- 値オブジェクト
    - 動作が安定する
        境界値テストが意味を成さなくなる
    - 区分ごとのビジネスルールを扱う
        - enum
- コレクション操作の問題と改善

18:10~19:00
 パネルディスカッション

チームメンバーがDDDに興味を持たず、やる気を示さない。どうメリットを伝えればいい
- (補足)業務委託の人たちを巻き込んでやるためには
    どうすればいい?
- 一緒に勉強し、ディスカッションや実践を一緒にする
- モチベーションは人それぞれ。
- 一切DDDとか言わない、マーティンファウラーの
 リファクタリングを取り入れる
- 正面切ってDDDと言ってやらない方が良い。
DDDで開発する際にリリース日程や作業工数をどのように見積もって計画すればいいか
- DDDだからどうという訳ではない。見積もりは見積もり。
- 経験を積むことで見積もれるようになる。
(普通の見積もりと同じ)
- 小さいサイズから始める
- DDDではアジャイル前提
 → (イテレーションを繰り返して精度を上げる)
ユビキタス言語の管理方法
- 悩んでいる
 - 新しい言葉がいろいろなところで生まれる
- 一度ユビキタス言語を作ったが、どう使われているかは謎
  (現場では使われていない)
- (補足)
- 問題にはならないか?
- 中間管理職(翻訳担当)のような人がいる
- ソースコードに入れてしまう
- 最初から作る気はない
- 関係者とフラットにやって行くことに価値を見出していない
- ポイントを絞って深堀する(相当言葉にこだわる)
処理速度とのトレードオフはどれくらいありますか
- (補足)
- 開発当初は保守性を意識するが、終盤にかけてスピード優先に偏っていく
トレードオフの判断境界等があると知りたい
- パフォーマンスを求められるところをコンテキストとして切り出してしまう
コードが多くなりがちですがテストコードはどうしているか
- Pythonで通常の実装をすると変数にどんなデータが入るか
 担保されないので細かいテストが必要
 → 型に倒すことで入るデータの種類が担保されるのでテスト量が
  減る
 (テストを減らそうと意識していないが、結果的に減った)
- 型の存在は重要
- 型によって制約を設けてテストコードを減らす
- テストは大変なので減らしたい
- テストコードは書いていない
- E2Eで実際に動かして確認することは重視している
Railsでうまくやる方法はあるか
(それともリプレイスした方がよいか)
- Pythonの場合PyLintがあるので型の概念を導入できた
- Railsは0から1を作るには強力だが、モデリングという概念を入れにくい
- 考え方の文化が違う(良さと悪さがある)
- リプレイスには大きなリスクが伴う
-> スモールスタートで徐々に置き換えていく
- レガシーと共存することは大事
- ただし、きっちりと壁を作り、守るべきところは守る
DDDなくても開発できるじゃんって言われたときの
ベストな回答は?
- 今困っていないならば、無理に実施する必要はない
- 変更労力が減るのは確か
 -> 悩みや受注機会の拡大にはつながる
- エンジニアリングを駆使して試作やビジネスを回していく
 必要がある
- 小さく失敗を積み重ねてサービスを築く
- 仲間が数人いた
- 巻き込みやすい人を巻き込む
 (いかに母集団の2割りを味方につけるか。
 (組織改革をする際の基準になる
ユビキタス言語を作ってもビジネスサイドが違う言葉で会話していることへの対策は
- ビジネスサイドの言葉の方が正しいことがある
- 異なるドメインの人が異なる言葉を使っている場合
-> ドメインに分けて別定義とした

クロージング

現場でおきることのシェアという目的通り、良い場になった。
今後も続けていきたい。
外の話はきれいな話が多いが、そんなことは絶対ない。
ドロドロした内容を今後も共有していきたい。

この記事が気に入ったらサポートをしてみませんか?