社内ドメインモデリング・ワークショップを開催しました

マーベリック技術広報のリチャード伊真岡です。8月26日月曜日に弊社内でドメインモデリング・ワークショップを行いました!当日の様子を紹介します。

f:id:maverick-techblog:20190903131621p:plain

題材

今回は映画館の券売・発券システムを題材に以下のような架空の設定を元にワークショップを進めました。

https://github.com/richardimaoka/ddd_hanson

ある映画館ウェブサイト https://cinemacity.co.jp/ の券売システムと、映画館においてある券売機システムを統合することになりました。我々はその統合システムの分析・開発をするプロジェクトを任されました。チケットの購入から発券にまつわるルールと業務フローを分析・モデリングしましょう。

準備段階当初はツイッター上で盛り上がった #チケット料金モデリング を参考にワークショップを行うつもりでした。しかし私個人の好みもあり、今回に限ってはチケット料金モデリングだけを扱うよりは、券売システム全体を考えるほうがドメインモデリングの醍醐味を味わえるのではないかと考え、上記のような題材を設定しました。

ユーザーストーリー分析

いきなりドメインモデリングに入る前にチケット販売・発券の業務フローを理解するためユーザーストーリー分析を行いました。理解が深まった後にドメインモデリングを行った方が議論がスムーズになるだろうと考えたからです。

こちらはユーザーストーリー分析で貼った付箋のすべてです。

f:id:maverick-techblog:20190903131654p:plain

  • 見たい映画を決める(スタート)
  • シアターの席に座る(ゴール)

という2つの時点を定め、それらをつなぐ動作(水色の付箋)を洗いだす事から始めていきました。

手法の詳細は省略しますがオライリーの「ユーザーストーリー・マッピング」という本に載っている印象的な言葉を紹介します。

  • ストーリーを使う目的は、良いストーリーを書くことではない
  • ストーリーを作る本当の目的は、共通理解をつかむことだ

以下の画像は書籍「ユーザーストーリー・マッピング」から引用したものです。左上にあるようにみんなが「合意できた」と思ったことも、よくよく話してみるとそれぞれが違ったことを考えていたということがあります。そういった認識の齟齬を防ぐため、話し合いを通してほんとうに共通した理解を得られるようにすることが重要だということが書籍では語られています。

f:id:maverick-techblog:20190903131915p:plain

私リチャードはすっかりこの考えに感化されてしまい、ワークショップでも10回以上共通理解、共通理解と繰り返す人になっていました。若干めんどくさい人ですね。

ドメインモデリング

ワークショップの後半はいよいよ本題であるドメインモデリングにみんなで取り組みました。ユーザーストーリー分析から「オブジェクト」を抜き出し、どの属性がどのオブジェクトに属するか議論をしていきました。

https://cinemacity.co.jp/ticket/ を見ていただくと料金体系だけでもなかなか複雑であることがわかるかと思います。今回の題材はチケット料金の計算ロジックをコードに落とし込めばよいというわけではないので「チケット料金計算に必要な属性を全部パラメタとして突っ込んで力技で金額を返すメソッド」を実装すればよいわけではありません。券売システム全体を考えどのオブジェクトがどの属性をもつか設計しなくてはなりませんでした。

ドメインモデリングを始めると議論は盛り上がり、以下のような点をはじめとしていい意味で意見が割れ、議論を深めるに連れ券売システムというドメインにたいして理解が深まっていきました:

  • 映画を見る場所をなんと呼ぶ?シアター?スクリーン?
  • 映画館オブジェクトはチケット販売システムには不要なんじゃない?
  • 18歳未満は見られない映画がある
    • R18指定の映画がある
    • 東京都の条例により、18歳未満の方は、終映時刻が23:00を過ぎる回は、保護者同伴の場合でも入場はできない
  • 料金はメソッドの戻り値として計算されるべきじゃないか?
    • いや計算された値は固定されないと支払い後料金が変わるのはおかしい
  • チケットの「予約オブジェクト」をつくろう
    • 「予約オブジェクト」は「チケット」と同一なのではないか?
    • いや、一回の予約で一人が友人の分もまとめてチケットを予約するかも

議論が白熱する中、何度か洞察の鋭い意見を出していた参加者の一人がチケットの券面のスクリーンショットをみつけました。項目が多い…!

f:id:maverick-techblog:20190903132047p:plain

これらすべてを「チケットオブジェクト」に結びつけてしまうと大変な巨大オブジェクトが出来上がってしまうので、できるだけきれいにしようとしたのがこちら。

f:id:maverick-techblog:20190903132416p:plain

オレンジの付箋はオブジェクト名、水色の付箋はオブジェクトの属性、黄色はメソッド(時間がなくて網羅できませんでした)、そしてピンクの付箋は疑問点やモデリングが複雑そうな項目を忘れないようにメモとして残したものです。

感想

複数人で議論を深めながら「映画チケット発券」に対する共通理解を育てていくというのが体験を伴って学べたのが何よりの収穫でした。

今回はユーザーストーリー分析とドメインモデリング含めて3時間だったので、ドメインモデリングが完了するところまでは想定しておらず、またソースコードに起こす時間もとっていませんでした。個人的にはあとでソースコードを書く時間をとって考察を深めてみるつもりです。

実際の業務のなかでドメインモデリングを活かすにはソースコード、ドメインモデル、さらにはユーザーストーリーも含めてなんども行ったり来たりしながら議論を深めて共通理解を育てていくのが良いのかなと思います。

参加者からも好評だったようで第2回社内ドメインモデリング・ワークショップをいま計画中です!

atWareさんで出張Akkaワークショップを行ってきました

マーベリックの技術広報リチャード伊真岡です。

今回横浜にあるatWareさんのオフィスでAkkaワークショップで行ってきました。atWareさんはScalaMatsuriのスポンサーやScala先駆者インタビューなど様々な活動を行い会社としてScalaコミュニティ、その他技術コミュニティの発展に貢献されています。またかとじゅんさんを講師として招いてドメインモデリングワークショップAkkaハンズオンも開催するなど社内での技術教育・啓蒙にも力を入れています。

今回はatWareさんに私の知り合いがいたことから実現したワークショップ。私が以前にOSS貢献をしていたころの経験談と、それから私の得意分野であるAkkaについてお話しさせていただきました。

さてこちらはatWareさんのオフィス。WeWorkオーシャンゲートみなとみらい内にあり、とてもキレイなオフィスでした。

f:id:maverick-techblog:20190828123819p:plain

前半はOSS活動について。私リチャードはakkaというJava/ScalaのOSSに100件ほどコントリビュートしたことがあるので、その時の経験をもとにOSS活動に対して私が持っている心構えを紹介しました。私自身の考えをお話しましたが、とはいえOSS活動というのは人それぞれの形があるので、GitHubにpull requestを送らなくてもOSSの普及や発展に少しでも間接的であっても貢献できればそれは立派なOSS活動だと私は思います。atWareの皆さんにはOSSにすでに貢献したことがある方もいましたし、今後のOSS活動に意欲的な方がいたようなのでそれぞれのみなさんが満足のいくOSS貢献の形を見つけていただければ嬉しいです。

f:id:maverick-techblog:20190828123926p:plain

後半はAkkaについて。よくある「Akka入門」という話に終始せず、より踏み込んだ中級者向けの内容になるように意識しました。

akkaはすでにモジュールの数が多く「なぜこんなに沢山あるのか…」と感じてしまうかもしれませんが、akkaの発展の歴史を振り返ればそれぞれのモジュールが当時その時点で課題となったことを解決するために作られたことがわかります。その歴史を把握することで各モジュールの関係性が明確になるのではと考え今回の内容に組み込みました。

それから私見とLightbend社のFast Data Platform構想を交えて「Akkaを導入するにはどういうパターンがあるか?」という点にまつわる話もしました。Akkaは学習負荷が小さくはないツールなので、Akkaの全てのツールを取り入れてシステムを作るのは苦労する面があるとおもいます。そこで最初からAkkaを最大限活かす方向性の導入方法と、部分的・あるいは段階的にAkkaを取り入れるパターンについて紹介しました。

とはいえせっかくAkkaに興味をもってくれたなら、やはりその良さを最大限活かすAkka actor + persistence + cluster-sharding を使ったフルパワー(?)構成で使うAkkaの力を知ってほしいと思っています。そこでいずれAkka Clusteringハンズオンをやりたい、そこで練習をとおしてAkkaの真の実力を体感してほしいというお話をしました。

勉強会の後は懇親会を開いていただきました。VimConfスタッフをしているasanoさんと話してカンファレンス・技術コミュニティ話で盛り上がったのですが、atWareさんは2017年から継続的にVimConfのスポンサーをしていて2018年は唯一のプラチナスポンサーだった会社です!Vimユーザの皆さんにはとても頼もしい会社ですね!

vimconf.org

今回の勉強会について楽しく振り返ることができ、また今後私が技術広報として企画していきたいことについても相談に乗っていただき非常に有意義でたのしい一日でした。atWareさんとマーベリックの絆も深まったことでお互い技術コミュニティに今後一層貢献していきたいと思います。

マーベリックのDSPプロダクトSphereのバックエンド技術構成

マーベリック技術広報担当のリチャード伊真岡です。

今回は弊社のDSP(Demand Side Platform)プロダクトであるSphereバックエンドの技術構成を紹介いたします。Sphereも弊社のもう一つのプロダクトであるCirquaと同様、バックエンドはScalaで書かれています。

採用技術: Scala, Finagle, PlayFramework, ScalikeJDBC, MariaDB, Redis, Kafka, Spark, HDFS, 等

DSPとは

DSPとはDemand Side Platformの省略で、広告枠を「要求する・買う」側つまり広告主のためのサービスです。DSPと対になるサービスがSSP、Supply Side Platformと呼ばれこちらは広告枠を「供給する・売る」側、つまりWebサイトやアプリを運用するメディア側向けのサービスです。

どちらがDemandでどちらがSupplyかわかりづらいかもしれませんが、アドテクノロジーの世界では商品としての広告枠に対してのDemandとSupplyという意味でDSPとSSPという呼び方になっています。

DSPとSSPは別の会社が運営する全く別のサービスの場合もありますが、中には一つの会社がDSPとSSP両方のサービスを運営していることもあります。

さて、DSPとSSPがどう連携しているかをお見せするためにこちらをご覧いただきたいと思います。弊社デザイナ坂東とエンジニアが協力して作成しScalaMatsuri期間中に公開した「あなたのブラウザに広告がでる仕組み」です。この記事では簡単のためADNW(アドネットワーク)に関しては説明しませんが、DSPとSSPが連携することによって広告主の出向した広告がメディアの広告枠に表示される様子を見て取れるかと思います。(今回はアニメーションで表現していますが実際にはLEDデバイスを経路に沿ってひからせるIoTデバイスとして制作しました。)

f:id:maverick-techblog:20190819120115g:plain

Sphereの処理の流れ

DSPとSSPが連携して広告表示する場合、メディアの運営するWebページの広告枠に対してオークションが行われて表示される広告が決定されます。そのオークションに関わる処理の流れをSphereの視点から詳しく見ていきましょう。

f:id:maverick-techblog:20190819121252p:plain

まず、訪問者がメディアの運営するWebサイトを閲覧すると、SSPに対して広告要求が送られます。Sphereは入札サーバを通してSSPから入札要求を受け取り、入札要求に付属するデータに基づいて入札に参加するかどうかを自動で判断します。そして参加する場合入札サーバはSSPに対して入札を送信します。

f:id:maverick-techblog:20190819121334p:plain

ここでSSPはSphereにだけ入札要求を送るのではなくオークションを行うため複数のDSPサービスに対して入札要求を送っています。各DSPサービスはSphereと同様に入札参加すると判断した場合に入札をSSPに対して返します。

f:id:maverick-techblog:20190819121359p:plain

Sphereが広告枠を落札できたときはSphereから送信された広告が表示されます。ただし広告の画像は入札データの中に含まれるのではなく、Sphere内の別の画像配信サーバーから読み込まれます。 アドテクノロジーの世界では広告が表示されたことを「インプレッション」とよび計測の対象としています。Sphereの場合広告に含まれるタグによってトラッキングサーバにインプレッションのデータを送り、さらに訪問者が広告をクリックしてリンク先の広告主のページに遷移したら「広告クリック」を計測します。インプレッションや広告クリックなどの広告効果測定のためのデータはすべてトラッキングサーバからKafkaに送られ、その後HDFSに保存されます。 この記事では詳しく説明しませんが、Sphereの機械学習システムはこのHDFS上のデータに対してSparkジョブを走らせることが出来、その結果が広告配信の最適化などに利用されています。

Sphereの技術構成

ここからはSphereの技術構成を紹介します。

f:id:maverick-techblog:20190819121449p:plain

入札・トラッキングサーバはScalaで実装されていて、そのバックエンドにはRedis、さらにScalikeJDBCを通してアクセスするMariaDBがあります。また先程述べたように、トラッキングサーバーからは広告効果測定のためのデータがKafkaへ送られています。機械学習システムについてはこの記事では大まかにしか触れませんが、いずれ別の形で詳しく紹介するつもりです。

f:id:maverick-techblog:20190819121532p:plain

入札サーバはおよそ60インスタンス、トラッキングサーバはおよそ30インスタンスが同時に走っています。これらSphereのサーバー群はほぼ全てオンプレミスのデータセンタ内に配置されていて、機械学習用のインスタンスなどを含めると全体でのサーバーの数は約270台にもなり、そのサーバー郡の監視にはZabbixを利用しています。

実際にはこの記事で紹介する以外にも様々な処理が行われており、機械学習システムがバッチ処理の結果をMariaDBに書き込むケースも有ります。複雑なビジネスの要求に答えるため年月をかけて注意深く実装されたシステムがSphereの面白いところだと思います。

バックエンドはScala!インフィード広告プロダクトCirquaのバックエンド技術構成を紹介します

マーベリック技術広報のリチャード伊真岡です。

今回は弊社のインフィード広告プロダクトCirquaの技術構成及び技術的課題の一部を紹介したいと思います。CirquaのバックエンドはScala、フロントエンドはTypeScriptで書かれており、今回の記事ではバックエンドの紹介をします。

採用技術: Scala, Finagle, PlayFramework, ScalikeJDBC, Amazon RDS(MariaDB), Amazon ElastiCache(Redis), Fluentd, Amazon S3, Amazon Athena 等

Cirquaの仕組み紹介

Cirquaはインフィード広告と呼ばれる種類の広告を主に扱うプロダクトです。

f:id:maverick-techblog:20190801145339p:plain

インフィード広告とはSNSのニュースフィードに代表されるようなタイムライン状に表示されるコンテンツの中に表示される広告を指していて、「フィード」の「中」に表示されるので「インフィード広告」と呼ばれています。

技術構成の紹介の前に、まずCirquaの仕組みを簡単に紹介したいと思います。以下では訪問者がCirquaを導入しているメディアのWebサイトを閲覧したときの動作を簡略化して説明します。

f:id:maverick-techblog:20190801145324p:plain

訪問者がWebページを閲覧すると、ページのHTMLに埋め込まれたCirquaのScriptタグが読み込まれます。そのScriptタグによってマーベリック側のネットワークにある広告配信サーバから広告を取得しWebページ内にインフィード広告が表示されます。

f:id:maverick-techblog:20190801145345p:plain

インフィード広告が表示された時点で訪問者が広告を表示したことがカウントされ、それをアドテクの世界では「インプレッション」とよんで計測しています。インプレッションの発生はトラッキングサーバに送信され、更に訪問者がその広告をクリックして広告主のウェブサイトへ遷移した場合その「クリック」をトラッキングサーバに送信しそれも計測しています。

またトラッキングサーバ側は集計処理も行うので以下のデータ集計用のフローにもつながっています。 計測、集計したデータは機械学習チームにも渡され、広告配信の配信ロジックに利用されます。

f:id:maverick-techblog:20190801145343p:plain

Cirquaのバックエンドで採用している技術スタックを以下のように図示してみました。Webページから送信されたインプレッションとクリックのデータはfluentdを介してAmazon S3に送られ、バッチ処理が定期的に走ってAmazon Athenaを用いて集計しています。Amazon Athenaを使うとS3にため込むデータの形式さえ整えれば集計処理が手軽にできるので運用はとても楽です。

Cirquaバックエンドの技術スタックを以下のように図示してみました。

f:id:maverick-techblog:20190801145352p:plain

広告配信サーバはScalaで書かれており、非同期処理部分はFinagleを用いて実装しています。HTTPのRequest/Responseのパラダイムに従って素直に非同期処理が書ける点がCirquaチームがFinagleに感じる魅力です。トラッキングサーバはPlayFrameworkを使っています。このFinagleとPlayFrameworkの使い分けはチームの両フレームワークに対する慣れや過去のプロダクト開発における知見の積み重ねなどから総合的に判断して使い分けをしています。バックエンドのデータベースはRDS(MariaDB)を使っていてScala側からはScalikeJDBCを使って接続しています。ScalikeJDBCはSQLを素直に書けるところが使いやすいライブラリだと感じています。

バッチ処理については先進的な試みとして一部でScala ZIOを取り入れています。Scala ZIOは関数型を活かしつつもオブジェクト志向プログラマにも馴染みがあるDependency Injectionを取り入れており新たに学ぶ概念が少なくわかりやすいとされています。非同期処理がきれいに書けるところがとても良いと感じています。バッチ処理は広告配信サーバとトラッキングサーバ本体とは切り離されているのでScala ZIOの導入がしやすく、まずはバッチ処理から取り入れてみることにしました。

開発チームの構成

Cirqua開発チームの構成は:

  • バックエンドエンジニア2人
  • フロントエンドエンジニア3人
  • プロダクトオーナー1人

となっており、これ以外にインフラエンジニアとCirquaを含む複数プロダクトのサーバーやネットワークを管理し、Quality Assuranceチームが同じように複数プロダクトを担当しています。

Ciruquaチームでは毎週のリリースをdevelop環境は木曜、production環境は月曜日にリリースを行っています。 develop環境のリリース後はQuality Assuranceチームを交え全員で画面を触り、新機能のチェックを行います。 こうすることで常にチーム全員がプロダクトの新機能、いつどの機能が入ったかなどを把握できる状況を作っています。

リリースはslack botから実行できるよう自動化されています。少人数チームではContinuous Deliveryの仕組みは必須ですね。

今取り組んでいる技術的課題

現在CirquaのインフラについてはAmazon EC2上でそのままプロセスを走らせる形からKubernetesを使った運用に移せないか検証を行っている最中です。もちろん導入が上手くいけばKubernetesエコシステムを活かしたインフラ運用、そしてアプリケーションエンジニアがインフラ運用の一部を担当できるというメリットを狙ってのものですが、なによりKubernetesを触るのはエンジニアとして楽しいですよね!Kubernetesに伴う負担を可能な限り軽減しつつ、楽しさを存分に活かせる導入方法を現在模索中です。

さらにCirquaシステムは一部リファクタリングを行っており、Domain Driven Design的な設計手法を取り入れてアプリケーションのコア部分を書き直しています。scala言語の表現力の高さを活かし、コアドメインを宣言的かつ表現力豊かに再定義することができています。チームメンバは社内で開催されているDomain Driven Design読書会にも参加し、Domain Driven Designに対する理解を深める努力を行っています。

Lens の実用例

ご無沙汰しています。最近ヒトカラがマイブームのあおいの(@aoiroaoino)です。
そういえば ScalaMatsuri 2016 のスポンサー LT でこんなこと言っていたのを思い出しました。

「弊社では Lens(Monocle) を test で使用しています。」

今回はこれの話をしようと思います。

続きを読む

0.7以降のmsgpack-javaを使って古いフォーマットでシリアライズする方法

こんにちは、chaltosです。

今回は、msgpack-javaのバージョンを0.6.Xから上げたいが0.6.Xと同じフォーマットでシリアライズしたい場合の対処についてです。

MessagePackとは何なのかといった部分は省略させていただきます。

続きを読む

JVMのバイトコードの実行時最適化について発表してきた

こんにちは、todeskingです。

ScalaMatsuri 2016将軍スポンサーが合同で開催した「Scala将軍達の後の祭り」 というイベントで、バイトコードの実行時最適化について発表してきました。

抽象化によってオーバヘッドが存在するコードを実行時にバイトコードレベルで最適化すれば、抽象化とパフォーマンスが両立出来てお得、という夢のある話です。

以下、補足など。

続きを読む