読者です 読者をやめる 読者になる 読者になる

Productivity Engineering − Forkwell Meetup #4

【増枠!】Productivity Engineering − Forkwell Meetup #4 - connpass に参加したメモ。

チーム開発、改善のフローをどうやって回すかが大事。改めて感じた。 あとなんだかんだで、リモートとかで顔を合わせないことによるデメリットはなかなか埋められない。

@ryuzee さんの話きけたのはありがたかったな。ふりかえりは自分のチームでそこそこうまくいっている気がしていたけど、データを集めるって点で圧倒的に足りてないと思い知らされた。

@masamichi さんの品質の話。サービスのフェーズによって重要になる軸が異なるっていうのはナルホドと思った。ただ、これはユーザーストーリー駆動でやったら暗示的に解決されるのかも?とも。

@t_wada さん。ペアプロ。たまにやってはいたが、本質にたどり着いてなかったなと思った。来週やろう。本人もおっしゃっていたが、心理的安全がマジで大事だと思う。そのあたり、どうやって環境を作るかみたいな話も聞きたかった。

クックパッドにおけるモバイルアプリ開発の工夫 クックパッド @ichiko_revjune

  • モバイルアプリの開発体制とか
  • テストエンジニア
  • 利用者は多いけどアプリ利用者が少ない
  • モバイルは機能ごとにチームが分かれていて、技術部が共通基盤を担当。デザイナーも 分かれてる。クライアント/サーバーも両方同じチームにいる。
  • 2w - 1m でリリース。1リリースで10人程度のエンジニアが関わる。
  • 「サービスを変える」
    • 意図した通りに変更されたか
    • 効果が計測されているか
  • ユーザーが離れる、は損失。
  • 開発、テスト、リリースと分けている
    • 開発:issue, PR

キックオフ

  • ディレクター、デザイナー、エンジニア(みんな)
  • チーム間の情報共有
  • 朝会でタスク、施策を共有していたが、関係者が増えたりフレックスしたのでSlackに移行した
    • 非同期に議論できるようになった
    • 他人のタスクに言及しなくなってきた、関心が薄れていった
    • タスクが順調か、疲れてないか、という情報がなくなった
    • 1画面に複数プロジェクトが関与して表示崩れってのがあった
    • kickoff でやろう
  • 30m 20人くらい
  • 他チームへの懸念を伝えやすい
  • タスクが順調かとかはキックオフでは拾えていない。。

確認会

  • ディレクター、デザイナー、エンジニア
  • すべての変更をマージしたアプリを触る
  • 一貫性、意図通りになっているか。リグレッションテストではない
  • どんな課題があったか
    • チームが独立していたので一貫性が損なわれていた
    • 検証端末が多いので依存性をなくしたい
  • ユーザーのパターンでNGになる、
  • 1h, 15人くらい
  • NG があったらリリースマネージャーが調整

Effective Retrospective アトラクタ @ryuzee

  • スライドあるよ
  • ふりかえりはアジャイルだけじゃないよ; 開発だけでもないよ
  • KPT以外にもあるよ
  • もっとうまくできるようにする
    • 「あれ良かったね」「これよくなかったね」だいたい次のプロジェクトに反映されない。なので定期的に検査するのが大事。
  • 「強制的に仕事を停止する」意外と大事。
    • このままでいいのか一回止まる
  • 心理的安全性がないと無駄だよ
    • 参加者も大事。「口が達者ですぐに割り込むマネジャー」入れると良くない
      • どう伝えよう。。
      • 「ポジションが上の人が会議を乗っ取る」は防ぎたい。「忙しいだろうからチームで考えます」とか。ひっくり返されそうになったらそこは粘る。スクラムならスクラムマスター。ダメだったらその上の上司にいく。
    • 「私 vs あなた」ではなく「問題 vs 私たち」にどうやって持っていくか

場を設定する

  • 冒頭に全員に口を開いてもらう。効果が上がる。研究結果も出てる
  • 説明(タイムボックス、どこまでやるか、ルール確認)
  • 道具
    • コーヒー、甘いもの
    • 付箋、ホワイトボード
    • stopwatch
    • PC使わない!議事録はホワイトボードを写真で

データ収集

  • 客観的なデータ
  • イベント、メトリクス、完成した成果
  • 定性的なデータでもOK
  • 過去の写真とか会議のログとか
  • 「意見をもとに問題を解決しようとすると失敗する」factに基づかないと。
    • 「品質が悪い」「情報共有が不足している」は意見。

イデアを出す

  • いきなり出した解決策が正しいことは少ない。分析して改善する

何をすべきか決定する

  • 数が多すぎると無駄になる
  • 誰がいつまでにやるのかはっきりさせよう
  • fist to five (多数決じゃない方法)

終了

  • 記録を残す。フォローアップのアクションを決める。

よくある失敗と対策

  • くらい。特定の人しか喋らない。愚痴が多い。前回と同じになっちゃう。
  • 安全性欠如。
  • 不明確なアクション。トラッキングの仕組みができてない。
  • マンネリ。KPTは毎回やると飽きる。同じ観点になりやすい。やり方変えてみる。場所を離れる。
    • sprint retrospective でもタイムライン使っていいかも。
  • getting value of agile retrospective

最後に, Q&A

  • 日本人はあんまり褒めたがらない。ホメよう。
  • 遅い時間にやらない。昼頃にやる。
  • リモートだと
    • 同期的に書き込めるツール使う。振り返りの時だけは全員集まる。
  • 時間
    • データ収集と別に2hくらい。チェックインに10分くらい。
    • 短いと「仕事を止めてる」感じがなくなるという副作用。
  • 人数
    • 10人がギリギリ。兼務があるのならプロジェクトごとにやる、もあり。
  • 「マネジャーが言ったからダメ」でいいのか!
  • (直接伺った) 四半期だったり長期プロジェクトのふりかえりをタイムラインでやっているが、発散したり時間がかかる
    • 最初からテーマ決めてやるといいかもね(タイムラインはあってないかも?)
      • イベントの粒度が細かくなりすぎると発散する
      • (思ったこと) まず issue (problem ではなく) を先に集めといて、その中から厳選する
    • 人数が多いならワールドカフェ的にやるとか
    • ryuzee さんは長期のふりかえりは普段やってないっぽい

自己言及的なチームをつくる GMOペパボ @jue29

  • 自分たちが過ごす日々に対して自覚的であるチーム
  • 自分たちの日々を自分たちでデザインする
  • 問題は常にある

プロジェクトは何事もなければ失敗する

  • チームを評価するとき減点方式で行くか、加点方式で行くか。人によって考えが違う。
    • 加点方式のほうが良いんじゃないだろうか
    • 減点だとチームメンバーがトラブルを隠す
      • 「何もありませんでした」
      • 優秀なナースがいるとその場で解決されてしまい、全体に共有されない
  • トラブルを乗り越えることで信頼貯金が貯まる

どう作るか

  • 言葉を尽くす。行動で示す。
  • チームにとっての良さを言葉にする
  • 個人の価値観の押し付けはチームの価値観を壊す
  • 人は変化にストレスを感じるので「お得感」を出すと良い

どう変えるか

  • ブラウザ拡張、chatbotで自動化。お得感。

Make Jenkins Great Again サイボウズ @miyajan

Jenkins 2.0

  • release から1年。
  • ツールの用途、プラグインが複雑化。Jenkins職人問題。
  • docker イメージあるよ

plugin 多すぎ問題

  • install めんどい。品質バラバラ。
  • 推奨プラグインをインストールできるようになった。一般的な用途がカバー。

pipeline 作りづらい問題

  • 複数ジョブのつなぎあわせだった。ビルド後に云々〜
  • DSLでパイプラインを定義する。パイプライン自体が一つのジョブになっている

GUI 辛い問題

  • 項目多すぎ。バージョン管理できない。
  • Groovy でジョブの設定を記述。バージョン管理とか PR とかできる。
  • ただしプラグイン側が対応する必要ある

DSL syntax

  • Scripted Pipeline 手続き型。わかりづらい
  • Declarative Pipeline シンプル。Lint 効く
  • Declarative の中に Scripted を記述することもできる

共有ライブラリ

  • script を複数プロジェクトで共有が難しい
  • GitHub リポジトリからライブラリを読み込めるようになった。Grooby で書く
  • Error は赤字で出す、とか使いまわせる。プロジェクトごとに指定できるので変更の影響範囲が絞れる

ビルド、デプロイ

  • 設定が複雑。リポジトリの設定、ビルド・トリガーの設定などなど
  • GitHub Organization Folder
    • Organization 内のブランチを自動にビルドしてくれる
    • ジョブごとに設定する必要がない

Blue Ocean

  • UIダサい。
  • Blue Ocean UI かっこいい(RC)
    • Pipeline の設定 UI でやれる

今の懸念

  • staging のリトライ。Pipeline の途中からリトライ、とかやりたいけど OSS 版では実装されてない。issue で議論されているらしい。
  • プラグインの変更がでかい。

最速で価値を提供する ネクスト @masamichi

  • 品質について。
  • 品質をどう改善するか。
  • 最速で価値を提供する

品質

  • 狩野モデル
  • ビジネスフェーズごとに求められる品質が異なる。
    • 初期は魅力的品質が必要。そのうち「当たり前」が求められる。だんだん競合が現れて「性能品質」が大事になる。
  • サービスの特性
    • 無形である、非分離である(生産と消費が同時)、変動する(提供者、時間、場所によってサービスの質が変化する)
    • 作って終わりじゃない。そのあと品質を高めていく必要がある。
  • 品質
    • 有用性: ユーザーの利益になる、または損失を下げられる
    • 可用性
    • ユーザビリティ
    • セキュリティ
  • Webサービスの品質
    • 組み込みだとユーザはサービスを所有する。問題が起きたら大変。出荷したあとに修正が困難なことが多い。
    • Webサービスだとリリース後に修正できる。ユーザーの反応を見て改善できる。

品質改善の型

  • 品質の仕様化
    • そのプロダクトにどんな品質を求めるかを言語化する。
      • ISO25010 で決まってるらしい
    • 言語化されない品質は作られない!
  • 実装
    • 品質を高める技術
    • 欠陥検出型、予防型
      • テストで一気に消化するのが欠陥検出型、都度減らすのが予防型
  • モニタリングと改善
    • レスポンスタイム、安定性をモニタリング。脆弱性診断する。Net Promoter Score とる。

最速で価値を提供する

  • 品質とは誰かにとっての価値である
    • 内部品質: 開発者が書きやすい、メンテしやすい、も価値
  • 一方でスピードも必要。これは単純なトレードオフじゃない。両立できるよう工夫すべき。
    • リードタイムを短くする、無駄な工程をなくす。自動化する。
  • Value Stream Map
    • 原材料が加工されて顧客に渡るまでの経路を図にしたもの。どこがボトルネックになっているか。
    • 各工程で無駄を探す。
      • 計画だったらドキュメント、テスト、デプロイだったら自動化

Q&A

  • 実装者が品質について設計者に甘えがち。
    • 実装者も品質に歩み寄るべきだし、設計者も実装を理解すべき。実装者は学ぶことも多いのでQAを置くのもあり。

ペアプログラミングの使いどころ タワーズ・クエスト @t_wada

What

  • driver と navigator でやる。運転手は視野が狭まるよね、という趣旨
  • 先に目標を決める。始める。喋る(どっちも)。お互い何やってるか把握する。喜ぶ。交代する。
    • 5分で交代する、とか。テストとプロダクションを交互に書く、とか。

When

  • 疲れる。1日3hできたらいい方。
  • 新メンバーが入ってきたとき。不具合を修正するとき。新機能を作成するとき (レビューの手戻りを防ぐ)。日、週に決まった時間に。
  • あるチームでは新規機能だと必ずペアプロする、とか。

Why

  • 稼働率よりスループット
    • 良いレビューは手戻り&コミュニケーションコストを生む。じゃあ常にレビューしたらいいじゃん。 by Kent Beck (XP)
    • フィードバックが早い。設計しながらコードを書くので、初期の欠陥に気づける。
      • でかい WIP の PR 出すよりコスパが良い
    • 書き終えたコードを修正するのは気分が良くない。途中で指摘されるとむしろ気分がいい。
  • スキル伝授
    • 結果じゃなく過程が見れる。選ばれなかったものがわかる。
    • コードを書く瞬間の思考にアドバイスをもらえる。他の方法で代替できない。

FAQ

  • コスト倍になるじゃん
    • ペアプロが効くところとそうじゃないところを使いわけよう
    • ペアプロしなかったら入らなかった不具合の修正時間が減る
    • 生産量は倍にはならない。
  • 開発環境が違う
    • Kent Beck 「自分の好みとチームの成功でどっちが大事か考えろ」
    • ErgoDox とペアプロの相性は悪いw
  • 揮発性が高い
    • その二人は満足するけどチームの経験にならないのでは
    • モブプログラミング(3人以上で)
      • 週1回、それぞれが気にかけていた箇所をみんなでやる、とか
  • 上級者側のメリット?
    • 教えることで自分の知識が整理される (ドメイン知識、技術知識の両方)
    • いろんな開発環境に慣れることができる
  • プレッシャーが強い。。
    • 心理的安全が一番大事。
    • どうしても向いてない、って人は2割くらいいる。押し付けは良くない。
  • 「ここは俺が書いた」感が欲しい
    • コードは共有物である、というメリットの真逆。向いてない人はいる。
    • ソロプロはOSS活動に費やす。Write Code Everyday.

Q&A

  • 初心者同士だと効率悪い
  • 上級者同士は効果ある。長〜い PR にならなくて済む。
  • マネジメント層への説明 (コスト2倍になるんじゃないの)
    • 事前に許可をもらうより後で許可をもらう。リファクタリングも同じ。
    • 不具合修正は通りやすい(指差し確認、ダブルチェックと同じ)。

Code IQ 感謝祭メモ

落合陽一さん、澤円さん、ちょまどさん登壇決定!CodeIQ感謝祭~聞いて触って感じるデジタルアートな1日!~ #codeiq39 : ATND

に参加したメモ。全然まとまってない。すみません。

前回までは「第n回」と銘打っていたけど、今回は無いらしい。 落合さん、胡散臭い似非科学者なのかと思ってたけど、マジで凄かった。魔法だった。

落合さん「ミクスドリアリティからデジタルネイチャーへ」

  • 映像から物質を作れないか?
  • 空中にプラズマで3次元に物を作る
  • ホログラム: だいたい間違って定義されてる
  • 超音波で光の反射をいじる
  • 触覚を超音波で再現
  • 目と耳の解像度で世界の解釈が決まる
    • どうやって発展できるか?
  • 空間の一部だけ音がするスピーカー

mixed reality

  • バーチャルと物質の区別がつかなくなる
  • 触らないもの(金魚とか)はデータでいいじゃん
  • 電圧で動く素材
  • 筋肉に電流を流してリズムを学習

今やること

  • VR と AI で筋肉ロボを
  • 介護の自動化、遠隔化
    • おばあちゃんごと動かす
  • メディアアート
  • ファブリケーション
  • 魔術から科学 -> 再魔術化してきてる
    • コンピューターが何をしているのかわからん

naoya さん

  • マネジメントの話
  • いかに正しい問題に取り組むか
    • 問題をどう設定するかで解決策変わるよね
  • issue と problem
    • problem は確定している
    • issue は確定していない

人の性質 (issueから始めよ)

  • 目の前に問題らしきものが現れるとすぐに解こうとしてしまう
  • ある程度やると最後までやりたくなっちゃう

心理的安全性を高めよう」

  • 心理的安全性が高いと働きやすい、は合ってそう
  • 心理的安全性が高いといいプロダクトができる、と言われるとどうか?
  • いいエンジニアを雇っていい環境作れたんだけど、なんだか高揚感がなく、人が辞めていく
  • 心理的安全性と責任はセットで考えよ(責任も高くないと学習しないし、モチベーションを保てない)
  • チームビルディングばかりしてもプロダクトは良くならない
  • プロセスを良くしてからバリューを高める、ではなく、打って出てから、プロセスを良くする
  • 会社がうまくいってない: 「エンジニアの働き方を改善したい」->良くなるのか?
  • 業績が悪くなった -> 人、組織の問題と勘違いしてしまう
  • マネジャーいい兄貴問題
    • 好かれたい
    • 小さい仕事をしてフィードバックを得たい
  • ロジックか、願望か

経験

  • 一休で古いシステムをどうするか問題
  • ツールは新しくなってくけど、レガシーアーキテクチャーに突っ込めない
    • 問題が大きい、リスクも大きい
    • 「どうにかなってくれたらいいな」という願望だった、自分は何もしていなかった
    • 自分もやらなきゃ
  • エンタープライズアーキテクチャーと現行システムの比較、言語化
  • 問題の理解が進むと、現実的な打開策が見えてくる
  • 成果を出すことが目的; マネジメントもするし開発もする

問題にフォーカスする

  • マインドフルネス

HoloLens

  • mixed reality
  • phisical reality に映像を重ねるのが AR
  • バーチャルにあるものを知覚するのが VR
  • phisical と virtual の融合が mixed reality
    • AR と MR の違い。AR: 物に映像を重ね合せる。MR: 物にオブジェクトを重ね合せる(視点によって動的に角度が変わったりする)。リアルとvirtualが干渉しあう。
  • 端末にCPU,GPUが入ってる
  • レンズはシースルー
  • 音響も3D(オープンスピーカーがついてる)
  • CPU:32bit RAM:2GB Windows10で動いてる(ストアアプリ)
  • DirectX と Unity
  • Skype で画面共有して、向こうで丸かいたらHoloLensで丸が見える

澤さん、ちょまどさん

  • C# はいいぞ
  • リバースメンタリング
    • 若い人にメンターをやってもらう
  • 日本はプロのマネージャーが少ない、育てたい : マネジメントとは何か、を若い人に知ってほしい
  • 疲弊したエンジニア
    • 自信を取り戻す何か アウトプットする機会を与える 違う視点から未来を考える アウトプットによってユニークな立ち位置を得る(スーパーエンジニアじゃなくても)
  • エンジニアリングだけで生きてくのはしんどい、今後どんな能力を身につけるか
    • マネジメント:違う価値観を受け入れる

【翻訳】「イベント駆動」と言ったら、あなたは何を指しますか?

この記事は、Martin Fowler 氏の What do you mean by “Event-Driven”? を翻訳したものです。 もともと Serverless Architectures を翻訳しようとしていたのですが長すぎて諦めました。。 イベント実施状態転送 (Event-Carried State Transfer) の訳がイマイチしっくりこない。

(Martin Fowler 氏の許可を得て掲載しています)


去年の年の暮れに私は ThoughtWorks の同僚とともにワークショップに参加し、「イベント駆動」の本質について議論しました。ここ数年で、私たちは沢山のイベントを用いたシステムをいくつも開発してきましたが、それらは時に賞賛され、時にこき下ろされました。私たちの北米オフィスはサミットを開催し、世界中から ToughtWorks のシニアデベロッパーたちが集まってアイディアを共有しました。

このサミットの最大の収穫は、人々が「イベント」について話すとき、実は全く異なるものを指していることがある、と認識できたことです。私たちは、どんなパターンを用いるのが便利だろうかということを明らかにするために多くの時間をかけました。この記事は私たちが結論づけたものの簡単な要約です。

イベント通知 (Event Notification)

これはシステムがイベントメッセージを送信して、同一ドメインにある他のシステムに通知を送るときに発生するものです。イベント通知で大事な要素は、送信元のシステムは実はレスポンスについてあまり気を遣わないということです。全くレスポンスを期待しなかったり、対処するレスポンスがあったとしても、直接的でないこともしばしばです。イベントを送信するロジックのフローと、イベントの反応に応答するロジックのフローが完全に別れていることもあるかもしれません。

イベント通知は疎結合を暗に示し、構築が非常にシンプルであるという点において素晴らしいものです。しかし、様々なイベント通知をまたがるようなロジックのフローがある場合は問題になります。この問題は、どのプログラムも明示していないフローを確認するのが困難なことがある、ということです。このフローを確認するほぼ唯一の方法として、実際のシステムのモニタリングがあります。これはデバッグやフローの変更が困難かもしれません。危険なのは、スケールの大きいフローが見えなくなってしまうということを認識せずに、イベント通知でシステム分離を容易に行えてしまえるために、数年後に困ったことになるということです。このパターンは非常に便利ですが、罠にはまらないよう気をつける必要があります。

この罠の簡単な例として、イベントが受動攻撃的なコマンドとして用いられる場合があります。イベント送信元システムが受信者に対して何らかのアクションを実行してもらうことを期待するとき、その意図を表すためにはコマンドメッセージを用いるべきにも関わらず、メッセージをイベントとして位置づけているような場合です。

イベントは大量のデータを保持する必要はなく、多くの場合、ただいくつかの ID 情報と、より多くの情報を求められるように送信者へのリンクさえあれば十分です。受信者は変更されたことを知り、その変更の本質の最小限の情報のみを入手できますが、送信者にリクエストを発行し、次に何をすべきかを決定します。

イベント実施状態転送 (Event-Carried State Transfer)

このパターンは、システムのクライアントを更新する際、 次の作業を行うためにサーバーに通信させずにアップデートを実現したい場合に現れます。顧客管理システムの場合、 変更データの詳細を含むイベントによって顧客が詳細情報 (住所など) を変更したら、その都度イベントを発火させるかもしれません。イベントの受信者は自身の顧客データのコピーを変更内容で更新することができるので、次の動作のために大本の顧客システムに通信する必要がありません。

このパターンの明らかな欠点は、大量のデータが動き回り、また大量のコピーが発生することです。しかしこれは豊富なストレージのある時代では問題にはなりません。顧客システムが利用不可になっても受信側のシステムは機能するため、より強い障害許容力が得られます。顧客情報へアクセスが必要なリモート呼び出しが不要なため、レイテンシーも低下します。全てのクライアントシステムからの要求に答える顧客システムへの負荷を気にする必要もありません。しかし、追加の情報が必要になったとき送信者に問い合わせるだけでも全ての状態を維持、整理する必要があるため、受信側に複雑性をもたせてしまうことになります。

イベントソーシング (Event Sourcing)

イベントソーシングの核となる概念は、システムの状態に変更を与えたら、その都度状態の変更をイベントとして記録し、イベントを再処理することで、将来的にいつでも自信を持ってシステムの状態を再構築できる、というものです。イベントストアは重要な情報源であり、システムの状態は、ただそれのみによって派生します。プログラマーにとって、最も良い例はバージョン管理システムです。全コミットのログがイベントストアにあたり、ソースツリーのワーキングコピーがシステムの状態にあたります。

イベントソーシングは多くの課題があります。ここでは踏み込みませんが、よくある誤解について焦点を当てたいとおもいます。イベント処理は非同期である必要はありません。ローカルの git リポジトリをアップデートするケースを考えてみましょう。Subversion のような集中型バージョン管理システムをアップデートする場合と同様に、完全に同期的な操作になります。実際、これらの全てのコミットによって、あらゆる種類の興味深い振る舞いを行うことができます。 git は素晴らしい例ですが、その核であるコミットは根本的にシンプルなアクションです。

もう一つのよくある誤解は、イベントソーシングのシステムの登場人物は誰でもイベントログを理解、アクセスして、有用なデータを決定すべきである、という考えです。しかしイベントログの知識は制限可能です。私はこの記事をあるエディターで書いていますが、エディターはソースツリーの全コミットについて何も知らず、ただディスクにファイルがあると想定しています。イベントソースシステムでの多くの処理は有用なワーキングコピーに基づいて行わせることができます。イベントログは、その情報を本当に必要とする要素のみが扱うことができるようにすべきです。もし役立つのであれば、異なるスキーマで複数のワーキングコピーを保持することもできます。が、通常は主処理とイベントログからのワーキングコピーの派生処理は明確に区別されているべきです。

イベントログを用いて処理を行う際、ワーキングコピーのスナップショットを構築しておくと便利なことがよくあります。これによって、ワーキングコピーが必要になったときに毎回はじめから全てのイベントを処理する必要がなくなります。実は、ここには二元性があります。イベントログは変更のリストとも、状態のリストとも見ることができます。一方から他方を派生させることも可能です。バージョン管理システムは、最高のパフォーマンスを得るために、スナップショットとイベントログの差分を混ぜることがよくあります。 *1

イベントソーシングは多くの興味深い利点があります。それはバージョン管理システムの価値を考えればすぐにわかります。イベントログは強力な監査能力 (会計取引であれば預金残高のイベントソースになります) をもたらします。 イベントログをその時点まで巻き戻せば、過去の状態を再生成することができます。巻き戻す際に仮のイベントを差し込めば、異なる履歴を探すこともできます。イベントソーシングによって、 Memory Image のように、永続性のないワーキングコピーを保持することが自然になります。

イベントソーシングには欠点もあります。イベントの巻き戻しが、その結果が外部システムとのインタラクションに依存する場合に問題になります。この場合、イベントのスキーマの変更をいかに扱うか、時間をかけて明らかにする必要があります。イベントの処理がアプリケーションに多くの複雑性をもたらすことに多くの人が気づいています (しかし私は、ワーキングコピーを派生させるコンポーネントと主処理を行うコンポーネントの分離が甘さの方が、複雑性をもたらすことに強く影響を与えているのではないだろうか、と思っています)。

CQRS

コマンドクエリ責任分離は、情報の読込と書込のためのデータ構造を分離するという概念です。CQRS は厳密にはイベントのことではありません。設計にイベントが全く現れなくてもCQRSを使用することはできるからです。しかし、一般にCQRSは先述のパターンと組み合わせて用いられるため、非常に重要です。

CQRSが有用であるという理屈は、複合的なドメインにおいて、一つのモデルが読込と書込の両方を行うと非常に複雑になりますが、モデルを分離することでシンプルにすることができるということです。これは特に、アクセスのパターンが異なっている、例えば読込が多いが書込はほとんど無い、といったときによく起こります。しかしCQRSを使用する際は、分離されたモデルをもつことで複雑さが増えてしまう、ということに対してバランスをとって行わなければなりません。私の同僚の多くはCQRSが時として誤って用いられることに気づき、CQRSをかなり慎重に使用しています。

これらのパターンを理解する

ソフトウェアの植物学者になったつもりでサンプルを収集したいのですが、この地形が複雑であることに気がつきました。あるプロジェクトで、優秀で経験豊かなプロジェクトマネージャーが私に告げました。イベントソーシングは災害であると。どんな変更も、読込と書込の両方のモデルを更新するという二重の作業が発生するのだから、と。この言葉によって、私はイベントソーシングとCQRSの潜在的な混同に気づくことができました。この問題の原因がどちらにあるか、どうやったら明らかに出来るでしょうか?このプロジェクトのテックリードは、主要な問題は非同期通信であると主張しました。これは確かに複雑性を助長するものとして知られています。しかし、イベントソーシングとCQRSのいずれにとっても必要なものではありません。さらに、これらのパターンは適切な箇所では良く作用し、不適切な箇所では悪く作用するということに注意しなければなりません。しかし、これらのパターンを混同してしまうと、適切な地形がどういったものなのかがわからなくなってしまいます。

私はこの混乱を解消するような論文を書き、それぞれのパターンをどう実現するか、どういったときに使われるべきなのかに関する強固なガイドラインを用意したいと思っています。しかし残念ながらその時間を割くことができていません。この記事が役立てばよいのですが、本当に必要なことを満たせていないことには注意していただきたいです。

参考文献

2006年にさかのぼり、私は P of EAA book の続刊を作成しようと、いくつかのプロトパターンを書いていました。残念ながら、10年経ってもこの仕事を続ける時間はありませんでした。しかし、このとき書きためたものが、ここで読むことができるようになっています。イベントについては、私は Focusing on Events から始めました。これは私の当時のイベント使用に対する考えを要約したものです。月日が経ったものの、ここで書いたものも多くは未だに正当だと思っています。

これらの記事に最も影響を与えたのが Event Sourcing です。これははじめに、過去の、または異なる状態を形成するために巻き戻しを用いる価値について説いています。

Event Collaboration の記事は、イベント通知とイベント実施状態転送のパターンについて触れていますが、両者が混在しています (両者を分けることを考え出したのは今回のワークショップからでした)。

CQRS についての bliki ポストもあります。

Web にはこれらのトピックに関するたくさんの素材があるので、それらを探すのは楽しいことです。ここでは、それらに目を通しておすすめをピックアップする時間が取れなかったため、コメントは避けておきます。

*1:git はファイルとツリーの状態を .git/objects に保存するためイベントソーシングの例ではない、ということを耳することがあります。しかし、システムが変更やスナップショットをその内部ストレージを使うかどうかは、それがイベントソーシングであるかどうかには関与しません。 Git は幸せなことに、必要なときに変更のリストを提示してくれます。またデータをパックファイルに圧縮する際、パフォーマンス上の理由で、スナップショットと変更を組み合わせています。

目的を意識していますか

会社の新人くんから、「常に目的を意識していますか?」と聞かれた。

そのときは「している時もあるし、していない時もある」と答えたが、振り返ってみるとなんだかすっきりしないので一人で考えた。

 

この問いは、(私にとっては)二つの観点があると気づいた。

 

1. 何か行動する時、目的を決めるか。

2. 本当に「常に」目的を意識しているか。

 

時系列としては 1. → 2. なのだが、先に説明しやすい 2. について述べる。

2. はどういうことかというと、そもそも、本当に「常に」何かを意識することはできるのか、という問いにつながる。

少なくとも私はできない(そんなに脳のメモリがない)と思っているので、常には意識していない、という答えになる。

なので、目的を持つとすれば、まず目的を決めて、それに向けて行動する(この時は目的を意識していない)、というスタイルをとることになる。

ポモドーロテクニックになぞらえると分かりやすい。5分間で目的を決めて、25分間で、それに向けて行動するのだ。

実際の仕事では、これが階層を成す。タスクの目的はプロジェクトの目的を達成するためであり、それは事業の目的を達成するため、そして企業のビジョンへとつながる。当然、かける時間は長くなる。目的が誤っていた時のリスクも大きくなる。

 

1. の問いに戻る。 2. に関して、「目的を持つとすれば」、まず目的を決めて、それに向けて行動する、と述べた。いま注意したいのは、目的を持たなくても行動することができるということだ。

私は、目的を持っていなくても行動して良いと思っている。なので、必ずしも目的を決めない、という答えになる。

なぜか。私は常に先を見通して適切な目的を設定できるほど優秀な人間じゃないからだ。

ヒューリスティックを見出すよりも、ランダムウォーク的に、気まぐれに事をこなした方が、結果的に良い解をもたらすことがあるのは、アルゴリズムだけでなく現実も同様だ。

加えて、それまで自分では知りようがなかったことに触れるチャンスにもなる。

世間では「手段と目的が入れ替わってはいけない」は金科玉条とされる。しかし、目的を容易に決められないときなどは、手段が先にあってもよいと、私は思う。

 

ということで。私は「常には」目的を意識していない。目的は行動する前に決める。ただし、目的を決めずに行動することもある。

JavaScript で連続値からカラーコードに変換する

Number の値から赤さを変えたいことがあったので書いてみた。

Number.prototype.toString(radix) なんてあるのね。便利。

でも線形だとイマイチな気もする。あと真っ赤になるのも芸がない。

jsfiddle.net

[ASP.NET MVC] Controller から Json を Camel Case でシリアライズして返す

C#
public class User {
  public string Id { get; set; }
  public string Name { get; set; }
}

public class DefaultController : Controller
{
  [HttpGet]
  public ActionResult GetPerson()
  {
    IEnumerable<User> users;

    // DB からとってきたりする

    return Json(users.ToArray(), JsonRequestBehavior.AllowGet);
  }
}

このとき、Response の Json のプロパティ名はクラスのプロパティ名が引き継がれるので Pascal Case になってしまう。

[
  {
    Id = 'hoge',
    Name = 'fuga'
  },
  ...
]

JavaScript 側では Camel Case で処理したいことが多いのでイマイチだ。 簡単な方法は 2 つある。まずは匿名オブジェクトに変換してから返すというもの。

var json = Json(users.Select(x => new
  {
    id = x.Id,
    name = x.Name
  }).ToArray(), JsonRequestBehavior.AllowGet);
return json;

もう一つは JsonConvert を使うというもの。

var jsonSerializerSetting = new JsonSerializerSettings
  {
    ContractResolver = new CamelCasePropertyNamesContractResolver()
  });
var json = JsonCovert.SerializeObject(users.ToArray(), jsonSerializerSetting)
return json;

ちなみに、 ApiController なら Web アプリ単位で設定を持てるらしい (Application_Start() で指定する)。

参考

画像の解像度を変換する

C#

【注意】画像エンコードのことは全然詳しくないので、本質的に正しいやり方なのか不明。

System.Drawing.Image で読み込んで .SetResolution してもいいのだが、

var image = Image.FromFile(path);
image.SetResolution(dpiX, dpiY);

System.Drawing は ASP.NET で非推奨らしい (メモリリークするとかいう噂) ので、 Windows Imaging Components を使う。

void Encode(Stream fromBitmapStream, Stream toBitmapStream, double dpiX, double dpiY)
{
  var decoder = BitmapDecoder.Create(fromBitmapStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
  var frame = decoder.Frames.First();

  var stride = frame.PixelWidth * 4; // 1 ピクセルあたり 4 バイト
  var pixelData = new byte[frame.PixelHeight * stride];
  frame.CopyPixels(pixelData, stride, 0);

  var source = BitmapSource.Create(frame.PixelWidth, frame.PixelHeight, dpiX, dpiY, frame.Format, frame.Palette, pixelData, stride);

  var encoder = new JpegBitmapEncoder() { Frames = { BitmapFrame.Create(source) } };
  encoder.Save(toBitmapStream);
}

PresentationCore と WindowsBase の参照が必要。で using System.Windows.Media.Imaging; する。 ちなみに BitmapDecoder とかいってるけど Jpeg でも可。

参考