「DDD Alliance! ドメイン駆動設計のためのオブジェクト指向入門」に参加してきた #DDDAlliance

2015年1月21日に開催された、「DDD Alliance! ドメイン駆動設計のためのオブジェクト指向入門」に参加してきました。

ddd-alliance.connpass.com

以下から現地で書いたメモ

ドメインモデルとは

ドメインモデル = 関心事を集めたもの。サブセットと呼んでもいい

ドメイン駆動設計

ドメインを分析する人がコードを書く コードを書く人がドメインを分析する 毎日分析し、毎日コードを書く

コードを書くためにはクラスを見つけなければいけない 問題領域を分析することでクラスが見つかる 分析者 = 実装者 とならなければならない

モデルを見つけることとクラスを見つけることは一緒。人を別にしてはいけない。

ソフトウェアを立ち上げる時はフェーズと人を分けるけど、 保守フェーズでは分析と実装者が一緒。立ち上げ時もそれをやればいい。

ドキュメントを書いてからコードを書くという方法は大概無駄になる。

ドメインを学び学んだことをコードで表現することが大前提

ドメイン

ドメイン層はどこにも依存しない(プレゼン、アプリケーション、データベース) Springで実装

ドメイン層はPOJOフレームワークは導入しない。

ドメイン層のオブジェクト ドメインにGetter/Setterは使わない 業務の関心事の表現 知りたいこと 誰が、いつ、なぜ。。。 業務ルール 制約、閾値、手順。。。 業務ルールが破られた時の業務ルール

業務サービスの実行役 判断の結果 計算の結果 加工の結果 (基本データ型は返さない)

独自の型を作ることがドメイン指向設計

オブジェクト指向のメリット: コードの整理

クラス単位に関連するコードを整理する どこに何が書いてあるか特定しやすくなる 変更が飛び火しない - データと機能を分けると飛び火しやすい 変更した箇所のテストがOKなら全体もOK

アンチパターン:変更コストが高くなる設計

ふるまいを持たない、いわゆるデータクラス

データクラスがレイヤーを跨いで使われている

どこで使われているか特定しにくくなる

変更コストが下がる設計

役に立つクラスを作る(判断・加工・計算ロジックを持たせる) クライアントは使うだけ

オブジェクト指向ドメイン層の構造

主要な関心事をアグリゲートに組む

オブジェクト指向アーキテクチャ

構造

オブジェクトの集合体

強く関連する部品は集約する

アグリゲート同士は分散性を高め必要最小限につなげる

「変更」を前提にしたネットワーク構造

メタファ:LANアグリゲートとインターネット(全体)

工法

「変更」を前提にする

インクリメンタルに開発

少しずつ成長する全体

毎日変化させていく

オブジェクトの設計

独自の型を設計

オブジェクトのコラボレーションを設計

実現手段の隠蔽

独自の型を設計する

ドメイン層は独自の型だらけにする

独自の方=利用者の関心事

基本データ型=コンピュータの関心事

オブジェクトのコラボレーションの設計

契約による設計、責任駆動設計、擬人化。。。

結局は「オブジェクト」と「オブジェクト」が協力して設計することが大事

コラボレーションの設計原則

オブジェクト同士の契約(顧客と供給者の関係)を意識する

相手のことを深く知りすぎてはいけない

書籍:契約による設計

「契約による設計」

契約ってなんだ?技術者にはいいメタファじゃないよね

契約はビジネスルールの関心事。業務ルールの基本。

業務知識を学べば業務ロジックも契約による設計も学べて美味しい

オブジェクト指向:実現手段の隠蔽

Java標準の(コンピュータよりの)メソッドを徹底的に隠す

業務の関心事の表現手段として「不適切」

int string LocalDate => 値オブジェクトで包む

for while List => ファーストコレクションで包む

列挙型でswitchを減らす

事例の研究

「転職支援サービス」を例に

転職アドバイザ

求職者

求人

応募

スカウト

職務依頼

ドメイン層の隔離

初級

フレームワークと規約 貧血ドメインモデル

中級

ドメインロジックを(プレゼン層、アプリケーション層などから)ドメイン層に移動する

浅いリファクタリング

上級

知識豊富になったドメイン層の見通しを良くする

深いリファクタリング

主要な関心事(コア)の隠蔽

主要な関心事(コア)の抽象化

各層の実装

プレゼンテーション層

標準的なSplingの機能を使う

サービスをインジェクションする

サービス層

渡されたIDに対してデータをリポジトリから取得する

ドメインの型を受け取り、ドメインの型を返す

データソース層

SQL Mapperのインジェクション

SQLとオブジェクトをマッピング

ドメインの型を返す

メトリクス

ざっくり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との出会い

Kawasaki.rb | Doorkeeper

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を使って自社サービスを作っています。

これを作って欲しい!と最初から言われる受託系から、サービスを自ら考え物にしていきスピード感も違うスタートアップへの転職で、最初は発想の転換にとまどっていましたが最近ようやく慣れてきた気がします。

なお転職に興味ある方はこちらのエントリーもどうぞ

norizabuton.hateblo.jp

初めてのRubyKaigi

Rubyistを名乗っているくせにRubyKaigiに参加したことはなく、今年始めて参加してきました。

rubykaigi.org

Rubyの魅力はその言語だけでなく、周りをとりまくコミュニティによって強く支えられていると聞いていましたが、RubyKaigiに参加することでそれが実感できたかと思います。みんな本当にRubyが好きなのだなと。

参考: MINASWAN - Wikipedia, the free encyclopedia

なお来年は早速ScalaMatsuriもあるので今から楽しみですね:)

scalamatsuri.org

横浜道場スプリント! そして...

2年以上通っていたアジャイルサムライ横浜道場ですが、実際にアジャイルのプラクティスを実践しながら開発をするという「横浜道場スプリント!」に1年通して参加していました。

yokohama-dojo.doorkeeper.jp

Webの開発を一切やったことがないメンバー*2を交えながらなんとか動くアプリを実装し、12月の横浜道場忘年会で無事発表することができました。

そんな横浜道場ですが、悲しいことに今年をもって休止となりました。

takubon.hatenablog.com

アジャイルサムライ横浜道場は僕が参加した最初の勉強会で、よりアジャイルを深く知ること、アジャイルのコミュニティの広さを教えてくれましたし、何より現場を変えたいと強く思う人達と多く知り合えた素敵な場でした。心より感謝致します。

まとめ

今年成し遂げたことなんてあっただろうかと思いながら書き始めてみたら、様々なコミュニティにお世話になった、という形になりました。

とくに来年の豊富などを思いついているわけではありませんが、エンジニアとしてより一層成長するためにプライベートを有意義に使えればいいな、と思うしだいです。

*1:当者比

*2:経験はなかったが最終的に一番の功労者であった

技術勉強会『開発エンジニアが知っておくべきwebサービスの負荷対策』[TECH VALLEY#6] #tv6

2015年11月18日に開催された技術勉強会『開発エンジニアが知っておくべきwebサービスの負荷対策』に参加してきました。

geechs-magazine.com

進化の読めないシステムの負荷対策 @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」の成長と負荷対策

今日話すこと

DSPaspサービスの成長過程で起こったこと

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とも戦わなければいけない
  • 開発リソースは新機能に使いたい。

GunosyGunosyの高負荷アクセスを支える技術

  • 2年前にGo言語を導入
  • 日本だとGoogleの次に導入した会社では
  • 既にGoで書いた負債返している段階

RailsからSinatra

  • Railsを用いたシンプルなWebサーバ群
  • ユーザは数十万人程度

インフラ

出来る限りサーバを小さく、コストをかけないように

  • DBに対するIOから疑う
  • メモリを効率的に
  • CPUを使い切れてるか
  • 同時コネクション受け入れられているか

キャッシュ

  • ページキャッシュ
  • DBキャッシュ

フレームワーク

  • RailsのオーバヘッドをSinatraを組み合わせてカバー
  • 場所によってはRackアプリを直接書く

基本的な対応でも通常の負荷は対応可能

TVCMとGoの導入

  • TVCMの開始
  • 大幅なUI変更 → ユーザが見れる記事数が数倍に、通知の配信頻度も増加
  • Rails/SInatra→ 1台あたり200req/sec、札束で殴った(インフラエンジニアいない)

短期間・小リソースで性能を向上させる必要性

Goの特徴

Nginx-luaHaskell, node,jsと比較した

高パフォーマンス

  • 安定性
  • Goroutineとchannel
  • CPU使いきれる
  • 比較的省メモリ

** 独立性の高さ * 依存関係は全て1バイナリ * クロスコンパイル良い

安定運用の実績

  • Einhornと組み合わせて安全に再起動
  • GoogleSoundcloudによる実績
  • 最近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でやってみてるがコレジャナイ感

  • Gunosy: RabitMQやNSQueueというオープンソース使うのおすすめ。Dockerのリブチャンはプロセスまたいでアクセスできたかも

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つの現場からの報告」の抽選に当たったので参加してきました。

ddd-alliance.connpass.com

第一部 ビックローブでの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メソッド

  • あらゆる操作をsaveメソッドのみで対応
  • BaseRepository作ってみた → カオス感Up!
  • 業務イベント事にメソッド用意したほうがシンプル

他集約のRepositoryを操作

  • アプリケーション層のコードだけでは関連する集約が把握できない
  • やめよう

SQLに業務ロジックが混在

  • はがそう
  • 主キーのみで検索してドメイン層で絞った方が良い

まとめ

  • DDD本と実践を行ったり来たりして理解を深めよう
  • サービスが存在する限り変化しつづけ、成長しつづけ、価値を届け続けるソフトウェアを作ることが大事

第二部 受託開発の現場から

ドメイン駆動設計を実践するプログラマーの悩み

  • プログラミングの面で悩んでいること
  • 今は3層レイヤとドメインロジックで構築

気をつけていること

  • モデルの歪みに気づけるか
  • 人は作りやすい方向に流れてしまう...
  • モデルにロジックを集める方向に作りやすくする

辛いこと

UIからのデータバインディング辛い

  • publicなsetterがひつよう
  • 場合でデフォルトコンストラクタ必要
  • 型のミスマッチ
  • 階層を持った多肢選択UIや一覧表入力系UI

UIすぐに変わるし辛い

バリデーション辛い

  • 型のミスマッチ
  • 意味的なチェック
  • DBを必要とするチェック
  • 限定的な文脈でのみ行われるチェック

まとめ

  • データ境界面が主に辛い
  • Javaから何かに変換するのはあまり辛くない
  • 何かからJavaに変換するのが特に辛い

ドメイン駆動設計におけるシナリオテストの活用

シナリオテストの動機

  • ウォーターフォール的にすすめていた → 最後に大量のフィードバック → 辛い
  • アジャイル的 → 毎週打ち合わせ、成果物リリース → 画面をできるだけ早く揃えたいが、出戻りをできるだけ防ぎたい

BDDでシナリオをテストコードで表せれば顧客からのフィードバックを受けやすくなるのでは → Spock採用

効果

  • 開発にリズム感でた
  • ちゃんとした実装は後回し
  • 仕様の合意でたら実装にスピード感出る
  • 声に出して読み合わせして毎週フィードバック得られる

今後

  • よりよい可読性を目指す
  • 複数モジュールやコンテキストをまたいだテストを書けるようにする
  • どこまでテスト作るかの見極め
  • 画面を作るタイミングの見極め

第三部 内製の現場から

ECサイトのリプレイスをDDDでやってみた

背景

サービスをちいさく分割したい

某殿堂の圧縮陳列(ドンドンドン・ド○キー♪)

やってみた

ドメインモデリング

  • ドメインエキスパート不在...RDBからモデリングしてしまった
  • 結果として知識を噛み砕けていないモデルを作っただけだった

実装

  • レイヤー化アーキテクチャ
  • レイヤの役割やコンテキストを意識できた
  • DDDの実感ここだけ
  • ドメインモデルをきちんと落とし込めないと意味ないと増田さんからバッサリ

結果

  • いわゆるドメインモデル貧血症に陥る
  • 振る舞いを切り捨ててしまったのでDDDを導入した意味がなかったかも
  • チームでもっと言葉を使って探求すればよかった

その後

  • DDDの普及活動(読書会)によって仲間が最近増えてきた

最後に

  • たぶんDDDに正解はない
  • チームが言葉で話して納得できたらそれが正解
  • DDD本←→実装の反復作業がより理解する近道

ガチDDDを経てDDDって何?って現場に行ったあるプログラマーのお話

www.slideshare.net

DDDとの出会い、DDDと離れて、再び導入した話

DDDって?

転職してDDDが無い環境へ

  • ロジック分かれてない、ドメインが無い
  • リファクタリングでごまかしてたが拉致があかない → 勝手にDDD
  • 1つ何か対応するたびに20以上クラスが増える、毎日嫌がらせのようなPRを出し続ける
  • 気づいたらレビューしてくれるメンバーが似た感じのコードになっていた。

DDD導入には

  • エヴァンス本や勉強会で知識高めることも大事
  • 実際に手を動かすことの方が重要かも

最後に

ドメイン駆動設計のススメ

悪しき習慣

  • 基本データ型でプログラミングする→型を独自に定義しない
  • 動いたら設計を辞める → 本当に業務をあらわせているか?
  • コードを書く前にドキュメントを準備する
  • 分析/設計/実装を別の人間がやる
  • 分析/設計/実装を別の日にやる

身に付けるべき習慣

  • 独自の型をどんどん作ろう
  • 動いてるコードの設計改善に時間をかける -- まずコードを書いて動かす -- 動いてるコードに対して議論して設計改善する
  • ドキュメントは(必要なら)コードから生成する
  • 分析/設計/実装を同じ人間がやる(鉄則!!)
  • 毎日、分析し、設計し、実装する

学び方

書籍から学ぶ

コードから学ぶ

  • 動いてるコードを対象に設計改善を議論する
  • 動いてるコードを変更する
  • 設計の違いの効果を実感する

まとめ

  • DDDやったからといってすぐ見違えるわけではない
  • DDDをやりながら実感を増やし徐々にかわっていく

最後に

おなじみケント・ベックの言葉

どんな状況でも改善できる
どんなときでも「あなた」から改善を始められる
どんなときでも「今日」から改善を始められる

リファクタリング―プログラムの体質改善テクニック (Object Technology Series)

リファクタリング―プログラムの体質改善テクニック (Object Technology Series)

  • 作者: マーチンファウラー,Martin Fowler,児玉公信,平澤章,友野晶夫,梅沢真史
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/05
  • メディア: 単行本
  • 購入: 94人 クリック: 3,091回
  • この商品を含むブログ (312件) を見る

オブジェクト指向入門 第2版 原則・コンセプト (IT Architect’Archive クラシックモダン・コンピューティング)

オブジェクト指向入門 第2版 原則・コンセプト (IT Architect’Archive クラシックモダン・コンピューティング)

エクストリームプログラミング

エクストリームプログラミング

Scala Best Practiceの和訳を進めています

少し前からScala Best Practiceの和訳を進めていて、現在0章と1章が済んだところ。

github.com

ライセンスはCC BY 4.0だけど、一応著者本人に声かけとくかな―と思ってた矢先に、一緒に和訳してくれている知人が知らせてくれていた。

github.com

こんなことやってる、ということを同僚に伝えたらあれよあれよと各章の担当が決まり*1、大変感謝している状況なんですが、多くの人の目に触れた方がより良い翻訳になるので、ここの表現おかしくない?などの意見はドシドシご指摘ください。

*1:なお自分は全然英語が出来ず、「バンドやろうぜ!当方ボーカル」状態である

次世代 Web カンファレンス #nextwebconf に参加してきた

2015年10月18日に開催された「次世代 Web カンファレンス #nextwebconf」に参加してきました。

次世代 Web カンファレンス - connpass

server_perf

以下自分のつぶやきと参考になったツイート

server_arch

server_archでは開始早々、@yuguiさんが開発したJSON APIへの変換プロキシ生成機"grpc-gateway"の話となった。

そもそもgRPCとは、HTTP/2の利点である双方向ストリーミングや多重リクエストを扱えるRPCフレームワークであり、C、C++Java、Go、Node.js、PythonRubyなどの言語をサポートしている。

新しいオープン ソース HTTP/2 RPC フレームワーク、gRPC のご紹介 - Google Developer Japan Blog

ただ、gRPCはすべての言語をサポートしているわけではなく、かつHTTP/2が必須なため、これを今までのJSON API、HTTP 1.1でも動かせるようにするためのものが"grpc-gateway"とのこと。

gRPC-JSON proxy - 世界線航跡蔵

以下自分のつぶやきと参考になったツイート

standardization

(昼飯で抜けてたので途中からしか聞いていない)

以下自分のつぶやきと参考になったツイート

http2

以下自分のつぶやきと参考になったツイート

front_arch

以下自分のつぶやきと参考になったツイート

さいごに

主催してくださったJxckさんを始め、登壇された方々ありがとうございました。とても濃密でWebの未来について感じることができた1日となりました。

今回俺がいかにして転職したか晒す

9月から新しい会社で働き始めました。折角なので今回どのように転職したのかをまとめておきます。

何をつかったか

今回はWantedlyをメインに使って転職活動を進めてきました。前回の転職ではエージェントを使いましたが、今回は自分のペースで活動したかったのでエージェントは使いませんでした。

www.wantedly.com

期間・エントリー数

期間は3月~8月の間の5ヶ月間、活動しました。エントリー数は全部で6社となりました。

準備

プロフィールを書く

とりあえずWantedlyのプロフィールを埋めました。経歴、このさきやってみたいこと、作ったアプリなどは特に公開しておけばいいと思います。

履歴書・職務経歴書

企業によっては、エントリーしてすぐに履歴書・職務経歴書をメールで送ってほしいというところもありました。履歴書は、Wantedlyの「できる履歴書」で書くと写真込みでPDF出力できてすごく便利でした。

www.wantedly.com

職務経歴書版も是非欲しいですが、職務経歴書はフォーマットが様々なので厳しいのかもしれません。

企業にエントリーする

まずは1社エントリーすると良い

Wantedlyの場合、おそらく1社でもエントリーすれば最近活動のあるユーザとして企業側に伝わるようで、初エントリー後はスカウトがよく来るようになりました。*1

エントリー後の流れ

エントリー後はWantedlyのチャットでその企業の担当さんとやりとりします。 大体の流れとして、

  • 面接の日程調整
  • 履歴書・職務経歴書 → リモートで技術テスト
  • リモートで技術テスト → 面接

というケースがありました。この中ではいきなり面接というケースが一番多かったです。

福利厚生については別サイトで

Wantedlyでは、その企業がどのような活動をしているか、どのような技術を使っているかはわかりやすくなっていますが、福利厚生などがわかりにくいのでそこは別サイトに頼る必要があります。(実際に福利厚生について質問したら別サイトのリンクが渡された)

企業の規模でレスポンスに差がある

これは経験則ですが、社員数が十数名の企業はエントリーしてから数日で返信が帰ってくるのに対し、社員数3桁以上の企業は返信に2週間程度かかりました。これはその会社のエントリー数にもよると思いますが、転職活動のスケジュールを考える上で注意が必要です。

さいごに

最近自分の周りで転職を考えている人が増えてきているので自分のケースをまとめてみました。何かの参考になれば幸いです。

*1:数えてみたら16社あった