Object-Oriented Conference 2024に参加してきました

ooc.dev

オフラインのカンファレンスの参加はコロナ禍前からの4年ぶりの参加となりました。

OOCも4年ぶりということで、縁も感じつつ、4年前と比較してより実務のどこで実践していけそうかという具体をイメージしながら公演を聴いていました。

自身のステータスの変化を感じると共に、このような学びの宝庫である機会を提供いただきありがたい限りです。

登壇者、スタッフ、関係者の方々、ありがとうございます!!

今回は完全にお客さんで、何も貢献できていないのに学びだけ得たという状態で大変申し訳無いので、次回あった際は何かしらの形で私も貢献できればと思います。

以下聴講したセッションと所感です。

戦略的DDDを実践するための跳躍力

speakerdeck.com

DDDの戦略パターンを後天的に以下にして実践していくかというお話でした。

DDDの戦略パターンを実践していく上で、ドメインエキスパートの実際の業務を見る中で、ドメインエキスパート自身にとっては常識や意識していないこと、開発には関係ないと思って情報落ちしていたりする物が見えてくるというお話が特に勉強になりました。

私は開発とドメインエキスパートで組織体系が違う組織に属しているのですが、「互いの専門領域に踏み込んでいくの気を使いがち」という話は実体験として共感できましたし、その上で

  • 職域を超えて、わからないことをわかるまで追いかける力が大事
  • 自分が理解したら目的の半分は達してしまうが、チームに伝播しないという意味がない

という話は、もう爪の垢を煎じて飲みます。

今後自身の業務でより広範囲を巻き込んでいく際の参考に是非させていただきます。

イベントストーミングによるオブジェクトモデリングオブジェクト指向プログラミングの適用・開発プロセスの変遷・アーキテクチャの変革

speakerdeck.com

こちらもカンファレンスに続いてご無沙汰していたイベンストーミングや関連してCQRSについてのお話でした。

私の元々の理解が浅かった可能性も十分にありますが、お話の中でイベンストーミングで洗い出すものの中でポリシーについての話があり、私が結構前に実践した際には洗い出していなかったので、より認識の齟齬が無くなりそうでよいなと感じました。

イベントストーミングを実践するうえで最初は民主主義的な進め方は難しく、ファシリテーションスキルが必要ということで実践する際に備えて磨いておこうと思います。

また、イベントストーミングというと案件の最初などに関係者が一同に介して大規模でやっていくというイメージだったのですが、お話の中で数をこなしていくうちにメンバー間で壁打ち感覚で実施されている(と私が理解した)というお話があり、認識合わせの道具としても有用だなと改めて実感。

イベントストーミングで洗い出したイベントのイベントソーシングへの落とし込みについても大変興味深かったのですが、私の実務で導入するにはあまりにも一足飛びな感覚があり、まずはイベントに対して意識を向けたコミュニケーション文化の醸成からかなとぼんやり考えているところです。

DDDはなぜ難しいのか / 良いコードの定義と設計能力の壁

speakerdeck.com

DDDを実践するモチベーションの話からご自身の体験談、現在の取組のお話でした。

具体が伴っていたので、私が現状置かれている状況との照らし合わせがしやすかったです

今後同様の道を進むうえでにハマりそうな箇所について、あらかじめ看板を立てていただいているようなイメージでした。

  • 能力を上げるうえで何かしらのアウトプットは体系立てて整理する機会になるのでおすすめ
  • 質疑にあったおすすめの書籍

については今後取り組む指標になりましたし、DB駆動設計がうまくいくパターンについては

  • 設計うまくいかないかつ開発が進まないのが最悪のパターン。それよりは設計はうまくいかないけど開発進む方が良い

というお話があり、DDD導入に際してのトレードオフについても考えさせられました。

ビジネスロジックを「型」で表現するOOPのための関数型DDD

speakerdeck.com

型で縛りそもそも不整合を許さないという仕組みをより厳密に実践されているお話でした。

私が普段使用している言語がPHPであり、紹介されていた機能に類する機能について言語として担保されていないものもあるとは思うのですが、Sealedなどの制約でそもそも不整合なコードを書けないように縛るというのは合理的で良いと感じる取り組みでした。勉強になります。

現状私の現場ではコンストラクタで不整合弾いてその確認のためにテストコード書くというのをかなりやっていて、バリデーションやテストコードが膨らみがちです。

同様の制約をかける取り組みについて、世の中に需要はあると思うのでPHPで実践されている例がないか調べてみようと思います。

設計の知識と技能で駆動するソフトウェア開発

speakerdeck.com

分析設計パターンのお話についてはJJUGを楽しみにしようと思います。

経験則/習熟/競争については和ではなく積という話が面白く学びになりました。

ポートアンドアダプターについてのお話で、実際に交換するかどうかよりも交換できる状態になっていることが発展性において重要というお話や、 分析モデルと設計モデルは一致させるべき。その2つのギャップが負債。いきなり綺麗なものは生まれない。反復的に改善していく。というお話が改めてDDDの大事な要素を改めて思い出させてくれました。

アプリケーションサービスのクラス設計や連携モデルのプロトコル設計についての書籍についても(一部おすすめはしないけどということではありましたが)紹介されていました。

私は最近ポート&アダプターのアダプター側のコードに対してチームとしてどう秩序をもたせていくかということで、方針の確立に困ることが多いので、是非読んでみようと思います。

(コアドメインのロジック書くのが楽しく、その周辺はあんまり。。。というお話は激しく同意でした)

オブジェクト指向コードレビューの新しいアプローチ

speakerdeck.com

コードレビューの事例について詳しく紹介されているのを私がこれまであまり聞いたことがなかった&日々コードレビューの品質担保に本当に激しく困っていたので、目から鱗でした。

7つの指標を設け、あとから集計できるようPRのコメントにPrefixでどの項目に対する指摘かわかるようにしている取り組みについては明日からすぐ準備して真似します。

今回配布されてた冊子にもガイドラインについて記載されていましたので、バイブルとして大切にしようと思います。

コードレビューのAIについても工数削減のためぜひ取り組んでみたいですが、社内の仕組みの兼ね合いもありそうなので、プライベートなコードで素振りしてみたいと思います。

JJUG CCC 2019 Fallに行ってきました

11/23に行われたJJUG CCC 2019 Fallに参加しました。

聴講したセッションについて忘れない内に吐き出しておこうと思います。

Gradleを完全に理解した人が、何も分からなくなるための第一歩

@opengl-8080 さん

https://qiita.com/opengl-8080/items/c482998fa15ce738e2ba

Gradleについてタスクの作り方や複数の方法で実現できる関心事があったときにどのようなところに注目して選択するべきかなどのお話が聞けて、 普段SpringBootなアプリケーションを開発するときに何となくでGradleを触っていて深堀りしたことがなかったので、仕組みの話やご本人が初心者のときに迷ったポイントなどが聞けて勉強になりました。

ちょっと込み入ったことしようと思ったときはぜひ今回の発表と資料を参照しながら試してみようというモチベーションを頂きました。

Javaで学ぶオブジェクト指向プログラミングの基礎知識

増田亨(@masuda220)さん

www.slideshare.net

現場で役立つシステム設計の原則であえてカタカナ英語を使わないように記述した内容について、オブジェクト指向の用語を使ってわかりやすく説明されていました。

新人研修でわかったようなわからないような、とりあえずパターンだけを何となく覚えがちなオブジェクト指向について、しっかりこういうことだと腹に落とし込めるよう構成されていて、ぜひぜひ変な癖が付く前に新人の人とかにもおすすめしたい内容でした。

型は値の範囲と操作を制限するということについて初心者でもわかりやすいようにカプセル化と交えて説明されていて、内容を教わる側としても、知識を布教する側としてもどちらに視点でも参考になりました。 DDDという言葉は一言も登場してないのに繋がりも感じ、DDDの用語に対してアレルギー反応を示しそうな層にも優しい話の流れや例を紹介されていて勉強になりました。

開け!ドメイン駆動設計の扉

成瀬 允宣(@nrslib)さん

資料は諸般の事情により資料のWeb公開はしないみたいです

togetterでまとめてくださているのでそちらを読むだけでも雰囲気つかめるかもしれないです。

Evans本の問題領域の理解やユビキタス言語の発見、知識の蒸留から実装パターンまでの話をわかりやすい具体例を交えて説明されていました。

この例が非常にわかりやすくパクりたいレベルで、内容のわかりやすさももちろんすごいのですが、教える人としての力量も見せつけられました。 特に知識の蒸留のところの鉄鋼製造ドメインにおける炉の温度管理の話が実例として刺さる内容でした。

実装パターンとしての集約の話や値オブジェクトの話などもこういう風にするとこう嬉しいと、形ばかりがフォーカスされがちなところも心意気から説明されていて非常にわかりやすかったです。

増田さんのセッション→成瀬さんのセッションの内容で送る新人研修があったら初心者でも一気にステップ駆け上がれるなという印象を受けました。

長く続くサービスがモダンであり続けるには

角田拓己(@chan_kakuz)さん slides.com

改善活動の話で、息が長くなってきたサービスをどういい感じに維持していくかという視点で現在取り組まれている内容の紹介でした。 わかりみを感じつつ、gradle-versions-pluginなど知らなかった便利ツールを教えていただいたりと現場のお話を聞けて参考になりました。

一番ビックリしたのが、登壇者の方が新卒2年目の方で、2年目でこの内容もそうですし話し方も落ち着いててレベルが高く度肝を抜かれました。

AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション - 開発ツールやプロジェクト構成も含めて45分で丸わかり

株式会社カサレアル(@PR_CASAREAL)さん

www.slideshare.net

スポンサーセッションだからか宣伝色強めでしたがSpringBootなRest APIの作り方や3層アーキテクチャ、Angularの話などSPA + WebAPIという今ありがちなアプリケーションの作り方について基本から説明されていました。

誤解されがちな内容についてもきちんと否定されていたり、出来ること出来ないことを明確に説明されている印象でした。

JVM入門 -Javaプログラムが動く仕組み-

Abe Asami (きの子)(@aa7th)さん speakerdeck.com

JVMについて基礎的な仕組みからGCのタイミングまで裏で何が起こっているかを理解できるようになるための内容でした。 新人研修以来ご無沙汰になっていたGCの仕組みなどを復習しつつも更に深いところまで解説があり勉強になりました。

スタックトレースが何故そういう名前なのかというのが解説の中で理解出来、普段表面しか捉えずに利用している仕組みの裏側が知れてよかったです。

挿絵のイラストも可愛いかったです

DIコンテナ入門

うらがみ(@backpaper0)さん backpaper0.github.io

SpringなどでおなじみにDIコンテナについてどういうものなのかというのと、登録したComponentの利用の仕方など普段の業務で利用している技術について今日から使える内容が多く勉強になりました。

SpringでのAOPの実現の仕組みや注入についてもわかり易い言葉で説明されており、私も普段コンストラクタインジェクション推しで開発をおこなているので、共感できる内容も多く簡潔にまとまっているので他の人への伝える際の参考にもなりました。

終わりに

Springに引き続きFallもJJUG CCCに参加しました。

私も開発者としてやらせていただいていて、自分の知識を仕入れるという一方で、他の人に伝えるという機会も増えてきたのでそういった視点でも登壇者の皆様から多くのインプットを頂けて非常に勉強になりました。

知ったつもりになっているものを学びほぐすという意味でも収穫は多く、理解に厚みが増しました。

増田さんのセッションからの成瀬さんのセッションはオブジェクト指向からドメイン駆動設計に繋げる良い足がかりになると思い、私も伝播の際にもお二方の話した内容を意識しつつ本質を捉えた開発ができるよう伝えられればなと強く感じました。

貴重な学習の機会を提供してくださった、JJUG CCC 2019 Fallの実現に携わった方々、登壇者の方々、ありがとうございました。

AWS認定ソリューションアーキテクト-アソシエイトの試験勉強メモ

先日AWS認定ソリューションアーキテクト-アソシエイトを受験して合格したので、勉強の際に間違った部分のメモを忘れない内にダンプしておこうと思います。

以下メモ

グローバルインフラストラクチャとネットワーク

VPC

ルートテーブル

サブネット毎に1つ設定 1つのルートテーブルを複数のVPCで共有は可。1つのサブネットに複数のルートテーブルの適用は不可。 宛先アドレスとターゲットなるゲートウェイネクストホップ)を指定する。 VPCにはメインルートテーブルが有りサブネット作成時に指定しない場合のデフォルトのルートテーブルになる。

セキュリティグループとネットワークACL

セキュリティグループ

インスタンス単位の通信に利用
ステートフル (デフォルト拒否)

ネットワークACL

サブネット単位の通信に利用
ステートレス(デフォルト許可)

ゲートウェイ

インターネットゲートウェイ

各VPCに1つだけアタッチすることができる。
VPC内のリソースからインターネットへアクセスするためのゲートウェイ。インターネットゲートウェイをVPCにアタッチするとVPCからインターネットに出ることができる。

NATゲートウェイ

プライベートサブネットからインターネットへ接続するために用いる。AWSではマネージドなサービスとして提供されていてAZ内で冗長化されている。
NATゲートウェイを利用しない場合はNATインスタンスと呼ばれるEC2インスタンスを利用してインターネットにアクセスする。この場合は「送信元/送信先チェック」を無効化し、自身へのトラフィックを破棄する設定が必要になる。EC2インスタンスを利用するため単一障害点にならないよう冗長化の仕組みを検討する必要がある。

インターネットゲートウェイとNATゲートウェイ

パブリックサブネットにあるものはインターネットゲートウェイを通じてインターネットに出られる。
プライベートサブネットにあるものはインターネットゲートウェイへ直接接続できないので同じAZのパブリックサブネット内に配置したNATゲートウェイを通じてインターネットへ出る(前段に噛ますイメージ)。

仮想プライベートゲートウェイ

VPCがVPNやDirect Connectと接続するためのゲートウェイ

VPCエンドポイント

VPC内からインターネット上のAWSサービスに接続するための方法。
ネットワークレイヤーのゲートウェイ型とアプリケーションレイヤーのインタフェース型の2種類存在。

ゲートウェイ

ルーティングを利用。ルートテーブルに指定されたターゲットを追加することでS3やDynamoDBへインターネットを経由せずに接続できる。

インターフェース型

AWS PrivateLinkとも呼ばれ、AWSへのAPIコールに対してインターネットを接続せずに実現できる。

VPCピアリング

異なるVPC間をプライベート接続する機能。インターネットを経由しないでAWSのプライベートネットワーク内で直接通信できるようになる。異なるAWSアカウント間でも可能だがネットワークアドレスが一致or重複している場合は接続できない。

VPCフローログ

VPC内の通信の解析に利用。送信元/送信元アドレス、プロトコル番号、データ量と許可/拒否の区別が記録される。

ネットワーキングとコンテンツ配信

Route53

権威DNS

権威DNSはドメイン名とIPアドレスの変換情報を保持しているDNS ↔ キャッシュDNSは変換情報を保持していないDNS

ホストゾーンとレコード情報

ホストゾーン:レコード情報の管理単位。通常はドメイン名。
Zone Apex:最上位ドメインのこと
レコード情報:「www.example.comはIPアドレスが192.168.0.100である」のような変換情報。

レコードタイプ

Route53では各レコードに対してTTLを設定することができる Aレコード:ドメイン名からIPアドレスを取得 MXレコード:対象ドメイン宛のメール配送先ホスト名を定義 CNAMEレコード:ドメイン名から別のドメイン名を参照。ホストに関係なく登録できる。 ALIASレコード:各AWSプロダクト(ELB, CloudFront等)で利用するDNS名専用の、CNAMEレコード風の挙動を実現するレコード。ZoneApexの別名解決に用いる。

トラフィックルーティング

シンプルルーティング:設定されたレコードの情報に従ってルーティングする
フェイルオーバールーティング:ルーティング対象となるリソースへのヘルスチェックを行い、利用できるリソースへルーティングする
位置情報ルーティング:接続クライントの場所に基づいて地理的に近い場所へルーティングする
地理的近接性ルーティング:リソースの場所に基づいてルーティングする。リソースの移動の際に使用する。
レイテンシーベースルーティング:最もレイテンシーが低いリソースへルーティングする
複数値回答ルーティング:1つのレコードに異なるIPアドレスを複数登録しランダムに返却されたIPアドレスに接続。ヘルスチェックがNGになったIPアドレスは返却されないので正常に稼働しているサーバに対してのみアクセスを分散できる。
加重ルーティング:複数のリソースに対して加重度を設定し指定した比率に応じて処理を分散するようルーティングする

DNSフェイルオーバー

Route53が持つフォールトトレラントアーキテクチャ
フォールトトレラントアーキテクチャとはシステムに異常が発生した場合でも被害を最小限度に抑えるための仕組み。

コンピューティングサービス

EC2

EC2における性能の考え方

インスタンスタイプ

mとかpはインスタンスファミリー、数字は世代を表す。xlargeなどはインスタンスサイズを表す。
Dedicatedインスタンスはホストマシンを専有するタイプのインスタンス。

インスタンスメタデータ

インスタンスID
プライベートIPv4アドレス
パブリックIPv4アドレス
ローカルホスト名
公開鍵

AMI

EBS-Backedインスタンス or Instance Store-Backedインスタンスの2種類。EBS-Backedはデータを永続化でき、Instance Store-Backedは揮発性のためインスタンス停止時にデータが消える。

ELB

クロスゾーン負荷分散を有効にすると複数のAZに登録された全てのEC2インスタンスに対してリクエストを均等に分散する。

ELBの種類

Classic Load Balancer:L4/L7レイヤーで負荷分散を行う。
Application Load Balancer:L7レイヤーで負荷分散を行う。CLBよりも後に登場し機能も豊富。
Network Load Balancer:L4レイヤーで負荷分散を行う。HTTP(S)以外のプロトコル通信の負荷分散をしたいときに用いる。

Auto Scaling

EC2だけではなくELB, RDSに対しても設定できる。
最大インスタンス数などのスケールためのルールはAutoScalingGroupに記述する。

運用支援サービス

CloudWatch

メトリクス

標準メトリクスにある

CPUUtilization: CPU使用率
DiskReadOps: (指定期間における)インスタンスボリュームストアからの読み取り回数
DiskReadBytes: インスタンスボリュームから読み取られたバイト数
NetworkIn: すべてのネットワークインターフェースから受信されたバイト数

カスタムメトリクスで設定する必要がある

メモリ使用率
ディスク使用量等

等など

CloudWatch Logs

EC2などにCloudWatch Logs専用のエージェントをインストールする必要がある。
CloudTrailやVPCフローログ等様々なAWSのログを統合的に収集する。

CloudWatch Events

AWS上のリソースを監視しあるイベントをトリガーにアクションを実行する機能。例えばEC2インスタンスの状態を監視し変化があればLambdaやSNSを実行するなどができる。CloudWatchはメトリクスを監視していて、CloudWatch Eventsは状態を監視している。
スケジュールもイベントとして取り扱える。
GuardDutyと連携するときはGuardDutyの状態の変更をCloudWatch Eventsで監視する

CloudWatchアラーム

CloudWatchで監視している項目がある一定値になった場合にアラームとアクションを起動できる。

ストレージサービス

EBS

スナップショットを作成を開始する際は止めておく(デタッチしておく)。スナップショットを取り始めたらアタッチをしてもOK(完了を待たなくても良い)
AZをまたぐことは出来ない。

ボリュームタイプ

汎用SSD:デフォルトのSSD。安価。OSのルート領域などI/Oを要求されないデータ領域で利用
プロビジョンドIOPS SSD: 高パフォーマンスを実現。ミッションクリティカルなシーンで利用される。汎用SSDより高いパフォーマンスがほしい場合に利用
スループット最適化HDD:HDDタイプのストレージ。大容量を安価に利用したいとき。アクセス頻度が多いとき
Cold HDD:低コスト

EFS

スケーラブルな共有ストレージサービス。EC2やオンプレミスから利用できる。NFSの機能を有している。現状はLinuxのファイルシステムのみサポート

S3

ストレージクラス

スタンダード:頻繁にアクセスするデータの格納に適している。
標準低頻度アクセス:低頻度でアクセスされるものの、必要なときにアクセス可能なデータを格納するのに適している。
1ゾーン低頻度アクセス:RRS S3と呼ばれるもの。低頻度でアクセスされるものの、必要な時にアクセス可能なデータを格納するのに適している。1つのAZにしか格納されないため低コストだが、その分耐久性が低い。

オプション

デフォルトでリージョン内複製を有効になっている。バージョニングなどのオプションはユーザが任意で設定する。リージョン内複製をとっていても削除処理を行った場合は複製も消える(あくまで耐久性向上のための複製という見方?)。

バケットポリシー

削除の禁止を行うことで誤削除を防げる。

小技

ファイル名の先頭にランダムな文字列を付与するとインデックスが分散されてパフォーマンスの向上が期待できる。

Glacier

迅速(Expedited):1〜5分でアーカイブデータの取り出しが可能
標準(Standard):3〜5時間でアーカイブデータの取り出しが可能

大容量(Bulk):5〜12時間でアーカイブデータの取り出しが可能

データベースサービス

RDS

マルチAZ化可能。
リードレプリカにより読み取り性能の向上が可能(≠冗長化)
AutoScalingでリードレプリカを作ることも可能
SSL接続のためのオプションは--ssl-ca

Redshift

列指向データベース。
ペタバイト規模のデータを標準SQLで分析可能。
リーダーノードに対しコンピュータノードが1対Nで構成される。耐障害性を高めるにはノードを増やす。マルチAZは対応していない。

DynamoDB

DynamoDB Accelerator

DynamoDB用のインメモリキャッシュ

ElastiCache セッションを格納するのに良い。

セキュリティとアイデンティティ

KMS

AWS上で鍵管理を提供するマネージドサービス。
暗号化鍵の作成や有効/無効の管理、ローテーション、削除ができる

CloudHSM

AWSのデータセンター内に配置されるユーザ占有のハードウェアアプライアンス。

プロビジョニングサービス

Elastic Beanstalk

定番構成の自動構築
対応しているアプリケーション:Java, .NET, PHP, Node, js, Python, Ruby, Go, Docker
対応しているデプロイサーバ:Apache HTTP Server, Nginx, Passenger, Microsoft Internet Information Service(IIS) 等

AWS OpsWorks

OSより上のレイヤーの自動構築をサポート
ChefやPupperを利用できる。

AWSにおけるアーキテクチャ設計

AWS Well-Architectedフレームワーク

回復性の高いアーキテクチャを設計する
パフォーマンスに優れたアーキテクチャを定義する
セキュアなアプリケーション及びアーキテクチャを規定する
コスト最適化アーキテクチャを設計する
オペレーショナルエクセレンスを備えたアーキテクチャを定義する

AWS Trusted Advisor

コスト最適化
セキュリティ
耐障害性
パフォーマンス
サービスの制限

ストリーム処理

Kinesis Data Streams

ストリーミングデータをほぼリアルタイムで保存、EMRやLambdaなどの後続処理に流せる。
シャード単位でデータを分割して並行処理が可能。

Kinesis Data Firehose

ストリームデータをAWSの各サービスに配信、保存できる。

Kinesis Data Analytics

ストリーミングデータに対してSQLクエリを実行しリアルタイム分析を行う。

サービスの種類

グローバルサービス:S3, Route53
リージョンサービス:VPC
AZサービス:EC2, EBS, ELB, RDS

BPStudy#145〜進化する要件定義(RDRA meets DDD)に行ってきました(第2部)

DDDとRDRAを組み合わせて使うには

speakerdeck.com

かとじゅん様(@j5ik2o)

感想

DDDを実践しようと思ったらRDRAの外側のレイヤーに注目する考え方が有用で、業務を理解しないことには適切なドメインモデルが導かれないというお話でした。

DDDとRDRAを組み合わせていく上で現場で実践していることをDDDとRDRAの用語の関係ベースで説明されていて、自分の中で対応関係が明確になりました。

DDDの文脈で重要視されている、コアドメインで仕事しているか否かという部分についても境界づけられたコンテキストとシステム価値を対応させることで判断の助けになるなど実務で使える知識を得ることができ勉強になりました。

かとじゅん様、ありがとうございましたm( )m

以下メモ

要求の分析したことを分析したまま実装に落とし込むというDDDの考え方(単一モデル)の元でRDRAを生かしたという観点での発表。

ドメインモデルとは

  • 実装を見れば分析の結果がわかる、ビジネスルールがわかるという状態を目指す。
  • 例えば、請求クラスは支払い期日に基づいているのでインスタンスを内包する可能性が高い。

いきなりドメインモデルを作れるか

  • 初見だとほぼ無理であるためドメインモデルが導かれる元となる外部環境に注目する。
  • システム価値を整理することでコアドメインで仕事しているか否かがわかる。
  • システム外部環境を整理することでドメインモデルの輪郭が特定できる。その業務が未経験であればあるほど。

ユースケースモデル

  • 今回の発表では文章だがRDRAだと図で表す。人間とシステムの対話のシナリオを示していて、(E)はEntity、(C)はコントロール(動詞の部分)、(B)はバウンダリーを表している。
  • 用語の候補は操作マニュアル等が参考になる。

システム境界とBCEステレオタイプ

名詞

動詞

  • コントロールはI/Oも含まれるが、ドメイン知識ではないので注目するのはそれ以外の動詞。

イベントモデルから分析する

  • イベントは他のシステムと連携することがある。
  • 業務上で起きるイベントに注目してモデリングする(EventStorming)

ユースケースいきなりかけるか問題

→ システム外部環境を知るべき

  • 利用シーンを用いて、どのような場面で使われるかや利害関係者を紐づける。

→ 利用シーンや利害関係者がいない機能があったらそれはいらない機能。

ユビキタス言語の候補が整理していくと出てくる。

ユビキタス言語はこのような分析を行って初めてできるものであり、いきなり降って湧いてくるものではない。

概念モデル

声に出してモデリングのが良い。

→ 自分で言語化するときに違和感を覚えたものはモデリングがおかしい。相手に伝わる表現が大事。

→ どうしても声に出すだけでは伝えるのが難しいものはホワイトボードにインスタントに絵を描いて説明する。ただしホワイトボードに書かないと伝えられないものはシンプルなモデルではないかも。

→ 日常的な会話にモデルが出てこないとおかしい。

コアドメインで仕事しているか

  • 汎用サブドメインとは他の代替技術があれば置き換えられるもの。
  • 支援サブドメインとはコアほど重要じゃないけど必要不可欠なもの。
  • コアドメインとはビジネスの核心であり、システム価値を整理することでコアドメインで仕事しているか否かがわかる。
  • インセプションデッキやPRDとシステム価値は同様の事柄が記述されるはず。

コンテキストモデル

  • 利害関係者や外部システムとの関係を洗い出す。
  • 利害関係者が満足する要件は何か→その要件を満たすドメインモデルって何という感じでRDRAとDDDは直に繋がっている

要求モデル

  • ドメインモデル → 機能 → 要件 → アクターの状態で辿れないといけない。
  • RDRAではモデル図を書くということはその場に合意できる人がいることが大事。要件自体もモデリングする。

BPStudy#145〜進化する要件定義(RDRA meets DDD)に行ってきました(第1部)

RDRA2.0とは

資料

神崎善司様(@zenzengood)

感想

神崎様のRDRA2.0のお話はRDRA2.0の紹介と体験ワークショップに参加させていただいた際に伺ったことがあったのですが、数ヶ月経ち実際に業務で使ていくうちに浮かんだ疑問が今回の発表で解消されました。

業務で使っていている中で浮かんだ疑問点とそれに対する解決策は以下です。

  • 既存の案件に適用した際に依存の外側から順番に書いていこうとすると、既に開発してきていて合意が取れている部分についても作図していく必要があり今フォーカスしたい部分に注力できない。
  • ユースケースレベルの粒度で洗い出せれば良いところを情報/状態モデルまで作図する必要があると感じてしまう(これに関してはその時点で必要ないものについては書かなければよかったのですが、熟練しない内には型を破りたくないという私の趣向もあります)。

→ 外側のレイヤーから説明しているが必ずしもその説明した順番で記述する必要もなく、あくまでRDRAでは合意というのを大切にしているので合意が取れているのであれば必要のない図をわざわざ書く必要もなさそう

  • 概算見積もりにRDRAを適用していくイメージがつかめていなかった。

→ 重要なアクターに紐づくユースケースへと落とし込み、そのユースケースの数で概算見積もりを出す。より精度の高い見積もりが必要な場合はユースケース毎に画面等のブレークダウンした図を作成していき算出する。

また、前回の発表では一度に理解しきれなかった部分についても改めて聞くことで学び直しになり勉強になりました。

神崎様、ありがとうございましたm( )m

以下メモ

RDRAで解決したい世界

  • コンサルで苦労した要件定義をスムーズに進めたいのがモチベーション
  • 従来の要件定義では要件を決める人とその要件をまとめる人が分かれていて、要件を決める人が出したAsIsの資料をもとに要件をまとめ、レビュアーにレビューしてもらうで要件の決定がなされる。また、従来の要件定義にあるガントチャートについてはガントチャートを書く→計画どおりに行かないので人数を増やしてスケールさせる→するといきなり並行作業が始まって全体をわかっている人がいなくなりがちという問題がある。
  • アジャイル開発においても、最初は重なる部分が少ないがスムーズに開発が進んでいるように見えるが、結合が始まる中盤以降で手戻りが多くなってきて新規開発にリソースを割けなくなりバックログが減らなくなるという問題がある。
  • 保守開発においても品質の悪化が見られる。それは要求を出す人と実装する人が分かれているので影響度分析ができなく、また頼りになるドキュメントがなく頭の中の記憶が頼りになるため。システムの可視化を管理者がしたくても最新の状態をドキュメントとして維持できない。

上記の問題を解決することがRDRAのモチベーション

システム化に関わる要素

  • システムからシステム価値の方向へ依存している。 例) 画面のいるいらないはどうシステムを使おうと思っているのかがわからないと検討のしようがない

  • RDRAって何かを端的に理解するにはRDRAレイヤーのスライド一枚を参照する。

アイコンの関係

  • 文章ではなくアイコン間の線のつながりでWhyを表す。
  • システムの外部環境には業務フローと利用シーン、ビジネスユースケースが含まれる。業務フローで表現できない場合は利用シーンとして箇条書きで表す。商品のカテゴリ、取引先のカテゴリがあってある取引先に対するあるカテゴリの商品は1%割引のような組み合わせ間の条件をビジネスルールとして表で表す。
  • システム境界におけるイベントはファイルやり取りでもAPIでもOK。 なぜなら RDRAではHowを取り扱わない。WhatとWhyだけ 。 なぜHowを取り扱わないかというとHowを扱い出すと手が止まるから。

→ RDRAではスピード感のある合意を大切にしている

  • 情報モデルはビジネスを駆動する用語。
  • 状態モデルも情報モデル同様ビジネスを駆動する用語ではあるが、なんらかの動作を伴った結果。

ダイアグラム

  • システムコンテキスト→要求モデル→ビジネスコンテキスト→ビジネスユースケース→業務フロー利用シーンバリエーション→情報状態モデル→UC複合図 の順番で説明しているが、 必ずしもこの順番ではなく必要もなく、必要のないものは書かない
  • 一覧はRDRAのモデルを使えば後から生成できるので最初から一覧は作らない。合意の前に一覧にするということは色々先に決めてしまっていることが多いので注意。
  • 文章からではなくモデルのつながりで表現していく(文章と同じような表現力がある)
  • みんながドキュメント書き始めると関係がわけがわからなくなるのでみんなで図を書く。RDRAでは基本的に文章は書かない。最初から文章で書くと後から時間がなくて直さなくなり、いらない機能を作ることになりがち。
  • プロジェクトの特性に応じて使い分ける。 全部のプロジェクトで全部の図を書くわけではないアジャイル開発等ではある程度図を書いたら開発に入ったほうが良い。
  • システムの今を見られるので、保守開発とかで担当者ごとにバラバラのことを言っているのを防ぐことができる。
  • ブレークダウンしていく際は、ビジネスコンテキストの業務→ビジネスユースケース→業務フローという順番。これらをつくるとシステムの大体のスコープがわかるので概算見積もりを出せる。ただこれだけだと精度がわるいのでユースケースごとに画面とかを考えていくと精度を上げられる。

ダイアグラムの関係

  • システムコンテキストについては要件定義メンバー全員で認識合わせ。ただこれに時間かけてもしょうがないので30分程度でぱぱっと作る。
  • 要求モデルについては重要なステークホルダーと紐付いた要求リストを洗い出す。重要じゃないステークホルダーに紐づく要求は一旦切り捨てる(本当に重要ならまた話に上がってくるはず)
  • 1個1個の図を丁寧に作るのではなく、作れなかったらさっさと次に行く。現時点でわかることをできるだけ図に起こしていき、わからないことは一旦おいて次に行くイメージ。ヒアリングした要望がどこのモデルに属するのかを識別して書いていく。
  • 状態を変えるのはユースケースなので状態はユースケースにつなぐ
  • システムコンテキストは最初から書けない。色々な図を書いていく上で見えてくる。
  • 要求モデルもきちんとやろうするとすごい時間かかる。重要な要求を10個くらい整理していつでも見れるようにする。一覧100個もあるようなリストを作るとかやりがちだけど全部拾おうとしたらダメ。重要なもののみ救う。
  • 要求モデルは必ず作るわけではなくエクセルの一覧とかあるならそれにアクターくっつけて大事なもののみ拾う。
  • ビジネスコンテキストはリッチピクチャーよりちょっと引いて俯瞰してみたもの
  • システムの肥大化はビジネスユースケースでコントロールできる。何でもってビジネスユースケースを分けるかが大事。どのようなものを使っていてビジネスを回していて、 ビジネスユースケースが異なるということは何の差があるのかがわかるものを紐付ける ←これがビジネス要素
  • ユースケースに関わる画面や状態等を集めてきて結び付けているのがUC複合図
  • 状態モデルのユースケースこそ整合性の観点で重要。照会だけするユースケースとかは状態モデルに出てこなく、整合性という観点のみでいえばそんなに大事じゃない。ユースケース、情報、状態は繋がっている。ただ毎回やるのは大変なので毎回やるわけではない。 本当に精度が欲しいときだけあってユースケースさえ出れば良い時はやらない
  • 入出力、状態、バリエーションがビジネスでよく変わる。データ変えろってことはあんまりない。そこが変わるとどのユースケースにどういう影響が出るかを追跡できる。

RDRAが目指すもの

  • アイコン間のつながりが妥当かどうかで整合性が取れているか否かを判断する。

例)魚屋で寿司屋くれっていったらん?ってなるけどまぁなくもなさそう。ただ自転車くれって言ったら明らかに変なのでその温度感で業務に対しておかしいかどうかをつながりから判断する。

網羅性はアクターからはいってアクターに出ていくかどうかをみる。

  • 整合性も網羅性もつながりで説明できることで担保する。
  • 既存システムの可視化という観点では、1つの図を見て認識を合わせる。ドキュメントかっちり作るということではなくてある程度の粒度でもってコミュニケーションできる図をつくりましょうという話

ドメインモデルとの関係

  • RDRA的にはDDDと繋げてもつなげなくでもどっちでも良い。Howを取り扱わないので。
  • RDRAは外側から枠組み固めていくイメージ。DDDは内側から育てていくイメージ。タイムボックスで両方回していくのが良いのでは。

Puppeteer + TypeScriptでUIのテストを行う

設計の勉強会だったりbuildersconだったりで刺激的な話たくさん聞いたりできたりして、書きたいことはたくさんありますが結構文量がいる話で、普段の業務の忙しさにかまけて何もアウトプットしないということになりがちなので普段の業務で使っているようなライトなものでもアウトプットしていこうと思います。

Puppeteer + TypeScriptのテンプレート

画面があるアプリケーションを業務で作っていると粒度の大小はあれ手動や自動化などでUIのテストを行っていると思います。

そんな後者を便利に行えるツールでPuppeteerがありますが、私はチーム開発では型が欠かせないと思っているのでTypeScriptで書きたくなります。

そんなPuppetter+TypeScriptですがプロジェクトごとに都度用意するのはめんどくさいのである程度まで下処理してあるtemplate的なものをよく自分のGithubにあげています。

それがこちらです。

yarnを叩いたあとにyarn testを実行すればsampleのテストが1つ走ることの確認ができますので、確認ができたらあとはxxx.test.tsをお好みで作っていただいてガツガツ書いていくだけです。

どこかで誰かの役に立てば幸いです

値オブジェクトの悩みポイント:どこまで型を用意するか / nullableな値をどう取り扱うか

ライト版はこちら

speakerdeck.com

早速ですがドメイン駆動設計に関係するいくつかの書籍でも紹介されている、「人名」を考えます。

「名前」と「名字」は確実に存在し、「ミドルネーム」無い場合もあるという想定です。

public class PersonName {
    private <Type> firstName;
    private <Type> lastName;
    private <Type> middleName;

   ...

   @Override 
   public String toString() {
      return String.format("%s %s %s", 
        firstName.toString(), 
        middleName.toString(), 
        lastName.toString());
   }

}

このときそれぞれの型はどのようにするのが良いでしょうか。

Stringを採用

public class PersonName {
    private String firstName;
    private String lastName;
    private String middleName;
   ...
}

最も簡単な方法です。

「人名」という値オブジェクトを用意し、「名前」や「名字」はその構成要素でしかないという考え方です。

「名前」や「名字」単体でのでの利用がない場合はこのような設計がシンプルで良いかもしれないです。

メリット

  • 型が増えなくて済む
  • 取り回しが効く
  • 「人名」の生成時に渡す引数が簡単

デメリット

  • 「名前」、「名字」、「ミドルネーム」それぞれの個別の振る舞いは表現できない。
  • 「人名」の生成時に「名前」と「名字」が存在すること、「ミドルネーム」がnullではないことを担保する必要がある。
  • 型で「ミドルネーム」が空の可能性があることを表現できていない。

String + NonEmptyStringを採用

public class PersonName {
    private NonEmptyString firstName;
    private NonEmptyString lastName;
    private String middleName;
    ...
}

Stringのみと同様、「人名」という値オブジェクトを用意し「名前」と「名字」についてはその構成要素でしかないという考え方です。

値が空に可能性を明確に排除しているNonEmptyStringという型を用意することで通常のStringで値が空の可能性があることを示唆しています。

メリット

  • String同様型が増えなくて済む(NonEmptyString1個だけ)
  • 取り回しが効く

デメリット

  • 「名前」、「名字」、「ミドルネーム」それぞれの個別の振る舞いは表現できない。
  • 「ミドルネーム」がnullではないことを担保する必要がある。
  • 「人名」生成時に渡す引数がStringのみと比べて複雑になる。

FirstName / LastName / MiddleNameを採用

public class FirstName {
    private static final int MIN_LENGTH = 1;
    private static final int MAX_LENGTH = 50;

    private String value;

    // コンストラクタや生成メソッドで検証するか利用側で検証してから渡すかはまた別の悩みポイント…
    ...

    @Override 
    public String toString() {
        return value;
   }
}
public class MiddleName {
    private static final int MAX_LENGTH = 100;

    private String value;

    // コンストラクタや生成メソッドで検証するか利用側で検証してから渡すかはまた別の悩みポイント…
    ...

    public boolean isSpecified() {
        // valueが空文字での生成は許してもnullでの生成は許さない必要あり
        return !value.isEmpty();
    }

    @Override 
    public String toString() {
        return value;
   }
}
public class PersonName {
    private FirstName firstName;
    private LastName lastName;
    private MiddleName middleName;
    ...
}

「名前」、「名字」、「ミドルネーム」を表す値オブジェクトをそれぞれ用意します。

メリット

  • 言葉と1対1で対応する
  • 個別の細かな性質や振る舞いもコードで表現することができる。
  • 型が言葉そのもので表されているので意図が明確。

デメリット

  • 型がユビキタス言語の数だけ増え、取り回しが効かない。
  • 似たような内容の型が増える

どれを採用するのが良さそうか

その業務でどう取り扱いかによると言ってしまえばそれまでなのですが、私の場合は「名字」「名前」でそれぞれ個別の性質や振る舞いがあるか否かを考えて、 「命名された文字列を表す」より更にならではの振る舞いがありそうな場合は、FirstName / LastName / MiddleNameを採用し、そうでない場合はただの構成要素なのでStringを採用します。

今回のケースでは「ミドルネーム」という概念が登場した時点で「指定がないことがある」というならではの振る舞いがあることは想像できるため、Stringのみのパターンの採用は見送ります。

String + NonEmptyStringとMiddleNameのどちらを採用するのかは悩みポイントですが、「指定がないこともある」という性質も踏まえて「ミドルネーム」という概念だと考え、MiddleName型を採用するのが一番素直に思えます。

「名字」「名前」についてはString、MiddleNameだけを値オブジェクトとして表現するハイブリッドなパターンも考えられますが、振る舞いを表現する場所が構成要素毎にまちまちなのが気になるため採用を見送ります。

Option VS. 値オブジェクト単体

JavaのOptionalなどでnullである可能性を表現できる型を用いるか、値オブジェクト単体で空である可能性も表現するかも悩みポイントです。

今回のケースでは「指定がないこともある」という性質自体が「ミドルネーム」という概念であるという考え方で、私の場合はMiddleNameを採用しOptionalなどの形は見送ります。

また、指定されていないことの表現は意図していないミスを防ぐため極力nullを避け、文字列ならば空文字で表現したい気持ちがあり値オブジェクト単体での表現を採用します。

終わり

今回検討した内容は正解がなくケースバイケースで様々な答えが考えられると思います。

様々な意見がある中で、どうしてそのようにしたかという考え方についてフォーカスして色々な方の話を伺いたいです。