コネヒト開発者ブログ

コネヒト開発者ブログ

形骸化しない/させない定例的MTGアップデートの歴史

この記事はコネヒトアドベントカレンダー2022の6日目の記事です。

こんにちは。2017年11月にAndroidエンジニアとしてjoinした@katsutomuです。

前回のエントリーで、髪の毛のアップデート予定について触れましたが、今は黒髪7割金髪3割りといったところです。

さて今回は、コネヒトの開発組織で行われている定例的*1なMTGについて紹介させていただきます。

目次

コネヒト開発組織の定例的MTGはどんなものか?

コネヒトでは2018年ごろから、エンジニア全員が参加する定例的なMTGを実施しています。定例的なMTGは、ともすれば形骸化しがちですが、コネヒトではその時々で注力する課題から目的を定め、定期的なアップデートを行っていきました。今回はその変遷を紹介しようと思います。

ぜひ皆さんに読んでいただきたいですが、以下の方に特に届けられたらと思います。

対象読者

  • チームや部署間の情報同期の進め方にお悩みの方
  • 定例に課題はないが、他社の事例を知りたいという方
  • これから定例することが、決まっているが、やり方がわからない方

MTGの変遷

さて、まずはこれまでの定例の変遷を以下の図と表にまとめました。

名前 目的 時期 規模 内容
一歩MTG •部署/チーム間の相談&課題解決 2018年 ~ 2019年 スクラムチームが3。部署が1つ。 • 各チームのやったことや、アピールしたいことを話す
• みんなに質問・共有・相談
• 周知事項共有
戦略MTG • 戦略を実行精度を向上のための、課題の早期発見/早期対処 2019年 ~ 2021年 チーム3~4。部署が2つ。 • OKR進捗確認
• 開発チームトピック共有
• みんなに話したい!タイム
ボックスMTG ・「なぜつくるか」「どうつくるか」のノウハウ展開
・部署/チーム間のコラボのきっかけの場
2021年 ~ 2022年 チーム4~6。部署が2つ。 ・10分の共有・相談タイム*4枠
・連絡共有事項

日々アップデートしながら、大体1~2年が経つころに、大幅なアップデートをしています。次のセクションでそれぞれの課題と背景をふまえて、MTGの内容を具体的に紹介していきますが、MTGに正解の形はなく、今回紹介するもベストなものばかりでは無いものの、少しでも思考の刺激になればと思います。

一歩MTG時代 2018年 ~ 2019年

課題と背景

スキルを網羅したチーム編成から、ミッションを元にしたチーム編成するように変更した時期です。同時に会社の規模が大きくなり、従来のスクラムの枠では収まらない仕事やプロジェクトが増え、単独のチームで業務を完結出来ないケースが増えてきました。その状況を踏まえ、部門全体の目標達成を円滑にするべく、横串で情報や課題を共有して、解像度を上げる場が必要でした。 ちなみに名前はママの一歩を支えるという弊社プロダクトのママリのミッションからつけています。

各チームでやったこと・これからやることシェア

名前の通り各チームが取り組んだ施策や結果を共有し、次に何をするかを同期していました。スクラムチームで、取り組んだワークショップを紹介することもありました。当初は各チームの代表者が読み上げていましたが、質問・相談の時間を増やすために、読み上げなしとしました。

みんなに質問・共有・相談したいことタイム

チームの連携周りやシステム全般に関わることを相談する時間です。

例えば、画像にあるように特定ブランチのライブラリアップデートの進め方どうする?ということを話していました。

戦略MTG時代 2019年 ~ 2021年

課題と背景

中期ビジョン策定がなされ、ビジョン実現のために戦略の重要度が高くなった時期でした。ビジョン実現を念頭に各部門戦略を策定し、実行の精度を上げることを組織的に力をかけ始めました。そのため部門の全体像を可視化し、課題の早期発見/早期対処を進める場が必要でした。

OKR進捗確認

半期毎のOKRの進捗状況を共有し、打ち手の検討をおこなっていました。事前に課題を書き、状況をみんなで点検し、対策を打ちやすくしていました。

テックビジョン小噺

テックビジョンが策定されたので、全員が理解度を深めコミットする状態を目指すために、CTOに質問をぶつけて、どのようにテックビジョンを実現するかの議論をするコーナです。以下のフォーマットで、CTOとメンバー全員で議論をしていました。

テックビジョンはIntroduction · Connehito Tech Visionを是非お読みください!

みんなに話したい!タイム

相談したいことや、共有したいことを話せる時間です。例えば、画像にあるようにアプリケーションエンジニアと、インフラエンジニアコミュニケーションの課題や、既存プロセスの改善などの相談が行われていました。

ボックスMTG時代 2021年 ~ 現在

課題と背景

単独チームで戦略を実行できるが増え、チームの独自性が高まったこ反面、OKR進捗共有が共有のための共有になる、ナレッジのサイロ化とチーム間の協働がゆるくなり始めました。ノウハウの循環が止まり、チーム内に閉ざされたことで、本来上げられたはずの成功確率が上がらない状態となっていました。この課題に対し、戦略MTGのみんなに話したい!タイムを強めた、話したいことを話したい人が話せる場としてアップデートを行いました。

コンセプト

💡 レンタルボックスを借りて、そのボックスの中で自分のお店を開くように色んな人が、 期間限定で臨時開設されるポップアップストアのように柔軟に、関わっていける場

目的

  • 部門を跨いで情報を同期的にブロードキャストする場
  • 「なぜつくるか(Why)」や「どうつくるか(How)」をノウハウとして展開する場

このやり方で、2021年前半からMTGを実施しています。具体的な進め方は以下の通りです。

かためな内容〜ゆるめな内容まで話される課題に向き合ったMTG

  • 会場:Zoom
  • 頻度:隔週
  • 議事録:notion
  • 進め方
    • ボックス①~④を共有&議論(40分)
    • ライトな共有周知事項&WinSession(10分)

ボックスと呼ばれる枠を10分×4つの自由枠を用意したことで、議題のバリエーションが増え、結果的に以前よりも部署・チームを跨いだコラボレーションの場として機能するようになったと感じています。なおボックスは、以下のガイドラインに従って事前に抑えます。せっかくなので議題のいくつか例示します。

このように組織全体の目標の話から、技術的、チーム的な運用面の課題提起・改善議論をできる場となっています。開発部オンボーディングのテンプレを作りたいというテーマでは以下の画像のように話し合いがされました。

例示したように、チームや部署を跨いで相談し(少しでも)課題を解決するための場として機能していて、以前までの決まった方式でなく、ボックス方式にしたことで議題に柔軟性がでて、メンバーやチームが、それぞれの課題やアイディアをシェアし、コラボレーションを行う場になったと思います。細かい部分では、議事録担当を持ち周りにする不在メンバーのために録画を残しておくという工夫をしています。最近はボックスMTGの中で、各メンバーのGood Acitionを自薦・他薦で紹介するWin Sessionも実施しています。

コネヒトの強いカルチャー

改めて振り返ってみると、コネヒトの肯定から始めよう~Affirm&Follow~というカルチャーを強く感じられました。まずは肯定から初めて乗っかりやフィードバックをしていくことで、コトを進めていくカルチャーです。そのカルチャーとの相乗効果を高めるためにも、どのMTGでも全員が参加し議論するオープンさに拘り続けていました。いわゆる定例的なMTGは形骸化しがちで、参加する側が必要性を感じない環境も多いと思いますが、コネヒトの場合、定期的にMTGの役割をアップデートし、課題を放置せずにフォローし合う仲間がいることで、長い期間意義のあるMTGを作れていると思います。

最後に

今回は、エンジニア組織の定例MTGの変遷とフォーカスポイントを紹介させていただきました。同じような課題に悩んでいる方の参考になればと幸いです。

私自身も改めて振り返ってみたことで、組織の成長を実感できこれからのアップデートが、より楽しみになってきました。

最後までお読みいただき、ありがとうございました! 7日目はインフラエンジニアの @laugh_k の記事です。

tech.connehito.com

日曜日には、Webエンジニアの@TOCが、チームで実施している別のボックスMTGの事例を紹介してくれます。どちらもお楽しみに〜〜〜!

*1:定例呼ぶのが好きでなく的をつけてます

コネヒトでNotion導入活動を始めて1年以上経過した

🎅 この記事はコネヒトアドベントカレンダー2022の7日目の記事です。
前回は… katsutomuさん…. !!!

インフラエンジニアの @laugh_k です。 今回は私が中心となって去年から行っていたコネヒトにおけるNotion導入に関する話をまとめます。

tl;dr

  • コネヒトにおけるNotion導入を1年間でどのように進めたか紹介します
  • Notionの基本的な使い方や細かなプラクティスは書籍・インターネット上に多くの情報があるため、この記事では深くは触れません
  • 導入して終わりではなく、まだまだ課題はあるものの、確実にコネヒトのワークスタイルが進歩しました

アウトライン



なぜNotion導入を進めようとしたのか

最初になぜインフラエンジニアである私が中心となってNotion導入を進めたのか簡単に紹介します。

背景

昨年2021年の3Q始まりのタイミングで私の所属するテクノロジー推進部にて、リモートワークで一緒に仕事しつつも、どんなことを感じていたりするかといった「コンディション」をお互いもっと把握したいねという課題が出たことがきっかけです。

当時のコネヒトではリモートワーク中心の中のコミュニケーション系のことは大体「SlackかZoomでどうにかする」が主流でしたが、この課題に関しては非同期でも実現するべくアプローチの方が良いという話になり、以下の記事をベースとした「チーム日報」をやってみようという話になりました

razokulover.hateblo.jp

この記事では Scrapbox を用いていますが、当時安定したリアルタイム同時編集が可能でカジュアルに利用できる社内のツールに決定的なものもなかったため「せっかくならよりコネヒト全社で活用できそうなものを導入してみてはどうか」と動き始めることになりました。

Notion の選定

最低限必要になったのは「カジュアルにリアルタイム同時編集可能なツール」でした。ただ、これに加えて「インラインコメント可能なものの方がよりメンバー同士のコラボレーションを加速させられそうだ」と考え、さらには「ドキュメントツールと言うより、オンライン上でテキストベースのプロジェクト・ToDo管理、議論、社員の活動の可視化などのコラボレーションを加速させるものがいい」と考え Notion に白羽の矢が立ちました。

何でインフラエンジニアなのにNotion導入担当になったのか

「コンディション」をお互い把握するためにチーム日報の提案をしたのも、その手段としてNotionを選定すると全社に対しても良い影響を与えれそうだと直感的に思ったのも私だったことが大きいです。これに加えて他のメンバーの業務状況を考慮してもすぐに動け出せそうだったのが私だったこともアリ「じゃあ自分がやるか!」と腹をくくり、自称社内Notionエバンジェリストを名乗っていくことになりました。

結果論ではありますが、当時インフラエンジニアは @shnagai と私の二人体制で裁量も高く、新しいツールを業務にガンガンねじ込むのが比較的容易な立場にあり、むしろ適任であったようにも思えます。

ざっくりとした導入の流れ

大まかな導入の流れは以下の通りです。

  1. 自分の所属チームでトライアル(2021年11月~)
  2. エンジニア組織全体でのトライアル(2021年12月~)
  3. 全社員でトライアル(エンジニア以外はゲストアカウント)(2022年2月~)
  4. 経営会議に議題持ち込み(2022年2月~3月)
  5. 正式導入、全社員を対象にチームプランで契約(2022年4月)
  6. 各チームで本格的に業務投入が開始(2022年4月~)

正式に社内ツールとして承認されたのは2022年4月ですが、そこから全社でNotionを業務に取り入れていくのにあたり、各部署・チームによって少しずつ慣れていったところもあり、「Notionがあるのが当たり前」となったのは2022年10月ごろではないかと個人的には考えています。

ざっとどういった活動だったのかを紹介します。

1.自分の所属チームでトライアル / 2. エンジニア組織全体でのトライアル (2021年11月~)

一番最初は私の所属するテクノロジー推進部(テク推)でトライアルとして少しずつ利用をはじめました。利用用途としては背景でも紹介した「チーム日報」であったり、部内のMTG議事録をNotionにまとめてみるなどです。

チームでトライアル開始してから5日目くらいの「チーム日報」の様子
チームでトライアル開始してから5日目くらいの「チーム日報」の様子

部内でのトライアルと同時進行でエンジニアメンバー全体にトライアルの範囲を拡大すべく、開発組織ボックスMTGに議題として持ち込みチームプランの予算の確保にもも動きました。この時点でエンジニアの人数分でチームプランを契約しています。

チーム以外の開発組織全体に「Notionを使いたい」という表明をしている様子。メインのドキュメンテーションツールである Docbase で行っている
チーム以外の開発組織全体に「Notionを使いたい」という表明をしている様子。メインのドキュメンテーションツールである Docbase で行っている。

チーム以外の開発組織全体に「Notionのトライアルやってくよ」という表明をしている様子
チーム以外の開発組織全体に「Notionのトライアルやってくよ」という表明をしている様子

3. 全社員でトライアル(エンジニア以外はゲストアカウント)(2022年2月~)

エンジニアメンバーのみでトライアルを進めるも、すぐにエンジニア以外のメンバーともNotion上でコラボレーションしたいという状況が発生しました。

エンジニア以外の人にもNotionを早めに使えるようにしたいという意見が出ている様子
エンジニア以外の人にもNotionを早めに使えるようにしたいという意見が出ている様子

そこで、全社へ正式に導入されるまでの間は暫定対応としてすべてのページにエンジニア以外のメンバーもゲストアカウントとして招待する対応を取りました。人数が多く、APIで出来るものでもないので力業ではありますが、結果としてより多くのメンバーにNotionを使ってもらえる状況になり、業務に組み込みやすい状況にできました。

全社向けにゲストアカウントを発行したアナウンスの様子
全社向けにゲストアカウントを発行したアナウンスの様子

4. 経営会議に議題持ち込み(2022年2月~3月)

トライアルを通じた手ごたえから、正式に全社への導入提案を議題として経営会議に持ち込みました。最初に2月時点で中間報告としてどのような導入状況か、導入によってどのような問題が解決できそうな見込みがあるのかを報告をしました。

実際に中間報告の時に使ったNotionページの一部’
実際に中間報告の時に使ったNotionページの一部’

その更に1か月後に中間報告の結果を受けて最終的な形として提案議題を持ち込みました。

実際に全社への導入提案をした際に使ったNotionページの一部
実際に全社への導入提案をした際に使ったNotionページの一部

その際さらに追加の議論が発生し、合計で3回ほど経営会議に議題を持ち込むことにはなりましたが、2022年3月末に最終的に承認され無事に全社への導入が決定します。

5. 全社に正式導入(2022年4月)

4月に正式に全社向けの導入が承認され予算も確保できたため、チームプランの対象が全社員になりました。ここで改めて正式に利用可能になったアナウンスを出しました。

正式に全社導入が完了した際のアナウンスの様子
正式に全社導入が完了した際のアナウンスの様子

また、「Notionのアカウントができたんだけどとりあえず何すればいいの?」という人向けのページも用意し、少しでもNotionを触るための障壁を下げる試みもしています。

Notionに初めてアクセスした人向けのページの様子
Notionに初めてアクセスした人向けのページの様子

6. 各チームで本格的に業務投入(2022年4月~)

4月以降は全社員がNotionを利用できるようになりました。これをきっかけにエンジニア以外でも業務への導入が進み、全社的に「Notionを使おう」という流れができました。

コーポレート系の情報が集まるページの例
コーポレート系の情報が集まるページの例

一方で、トライアル期間に差があるのはもちろん入社時期や得意不得意によってもNotionそのものの習熟度は人によって異なります。日々Notionに関する困りごとの解決のお手伝いは続きます。

Notionの使い方に関する質問の様子(1)
Notionの使い方に関する質問の様子(1)

Notionの使い方に関する質問に答える様子(1)
Notionの使い方に関する質問に答える様子(1)

時間の経過とともに私以外の誰かが回答・解決してくれる機会も増えてきていますし、質問の内容もより突っ込んだものも増えてきている印象です。

Notionの使い方に関する質問の様子(2)
Notionの使い方に関する質問の様子(2)

Notionの使い方に関する質問に答える様子(2)
Notionの使い方に関する質問に答える様子(2)

導入の際に意識したこと・工夫したこと

実際、ここまで進めるには様々な困難があり、工夫したことや意識したことは数え切れません。この記事にすべてを詳細に書くととんでもない長さになってしまうので簡単に厳選すると以下のようなものがあります。

意識

  • 社内Notionエバンジェリストを名乗るからには「コネヒトで一番のNotionヘビーユーザーであるべき」と意識の元、隙さえあれば業務にNotionねじ込み、活用しつづけました
  • 「社内で一番Notionに詳しい人」を演じ、「@laugh_k に声をかければNotionに関する悩みは解決するぞ」という雰囲気づくりの徹底。特にトライアル時は Notion相談ワイガヤ Slack チャンネルに張り付いていました
  • 勝手に導入するのではなく、関係各所と調整しチームのプロジェクトとして立ち上げ正面から進めました。特に四半期の部署としての目標にNotion導入を掲げさせてくれ、布教活動の際にいっぱい助けてもらったテクノロジー推進部には感謝しています
  • ボトムアップで新たなツール・サービスの導入には現場が納得していることが一番重要と考え、「そっちのチームのこの業務でNotion使ってください」というお願いは一切せず、「こういう活用ができて便利です!」という提案にひたすら徹して布教活動をしました。

工夫

Notion 相談ワイガヤSlackチャンネルを用意

「Notionに関する話ならここで!」というSlackチャンネルを用意しました。Q&Aにとどまらず、新しい機能や便利な使い方を見つけた際に「これ便利!」という共有やNotion導入時に必要な議論も行われました。

Notionの新機能を見つけてはしゃいでいる様子
Notionの新機能を見つけてはしゃいでいる様子

Notionに関する疑問を話している様子
Notionに関する疑問を話している様子

Notionの理解具合をつぶやいている様子
Notionの理解具合をつぶやいている様子

Notionのページ階層のやり方に関する議論の様子
Notionのページ階層のやり方に関する議論の様子

また、@NotionJP やNotionの中の人である @katsu2488 さんの Tweet が流れるようにして情報のキャッチアップをできるようにしています。

Notionのリリースに沸く人々
Notionのリリースに沸く人々

「Notionに何書けばいい?」問題の解決

トライアル初期の「Notionに何書けばいい?」は日報のような既存の社内文化や、自己紹介データベースなどの緩めなコンテンツを置く場所を用意したり、なるべくルールを設けず自由に使ってもらうようにしました。

誰でも自由に何を書いてもいい日報置き場(もともとSlackにあった文化を踏襲)
誰でも自由に何を書いてもいい日報置き場(もともとSlackにあった文化を踏襲)

自己紹介ページを置いておくデータベースの様子
自己紹介ページを置いておくデータベースの様子

また、議事録やドキュメントと言ったものは自分たちのチームに制限する必要のないものは共通のデータベース置き場を用意し、本体はそこに作成。各チームごとに必要なページに必要な形でリンクドビューを設置できるようなやり方にしました。

議事録など自分のチーム以外でも使えそうなものはチームに閉じない形でデータベースを設置
議事録など自分のチーム以外でも使えそうなものはチームに閉じない形でデータベースを設置

ドキュメント置き場も、特定のチーム向けではなく全社員で利用する前提で用意しています
ドキュメント置き場も、特定のチーム向けではなく全社員で利用する前提で用意しています

自分の裁量がある業務領域ではガンガン使いまくる

自分が所属するインフラエンジニアチームやテクノロジー推進部の業務には多少強引にでもNotionを組み込んでいき、Notionを扱う知見を先行して習得しつつ、先行事例として他のチームへも提案していきました。実際ちょうど1年前の時期に書いたブログの時点でも、インフラチームでNotionを活用していました。

tech.connehito.com

定期的に集まってNotionに関する知見共有できる場を用意

Notion の知見をゆるく共有し合うオンライン定期イベントを開催しました。その際に、会の様子をNotion上にリアルタイムでメモを取ることによって、Notionのことを知るだけでなく同時編集可能なツールでの議事録の取り方を体験してもらう機会を提供する試みもしました

社内Notionイベントを告知する様子
社内Notionイベントを告知する様子

Notionイベントの議事録の様子。文末にあるアイコンは自己紹介ページへのメンションで、その行を誰が書いた/発言したのかがわかるようにしています
Notionイベントの議事録の様子。
文末にあるアイコンは自己紹介ページへのメンションで、その行を誰が書いた/発言したのかがわかるようにしています

イベントの議事録は全社共通のデータベースで管理します。プロパティでフィルタすればいいので誰がどんな目的でやったものでも利用できます
イベントの議事録は全社共通のデータベースで管理します。プロパティでフィルタすればいいので誰がどんな目的でやったものでも利用できます

Notionが導入されてどうなったか

Notionが導入されたことにより、様々な変化がありました。

議事録やボードビュー、通知による社内の動きの可視化

これまでなかなか見えなかった社内の活動も一か所の議事録データベースに集まりやすくなりました。

データベースのボードビューを活用したタスク管理が社員ならだれでも見れる場所で行われるようになり、「あのチームが何をやっているのか分からない」となったときにも気軽に見にいけるようになりました。

他にも、通知欄からワークスペースにおける更新状況を眺めることができるので、なんとなく「今こんなことが動いているのか」という情報をキャッチアップ出来るようにもなりました。

同時編集とインラインコメントによるコラボレーション

リアルタイム同時編集とインラインコメントも当たり前となり、オンライン上のテキストベースの議論やレビューが活発に行われるようにもなりました。

また、導入のきっかけとなった「チーム日報」については私が所属するテクノロジー推進部にとどまらず複数のチームのものが毎日更新されるようになり、新たなコネヒトの文化となっています。

課題や不満ももちろんある

Notion はかなり自由度が高く利用できるため、ページの階層や、データベース自体の整備はまだやりきれていないというのはあります。特に導入時は「まずNotionに触ってもらう」事が重視されるので必要ではあるもののどうしても後手になりがちですし、各チームでのワークフローに依存するところもあるのでボトムアップでのアプローチはなかなか難しいです。

また、実際に業務で利用してみると導入時点では見えていなかった不満が出てきている部分もあります。Slack通知か細かすぎてあまり柔軟にコントロールできないことや、メンションに続けて日本語入力をする際の挙動が安定しないところなどは改善してもらいたいところです。

それでも、Notion の導入は確実に組織にとってプラスになった

課題もあるものの、Notion導入を通じてコネヒトにおける業務をより濃密なものとなりました。

職種関係なく一つの会社のメンバーが平等に利用できるオンライン上のコラボレーション環境として、大いにその力を発揮しているのは間違いないです。Notion を選定する際に「ドキュメントツールと言うより、オンライン上でテキストベースのプロジェクト・ToDo管理、議論、社員の活動の可視化などのコラボレーションを加速させるものがいい」としていた期待には大いに応えてもらっています。

さいごに

Notionはコネヒトにおける利用状況は全社員で平等に利用できるようになった段階で、まだまだ未成熟な部分も多いため、これからも発展させていく段階ではあります。しかし、Slack・Zoomと並び業務になくてはならないものとなりました。

あわよくば、この記事が少しでもNotionの導入を検討している方の助けとなれば幸いです。


明日の コネヒトアドベントカレンダー2022 は PdM の @soracoco440 の記事です。 お楽しみに。

ママリへのSwiftConcurrencyの導入

こんにちは!コネヒトでiOSエンジニアをやっていますyanamuraです。

Xcode13.2からSwift ConcurrencyがiOS13からでも使えるようになり、遅ればせながらママリのiOSアプリでSwift Concurrencyを導入してみました。

ママリのアーキテクチャ

現在ママリのiOSアプリのアーキテクチャはMVVMになっています。 全体的にRxSwiftを用いてView, ViewModelのbindingだけでなく非同期処理を実装していて、新しく追加したところはCombineを使っているといった状況です。

どこに導入したか

今回Swift Concurrencyを導入したのは、Web APIとの通信部分です。これまではRxSwiftやCombineを用いて通信の非同期処理を行なっていました。しかし、基本的やっていることは通信して終わったら処理をするといった単純なことで、reactiveなことをしなくてcompletion handlerやResult型などでも事足りる感じでありました。Swift Concurrencyを導入することでasync/awaitでシンプルに書け、RxSwiftの依存部分を減らすことができないかと考え今回試してみました。

実装

通信周りは外部ライブラリに頼らずシンプルにURLSessionで実装していたので、以下のようなfunctionを用意してasync/awaitを使えるようにしました。

// 例 (見やすくするためかなり端折ったものでこのまま使わないでください)
func request(url: URL) async throws -> Data? {
    try await withCheckedThrowingContinuation { continuation in
        let task = URLSession.shared.dataTask(with: URLRequest(url: url)) { data, response, error in
            if let error {
                continuation.resume(with: .failure(error))
            } else {
                continuation.resume(with: .success(data))
            }
        }
        task.resume()
    }
}

呼び出す時はawaitすることで同期っぽく書けるようになります。

let data = try await API().request(url: URL(string: "https://connehito.com")!)

このawaitする関数自体も結果待ちする場合はasyncし

func fetchUserID() async -> UUID {
  let data = try await API().request(url: URL(string: "https://connehito.com")!)
  … // dataをparseしてuserIDを取得

  return userID
}

結果待ちしなくてもいい場合はTaskで投げっぱなしにします。

func refresh() {
  Task {
      let data = try await API().request(url: URL(string: "https://connehito.com")!)
      …. // dataをparseしてuserIDを取得
      
      self.userID = userID
  }
}

まとめ

RxSwiftだとこんな感じだったものが

func fetchUserID() -> Observable<UUID> {
  return API().request(url: URL(string: “https://connehito.com”)!)
      .map { data in// dataをparseしてuserIDを取得
          return userID
      }
}

async/awaitを使うと直感的な記述になりました。

func fetchUserID() async -> UUID {
  let data = try await API().request(url: URL(string: "https://connehito.com")!)
  … // dataをparseしてuserIDを取得

  return userID
}

一部に導入してみて割と良い感じだったので、どんどん使っていきたいと思います!


コネヒトでの開発に興味を持っていただいた方はカジュアルにお話しましょう〜
TwitterのDMなどでも大丈夫ですのでお気軽にどうぞ
日本中の家族をITの力で笑顔にしたい、iOSエンジニア募集! - コネヒト株式会社のモバイルエンジニアの採用 - Wantedly

BigQueryのシャーディングされたテーブルをOpenSearchへ連携する方法

皆さん,こんにちは!最近は検索エンジニアとしての仕事がメインの柏木(@asteriam)です.

はじめに

今回はTips的な記事になります.背景としては,アプリの検索ログをBigQueryに溜めているのですが,それを検索エンジンのサジェスト機能で使用するために,BigQueryからAmazon OpenSearch Serviceへデータ連携を実施しました.その際にBigQueryのシャーディングされたテーブルをどのようにして連携したかというお話になります.

検索システムのデータ基盤構築に関する過去のブログでも紹介していますが,我々はGlueを用いて検索エンジン(OpenSearch)へのデータ連携を行っています.今回はGlueを用いる点は同じですが,データソースはBigQuery,ターゲットソースをOpenSearchとしてデータ連携しました.

今回は以下の内容を紹介していこうと思います.

  • BigQuery→OpenSearch連携の概要
  • BigQueryのシャーディングされたテーブルを連携する方法

目次


BigQuery→OpenSearch連携の概要

今回紹介するデータ連携は至ってシンプルです.

下図にあるように,BigQueryにある検索ログをGlueでExtractし,検索エンジンであるOpenSearchへLoadする流れになります.

  • データソース:BigQuery
  • ターゲットソース:OpenSearch

データパイプラインの概略図

Glueには,BigQueryに接続するためのコネクターが用意されており,簡単に連携ができるようになっています.接続方法の手順はクラスメソッドさんのブログが参考になるので,そちらに譲ろうと思います.(コネクターをSubscribeする画面にも英語ですが,説明が記載されています)

参考:AWS Glue Connector for Google BigQueryを使ってBigQueryからS3にデータを転送する

データソース(BigQuery)の設定では,BigQueryのプロジェクトIDや連携したいテーブルIDなどの情報が必要になります.一方で,ターゲットソース(OpenSearch)の設定では,インデックス名やエンドポイント名などが必要になります.

ここで,連携したいBigQueryのテーブルは日付でシャーディングされており,そういったテーブルをどうやって連携するかが問題になります.

BigQueryのシャーディングされたテーブルを連携する方法

日付でシャーディングされたテーブルとは,下図のようにtable suffixが日付になっていて,日ごとにインクリメントされた形式のテーブルのことを言います.

シャーディングされたテーブル

このようなテーブルを連携したい場合にどうすればいいか?

Connection optionsのKeyにqueryを使う

BigQueryコネクターのConnection optionsに幾つかの設定が必要になりますが,そのうちの一つとして,queryというkeyを使うことでシャーディングされたテーブルの連携に対応することができます!

参考:Push down queries when using the Google BigQuery Connector for AWS Glue

下図はGlue StudioでのBigQueryコネクターの設定画面になります.

BigQueryコネクターで設定する内容は4つになります.

  • materializationDataset: <BigQuery側で連携用に一時的に作成するデータセット名>
  • parentProject: <プロジェクトID>
  • viewsEnabled: <ビューの許可>
  • query: <データ抽出するためのクエリ>

Glue Studio: BigQueryコネクターの設定

queryには実行したいクエリをそのまま入力します.例えば,現在から30日前までの検索ワードとそのカウント数を集計したデータを抽出したい場合は,以下のような感じになります.

SELECT
    word,
    count(word) AS word_count
FROM `hogefuga.search_events_*`  # 検索ログが入ったテーブル
WHERE 0 = 0
AND _TABLE_SUFFIX >= FORMAT_DATE('%E4Y%m%d', CURRENT_DATE('Asia/Tokyo') - 30 )
GROUP BY word

ただし,注意点があります.

  • materializationDatasetに設定するデータセットは予めBigQueryに作成
    • 試行錯誤の結果,データセットがない場合にGlueは勝手に作ってくれず,エラーになってしまうので,予め作成しておく必要があります
    • 加えて,このデータセット配下に一時的に作られるテーブルに対するwrite権限が必要で,それがないとエラーになります

最後に,OpenSearch側の設定も載せておきます.

  • path: <インデックス名>
  • es.node: <エンドポイント名>

Glue Studio: BigQueryコネクターの設定

おわりに

単一のテーブルは簡単に連携できたのですが,シャーディングされたテーブルを連携する時にハマってしまったので,今回のTipsが誰かの役に立てば幸いです!GCP側の権限などはハマりポイントかなと思うので,試しながら試行してみて下さい.

検索ログが連携できたことで,サジェスト機能も前進しているので,これからも検索エンジンの改良を進めて行こうと思っています!

最後に,コネヒトではプロダクトを成長させたいMLエンジニアを募集しています!!(切実に募集しています!)
もっと話を聞いてみたい方や,少しでも興味を持たれた方は,ぜひ一度カジュアルにお話させてもらえると嬉しいです.(僕宛@asteriamにTwitterDM経由でご連絡いただいてもOKです!)

www.wantedly.com

また,コネヒトにおける機械学習関連業務の紹介資料も公開していますので,こちらも是非見て下さい!!

tech.connehito.com

参考

スキルマップを使ったチームビルディング

こんにちは!エンジニアの富田です。先月末に開催したスキルマップを使ったチームビルディングがとても良かったので、内容を紹介したいと思います。

なぜやろうと思ったのか

前提として私が所属しているプロダクト開発チームは以下の構成です。

  • PdM 1名
  • デザイナー 2名
  • エンジニア 4名

ご覧の通り職能横断型のチーム構成になっており、チームとして4ヶ月ほどプロダクト開発を進めているのですが、お互いのことをあまり知らないなと感じることがありました。もちろん自己紹介をしたり、スクラムの朝会でちょっとした小話をしているのですが、なかなか自分の得意なこと、苦手なことを開示する機会がありませんでした。

自己開示することで、自分のことを知ってもらったり、周りのことをより知ることができるので、結果としてパフォーマンスやモチベーションが向上するのではないかと考えました。何かしらチームビルディングのワークをやりたいと考えていたものの、稼働時間の限られている業務委託メンバーも一定数いるため、「作業時間を奪ってしまうかもしれない?」という懸念からなかなか一歩踏み出せませんでした。

そんな困っていた中、弊社のデザイナーチームが「スキルマップは自己紹介、リモート前提の業務設計ですごく役立つよ」と話していて、これは簡単で面白そうだと思い、スキルマップの進め方及びテンプレートを教えてもらい、スキルマップを使ったワークを試す運びとなりました。

どんなことをやったのか

好き・嫌い、できること・できないこと、を軸にして、付箋を貼ってチームメンバーで共有するというものです。それぞれ発表した後、チームの他のメンバーが「得意そうだとと思っていること」「苦手そうだと思っていること」を付箋に書いていって、認知のずれを確認し合うワークです。

スキルマップのテンプレート

テンプレートは上記の通り Miro で作成しており、3つのステップに大別されます。

1.(事前準備)自分のスキルを黄色の付箋に書いて貼ってみよう

  • ハードスキルでもソフトスキルでもOK
    • ハードスキル:Swift、PHP、Photoshop・Notionを使ったタスク管理
    • ソフトスキル:ファシリテーション・コミュニケーション、誰とでも仲良くなれる

自分のスキルを付箋に記入して、好き・嫌い、できること・できないこと、を軸にマッピングします。 一見簡単そうに見えますが、自分のスキルと聞かれてパッと思いつく人は少ないのではないでしょうか。 実際、事前準備なしにワークをしたところ、悩んでいるメンバーも多く、付箋を書くのに15分ほどかかりました。 ですので、スキルに関しては事前に記入してもらうと、効率的にワークを進められるのでオススメです。

2.参加メンバーに自分のスキルを発表します

  • 1人5分程度で発表します。ポジティブな話題の方が共有しやすいため、右上の得意なところから時計回りに話していくと良いです
  • メンバーはチャットなどで感想を書いたり、質問をしてみましょう
  • また、周囲から見て得意そうなこと・苦手そうなことを付箋に書いていきます

マッピングした内容を各自共有します。周囲からのコメントは周りにどう思われているか知る良い機会ですので、ぜひ感想や質問、または周囲から見て得意そうなこと、苦手そうなことを付箋に記入してみてください。

3.周囲から見て得意そうなこと・苦手そうなことをマッピングします

  • 他のメンバーの認知と自分の認知の違いを見てみましょう
  • ギャップがある時はなぜそこにマッピングしたかを議論してみましょう

周囲から記入してもらった得意そうなこと、苦手そうなことをマッピングします。周りから見て得意そうなことが自分にとっては実は苦手だったまたはその逆も然り。マッピングすることで暗黙知のギャップを埋めることができます。

結果はどうだったのか

実際にスキルマップを使ってワークを試してみました!

実際に試したスキルマップの一部

メンバーのコメントをいくつか抜粋します。

  • デザイナーだけどフロントエンドの実装もしたい!
  • 周りからは取捨選択得意そうに見えていたけど、ちょっと苦手に感じていた
  • グラフィックデザインはできるんだけど、あんまり好きではない
  • ファシリテーションが苦手なんだけど、周りは得意だと思ってくれていた
  • コンテンツディレクションをしているけど、コンテンツ制作が若干苦手

結果として意外な発見も多く、認知のギャップを解消できました。今回のように職能が異なるメンバーが混在したメンバー編成時に試すと効果が高いと思います。

最後に

スキルマップを使って「得意そうだと思っていること」、「苦手そうだと思っていること」の認知のギャップを埋めるワークを紹介しました。

当初の「お互いのことをあまり知らない」という課題感に対して、一定の暗黙知を解消できたように思います。同じような課題感をお持ちでしたら、コストも低く、試しやすいワークになっていますのでお試しください。

直近ではドラッカー風エクササイズも試していますので、よろしければご覧ください。 tech.connehito.com

コネヒトでは一緒に働く仲間を募集しています! そして興味持っていただけた方は気軽にご連絡ください!

www.wantedly.com

Character filterを用いたアルファベットの大文字小文字対応によるゼロ件ヒット改善

皆さん,こんにちは!最近は検索エンジニアとしての仕事がメインの柏木(@asteriam)です.

直近は,検索基盤が整ってきたので,検索エンジンの精度改善の取り組みを行っています.その一環としてゼロ件ヒットの削減に努めていて,今回は「アルファベットの大文字小文字」に対応した話になります.

はじめに

改めて,今回は「検索クエリにおけるアルファベットの大文字小文字に依らない検索結果」を出すための取り組みとして,Character filterを用いて検索クエリを正規化することでこの問題に対処した内容になります.

今回は以下の内容を紹介していこうと思います.

  • 取り組みの背景と課題
  • Character filterを用いた正規化
  • 対応後のゼロ件ヒットの推移

※ 検索エンジンとしてAmazon OpenSearch Serviceを活用しています.これはElasticsearchから派生したOSSの検索エンジンであるOpenSearchのマネージドサービスになります.


目次


取り組みの背景と課題

背景

私たちのチームでは検索結果の改善を行うためにゼロ件ヒットのログを収集しています.僕はそれを毎日眺めているのですが,その中でドキュメントとして存在してそうなワードが含まれているのに何故かゼロ件ヒットとして検索されている回数が多いものがあったため,調査したのが始まりです.

実際のゼロ件ヒットワードの一例ですが,「hpvワクチン」というワードがありました.小文字では検索結果が0件でしたが,これを大文字の「HPVワクチン」で検索するとドキュメントが数十件と返ってくることを確認しました.

このように幾つかのワードで,アルファベットの大文字小文字の違いによるゼロ件ヒットを確認し,中にはゼロ件ヒットワードとして,2~3週間で数百件以上検索されているものもあったので,この問題の解決に当たろうと思いました.

課題

課題としては明確で,アルファベットの大文字と小文字の違いだけで検索結果が変わってしまいユーザーの検索体験がマイナスになっている ということです.そもそもドキュメントが存在しない場合と違って,僕たちのドメインでは普通に使われうるワードでゼロ件ヒットしてしまうことは,検索に対する期待も下がってしまいますし,アプリからの離脱も発生します.

また,この問題は登録しているユーザー辞書による影響もあり,以前からユーザー辞書の整理は必要だと考えられていたため,そこをまとめて整理する良い機会でもありました.

Character filterを用いた正規化

前提理解

この問題を解決するためには,ElasticsearchにおけるAnalyzerの処理の流れを理解する必要があります.

  1. 0個以上Character filters
  2. 1個かつ必須Tokenizer
  3. 0個以上Token filters

参考:Anatomy of an analyzer

こちらの図がわかりやすいので,引用(Elasticsearch のアナライザをカスタマイズする)させて貰います.

引用:Elasticsearch のアナライザをカスタマイズする

上図では,それぞれどのような動きをしているかというと,

  1. HTML要素を除去するCharacter filter
  2. 空白で分割するTokenizer
  3. 大文字を小文字に変換するToken filter

となっています.

ここで,ユーザー辞書が適用されるのは2番目のTokenizerを行う部分になります.我々が元々設定していたAnalyzerの定義では,Character filterとしてicu_normalizerのみを適用してました.Token filterはTokenizerの後に適用されるため,ユーザー辞書に基づいたトークナイズが優先され,アルファベットの大文字ワードをToken filterで小文字化しても別ワードとして処理される状況でした.このためシノニム辞書を用意していても別ワードとして処理されます(大文字と小文字は別物になってしまいます).

対応方法

この解決方法としては2種類あると思います.

  1. Character filterを使ってアルファベットの大文字を小文字にする(Character filterによる正規化)
  2. API側で検索エンジンに入れる前にアルファベットの大文字を小文字にする

そして,辞書に登録するワードは全て小文字で登録する.

今回は,検索されたワードは検索エンジン側で処理が全て完結するようにしたかったため,1番目の方法で対応することにしました.

処理の追加自体はとても簡単で,下のサンプルコードのように,char_filterに新しくフィルターを追加し,そのmappingsに愚直に大文字と小文字の変換を入れるだけになります.

# sample
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "standard",
          "char_filter": [
            "alphabet_mappings_filter"
          ]
        }
      },
      "char_filter": {
        "alphabet_mappings_filter": {
          "type": "mapping",
          "mappings": [
            "A => a",
            "B => b",
            "C => c",
            "D => d",
            "E => e",
            "F => f",
            "G => g",
            "H => h",
            "I => i",
            "J => j",
            "K => k",
            "L => l",
            "M => m",
            "N => n",
            "O => o",
            "P => p",
            "Q => q",
            "R => r",
            "S => s",
            "T => t",
            "U => u",
            "V => v",
            "W => w",
            "X => x",
            "Y => y",
            "Z => z"
          ]
        }
      }
    }
  }
}

あとは,ユーザー辞書とシノニム辞書に登録されているアルファベットを全て小文字に変更することで,大文字と小文字の区別なく検索結果として同じ結果が返ってくるようになります.

1つ注意事項として,今回のようにAnalyzerの定義が変更されて,それに伴って辞書の更新が入る場合は都度インデックスの再作成が必要になるので注意が必要です.

事象としては,辞書が変更されたことにより,元々インデックス化されていたトークンとの整合性が取れずに何もヒットしない状態でした.改めてインデックスを作り替えることで,トークンが正しい状態でインデックス化された状態になりヒットするようになります.

対応後のゼロ件ヒット率の推移

ゼロ件ヒット率の推移を見てみると,下図から今回の対応前後で数値が減少していることがわかります.実際の割合で言うと,減少率は1%以下ではあるものの,検索数ベースだと数百件は減っていることになります.

ここで,ゼロ件ヒット率=全検索数のうち検索結果が0件であった検索数の割合と定義しています.

ゼロ件ヒット率

今回の施策では,他の「検索利用率・1訪問あたり平均検索回数」といったメトリクスには影響は見られませんでした.

そもそもゼロ件ヒットの検索数は全検索数のうち数%しかないため,改善できる幅はそれほど大きくなく,減少率で言うと大きな改善にはなっていませんが,ゼロ件ヒットの上位ワードは今回の対応で改善できたので,よりニーズのあるワードへの対策は実施できたのと,ドキュメントが存在しているのにヒットしないのはユーザー体験にも大きく影響するので,実施したことに価値はあったと考えています.

おわりに

今回はCharacter filterを用いてアルファベットの大文字小文字対応(Character filterによる正規化)を行いました.その結果としてゼロ件ヒットの削減に貢献できました!

今回の改善でも実感しましたが,トークナイズに影響を与える辞書整備は重要で,その整備がまだまだ十分行えていないので,ガッと進めて行きたいと思っています.

また,捨て仮名/中点対応,ひらがな/漢字対応なども今後進めて行く予定です!

千里の道も一歩からということでゼロ件ヒット削減に向けて,今回の取り組みや辞書更新,今後の取り組みを通して,小さな積み重ねでユーザー体験の向上目指して改善して行きます!

最後に,コネヒトではプロダクトを成長させたいMLエンジニアを募集しています!!(切実に募集しています!)
もっと話を聞いてみたい方や,少しでも興味を持たれた方は,ぜひ一度カジュアルにお話させてもらえると嬉しいです.(僕宛@asteriamにTwitterDM経由でご連絡いただいてもOKです!)

www.wantedly.com

また,コネヒトにおける機械学習関連業務の紹介資料も公開していますので,こちらも是非見て下さい!!

tech.connehito.com

参考

ドラッカー風エクササイズをやってみました!

こんにちは。コネヒトに8月に入社し、サーバーサイドエンジニアをしている高橋です。

今回は私自身のチームジョインや、更なる新メンバーのジョインもあったので、「お互いを理解し期待をすり合わせる」ことを目的に「ドラッカー風エクササイズ」を開催しました! オンラインでも開催できるように今回はmiroを使って実施したので、ご興味ある方はぜひご覧ください。

目的・背景

  • メンバーのスキルや経験、価値観、期待値などをお互いに理解し、期待をすり合わせる

→背景は新メンバージョインに伴いチーム人数が多くなったので、チーム内でお互いの得意なことや期待値を把握し、理解促進を図りたいと思ったからです。

ドラッカー風エクササイズとは

ドラッカー風エクササイズとは、アジャイルサムライの著者Jonathan Rasmusson(ジョナサン・ラスマセン)が名付けたチームビルディングのことです。 4つの質問に全員が答えることで、相互理解の促進と期待の擦り合わせという効果があります。

ワークの進め方

今回は9人で実施をしたので進め方を工夫しました。

  • 事前にワーク内容を伝え、自己開示パートの3つの質問はある程度考えてきてもらう
  • タイムマネジメントをしっかりと行う

今回は90分の枠をとって実施をし、以下のような流れで行いました。

  1. 導入 (5分)
  2. ワーク内容の説明 (5分)
  3. チェックイン (2分)
  4. ワーク (60分)

    自己開示パート 以下の3つの質問に回答してもらい、本人から説明していただきます。

    • 自分は何が得意か
    • 自分はどういう風に仕事をするか
    • 自分が大切に思う価値は何か

    各質問を最大3つに絞ることで自分の中でも特に大切にしている価値観が整理することができます。

    期待値パート

    • 自分がメンバーから期待されていると思うこと この質問は先入観が生まれないよう紹介はせずに以下の回答をそれぞれが他のメンバーに書いていいきます。

    • 自分以外のメンバーがその人に期待していること その後ファシリテーターから上記2点を紹介し、なぜこの人にこう書いたか、どういった背景で書いたのか、など深掘りを一人ずつしていきます。

    • ファシリテーターが一人ずつ発表

  5. 感想一人一言 (10分)

また今回急に参加が難しくなってしまったメンバーに対しては、事前に付箋を記入してもらい、他のメンバー同様に期待値なども欠席者のところに貼るようしました。そして後日ワークの動画を共有しました。 ワークの様子を動画で正確に残せるのはオンライン開催の良いところですね。

注意点

目的は期待をすり合わせることになるので、ワークをする上で以下の2点留意しましょう!

  • メンバーを否定しない
  • 期待されていることは鵜呑みにしない→絶対にやらなくてはいけないということではない

私は過去にドラッカー風エクササイズを行い、自分が思う期待値とメンバーからの期待値に違いがあり少しマイナスな印象を抱いてしまったので、あくまで意見として捉えることが大事です。

感想

メンバーのことを知れるというのはもちろんですが、自分の価値観を整理できるいい機会になったと強く感じることができました! 私は一児の母ということもあり、メンバーからの期待してることに「当事者ならではの視点」という付箋が多く自分がどう期待されているか具体的に知ることができました。 また「遠慮しないでもいいよ」というような付箋もあり、もっとこうしていいんだというこれからの動き方にもいい変化が出てきそうと感じました。

改善点

  • 期待値が現状行っていることの延長線上が多い
    • こうしたらよかったんじゃないか?みたいな課題に対するアクションもセットで書けると良さそう
  • 自己開示パートの時間が少し短かったので、メンバーの価値観を知り切れなかった
  • 自己開示パートは事前記入しておいてもらった方がスムーズだったかも
  • チームとして何を目指すかなどが話せなかったこと

メンバーからの感想も一部挙げておきます。

  • 自分で思いつかなかったポイントで期待されている側面は学びになりました!
  • 改めて自分が大事にしていることってなんだっけ?を見つめ直すいい機会になりました!
  • 各メンバーがそれぞれ、自分に対してもしくは他人に対して感じるものを言語化したことで、自己認識・他者認識の再構築ができて良かった。
  • 新メンバー参画の際にまたやりたい!
  • 定期的にやりたい

まとめ

今回のドラッカー風エクササイズを通じてメンバーからはポジティブな意見が多く、開催してよかったなと思っています。人の価値観、モチベーションなどは変化していくものでもあると思うので、定期的にチームビルディングを開催していきたいです。 すごく良いチームであるのでもっともっとお互いに刺激し合えるチームになっていけたらと思っています。

過去のチームビルディングのブログ記事↓ tech.connehito.com

tech.connehito.com

コネヒトでは一緒に働く仲間を募集しています! そして興味持っていただけた方は気軽にご連絡ください! https://www.wantedly.com/companies/connehito/projects