Classi開発者ブログ

教育プラットフォーム「Classi」を開発・運営するClassi株式会社の開発者ブログです。

Classiのエンジニア2名が RubyKaigi 2024 に参加しました

はじめに

こんにちは、エンジニアの id:kiryuanzu です! 今回の記事は 5月15日(水)から 5月17日(金)の3日間を通して開催された RubyKaigi 2024 の参加レポートです。

rubykaigi.org

弊社からは 2名のエンジニアが参加しました。本記事では各メンバーによる参加レポートをお送りします。

id:kiryuanzu の参加レポート

改めて今回の RubyKaigi 2024 に参加してきた id:kiryuanzu です。
自分自身は学生の頃(2017年)からほぼ毎年参加していますが、弊社のメンバーと参加するのは RubyKaigi 2022 以来で 2年振り 2回目となりました。

tech.classi.jp

前回と同じく初参加のメンバーにもできる限り楽しんでもらえるように意識しつつ、自分もたくさんインプットできるように心がけて過ごすようにしました。

発表の感想

Community-driven RBS repository (pockeさん)

Rubyの型情報を収集するOSSリポジトリである gem_rbs_collection の運用についての発表でした。
GitHub Actions のワークフローの仕組みを使いつつメンテナのレビューに依存しない運用に切り替えていった話について紹介されており、筆者もここ最近の業務で GitHub Actions を使って運用フローの効率化について考えていたため、とても親近感が沸く内容でした。
OSSリポジトリの場合、様々な人がコントリビューターとして関わる際に開発の効率性とセキュリティのリスクの双方を気にしつつ運用フローを考える必要があるのが難しいポイントだなと思いました。

発表が終わった後、早速ワークフローのコードを見に行ったのですが、ワークフロー内で呼び出すスクリプトを全部 Ruby で書いている点に強い Ruby愛を感じました。

github.com

スライド内でも「It uses Ruby scripts Because I love Ruby」と言及されていますね。

Adding Security to Microcontroller Ruby (sylph01さん)

PicoRuby に暗号機能を実装する話についての発表でした。
現地では英語発表で分からない部分も多かったのですが、とても楽しそうに話されている姿が印象に残っていました。その後、るびま(Rubyist Magazine)で日本語版が公開されていて改めて発表の内容について知ることができました。

magazine.rubyist.net

記事中の「Ruby での真のIoT」という表現がかなり印象的で、今後もまだまだやれることがありそうな雰囲気を感じました。

実際の IoT 環境ではこれらの違ったスペックを持つハードウェアは協調して動作させるので、PicoRuby が WiFi に繋がるようになったことで、「Ruby での真の IoT」は現実に近づいたといってよいでしょう。IoT に関するプロトコルは数多く存在しており、これらを PicoRuby で扱えるようにすることで、Ruby での IoT の可能性は広がっていくものと考えられます。このことから、Ruby での IoT は「ブルーオーシャン」であるといえます。コミュニティは皆さんのコントリビュートをお待ちしています。

自分は PicoRuby 自体書いたことがなかったのですが、他の発表でも多く言及されていたトピックの一つで「なんだかみんな楽しそうにやってていいな……」と思い会期終了後にRassberry Pi Pico W を購入しました。
まずは以下の記事を見ながらLチカチャレンジしてみようと思います。(この記事の執筆者の hasumikin さんは PicoRuby/R2P2 の開発者かつ今年の RubyKaigi のスピーカーの方です)

shimane.monstar-lab.com

発表以外で印象に残ったこと

会期中の社外の方々との交流についてはいもりさんのパートでたくさん取り上げているので、id:kiryuanzu のパートでは RubyKaigi に絡めて行われた社内での活動についてピックアップします。

今回の現地参加組はいもりさんと私の2人だけでしたが、社内の Slack で #spot-rubykaigi-2024 チャンネルを作って、会社のメンバーに向けて発表の感想や現地での出来事をその都度発信するようにしました。
今回は現地参加されなかった方々も、発表の解説ツイートや私たちの発言に対して反応してくださり一緒に楽しむことができました。

社内slack での様子

また、今年の4月から株式会社万葉から参画し、tetoru チームで関わってくださっている櫻井さんも RubyKaigi に参加されていました。
イベント直前に社内で企画した予習会では、初参加の人向けの RubyKaigi の楽しみ方についてお話ししていただき、会期中にも交流の機会をたくさん作っていただきました。
会期中は Classi Tシャツも着てくださっていたのが大変嬉しかったです。なんとよく見ると名札の方にも tetoru のロゴを手書きで描いてくださっています。

RubyKaigiが終わってすぐのタイミングで、会期中に印象に残ったことについて語る会も実施しました。
筆者が「パーサーについてみんなどうやってインプットしてるんだろう……」とぼやいた際に、同僚の方から「まずはインタプリタの作り方の第二部まで読むのがおすすめです」とアドバイスをもらい読むことにしました。紙の本を購入したところですが、中々の分厚さにびっくりしています。

(当時の会話をメモした社内esaを一部抜粋)

そのようにして、現地参加組とリモートで見守ってくれたメンバーの間で交流を深めつつ一緒に RubyKaigi の空気感を楽しむことができました。
来年はもっと多くのメンバーに現地参加してもらえるよう社内での発信を続けていきたいです。

いもりの参加レポート

2024年4月に新卒入社したいもりです!

今回、ありがたいことに新卒研修期間中にRubyKaigiへ参加する機会をいただきました。 ところが当時私のRuby学習歴はたったの4日…

そんな人間のレポートとなっています。生暖かい目でご覧ください。

参加しての感想・交流について

第一印象として、とにかく新参者に優しいコミュニティでした!

交流の場として、日中はRubyKaigiで知り合った人と一緒に昼食を食べたり、夜には多くの交流の場が設けられていたのでそちらに参加したりしました。
その場では初学者でも非常に温かく出迎えてくださり「今日の発表は何が印象に残った?」「普段はどんな研修を受けているの?」など、私の目線で会話に加えていただいたことが本当にありがたかったです。

登壇者の方ともお話しする機会に恵まれ、RubyKaigiの沿革や、登壇者ならではの苦労などを話していただきました。
特に「自分が発表している時間の発表を聞きに行きたいんだ!」という一言は忘れられません。

また、私は現在フィヨルドブートキャンプにて研修しているのですが、同じフィヨルド生の方とも交流できました。
研修で使っている『ゼロからわかる Ruby 超入門』の著者であり、Classiの新卒研修の設計に携わられていたigaigaさんとも快くお話ししていただき、サインもいただきました。大事にします!

発表

全体として、登壇者の方々が「この技術はこの方の登壇を聞けばより詳しいことがわかる 」と、他の方の発表を引用し合っているのが非常に印象的でした。

これは本当に素晴らしいことだと思います。Rubyコミッターの方々が互いを知り、また信用していないとできない引用だと思います。 改めてRubyコミュニティの活発さを感じ取った瞬間でした。

ここでは特に印象に残った発表3つについて、簡単ではありますが感想を書かせていただきます。

Writing Weird Code

初日トップバッターのキーノートの登壇です。 正直なところ、この発表がなければ私はRubyKaigiを楽しめていなかったかもしれません。それくらい衝撃的で感銘を受けた発表でした。

内容としては、irbで奇妙なコードを書くというものです。その奇妙さが本当に強烈でした。

これは紹介された一例ですが、irb上でコードのクラゲが泳ぎ、マウスでクリックするとそれに反応して変形するという内容です。

この発表では、この他にも視覚的に楽しむことができる奇妙なコードが合計で6つ用意されており、そのどれもが本当に衝撃的でした。

肝心の実装についての説明はあまりに高度な内容で、会場含め「…?なるほど…ね?」という反応にならざるを得ませんでしたが、irbすごい!これから使っていこう!と思えた発表でした。

Cross-platform mruby on Sega Dreamcast and Nintendo Wii

こちらは1日目午後の登壇でした。内容としては、mrubyを用いてNintendo WiiとDreamcastのクロスプラットフォームを作成するというものでした。

この方の発表はとてもゲーム製品への愛が伝わってくる内容で、ゲームコントローラーがいわゆるスライドポインターの働きをしており、登壇中は軽快にWiiコントローラーを振っていました。また、Tシャツが非常に個性的でした。

この発表で驚いたのは、最初はまた個性的だと思っていた発表スライドが、実は起動したゲーム内でテキストを表示させていたことでした。

発表の後半ではDreamcastを起動していたのですが、先ほどまで見ていた全く同じテキストが、Dreamcastのフォントで表示されていることに気づいた時は鳥肌が立ちました。

Ruby Committers and the World

こちらは3日目最初のRubyコミッター同士の対話形式登壇でした。 内容としては、2日目深夜にRuby3.4.0-preview1がリリースされたこと、そしてこれからのRubyについて議論するという内容で、活発に意見が交わされていました。

この対談で印象的だったのは、コミッターの方が現在検討しているRBSの文法について、参加者がどちらを好むか多数決で世論調査を行ったことでした。
この多数決が将来のRBS文法を決めるものになるかもしれないと思うと、Rubyコミュニティに少し関わることができて嬉しかったです。

また、対談は日本語と英語の二か国語で実施されたのですが、途中からMatzさんによる同時翻訳が始まったのが面白くもあり、非常にありがたかったです。

まとめ

今回、先輩の id:kiryuanzuさんを通して多くのRubyistの方とお話しさせていただきました。貴重な交流の時間、本当にありがとうございました。

また、株式会社万葉から参画しClassiに携わっていただいている櫻井さん、社内から後押ししてくれたClassiメンバーの皆さん、RubyKaigiを運営していただいたスタッフの皆さん、その他ランチや飲み会の場で交流をしていただいた方々に深く御礼申し上げます。

次回は愛媛県松山市開催ということで、関西在住の私にとっては比較的好立地なこともあり、ぜひ参加したいです。

これからもRubyコミュニティに関わっていき、一人前のRubyistを目指します!

おわりに

以上、Classi メンバーの感想レポートをお届けしました! 今回の RubyKaigi での経験を経て普段の業務や趣味の開発を頑張っていこうという気持ちを改めて持てました。

RubyKaigiの翌週には Classiオフィスで開催された shinjuku.rb #92 ではいもりさんが「RubyKaigi 2024 行ってきたレポ」というタイトルでLT発表をされていました。

tech.classi.jp

このように早速コミュニティ活動へと飛び込んでいく姿を見せており、RubyKaigi での経験が後押しになったとしたら嬉しい限りです。

来年の4月には愛媛県松山市で RubyKaigi 2025 が開催されます。その時に向けて日々の生活の中で学びを重ねつつ、今回よりも更に RubyKaigi という非日常の場を楽しめるようになりたいです。

来年もまた RubyKaigi でお会いしましょう!

Strict CSP を Content Security Policy Level 3 に対応したブラウザに絞って適用する

こんにちは、プロダクト本部エンジニアの中村 (kozy4324) です。

現在 Classi が提供している Web サービスでは Content Security Policy を導入しています。その導入時の話は以下の記事で紹介させてもらいました。

今回の記事では、運用を続けていく中でわかったことや出てきた課題、またそれらを踏まえて現在どういった CSP のポリシーで運用を行っているのか紹介します。

オリジンの許可リストをベースにしたポリシー

導入時の記事でも紹介している通り、運用開始時のポリシーは以下のようなものでした。

Content-Security-Policy:
  default-src 'self';
  script-src  example.com 'sha256-xxx' 'nonce-hogehoge111';
  style-src   example2.com 'sha256-yyy';

ベースは ’self’ (文書が提供されたオリジンと同一オリジンのリソースを許可する)とホスト名による許可リスト方式で、特定のインラインコードやインラインスタイルを追加で許可したい場合にハッシュ値や nonce を追加しています。

最初はできる限り厳格な規格に沿ってポリシーを設定、違反レポートを確認しながら必要に応じてポリシーを追加、もしくは無害と判断できるものは無視するという運用ルールとしていました。

出てきた課題1: オリジンの許可リストベースでは攻撃とは見なせない違反レポートが雑多に出てくる

上記ポリシーで運用を始めたところ、すぐに多くの違反レポートが日々あがってくる状況になりました。ところがそのほとんどがブラウザ拡張機能や 3rd party 製の何かによる img や style 、script の挿入に見受けられ、総合的にみて「攻撃とは見なせない」という判断になるものばかりでした。

Sentryに収集された実際の違反レポートの一部

違反レポート自体にはそれほど多くの情報は含まれておらず、頻度やブラウザの分布なども確認しながら一つ一つ丁寧に調査していく必要があります。新しいレポートが発生するたびに調査対応していくと運用負荷は大きなものになっていきました。

Strict CSP をベースにしたポリシーへの変更

オリジンの許可リスト方式で厳密に制限して運用していくのは運用負荷が大きいということが分かりました。また許可リスト方式では CSP バイパスの問題も指摘されています。なので方針を変更し、nonce + strict-dynamic による Strict CSP をベースにしたポリシーとすることにしました。Strict CSP では XSS に対する防御に重点を置き、基本的にはスクリプトに対してのみ制御を行います。XSS に対して効果の薄いスクリプト以外のリソースには制御を行わないため、スクリプト以外で発生する雑多な違反レポートが抑止されることを期待しました。

Strict CSP をベースにしたポリシーは以下のようになります。

Content-Security-Policy:
  object-src 'none';
  script-src 'nonce-{random}' 'unsafe-inline' 'unsafe-eval' 'strict-dynamic' https: http:;
  base-uri   'none';
  report-uri https://your-report-collector.example.com/

この設定内容は、例えば strict-dynamic をサポートしていないブラウザでのフォールバックが含まれています。 Strict CSP のページでも説明がなされていますが、より詳しく整理したものが以下です。

  • CSP Level 3 まで対応しているブラウザの場合
    • 'nonce-{random}' が採用されるので 'unsafe-inline' は無視される
    • 'strict-dynamic' が採用されるので https: http: は無視される
    • よって nonce + strict-dynamic で許可されたスクリプトだけが実行される
  • CSP Level 2 まで対応しているブラウザの場合
    • 'nonce-{random}' が採用されるので 'unsafe-inline' は無視される
    • 'strict-dynamic' が解釈できないので https: http: が採用される
    • よって nonce で許可されたインラインスクリプトと外部スクリプトだけが実行される
    • nonce が付与されないインラインスクリプトは実行が制限される
  • CSP Level 1 まで対応しているブラウザの場合
    • 'nonce-{random}' が解釈できないので 'unsafe-inline' が採用される
    • 'strict-dynamic' が解釈できないので https: http: が採用される
    • CSPによる実行制限はない(保護されない)
  • CSPに対応していないブラウザの場合
    • CSPヘッダは何も作用しない
    • CSPによる実行制限はない(保護されない)

出てきた課題2: Strict CSP ベースでは一部ブラウザで Google Tag Manager による違反レポートが発生する

Classi サービスでは Google Tag Manager を利用している箇所がいくつかあり、Google Tag Manager が動的に追加するスクリプトで違反レポートが発生しました。これは一部のブラウザのみで発生し、確認したところ CSP Level 2 まで対応しているブラウザ、2024年5月時点では iOS 14.x〜15.3 の Mobile Safari が該当しました。Classi サービスにおいてまだ一定数のアクセスがある状態です。

CSP Level 2 まで対応しているブラウザでは strict-dynamic は解釈されないため、動的に追加するスクリプトの実行を許可するには nonce を付与する必要があります。 Google Tag Manager のガイドに nonce 対応バージョンの言及があるので、この nonce 対応バージョンとすることで問題なく CSP の実行許可がなされると思われましたが、一つ落とし穴がありました。Google Tag Manager の「カスタム HTML 」で追加されるスクリプトタグには nonce を付与することができませんでした。補足として Google Tag Manager 上で「 document.write をサポートする」というオプションを有効にすることで nonce を付与することは可能になりますが、 Classi での利用方法的にこのオプションを有効にすることもできませんでした。

CSPで制御されるスクリプトの種類とディレクティブの整理

ここまでに遭遇した課題をうまく回避できる CSP 設定はないものかと思い、スクリプトの種類とディレクティブについて整理をしてみました。

種類 具体例 制御ディレクティブ ‘self’ と host-source による許可 nonce による許可 strict-dynamicによる許可
外部スクリプト <script src="outer.js"></script> script-src-elem できる できる できる
インラインスクリプト <script>alert(1)</script> script-src-elem できない できる できる
インラインイベントハンドラー <a onclick="alert('clicked')">link</a> script-src-attr できない できない できない
JavaScript URL <a href="javascript:void(0);">link</a> script-src-elem できない できない できない

a タグの href 属性に設定する javascript: で始まるスクリプト記述は script-src-attr ではなく script-src-elem で制御されるというのは押さえておきたいポイントです。

またこの整理の中で strict-dynamic 以外に script-src-elem と script-src-attr の両ディレクティブについても CSP Level 3 からの機能であることに気づきました。 CSP Level 3 に対応していないブラウザではこれらのディレクティブは単純に無視されます。

Strict CSP を CSP Level 3 に対応したブラウザに絞って適用する

上記の整理を行うことで、以下の CSP 設定を導き出すことができました。

Content-Security-Policy:
  object-src      'none';
  script-src      'report-sample' 'unsafe-inline' 'unsafe-eval' https: http:;
  script-src-elem 'report-sample' 'nonce-xxxxx' 'strict-dynamic';
  script-src-attr 'report-sample' 'none';
  base-uri        'none';
  report-uri      https://your-report-collector.example.com/;

この設定における整理は以下の通りです。

  • CSP Level 3 まで対応しているブラウザの場合
    • script-src-elem, script-src-attr によって Strict CSP と同等の効果が得られる
  • CSP Level 2 / CSP Level 1 まで対応しているブラウザの場合
    • script-src-elem, script-src-attr は無視され script-src のみが採用される
    • CSP による実行制限はない(保護されない)

Classiの運用ポリシーとしてインラインイベントハンドラーで違反となるスクリプトについては極力インラインスクリプト形式にリファクタリングをするべきとしています。リファクタリングが妥当でない場合と JavaScript URL については unsafe-hashes で許可をすることも認めており、 script-src-elem と script-src-attr の適切な方にそれぞれ hash を追加していくことになります。最終的には以下のような設定例になっていきます。

Content-Security-Policy:
  object-src      'none';
  script-src      'report-sample' 'unsafe-inline' 'unsafe-eval' https: http:;
  script-src-elem 'report-sample' 'nonce-xxxxx' 'strict-dynamic' 'unsafe-hashes' 'sha256-xxxxxx';
  script-src-attr 'report-sample' 'unsafe-hashes' 'sha256-xxxxxx';
  base-uri        'none';
  report-uri      https://your-report-collector.example.com/;

まとめ

この CSP 運用を続けていく中でわかったことは以下の通りです。

  • オリジンの許可リストベースではレポート運用負荷が高くなり、CSP バイパスという問題も含めると費用対効果の観点では微妙と判断せざるを得ない
  • Strict CSP ベースで Google Tag Manager を利用している場合に、一部ブラウザでの違反レポートが抑止できない問題が発生しうる

CSP のディレクティブを整理することで、 CSP Level 3 に対応したブラウザに限定されますが適切な設定方法が見出せました。行き詰まった時は一度立ち止まって仕様や実装状況を整理することも大事だということを痛感しました。

現在、 Strict CSP をベースにした前述のポリシーで数週間運用をしていますが、違反レポートのノイズも少なく運用負荷も気になるレベルではありません。 Report Only で運用をしていましたが、一部ページでは Report Only も解除し、実際に不正なスクリプト実行には CSP によるブロックがかかる状態にも問題なく移行できています。 CSP の適用範囲を広げ、よりセキュリティ強度の高い設定を目指していくのが次の目標です。

今後も CSP に関わる運用が続いていきますので、また共有できる事例があれば紹介したいと思います。読んでいただきありがとうございました。

Shinjuku.rb#92をClassiで開催しました

ソフトウェアエンジニア&Shinjuku.rbオーガナイザーの onigra です。5/31にClassiオフィスにてShinjuku.rbを開催いたしました。足元の悪い中ご参加くださった方々、本当にありがとうございました。

Shinjuku.rb とは、新宿周辺のRuby技術者たちが気軽に集まるコミュニティです。 ミートアップでは一方的な発表のみならず、ディスカッションを通じたインタラクションを大事にしているのが特徴の1つです。

今回の開催にあたり、同じくShinjuku.rbオーガナイザーである yuki3738さんが所属する 株式会社mov様より、フード&ドリンクスポンサーの協賛をいただきました。mov様は先日のRubyKaigi2024でもAfter Party Sponsorを行なっており、お世話になった方も多いと思います。心より感謝申し上げます。

Classiのエンジニアメンバーも設営兼ねて数名参加したのですが、今回、千葉県教育委員会から研修でお越しの小川先生がShinjuku.rbに興味をお持ちでしたので、参加いただきました。現役の学校の先生がプログラミングコミュニティに参加するのは珍しい機会だと思いますので、Classiらしさを出せたと思っています。

また、LTにはClassiメンバーのkozy4324さんと2024年新卒の伊森さんが参加してくれました。伊森さんは新卒らしからぬ小慣れた調子で発表しており、驚きました。

DevTools と デバッグ と 私(kozy4324

RubyKaigi行ってきたよレポ(いもり)

Shinjuku.rbはこれからも新宿界隈のRubyコミュニティを盛り上げていきたいと思います! 次回開催の際は是非お越しください!

dbtを導入した話、そしてClassiのデータ基盤「ソクラテス」の現在地

こんにちは、データプラットフォームチームの鳥山(@to_lz1)です。

Classiでは、2019年ごろからデータ基盤に「ソクラテス」の愛称をつけて運用を続けています。初期の構成は2021年に書かれたエントリ*1にも詳しいですが、数年の間に進化したことも増えてきました。

大きな変化の一例として、最近、私たちのチームではdbt*2を導入してジョブ間の依存管理やメタデータの管理を改善しました。

本記事ではこの取り組みをピックアップして紹介します。また、進化したソクラテスの構成図をアップデートするとともに、Classiデータプラットフォームチームの最新版の雰囲気もお伝えできればと思います。

dbt移行前の構成

正直に言ってしまえばdbt移行前の構成でも運用が崩壊するほどには困っていなかったのですが、個人的には大きく以下の2点に課題を感じていました。

  • ジョブ間の依存管理がつらい
  • メタデータの管理がつらい

以下、それぞれ説明します。

ジョブ間の依存管理がつらい

dbt導入以前のジョブはCloud Composer(Airflow)が提供するOperator*3が担っており、1クエリ1タスクになるような構成でした。

ところで、データマートのテーブルは材料となるテーブルがあって初めて作れます。そして材料となるテーブルもまた加工テーブルである可能性があるので、必然的にクエリ間には依存関係が生じます。移行前はこうしたクエリの依存関係を以下のようなyamlの設定ファイルに書いて対応していました。

- task_id: update_classi_dwh.students
  file_path: queries/dwh/students.sql
  destination_table: classi_dwh.students
  table_type: table
  write_disposition: WRITE_TRUNCATE
  dependent_tasks:
    - update_classi_dwh.schools
    - update_classi_dwh.users

生徒のdwhは、学校のテーブルとユーザーのテーブルに依存して作られる...納得感が高いですね。

dependent_tasksが比較的自明であるうちは良いのですが、これだとテーブル数が増えてきたときや、処理の中心に新たにテーブルを加えたくなったときに認知コストが非常に高いという問題があります。また、このアプローチでは依存タスクの記述漏れがあったときにも気づくことができません。依存関係を目で追ってそれを慎重にyamlファイルに反映していくことが作業時間を圧迫するようになってしまっては本末転倒というものです。

メタデータの管理がつらい

Classiでは、過去在籍していたメンバーがFlask-AppBuilder*4を用いたメタデータ管理システムを作ってくれていました。

tech.classi.jp

このシステムの功績は大きく、特にデータエンジニアでないメンバーが定義を書き込めるようになっていたことで、関係各所から「このテーブルのこのカラムはどういう意味?」といった重要なメタデータを収集することに成功しました。

しかしながら、独自管理Webシステムの限界もまたあります。

例えば、新たなテーブルをデータ基盤に追加したときにその説明をわざわざ書きに行くのか?というと微妙なところです。手間が勝ってしまうので充足率がいまいち高くならない、という課題もまた残っていました。

この点、dbtではmodelの定義ファイルにそもそもテーブルごと、カラムごとのdescriptionを記述できます。「新たなテーブルを追加するときに、そのPull Requestには同時にメタデータも書いてある」という世界なら、「リリース後にメタデータを書きに行く」という作業そのものが不要です。データ基盤の改善を加速させていくためにも、早くこのような構図に移行したい、というモチベーションがありました。

過去との差分と、移行への機運

実は、過去Classiではdbtに移行しようとしたものの諸々の状況を考慮して取りやめたことがあります。

tech.classi.jp

当時との状況の差分としては、以下のようなものがあると思います。

周辺ツールのエコシステムが整った

「dbtならyamlにdescriptionを書ける」と言っても、全テーブルの全カラムに手でdescriptionを付けていくのは実際のところかなり大変です。しかし、 dbt-osmosis のようなツールが出てきたことでこうした作業を効率化できるようになり、dbtのエコシステムに乗るメリットが大きくなってきました。

GitHub - z3z1ma/dbt-osmosis: Provides automated YAML management, a dbt server, streamlit workbench, and git-integrated dbt model output diff tools

dbt-osmosisについてはこちらのブログなどが詳しいため、詳細については割愛します。

dbt-osmosisを利用して、なるべくコストを抑えつつ効率的にメタデータ管理を行なう - yasuhisa's blog

エンジニア以外のメンバーがPull Requestを出すことが減った

Classiではかつて、データサイエンティストやビジネス側のメンバーもデータ基盤のリポジトリにPull Request(以下、PR)を出す、という光景が当たり前でした。しかしながら、エンジニアリングを熟知したメンバーばかりではなかったので、これが逆に新たなツールを導入することをためらわせる要因にもなっていました。

時が経ち、ビジネスメンバーからエンジニア陣へのドメイン知識の移転(≒dwh化)はある程度果たされたので、継続的にPRを出し続ける必要は無くなってきました。これにより、「学習コストが隣のチームの人達には厳しすぎるかも...」といった心配をする必要がなくなり、自分たちの裁量で新しいツールをより気軽に導入できるようになりました。*5

移行に際しての工夫点

上に述べたような状況を踏まえて、2023年末から2024年初頭にかけてdbtへの移行をやり切りました。移行においては以下のようなことを意識しました。

少しずつ行う

ビッグバンリリースではトラブル発生時の影響が計り知れないので、独立してリリース可能な範囲を切り分け、比較的難易度・複雑度が低いと思われるものから以下の順に移行を進めていきました。

  1. 社内でしか使わない、独立した小さいワークフロー群
  2. 社内でしか使わないが、データ基盤のコアとなるワークフロー
  3. エンドユーザーにも使われる、プロダクト機能に関連するワークフロー

また、社内データ基盤のコアを移行する際にはテーブルの棚卸しも実施しました。少数ですが、「移行せずとも2024年度になれば必然的に要らなくなる」といったテーブルも混じっていたため、こうしたテーブルはあえてdbt移行せず古いバージョンのまま残しました。

これにより、後述する差分確認の手間を減らしつつ、利用者がいなくなってから削除することでユーザーに影響を与えることなく古い処理系を一掃することに成功しました。

後から思ったことですが、このように徐々に移行を進めていくアプローチは、Martin Fowlerが提案したstrangler figパターンに近いものがあるかもしれません。

strangler fig パターンを実装してモノリシックなアプリケーションからマイクロサービスに移行するプロセスは、変換、共存、排除の 3 つのステップで構成されています。

strangler fig パターン - AWS 規範ガイダンス

差分確認を怠らない、でも楽にやる

さて、dbtへの移行ですが、クエリを移動して、必要な部分を書き換えて、全体のジョブが成功したら終わり...でしょうか?

いえ、それでは不十分なケースもあります。例えば処理は成功しているのにテーブルには差分が出ている...ということになると大変ですよね。データ基盤ではデータの正確性が重要な要素の一つですから、移行前後のデータの比較をしておけると安全です。

BigQueryでは、こうしたテーブル同士の比較はExcept句を用いた集合演算で実現できます。

Query syntax  |  BigQuery  |  Google Cloud

移行前のテーブルbefore、移行後のテーブルafterがあるとして、以下のようなクエリが結果を返さなければ、2つのテーブルは完全に一致していると言えるわけです。

select * from before
except distinct
select * from after

こうしたクエリの作業を全テーブルで行うのは大変なので、小さなシェルスクリプトを書いてチーム内に共有し、簡単に差分比較を行えるようにしました。実際はもう少し機能を追加しましたが、概ね以下のようなものです。

#!/bin/bash

# 比較元と比較先のテーブル名の組をCSVで作っておく
TARGET_FILE="./target.csv"
if [[ ! -f "$TARGET_FILE" ]]; then
    echo "File $TARGET_FILE not found!"
    exit 1
fi

project_id=$1
tables_with_diff=()

while IFS=, read -r compare base; do
    table_id_compare="${project_id}.${compare}"
    table_id_base="${project_id}.${base}"

    echo "Checking diff between ${table_id_compare} and ${table_id_base}."

    SELECT_MINUS_QUERY="\
    (select '${table_id_compare}' as table_name, * from ${table_id_compare} except distinct select '${table_id_compare}' as table_name, * from ${table_id_base} limit 3)\
    union all\
    (select '${table_id_base}' as table_name, * from ${table_id_base} except distinct select '${table_id_base}' as table_name, * from ${table_id_compare} limit 3)"

    result_rows_with_headers=$(bq query -q --nouse_legacy_sql "$SELECT_MINUS_QUERY" | tee /dev/tty | wc -l)
    if [[ $result_rows_with_headers -gt 0 ]]; then
        tables_with_diff+=("${table_id_compare} and ${table_id_base}")
    fi
done < $TARGET_FILE

if [[ ${#tables_with_diff[@]} -gt 0 ]]; then
    echo "Tables with diff:"
    for table in "${tables_with_diff[@]}"; do
        echo "- ${table}"
    done
    exit 1
else
    echo "No diff found with $(wc -l < $TARGET_FILE) table pairs✨"
fi

スクリプトを流した結果をrevieweeがPRに貼ることで、差分がないことについてはわざわざSQLをレビューしなくても分かります。これにより、それ以外の場所、例えばmacroの設計や命名、過去遡及時の冪等性の確保といったより重要な部分のコードレビューに集中できました。

反省点

以上述べたようにスクリプト等も駆使しつつ大きなトラブルなくdbt移行を終えたのですが、一部テーブルでCluster列*6の設定を忘れたまま移行してしまい、移行直後のクエリコストが急騰するという問題が発生しました。

幸い数日で気づけたので影響は小さかったのですが、皆さまに置かれましてはデータだけでなくメタデータ(descriptionに限らず、labelやpartition設定等も含む広義のメタデータ)もきちんと移植できているか、という観点も忘れられませんようご注意下さい。

ソクラテスの現在地

dbt移行などいくつかの刷新を経て、Classiのデータ基盤は今このようなアーキテクチャになっています。

Classiのデータ基盤構成図

ジョブの依存関係の管理の他、メタデータの提供もdbtの機能を使って実現できたのが大きな改善点です。

dbtをDockerizeされたジョブとして動かすようにしたため、model間の依存関係がComposer上では見れなくなってしまったのですが、dbt Docsを確認すればmodelごとのlineageグラフを可視化出来るので、大きな問題は出ていません。

dbt Docs上で可視化されたデータリネージュの一部

先述した独自のメタデータ管理システムについても、クローズする前にすべてのデータをCloud SQLから吸い上げ、dbtのConfigに反映する対応を行いました。これにより、これまでメンバーが書いてくれた有益な情報をdbt Docs上に集約でき、データカタログの利便性も向上したと思います。

dbt移行の他に大きい差分としては、ログのBigQueryへの連携を毎時のバッチで動かすようになりました。

実はそれまではAWS Athenaをベースに作られていたログ分析基盤を使っていました。それはそれで便利な点もあったのですが、AWS内に独自にホストされたRedashがメンテナンス不能になっていたり、BigQuery上のデータともjoinできないなど、負の側面も強くなっていました。このため、2024年初頭にBigQueryへの連携パイプラインを構築し、旧システムも先日すべて無事に削除しました。

これらの取り組みによって、RDBデータはdaily、ログデータはhourlyで、それぞれBigQuery(a.k.a. ソクラテス)に安定して供給される状態が実現できました。

今後の展望

Data Catalog as a Code

dbtによってメタデータの管理性は向上しましたが、今後のメンテナンスが本当に円滑に行われるか、という点では更なる工夫が必要です。メンテナンス業務にあたっては、descriptionをあちらにもこちらにも書かないといけない...といった二重管理を避けることが何より重要ではないでしょうか。

これに関しては、RDBのテーブルと加工テーブルのメタデータをそれぞれ1回記述すれば他のすべてのコンポーネントに反映されるような仕組みを構築中です。目指したい構成は以下のようなものです。

順を追って説明します。

  1. データエンジニアおよびデータ供給者(プロダクトチームのエンジニア)は、RDBのテーブルをBigQueryに連携するときにdescriptionを記述する
  2. bq load時に、書かれたテーブル定義を参照して実テーブルにメタデータが付与される
  3. dbt-source-importerによって、sourceテーブルのメタデータがymlに反映される
  4. dbt-osmosisによって、sourceテーブルのメタデータは加工テーブルのymlにも反映される
  5. データエンジニア及びデータ利用者は、集計カラムなど加工テーブル独自の列があればそのdescriptionを記述する
  6. dbt build時に、ymlを参照して実テーブルにメタデータが付与される
  7. dbt docs serveの定期的な実行により、最新のデータカタログが社内に公開される

dbt-source-importerが初出なので説明しておきますと、これはBigQueryの実テーブルからsourceの設定ファイルの内容を生成してくれるCLIツールです*7。sourceのメンテナンスについて、dbt-helperやdbt-osmosisなど公式に近いツール群ではかゆいところに手が届かないケースがあるのですが、こちらは必要な機能が軽量にまとまっているため重宝しています。

余談ながら、先日機能追加のPRを送った際も迅速に対応いただき、非常にありがたかったです。この場を借りて感謝いたします!

github.com

上図のような世界が実現できれば、人間の手が必要な作業は「RDBのテーブルのメタデータの記述」「加工テーブルのメタデータの記述」だけになります。あとは各ツール群が実テーブルにも設定ファイルにも、データカタログにも最新の状態を反映してくれるという算段で、細かい部分を調整しつつこうした自動化を進めています。

ここに書き切れないさまざまなこと

本記事では技術的なトピックに焦点を当てて来ましたが、ここに書き切れない施策もたくさん行っています。例えば、私のチームが属するプラットフォーム部では、より事業成果に直結する取り組みを増やすべく、全チームそれぞれがプロダクトのKPIに直接コミットするような目標を盛り込みました。

これに伴い、データプラットフォームチームでは例えば、

  • KPIのモニタリングと提言
  • 施策の立案と効果検証
  • ユーザー向け調査の設問設計

などビジネス的にチャレンジングな活動にも取り組み始めています。KPIをタイムリーに測定するためのデータマートの整備もアナリティクスエンジニアリングの一環ですから、当然我々の守備範囲です。データとビジネスが重なることは何でもやる。という覚悟で引き続きやっていきます。

We are hiring!

dbt移行プロジェクトの詳細と、データプラットフォームチームの近況についてお話してきました。何でもやる、とは言いましたが、現在データプラットフォームチームは4月からリーダーとなった筆者を含め3名しかおらず、やりたいことに対しては手が足りていない状況です。

データエンジニアリングもアナリティクスエンジニアリングも存分に行える環境が揃いつつあるため、Classiのデータプラットフォームチームに興味をお持ち頂いた方はカジュアル面談や面接にエントリー頂ければ嬉しいです!

hrmos.co

*1:https://tech.classi.jp/entry/2021/05/31/120000

*2:https://www.getdbt.com/

*3:https://airflow.apache.org/docs/apache-airflow-providers-google/stable/operators/cloud/bigquery.html

*4:https://flask-appbuilder.readthedocs.io/en/latest/

*5:かつてPRを出してくれていたメンバーはSQLやBIツールを使って今もガンガン力を発揮してくれていますし、dbt Docsへのフィードバックやデータ項目の追加依頼をもらうことで間接的にデータ整備にも貢献してくれています。PRが頻繁に飛んでくる文化も素敵とは思うのですが、形を変えて引き続き良い関係が築けているため、自分はこの変化はポジティブに捉えています。

*6:https://cloud.google.com/bigquery/docs/clustered-tables?hl=ja

*7:https://www.yasuhisay.info/entry/2022/01/22/121000

Classiは技術コミュニティの勉強会・ミートアップに会場提供を行います

はじめに

ソフトウェアエンジニアの onigra です。タイトルの通り、Classiは技術コミュニティの勉強会・ミートアップ等に、自社のイベントスペースを会場として提供致します。

昨今、オフラインでの勉強会・カンファレンス・ミートアップの盛り上がりを強く感じており、RubyKaigiはもちろんのこと、 Omotesando.rb などをはじめとした地域Ruby Meetupもオフライン開催がされるようになってきました。私も先日再開した Shinjuku.rb のドリンクアップに参加してきました。

参加者と交流する中で、今後の会場探しに困っていると伺ったので、西新宿にオフィスがあるClassiも会場提供できるという話をし、その流れからオーガナイザーの1人である tdakakさん より運営参加のお誘いを受けたので、引き受けることにしました。

Shinjuku.rbの再会&運営参加の経緯については同じくオーガナイザーの trebyさん のブログ記事が詳しいので、ぜひこちらもご覧ください。

Shinjuku.rbを再開した + 今後の話 https://treby.hatenablog.com/entry/2024/04/04/010121

Classi、tetoru自体がRubyやGo、TypeScriptをはじめとした多数のOSSで成り立っているサービスであり、私自身も地域Ruby Meetupやカンファレンスに参加したり、OSS活動を通じた人との出会いの中で成長できた恩があるので、会社として、いちプログラマとして会場提供という形でコミュニティへの参加と 恩送り を積極的にしていきたいと考えています。

もちろん、Shinjuku.rbのような地域RubyMeetupに限らず、さまざまなコミュニティに会場提供を行っていきたいので、技術コミュニティを運営されてる方々はお気軽にご相談ください。

会場スペック

追記

  • 2024/06/06 収容人数をMAX30名から35名に増やしました

会場の雰囲気

会場の雰囲気
会場の雰囲気

会社概要

住所

  • 〒163-0415 東京都新宿区西新宿2丁目1-1 新宿三井ビルディング 14階

アクセス

  • JR山手線 / 中央線 / 埼京線 小田急線 京王線「新宿駅」 徒歩約6分
  • 東京メトロ丸ノ内線「西新宿駅」 徒歩約2分
  • 都営地下鉄大江戸線「都庁前駅」 徒歩約1分
  • 都営地下鉄新宿線「新宿駅」 徒歩約11分

収容規模

  • MAX 35名(余裕見て)

設備

  • スクリーン: 1基
  • マイク: 2本
  • ゲストWi-Fi: あり
  • オンライン配信設備: なし
    • 準備中

費用

  • 無料

利用可能日程

  • 原則平日夜(18時以降開始で21時頃までに完全撤収イメージ)

備考

  • 飲食可能(アルコール可)

貸出条件

  • 技術的な勉強を目的とした技術コミュニティであること
    • 自社にスペースが無い企業コミュニティでも、技術イベントの開催目的であれば貸し出し可能です
  • 目安として10名以上の参加が見込まれていること
    • 厳密でなくても大丈夫です
    • 参加見込みが2, 3名だと提供は難しいです
  • 会場提供企業として、Classi株式会社の会社情報告知をOKしていただけること

貸出希望の際の連絡先

  • venue-booking-request@classi.jp
  • Classi株式会社 技術戦略室 鈴木

GitLab本輪読会、他社と合同で振り返りを行いました

こんにちは。プロダクト本部でエンジニアをしています daichi ( id:da1chi24 ) です。

先日、社内でGitLab本の輪読会を実施しました。

さらに今回はそれだけでなく、同時期に同じ本の輪読会をした他社の方と合同で振り返りを行うイベントに参加しました。

今回は輪読会や、他社と合同で行った輪読会の振り返りの内容、経緯や学び、参加した感想をシェアします。

GitLab本とは

GitLabに学ぶ世界最先端のリモート組織のつくりかた」(以下 GitLab本)という本です。

www.shoeisha.co.jp

この本はGitLab社が公開している「The GitLab Handbook」というドキュメントを参考に、著者が自社をリモートワーク化した実体験を通して得られたノウハウをまとめた内容が書かれています。

大まかな章立ては以下のようになっています。

  • リモート組織のメリットを読み解く
  • 世界最先端のリモート組織へ移行するためのプロセス
  • GitLabが実践するリモート組織を活性化させるカルチャー醸成法
  • GitLabが成果を出すために実践している人事制度や業務ルール

輪読会を開催しようと思ったきっかけ

Classiはリモートワークがメインなので、リモートワークを活用して生産性を高める実践例に興味がありました。

しかし、本の内容を把握するのは簡単ですが、その背景やコンテキストを理解するのは難しいです。

そこで他の人の意見を聞きながらディスカッションすることで、本の内容の理解がより深まるのではないかと思い、実施しました。

また、本で紹介されている事例は、個人やチームのみならず、文化や方針などの会社全体に関わるものも多いです。

そのため、普段一緒に仕事をすることのない他の部署や別のチームの方々と課題意識を共有することで、新しい気づきや発見があることも期待していました。

輪読会の進め方

輪読会はソフトウェアエンジニアだけでなく、データエンジニアや労務の方などさまざまな職種の方に参加していただき実施しました。

メンバーの層もジュニアから部長クラスの方まで幅広くいました。

1章ずつ担当を割り振り、担当者はその章を事前にまとめて発表、その後参加者同士で気になったことをディスカッションしました。

この本は全部で13章あり、単純計算で3ヶ月以上かかる長期戦です。

そのため途中で息切れしないよう、参加者の都合が合わない場合はスキップをするなど柔軟に開催しました。

輪読会を通して学んだこと・合同振り返り会に参加する動機

GitLab社が強く打ち出しているドキュメント文化や、リモート化におけるコミュニケーションの方法、新入社員のオンボーディングなど、明日からすぐ使える知識や基準が数多くあり満足度の高いものになりました。

以下は、参加者の感想です(一部抜粋)

  • 中途入社の人から違う会社の話、他の部署の人から違う組織の話、若手メンバーから違う年次の話が広く聞けたのがめちゃくちゃ良かった。
  • 具体例が多いので読み進めやすく、それでいてコミュニケーションといった普遍的な所作に通ずるところも多い。
  • フィードバックの様式やコミュニケーションガイドラインが具体的ですぐに取り入れやすくて良い。
  • 「前向きな意図を想定する」から始まるコミュニケーションガイドラインが、同意できるところが多くて個人的に最も気に入った部分。
  • 読んで終わりと違って、感想を書き合う・話し合うことで内容がより自分の中に落とし込めた感じがします。他の本でもやってみたい。

また、この本で推奨されている方法の中で、Classiでも既にできていたり文化として根付いているものは改めて良いものだと認識することもできました。

例えば、この本では「リモートワークだとメンバーが何をしているかわからない、マネジメントやメンバーの成果に対する評価がしにくい」という課題が取り上げられています。

Classi ではたびたび引用されている Working Out Load (大声作業をしなさい)という行動を推奨しているという話がありました。

www.workingoutloud.com

一方で、生産性を高め仕事を円滑に進める工夫を、他社ではどのようにやっているのかは、社内の輪読会だけではわかりませんでした。

また、これからリモートワーク化を進める組織やハイブリットな組織にとってどのような障壁があるのかは、既にリモート化された組織にいる身として実感が湧かない部分もありました。

そんな時ちょうどGitLab本の輪読会を同時期に行っている方々と合同で輪読会を行うイベント(後述)があることを知りました。

このイベントに参加することで、さまざま他社の悩みや事例を共有しさらに学びを深められるのではないかと思い、参加することにしました。

他社との合同振り返り

参加した合同振り返り会とは、KINTO テクノロジーズ株式会社様が主催されていたイベントです。

各社それぞれで行った輪読会について振り返りを行い、どのような気づきや学びがあったかを共有するものです。

connpass.com

私はワークやパネルディスカッションに参加し、自社ではどのように輪読会を行ったか、輪読会を通してどういう変化があったかなどを、お話しさせていただきました。

実際のパネルセッションの様子

実際に話したディスカッションの内容

参加者の方々はさまざまな勤務形態で、フルリモートで遠方から参加していた方もいれば、出社がメインの企業の方もいらっしゃいました。

また、職種はマネージャーやITコンサルタント、SREなど幅広く、それぞれのコンテキストで議論が盛り上がりました。

振り返りでの話題

色々な話で盛り上がったのですが、輪読会の実施方法と本の内容から1つずつ共有します。

輪読会の方法はたくさんある

あらためて輪読会の実施方法はたくさんあることを再認識しました。

KINTOテクノロジーズさんの事例では、生成 AI を利用して要約する、欠席した方のために同じ内容を2回行うなど、いかに参加者に負荷なく参加してもらうかをかなり工夫されていて実施していました。

blog.kinto-technologies.com

他にも本を読むタイミング(事前に読むか、当日読むか)、予定が合わない時のスケジュールの調整方法も会社ごとに違いがありました。

実施方法は本の内容や参加者の属性によっても異なるので、色々な選択肢を持ちつつも状況に合わせて良い方法を選んだり、途中で変えたりするのが良さそうだと思います。

リモート化でのインフォーマルなコミュニケーションの工夫

GitLab本ではインフォーマルコミュニケーション(いわゆる雑談)は生産性を高めるために大事だと書かれていますが、それぞれの企業で継続するのはなかなか難しいという話で盛り上がりました。

その中でも工夫している企業では、共通の話題を日報や週報から見つけ会話の接点を増やす、制度化せずに自然発生するコミュニケーションを大切にする、オンサイトで話すタイミングやきっかけを作る、などを実施していました。

後に気づいたことですが、輪読会自体が同じテーマで話しやすく親睦も深まるため、チームや部署を超えた関係の発展に寄与するものだと感じました。

全体の感想

今回は社内だけでなく、普段関わることがないような業種の方々と振り返りを行いました。

社内に留まらない一般的な共通の課題を再認識すると共に、Classiの良い文化や強みを改めて実感する良い機会となりました。

今後も社内だけに閉じず、社内外でディスカッションや知見共有をする活動は続けていきたいです。

輪読会に参加されたメンバー、合同振り返りを主催いただいたKINTOテクノロジーズ様、ご参加いただいた方々、ありがとうございました。

データを活用したQA検証の取り組み

こんにちは!QAチームの池田です。

今回は、2023年度でQAチームが行った取り組みについてご紹介します!

QAチームでは、2023年度で2つ目標を掲げ活動をしてきました。 そのうちの1つの目標が「機能別の検証密度と優先度の抽出」です。

この目標は、検証漏れによる本番環境での不具合を防止することを主な目的としていました。 また、検証実施時の負荷の分散にも考慮し、利用頻度の高い機能の検証密度を高くすることにより効率的に検証を進めていくことを目的としていました。

「機能別の検証密度と優先度の抽出」をするには?

弊社のプロダクト「Classi」には多くの機能があり、それに伴い開発チームも複数存在します。QAメンバーはそれぞれ開発チームに配属されています。

機能により利用頻度の高いユーザー種別やデバイスカテゴリなどが異なりますが、今までそういったデータを活用できていませんでした。 そこで、QA観点での検証密度の向上、機能別の優先度を抽出するために、Google Analytics(以下GA)のデータを活用していくことにしました。

まずGAの中からQA検証時に役立ちそうなデータをピックアップしました。 具体的には下記データです。

  • ユーザー種別
  • PV(ページビュー)数
  • デバイスカテゴリ
  • OS
  • iOSバージョン
  • Androidバージョン

Google AnalyticsとLooker Studioを連携する

QAチームでは、権限の関係でQAチーム全員がGAにアクセスできるわけではありません。 そのためGAでピックアップしたデータを活用しやすいように見える化する必要があります。 以前からQAチームでは見える化施策でLooker Studioを活用していたため、Looker Studioで作成された既存のレポートを参考にデータの見える化を進めました。

Looker Studioで作成したレポートの一部

Looker Studioで作成したレポートの一部

Looker StudioでGAデータのレポートを作成するにあたり、ただデータをグラフとして出力するだけでなく、実際にQAメンバーが現場で活用できるよう分かりやすく使いやすい内容を意識して作成しました。

例えば、GAのデータのままだと分かりづらい内容を計算式を使って分かりやすいテキストに置き換える作業を行いました。 当初ユーザー種別(user_type_id)を表示させようとすると、idがそのまま表示されておりどのユーザー種別なのかが分かりづらい状態でした。そのため、それぞれのidを日本語に置き換える計算式を追加し、誰が見ても分かる表示に変えました。

レポート編集内容の一部

GAのレポートを実際に自分で活用してみる

GAのレポートを作成した後、具体的にどう活用できるのか自分で試してみることにしました。

当時活用できそうな案件がなかったため、自動テストの運用で活用できないかを考えました。 そこで、自動テストで行っているリグレッションテストの内容、範囲の見直しをPV数を基に行いました。

私はプロダクトの中で、「設定・登録」領域を担当しています。設定・登録は学校の先生向けの機能が大半のため、自動テストのシナリオは当時先生の機能しか作成されていませんでした。 しかし領域のPV数を参照したところ、常に「/parent_top」が上位に入っていることに気づきました。設定・登録の中で保護者の機能は少ないですが、保護者からのアクセスが多いということが分かりました。

保護者の設定・登録画面

そこで保護者機能の自動テストを作成し、定期実行に追加しました。

レポートを活用することで、リグレッションテストの範囲の拡充を行うことができました。また、自分の担当領域でどの機能、画面が実際にユーザーから使われているのかを把握していなかったため、検証の優先度を考慮していなかったのだと気づきました。

QAメンバーに展開

実際に自分で活用を試した後、QAメンバーに展開するため説明会を行いました。 今後各QAメンバーがレポートを活用できるよう、活用がイメージできるような説明と発表資料を準備しました。

発表資料の一部①

そのために、実際に私がレポートを活用して行った取り組みを活用例として紹介しました。

発表資料の一部②

QAメンバーの活用状況

QAメンバーにレポートを展開した数ヶ月後に活用状況ヒアリングのためアンケートを実施しました。

アンケート結果によると、1/3のメンバーが早速レポートを活用してくれていることが分かりました。

アンケート結果の一部

活用しているメンバーからは、下記の活用事例が上がりました。

  • 全体のリグレッションテストをする際に、よく見られている画面は細かく、あまり見られていない画面は一通りの機能が触れればOKのように効率よく項目書作成ができた。

  • OS利用状況の確認を行い、検証対象のOS選定を行った。

  • PdMやエンジニアから「生徒がどの端末をよく利用しているか知ってますか?」等の相談事項が多々あったので、その際にレポートを見せて利用頻度の高い端末やOSを確認した。

検証の優先度を考えたり、検証端末・OSの選定、さらにはQAチーム以外のメンバーとも連携をとっている活用状況が見えてきました! まさに施策の目的である「機能別の検証密度と優先度の抽出」に沿った活用が進んでいました。

今後の課題

一方で、まだレポートの活用を進められていないメンバーにどう推進していくかという課題もあります。

QAチームでは、テスト項目書作成前に開発メンバーなどと検証についてのすり合わせをする「QAヒアリング」を行っています。 QAヒアリングではそれぞれのQAメンバーが経験値を問わず必要な情報を確認できるよう、テンプレートとして「ヒアリングシート」を用意しています。 このヒアリングシートの中にレポートのURLの記載をしました。

こうすることでヒアリング準備、もしくはヒアリング中にレポートの確認、活用の検討ができると期待しています。

項目書作成前に開発メンバーとのすり合わせで使用するヒアリングシートの一部

おわりに

前述の通りClassiには多くの機能があり、機能ごとに検証密度と優先度を抽出していく必要があります。

2023年度以前は各機能ごとのデータの活用ができていませんでしたが、2023年度以降実際にデータを参考に検証密度の向上、優先度の抽出に繋げることができたチームもあり、成果が出始めていると実感しています。

今後さらにデータを駆使した検証に貢献できるよう、レポートで反映するデータや対象期間など改良を続けていき日々QAメンバーに活用してもらえるようアップデートしていこうと思っております!

© 2020 Classi Corp.