ユニファ開発者ブログ

ユニファ株式会社システム開発部メンバーによるブログです。

SQS + Shoryukenのメッセージ重複配信問題にMiddlewareで対応する

まだ鍋シーズン序盤だというのに、ごま豆乳鍋を3日に1回は食べているWebエンジニアの本間です。

最近、Railsアプリケーションのバックグラウンドジョブのworkerとして Amazon SQS, Shoryuken, Active Job を組み合わせて使うことが増えました。 過去にも以下のようなエントリを書いてます。

tech.unifa-e.com

今回は、Shoryukenを使ったバックグラウンド処理を実運用で使用するにあたって1つ悩ましい問題があり、それをMiddlewareを使って解決した話をご紹介します。

続きを読む

心理的安全性がもたらす効果と、安全性を阻害するBadパターン

こんにちは。スクラムマスターの渡部です。

最近出版された「心理的安全性のつくりかた*1」という本が、発売から2ヶ月経たずに4版決まった*2り、Tech系カンファレンスでも心理的安全性についてのセッションがあって*3かなり盛り上がったりと、心理的安全性機運の高まりを感じている昨今です。

当然(?)ながら僕も「心理的安全性のつくりかた」を読んで、短期的にも長期的にも今後のふるまいを見直す良いきっかけになりました。

ただ、いかんせん「心理的安全性ってわかりにくい言葉だなぁ」という感想は今でも変わっていないので、備忘的な意味で次の2つのことをブログに残したいと思います。

このブログで扱うこと

  • そもそも、心理的安全性ってなに?どんな効果があるの?
  • 心理的安全性を阻害するBadパターン

このブログで扱わないこと

  • 心理的安全性を構成する4つの因子の詳細
  • いかにして心理的安全性を高めていくか?

これらは書籍「心理的安全性のつくりかた」を参照していただくか、どこか別の機会で「ユニファにおける取り組み」などをご紹介できればいいかなぁと思っています。

心理的安全性について

そもそも、心理的安全性とは何か?

心理的安全性は、Google の調査結果によってビジネスの世界で一気に広まった概念です。(Googleが定義したものではありません)

rework.withgoogle.com

本来の定義としては「チームの中で、対人関係におけるリスクをとっても大丈夫だ、というチームメンバーに共有される信念のこと*4」とされています。

若干難しいので、本の中で紹介されてる次の考え方がわかりやすくて僕も好きです。

一言でいうと「メンバー同士が健全に意見を戦わせ、生産的で良い仕事をすることに力を注げるチーム・職場のこと*5

心理的安全性の効果

定義はなんとなくわかりましたが、結局、それがあることでどんな効果があるのかがわからないと、興味もわかないですよね。

Googleによれば、以下の説明がありました。

  • 効果的なチームには、心理的安全性を含む5つの因子が関係していた
  • 心理的安全性は、他の因子の土台となるために圧倒的に重要だった
  • 心理的安全性が高いチームには、以下の特徴があった
    • 離職率が低かった
    • 収益性が高かった
    • 「効果的に働く」とマネージャーから評価される機会が2倍あった

「ふむふむなるほど、心理的安全性があると効果的に働けるんだな!」ということはざっくりわかりますね。

ただ、どんな理屈で効果的に働けるのか?はまだちょっとわかりにくいですよね。

それについて、「心理的安全性のつくりかた」では、以下のように解説されていました。

心理的安全性が効果的な主な理由
  • 心理的安全性があることにより、チーム内で情報が積極的に共有されるようになったり、意見の衝突頻度が増えるようになる。それによりチームが学習していくことで、パフォーマンス向上へ繋がる。
  • 心理的安全性があることにより、タスクにおいて意見の衝突が起こるようになる。(いまやるべき?その方法だとこんな問題があるよ。etc)その結果、イノベーションやプロセス刷新が促され、パフォーマンス向上へ繋がる。

心理的安全性は、チームや組織の学習や、イノベーション・プロセス刷新に寄与することで、最終的にパフォーマンス向上に繋がるということです。

「どうにかしてパフォーマンスを向上させていきたい」という場合には、心理的安全性向上を視野に入れてみるのも良さそうです。

ただ、「学習は、心理的安全性の状況に依らず、普段の業務の中で個人が各々見出していくべきもの」または「学習は、業務とは切り離してプライベートでするべきもの」という考えですと、あまりピンとこないかもしれません。

心理的安全性についてのよくある誤解

ここまで、「心理的安全性とは何か?」「どんな効果があるのか?」について触れてきましたが、その言葉が持つイメージからか、誤解されて広まってしまっているのも事実です。

ここでは念の為、よくありそうな誤解をいくつか紹介しておこうと思います。

誤解①:くだらない話もできて仲が良いから心理的安全性は高いよ!

話しやすい状態のように思われますので、良いチームなのは間違い無いでしょう。

そのチームの中で、「このタスクって本当に必要なんだっけ?」「この進め方が一番良いんだっけ?」「勉強会でこんなアイデアを知ったんだけど、試しに1~2週間試しにやってみない?失敗するかもだけど」的な会話を、変に思われる心配なく繰り広げられていたら、間違いなく心理的安全性の高いチームです。

逆に、雑談はしているし、チャットも和気あいあいとしているけど、上記のような話し合いができていなかったり、あえて議論を避けているようなふしがあるとすれば、心理的安全性は低い状態だと言えます。

誤解②:アイデアを募るとたくさん出てくるから心理的安全性は高いよ!(最終的な決定事項には納得していない人がいて、成果も出にくい状態)

こちらも、「そもそも発言や提案がされない状態」ではないので、良いチームではあるでしょう。

ただ、本当に心理的安全性が高いのであれば、「決定事項に対して、自分はまだこんなところがわかっていない」などの発言が出てくるようにも思えますので、納得していない人が多い状態なのであれば、やはり心理的安全性は低い状態だと言えるでしょう。

リスクの無い発言や提案ができるかどうかではなく、リスクのある行動を、心配することなくとれるかどうかがポイントです。

誤解③:いつも特定の人は臆することなく発言してくれているから心理的安全性は高いよ!

人によってはそんな人も当然いますが、それだけでは判断できません。

そもそも、そのチーム内の人であれば誰しもが、勇気なんて持たなくても行動できる状態が、心理的に安全な状態です。

ですので、一部の人が勇気を振り絞って行動してくれている状態は寧ろ、勇気を出す必要がある程度には、心理的な危険が潜んでいる状況なのでしょう。

誤解④:「なんでも話して良いよ」と言っているから心理的安全性は高いよ!

マネージャーからそのようにコミュニケーションを取ること自体は重要なことです。

が、それを言っている = 心理的安全性が高い という訳ではありません。

誤解についてパッと浮かぶところはこんな感じでしょうか。

そもそもなぜ誤解が広まってしまったのかについては、正確な情報は辿れていないので定かではないのですが、「安全」と「安心」の意味が日本では混同されてしまっているからではないか?という説があるようです。

そう考えると確かに誤解にも納得がいきますね。

もし、誤解が広まっている経緯について詳しい方がいましたら、是非コメントなどでお知らせいただけると大変うれしいです。

心理的安全性の4つの因子

この章では、今後の話のために、書籍で紹介されていた「心理的安全性の4つの因子」について、概要だけ触れておきたいと思います。

本当にさらっとだけ触れるので、詳しく知りたい方は書籍を参照していただくのが良いです。

書籍によると、日本においては、次の4つの因子が満たされているとき、心理的安全性が高いと感じられるとあります。

  • ① 話しやすさ因子
    • 話す、話を聞く、相づちを打つ、雑談するetc
  • ② 助け合い因子
    • 相談する、相談にのる、自分一人では対応できないと認める、チームの成果を考えるetc
  • ③ 挑戦因子
    • 挑戦する、機会を与える、新しいことをする、失敗を歓迎するetc
  • ④ 新奇歓迎因子
    • 個性を発揮する、強みに応じて役割を与える、違いをただ違いとして認めるetc

次の章では、それらの因子(と、因子に紐づく行動)を阻害してしまっている、よくありそうだなぁと思うパターンを紹介していきます。

本当であれば、「じゃあどんな言動が良いだろうか?その理由は?」まで書こうかと思っていたのですが、大長編になって大変なので、今回は割愛しています…

心理的安全性を阻害するBadパターン

「話しやすさ因子」を阻害すること

  • 相手の目を見て話をきかない。
  • 相手の話しに相づちを打たない。
  • 雑談しない。認めない。
  • 悪い報告があったとき、ミスを責める。
  • 課題に思っていることや問題を報告したとき、「じゃあ、◯◯さんやっといて」と戻ってくる。
  • 何かに付けてすぐ怒鳴る、大声を出す。
  • 提案時、資料の些細なミスをあげつらう。
  • 反対意見が出てきたとき、「いやそれは〜」「でもさぁ〜」とすぐに抵抗する。
  • わからないことを質問したとき「自分で考えた?」「わからないの?」「前も教えたよね?」と言う。
  • 会議で、ちょっとした思いつきが発言されたとき、上司やマネージャーから冷たくあしらわれる。

「自分の話に興味を持ってくれてないな〜」「忙しいんだろうな〜」と思わせてしまったら、当然「本当に重要なこと以外は話さなくていいかなぁ〜」と思ってしまいますよね。

また、報告した結果責められれば、例え本当に100%その部下のミスが原因だったとしても(実際にはそんなことはあり得ないと思いますが)、報告する = 自分にとって損 という構図を学習してしまいます。

課題の提案も同様です。良かれと思って発言や行動を起こしても、自分の負担が増えるだけで、更にはそこで失敗して責められでもしたら、発言せず静観しているのが一番得な行動になってしまいます。

重要なことは、業務に関してでも、業務と関係無いことでも、「話す」という行動を積極的に推奨すること、「行動」と「行動の内容」をしっかり分けてフィードバックすることでしょう。(発言してくれた行為そのものは、どのような内容であれ、歓迎したいことのはずです)

「助け合い因子」を阻害すること

  • 何か問題が起きたり、失敗したときに、「誰のせい?」と犯人探しをする。
  • 評価は全て減点主義。
  • 相談をするために、厳格なルールが定められているなど、相談に対するハードルが高い。
  • 相談を持ちかけられたとき、嫌な顔をしたり、時間が無いことを理由に断ったりする。
  • 与えられた仕事は◯◯という役割の人が責任を持って一人で遂行するべき、という風潮、仕組みにしてしまう。
  • 個人としての成果のみを重視して、チーム全体としての成果を考えない。

減点主義や、それに近い雰囲気が漂っていると、できるだけ減点される要素を減らそうと考えますよね。そうなれば当然、自分が組織から明確にアサインされた仕事以外に手を広げることは、純粋なリスクになります。

ちょっと困ってるから相談したいけど、そのためには何らかのルールに則って行う必要があったり、「相談は相手の時間を奪う行為である」という風潮になっていれば、その場合もやはり「仕方ない、みんなのことを思って、みんなに迷惑を掛けないために自分ひとりでなんとかするか…」と思ってしまいます。 相談のアクションに対する反応がネガティブだった場合も同様です。

また、組織として「◯◯(ある作業)は△△(役割名)が担うべし」という決まりも、それだけが表にでてしまうと、当然のことながらその枠内だけを努力しようとするでしょう。

「マネジメントコストを減らすこと」だけにフォーカスすれば、個人は決められた仕事だけをやる仕組みにした方が管理がしやすいのは間違い無いと思いますが、その管理をなんのためにするのか?そしてそれは果たしてマネジメントしていると言えるのか?を考えることが重要かもしれません。

「挑戦因子」を阻害すること

  • 何かアイデアを持ちかけたとき、「それ、本当にうまくいくの?効果あるの?」と問い返す。
  • 「これまでやったこと無いから」「今と違うから」という理由でNGを出す。
  • ちょっと非現実的のように思える提案に対して、即「いや、うちの会社(うちのチーム、いまの状況)では無理だよ、合わない」と返す。
  • 企画自体は会社に承認されたものだが、実際やってみて失敗したら、実行者の評価に影響が出る。
  • 極端に失敗を避けようとする。

そもそも新しいことにチャレンジしようとするとき、書籍やカンファレンス、ネットなどである程度の情報は仕入れることができますが、100%上手くいく保証なんてどこにもありません。

「上手くいくかもしれないし、失敗するかもしれない。」というのはある程度仕方の無いことですので、「本当に上手くいくか?」と問われれば「わからない」と言う他ありません。

完璧を求められるのであれば、やはりリスクを伴ったチャレンジは受け入れられないんだ…と学習していき、何も変えることのできない環境になっていくでしょう。

ここで重要なのは、短期ばかりに目を向けるのではなく、長期を見据えてある程度の失敗リスクは許容してでも成長していけるチーム・組織としての目標を業務として設定することと、仮に失敗したとしてもリスクを最小限に抑えられるよう、小さな挑戦を推奨することのように思います。

「新奇歓迎因子」を阻害すること

  • 強みや個性をいかすのではなく、決められたら役割のなかで当てはめる
  • 同じ考えの人だけでまとめる。そのような人選をする。(特に経営陣でそのような状態はよろしく無いようです)
  • 人を、一律に扱うマネジメントをする。
  • 採用において、意識して多様性を取り込もうとしない。

VUCAの時代(変動が激しく、不確実性が高く、複雑で、曖昧な時代)に、チームや組織として競争力を保ち続けるためには、個々の多様性を尊重して強みを掛け算し、それを全体として一つの方向にマネジメントしていく必要があるとのことです。

ですが、「◯◯という役割であれば、全員が同じようにこの作業をするべし」とされてしまうと、弱みをカバーしあいながら、強みを活かすことができません。

また、組織のほとんどが同質で構成されていると、異質な価値観の人は自分の声に重要性を感じなくなり、組織に所属している感覚も薄れるそうです。

チームや組織としては、同質でない人も声をあげやすくなるよう配慮することと、意識的に多様性を取り入れていくこと、そして、そもそものところで、個々の価値観をお互いが知ろうとすること*6から始める必要があるのかもしれません。

おわり

以上となりますが、「それって違うのでは?」というご指摘や、「こんな言動もあるよね〜」などあれば、ぜひお知らせいただけると助かります。

今回は、心理的安全性そのものと、よくありそうなBadパターンのみの紹介でしたが、「心理的安全性のつくりかた」では、4つの因子の詳細な解説から、「心理的安全性を高めるためにはどのようなリーダーシップが求められるのか?」「行動分析学にそって、いかにして心理的安全性を高めていくか?」などがわかりやすく書かれています。

もし、この記事を読んでちょっとでも興味が湧いた方は、ブログ末に書籍へのリンクがあるので、購入して読んでみても良いかもしれません。

比較的読みやすい文体と、内容もわかりやすく説明されているので、早いひとなら2~3日で読めると思います。(僕は遅いので2週間くらいかかりましたが…)

…と、あまり「ユニファ」要素がほぼ無い記事でしたが、楽しんでいただけたら幸いです。

そして、共に心理的安全性の高いチーム・組織を作ろうという熱い思いのある方は、是非一緒に働きましょう!!!

それではまた次回。

unifa-e.com

*1:https://www.amazon.co.jp/dp/4820728245www.amazon.co.jp

*2:

*3: speakerdeck.com

*4:https://web.mit.edu/curhan/www/docs/Articles/15341_Readings/Group_Performance/Edmondson%20Psychological%20safety.pdf

*5:心理的安全性のつくりかた p22

*6:チーム内でお互いの価値観を知っていく方法としては、アジャイルサムライで紹介されているドラッカー風エクササイズ(リンクは別のブログ)がおすすめです。社内の方であれば渡部までご相談いただければ嬉々としてファシリに伺います!tech.pepabo.com

ユニファのエンジニアの業務領域とは?

こんにちは。 ユニファのエンジニアマネージャーの田渕です。

気づけば今年も、残り二ヶ月になってしまいました! コロナの影響などもあり、ハロウィンも例年ほどにお祭り騒ぎにはならなかったので、落ち始めた気温と乾燥した空気で季節を感じています。。。

各種媒体や弊社コーポレートサイトでも掲載しているように、現在ユニファでは技術職を盛大に募集しています! 過去にも何度か採用関連のお話を書いたことがありますが、今回は「ユニファのサービス開発のエンジニアって何してるの?」の最新状況を、これまでに掲載された記事の内容と合わせて書いてみたいと思います。

参考:過去の採用関連記事 tech.unifa-e.com

一口に「サーバーサイドエンジニア」と言っても色々ある

私自身がサーバーサイドエンジニアなので、差し当たりサーバーサイドエンジニアを例にとってお話を進めます。 外部コミュニティに参加したり、あるいは同業他社に知り合い/友人が居るエンジニアの方なら、一度は感じたことがあるかもしれません。

「同じサーバーサイドエンジニアでも、会社によって仕事の内容結構違うな。」

そうなんです。 一口に「サーバーサイドエンジニア」と言っても、その仕事内容や仕事の範囲は会社規模や扱う製品、サービスによってまちまちです。 「プログラムを書くこと」が役割のケースもあれば、「要件をまとめること」「顧客と話をすること」とか「インフラ構成を考えること」「モバイルのアプリを書くこと」までもその仕事の範囲に含んでいるケースもあります。 これはエンジニアに限った話ではなく、どの職種に於いても言える話だと思います。

そしてそのことが、時々起こる「転職者と会社のミスマッチ」の原因にもなります。 それ故に、ユニファの採用活動ではそのミスマッチを防ぐため、極力応募者の方と面接の段階で業務内容や範囲、期待する役割のイメージ合わせをさせて頂くようにしています。

ユニファのエンジニアの業務範囲

かつて(と言っても5年前。。。)は正社員エンジニアが片手で数えられるほどしかいなかった弊社ですが、今では海外メンバーも合わせ多数のメンバーが参画してくれています。 昔は要件の取りまとめなども含めてエンジニアが広くやっていましたが、今はプロダクトマネージャーやディレクターが居るため、その部分はそちらのメンバーにお任せするなど、役割も少しずつ変わってきています。 そんな中で、現在のユニファのエンジニアの業務範囲ってどんな感じなんだろう?と言うことを、現時点の情報として書いてみたいと思います。

サーバーサイドエンジニア

要件はPdM、ディレクターの方々がまとめてくださるため、基本的にはその内容に沿って開発を行っていく形になります。 また、画面設計/デザインについては、必要と判断したケースではデザイナーさんに作って頂いています。 要件決めの際にはもちろん技術的な実現性の考慮も必要となってくるため、要件検討段階でなんらかの形で検討に加わっています。

前回、赤沼がご紹介した午睡チェックのケースでは、大凡の要求定義の段階でシステム的な様々な課題(5分に一回一斉にデータが飛んでくるなど)が分かってきたため、早い段階からモバイルエンジニア、サーバーサイドエンジニア、インフラエンジニアが協力してアーキテクチャ設計を行っていました。 その後、運用が始まってからも、少しずつ改良を重ね現在の構成を作っています。

tech.unifa-e.com

大きな会社ですと、各社員の役割分担がかなり細分化されているため、例えばサーバーサイドのエンジニアが一切インフラの設計には携わらないケースもあります。 一方、弊社では技術検討段階でサーバーサイドエンジニアが実際にAWSの環境でテスト用の構成を作って試してみたり、「この仕組み使いたいんだけど」とインフラエンジニアに持ち込んで相談したりと、インフラ構築面にも比較的入り込んだ形で開発を進めています。

モバイルエンジニア

要件やデザインに関してはサーバーサイドエンジニアの項目で記載した通りです。 同様に、要件検討段階でももちろん検討に加わります。 モバイルエンジニアの提案により要件が大きく変わることもあり、「ただ言われたものを作る」と言う立場ではありません。 提供しているサービスの性質上、モバイルアプリは実際に保育士さんや保護者の方が一番目にする機会が多くなります。 その使い勝手や品質によって大きく利用者の満足度が変わるため、とても重要な役割をになっています。

モバイルのアプリはiOS/Androidでそれぞれにデザインのガイドラインがあり、それが各OSのバージョンアップなどに伴い少しずつ変わっていくなど、Webとは違った状況もあります。 また、それぞれに独特の「セオリー」や「トレンド」が存在し、それに追従した形での開発が求められます。 そのため、現在弊社ではモバイルのエンジニアが主導しモバイルアプリのデザインのガイドラインの輪読会を開催しています。 これを行うことで、企画や仕様検討段階で皆が想像するアプリや各種デザインのイメージを少しでも近くしようとしています。

インフラエンジニア

弊社はAWSを利用しているため、主としてAWS内の環境構築/管理を行っています。 前述した通り、サーバーサイドやモバイルのエンジニアから「この仕組み使いたい」と持ち込まれることも多々あるので、それらの相談を受け付けつつ、最終的な構成をどうするのかと言ったあたりを決めていきます。 ログ管理や監視周り、バックアップの計画/設定など、信頼されるシステム運用に欠かすことの出来ない大切な領域について担ってもらっています。 Terraformを利用した環境構築の自動化などにも取り組んでいます。 tech.unifa-e.com 提供するサービスが増えていくに連れて、インフラエンジニアが管理するサーバーが増えてきたため、現在はサーバーサイドエンジニアと一部業務の分担を計画しているところです。

でも、棲み分けは絶対ではない。

と言う感じで、ここまで長々書いた通り、各職種ごとに一応の棲み分けは存在します。 ただ、この棲み分けも、絶対ではありません。 どう言うことかと言えば、自分の主たる職種に近い領域については「はみ出して」仕事をすることが多々あります。 会社によってはサーバーサイドエンジニアが本番のインフラ設定を直接変更するなんてことは許されないケースもありますが、そう言うことも実施しています。 また、現在は募集条件の都合上「サーバーサイドエンジニア」「iOSエンジニア」「Andoroidエンジニア」と言う職種で募集をしていますが、「サーバーサイドエンジニアだからモバイルのコードを書いてはいけない」と言うことも実はありません。 ですので、募集要項職種にぴったりとハマらないケースであっても、十分にご活躍頂ける可能性があります。

もちろん、その時の開発計画などの兼ね合いもあるため、必ずしも希望通りのことが出来る訳ではありません。 ですが、状況が許す限りはご本人の志望を汲んだ形でお仕事がお願い出来るように考えています。

We are hiring!!!

そんな感じで、ユニファでは現在技術職を絶賛募集中です! 少しでもご興味をお持ちの方は、ぜひ一歩踏み出してみてください! unifa-e.com

ルクミー午睡チェックの Well-Architected なポイント

皆様こんにちは、ユニファ CTO の赤沼です。

もう1ヶ月以上前になってしまいますが、 AWS Startup Architecture of the Year Japan 2020 で優勝したことはこのブログにも書かせていただきました。

tech.unifa-e.com

ですが実際のアーキテクチャの内容についてはほとんど書いていなかったので、今回は改めてどのような点が Well-Architected であると評価されたのか、ピッチでアピールした内容を説明させていただきたいと思います。 ピッチで使用したスライドは下記に公開していますので、よろしければご覧ください。

www.slideshare.net

ピークタイムに合わせた Auto Scaling

f:id:akanuma-hiroaki:20201030000500p:plain

iPadから送信される午睡チェックデータを受け取るサーバサイドのRailsアプリケーションはEC2インスタンス上で稼働しています。ピークタイムはある程度特定されていますので、時間指定でオートスケールし、インスタンス数を増やして負荷に対応します。午睡チェックの開発開始当初は今ほどにコンテナ関連の環境が充実していなかったり、メンバーのナレッジ等の都合でコンテナ化はしませんでしたが、アクセスパターンがある程度読めて、急激なトラフィック増加の懸念もあまりないプロダクトであれば、EC2でも十分に安定的な運用ができますので、何でもコンテナ化するのではなく、それがどれぐらいメリットがあるのか、ビジネスに貢献するのかを考えてアーキテクチャを選定するのが良いかと思います。

Redis を使用した処理順番の担保

f:id:akanuma-hiroaki:20201030001149p:plain

サーバサイドで受け取ったセンサーデータは、後述するように SQS に格納され、Worker によって DynamoDB に格納されます。その際に Worker が複数の場合には SQS からデータが取り出される順番は保証されません。ただこのプロダクトにとっては処理順番も重要ですので、サーバサイドでデータを受け取るとまず Redis(ElastiCache) に午睡チェックシートの各セルのステータスをフラグ情報として書き込みます。そして Worker が SQS からデータを取り出した際には、そのフラグ情報を確認し、期待した通りのステータスになっていれば DynamoDB に書き込むことで、処理順番を担保するようにしています。

SQSを介した非同期処理によるDynamoDBへの書き込み

f:id:akanuma-hiroaki:20201030001722p:plain

このプロダクトのアクセス特性として、5分毎に数千施設の iPad アプリから一斉に午睡チェックシートのデータが送信されてくるという点があります。それをサーバサイドで直接 DynamoDB に書き込もうとすると、 DynamoDB のスケールが間に合わない、もしくはオンデマンドキャパシティーでオートスケールが間に合ったとしても、スパイクするアクセスパターンの最大値にフィットしてしまい、利用料金が高額になってしまうということになります。そこでデータを一度 SQS に格納し、Worker が非同期で順次処理していくようにすることで、安定的に処理をしていくと共に、キャパシティー値をリーズナブルな範囲に止めておくことができています。

また、Worker は EC2 インスタンスに相乗りしているため、オートスケールによって EC2 インスタンスが増えると Worker も増えるのですが、その場合にキャパシティーの設定値を超過しないように、 ElastiCache に DynamoDB のキャパシティーの設定値を登録しておき、各 Worker は起動時に自身の情報を ElastiCache に登録すると共に、稼働中の Worker の情報とキャパシティーの設定値を取得し、キャパシティーを超えないように書き込み速度を調整するようにしています。

DLQを使用した失敗データ対応

f:id:akanuma-hiroaki:20201030002943p:plain

SQS から取り出した午睡チェックデータが正しく処理されなかった場合、10回まではリトライされますが、10回処理に失敗したデータは DLQ(Dead Letter Queue)に格納され、エンジニアに通知が来るようになっています。エンジニアは通知を受けるとそのデータの内容を確認し、対応が必要であれば対応を行います。対応が必要ないデータは4日間DLQに格納されたままになると削除されます。

Design for Failure

f:id:akanuma-hiroaki:20201030003439p:plain

プロダクトの利用中に、ネットワーク障害等で iPad アプリがサーバに接続できなくなった場合に、既に午睡チェック業務が開始されている状態であれば午睡センサーと iPad アプリ間だけで最低限の午睡チェック業務が継続可能になっています。

セルラー回線使用によるネットワーク安定性の担保

f:id:akanuma-hiroaki:20201030003718p:plain

iPad アプリからサーバへの接続は、 SORACOM Air Sim によるセルラー回線を使用しています。これによって保育園の Wi-Fi 環境の有無や安定性に左右されることなく、安定的なネットワーク接続を提供することができます。

また、サービスの導入時に保育園側で Wi-Fi 接続の設定を行うのはハードルが高い場合も多いのですが、SORACOM Air Sim をセットし、アカウント登録も済ませた状態で iPad や午睡センサーをお届けすることで、箱から出したらそのまますぐにお使いいただくことができるようになっていますので、導入に対する保育園側のハードルを下げることにも役立っています。

まとめ(そして We are hiring!!)

以上がピッチの中でアピールさせていただいた、ルクミー午睡チェックの Well-Architected なポイントになります。アーキテクチャには絶対的な正解はなく、そのプロダクトの特性や制約、ビジネスメリットを考慮して適切な選択をしていくべきですが、ご紹介した内容が参考になれば幸いです。

そしてユニファでは、より良いプロダクトを提供するためのアーキテクチャ構成に挑戦したいインフラエンジニアの方を始めとして各種ポジションを絶賛募集中ですので、興味がありましたらぜひご連絡ください!!

www.wantedly.com

「価値の押しつけ」とならないように。

f:id:unifa_tech:20201010174141p:plain こんにちは、PdM(プロダクトマネージャー)の田嶋です。

プロダクト開発において、何を置いても大切なのは、顧客に「使われる」こと。そして、そのために顧客を「よく知る」ということ。
理想を求めるばかり、最近は基本を忘れかけていました。改めて思い出すためにもこのブログを書こうと思います。

これから新規事業に取り組まれる方にとっても、「使われる」を目指すペインの超入門編として参考にして頂ければ幸いです。
※特定の参考文献はなく、様々な知識の寄せ集めのため、別の理解があればぜひ教えてください。

【目次】

■1.顧客に使われなければ始まらない

大前提として、下図の「作れる」領域でしか事業化できず、★領域でしか事業は持続できません。 f:id:unifa_tech:20201010174223p:plain

では、「儲かる・作れる・使われる」のうち、第一に私たちが意識すべきは何でしょうか?
それは、顧客に「使われる」ことです。

時は遡ることX年、高度経済成長の最中では、作れば売れる時代もあったそうですが、供給過多の現代においては、顧客に「使われる」ことのハードルが上がっています。
この状況において、単に「作れる」モノを作っても、使われず無駄になる場合がほとんど。顧客に「使われる」確度の高いモノを、後から「作れる」か検討すれば良いでしょう。

※ここで指す「作れる」とは、技術的な可否だけを想像しがちですが、「既存リソースの強み,制約」と捉えておくと、後に"ビジネス上の要件"として働くため、事前に整理しておくと良いかもしれません。

また「儲かる」については、「作れる・使われる」を見込めない状況では値決めすらできないため、考えるのは最後です。マネタイズ方法は、これから私も勉強したいと思っているところです。

■2.課題解決型を狙う

顧客に「使われる」を目指すにおいて、新しい領域に事業展開するには大きく分けて2通りのビジネスがあります。
それは、「価値提案型」と「課題解決型」です。 f:id:unifa_tech:20201010174151p:plain

両者を比較した際、ビジネスとして成功しやすいのは「課題解決型」だと思っています。
その理由は、人間は悩みが切実なほど、お金を払ってでも解決したいと考えるからです。この "お金を払ってでも解決したい切実な痛み" を「ペイン」と呼び、ペインの解決を通じてお金を得ることがビジネスとなります。

一方で「価値提案型」の場合は、新しいビジョンや価値観によほど強い共感を得られない限り、浸透させることが難しい印象です。

まさに今私の取り組む "保育施設の先生向けプロダクト" においても、この方向性で悩んだ時期がありました。特に教育事業においては、こうあるべき!という理想が掲げられる一方、現場とはギャップがあることもしばしば。
保育書籍のインプットから始めた私にとって、インタビュー訪問を通じた現場の実態と、どのようにバランスを取るべきかに苦しみました。
しかし、顧客の共感を得られない価値提案型は、それこそ「価値の押しつけ」となりかねません。
仮に売りたいものが新しい価値だとしても、ビジネスとしては課題解決を謳う方が顧客に受け入れられやすい。認識を改め、現場の先生方のペインを探りました。

■3.課題の深いペインを狙う

さあ、解決すべきペインを見つけよう!と意気込む訳ですが、一概にペインと言っても、より「使われる」に足る "ペインの質" の見極めが重要です。

では、「課題の深いペイン(=お金を払ってでも解決したい、より切実な痛み)」とは、どんなものでしょうか? f:id:unifa_tech:20201010174402p:plain

それは、「既にコストを払って対策しており、それでも解消できない不満」です。コストとは、金銭だけでなく、時間的や労力的なものでも良いでしょう。痛みが強いほど解決したい想いとなり、対策(コスト)として現れているはず。このコストを大きく払っているほど、より課題の深いペインとも言えます。

そして、現状より低いコストで不満解消できる手段(=新サービス)を提供できれば、顧客はぜひ乗り換えたいと思うでしょう。

このペインを探るにあたり、注視すべきは顧客の行動です。
既にコストを払って対策を取っているか?行動の事実をきちんと確認します。一方で「課題だ」「困ってます」と口で言うだけの事象は、そもそも解決に懸ける想いが弱いため、もし新サービスを提供しても、「お金を払うくらいなら今のままで十分!」と、使われる可能性は低くなります。 f:id:unifa_tech:20201010174206p:plain

ただ、便利な世の中になったもので、私たちの日常生活は不便の少ないものになりつつあります。(未来の自分が見たらどう思うかな?笑)
"顕在的なペイン" は、既にサービス化されているか、訳ありで解決されていない場合かが殆どでしょう。そこで私たちは、"潜在なペイン" にも目を配らせます。普通という価値観は、環境に依存しやすく、傍から見ると異質なことも。顧客が当たり前と思って取り組むことは、意外と本人がコストと気付いていない場合も多くあります。だからこそ、私たちは顧客の行動を注視し、顧客を「よく知る」ことが大切です。

〜おわりに〜

これまで、
・事業における「使われる」ことの重要性
・「使われる」には課題解決型、課題の深いペインを狙うと良いこと
を説明しました。

引き続き、顧客に使われることを目指して、顧客と向き合っていきます。くれぐれも「価値の押しつけ」とならないように。

以上、ありがとうございました!

ーーーーーーーーーーーーーーーーーーーーーーーーーー
ユニファでは、新たな仲間を積極採用中です。
プロダクトマネージャーも大絶賛募集中!よろしくお願いします! herp.careers

強化学習で最強の打順を求める(前編)

こんにちは。機械学習やデータ分析に加えて最近インフラ周りにも入門して修行中の浅野です。新しいことにチャレンジするのは楽しいですね。新しいことといえば機械学習の中でも強化学習についてはなかなか手をつけられていなかったので、今回はその強化学習を使って何かを作ってみたいと思います。息子が野球をやっていることもあり、「シチュエーション別の打率データから最強の打順を求める」という課題設定にします。通常は解くべき課題に対して最適な解法を選択していくのが筋ですが、今は「理解を深めるために強化学習をオリジナルの課題に使ってみたい」というのがモチベーションなので、強化学習を使うのが適切か、そもそも解けるのか、といったところはあまり気にせず探索していきたいと思います。

長くなりそうなので次のように2回に分けてまとめていく予定です。

  • 前編:打率データの作成とシミュレーション環境の構築 ← いまココ
  • 後編:強化学習モデルの学習と評価

強化学習としての大まかな問題設定

強化学習では、ある環境においてエージェントが観測した状態をもとに行動を起こし、それによって得られる報酬の累積値を最大化するような行動指針を学習していきます。今回の課題では、9人の打者のシチュエーション(アウトカウントとランナーの有無)別の打率データがあるとき、ランダムな打順からスタートしてある二人の打順を入れ替えていき、得点力がなるべく大きくなるような打順を求める、という立て付けを考えています。強化学習の枠組みに照らし合わせると、打順が状態に対応し、打順の中で1組を入れ替えることが行動にあたります。報酬については、与えられた打順で各イニングの攻撃をシミュレートし、1試合(9イニング)で得られる総得点をもとに設計していくつもりです。まだこのモデル化が良いのかどうか定かではありませんが、この前編ではそれを検証する上で必要になってくる打率データの生成と得点シミュレーション部分の作成について書いていきます。後編ではそれをもとに実際に行動モデルを強化学習によって求めます。

打率データ

f:id:unifa_tech:20201005143500j:plain
高打率タイプの打者のランナー状況毎のアクション割合(ノーアウトの場合)

上図はある打者の状況別の打率を定義したものです。ランナーがいるほうが一般に打率が高くなりますが、この打者はランナー状況によってヒット(single), 2塁打(double)、3塁打(triple)、ホームラン(homerun)、犠打(sacrifice)、アウト(out)の割合は変化しない設定です。どんな状況においても35%の確率でシングルヒットを打ち、3%の確率で2塁打、3塁打とホームランは1%ずつです。犠打は行いません。1人の打者に対してこれをアウトカウントごとに定義します。それを9人分作成します。ノーアウトかワンアウトでランナーがいれば高確率で犠打を成功させる川相タイプ、満塁になると異常に打率があがる駒田タイプ、2塁打が多い立浪タイプなど、いろんなバリエーションの選手を用意します(例えが昭和ですね)。一般にツーアウトになると投手が有利なので打率を全般に下げたりするなどの調整も自由ですし、現実のデータを利用することも可能です。今回準備した9人のラインナップは下記のような感じです。

  1. リードオフマンタイプ:ランナーがいないときの出塁率が高い
  2. 川相タイプ:犠打の成功率が高い
  3. 高打率タイプ:どんな状況でも出塁率が高い
  4. 三冠王タイプ:長打も含めてとにかく打つ
  5. 駒田タイプ:満塁に強い
  6. 立浪タイプ:2塁打が多い
  7. ランスタイプ:打率が極端に低いがホームランだけは多い
  8. 守備の人: 全体的に打率が低い
  9. ジョーカータイプ:なぜかツーアウトになると打ちまくる

試合における得点数のシミュレーション

ある打順が与えられたとき、1回の先頭打者から1人ずつ上記で定めた打率データに基づいてアクションを選び、アクションに応じてアウトカウント/ランナー/得点をアップデートし、3アウトになったらイニングを終了させる。それを9イニング繰り返すことで、その打順で1試合でどれだけ得点することができたのか計算することができます。特に実装が難しい部分はありませんが、アクションに応じてランナーを進塁させたり得点を計算したりする部分は下記のようにビット演算にすることで多少すっきりと書けるので一応例を示しておきます。

def update(self, out, runner, action):
    if action == 'out':  # アウト
        out += 1
    elif action == 'sacrifice':  # 犠打:ランナーを1つ進塁(左シフト)してアウトカウントを1つ増やす
        runner = runner << 1
        out += 1            
    elif action == 'single':  # ヒット:ランナーを1つあるいは2つ進塁して1塁走者をおく(第0ビットをたてる)
        if random.random() > 0.5:
            runner = runner << 1
        else:
            runner = runner << 2
        runner = runner | 0b0001
    elif action == 'double':  # 2塁打: ランナーを2つあるいは3つ進塁して2塁走者をおく
        if random.random() > 0.5:
            runner = runner << 2
        else:
            runner = runner << 3                
        runner = runner | 0b0010
    elif action == 'tripple':  # 3塁打: ランナーを3つ進塁して3塁走者をおく
        runner = runner << 3
        runner = runner | 0b0100
    elif action == 'homerun':  # ホームラン: ランナーを4つ進塁し第3ビットをたてる
        runner = runner << 4
        runner = runner | 0b1000

    run, runner = self.get_score(runner)  # アクションの結果入った得点を計算
        
    return out, runner, run
    
def get_score(self, runner):
    run = bin(runner & 0b1111000).count('1')  # 第3ビット以上で1がたっているビット数が得点
    runner = runner & 0b111  # 第0−2ビットに残っているのがランナー
        
    return run, runner

得点力が高い打順の例

9人で組める打順は9!= 362,880通りです。かなり時間はかかりますが全てのケースで上記の得点シミュレーションを走らせることで、どんな打順が得点力が高いのかを知ることができます。各打順で100試合分のシミュレーションを行い平均得点数を調べてみた結果、私が直感でこんな順番がよいのではないかと思った打順での平均得点は3.05点でした。また、すべての組み合わせの中で最も平均得点が高かった打順では4.03点でした(最低は1.76点)。それぞれの打順を比べてみるとこんな感じです。

私の案 (3.05点) 最高の打順 (4.03点)
1 リードオフマン 高打率
2 川相 三冠王
3 高打率 ジョーカー
4 三冠王 駒田
5 駒田 川相
6 立浪 ランス
7 ランス 守備の人
8 守備の人 立浪
9 ジョーカー リードオフマン

平均だけでなく得点の分布も比較してみましょう。水色のヒストグラムが私が考えたオーダーの得点分布で、クリーム色が最高得点の打順の分布です(茶色は両者が重なっている部分)。これを見ると確かに5点以上得点する試合の数がかなり違いますね。

f:id:unifa_tech:20201005180456j:plain
2つの打順における得点の分布
最高得点の打順を見てみると、まず、2番に強打者を置くという最近のトレンドと合致していて面白いです。また、上位に打率が高めのバッターを集め、ランナーが溜まったときにまわりやすい4番に満塁に強い駒田を入れたり、川相/ランス/守備の人と打率が低めな選手を固めることで打線が分断されるのを防ぐなど、言われてみるとそうだよなと納得させられるオーダーになっており興味深いですね。

まとめ

打率データをもとにある打順での得点数を算出するシミュレーションが完成しました。対戦相手の能力や相性、ボールカウント、走力、代打、守備力など野球において考慮できていない要素がたくさんありますが、今回は野球の正確なシミュレーション環境を構築するのが目的ではないので気にしないでおきましょう。また、全探索の結果から得点力の高い打順の例を示しましたが、打者の特徴が少しでも変わるたびにこのような計算を行うことは現実的ではないため、後編では強化学習モデルによって得点力のある打順をより効率的に求める手法に挑戦していきます。

AWS Startup Architecture of the Year Japan 2020 で優勝しました!!

f:id:akanuma-hiroaki:20200923223808j:plain

皆様こんにちは、ユニファの赤沼です。

先日プレスリリースも出させていただきましたが、9/16 に行われた AWS Startup Architecture of the Year Japan 2020 Live Finale にて、ルクミー午睡チェックのアーキテクチャについてプレゼンさせていただき、ユニファが優勝することができました!これも日々社内でサービス提供のために取り組んでいる開発、ビジネス、コーポレートの全メンバーの努力が評価されたものですし、メンタリングいただいた AWS の松田さん、岡田さんのおかげですし、何より日々保育の現場で真摯に保育に取り組まれている保育者の方々のご尽力の成果でして、本当にありがたく思っています。

今回はどういったところが評価されて受賞に至ったのか、また、事前の準備や当日の様子などについてご紹介できればと思います。

AWS Startup Architecture of the Year とは

「AWS Startup Architecture of the Year」は2018年に日本で生まれ、今年から世界規模で展開されるスタートアップのためのコンペティションで、評価の対象はビジネスを成功に導く優れた「アーキテクチャー」です。そのアーキテクチャーがいかに AWS Well-Architected Frameworkの基準に適合しているか、ビジネスにインパクトを与えているかといった点が評価の対象となります。日本、米国、インド、欧州の各地域から、優れたアーキテクチャーでビジネスをけん引しているスタートアップが選出され、11月に開催予定の世界大会(オンライン)にて世界一を決定します。

Startup Architecture of the Year Japan 2n020

aws.amazon.com

評価されたポイント

さて、今回どういったところを評価いただいたかですが、受賞時に審査員の藤本さんからいただいたコメントから、派手さはないけれどやるべきことをしっかりやっているというところを評価いただいたと思っています。

ルクミー午睡チェックでは命に関わる業務の安心・安全をサポートするというプロダクトの性質上、 Well-Architected Framework の5つの柱の中でも、特に信頼性と運用上の優秀性が求められます。信頼性という点では、DynamoDB と SQS を使ってパフォーマンスを担保している点や、 Design for Failure を考慮した DLQ の仕組み、ネットワーク障害等が発生してもローカルのみで一定の業務が継続可能にしている点等で担保しています。また、運用上の優秀性といった点では、SORACOM Air Sim を用いたセルラー回線を使うことでの安定した接続や導入時の保育園側のハードルの低減といった点で考慮しています。

一つ一つは技術的に尖っているわけではないですが、サービスの特性を考えて求められる点を総合的にしっかりカバーし、そしてこれらが実際にプロダクトの導入実績と紐づいて、事業に貢献できているというところが評価いただけたものと思っています。

メンタリング

応募後に書類選考を通って Live Finale での登壇が決まった段階で、 AWS の松田さんと岡田さんにメンタリングいただき、5分間という短い時間でどういった点を伝えるのが良いかをアドバイスしていただきました。それをもとにプレゼン資料とシナリオを作成したのですが、5分間というのは思っていたよりもとても短く、その中で事業やアーキテクチャ、ビジネスへの貢献をしっかり説明するには、スライドで表示して理解してもらうことと喋って説明することを吟味して、不要なものをできる限り削る必要がありました。そして一旦作ったもので松田さんと岡田さんにレビューいただき、ダメ出しを経てなんとか5分間で伝えるべきことをまとめることができたと思います。松田さんと岡田さんには本当に感謝です。

当日の様子

当日のプレゼンの順番は社名の五十音順ということで、六社中一番最後だったのですが、ということは一番最後まで緊張してることになるので、正直他社のプレゼンをしっかり見てる余裕はありませんでした。見てると余計に緊張しちゃうので。。

またこれは完全に自社の事情なのですが、当日 Live Finale の直前に取締役会があり、どうしても外せなかったので、岡田さんに会議室を手配いただき、Amazon目黒オフィスの会議室からリモートで取締役会に参加させてもらいました。取締役会では自分のアジェンダもあり、 Live Finale のことを考えるとそわそわしながら参加していたのですが、なんとか無事に予定時間までに取締役会も終えることができました。岡田さんには私のわがままにご対応いただき、感謝です。

朝から吐きそうに緊張してましたが、プレゼン自体もなんとか5分間に収めることができ、審査員のCTOの方々からどんなマサカリが飛んでくるかとびびっていた質疑応答も乗り越えて、やっとほっとした感じでした。

世界大会

今のところ世界大会については、11月にオンラインで開催、という以外にはまだ何も聞いていないので、プレゼン英語なのかなー、というぐらいなのですが、審査員の藤本さんや松本さんからはしっかりプレッシャーかけられたので、日本代表としてはがんばらねばと思っています。プレゼン自体は英語でもなんとかなりそうな気がしますが、質疑応答が英語でできるのか。。英語力を鍛える必要がありますね。。

まとめ

事前の準備は色々と大変でしたが、受賞できたことは本当に嬉しく、SNS等でも多くの方からお祝いの言葉をいただきました。本当にありがとうございます。また、社内のメンバーとしても自信につながるところもあると思いますし、社外に向けてのアピールになる点も大きいのではないかと思います。私自身も改めてアーキテクチャを見直して Well-Architected Framework について考えるきっかけにもなりましたし、今後より良いプロダクトを提供できるようにチャレンジしていこうというモチベーションにもつながりました。

そしてインフラエンジニアをはじめ、このチャレンジに一緒に参加してくれる方を募集してますので、興味のある方はぜひご連絡ください。一緒に保育をハックしていきましょう!!

herp.careers