"攻めの開発"を支える安全安心なリリース

この記事は、10X 新春ブログリレー 2026の記事です。前日は、jojoさんによる「バージョンアップ手作業のつらみから解放された4つの自動化施策」でした。自動化って尊い!


もう1月中旬!早いですね。 id:hisaichi5518 です。

2025年は、Stailer ネットスーパーの店内業務・配達用アプリのリアーキテクチャに伴う作り直しを主に進めていました。特に店舗で注文された商品を集めるときに利用するピッキングリストというStailer ネットスーパーを利用する小売企業のほとんどが利用する部分の作り直しを行いました。

この作り直しを"攻めた開発"として、安全安心なリリースとの両立を強く意識して進めていたので、それについて書きます。

なぜ安全安心なリリースが必要なのか?

Stailer ネットスーパーの店内業務・配達用アプリは、注文された商品を集める(ピックする)ときに利用する機能や配達に関する機能などを持っています。多くの小売企業がこの機能を利用しており、1日にたくさんの注文がこのアプリを通じて処理されています。

そのアプリでもし不具合が発生したら

  • 店舗スタッフの業務が遅延*1
  • お客様への配達が遅延
  • お客様・店舗からの問い合わせが殺到

つまりネットスーパーを利用するお客様の食卓はもちろん、小売企業の生産性、10Xの生産性、間接的には売上など影響が大きいです。なので、安全安心なリリースをしていく必要があります。

安全安心なリリースをするために

安全安心なリリースは、以下を満たすものだと考えています。

  • なるべく早く開発チームが問題に気付くこと
    • リリース後よりはリリース前、実装後よりは実装前などなるべく早いことが望ましい
  • リリース後に問題があったら1分1秒でも早く元に戻せること
  • リリース後に問題があったら1分1秒でも早く原因を特定できること

これらを満たすためにやっていることを書いていきます。

機能が持つ概念をまとめる

今回の作り直しでは、ただ機械的に既存実装を新しいアーキテクチャに置き換えていくというよりは、改めて「この機能はどういう概念を持っているか」をDesign Docに書いてから実装しています。例えば「商品のバーコードを読み取ってピックしたことを記録する」という機能を扱う時、以下のように捉えました。

  1. 読み取る
    • Android は 内蔵カメラを使ってバーコードを読み、 MLKitを利用してバーコードを読み取る
    • iOS は内蔵カメラを使ってバーコードを読み、AVFoundationを利用してバーコードを読み取る
    • 外付けスキャナは外付けカメラを使ってバーコードを読み、外付けスキャナ独自の方法でバーコードを読み取る
  2. 変換する
    • AVFoundationは、12桁のバーコードを読み取った時、13桁に自動的に変換する。Stailer的には、12桁として扱いたいので13桁かつAVFoundationで読み取りかつ最初の桁が0の場合は、12桁に変換する
  3. 処理する*2
    • アプリ内に保持されたリストの中から読み取ったバーコードに一致するものを見つけて、結果によってピックを記録する

「商品のバーコードを読み取ってピックしたことを記録する」は、1.読み取る, 2.変換する, 3.処理するによって構成されており、1, 2, 3はそれぞれが疎結合になっているべし!というのが整理することで見えてきます。

このあたりを整理せずに実装し始めると、既存実装に引っ張られて密結合した状態の実装が出来上がって残念なことになるみたいなことがありました。

整理した内容はDesign Docに記載して、実装前にQAE, SWEにレビューしてもらっています。

実装時に何を検討するかを書く

またDesign Docには「より詳細な設計をする実装時に何を検討するか」も書いていています。

例えば、「商品のバーコードを読み取ってピックしたことを記録する」という機能を整理した結果、1.読み取る、2.変換する、3.処理するというのがあることがわかりました。また読み取る部分では複数の読み取り方法があり、今後も新しい読み取り方法が追加されうることがわかりました。

そこで「バーコード読み取り方法の追加にはどのように備えておくか?」という疑問が出てくるのですが、これはクラス設計など詳細設計時に色々試しながら決めたいので、それは未確定の論点としてDesign Docに記載しておき、プルリクエストを出すときに一緒にDesign Docに結論を追記してレビューを依頼するとしています。

実装前にリリース計画と切り戻し方法を書く

実装前にリリース計画をDesign Docにまとめていて、そこに問題が起きた時どうやって切り戻すかを書いています。実装してから切り戻し方法を考えるよりは、実装する前に考えておくとそれを踏まえて作るので後から継ぎ足しにならないので考えることが少なくていいです。

自動テストを書く

今までテストが書けてなかったのがリアーキテクチャによって書きやすくなったので書くようになりました。単体テストとWidgetテスト(ゴールデンテスト)を書いています。

意味のあるテストであることが重要だと思っていて、QAEが行ったテスト設計を元に単体テストを書き足したりすることもあります。またあえてテストを書く作業を見積もり時に考慮していて、実装は2ポイントテストはその半分くらいの作業量だからこのチケットは3ポイントみたいなことを見積もり時に考えています。

本番に近いデータで単体テストする

商品に付いてるバーコードをアプリで読み取ってピックを記録するいう機能があるのですが、バーコードは様々なデータがあり標準的なパターンだけではなく小売企業が独自に定義したパターンもあったりするので、本番に近いデータを利用して単体テストを動かすことで知らなかったパターンを見つけたり、作り直す前と後で動作に予期しない変化がないことを確認しています。

しかし、店頭に並んでいる実際の商品のバーコードはStailerは持っておらずわからないので、あくまで実際にスキャンするバーコードに近いだけであるというのは念頭においておく必要はあります。

シャドウテストをする

特定のリストから条件によってデータを抽出するというような表示や直接データ変更を行わないロジックはシャドウテストを行うようにしています。

シャドウテストは、本番環境で新旧両方の実装を並行して動かし、新しい実装の結果を実際には使わずに記録・比較するテスト手法です。ユーザーには旧実装の結果だけが返されるため、新実装に問題があってもユーザー影響はゼロで、本番の実データで新実装を検証できるのが最大のメリットです。

シャドウテストを行ったおかげで既存実装と作り直し後の実装で動作に差異があることがわかり、事前にプロダクトマネージャーに「リリース後、こういう変化があります。これは新しい実装が仕様に沿っているので正しい変化です」というコミュニケーションが取れて、リリース後にドタバタせずに済みました。

Feature Flagで機能の有効無効を切り替える

モバイルアプリはリリースするのにも審査などで早くても1日くらいかかるので、Feature Flagで機能の有効無効を切り替え出来るようにしてリリースして、有効後に安定していると判断できたらFeature Flagの利用をやめるようにしています。問題が合ったときは、Feature Flagをオフにするだけで切り戻しが高速に行えます。

調査用のログを出す

とにかくログを出して問題が起きてそうな時に何が起きてるのかを把握できるようにしています。何をログとして記録するかがポイントだと思いますが、自分は以下を意識して記録するようにしています。

  • いつ
  • 誰が
  • 何が起きたか
  • 変化がある場合は、変化前と変化後の値
  • 異常がある場合は、なにが異常で異常とした根拠

一方でこのログはあくまで不具合の調査用です。分析用のログは極力サーバーサイドで記録するべきです。「A画面を開いた」など分析用にどうしてもモバイルアプリ側で記録する必要があるときは、別の仕組みを利用しています。

DataDog RUMに記録出来ることは記録する

Datadog RUMは以下のようなイベントを記録できます。これらを取ることで今までは時間がかかっていた調査もかなりスムーズにできるようになってきました。

  • ユーザーが表示したビュー / Dialog
  • タップイベントなどのユーザーアクション
  • エラー
  • APIリクエスト
  • Feature Flagの値
  • Shared Preferencesの値

今のところセッション数の制御はしておらず、toCサービスに比べてセッション数が多くならず突然跳ねることもないので、今はとにかく全て送るとしています。

モニタリングを行う

クラッシュ率、このログが大量に出たらアラートなど色々モニタリングしてます。 この辺りはRUMとログをDatadogに送っているので、Datadogで行っています。

俺たちの戦いはこれからだ!

安全安心なリリースのためにやれることはやり尽くしたように見えますが、作り直すこと以外も含めて攻め続けるにはまだまだやれることはあるはずです。例えば

  • APIリクエストはエラーによってはリトライが行われるがそれを考慮したモニタリングにはなってない。または考慮できていないため意味のあるモニタリングになりにくい。SLO化もまだ
  • ピックにかかる時間を監視して、一定の基準以上遅くなればアラート
  • E2Eテストがなく人間による手動の結合テストが必要

2026年も引き続き、攻めの開発と安全安心のリリースの両立をしていきたいと思います!!明日は、uraさんによる「仮)登壇資料をAIに作らせたら失敗した話」です。楽しみですね!

*1:完全な業務停止はしないように代替性を持たせています

*2:正確には、ここはもっと複雑なのですが、例なのでシンプルにしています

バージョンアップ手作業のつらみから解放された4つの自動化施策

バージョンアップ手作業のつらみから解放された4つの自動化施策

この記事は10X 新春ブログリレー 2026の1月13日分の記事です。


はじめに

こんにちは。10Xでソフトウェアエンジニアをしていますjojo(@joj0hq)です。

2025年4月にチームが合併し、それまで触れてこなかった商品データパイプライン(ETL処理をdbtで実装)の開発に携わるようになりました。チーム合併の詳細については、EMのfutaboooさんが書かれた以下の記事をご覧ください。

10x.co.jp

新しい技術領域に触れる中で、バージョン管理の運用負荷という課題が明らかになってきました。本記事では、十数パートナーに対する共通パッケージのバージョンアップ作業を自動化し、開発効率を大幅に改善した取り組みを紹介します。


システム構成の概要

改善内容に入る前に、私たちのアーキテクチャについて簡単に説明します。

私たちは、共通パッケージ(data-express)実装プロジェクト(stailer-dbt) という2層構造でマルチテナント型のデータパイプラインを運用しています。

アーキテクチャ図

graph TB
    subgraph "data-express (共通パッケージ)"
        DE[dbtパッケージ<br/>共通モデル・マクロ提供]
        style DE fill:#e1f5ff
    end

    subgraph "stailer-dbt (実装プロジェクト)"
        direction TB
        P1[パートナーA<br/>data-express v0.1.0使用]
        P2[パートナーB<br/>data-express v0.2.0使用]
        P3[パートナーC<br/>data-express v0.1.5使用]

        style P1 fill:#fff4e6
        style P2 fill:#fff4e6
        style P3 fill:#fff4e6
    end

    DE -->|パッケージとして利用| P1
    DE -->|パッケージとして利用| P2
    DE -->|パッケージとして利用| P3

    BQ[(BigQuery)]

    P1 --> BQ
    P2 --> BQ
    P3 --> BQ

構成要素

  • 共通パッケージ(data-express): 複数パートナーで共通利用できる再利用可能なdbtパッケージ。データ変換ロジックや集計処理などのコアロジックを提供
  • 実装プロジェクト(stailer-dbt): 各パートナーの個別要件に対応する実装。共通パッケージを参照し、パートナー固有の処理を追加
  • バージョン管理: 各パートナーは独立したバージョンの共通パッケージを利用可能。段階的なバージョンアップが実現

この構成により、共通ロジックの品質を保ちながら、各パートナーの要件にも柔軟に対応できています。


直面していた課題

共通パッケージの新バージョンがリリースされるたびに、以下のような手作業が発生していました。

  1. PR作成の手間: 十数パートナーに対して、都度バージョンアップ用のPRを手動で作成
  2. レビュー負担: パートナーごとにレビューと差分検証(developブランチとfeatureブランチのBigQueryテーブル比較)を実施。レビュワーの負担が大きい
  3. 差分確認の煩雑さ: 差分結果を都度Looker Studioのダッシュボードを確認しに行く必要があり、結果の把握に時間がかかる
  4. 通知の不足: データ作成の検証をするためのdbt Cloudでの処理完了や失敗を能動的に確認する必要がある

この運用負荷により、バージョンアップのたびにSprintのチケットを切り、計画的に作業時間を確保する状態になっていました。


改善への取り組み

上記の課題に対して、4つの観点から改善に取り組みました。

改善後のワークフロー全体像

graph TB
    subgraph "改善後のワークフロー"
        V[共通パッケージ<br/>新バージョンリリース]

        subgraph Auto["自動フロー"]
            RN[Renovate<br/>PR自動生成]
            CR[Claude Code Review<br/>自動チェック]
            DC[差分検証<br/>自動実行]
        end

        Manual[スラッシュコマンド<br/>/diffcheck]

        subgraph Notification["通知"]
            Comment[PRコメント通知<br/>完了/失敗通知]
            Diff[差分結果表示<br/>差分の有無とサマリー]
        end

        V --> RN
        RN --> CR
        CR --> DC
        DC --> Comment
        DC --> Diff

        Manual -.->|手動実行| DC

        style V fill:#e3f2fd
        style RN fill:#c8e6c9
        style CR fill:#c8e6c9
        style DC fill:#c8e6c9
        style Manual fill:#fff9c4
        style Comment fill:#c8e6c9
        style Diff fill:#c8e6c9
    end

    Solution[✅ PR作成自動化<br/>✅ レビュー自動化<br/>✅ 差分確認自動化]

    Notification -.-> Solution

    style Solution fill:#e8f5e9

1. PR自動生成(Renovate導入)

課題

実装プロジェクトで適用する共通パッケージのバージョンを上げるために、パートナーごとにPRを手動で作成する必要がありました。十数パートナー分のPRを作成するのは非常に手間がかかります。

解決策

Renovateを導入し、共通パッケージのリリースと同じタイミングで各パートナー向けのPRを自動生成するようにしました。

実装詳細

  • Renovateの設定ファイルで、共通パッケージの更新を監視
  • 新しいタグがリリースされると、自動的にパートナーごとのPRを作成
  • PRには変更内容のサマリーを自動で含める

Renovateによる自動PR作成
Renovateによる自動PR作成

効果

  • PR作成作業がゼロに
  • リリース直後に即座にPRが作成されるため、バージョンアップの遅延を防止

2. レビュー自動化(Claude Code Review × reviewdog導入)

課題

バージョンを上げるごとにパートナーごとのレビューが必要で、レビュワーの負担が大きくなっていました。

解決策

Claude Code Reviewとreviewdogを組み合わせて導入し、PR作成時に自動で基本的なチェックを実施するようにしました。

実装詳細

  • GitHub ActionsでClaude Code Reviewを実行
  • 共通パッケージの変更内容を解析し、パートナー固有の実装に影響がないかチェック
  • reviewdogと連携することで、実装に紐づく細かいコメントをコードの該当行に直接投稿
  • 問題があればPRにコメントで指摘

Claude Code Reviewによる自動チェック
Claude Code Reviewによる自動チェック

効果

  • 基本的なチェックは自動化され、人間は最終確認のみに集中できるように
  • reviewdogにより、コードの該当箇所に直接コメントが付くため、レビュー内容が分かりやすい
  • レビュー時間の大幅な短縮

3. 差分検証の自動実行

課題

バージョンアップ前後でのデータ差分を確認する作業が手動で、毎回実行するのが大変でした。

差分検証とは: developブランチとfeatureブランチでそれぞれdbt runを実行し、生成されたBigQueryのテーブルを比較することで、機能開発や修正によるデグレ(品質劣化)を検出する取り組みです。この検証により、意図しないデータの変更を早期に発見できます。

graph TB
    subgraph "差分検証の仕組み"
        subgraph Branch1["developブランチ"]
            D1[dbt Cloud<br/>dbt run実行]
            D2[(BigQuery<br/>developスキーマ)]
            D1 --> D2
            style D1 fill:#e3f2fd
            style D2 fill:#bbdefb
        end

        subgraph Branch2["featureブランチ"]
            F1[dbt Cloud<br/>dbt run実行]
            F2[(BigQuery<br/>featureスキーマ)]
            F1 --> F2
            style F1 fill:#fff3e0
            style F2 fill:#ffe0b2
        end

        Comp[BigQuery<br/>テーブル・カラム比較]
        D2 --> Comp
        F2 --> Comp

        Result{差分あり?}
        Comp --> Result

        Result -->|差分なし| OK[✅ デグレなし<br/>安全にマージ可能]
        Result -->|差分あり| NG[⚠️ 差分を確認<br/>意図した変更か検証]

        Visual[結果の可視化]
        OK --> Visual
        NG --> Visual

        subgraph "確認方法"
            V1[Looker Studio<br/>詳細ダッシュボード]
        end

        Visual --> V1

        style Comp fill:#f3e5f5
        style Result fill:#fff9c4
        style OK fill:#c8e6c9
        style NG fill:#ffccbc
        style Visual fill:#e1bee7
        style V1 fill:#c5cae9
    end

この差分検証を自動化するため、以下の2つのアプローチを取りました。

解決策

差分検証を2つの方法で実行可能にしました:

  1. Renovateとの連携による完全自動実行: RenovateがPRを作成すると、自動的に差分検証が実行される
  2. スラッシュコマンドによる手動実行: 必要に応じて /diffcheck コメントで差分検証を実行できる

実装詳細

  • dbt Cloudのジョブを呼び出すGitHub Actionsを作成
  • RenovateによるPR作成をトリガーに、自動で差分検証を実行
  • 必要に応じて /diffcheck コメントでも実行可能
  • 検証結果をPRにコメントで返す

スラッシュコマンドによる差分検証の自動実行
スラッシュコマンドによる差分検証の自動実行

効果

  • RenovateによるバージョンアップPRでは、完全自動で差分検証が実行される
  • 手動での確認作業を大幅に削減
  • 必要に応じてスラッシュコマンドで再実行も可能

4. 差分検証結果の通知と可視化

課題

差分検証の結果確認に関して、以下の問題がありました:

  1. 通知の不足: dbt Cloudで処理が実行されるため、処理の完了や失敗に気づきにくい
  2. 結果の確認が煩雑: Looker Studioのダッシュボードを見に行かないと差分の詳細が分からず、確認に時間がかかる

解決策

GitHub PRへのメンションコメント通知を導入し、差分検証の完了・失敗を自動的に通知するとともに、差分の詳細を可視化しました。

実装詳細

  • dbt Cloudのジョブ完了/失敗をトリガーにGitHub Actionsを実行
  • PRにメンションコメントで結果を通知
  • PRコメントに差分サマリーを含める
  • エラーの場合は詳細なログへのリンクも含める

実行結果のGitHubコメント通知
実行結果のGitHubコメント通知

効果

  • dbt Cloudを能動的に確認する必要がなくなった
  • 差分の有無とサマリーをPRコメント通知で即座に把握できるようになった
  • Looker Studioに確認しに行かなくても、意図しない差分にすぐ気づけるようになった

改善の効果

Before / After比較

項目 Before After
PR作成 十数パートナー分を手動作成 完全自動化
レビュー パートナーごとに個別レビュー 基本チェックは自動化
人間は最終確認のみ
差分検証 手動で実行して結果確認 Renovate PRでは自動実行
必要時はコマンド1つで実行可能
結果確認 dbt Cloudで処理完了を確認
Looker Studioで差分を確認
PRコメント通知で即座に把握

得られた成果

  • 作業時間の大幅削減: バージョンアップに伴う手作業がほぼゼロに
  • リードタイムの短縮: リリースから適用までの期間を大幅に短縮
  • レビュー負荷の軽減: レビュワーは本質的な確認に集中できるように

まとめ

本記事では、マルチテナント型dbtプロジェクトにおける共通パッケージのバージョンアップ運用を自動化した取り組みについて紹介しました。

一度にすべてを自動化するのではなく、課題を分解して1つずつ改善することで、着実に効果を得られました。Renovate、Claude Code Review、dbt Cloud、GitHub Actionsなど、既存ツールを組み合わせることで、短期間でバージョンアップ作業を大幅に削減することができました。

マルチテナント型のデータパイプライン運用において、同じような課題を抱えている方の参考になれば幸いです。

私たちのチームでは、このようなdbtを活用した開発効率改善のほか、dbtとAIエージェントを組み合わせたデータ調査など、AIを拡張した取り組みも行っています。

speakerdeck.com

また、Podcastでチームの開発の裏側や働き方についても語っていますので、興味があればぜひご覧ください。

open.spotify.com


10Xはこの社会インフラとなるネットスーパーや、小売業のDXを通じて半径1mの人の生活を良くしていくために、仲間を募集しています。本記事のような開発効率を改善する取り組みに関心がある方は、ぜひカジュアル面談でお話ししましょう!

open.talentio.com

conftestによる自動レビュー

conftest は、Open Policy Agent (OPA) の Rego 言語を使って、構造化データ(YAML、JSON、Terraform、Dockerfile など)に対するポリシーテストを実行するCLIツールです。

よくあるユースケースとして、Kubernetes マニフェストや Terraform の設定ファイルに対して「コンテナは root で実行してはいけない」「すべてのリソースにタグが必要」といったルールの適用です。これらのルールを組織ポリシーとして定義して、それに適合しているかをconftestで検査できます。conftestをCIに組み込めば、PRに含まれた変更が問題ないかどうかを機械的にチェックできるというわけです。

これまでの10Xでも、Regoを書きconftestを使って検査してきていましたが、Rego言語のとっつきにくさ/学習コストの高さがネックでポリシーの追加が億劫でした。しかし最近はLLMがかなりマチュアになり記述コストがゼロになったので年末に一気に再整備しました。

conftest以外にも社内の組織ポリシーを評価してconfig類にapplyする手段はありそうですが、自然言語(AIによるRego記述)を通して「こう書いてほしい」を強制できているため今はconftestがお気に入りです。AIによる検査は、自然言語のみだと評価結果にゆらぎが出る可能性がありますが、RegoというDSLを通すことでAIと人間の共通プロトコルができ、毎回必ず同じ評価結果を得られます。conftestを使うことでレビューで人間が同じ指摘をする必要もなくなるし、例えば「ここハイフンを使ってほしくないんだよなぁ」みたいなもう申し訳ないnitsレビューもconftestを通して代弁することができます。裏を返せばtestが通ってconftestも通っているなら、問答無用にApproveできる状態というのが理想かもしれません。

今回は再整備して追加したポリシーなどを含めて、10Xでどんなポリシーを定めているのかを一部紹介します。

続きを読む

OpenSSL x509 コマンドはPEMのフォーマットの検証まで行っていない

10X SREの栗原です。
この記事は10X 新春ブログリレー 2026の1月7日分の記事です。

OpenSSLのコマンドではエラーにならなくても、Google Cloud側の証明書アップロードで弾かれることがあるため、PEMを厳密に検証するステップを追加して再発を防いだ、という話です。

続きを読む

フルスタックDartからRustバックエンドへ

この記事は10X 新春ブログリレー 2026の1月5日分の記事です。


弊社が提供するネットスーパーのサービスは、モバイルアプリとWebはFlutterアプリ、バックエンドはDartのgRPCサーバーで実装されています。isomorphicではないですが、言語統一がされたフルスタック的な状態と言えると思います。

バックエンドでのDartはマイナーであり、それに伴って様々なデメリットもありました。それらを乗り越えたり飲み込んだりしながら、5年ほどサービスを運用してきましたが、これから先は方針を転換することに決めました。

この記事では、我々が何故フルスタックDartから方針転換することにしたのかと、今後のバックエンドの言語としてRustが有力になっている背景を説明します。

方針転換のきっかけは採用

バックエンドのDartでは様々な問題にぶつかってきましたが、どれも方針転換に踏み切るほどにはならず、なんとか対処してきたのがこれまでです。そんな中、方針転換のきっかけとなったのが採用です。

事業の初期フェーズではマルチスキルのソフトウェアエンジニアで開発チームを構成し、技術領域で役割を分けないやり方をしてきました。事業のフェーズが進むにしたがって、バックエンドの開発ニーズが高まりましたが、世間のバックエンドエンジニアからすればDartは積極的に選びたい言語ではありません。マネジメントの立場としてはバックエンドを強化したいが、技術スタックがマッチしていないという状況になっていました。

技術的な課題であればなんとかできる可能性もありますが、採用と技術スタックのアンマッチは変えない限りはどうにもなりません。バックエンドにおけるDartの立ち位置が変わるのを待つか、自分たちがバックエンドで使う言語を変更するかを考えた時、会社としては後者を選ぶことに決めました。

バックエンドのDartのふりかえり

次の言語を選ぶ前に、バックエンドにおけるDartのメリットとデメリットを整理しました。

メリットとしては以下のものがありました。

  • 静的型付き言語として程々に機能が揃っている。nullabilityやmutabilityの制御ができる、網羅性検証つきのパターンマッチがある、といったラインは抑えられており、ロジックの記述における不便は少ない。
  • 学習コストが高くない。言語仕様はJavaとKotlinの間くらいという感じで、際立った特徴は少ないのでキャッチアップしやすい。複雑な型制約などが書けないこともあり、言語の理解度の差による実装方法に差が大きくなり過ぎない。
  • シングルバイナリで動かせる。

デメリットとしては以下のものがありました。

  • バックエンドのエコシステムが未成熟。ミドルウェアのドライバはあったりなかったりで、あっても不安なものもある。外部サービスのSDKはまずない。モニタリングや分散トレーシングの実装も少ない。
  • 基本的にはシングルスレッドであり、CPUバウンドな処理はつまりやすい。Isolateで逃すことはできるが、Isolateの立ち上げが重い、メモリ共有ができない、スタックトレースが分断される、といったハードルがあり、広くは使いづらい。

キープできるメリットはキープしつつ、解消すべきデメリットは解消することにしました。

運営自律性という事業上の特性

言語の候補を選ぶ上では、我々の事業に合っているかどうかも考慮しました。

10Xの社内には運営自律性と呼ばれる特性があります。システムの利用者が失敗をタイムリーに認識し、自力で訂正できる状態になっているかどうかを指すものです。プロダクトが扱う業務フローが複雑で、多様なシステムとも連携する必要があるため、運営自律性の有無は運用コストに大きく影響します。

運営自律性はタダではなく、それなりのコストを払う必要があります。開発者がエラーをトレースできるだけでは不十分で、エラーを業務上の意味のあるアプリケーションの仕様として扱うため、その分の実装コストが乗るためです。このコストを払うべきかはプロダクトによって異なると思いますが、我々のプロダクトでは必要だと判断しています。

運営自律性の得やすさは、言語がエラーをどう扱うかに左右されます。最下層のレイヤーのエラーから利用者に見せる最上位のエラーまで漏れなく仕様を定義して変換することを前提とすると、一般的な例外や、型なしのエラーでは、コンパイラによる網羅性検証に頼れなくなるため、その分不利になります。そのため、一貫して型付きでエラーで扱える言語が、事業に適していると判断しました。

現在はRustを検証中

これまでに説明した論点を踏まえて色々と検討した結果、現在はRustで一部のシステムを置き換えの検証を進めています。実装面ではかなり良い手応えを得られていて、幅広いエラーを漏れなく仕様に反映する営みが自然に回せています。一方で、人材の多さやエコシステムの充実度という意味では少し不安もあります(それでもDartよりは遥かに良いですが)。

現状不安を感じている点も踏まえて飲めるものか判断し、最終的な決定に進む予定です。

また、今回決めようとしているのはあくまで汎用的にバックエンドで使う言語であり、特定の言語を使った方が良い場面では引き続きその言語を使うことになると思います。Go、Python、TypeScriptに関しては明確にそういう箇所があり、併用していく予定です。

おわりに

以下のインタビューに、Dartで統一した時の状況がよくまとまってました。 https://type.jp/et/feature/15075/

Dartで統一するまでの壁や、統一したことによるメリットなどを話しているのですが、最後は以下の言葉で締めくくられていました。

――中には、あえて言語を統一せず、そのときどきの現場判断で10以上の言語を使っている開発組織もあると聞きます。石川さんは、エンジニアリング組織はどうやって言語選択していくべきだと思いますか?

大切なのはその言語を使う目的と「どんな問題を解決したいのか」を考えることだと思います。10言語を扱っている組織にしても、きっと事業フェーズやプロダクトの状態など、その時抱える課題や目的に応じて最適な方法を選んでそうなっていると思うんですよね。

うちの会社もプロダクトが増えたりして、Dartだけでは困るような状況になれば、また言語を増やすことだってあるかもしれません。流行っているからといって組織やプロダクトが抱えている問題を解決できないなら、その言語を採用すべきではないですし、新しい言語で自分たちが解決したい問題を解決できるなら、そのためのハードルはフットワーク軽く乗り換えるべき。

組織のフェーズや目的によって正解が違うので、ただ「新しいから」「人気だから」ではなく、その時に抱えている課題を解決するために、言語を選び取っていくスタンスが大切なのだと思います。

上記で触れている"その時に抱えている課題を解決するため"に大きな変化を起こす時が来た、というのが今なのでしょう。

サービスは5年続けることができましたし、今の調子を考えると10年以上は続きそうです。プロダクトの中には、このままで10年目を迎えられる箇所もあれば、このままでは事業成長のボトルネックとなる箇所もあります。何をどう変えるかによって10年目の状態が変わるので、技術的な変化の価値が高いフェーズでもあると思います。

難しいですが、上手くやって良い業績を出せるソフトウェア開発に挑戦していきます。

仲間募集

10Xはそんな感じでエンジニアリングしていきたい仲間を募集しています。ピンと来た方は是非1度話しましょう。

10x.co.jp

10X の CX (Cool Experience) チームで働きませんか

10X の CX (Cool Experience) チームの @metalunk です!

この度、CX チームのバックエンドエンジニアの求人をはじめました。

バックエンドエンジニア(検索、推薦) / 株式会社10X

このブログは当ポジションの魅力を紹介するための文章です。

その中で、CX チームがこれまで上げてきた成果、それらの成果を上げられた理由、いま抱えている問題、それを解決した先に目指していること、をお伝えできたらと思います。

続きを読む

イベントを活用したアプリケーション実装 | お届けチーム取組紹介

これまでシリーズの記事で書いたように、お届けチームの扱っているシステムはイベントを扱って非同期処理をしています。

product.10x.co.jp

非同期処理でイベントを扱うということは、イベントをモデルとして扱うのとセットです。 イベントは書き込み系で作成しか発生しないモデルかつ、参照系でイベントそのものをクエリしないものとしています。

この記事では書き込み系・参照系でそれぞれイベントに関わる実装がどうなっているのか紹介します。

続きを読む