「DDD Alliance! ドメイン駆動設計のためのオブジェクト指向入門」に参加してきた #DDDAlliance
2015年1月21日に開催された、「DDD Alliance! ドメイン駆動設計のためのオブジェクト指向入門」に参加してきました。
以下から現地で書いたメモ
ドメインモデルとは
ドメインモデル = 関心事を集めたもの。サブセットと呼んでもいい
ドメイン駆動設計
ドメインを分析する人がコードを書く コードを書く人がドメインを分析する 毎日分析し、毎日コードを書く
コードを書くためにはクラスを見つけなければいけない 問題領域を分析することでクラスが見つかる 分析者 = 実装者 とならなければならない
モデルを見つけることとクラスを見つけることは一緒。人を別にしてはいけない。
ソフトウェアを立ち上げる時はフェーズと人を分けるけど、 保守フェーズでは分析と実装者が一緒。立ち上げ時もそれをやればいい。
ドキュメントを書いてからコードを書くという方法は大概無駄になる。
ドメインを学び学んだことをコードで表現することが大前提
ドメイン層
ドメイン層はどこにも依存しない(プレゼン、アプリケーション、データベース) Springで実装
ドメイン層のオブジェクト ドメインにGetter/Setterは使わない 業務の関心事の表現 知りたいこと 誰が、いつ、なぜ。。。 業務ルール 制約、閾値、手順。。。 業務ルールが破られた時の業務ルール
業務サービスの実行役 判断の結果 計算の結果 加工の結果 (基本データ型は返さない)
独自の型を作ることがドメイン指向設計
オブジェクト指向のメリット: コードの整理
クラス単位に関連するコードを整理する どこに何が書いてあるか特定しやすくなる 変更が飛び火しない - データと機能を分けると飛び火しやすい 変更した箇所のテストがOKなら全体もOK
アンチパターン:変更コストが高くなる設計
ふるまいを持たない、いわゆるデータクラス
データクラスがレイヤーを跨いで使われている
どこで使われているか特定しにくくなる
変更コストが下がる設計
役に立つクラスを作る(判断・加工・計算ロジックを持たせる) クライアントは使うだけ
主要な関心事をアグリゲートに組む
オブジェクト指向:アーキテクチャ
構造
オブジェクトの集合体
強く関連する部品は集約する
アグリゲート同士は分散性を高め必要最小限につなげる
「変更」を前提にしたネットワーク構造
メタファ:LANアグリゲートとインターネット(全体)
工法
「変更」を前提にする
インクリメンタルに開発
少しずつ成長する全体
毎日変化させていく
オブジェクトの設計
独自の型を設計
オブジェクトのコラボレーションを設計
実現手段の隠蔽
独自の型を設計する
ドメイン層は独自の型だらけにする
独自の方=利用者の関心事
基本データ型=コンピュータの関心事
オブジェクトのコラボレーションの設計
契約による設計、責任駆動設計、擬人化。。。
結局は「オブジェクト」と「オブジェクト」が協力して設計することが大事
コラボレーションの設計原則
オブジェクト同士の契約(顧客と供給者の関係)を意識する
相手のことを深く知りすぎてはいけない
書籍:契約による設計
「契約による設計」
契約ってなんだ?技術者にはいいメタファじゃないよね
契約はビジネスルールの関心事。業務ルールの基本。
業務知識を学べば業務ロジックも契約による設計も学べて美味しい
オブジェクト指向:実現手段の隠蔽
業務の関心事の表現手段として「不適切」
int string LocalDate => 値オブジェクトで包む
for while List => ファーストコレクションで包む
列挙型でswitchを減らす
事例の研究
「転職支援サービス」を例に
転職アドバイザ
求職者
求人
応募
スカウト
職務依頼
ドメイン層の隔離
初級
中級
ドメインロジックを(プレゼン層、アプリケーション層などから)ドメイン層に移動する
浅いリファクタリング
上級
知識豊富になったドメイン層の見通しを良くする
深いリファクタリング
主要な関心事(コア)の隠蔽
主要な関心事(コア)の抽象化
各層の実装
プレゼンテーション層
標準的なSplingの機能を使う
サービスをインジェクションする
サービス層
渡されたIDに対してデータをリポジトリから取得する
データソース層
SQL Mapperのインジェクション
ドメインの型を返す
メトリクス
ざっくり20ヶ月、100人月くらい
アグリゲートに対して10くらいのドメイン(平均なのであくまでイメージ)
ドメイン層のクラスの行数はだいたい100行くらいで収まっている
30行〜60行がほとんど
クラス数が1000~2000あっても、関心事が集約されているのでたいして困らない
ドメインオブジェクト「善い部品」
ドメイン駆動設計のEntityパターン:参照オブジェクト
Entityと呼ぶのではなく参照オブジェクトと呼んだ方がいい
主要な関心事への参照点
顧客との会話の語彙の起点となる
JPAの@Entity
ただのデータの入れ物クラス
テーブルと対応する
ドメイン駆動のEntityとは無関係(むしろ逆に位置する)
値オブジェクト
業務の関心事と基本語彙(日付、期間、数量、金額、単位...)
目的に特化して制約をかける
暗黙の業務ルールをコードで表現する
コードを読んで業務ルールがわかるようにする
ロジックを集約する
コードの重複がなくなり変更が楽になる
値オブジェクトの実装パターン
完全コンストラクタ
不変なオブジェクト
何もしないgetterはNG
例えば、求人者の転職回数というのは今後関心事となることが予想される。そういったものを値オブジェクト化するのは有効。
値オブジェクトの効果
コードにドメインの言葉が増える => コードが仕様を語れる
一覧オブジェクト(ファースクラストコレクション)
ListやSetをラップ
コレクションの操作はコードがごちゃごちゃしやすく、変更の副作用が多い
クラスとして独立させ、そのクラスに閉じ込める
一覧オブジェクト vs SQL問い合わせ
SQLの抽出条件を単純にし、微妙な抽出を一覧オブジェクトにやらせる選択肢もある
どちらのやり方が関心事をうまく表せられるか
メモリとトレードオフ
区分オブジェクト
場合ごとのルールを理解し表現する道具
列挙を有効活用しifやswitchを削減する(ポリモフィズム)
区分オブジェクトの効果
関心事の明示的なコード表現
複雑なif文の削除
どこに何があるかわかりやすくなる
区分の追加や削除時の変更の副作用が少ない
How より What でコードを記述する
業務の関心事を明示的に表現する
より業務に寄せたメソッド名にする
深い洞察に向かうリファクタリング
お客さんの要望からやりたいこと、関心事を洞察し、コードに反映させるようにリファクタリングをしていく
関心事をより強調されるようにドメインオブジェクトを捻出していく
オブジェクト指向設計の学び方
本やスライドで用語を学ぶ
実際にコードを書く
元の本やスライドを読みなおす
変更作業が学びの絶好のチャンス
既存コードを変更しながらコードを読んだ範囲、変更箇所の数、テストの範囲を意識
オブジェクト指向設計に書き換えてから変更してみる
変更の際にリファクタリング
既存のコードの設計と比較して成功を実感する
ドメイン駆動設計とは
ドメインを学び、学んだことをコードで表現すること
QA
Q: リポジトリでトランザクションやロックするの難しくない?
A: 最近はトランザクションなしでの開発にチャレンジしている(現場はトランザクション使う)
Q: リポジトリから特定の値オブジェクトだけを取るのはあり?
A: 業務として必要であるのであれば全然あり。(ただし業務として成立している場合)
Q: コンストラクタは隠した方が良いか?
A: 隠したほうが良い。ファクトリメソッドで生成する考え方は推奨。
Q: DDDによって開発スピードが落ちないか?
A: ビジネスががらっと変わることはなく、既存のサービスをどんどん成長させていくケースがほとんどで、
ビジネスと開発に大きなスピードのギャップは生まれない。
開発スピードがでないのであれば、それを判断材料にオブジェクト指向を習得していくべき。
Q: ドメインエキスパートが不在、もしくはまだビジネス未成熟の場合どうすれば?
A: ドメインエキスパートなんてものは存在しない!ビジネスの全てを知っている人はいないので、技術者が積極的にキャッチしにいくべき。ドメインの知識をためていく。
2015年を振り返る
2015年も最後の日になってしまったので今年を振り返ってみようと思います。
Kawasaki.rbとの出会い
1月に参加した、神奈川Ruby会議の中でRubyの地方コミュニティとして紹介されていた、Kawasaki.rbに通い始めました。
Kawasaki.rbは文字通りれっきとしたRubyのコミュニティですが、土地柄からかWeb系でない人の参加も多く、Ruby以外の言語(Python,Julia,Go,Scala,etc...)に精通している人も多数おり、とてもバラエティに富んだコミュニティで、毎回参加しては刺激を受けることができました。そういえばDoorKeeperを遡ってみたら僕は今年の1月から12月まで全て参加している皆勤賞者でした。誰も言ってくれないので自分で言います。
Kawasaki.rbでは毎回誰かがLTをする時間が設けられており、とくにスライドがなくてもブログ記事などで軽く喋るくらいの空気感で良いので、自分も何度か発表させてもらいました。そういう意味ではここに来て自分のLT力が心なしか向上したような気がします。*1
また、Kawasaki.rbには公式ブログがありますが、#23から記事を寄稿するという形で微力ながらコミュニティに貢献させていただいています。
転職した
9月1日をもって新しい会社に移籍しました(3年ぶり2回目)
前の職はいわゆる受託系の会社で、Webをまともに開発したことの無い状態からRailsを触ったり、iOSアプリ開発、node.jsとMongoDBでスマホ向けゲームアプリのサーバサイドを開発したりと様々な仕事をやらせていただきました。
新しい職はスタートアップで、今は主にScalaを使って自社サービスを作っています。
これを作って欲しい!と最初から言われる受託系から、サービスを自ら考え物にしていきスピード感も違うスタートアップへの転職で、最初は発想の転換にとまどっていましたが最近ようやく慣れてきた気がします。
なお転職に興味ある方はこちらのエントリーもどうぞ
初めてのRubyKaigi
Rubyistを名乗っているくせにRubyKaigiに参加したことはなく、今年始めて参加してきました。
Rubyの魅力はその言語だけでなく、周りをとりまくコミュニティによって強く支えられていると聞いていましたが、RubyKaigiに参加することでそれが実感できたかと思います。みんな本当にRubyが好きなのだなと。
参考: MINASWAN - Wikipedia, the free encyclopedia
なお来年は早速ScalaMatsuriもあるので今から楽しみですね:)
横浜道場スプリント! そして...
2年以上通っていたアジャイルサムライ横浜道場ですが、実際にアジャイルのプラクティスを実践しながら開発をするという「横浜道場スプリント!」に1年通して参加していました。
Webの開発を一切やったことがないメンバー*2を交えながらなんとか動くアプリを実装し、12月の横浜道場忘年会で無事発表することができました。
そんな横浜道場ですが、悲しいことに今年をもって休止となりました。
アジャイルサムライ横浜道場は僕が参加した最初の勉強会で、よりアジャイルを深く知ること、アジャイルのコミュニティの広さを教えてくれましたし、何より現場を変えたいと強く思う人達と多く知り合えた素敵な場でした。心より感謝致します。
まとめ
今年成し遂げたことなんてあっただろうかと思いながら書き始めてみたら、様々なコミュニティにお世話になった、という形になりました。
とくに来年の豊富などを思いついているわけではありませんが、エンジニアとしてより一層成長するためにプライベートを有意義に使えればいいな、と思うしだいです。
技術勉強会『開発エンジニアが知っておくべきwebサービスの負荷対策』[TECH VALLEY#6] #tv6
2015年11月18日に開催された技術勉強会『開発エンジニアが知っておくべきwebサービスの負荷対策』に参加してきました。
進化の読めないシステムの負荷対策 @Sansan社
サービスの目的
運用しているサービス
- Sansan 3000社利用
- Eight ユーザ数100万人
Eightの裏側にある名刺データ変換の負荷対策について
- 名刺のデータ化: 30万枚/日
- 400万タスク/日
- 累計名刺データ数1億万枚以上
- 600万PV/日
- 1億6000万PV/月
- 常に1600人が同時に利用
- ひとつのタスクは5秒で終わる
インフラ
- Rails
- S3
- RDS
- Redis
- Redshift
- CloudSearch
20 Servers/3RDS & 15 databases
システム課題
依頼枚数が増えていく
増えるタスク 各種処理のスケール
UI応答性能の維持、向上
スケーラビリティの確保
DBシャーディング 失敗 データはかなりの両たまることはわかっていた 蓄積したデータは特定の項目
シャーディングうまくいくはず → いかなかった
リリース後
1年でスロークエリ出始める
シャーディングいやだ
- 項目で検索、集計したい
- 1億のテーブルスキーマ変更辛い
データ化中のデータ
- 頻繁に参照、更新したい
データ化完了のデータ
- 検索、集計したい
ただしいストレージ選択
- データ化RDS
- 検索にはCloudSearch
- 集計はRedshift
十分な情報集まらないなら作りこみしない
データ状態の変化と使われ方
RDBで億行は十分捌ける
microservicesして良かった
データ化は複数の工程
工程をワークフロー化
SimpleWorkflow
利点
- ソフトウェアを小さくできる
- 拡張、保守
- DBを意味のある物理的に分割
スケーラビリティの確保でだいじなこと
- とり得る手法は複数。何を選択するか
- 大事なことは複雑にしないこと
UI性能維持、向上
やったこと: モニタリング、改善
普段やってること
- スロークエリ監視の改善
- サービス魚頭性能のモニタリング
クエリの把握
ORMの発行クエリなんだっけ
クエリ正しいか?
- N + 1
- インデックス
重たい複雑なクエリを分割
- ID取得とデータ取得にわけるとか
ネクストキーロック
- 更新対象行のみがロックされるわけではない
複合インデックスの順番
インデックス効いているかチェック
スロークエリ
- 0.5sで監視
- 1日で見た時の総処理時間が大きい物を優先
サービス応答性能のモニタリング
New Relic
- 応答性能の異常検知
- 異常時の詳細情報
- 傾向の把握
これから
- 無駄な通信の排除したい
- 画面をシンプルに
- キャッシュ
- 画面の部分更新
まとめ
- 正しく把握、設計、実装
- 小さくシンプルに
- SQLコツコツチューニング
- サービス応答性能
Supership社 DSP 「ScaleOut」の成長と負荷対策
今日話すこと
DSPとは
- 広告枠をオークション形式で購入する広告配信プラットフォーム
- リクエストがとんでもなく多い
- レスポンス速度の制約→0.1秒以内にレスポンス
- ピークタイムは20~24時
インフラ
- 配信にRDBは基本的に使わない
- KVSを利用するのが一般的
インフラの変化
- 全てオンプレ
- 当初 配信サーバ48台
- 現在 配信サーバ500台 + 集計サーバ150台
リクエスト数
- 当初 8億/month
- 現在 2000億強/month
- 売上数十億/year
システム構成は当時と大して変わらない
- 初期設計大事
- 社長が元yahooでトラフィックさばいてた経験が生きた
サーバの熱問題
- サーバ自作してた
- 排熱性悪くcpuクロック悪化
- サーバどうやって冷やすかを議論
- 結論: 自作しない
オンプレだとサーバ急に足せない
- 急なリクエスト増
- 優先順位をつけて、売上に貢献しない処理から削る
- 自分たちでサーバ負荷を減らす方法を用意しておく。SSPによっては管理画面からリクエストを止める
- 優先順位が低い枠からオークションに参加する確率を下げる
- ほぼ買えない枠や買っても広告効果を期待できない枠はCPU時間の無駄
- 60msを超えたら処理を打ち切る
- ほとんど配信されない案件にはペナルティを与える
- 案件を無駄に登録出来ないように
- 事前に案件の脚切りを行う
- 特定のユーザは極力同じサーバで処理→キャッシュヒット率をあげる
- 配信時の価格決定に必要な計算をシンプルに
集計系も時間かかる
- Hadoop150台
- Resource Managerで優先度に応じてqueueを分ける
- 集計基盤に、サンプリングされたデータが入るテーブルも用意する
- 概算だけ分かれば良いケースも
- uu数を計算するためのサンプリングを用意する
- ユーザをn個の集合に分割
まとめ
なぜ負荷対策重要?
- 怠るとサービス止まる
- 利用者が増えると負荷は勝手に上がるので定期的に対策が必要
- 重要なのは対策に開発リソースを一定量以上とられないこと
競争力激しい
- googleやFBとも戦わなければいけない
- 開発リソースは新機能に使いたい。
Gunosy社 Gunosyの高負荷アクセスを支える技術
- 2年前にGo言語を導入
- 日本だとGoogleの次に導入した会社では
- 既にGoで書いた負債返している段階
RailsからSinatra
- Railsを用いたシンプルなWebサーバ群
- ユーザは数十万人程度
インフラ
出来る限りサーバを小さく、コストをかけないように
- DBに対するIOから疑う
- メモリを効率的に
- CPUを使い切れてるか
- 同時コネクション受け入れられているか
キャッシュ
- ページキャッシュ
- DBキャッシュ
基本的な対応でも通常の負荷は対応可能
TVCMとGoの導入
短期間・小リソースで性能を向上させる必要性
Goの特徴
Nginx-lua、Haskell, node,jsと比較した
高パフォーマンス
- 安定性
- Goroutineとchannel
- CPU使いきれる
- 比較的省メモリ
** 独立性の高さ * 依存関係は全て1バイナリ * クロスコンパイル良い
安定運用の実績
- Einhornと組み合わせて安全に再起動
- GoogleやSoundcloudによる実績
- 最近Githubのライブラリ急増
ひとつ上を行く負荷対策
プロセスキャッシュ
- DBにアクセスをしないAPIが作れる
- データフローに不整合が起きないように設計
ChannelをQueueとした非同期処理
- Channelのキャパシティを利用
- 直列化と処理効率の両立が可能に
Goとプロセスキャッシュについて
syncパッケージで競合防げる
GoroutineとChannelによる簡易MessageQueue
時間のかかる処理を非同期に、かつ直列に流していく
似非microservices
GunosyをPlatform化
- 予測できない負荷
- 機能ごとのに求められる要件が大きく変わる
- 画面単位(機能単位ごと)で分割することに
Opsworkでの効率化
負荷対策大切なこと
目標設定大事 ボトルネックを見極めること ツールを見極めること→問題に突き当たる前に調査しておこう
まとめ
適切な技術を選び適切にスケールさせていこう
質疑応答
Q. Opsworks使ってて、コード乖離したときにどうしてるか、新機能デプロイ時に設定どう変えているか
- ピーク時がわかっているのでそのタイミングにスタンバイさせている。CustomJsonにすべて設定持たせている
Q.シングルページアプリケーションにした方が良いのでは
- Sansan: 今後の項目によっては考えていく。入力のパフォーマンスあげることは課題
Q シンプルなクエリであればRDSでも捌ける クエリのリファクタリングをしたのか、そもそも設計段階でシンプルだったのか
- Sansan 最初からシンプルなクエリだった。AR使っているので非正規化もけっこうある
Q RailsをGOに移行するの大変じゃない?
- Gunosy nginxの後ろにRailsとGO置いてた。少しずつ変えていたがE2Eテストあるのが理想。UIがないところはGoおすすめ。UIがあるならRailsやDjungoなど。Sessionの共有ちょっと大変だった。
Q Channellを使った通知だとプロセス間通信難しくない?Redisでやってみてるがコレジャナイ感
Q クエリ監視どうしてる?
- Sansan スローログとAppの例外で頑張ってた。クエリのレビューはやってる。
Q Redshift高くない?予算の基準ある?
- Sansan: 基準はないけど、名刺1枚あたりのコスト感でジャッジしてる。安定稼働に注力している。クオリティ、コスト、デリバリーの中ではコストが一番動かしやすい
Q どんなエンジニア求めてる?
- SanSan: 全般的に求めてる。インフラからアプリから。
- Gunosy: 全て、マネジメント含めて求めてる。Go書こうぜ!
- ScaleOut: 一番緊急で欲しいのはデータマイニングエンジニア。オークションの最適価格決定したい。
Q 今の設計の正解をどのように導き出しているか
- SanSan: 一人で考えない。チームでよく揉む。複雑な部分に違和感をもつ。
- Gunosy: データフローをいかに構築するか。データの持ち方や配信を思考実験から。まずはサービスを作りきるところが大事では。
- ScaleOut: 初期から大きく変えていない。問題が起こりつつあるログ転送にKafka使ったり、KVSは集約化した方が良いかもと思っている
「DDD Alliance! ドメイン駆動設計をやってみた 6つの現場からの報告」に参加してきた #DDDAlliance
2015年11月10日に開催された「DDD Alliance! ドメイン駆動設計をやってみた 6つの現場からの報告」の抽選に当たったので参加してきました。
第一部 ビックローブでの2年間の取り組み
DDDを組織で始めるための考え方
1. DDDはじめの一歩
当時のビッグローブでは内製をしておらず外注メイン、プログラマがいないスクラムを始めた → メンバーが増え、2、3年で十数チームできた
課題:アーキテクチャ
- 15年稼働しているシステム
- 独自言語で書かれている(!)
- 複数の会社に外注してた
結果: カオス!
コンテキストマップ作ってみたけどわけわかんない
スクラムでも成果でそうになかった 独自言語で人が成長しない
課題: 業務ロジックの設計
- MVCでは足りない
- ある日:DDDがいいのではというメンバー
- DDDおじさん(増田さん)の記事→呼んでみよう!
増田さんの言うとおりに守破離の守
作っては壊しを3人で半年
取り組んだこと
できそうな気がする → 案件探し
案件の条件
- 「新規サービス」
- 小さい
- 他に影響しない
- 納期調整可能
独自言語を書き直し機能追加も→うまくいった!
暖簾分け→育ったメンバーを別チームに配分して拡大する
時間かかるが暖簾分けおすすめ
2.組織に導入するポイント
DDDのような組織がやったことがないことをやるには
- 小さくやる 5人くらい
- 知っている人に教えを請う
- 暖簾分け
重要:結果を出す
3. なぜDDDか
クリストファー・アレグザンダーの思考の軌跡より
設計の仮設:設計(デザイン)の動機は自分たち(プログラミング)の外にあるべき
DDDの価値とは
組織全体として考え方を統一する
- サービスとコードをドメインでつなぐ → サービスを考えるようになる
- 変化へのしなやかな対応 → 変えることが当たり前になる
やるのは「人」
設計する人、サービスを使う人、プログラミングする人
開発メンバーの成長 道具を変えることで人は成長する アジャイル スクラムとの相性は良い
まとめ
サービスを考える人(経営者)と作る人との理解がつながる。これをしないとサービスが良くならない
キーワードは「統合」
開発現場から学んだドメイン駆動設計中心のサービス開発
www.slideshare.net
- 現BIGLOBE社員
- リードエンジニア(技術リーダー)
導入
- 5チーム/30人気簿でDDD
- 目標は100名くらいでやりたい
大事にしてること
- DDDの価値を共有
- 課題分析と解決に向けての行動
- 人材育成計画
- 新たな技術(CQRSとか)
- 開発環境基盤の高度化
DDDを採用する価値
- エンジニアもサービスの価値を考えないといけない
- サービスの継続が大事(人増える、変化多い、価値が変わる) 5~10年
独自言語はサービスの維持が精一杯
DDDの価値→サービス終了までのトータルコストの削減
変更コスト、属人性を下げる→業務をコードで表す
チーム環境の考え方
立ち上げ時の心構え
- 開発初期はわからないことだらけ
- 方向付けのレベルの設計に留める
- コアドメインを議論することはサービスを理解する第一歩
- サービスの複雑性と向き合う(大事)
スプリント
- ドメインモデルとコードを結びつける
- モデルの持つ糸をコードに引き継ぎコードを通してモデルにフィードバックする
- 設計者と実装者を分離しない
スプリント時の心構え
- コアドメインの設計・実装は重点的に
- 時間の都合上、すべての設計を完璧にはできない。
- プルリクエストのWIPを活用して効率的にレビューする(バックログ取ってから半日でPRがでる)
- スプリントごとに重要な概念を追加、ふような概念を削除
- 普段の会話のぎこちなさに敏感になった
- 書き言葉と話し言葉がずれたら警告
- 初期のドメインモデルや実装では重要で
- 見つけた問題を放置すると困る(特にコアドメイン)
- ドメインモデルを改善するプロセスが大事
チームビルディング
- 人的要因がパフォーマンスに影響
- 相乗効果(1 + 1を3以上にする)
- 知識(要求)は変化する。知識の共有が大事
DDDにおけるチームビルディング
「チームが機能するとはどういうことか」
- 学習するための組織づくり
- 学習しながら実行する → DDDで必須
リーダーは方向性を定める
- 絶えず少しずつ変化することが日常的
- 双方向のフィードバック
- 社員の判断は不可欠
- 目標:長期的な価値を生み出すこと
チームビルディングの内容
1. 全員で設計する
- メンバーが考える場所を作る
- メンバーの意見を引き出す
- メンバー間のギャップをなくす
メンバー全員が同じ地図を(ドメインモデル)を理解するため
設計の目的と効果をメンバー全員が理解して実装するため
熟練者のノウハウを経験が浅いメンバーに伝授する
2. モデリング済みの部分も積極的に改めてモデリングする
- メンバー間で確認
- 機能強化時、プランニング時、コードレビュー時、いつでもやる
- 経験が浅いメンバーはモデリングする機会を増やすことが成長につながる
- 新規加入メンバーはドメインを理解するチャンス
- 大事:モデリングはメンバー自身に実施させる(考えをアウトプットさせる場)
結果:
- チームの設計力が向上
- 変更コスト、属人性が下がる
- DDDを採用する価値を実感
まとめ
- DDDはチームビルディング大事
- 全員で設計に参加
- 既存部分も設計しなおそう
開発
- コアドメインになりそう、変更がありそうな所は積極的に分離
- 業務を中心に添えると業務ごとにデータが増えるのが自然
- Eventテーブル: 業務(申し込み、契約、解約など)ごとに用意。Insert中心。イベントログとしての役割。
- Stateテーブル: 業務によってUpdate。Eventテーブルの補助としての役割。データアクセス層の関心事で利用。
- imuttableデータモデルを使用するとNULLが減って良かった
- アプリケーションのみでなくDBで業務ロジックを表せられた
失敗談
ドメインモデルが古い
Policyクラスの乱立
- 業務チェックのために
- エンティティから業務ロジックが減っていく貧血症
- Policyパッケージを作った時点で負け
RepositoryのSaveメソッド
他集約のRepositoryを操作
- アプリケーション層のコードだけでは関連する集約が把握できない
- やめよう
SQLに業務ロジックが混在
- はがそう
- 主キーのみで検索してドメイン層で絞った方が良い
まとめ
- DDD本と実践を行ったり来たりして理解を深めよう
- サービスが存在する限り変化しつづけ、成長しつづけ、価値を届け続けるソフトウェアを作ることが大事
第二部 受託開発の現場から
ドメイン駆動設計を実践するプログラマーの悩み
- プログラミングの面で悩んでいること
- 今は3層レイヤとドメインロジックで構築
気をつけていること
- モデルの歪みに気づけるか
- 人は作りやすい方向に流れてしまう...
- モデルにロジックを集める方向に作りやすくする
辛いこと
UIからのデータバインディング辛い
- publicなsetterがひつよう
- 場合でデフォルトコンストラクタ必要
- 型のミスマッチ
- 階層を持った多肢選択UIや一覧表入力系UI
UIすぐに変わるし辛い
バリデーション辛い
- 型のミスマッチ
- 意味的なチェック
- DBを必要とするチェック
- 限定的な文脈でのみ行われるチェック
まとめ
ドメイン駆動設計におけるシナリオテストの活用
シナリオテストの動機
BDDでシナリオをテストコードで表せれば顧客からのフィードバックを受けやすくなるのでは → Spock採用
効果
- 開発にリズム感でた
- ちゃんとした実装は後回し
- 仕様の合意でたら実装にスピード感出る
- 声に出して読み合わせして毎週フィードバック得られる
今後
- よりよい可読性を目指す
- 複数モジュールやコンテキストをまたいだテストを書けるようにする
- どこまでテスト作るかの見極め
- 画面を作るタイミングの見極め
第三部 内製の現場から
ECサイトのリプレイスをDDDでやってみた
背景
サービスをちいさく分割したい
某殿堂の圧縮陳列(ドンドンドン・ド○キー♪)
やってみた
実装
結果
- いわゆるドメインモデル貧血症に陥る
- 振る舞いを切り捨ててしまったのでDDDを導入した意味がなかったかも
- チームでもっと言葉を使って探求すればよかった
その後
- DDDの普及活動(読書会)によって仲間が最近増えてきた
最後に
- たぶんDDDに正解はない
- チームが言葉で話して納得できたらそれが正解
- DDD本←→実装の反復作業がより理解する近道
ガチDDDを経てDDDって何?って現場に行ったあるプログラマーのお話
www.slideshare.net
DDDとの出会い、DDDと離れて、再び導入した話
DDDって?
転職してDDDが無い環境へ
- ロジック分かれてない、ドメインが無い
- リファクタリングでごまかしてたが拉致があかない → 勝手にDDD
- 1つ何か対応するたびに20以上クラスが増える、毎日嫌がらせのようなPRを出し続ける
- 気づいたらレビューしてくれるメンバーが似た感じのコードになっていた。
DDD導入には
- エヴァンス本や勉強会で知識高めることも大事
- 実際に手を動かすことの方が重要かも
最後に
ドメイン駆動設計のススメ
悪しき習慣
- 基本データ型でプログラミングする→型を独自に定義しない
- 動いたら設計を辞める → 本当に業務をあらわせているか?
- コードを書く前にドキュメントを準備する
- 分析/設計/実装を別の人間がやる
- 分析/設計/実装を別の日にやる
身に付けるべき習慣
- 独自の型をどんどん作ろう
- 動いてるコードの設計改善に時間をかける -- まずコードを書いて動かす -- 動いてるコードに対して議論して設計改善する
- ドキュメントは(必要なら)コードから生成する
- 分析/設計/実装を同じ人間がやる(鉄則!!)
- 毎日、分析し、設計し、実装する
学び方
書籍から学ぶ
- リファクタリング本は何度も読んだ(一番現場で生きた)
- オブジェクト指向設計の原則
- エクストリーム・プログラミング
コードから学ぶ
- 動いてるコードを対象に設計改善を議論する
- 動いてるコードを変更する
- 設計の違いの効果を実感する
まとめ
- DDDやったからといってすぐ見違えるわけではない
- DDDをやりながら実感を増やし徐々にかわっていく
最後に
おなじみケント・ベックの言葉
どんな状況でも改善できる どんなときでも「あなた」から改善を始められる どんなときでも「今日」から改善を始められる
リファクタリング―プログラムの体質改善テクニック (Object Technology Series)
- 作者: マーチンファウラー,Martin Fowler,児玉公信,平澤章,友野晶夫,梅沢真史
- 出版社/メーカー: ピアソンエデュケーション
- 発売日: 2000/05
- メディア: 単行本
- 購入: 94人 クリック: 3,091回
- この商品を含むブログ (312件) を見る
オブジェクト指向入門 第2版 原則・コンセプト (IT Architect’Archive クラシックモダン・コンピューティング)
- 作者: バートランド・メイヤー,酒匂寛
- 出版社/メーカー: 翔泳社
- 発売日: 2007/01/10
- メディア: 単行本(ソフトカバー)
- 購入: 11人 クリック: 307回
- この商品を含むブログ (131件) を見る
- 作者: ケントベック,シンシアアンドレス,Kent Beck,Cynthia Andres,角征典
- 出版社/メーカー: オーム社
- 発売日: 2015/06/26
- メディア: 単行本
- この商品を含むブログ (4件) を見る
Scala Best Practiceの和訳を進めています
次世代 Web カンファレンス #nextwebconf に参加してきた
2015年10月18日に開催された「次世代 Web カンファレンス #nextwebconf」に参加してきました。
server_perf
以下自分のつぶやきと参考になったツイート
「パフォーマンスを上げるには仕様を変えるのが一番よかったりする」
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
cookpadではアプリから叩くAPIのリクエストが支配的になっていて、Webの比率は下がってきている #nextwebconf405
— でめ (@deme0607) 2015, 10月 18
webよりapiが増えている。勘所が違う。やることが単純に。ただし単体の処理性能は求められる #nextwebconf #nextwebconf405
— Hiraku (@Hiraku) 2015, 10月 18
IoDrive使ったりする(札束で殴る) #nextwebconf405
— 再利用性 (@reizist) 2015, 10月 18
全部キャッシュするとメモリが溢れる。効果が抜群なところ、ユーザーごとに共通なもの、ランキング上位でよく見られるところ、そう言った特性を活かす #nextwebconf #nextwebconf405
— Hiraku (@Hiraku) 2015, 10月 18
「キャッシュがあるとABテストしにくい」「不具合がキャッシュのせいか判別するコミュニケーションコストある」 #nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
CPU1個あたりの性能は結構前から頭打ちになっているのでコアを増やして性能を出すようになっている、複数のCPUを扱いやすいような言語としてCやGoなど使ってるらしい #nextwebconf405
— 再利用性 (@reizist) 2015, 10月 18
us-east においておけばまんべんなく遅い (日本においておくよりはいい) #nextwebconf405
— Takumi Kanzaki (@tknzk) 2015, 10月 18
昔に比べてCDNに求められていることは増えていて、今まではstaticなコンテンツ配信のみだったけど今後はapiへのリクエスト等もCDNを通してレイテンシを抑えるという会社も増えてきたとのこと、へえ #nextwebconf405
— 再利用性 (@reizist) 2015, 10月 18
「Opera miniは画像のリサイズをプロキシ側でしてくれたり、JSをサーバサイドでレンダリングしてくれたりする」 #nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
server_arch
server_archでは開始早々、@yuguiさんが開発したJSON APIへの変換プロキシ生成機"grpc-gateway"の話となった。
そもそもgRPCとは、HTTP/2の利点である双方向ストリーミングや多重リクエストを扱えるRPCフレームワークであり、C、C++、Java、Go、Node.js、Python、Rubyなどの言語をサポートしている。
新しいオープン ソース HTTP/2 RPC フレームワーク、gRPC のご紹介 - Google Developer Japan Blog
ただ、gRPCはすべての言語をサポートしているわけではなく、かつHTTP/2が必須なため、これを今までのJSON API、HTTP 1.1でも動かせるようにするためのものが"grpc-gateway"とのこと。
以下自分のつぶやきと参考になったツイート
HTTP2をカスタムプロトコルの土台にするユースケースがGRPCだと。 #nextwebconf405
— 0x1F歳になったじょーかー (@joker1007) 2015, 10月 18
言語として db とのコネクションプールをサポートしているのは java だけ、そういう視点なかったな、おもしろい #nextwebconf405
— Tetsuya Morimoto (@t2y) 2015, 10月 18
JDK9にReactive StreamsのDoug Leaさんの話題。JSR前のJEPはこれですね。http://t.co/FUZOtbE8Ti #nextwebconf #nextwebconf405
— guyon (@gu4) 2015, 10月 18
これか。 http://t.co/J2rXQMV8g8 #nextwebconf405
— Shinpei Ohtani (@shot6) 2015, 10月 18
「Googleは海底ケーブル引くセクションを持ってる」
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
「ちゃんと自前で海底ケーブル引いてる会社のとこ使えばいいんじゃないですか」「たとえば Google にはそういうセクションがありますよね」 #nextwebconf405
— そらは (@sora_h) 2015, 10月 18
「内部通信はマイクロサービスでのコンテキストと呼んでいる。前提としてマイクロサービスがあって非同期な話が出てくる。」 #nextwebconf #nextwebconf405
— guyon (@gu4) 2015, 10月 18
非同期あってのMicroServices、ってところが落とし所っぽいな
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
普通にMicroservicesはデフォルト非同期・ノンブロッキングじゃないと、粗にできないから、難しいと思いますよ。 #nextwebconf405
— Shinpei Ohtani (@shot6) 2015, 10月 18
standardization
(昼飯で抜けてたので途中からしか聞いていない)
以下自分のつぶやきと参考になったツイート
ES6の仕様策定は6年かかってる
#nextwebconf #nextwebconf406
— ぺら (@Peranikov) 2015, 10月 18
ES6 の仕様策定には 6年かかったが、最後には凄くスピードが上がった。それは Babel の存在が大きい。実際に開発者に使ってもらいフィードバックを得ることで標準化の速度を加速する。 ES.next の仕様の議論にも Babel の名前が出てくる #nextwebconf406
— Takuto Wada (@t_wada) 2015, 10月 18
extensible webで低レイヤなものを作るともう一回POSIX作るみたいな事になりがち、OSでやってることもう一回やるんですか?!皆さん?! #nextwebconf #nextwebconf406
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
Webっていうのが複雑になりすぎてて、vivaldiみたいな小さいブラウザが標準に沿おうとしてもかなり小さいベンダーだけでは難しくなっている。 #nextwebconf #nextwebconf406
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
http2
以下自分のつぶやきと参考になったツイート
http2の現状
- 仕様は去年の11月でほぼ固まっている
- クライアントブラウザ側はほぼ対応済み
- nginx/Apacheもモジュールがある
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
http2は本当に速くなってるのか?1より遅い部分もあるのでは?
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
- http1では同時接続が6本、http2では100本
- http1では先にHTML、後からJSや画像が来る。http2ではすべて同時に来る。
- つまり最初のレンダリングが遅くなるケースがある
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
http2で遅くなるケース:
http1だったら6本でファイルをDLできたけど、http2だと同時に何本も取れるようになる、htmlに書いてある全部のリクエスト同時に送る、そうすると画像もcssもjsも混ぜこぜに来るので初期レイアウトを見るのがhttp1よりも遅くなるケースが有る
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
多重でロードできるが、「CSSや画像を先にくれ」という優先度をつける仕組みをきちんと実装できているのは現時点firefoxしかない
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
Chromeはpriorityの実装を進めようとしてるがIEはすでに諦めてる #nextwebconf #nextwebconf405
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
http2を使いこなすために
- ブラウザ側で指定しないのであればサーバ側で優先度つけてあげる
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
大津さん「priority自体が万能な銀の弾丸とは思っていない、いくらpriorityが高くても手元にリソースがないと送れない、この手元にちゃんとリソースがある状況がそんなに沢山ないのではないか。」 #nextwebconf #nextwebconf405
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
priorityは万能ではない
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
大津さん「CDNしかり、ファイルからまだ読み込めてない状況もあるし、コンテンツのシチュエーション次第では指定しても無駄になるケースが有る」 #nextwebconf #nextwebconf405
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
http2は1に比べ遅延の影響を受けにくいのがメリット
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
日本でのRTTは数十msec程度。1つのWebページ表示するのに10~20RTT。ServerPushで1RTT減ったところで大したインパクトはない。
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
「ServerPushは高速化にメリットは無いのでは」
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
『Server Pushいらないんじゃない?』っていう話も仕様の際には出てた。キャッシュ用途に使うというのはキャッシュがあるかどうかを判別するのが難しい。 #nextwebconf #nextwebconf405
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
server pushが意外と難しい問題はこの辺もご参考に / ES6 ModulesはHTTP/2によってconcat無しで使えるようになるのか - teppeis blog http://t.co/v1hJIkcSex #nextwebconf405
— teppeis (@teppeis) 2015, 10月 18
http2は速さ以外のメリットがあるか?
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
http2のメリットとしてサーバ側からクライアントへのPushがやりやすくなる。
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
http2は"基本的に"速くなると思っている。1つのコネクションで複数リクエストに対応できるので結果的にサーバ側の負荷が下がる。
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
TCPの接続を毎回切断しないのでサーバーの負荷を下げるっていう速度以外の効果もある。Googleみたいな大規模になればなるほどその効果が上がる #nextwebconf #nextwebconf405
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
http2 はハイパージャイアントだけのものなのか?小さいベンダーで使う意味があるのか?身の丈に合うのか?? #nextwebconf #nextwebconf405
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
WebSocketはhttp2では使えなくなった
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
いつ http2 only のサイトを作るか、 mobileで言えば iOS10 が来年出る、そうするとSafariはクライアントがhttp2を対応してる、そういうタイミングだったらhttp2オンリーでもいいのではないか #nextwebconf #nextwebconf405
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
セマンティクスとして一番足りないものは何かというと、HTTPはreq/resで双方向でデータやりとりする仕組みが足りない、GRPCは複数の接続を貼って実現してる、そういうのができるような動きが増えると良い #nextwebconf #nextwebconf405
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
Google QUIC
https://t.co/VTCCn2Qozp
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
HTTP/2, QUIC入門
http://t.co/L5IdMt0w1J
#nextwebconf405
大津さんの資料がわかりやすいです
— ゆき (@flano_yuki) 2015, 10月 18
QUICの場合はUDPでデータを暗号化していっぺんに送れる、0-RTTでできる、レイヤをまたぐことでレイヤごとにやってる無駄な処理を省くという効果がある #nextwebconf #nextwebconf405
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
丁度雑談で、「HTTP/2はハイパージャイアントのためだけのものだと思ってたけど、特定用途のカスタムプロトコルの基盤としてなら多重化もプライオリティも重要だしライブラリが自動で対応してくれる余地がある」という話をした。 #nextwebconf
— Yuki Yugui Sonoda (@yugui) 2015, 10月 18
QUICの標準化で興味が有るのはwire formatがリトルエンディアンで実装されてる、そういう仕様ってあんまりない、ほとんどのサーバはリトルエンディアンなので、ビッグからリトルの変換がない分無駄な処理が減る #nextwebconf #nextwebconf405
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
kazuhoさん「QUICの期待:ゲーム系ではUDPが普通だし、それによってリアルタイムなものが増えてくる、そういう意味でもhttp2ではなくQUICの重要性は高い」 #nextwebconf #nextwebconf405
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
「将来的にはhttp1.1とhttp5だけ、みたいな世界になるのでは」
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
「Webはエコシステムで成り立っていると思っている。エコシステムの中心が移っていった時、http1は取り残されたもの、という恐怖がある」
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
Jxck「エコシステムの中心はhttp1.1じゃなくて先に行ってしまうのではないか、そういうエコシステムが先に先に行くことでhttp1.1の人たちは取り残される懸念がある」 #nextwebconf #nextwebconf405
— Yosuke FURUKAWA (@yosuke_furukawa) 2015, 10月 18
front_arch
以下自分のつぶやきと参考になったツイート
ルーティングどのようにしているか
- ReactではReact Routerを素直に使っている
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
ルーティングどのようにしているか
- Angularはルーターが強い
- ngRouteという標準APIがある
- サードパーティuiRouterを公式が勧めるほど強力
- Angular2でもルーターはサポート
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
Angularは1.4でReactと同等のパフォーマンス!
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
Angular2のアーキテクチャ
- MV?と言っていない
- データフローを特に提示していない
- コンポーネントをツリーにするのでFluxライクである
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
イベント管理どうしてますか?
- Reactでは担当するコンポーネント作ってそのコンポーネントに任せてる
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
イベント管理どうしてますか?
- イベント扱うのにStreamは良い
- Promiseが発達することが条件
#nextwebconf #nextwebconf405
— ぺら (@Peranikov) 2015, 10月 18
さいごに
主催してくださったJxckさんを始め、登壇された方々ありがとうございました。とても濃密でWebの未来について感じることができた1日となりました。
今回俺がいかにして転職したか晒す
9月から新しい会社で働き始めました。折角なので今回どのように転職したのかをまとめておきます。
何をつかったか
今回はWantedlyをメインに使って転職活動を進めてきました。前回の転職ではエージェントを使いましたが、今回は自分のペースで活動したかったのでエージェントは使いませんでした。
期間・エントリー数
期間は3月~8月の間の5ヶ月間、活動しました。エントリー数は全部で6社となりました。
準備
プロフィールを書く
とりあえずWantedlyのプロフィールを埋めました。経歴、このさきやってみたいこと、作ったアプリなどは特に公開しておけばいいと思います。
履歴書・職務経歴書
企業によっては、エントリーしてすぐに履歴書・職務経歴書をメールで送ってほしいというところもありました。履歴書は、Wantedlyの「できる履歴書」で書くと写真込みでPDF出力できてすごく便利でした。
職務経歴書版も是非欲しいですが、職務経歴書はフォーマットが様々なので厳しいのかもしれません。
企業にエントリーする
まずは1社エントリーすると良い
Wantedlyの場合、おそらく1社でもエントリーすれば最近活動のあるユーザとして企業側に伝わるようで、初エントリー後はスカウトがよく来るようになりました。*1
エントリー後の流れ
エントリー後はWantedlyのチャットでその企業の担当さんとやりとりします。 大体の流れとして、
- 面接の日程調整
- 履歴書・職務経歴書 → リモートで技術テスト
- リモートで技術テスト → 面接
というケースがありました。この中ではいきなり面接というケースが一番多かったです。
福利厚生については別サイトで
Wantedlyでは、その企業がどのような活動をしているか、どのような技術を使っているかはわかりやすくなっていますが、福利厚生などがわかりにくいのでそこは別サイトに頼る必要があります。(実際に福利厚生について質問したら別サイトのリンクが渡された)
企業の規模でレスポンスに差がある
これは経験則ですが、社員数が十数名の企業はエントリーしてから数日で返信が帰ってくるのに対し、社員数3桁以上の企業は返信に2週間程度かかりました。これはその会社のエントリー数にもよると思いますが、転職活動のスケジュールを考える上で注意が必要です。
さいごに
最近自分の周りで転職を考えている人が増えてきているので自分のケースをまとめてみました。何かの参考になれば幸いです。
*1:数えてみたら16社あった