お届けチームがイベント駆動アーキテクチャを採用した理由

ネットスーパーで注文された商品が効率よく確実にお客さまのもとに届くためには、店舗でのピッキングやパッキング、配送といった業務が必要となります。この業務を支えるStailer上のアプリケーション開発を担っているのが、お届けチームです。

10x.co.jp

お届けチームは昨年「イベント駆動アーキテクチャ」を導入する取り組みを行いました。イベント駆動アーキテクチャをどんな狙いで導入し、どんな成果が得られたのか。お届けチームの開発メンバーである鈴木さんに聞いてみました。

イベント駆動アーキテクチャ: イベント駆動アーキテクチャは、システム内で発生するイベントをトリガーにして処理を実行する設計パターン。コンポーネント同士が直接やり取りをせず、イベントを介して情報を共有するため、疎結合になり、スケーラビリティと柔軟性が高くなる。イベントはイベントバスやメッセージキューを通じて通知され、受け取ったコンポーネントが必要に応じて処理を行う。

密結合なシステムの課題

── まず最初に、どんな課題を解決するためにイベント駆動アーキテクチャを導入しようとしたのか、というところを聞いてみていいですか?

鈴木: はい。 元々あった課題として、Stailerはいろんな領域のデータだったり、コードだったりと、いろんなものが密結合になってたんですね。 密結合になってるがゆえに、ソースコードを触るときに、あっちにお伺いを立てて、こっちにお伺いを立てて、みたいな一つ触るのにも気にすることが多いという状況でした。そうした、開発の面での認知負荷が高いというところが1つ。

それに、障害リスクの観点がもう1つ課題としてありました。ネットスーパーをやってると、エンドユーザーが利用するECサイトと、店舗のスタッフの方が利用するシステム、2つのシステムを管理する必要があります。店舗向けのシステムで障害起きてしまうと、ECサイトまで注文できなくなるようなシステムが本当にいいシステムなのか?というと、そうではないと思うんですね。

実際、密結合がゆえにスタッフ向けのシステムの面がちょっと壊れたりすると、エンドユーザー向けのECサイトでも注文が受け付けられないといったような障害に繋がる、カスケード障害のリスクが当時はいろんなところに点在していました。そういうのを解決したくてイベント駆動を採用しようとしてた。 ってとこですかね。

Eventarcの活用

── そうしたモチベーションでイベント駆動を導入し始めたと思うんですが、導入するにあたってどんな部分が大変でしたか?

鈴木: そうですね。やはり、スタート地点でコードやデータがすごい密結合になっていたので、これをどうやって分解しようかな、というところですかね。イベントをどうモデリングするかっていうのは、頭を抱えましたし、モデルって、常に省みるものなので、今でもこれは正しいのかなぁ、どうなんだろうなぁっていうのは、悩み続けているし、大変だったところですかね。

一方でより技術的な面でいうと実はそんなに大変ではなかった、 とは思っていて。弊社ではFirestoreを中心的なアプリケーションのデータベースとして使ってるんですけど、それがEventarcっていうイベント駆動のためのサービスとうまく繋げることができたので、イベント駆動をシステム的に実現するっていうのは、思ったより大変ではなかったとこでした。

Stailerでは主にDB(Firestore)上の特定のデータの書き込みや更新をトリガーとし、Cloud Runを経由して期待されるコンポーネントの処理が実行される。

Eventarc: Google Cloudの内外のイベントを統合して処理できるサービス。Cloud StorageやCloud Pub/Sub、Firebaseなどからのイベントをトリガーにして、Cloud RunやCloud Functionsで処理を実行することができる。

意思を持って言葉を定義すること

── モデリングをちゃんとやろうとしたとき、使ってる言葉がブレてるとか、そもそも言葉の定義が決まってないみたいで苦労することがあるんじゃないかと思うんすけど、その辺で何か工夫されたこととかってありますか。

鈴木: まず、自分たちで決めないと、その言葉がないってことからスタートだなって思ってまして。

例えば会計とかクレジットカードみたいなドメインだと、その業界の中でいろんな言葉があったりするんですけど、僕らの作ってるピックパックってそもそも紙ベースで仕事がされてた頃からシステム化しましたっていう経緯がありまして。

紙のときにはそもそもやってなかった業務が増えてる。 増えた業務ってまだ名前がなかったり、ふわふわしてたり、名前があるけど、実は何かお届けの領域にとっては正しくない名前をしてるとか。

そういうのが多かったんで、自分たちでこれはこういう言葉を使うんだっていう強い意志を持ってことを決めるっていうことがすごい大事でした。そこで、そのユビキタス言語辞書を作ってみるっていうのはすごいやってよかったというか、これがなかったら厳しかったなっていうとこですよね。

お届けチームのユビキタス言語辞書の一部

── モデリングを見直したときって、既存のデータ構造を変えるみたいな必要があると思うんですけど、実際動くものがある状態でデータ構造とかモデルを変える大変さってありましたか?

鈴木: そうですね。 もちろんデータマイグレーションとかは大変なんですけど、幸いにもお届けチームが受け持つ領域って、一つのデータの生存期間というか、使われる期間が非常に短いんですね。

お客さまが注文を入れてから、手元に行くまでの間で扱われるデータなので、長くても2週間ぐらいで役目を終えるし、後からその生のデータを省みるってことはあんまりないんですよね。

データの生存期間が短いんで、並走期間はその2週間分を見てダブルライトして短い期間の移行期間を経て対応できたので、実はそんな大変じゃなかったんですよね。

イベント駆動アーキテクチャの恩恵

── お届けチームが持ってるコンポーネントと他のチームのコンポーネントが密結合だと、境界上から見えづらくてモデリングしづらいみたいなところとかもあったりするんじゃないかなと思うんすけど、その辺で苦労されたこととか、工夫されたことってありますか。

鈴木: そうですね。 ピックパックの話で言うと、幸い他のチームが運んできたものを最後扱うところなので、比較的自分たちの都合で決めるというか、あんまりお伺いを立てずに進められたかなとは思ってますね。

なので他チームとのインタラクションという観点だと、ここまではあんまり苦労はなかったです。ただ、チームの中で発見したり、作った言葉を他チームに浸透していく大変さを、これから味わっていくんだろうな、というのは予感しています。

── イベント駆動アーキテクチャを導入してみて、実際にどんな恩恵が得られましたか?

鈴木: 保守性の話にも繋がると思うんですけど、イベント駆動で開発をするとイベントを大事にするからモデリングをしっかりする、といったようにモデリングする動機付けになったという部分があります。

また、イベントを保存して扱うというやり方になったので、トラブルシューティングのときに信用できる事実が溜まってくってのはすごい良かったことですね。

以前からも業務の生産性を計測するために、いわゆるGoogleアナリティクスにログを送るみたいなことをしてました。 広い意味だとそれもログではあるんですけど、どうしてもデータが使いにくかったり、実際にシステムに反映されてる状態と、Googleアナリティクスにあるログは乖離し得るものなので、何かデータの不整合があるんですけどみたいなことがあったりしました。

イベント駆動を始めてイベントを保存するようになってから、それを基準に業務の生産性を図ることができるようになりました。システムの都合で変な不整合が起きないっていうのは、明確に前進したかなっていうところですね。

理想のモデリングを志すことに価値がある

── 正しく業務の内容を記録するされるっていう副産物も得ることができたってことですね。ありがとうございます。 最後に何か今、この話を聞いて、イベント駆動を自分をやってみたいなってなった人へのアドバイスとかってありますか。

鈴木: いろいろあるけど、やっぱりイベントを通してモデリングする業務に着目することですね。この業務の中ではどういうことが起きるんだろうっていうのに着目して作っていくことが何よりも大事かなって思ってます。

あとはイベント駆動なので非同期処理が入ってくると、非同期であるが故に技術的に難しいことがたくさん出てくる。 そこは失敗しながら、学んでいくしかないのかなと思ってます。

それから、もし仮にですけど試してみたが、やはりイベント駆動はやめておこう、という結果になっても、イベント駆動を志してモデリングした経験は残ると思うんですよね。イベント駆動アーキテクチャを最終的に採用しなくても、今後の自分のモデリングの糧にはなるはずなので、ぜひやってみるといいんじゃないかなと思います。

モデリングを大事にしてやってみると良い、というのは明確にアドバイスの一つかな、と思います。

── なるほど。イベント駆動が導入されたこと自体より、業務があるべき姿にモデリングされていることこそが一番良い成果、というような。

鈴木: そうですね。志すといいますか…あるべき姿、完璧になるってことはやっぱ難しいし、出来ないかもしれないんですが、でもそれを目指す。 目指して、頭の中に理想がある状態を作る。足元の現状を考える際にそうした理想とのギャップを考えることができると良くて、それをさらにシステムに反映できるとより良いな、と思ってます。

おわりに

10Xではより良い設計、より良いモデリングによってプロダクトや事業を成長させたい、というソフトウェアエンジニアを募集しています。 この記事を読んで、自分も理想のモデリングを志したいと、と感じた方はぜひ下記をご覧ください。 open.talentio.com

Devin AIの商品データパイプラインへの適用

はじめに

10X ソフトウェアエンジニアの野々村です。元々アプリケーション開発者としてサーバーサイドを中心に仕事をしてきましたが、最近は協業する小売事業者様から受領したデータをネットスーパーに掲載できる状態へ加工する商品データパイプラインの開発に主に携わっています。

10x.co.jp

10XでもDevin AIを利用し始めて1ヶ月程度が経ったので、適用事例と展望について紹介します。

前提

Devin AI とは

Cognition AI社によって提供されるAIエージェントSaaSです。2024年12月に一般利用が開始され、各所で導入事例が紹介されています。

devin.ai

Devin AIの特性として、以下のようなタスクが得意とされています。

  • 実装の検証が容易である
  • 参考実装にアクセス可能である

Devin AIと適用領域の特性のマッチング

10Xでは私が開発に携わる商品データパイプライン領域においてDevin AIの特性がマッチするのではという仮説があり、導入検証を行いました。

弊社の商品データパイプラインは大きく、「小売事業者様から受領したデータを計算処理に渡すための共通フォーマットにクレンジング・結合・絞り込み・整形を行う箇所」と「検証されたデータセットを元に共通の計算処理を行う箇所」の2層で構成されています。

前者の小売事業者様に近いレイヤーは、小売事業者様ごとに個別のパイプラインが実装されています。一方で完全なワンオフではなく、開発者の認知負荷を削減するため、一定のルールに基づいた共通構造が実装されています。

商品データパイプラインのイメージ図

そのため、「ある小売事業者様向けのパイプラインで実装した内容を他のパイプラインに水平展開する」ようなタスクが頻繁に発生します。このようなタスクは以下のような点でDevin AIに依頼しやすいタスク群でした。

  • 事前定義されたスキーマによって型制約を与えつつ実装が進められ、自動化された単体テストや結合テストで回帰試験が可能である → 作業中および作業完了後の検証容易性を担保できる
  • あるパイプラインへの実装を参考実装として渡してDevin AIに指示を出せる → 参考実装のアクセス容易性を担保できる

効果測定

導入による影響と費用対効果

商品データチームではスクラムを採用して1週間毎にSprintを回しています。4週間の消化StoryPointの比率からDevin AIを利用して対応したStoryPointを観測すると、概ね20-30%程度の消化StoryPointへの貢献が見て取れました。

商品データチームはEMを含め4人で運営しているため、20-30%は単純計算でエンジニアを1人追加した程度のインパクトと言えます。

一方で費用についてですが、Devin AIの料金はACUと呼ばれる計算量の単位で決まります。

devin.ai

記述時点(2025/3/17)では$500/250ACUsが月間の基本料金であり、以降は$2/ACUの従量課金です。

検証期間中利用したACUは400ACUs程度でした。金額換算では$800程度になります。¥150/$で換算すると¥120,000程度となります。

開発ツールへの出費としては安くありませんが、開発生産性へ与える影響との比較で言えば破格と評価しています。

導入時の工夫

使い始めるためのドキュメントを整備する

AIエージェントを利用した開発は開発者の受け入れコストが小さくありません。自分の手元で完結するコーディングとは異なるマインドセット、ワークフローを要求しますし、そもそも仕組みの理解やサービスの仕様について理解しておく必要もあります。

まずは使ってもらわなければ妥当な検証が行えないため、社内でのプラクティスをまとめた手引を作成し、少しでも初回利用のハードルを下げてもらえるようにしました。

実際に作成した手引の目次(一部)

最小権限を付与する

Devinは高い自由度を持ちます。ミニマムでも対象GitHub Repositoryへのwrite権限を持つため破壊的な変更を実行できますし、例えばインターネットアクセス環境とブラウザを持つため、認証情報を持てば多くの環境にログインして作業することができます。しかしセキュリティ的に、あるいは本番オペレーターとして信頼できる水準では必ずしもないという事例も共有されています。

note.com

note.com

一方でDevinへのタスク委譲を考えると一定の権限付与は避けられません。例えば商品データパイプラインにおいては、BigQueryへのwriteができないと修正後のパイプラインにおいてスキーマの一貫性が保たれているかの検証ができません。

このようなケースにおいて、Google CloudのProjectレベルの権限を付与するのではなく、データセット単位の権限付与を行うことで意図せぬ開発環境への影響が起こらないようにしました。具体的にはDevinが作成するデータセットは所定のprefixを設定する運用とし、Google CloudのIAM Conditionsを用いて特定データセットへのみwrite権限を持つように定義しました。

cloud.google.com

10XではIAMをTerraform管理しているため google_project_iam_member resourceを用いて以下のように実現しています。

registry.terraform.io

resource "google_project_iam_member" "${resourceName}" {
  project = "${projectId}"
  role    = "roles/bigquery.jobUser" # クエリ発行のために最低限jobUserが必要
  member  = "serviceAccount:{devin's ServiceAccount}"
}

resource "google_project_iam_member" "${resourceName}" {
  project = ${projectId}
  role    = "roles/bigquery.dataEditor"
  member  = "serviceAccount:${devin's serviceAccount}
  condition {
    title       = "only_owned_dataset"
    description = "商品データパイプライン用のDevinは自分用のdatasetのみ編集可能"
    expression  = "resource.name.startsWith(\"projects/${projectId}/datasets/dbt_devin_sandbox_\")"
  }
}

またDevin AIはSlack Appを用いたSlack Integration機能を持ちますが、このAppは参加したチャンネルの全メッセージの読み取り権限を持つため、所定のDevin連携用チャンネル以外では参加させない運用とし、予期せぬ情報漏えいを防ぐようにしました。

DevinによるPull Requestのレビュールールをチームで決定する

Devinが作成したPull RequestはGitHub上ではbot userが作成したものとなります。商品データチームの所管Repositoryでは、CodeOwnerによる1 approvalでマージ可能な運用としていたため、Devinが作成したPull Requestを依頼者がapproveすることで実質的なセルフレビューでのマージが可能になってしまいます。

これに対し我々のチームでは以下のような運用を決めて運用しています。

  • 原則、依頼者 + 1名のapprovalでマージ可能とする
  • 本番影響のないドキュメンテーション、テストコードの修正に限り依頼者のレビューでマージして良い

ドキュメンテーションの補填や欠けているテストの充足などもDevin AIに期待する役割に含まれるため、それらの速度を落とさず、一方で安全に本番運用を進めるために上記のようなルール設定としました。

Knowledgeは定期的にリポジトリにdumpさせる

Devin AIでは作業に必要な知識・コンテキストを Knowledge という形で登録することができます。

docs.devin.ai

作業毎にDevin AI側から更新を提案してくれるなど非常に便利な機能です。一方でチームのスタンスとして、今後Devin以外のAIエージェントやツールへの転換も十分あり得ると考えています。そのため、Devinに対し定期的に Knowledge をまとめたものをドキュメントにまとめてRepositoryに追記させ、重複するようになったKnowledgeは削除するような運用を取っています。

これにより、ロックインを避ける形でAI ReadableなRepositoryへの磨き込みを進めています。

今後の課題

適用範囲の拡大

今回の検証期間では商品データチームが主要なユーザであり、適用範囲はdbt, GitHub Actions等限定的でした。現在、terraformにて管理されるinfrastructure resourceやDartで実装されたアプリケーションコードへの適用を進めています。

開発チームのパフォーマンスへ与える影響については引き続き測定が必要ですが、特にDartのような静的型付けをもつ言語においては、SQLを主体とするdbtより直接に、高い表現力で値への要求を表現できるため、精度の向上が期待できるのではと考えています。

一方で技術的な課題として認証情報の使い分けがあります。DevinにSecret管理の機能はあるもののグローバルに利用可能なため、チームごとに最小権限で運用しようとすると一工夫が必要です。

docs.devin.ai

現状はSnapshotとして認証情報を保持した状態を保存し、作業指示する際に指定するような運用を想定していますが、改善の余地があります。

レビュー運用の仕組み化

上述の通り、現状のマージルールは運用によってカバーにしていますが、GitHub Actionsによる仕組み化を進めています。具体的には、Commit author および co-author*1 によるapproveしかない場合はfailするようなGitHub Actionsを実装し、GitHubのRuleSetにおいてrequiredとすることで、安全に運用できる状態を作ろうとしています。

導入しての所感

チームの生産性に与える影響はスケールアウト的

Devinを利用しての作業は概ね作業依頼と成果物のレビューというサイクルで成り立ちます。

Devinを使い倒すのであれば、例えばDevinに対して3件の作業を並列に依頼し、これを順次レビューしていくという方法も可能でしょう。一方でDevinに渡せるのは比較的ゴールの明らかな、複雑度の小さいタスクがメインとなるため、このようなタスクばかりを大量に消化するという場面も限定的です。

実際はDevinに定型的なタスクを依頼している裏で人間が複雑度の高いタスクを請け負う(あるいはDevinに渡すための最初の参考実装を作る)という働き方が最もうまく回るように感じました。

この場合、複雑なタスクと並行に簡単なタスクを進められるため、開発者の能力を高めるというよりは、既存の開発者と並列に作業を進めてくれるメンバーが追加されたような捉え方のほうが近いと考えます。

従って、今より複雑な課題が解けるというよりは、今までは後回しになりがちだった事にも適切に取り組めるようになるという工数制約の解消を期待する場合に、うまくフィットしそうです。

投機的な依頼という付き合い方

今のところDevinが作成する成果物は、常に100点を取ってくれるわけではありません。細かいところで意図と違う事をしてしまったり(ベタ移植して欲しいところを手直ししてしまったり、必要なコメントを消してしまったり…)、そもそも作業方針が期待と異なることも間々あります。

Knowledgeという形式で必要な知識を伝授したり、RepositoryにAIエージェント向けのヒントを拡充することである程度は精度を高められますが、それでも本番環境にリリース可能な成果物を常に生み出せるようになるまでにはしばらく時間がかかりそうです。

それまでの付き合い方として、投機的な依頼という付き合い方をチーム内には推奨しています。

依頼を投げてみて、人が作業すると4hかかるはずだった作業がうまくすると5-10minで完結する。もし細かいところが期待と異なっても、それを手直しすれば30minで対応できることがあります。

AIエージェントに確信を持って依頼できるタスクと、複雑度が高すぎて振りづらいタスクの中間に、できるかも知れないが完璧にはやれないかもしれないタスクが無数に存在します。これらを投機的に依頼してしまうことで、期待値としてのパフォーマンスは大きく伸ばしうると感じました。

We are hiring!

この記事では10Xの商品データチームにおけるDevin AIの導入について事例を紹介しました。

開発ツールとして考えると必要な費用が小さいツールではありませんが、開発生産性への影響は非常に大きいと捉えています。

生成AIの発展に伴いエンジニアリングの手法は大きな変革期を迎えつつありますが、この波を乗りこなしてともに10Xを作るメンバーを募集しています。

興味がおありのところがあれば、お気軽にカジュアル面談からお声がけください。

open.talentio.com

*1:デフォルトの設定ではDevinの積むcommitには依頼者がco-authorとして設定されます

アーキテクチャの変更をどうやって完遂するか

既存のアーキテクチャの問題が見えると、アーキテクチャを変更して解決すると思います。

それ自体は素晴らしいことなのですが、変更が全体に浸透し切らず古いアーキテクチャと新しいアーキテクチャが混在したままになってしまうと、状況はさらに悪化します。そのため、アーキテクチャを変更する時には、「どうやって完遂するか」もセットで考えるべきでしょう。

10Xの現状は?

混在しています。

自然と移行を完遂できる日は来なかったので、完遂する努力をしています。

完遂するための取り組み

アーキテクチャの限界を漸進的に押し上げる取り組み で紹介した通り、10Xでは 以下の4ステップのサイクルを回してアーキテクチャを改善しようとしています。

  • 欲しい特性を狙ってアーキテクチャ決定を積み重ねる
  • ADRでアーキテクチャ決定の意図を明確にする
  • linterでADRに辿り着けるようにする
  • ADRへの違反状況を可視化して漸進的に適応度を上げる

完遂に向かう話は4番目で触れているのですが、実際に移行を完遂するには非適合箇所がわかるだけではなく、適合状況の俯瞰的な現在地がわかる必要があると感じました。

そこで、以下のようなイメージの可視化を行いました。

横軸は日付で、縦軸は非適合の数です。アーキテクチャ決定ごとに色分けしています。

可視化にあたっては、以下の2点を把握できることを重視しました。

  • アーキテクチャ決定とコードの乖離は過去と比べて増えているのか。
  • コードとの乖離が多いアーキテクチャ決定はどれか。

アーキテクチャ決定とコードの乖離は過去と比べて増えているかどうかが把握できると、乖離を解消する動きに割く力が今くらいで十分なのか、それとも不足しているのか、理解できます。また、乖離の増減に加えて総量も把握できると、今が新しいアーキテクチャ決定を加えても良い時なのかどうかも判断できます。

コードとの乖離が多いアーキテクチャ決定を把握できると、何の乖離の解消に力を割けば状況が良くなるのか理解できます。乖離が生じている理由は様々で、単に移行の腕力不足の場合もあれば、アーキテクチャ決定の内容自体に移行を鈍らせる要因がある場合もあります。いずれにせよ、何を見るべきかのヒントにはなります。

可視化の仕組み

10Xではアーキテクチャ決定はADR化し、ADRへの非適合箇所はlintで検出できるようにしています。新しいADRの導入時には非適合箇所がたくさん出るので、当該箇所ではlintを無効にするのですが、この無効にするコード(Dartの場合は // ignore: <rule>)を可視化の材料にしています。

以下のようなスクリプトで日ごとの非適合箇所を抽出し、データを作成しています。

date=<YYYY-MM-DD>
sha=$(git log main --merges --until="${date}$ +0900" -1 --pretty=format:"%H")
git grep -rE "// (ignore|ignore_for_file): .+" "${sha}"

デイリーのデータ作成はGitHub Actionsで行い、BigQueryにロードし、Looker Studioでグラフ化しています。

やってみた手応え

実際にアーキテクチャ決定への適合状況を時系列で可視化してみて、今までよりも良い判断ができそうだと感じました。今自分が主に開発しているリポジトリでは「今はアーキテクチャ変更よりも既存のコードを適合させることに注力する」と判断していますが、今回の可視化は判断の拠り所となる事実であり、この判断を変える条件を考える材料にもなりました。

今後もより良い判断をするための仕組みづくりをしていきたいと思います。

メンバー募集

10Xでは技術的判断をより良くしていきたいソフトウェアエンジニアを募集しています。

興味を持っていただけた方は、ぜひ会社紹介をご覧ください!

open.talentio.com

しなやかなデータ連携に向けたdatacontract-cliへの貢献について紹介します

データ基盤チームに所属しているデータエンジニアの吉田(id:syou6162)です。10X社内のデータマネジメントの仕事をしています。

最近、チーム内外でData Contractを取り扱う機会が増えています。本エントリでは、Data Contractの実践にあたり利用しているdatacontract-cliというOSSをなぜ選定したのか、業務で利用するにあたり不足していた機能にpull requestを送って貢献した話を紹介します。

Data Contractの必要性: しなやかなデータ連携を実現したい

10Xのこれまでのデータ基盤は

  • プロダクトから出力されるデータをBigQuery上に取り込んだ上で
  • ディメンショナルモデリングなど分析に使いやすいデータに加工し
  • その上でTableauなどのBIツールで分析結果をダッシュボードで可視化する

というよくある形式でした(この役割はもちろん現在も担っています)。しかし、プロダクトの高度化や事業の進展に伴ない、以下のようなユースケースも登場してきました。

  • BigQueryで集計したデータをプロダクト側の管理画面に表示したい
    • 単純に集計すればよい、というわけではなく、DWHやBIツールなどで整備されているロジックと共通化された集計結果を出したい
    • プロダクト側の開発チームとしては、集計された結果のロジックの詳細には踏み込まず、表示や可視化の部分に集中したい
  • データプロダクト間でデータのやり取りが発生するため、その仕様をプログラムが扱いやすい形でやり取りしたい
    • 手動で仕様をやり取りする形式(例: スプレッドシートやnotionで仕様の管理)はやめたい。実装と乖離してしまうことが経験的にも分かっている
    • データがある状態にたまたまなっているのか、生成側の制約として担保されているのかをスキーマの制約として記述したい
    • コードから仕様の自動生成や仕様からコードの自動生成(例: dbtのsourceの自動生成、Protocol Bufferの自動生成)を行なえるようにして、チーム間のコミュニケーションを疎にできるようにしたい

データを中心としたこういった複数チーム間でのデータの仕様(スキーマやその制約)を担保しつつ、機械からread / writeが可能で、開発者同士のコミュニケーションはなるべく疎にするようなデータ連携を本エントリでは「しなやか」と定義します。

Data Contractの導入に向けたより詳しい背景については、以下の発表資料にまとめていますので、そちらを参照してください。

datacontract-cliを通じて、しなやかなデータ連携を実現したい

Data Contractの仕様を考える際、10X独自の仕様を自分たちで考えることもできますが、継続的なメンテナンスを考えると、世の中の標準に合わせるのがよいと考えました。Data Contractの仕様としてはData Contract SpecificationOpen Data Contract Standard (ODCS)がありますが、10Xでは前者のData Contract Specificationを選択しました。理由としては

  • 取り扱える情報にそれほど大きな差異がない
  • 仕様だけでなく、周辺ツールであるdatacontract-cliが強力であると感じた
  • datacontract-cliを通じて、 Data Contract SpecificationからOSDCへの変換が比較的容易であり、後から乗り換えることが可能

が挙げられます。datacontract-cliは様々な機能を持っているため、詳しくは本家の情報を参照して欲しいですが、10Xで特に魅力に感じた点は

  • 様々な種類のデータ仕様書からのdatacontract-speficiationへの変換
  • datacontract-speficiationから様々な種類のデータ仕様書への変換

が挙げられます。こうした変換は一個一個は大したものではないため、自作する選択肢もありえます。直近でありえる変換{元, 先}としては

  • dbtのsourceやmodel
  • protobufやjsonschema
  • great-expectationsなどのvalidatorコード

などがあり、これら全てを自分たちで実装 / 継続的にメンテナンスするのは骨が折れます。datacontract-cliを利用することで、事業ドメインに深く関わる時間をより確保できる可能性が高いと考え、datacontract-cliを採用することにしました。

datacontract-cliに取り込まれた修正

これまで説明したように魅力的な機能を持つdatacontract-cliですが、10Xの業務利用を考えると不足している点も多かったです。ここでは、業務で利用可能にするためにdatacontract-cliにpull requestを送って取り込まれた修正について紹介します。

Data Contractとdbtの相互変換の際の型修正

最近Snowflakeの利用が増えているというのはOSSの世界でも感じることが多いですが、これはdatacontract-cliにおいても同じでした。data contract側で持っている型とdbt側で持つ型を変換する際、Snowflakeしか考慮されておらず、そもそもBigQueryが対象のdbtモデルではdatacontract-cliが動かない、という状況でした。そこで、BigQueryをはじめ、他のDWHにおいても動かしやすい形にリファクタリングし、Snowflake以外が対象でも動くように修正をしました。

スキーマの制約が反映されるように修正

Data Contractとdbtで仕様を変換する際、当初はスキーマの制約に関する情報の大半が抜け落ちてしまう状況でした。具体的には当初は

  • テーブル名、テーブルのdescription
  • カラム名、カラムのdescription、カラムの型

といった本当に必要最小限の情報しか変換後は残っていませんでした。チームをまたいでデータを取り扱う場合、以下のようなよりリッチなスキーマに関する情報が必要なことが多いです。

  • テーブルの主キーはどれか
  • 該当カラムは値が入っていることが必須かどうか(dbtのnot_null)
  • 該当カラムの値は一意であるか(dbtのunique)
  • 該当カラムはどのカラムの外部キーになっているか(dbtのrelationships)

10Xでもこういった情報はこういった情報はまさに必要としたため、datacontract-cliに対応するpull requestを少しずつ送り、その結果全て取り込まれました。

その他の細かい修正

これまで紹介した修正以外にも、datacontract-cliの使用感に関わる細かい修正も多数pull requestを送り、取り込んでもらいました。

Pull Requestが取り込まれたことでできるようになったこと

これまでに紹介した修正により、datacontract-cliを使って以下のData Contractの運用ができるようになりました。

  • データ基盤チームが管理するBigQuery上のデータの仕様をData Contractのyamlとして渡す
    • dartやprotobufの自動生成などに利用を想定
  • データメッシュ的な文脈でデータアプリケーションBが必要とするデータアプリケーションAの仕様をData Contractを通じてやり取りする
    • データアプリケーションAとBはそれぞれdbtで動いており、dbtのmodel定義 => Data Contract => dbtのsourceという形でdatacontract-cliを使って変換

Data Contractとの相互変換はGitHub Actions上で行ない、成果物であるyamlファイルはGitHub Releasesとして保存するようにしています。また、主キーや外部キーといったスキーマ上の制約も相互変換内で欠落することなく保持できるようになったため、しなやなかデータ連携に向けてのスタートを切ることができたかなと思っています。

今後の予定

現状の10Xの業務で必要なレベルのものは上記でひとまず揃ったのですが、まだまだ整備したい点がdatacontract-cliにはあると感じているので、いくつか紹介します。

インストール時に必要な依存ライブラリの整備

datacontract-cliはData Contractと多様な形式への相互変換ができることが魅力の一つですが、多様な形式をサポートするため、インストールに必要なライブラリが非常に多くなっています。ユーザーサイドが使う予定のない形式のための依存ライブラリもインストールされてしまうため、pip installなどの複雑性が上がってしまっています。実際、dbtやdbt-osmosisなど他のエコシステムと同居させる際に、依存ライブラリのバージョンの噛み合いが悪く、dbtが最新バージョンになかなか上げられない、といった弊害も出てきています。

そこで、ユースケース毎にoptional-dependencyとして切り出す作業を少しずつ進めています。

追加的なスキーマの制約に関する仕様のやり取りをできるようにする

本エントリでData Contractと相互変換をする際にリッチなスキーマ情報が落ちないようにする、という話を書きましたが、Data Contractの仕様ではよりリッチな情報を保持できます。例えば

  • あるカラムが取り得るenumの値の種類を記述
    • これらの値のどれかしか入らない
    • dbtのaccepted_values
  • あるカラムが取り得る値の範囲を記述
    • dbtのdbt_utils.accepted_range

といったものがあります。そういったものも相互変換の際に抜け落ちないようにする対応をいつかやりたいなと思っています。

まとめ

本エントリでは

  • 10XでData Contractが必要になった背景 / 課題
  • しなやかなデータ連携を実現するため、datacontract-cliを選定した理由
  • 業務で活用できるレベルまでdatacontract-cliにpull requestを送って貢献した話

を書きました。datacontract-cliは2024年のAdvent Calendarでも紹介している記事が複数上がっており、盛り上がりを見せています。

本エントリで紹介した内容やより踏み込んだ話題を上記のエントリの著者の方々とパネルディスカッションで議論する場を来月(?)主催しますので、ご興味ある方は是非ご参加ください!

参考:

セキュリティチームの日々の取り組みの紹介 (10X アドベントカレンダー 2024)

10xall.notion.site

10Xセキュリティチームの沢田(@swdyh)です。10Xアドベントカレンダー2024 の26日目の記事です。昨日は@yutatatatata さんの「商品データの裏側を覗く:意外に知らない商品IDの世界」という記事でした。自分も商品データに関する開発をしていた時期がけっこうあったので、奥が深くて面白いなと思って読みました。

先日、情報処理安全確保支援士の試験を受けたのですが、今日が結果の発表日でした。結果は不合格でした。JavaScriptのコードができてたり、画面を描く問題あったりして面白く解いてたはずだったんですが、午後の点数が57点で、あと1歩でした。またがんばります。

今日の記事では、セキュリティチームの日々の取り組みについて紹介したいと思います。

プロダクトの設計と実装レビュー

社内で書かれたDesign Docに一通りチームで目を通すようにしていて、気になるものあればレビューをするようにしています。また開発チームから、ここ気になるのでみてほしい言われることもあります。また実装されたときのコードレビューもやれる範囲でやっています。レビュー対象は、外部連携だったり、認証に関わるものが多かったりします。最近の事例だとOpenID Connect連携があります。

10x.co.jp

安全なサービスを提供するというのが第一の目的ではありますが、自分も元は開発をしていて、そういう大事な部分をつくるときには、これで大丈夫なはずだけど、、、みたいな不安を持っていたので、そういう開発者の不安を減らすこともできればと思っています。

プロダクトに関わる脆弱性アラートのトリアージ

GitHubの全リポジトリでDependabotのチェックを有効化し、新しくてできたアラートにに対処しています。さっと更新できそうなものは更新しつつ、そうでなくて影響がありそうなものは、issueを作って調査しています。

それとは別で、全範囲に適用できていないものの、Renovateを運用していて脆弱性のあるなしにかかわらず日々依存パッケージ更新できるようにしていて、こっちの更新でアラートが解消する場合もあります。

それから各リポジトリの更新できていないパッケージ情報集めるスクリプトを書いて、可視化するツールをお試しで作っていて、全体でどれくらい溜まっているとか、どのあたりのパッケージが手当されていないのかなどが分かるようにしています。

未更新パッケージの可視化

クレデンシャルレビュー

サービス連携などの使われるクレデンシャルを発行して使うケースで、それらの情報を記録し、管理方法や権限の強さや範囲をレビューするようにしています。過去、Secret Managerや1Passwordなどに用途不明のsecretがある状態になってしまっていたために、それはら棚卸ししつつ新規に発行するものにつては記録をしようということで始めました。クレデンシャルでできることは、その目的に対して最小限のものになっていてほしいところですが、そもそも細かく権限を指定できるサービスも多くなかったりして、大きめの権限を要求するサービス連携が多いのが悩み種だったりします。あとWorkload Identity Federationが普及してほしいなと日々感じています。Workload Identity Federationであっても適切に設定されているかのレビューは必要ですが、クレデンシャルそのものがないというのは安心ですね。

外部セキュリティアドバイザーとの相談会

セキュリティに関わる施策の相談や、設計レビュー、そのほか悩み事を相談をさせてもらっています。もともとチームメンバーがセキュリティ専門でないことを補うために始めた取り組みですが、悩みはつきないし、自分たちでは気づきにくい視点を得られるため大変助かっています。開発チームから開発担当者を呼んでいっしょにレビュー会をすることもあります。

アクセス制御不備チェック会

定期的に脆弱性診断を実施していますが、よく見つかるのが、本来アクセスできてはいけないデータにアクセスできてしまうケースで、パラメータのチェックが足りていなかったり、認可のチェックが足りていなかったりするものです。これに類似したケースは見つかってないだけで、他にもあるだろうということで、エンドポイントを1から眺めて同じようなパターンがないかを確認するという作業をはじめました。なかなか地味で果てのない作業なので、それぞれの担当場所のコードを読みながら、これどういうことなんだろうとか、ここちょっと危ないかも、みたいなことを話しながらやっています。実際に危なそうな箇所をみつけることもあり、成果もあるんですが、これをずっと続けるのはコストが高いので、ある程度読み進めた中で、いくつかパターンをまとめ、そういうこと自体がおきにくくする仕組みを作れないかみたいなことを考えたいと思っています。

セキュリティ輪読会

セキュリティに関する本やWebの記事を読みながら話合う会をしています。事前準備なしで参加者のた誰かが本文を読み上げ、気になるところがあれば都度話をしながら進めています。これもセキュリティの専門性を補うためにはじめた取り組みですが、ときどき仕事のなかでも「あの本のあれに書いてあった」ということもあったりしています。今年読んだものとしては以下になります。

これらの日々の取り組み以外にも、いろいろな施策をしていて、一部紹介の記事があるので興味のあるかたはこちらも見てみてください。

product.10x.co.jp

これからの話

今まではプロダクトセキュリティをメインに担当していましたが、それに加えて、コーポレートセキュリティ/コーポレートIT領域もやっていくことになりました。いくつかの経緯があってこうなったのですが、それぞれの領域は重なっている部分も多く、ソーシャルエンジニアリングやマルウェアなどの攻撃が高度化してるなかで、プロダクトという枠を超えていくことでやれることも多くあると思っています。

こんなセキュリティチームで、コーポレートIT/コーポレートセキュリティ領域メインに一緒にやってもらえる方を募集しはじめました。応募とまではいかなくても、少しでも興味があるかたは声をかけてもらえると嬉しいです。

コーポレートIT / 株式会社10X

[共通]カジュアル面談 / 株式会社10X

明日のアドベントカレンダーは、代表の矢本さんの記事です。おたのしみに。

商品データの裏側を覗く:意外に知らない商品IDの世界

本記事は10Xアドベントカレンダー2024の25日目の記事になります。メリークリスマス!🎄 🎁 🎅 🤶 🧑‍🎄

昨日はエンジニアの@futaboooさんが、『10Xも子育ても4年目のソフトウェアエンジニアが人生初EMになった話』という記事を公開されています。

膨大な商品データを眺めていて思うこと

こんにちわ!商品データチームの吉田(@yutatatatata)です。

私が所属するチームでは、ネットスーパーアプリ上で表示する「商品データ」を生成するデータパイプラインを開発しています。

複数パートナー様(10Xでは契約先の小売企業様をパートナーと呼んでいます)の膨大な商品データを日々触っていると、「パートナー横断で全商品をきちんと整理して並べてみたいなぁ」という気持ちが湧いてきます。

今回はそんなアイデアから商品のデータを整理して可視化してみた話を紹介します。

意外に知らない「バーコード」の話

普段スーパーなどに並んでいる商品には「JANコード」と呼ばれる商品識別IDが付いています。 世間的には「バーコード」と呼ばれているアレです。

商品コードはそれはそれでなかなか奥が深いですが、ここではややこしい部分は割愛して特徴をざっと紹介してみます。

JANコードとは

  • 定義:
    • JANコード(Japanes Article Numberの略)は、日本国内で広く使用されている商品識別用のIDで「どの事業者の、どの商品か」を表します。13桁の数字で構成されている「EAN-13」と、短縮版である8桁の「EAN-8」があります。
  • 桁数:
    • 13桁の数字(標準)と短縮版の8桁(小型商品用)

バーコードには13桁版と8桁版がある。パッケージ面積の小さい商品に8桁版が使われる。
図引用: https://www.keyence.co.jp/ss/products/autoid/codereader/basic_jan.jsp

  • 用途:
    • 日本国内の流通における商品管理、在庫管理、販売管理などに利用されますが、国際的にもEANコードとして認識されるため、海外でも使用可能です。

また、よりグローバルなGTINコードというものもあります。

GTINコードとは

  • 定義:

    • GTIN(Global Trade Item Number)は、GS1(流通コードの管理及び流通標準に関する国際機関。)によって定義された国際標準のバーコードで、商品やサービスを一意に識別するための番号です。JANコードはGTINの一部として扱われます。GTINは、地域や業界を問わず、世界中で使われる商品識別の基盤となります。
  • 用途:

    • GTINはグローバルに通用する商品識別コードで、輸出入を含めた国際的な取引でも使用されます。

違いのまとめ

  • JANコードは、日本国内の流通システムに特化したバーコードで、GTINの一部として機能する。
  • GTINコードは、JANコードを含む世界共通の標準として、商品を識別するために使われる。

簡単に言えば、JANコードは日本向けの識別コードであり、GTINはそれを含むグローバルな識別コードです。

普段何気なく見ているJANコードですがきちんと法則があり、先頭数桁は販売している企業を示す企業コードとなっています。そしてそのうちの先頭2桁はその企業の国コードを示しています。

先頭2桁は国コードを表す。日本のメーカであれば 45か49から始まる

日本の企業が販売する商品のバーコードは先頭が必ず 45 もしくは 49 で始まります。こういった商品は日本企業が販売している商品なので “ナショナルブランド商品” と呼ばれたりします。

なので、例えば輸入品オリーブオイルや韓国の食品などの海外食品のバーコードはそれぞれの国コードから始まります。

これでバーコードに詳しくなりましたね!今度スーパーに行ってみた際にぜひ確認してみてください。

10Xでは、スーパーのスタッフさんが商品をピッキングする際に使う便利なアプリも作っている関係で、パートナー様からそれぞれの商品のバーコードデータも受領しています。

バーコードには上記のような規則があるので、これを使えば一意に商品を識別できるIDとして使えそうです!

と、思うじゃろ?

ところがどっこい、厄介なバーコードたちがいます。

例えば↓

みんな大好きジャイアントコーンには複数の味がありますが全て「4901005312005」というJANコードになっています。

データ管理の観点からは、味ごとにユニークなJANコードが振られていてほしいですが、JANコードは「商品を完全にユニークに識別する」というよりは、「その商品を販売している企業が商品管理できるように」振られているようです。

そのため、「販売終了となった過去の商品のバーコードを再利用する」というケースもあり、時間的にも、商品的にも必ずはユニークにならないというなかなか難しい状態があるようです。

さらに、生鮮食品までこの話を展開すると、更に大変です。

生鮮食料品(野菜や肉など)は、個々の重さによって値段が異なるため各スーパー独自のコードを発行しています。このように店内でのみ使うコードをインストアマーキングといいます。

インストアマーキングの商品はその店内のみでしか販売しないため、JANコードとは異なりある程度自由に設定することができるようです。ただし、JANの国コードに対応する最初の2桁については、混同を避けるため20~29を使用するように決められています。

図引用: https://www.keyence.co.jp/ss/products/autoid/codereader/basic_jan.jsp

ここまで来ると「パートナー横断でJANコードをユニークIDとして商品データを統合する」ことが片手落ちになってくることがわかります。特に生鮮食品は難しそうです。

が、「結合が難しい商品もいろいろあるなぁ」ということを頭に入れつつ、とりあえず結合できるものは結合してみるかの精神でやってみます。データ分析あるあるですね。

商品の価格推移を出してみた

dbtとstreamlitで社内限定のダッシュボードアプリとして作成しています。

ナショナルブランド(バーコードが45,49から始まる日本の商品)に特に絞って商品データを整理してみました。10Xではサービス維持のため過去の商品データもある程度保持しているため、時系列データとして見ることもできます。

(注釈※10Xでは以下のような情報提供サービスを行っているわけではなく、あくまでデータ活用の可能性を考えるうえでの社内研究です。)

例えば、僕はここ数年毎朝お決まりのヨーグルトを食べていますが、そのヨーグルトの直近3週間ほどの価格推移を可視化してみるといろいろ興味深いです。

各パートナーで販売されている、とあるヨーグルトの3週間の価格変化

線は1つのパートナー様の価格推移を示しますが、同じヨーグルトでも日によってコロコロと価格が変わり、そして比較的価格差もあります。 ヨーグルトのような多くの人が日常的に購入する商品は、絶対値としては小さな金額差でも”あそこの店は高い/安い”という印象が残りやすい(”価格弾力性が高い”と表現される)ため、各社が価格競争を頑張っている雰囲気が伝わってきます。

ある1日における最安値との価格差を見てみても差が大きいことがわかります。

とある牛乳でも同じ雰囲気があります。赤い線のパートナー様は定期的にセールをしているんだろうな、など。

各パートナーで販売されている、とある牛乳の3週間の価格変化

他方で、とある缶ビール350ml缶は各パートナー様で固定の価格で販売されており、価格差もそれほど大きくありません。商品によって値段の付け方、売り方は様々だなぁと感じます。

各パートナーで販売されている、とある缶ビールの3週間の価格変化

最近は卵の価格が上がっているとニュースで聞くので、またその時系列データも見てみたいなと思いました。価格推移ひとつとっても、やはりデータを眺めているといろいろと思いつくことがあり面白いです。

小売データは堀り甲斐がある

いつもスーパーで見る馴染の商品のデータを触るのは単純に面白いですし、商品単位に整理されたデータは商品理解を深めるきっかけになり業務のいろいろな場面で役立ちそうです。また、単純に商品データ量が膨大であること、上述したような商品IDの難しい問題もありデータエンジニアリングの観点からも面白いテーマだと思っています。

私見ですが、この「商品を管理するID体系が微妙にイケてない」ことが小売企業のDXに少なからずブレーキをかけている面もあるんじゃないかなぁと感じています。中には、JANコードとは別に小売企業独自の商品IDを新規に振り直して管理されている気合の入った企業も見られます。現状のJANコード体系でも「店舗の運営」は可能かもしれませんが、デジタルによる業務効率化を行うには「(本当の意味で)商品単位でユニークに管理するID」が必要になると思っています。小売データの管理や分析は10Xの強みなので、このあたりもいい感じにしたいなと!

P.S. 最後に、私達 商品データチームが全パートナー様に対してどのように日々膨大な商品データを生成しているかの試行錯誤の歴史をまとめた90ページの気合が入ったスライドも公開しています。商品データのエンジニアリングに興味が湧いた方はぜひ御覧ください!

speakerdeck.com

(今回お話した商品データチームとは別職種ですが、)10Xではメンバーを募集しています!採用ページもぜひご覧ください。

まだまだ続くよ10Xアドベントカレンダー!明日はエンジニアのSawadaさんからプロダクトセキュリティーの取り組みのお話です!

本記事の参考:
GS1 Japan 一般財団法人流通システム開発センター
JANコードとは?JANコードの意味や作成方法などを紹介|ECのミカタ
JAN | バーコード講座 | キーエンス

人生初の在職エントリー

この記事は10Xアドベントカレンダー2024の22日目の記事になります。
昨日はSREの栗原さんが、Google Cloud IAM一時付与システムを「作らなかった」話という記事を公開しています。


こんにちは。10X 在籍1年目のQAエンジニア、こじしょー @KojiShaw です。
私の10Xの推しポイントは「オープンチャンネルが多く透明性の高いSlack環境」です。

実は今日、誕生日を迎えました。新しい1年に新しいチャレンジということで「人生初の在職エントリー」と題して、1月に10Xに入社してからのこの1年を振り返ってみたいと思います。(記念すべき初めてのブログ記事執筆です。)

入社の経緯

QAエンジニアとして

わたくし、QAエンジニア(以下、QAE)を名乗っておりますが、社会人キャリア16年半の中でQAEとしてのキャリアはまだ4年半です。前職からこの職種で働いています。

そのきっかけを作ってくれた一人が、アドベントカレンダー9日目に10Xに入って1年半でやったこと・感じたことという記事を公開しているブロッコリーさんです。前職の一次面接官の一人だったブロッコリーさんにより、私のQAEとしてのキャリアの扉は開かれました。

キャリアの転機・人生の転機

2022年の後半頃から、組織変更や異動が重なって求められる役割が大きく変化したり、一緒に働きたかった同僚が異動や卒業で離れてしまったりして、先々のキャリアについて考えざるを得ない状況になっていました。

さらに、年齢的にも節目を迎え、この先5年〜10年で起こるであろうライフイベント(身体の変化・生活の変化)にも自然と向き合うようになりました。コロナ禍が終息し多くの企業で出社回帰の動きが活発になる中、都心に住み続け都心に週の半分以上出社するフルタイム勤務に耐えうるのか不安を感じ始めた頃でした。

社内外の先輩・知人・友人に相談を重ねていたそんなとき、ブロッコリーさんが何だか楽しげに働いていそうだぞ、ということを聞きつけ、ご連絡してカジュアル面談をしてもらいました。

すると、私の好きなことに近い事業領域*1、噛みごたえありそう*2なプロダクト、QAEとしてやりがいがありそう、中長期で長く働けるよう配慮された制度がありそう...と10Xの魅力にグイグイ引き込まれてしまいました。

選考過程でQAEだけでなく、SWE・PdM・Designerにそれぞれインタビューする機会をいただき、そこで皆さんが品質に対しての思いや課題感を自分の言葉で語れること、QAEが求められていることを実感したことも大きかったです。

そして2024年1月、私も10XにJOINすることになりました。

開発体制と私が所属するチーム

10Xではドメインベースの開発体制を採用しており、ドメインごとの開発チームがあります。QAEは品質管理チームという横軸の組織に所属しつつ、各開発チームの中に入り込んで各チームの品質に関する幅広い業務を担います。

私は入社〜2024年3月までの3ヶ月はお買い物チーム、その後4月以降は店舗チームで活動しています。店舗チームはお買い物チームのドメイン領域を分割したチームなので、入社以来同じチームを担当していると言えます。

店舗チームはパートナーの店舗がネットスーパー・ネットドラッグストアを運営する上での各種管理機能を扱っています。例えば、お客様へ何時から何時までに商品をお届けするか・何件の注文を受け付けるかなどを定義する「注文枠」を作成や、その店舗からどの地域に配達するかを定義する「配達エリア」の登録などです。

入社当時の状況

お買い物チームに入った当初、既にチームには2人のQAEがアサインしていました。ただ、チームとの関わり方は以下のようになっており、もっと融合できる・もっとスクラムを組む ONE TEAM になれると感じました。

  • QAEのタスク状況はQAEのみが参加するQA朝会で会話され、チーム朝会(daily scrum)では必要なとき以外は特に報告していない
  • QAチケットのボードはチームボードと分かれている
  • Planningには参加せず、Planningの結果を後から把握してQAEのタスクを振り分けている
  • (全てのスクラムイベントに参加していないので)輪番で担当するスクラムイベントのファシリテーターもやっていない、ちょっとゲスト参加者っぽい

SWEとQAEのコミュニケーションは問題なく取れていますし、テストに必要な情報も双方向にやり取りをしながらきちんと取得できていて、問題が起きているわけではありません。

でもなんとなく、開発チーム内に専門のQAチームが別にあるような感じです。

この1年でやったこと

その1:QAEも含めた ONE TEAM を目指す

QA独自の活動をなくし、チームの活動に統合

まずはQA朝会を残しつつ、チーム朝会でQAの状況を報告することから始めました。

QAの状況をチームに伝えることで、特にEM(スクラムマスター)がQAタスクも含めたチーム全体の最適化をしやすくなるのではないか...

などと堅苦しい理屈を書くこともできるのですが、もっとシンプルに、朝会の場でQAEの存在感を出そうと思いました。それ以前も必要があれば朝会の場でQAEとSWEの会話はありましたが、アジェンダとしてファシリテーターが話を振ることで全員の注意が向き、そこにQAEがいる実感が生まれるのではないかということです。

また、お買い物チームから店舗チームに移行するタイミングでQAチケットをチームボードに統合し、QA独自ボードは廃止しました。SESで参画いただいていたQAEの方との確認用にQA朝会はしばらく残していましたが、その方の離任に伴い廃止して、今はQA独自の活動は残っていません。

Planningを含めた全てのスクラムイベントに出席する(ファシリもする)

Planningに参加せずにバックログだけ見ていると「どういう意思決定で開発着手するチケットを決めているのか」や「チケット同士の(隠れた)依存関係」などの計画に至る背景がわかりにくく、SWEとQAEの間でチケット毎の具体的な内容だけではない、もっと深い部分の認識の共有がしづらいと感じていました。

また、上述の背景がわからないことで先々の見通しも立てづらく、開発の早い段階からQAEが関わり、テストフェーズ以外のフェーズでもテストする取り組み*3に繋げにくいという課題もありました。

そこで、QAEもPlanningに参加するようにしました。これにより計画の背景が見えやすくなったのはもちろんのこと、Planningの段階でQAチケットについても必要に応じて会話できるようになったので、SWEも品質やテストに目が向きやすくなったと思います。

同時にスクラムイベントのファシリテーターのローテーションにQAEを組み込んでもらいました。チームの一員として役割を担っている意識にもなりましたし、ゲスト参加者っぽい雰囲気はなくなりました。

その2:開発のより早い段階からQAEも関わる

店舗チームでは今年、配達エリア移管機能という大物の機能開発に取り組み、12月初旬にリリースを迎えました。

この機能開発ではQAEを要件定義フェーズから巻き込んでもらうことができ、テストフェーズ以外のフェーズでもテストする取り組みを形にすることができました。

PdM、Designer、SWE、QAEが集まりオフラインでホワイトボードを使って議論しながら要件を固めていく場は長時間を要し、大変でしたが達成感があり熱かったです!

この場を通じて機能への解像度が高まっていたので、QAEのテスト分析は開発の初期段階で終えていました。その内容をSWEが機能を作り込む前にお伝えできたので、QAEが気になったポイントは機能開発を進める段階で取り入れられ、開発完了後のテスト指摘や手戻りをかなり抑えることができました。また、SWEがテスト内容を把握して事前に基本的な確認を行なってくれたので、テストフェーズでは複雑なパターンやエラーパターン、特殊なケースの不具合に集中でき、効率よくテストができていたように見えました。
(私は要件定義フェーズまで参加し、QAテストは別のQAEメンバーが担当しました。)

配達エリア移管機能のほかにも、複数の新機能開発の施策でこのような取り組みができ、早い段階からQAEを巻き込むことが店舗チームの型となって定着したと感じています。

その3:プロジェクト振り返りの企画・運営

上述の配達エリア移管機能は8ヶ月超というかなり長期に渡るプロジェクトとなりました。このようなプロジェクトでの学びを次に活かすべくプロジェクト振り返りが企画されたのですが、その振り返りでどのような手法を用いるかの提案や、その準備作業を 勝手に 引き受けて進めました。

振り返りは店舗チーム全員(SWE&QAE)、担当のDesigner及びPdM、さらに品質管理チームのEMとしてブロッコリーさんの総勢10名が参加予定です。しかし、全員が8ヶ月もの間、同じ密度・強度でプロジェクトに関わっていたわけではありません。途中からチームにアサインしたり、逆に関わりが薄くなったりしたメンバーもいます。このため、通常のスプリントレトロスペクティブで採用しているKPTだと個人間の認識の差が大きすぎ、チームとして振り返りにくいという懸念がありました。

そこで、タイムラインを用いた振り返りを採用するとともに、小チームに分かれたインタビューのプラクティスを取り入れることにしました。タイムライン上の付箋についてその要因やきっかけとなる出来事などを参加者同士がインタビューすることで、全員が共通認識を持った上で振り返りができるようにする狙いです。

...本来であればこの下に、その振り返りの様子を収めた写真を載せたり感想を書いたりしていた筈でした。しかし、私が直前にA型インフルエンザに感染し、出社できなくなったためリスケとなりました!!ああぁ...。

開催がこの記事の公開後になってしまい間に合わなかったのですが、こんな間の悪いタイミングで感染した私も参加すべきだからとリスケしてくれたチームには感謝しかありません!

この1年の満足度

この1年の満足度はかなり高く、とても良い形で1年を終えられそうです。

上述の通り、QA目線でチームに良い変化があったというのはもちろんですが、何よりそれを支えてくれる10Xのヒトに助けられました。

まずは店舗チームの皆さんです。私のような主張の強いQAEを受け入れてくれました。随分とグイグイ首を突っ込んでくるQAEだなぁと思われたと思いますが(笑)、とにかく ONE TEAM になってテストフェーズ以外でもQAEが当たり前にいるようにしたかったので、自分がわかりそうなところ・できそうなところにはとにかく首を突っ込みまくっていました。

そして、通常業務では関わることの少ないBizDevやCorpの方々。冒頭の推しポイントでも書いた通りオープンチャンネルが多いので、BizDevの皆さんの粘り強い仕事ぶりも、Corpの皆さんの心配りもSlackから知ることができて、勝手に他職種との距離がとても近いと感じていました。スタンプでリアクションするなどして距離感を縮めていたのでたまに出社した時や飲み会がある時に会話しやすく、10Xに馴染むことができました。

さらにはなんと、10Xを卒業した方々とも飲み会を通じて知り合うことができました。たまにカラオケに行くなど仲良くしてもらっています(笑)。

これだけ人の繋がりが広がることはあまりない経験で、今年はそのありがたみを痛感する1年となりました。

終わりに

なんだかめちゃくちゃ調子が良いまま何の曇りもない1年だったような文章になっていますが、実は一時は自分が価値が出せているのか、どう貢献できるのか不安で相当悩んだりもしました。悩みすぎて、一旦自分のできることを愚直にやろう、あんまり深く考えずにたまに自分を甘やかそう、そんな力加減も身につけて年末を迎えています。

2024年、なんとか走り抜けることができました。来年は他のチームでも何かしら良い変化を起こせるQAEでありたいな、と思うのでした。


10Xではメンバーを募集しています!採用ページもぜひご覧ください。
明日はビジネス本部の佐藤さん(kiyoseさん)が記事を公開する予定です。お楽しみに!

*1:料理が好きで、スーパーマーケットや八百屋・魚屋で食材の買い出しをするのが人生の喜びなのです。

*2:SIの基幹システム開発畑が長かったので、普段知ることのない企業内の業務オペレーションとプロダクト仕様が頭の中で繋がると高揚します。

*3:10Xが目指すQAの姿については少し古いですが、こちらの記事に記載があります。