ICONIX で Re:DDD と FP
他社の実際の商品ページを見て、数日間勝手にモデリングしていた
商品ページは載せづらいので控えるけど、特定の契約に毎月金を払うとセットでいろんなサービスも毎月使えるというもの
「電気を契約するとガスとテレビもセット」とか「PC を分割で買うと保証サービスとアンチウィルスソフトがセット」とかそんなイメージのもの
それなりに実装してきたけど、なんか言うほどわかってない気がするなぁと思って初心に戻って守破離の守からやることにした
明日から使えるDDDのためのユースケース駆動開発(ICONIXプロセス) - Qiita をなぞりながら実装した
参考記事がすでに「ユースケース駆動開発」を砕いてくれているのに、それをさらに勝手に砕くとこんな感じだろうか
黄色が「やること」青が「作るもの(静的)」赤が「作るもの(動的)」
2行目は「概要」もしくは「成果物の満たす条件」
Process Flow Diagram に則ってやることと作るものを交互に整理した
勝手がテーマなんで(?)勝手にやりました
あくまで今の自分の理解の図示です
各フェーズに静的なものと動的なものが両方入ってるのがわかる
やってみて個人的に思ったことを添えるとこんな感じ
特に大事だと感じたのが「必ずユースケース記述やロバストネス図はドメインモデルの単語で書く」こと
そりゃそうだろと思うが、案外徹底するのが難しい
特に「ガスのプランに応じて割引を行う URL を作る」みたいな適当なことを書いてるとまずい
というかこの場合は多分ドメインモデルに「ガス」とか「割引」とか「URL」というただの単語が列挙されているだけで、それを使ってるから良いんでしょ、という状態になっていると思う
僕の経験上極めて重要なのが、「商品定義」と「契約管理」と「課金請求」をちゃんと整理することと、「名詞」と「動詞」をちゃんと整理することの2つで、必ずドメインモデルを軸にした設計フローはそこを強制的に整理させてくる
「ガス」は「月々 xxx 円で yyy 分量のガスが使えるもの」という定義か、「2020/10/25 から A さんが契約しているもの」という契約かをごっちゃにしてはいけない
「ガスは 900 円」という定義と「今月 900 円を請求する」という行為もごっちゃにしてはいけない
「割引」も「割引額」という値か「割引する」という行為かで扱いが全く変わる
もしかしたら「割引ページ」かもしれない
そしたらシステムからユーザへの行為ではなくてユーザからシステムの行為になるのでユースケースモデリングなんてひっくり返る
あーあと「購入した商品名をメールする」とかも要注意
「メールする」をふわっと動詞だと思ってるとmailRepository.send(itemName)
みたいになる メー...ル...?? 内容と文面はいずこに...??
「メールを送信する」だと思っていればmailRepository.send(Mail.of(itemName))
みたいに「メールドメイン」がちゃんと出てくるはず
「ガス」とか「割引」が単語帳にあるから良いでしょ、のレベルだとここまでできないけど、逆にドメインモデルがちゃんとしていればそれを軸にした強制的な相互洗練はすごい機能すると感じた
あと類似で「商品名」と「会社名」が同じパターン
ガスとセットで Netflix が使える、Netflix へはユーザに変わりガス会社が支払いを代行する、みたいなケース(そんなサービスあるか?)
だせーとかめんどくせーと思っても無理にでも識別しておかないと、「契約管理」と「課金請求」で混ざる
実装とかまで行っちゃうとかなりしんどい 「Netflix.java is 何」状態になる
とりあえずででも「Netflix 契約」とか「NetflixService」とか書いて強制的に分離してみるところからやると良さげ
名詞の列挙は簡単なんだけど、単なる列挙をドメインモデルに強制的に引き上げてくれるプロセスなのかもしれない
我流で何種類も失敗してきて数年かけてこういう理解に到達したけど、このプロセスの「強制的に磨かせてくる」感じは結構すごいと思った
今までは我流でこんなこと(とか)をやっていた
システムにおいて発生する全イベントを列挙・整理する(ここでのシステムは利用者とプログラムとオペレータや SE 等全てを統合してシステムとしている)
その各イベントの入力と出力とシステムに与える影響を整理する
この段階での入出力は「キー」は必ず徹底して整理する
影響は例えば「契約を利用開始にする」「メールを出す」みたいに列挙
イベントの前後関係を整理する
例えば「申込」「解約」「申込」「解約」はぐるぐるできるとか
なんやかやもう少し細かく設計してエンティティの認識とか合わせたら、シーケンス図じゃあなくて本文空で型とかリポジトリとかだけ全部作って頭からケツまでコンパイル通す
レビューしながら中身埋める
これで少なくとも自分は「ものが作れない」ってレベルで困ることはなかったから、一度もロバストネス分析をしたことがなかった
「自然言語を実装できるものにする手法」と聞いていたので、別に触れなくても良いかなと思っていた(自分で確認もせずにね)
なんとなくかつ手前味噌だけど、叙述的な記述を若干飛ばしてもう少し実装に近い気持ちで似た整理をやっていたのではないかと思う
もともと「コーディングなんか楽しい」みたいなところから入っていったので、叙述的ではなくプログラム的な文書で整理していたのかなって感じ
抽出したただの名詞を実装できる形に変えながら振る舞いを整理しようと思うと、こういうやり方になった
ただやっぱ素直にやったら、全体が強制的に洗練されていく様はおもしろかった、反省
その反面まだ若干「ロバストネス分析めんどくせーなー、さっさと実装で検証したい」という気持ちも正直ある
余談
「キー」に徹底して気を配っているのは、主キーを誤った結果地獄を作ったシステムをたくさん知っているから
例えば「電話番号」なんて世の中で使い回されるから全然主キーじゃあないし、貸与してる備品をトレースしようと思ったら「社員番号」だって全然主キーじゃあない
あとは「集約設計」について不勉強なことがよくわかった
これに関しては本当に経験が少ないし無知なので我流もクソもなく単純によくわからなかった
「ガス」や「テレビ」は「電気」と必ず連動しているので単体で解約したりできない、という仕様だけ見れば「電気集約」という発想にもなるかなと思うけど、「ガス」や「テレビ」それぞれに「商品定義」「契約管理」「課金請求」があるので肥大化するのは容易に想像できる
そうすると例えばマイクロサービス的に独立させる方が良いのかな、と(そこまでしないとしてもモジュール分離くらいは的な)
マイクロサービスと集約って背反する概念?
the 無知
ちなみに今回は実装は haskell で fp 的にやろうという試みもあった
別に全く得意とかいう程ではないけど、なんか好きなんで
これなんかモロその影響を受けてる
本文空で型とかリポジトリとかだけ全部作って頭からケツまでコンパイル通す
レビューしながら中身埋める
もしかしたら「値(名詞)」と「行為(動詞)」を徹底して分けるのも、fp に影響を受けているのかもしれない
正直今回は分析設計が自分の中でうまくいかなかったので、ここの検証はまだ足りてないけど、感じたのは 2 つ
ロバストネス図の「コントロール」をどんどん結合して workflow みたいな形で実現できたら面白いなと思った
ロバストネス図とか PFD って基本的に「やること」と「できるもの」が交互に出てくるので、とても関数的だなぁと思うから
今回はちょっとそこまで想定して設計できなかったので、持ち越し課題
もうひとつは若干実装しづらいと思った点
oop だとtype.function()
になるところを fp だとfunction(type)
になるわけだけど、このfunction
を実装する場所をどこにするかがしっくりこない
クラスA
にインスタンスメソッドb = a.createB()
が定義されるときは依存はA -> B
になるけど、fp だとb = start(a)
になるので依存はstart -> a, start -> b
になる
Type A
からFunction createB
に向かって線が出ていないので、自分に行われる操作を探すのが oop と fp で逆になる
このcreateB
を A.hs に書くか B.hs に書くか迷う(functions.hs に置くのはないかなー 神.hs になってしまう)
なんとなく A.hs に書いて「変換先一覧」みたいにしたくなるけど、B.hs なのかなー
A, B から C を作ります、みたいになると A には置けないしなー
oop だって C に static で A と B を受けるメソッド作ったりするし
なーんて、結構ポリシーを持たずにやってると終盤で困ることになったりする
特に haskell は双方向 import が(基本)できないので、コンパイルできなくなったりしたことが前は結構あった
必ずしも fp が不向きとは限らなくて、例えば haskell の関数と副作用の徹底した分離みたいなところは十分ドメインとして有用だと思う
副作用を極力排除する過程でドメインを洗練しようという発想が DDD の個人的なスタート地点だったのを思い出した → DDDをHaskellで考える 業務ロジックとシステムロジック - Qiita
問題領域が数学なら適した言語は変わるってこともあるだろうし
なのでなんか oop の発展形として ddd があるよみたいなイメージには個人的には一石を投じ続けたい(稀によく感じる)
別に何かを敵視したりはしてないけどね
いいとこ取りしたいだけ
要お勉強 ( fp, ddd )
今年の目標が定まってよかった
本を読もうw
圧倒的に無知なことを正しく確認できたw
本これしか読んでないの...
積んであるエヴァンス本と nrs 本と、あとユースケース駆動開発を読もう
これは読んだけど、ちょっと今知りたいこととは違う内容だったかな...
x と y はわけるのが大事とかいろいろ言っといて、それをプロセスの中で上手にやれなかったのでひどい出来上がりだった
とりあえずそこら辺の反省を踏まえるのと、バッチとかトランザクションっていつ設計するのか、ロバストネス図の先の詳細設計とか集約設計とかの疑問(無知)を解消したい
今回は手探りすぎてズタボロな出来だったので、近いうち雪辱を晴らす
以上
ちゃんと学んだらこのスクラップを掘り起こして整理する、かも