組織をハイパフォーマーにするスキル、DevOps

こんにちは。弊社のエンゲージメントサーベイ製品HR Spannerのリードエンジニアを担当している岡部です。昨今注目されているDevOpsとそのケイパビリティについて、およそ一年前に社内の勉強会で発表を行ないました。今回の機会に、こちらでも寄稿させていただきたいと思います。


元になっている書籍は比較的大規模な開発を対象にしていると思いますが、当社のHR Spannerは10名程度の比較的小規模な開発であり、それを前提とした内容になっています。

DevOpsとは何か?

書籍「LeanとDevOpsの科学」では大規模アンケート調査により、高収益、高利益率、高市場占有率を持つ企業は、単に起業家精神やM&Aの取り組みだけでなく、開発組織におけるDevOpsのケイパビリティを強化している傾向が浮かび上がっています。この結果は単なる相関関係ではなく、統計手法によって因果関係として確認されています。また、DevOpsの取り組みは創造的な組織文化にもポジティブな影響を与えていることが示されています。

関連書籍では、顧客フィードバックサイクルを迅速に回すことができる企業は、今後のビジネス環境においても競争力を保持・強化できるとされています。

https://www.amazon.co.jp/dp/B07L2R3LTN

 

一部のレビューでは、本書がエンジニア目線のポジショントークであるとの指摘があります。しかし、古典的な組織論の視点から見ると、組織は個人の能力を超えた特定の目的を達成するための集合体であり、その最適な配置が求められます。技術進化により、個人の生産性が向上すれば組織の構造やその文化、チームの形態も変化すると思います。

本書では、DevOpsのケイパビリティやプラクティスを詳細に紹介しています。これらを平易な言葉で言い換えれば「スキル」なので、表題の「組織をハイパフォーマーにするスキル」は、ここで示される継続的デリバリーやWIP制限、システム監視がそうだということになります。

dora.dev

 

また、この取り組みの効果を示す指標として「Four Keys」という4つの要点が挙げられています。

  • デプロイ頻度:本番環境へ正常にリリースを行う頻度。
  • 変更のリードタイム:コードの初回commitから本番リリースまでの所要時間
  • 変更障害率:デプロイにより起きる本番環境で障害発生率
  • 平均復旧時間:本番環境の障害から復旧するまでの平均時間

これらの指標は「Findy Teams+」というGitHubと連携するSaaSでも測定することが可能で、弊社ではHR Spanner以外のプロジェクトでも活用しています。

パーソルキャリア、 「Findy Team+ Award 2023」を受賞 | プレスリリース | パーソルキャリア - PERSOL CAREER

 

本書では、スキルが組織のパフォーマンスを向上させるという点に科学的根拠を持ってアプローチしています。具体的な実践方法には詳細に触れていない部分もありますが、web系企業の開発では一般的なバージョン管理のような基本的な手法も含まれています。

この投稿では私自身が調査が必要と考えた部分と実践内容から、特にアーキテクチャー特性の部分について、当該の書籍で特に重視されている以下の二点を中心に、それらを向上させる手法について紹介します。

  • デプロイ容易性
  • テスト容易性

 

デプロイ容易性


クラウドネイティブ

「クラウドネイティブ」という言葉はバズワードのように聞こえるかもしれませんが、実際には、具体的な考え方があります。この概念はおよそ10年前にHerokuのエンジニアによってまとめられた「The Twelve-Factor App」という設計ガイドで説明されています。さらに、近年のクラウド技術の発展を反映して、VMwareが「Beyond the 12 Factor App: Exploring the DNA of Highly Scalable, Resilient Cloud Applications」というアップデートされたガイドを公開しています。

 

The Twelve-Factor App (日本語訳)

Beyond the 12 Factor App: Exploring the DNA of Highly Scalable, Resilient Cloud Applications

 

The Twelve Factor Appはいわゆるステージングや本番などの個別の環境に対応する構成情報や依存パッケージをアプリケーションコード内に持たせない(環境変数や、環境内で共通で使うデータストアを使用する)ことで、一度ビルドしたアプケーションイメージを複数環境間で使いまわすことができ、並列起動も可能にしてデプロイ容易性を高めます。
この性質以外にもデリバリの安定・高速化が見込めるプラクティスが示されており、とても有用だと思います。

また、これによるデプロイの容易さを実感するには、Herokuが提供している「Heroku Flow」のフローが具体的でわかりやすいです。

Heroku FlowではGitHubリポジトリにPull Requestを作成するだけで検証環境を自動でデプロイしたり、アプリケーションインスタンスの開発環境、ステージング環境、本番環境などと移動・デプロイを開発者の承認プロセスと合わせて定義することができ、一連のデプロイの流れを非常に効率的に進めることができます。

jp.heroku.com

 

トランクベース開発

トランクベース開発についての詳細は、Google Cloudの公式ドキュメントで詳しく解説されています。

DevOps 技術: トランクベース開発  |  Cloud アーキテクチャ センター  |  Google Cloud

 

トランクベース開発とは: 短期間でのデプロイを重視した開発手法で、全ての開発者が単一の本番用ブランチ(多くの場合「trunk」や「main」)上で作業し、頻繁にコードをマージ・デプロイする手法です。

先に挙げたThe Twelve Factor Appにおける「開発/本番一致」の考え方とも付合し、うまく運用すれば安定したデリバリが実現でき、Four Keysの指標を直接的に向上させることが期待されます。ただし、導入の際のハードルは無視できないものと思われます。その理由として、トランクベース開発を効果的に行うためには、TDD (テスト駆動開発) とフィーチャートグル(機能の公開・非公開を管理する手法)の導入が必須となるからです。
単純にテストが自動化されていないとそんなに早くリリースはできない、ということだけでなく、機能が中途半端に公開されたり、逆にそれを制御しようとするコードが技術的負債として積み重なるリスクがあります。

したがって、まずは一般的なgit flowを基本として開発を進め、次第に上記のプラクティスを取り入れ、最終的にトランクベース開発へと移行するのが適切と考えられます。

以下の表は、トランクベース開発、フィーチャートグル、TDDの組み合わせによる予想される開発結果を示しています。

 

トランクベース開発 フィーチャートグル TDD 予想結果
Excellent: ハイパフォーマー
 
Good: ミドルパフォーマー
 
Bad: 中途半端な状態の機能が公開される
 
Bad: 負債化したフィーチャートグルのコードが堆積・テスト不足で不具合頻発

 

 

フィーチャートグル

フィーチャートグルは、機能の公開・非公開を動的に切り替える機能で、これにより開発中の機能を完了するまで非公開に保つことような機能でリリース管理する手法です。これについてはMartin Fowler氏のサイトで詳細に紹介されています。

martinfowler.com


特にこのうちのRelease Togglesが必要になるでしょう。

  • Ops Toggles:メンテナンス画面の切り替えなどに用いられ、APIミドルウェアなどでDBのフラグを参照してHTTP Statusを503に変更する方法などがあります。
  • Experiment Toggles:A/Bテストのようにユーザーごとに異なるコンテンツを表示するためのフラグ。
  • Permission Toggles:ベータ機能のオプトインなどがこれに該当します。Experimental Toglleとともに実際に使用する際にはGoogle Analyticsとの連携が重要となると考えられ、Firebase Remote Configでの実現が想定されます。
  • Release Toggles:新機能の公開・非公開を管理するもので、トランクベース開発のサポートとして活用されます。静的なハードコードによる実装が紹介されていますが、個人的にはクラウドネイティブの考え方とは異なるため、環境変数やFirebase Remote Configのような専用SaaSを使う方が良いと思います。受け入れテストやデモ環境などで、将来公開予定の機能を先に見たい/本番同様に隠したいなどが起こりえると想定されます。

また、Release Togglesは機能公開後は不要なコードとして技術的負債になるため、そのことへの対策として、以下のアプローチが推奨されています。

  • フィーチャートグルを使わないことを検討する
    • APIから先に開発・デプロイしていくなど
  • 公開から一定期間後のRelease Toggleが自動的にテストで失敗するよう設定する

 

テスト容易性

コードレビュー

テストの一つの目的は「エラー検出」です。そもそもの話になってしまいますが、この観点から見ると、過去の調査からコードレビューはエラーを検出する上で非常に効果的であることがわかっています。
コードの可読性を向上させることは、レビューを円滑に進めるために重要です。可読性を向上させる手法に関しては多岐にわたるため、ここでは詳しくは触れませんが、その重要性は念頭に置いておくべきです。

QA活動の種類 バグ検出率
カジュアルなデザインレビュー 25%〜40%
フォーマルなデザインレビュー 45%〜65%
インフォーマルなコードレビュー 20%〜35%
カジュアルコードインスペクション 45%〜70%
モデル化やプロトタイプの作成 35%〜80%
個人的なコードチェック 20%〜60%
ユニットテスト 15%〜50%
新機能のテスト 20%〜35%
統合テスト 25%〜40%
回帰テスト 15%〜30%
システムテスト 25%〜55%
小規模のベータテスト(10サイト以下) 25%〜40%
大規模のベータテスト(1000サイト以上) 60%〜75%

 

Beizerのバグ検出率を元に作成

 

テスト自動化戦略: Test Automation Pyramidと割り振り

システム条件の全ての組み合わせを網羅するテストは、自動化の観点からも非現実的です。テストの中で、単体テストが最もコスト効率が良いとされています。しかし、単体テストのみではリファクタリングに伴うリスクを完全にカバーすることはできません。したがって、まず統合テスト(例: APIのブラックボックステスト)を実装し、その後で単体テストを追加することが推奨されます。

テスト自動化ピラミッドと、その容易性を高める手法

 

https://www.amazon.co.jp/-/en/Mike-Cohn/dp/0321579364

 

手動テスト

下記の書籍やテスト自動化ピラミッドを定義した書籍Succeeding with Agileでは、手動で行うテストは、探索的テストのみが推奨されています。探索的テストは、事前に定められたテストケースに縛られず、ソフトウェアの振る舞いを直感的に確認しながらテストを進める方法です。このテスト方法は、以下の理由から推奨されています:

  • 他のテスト方法では検出が難しいバグを発見できる。
  • 短時間で効果的にテストを実施できる。
  • 手動のシステムテストは、バグ検出率が低くコストが高い。

ソフトウェア品質を高める開発者テスト 改訂版 アジャイル時代の実践的・効率的でスムーズなテストのやり方(高橋 寿一)|翔泳社の本

 

また、前述のHeroku FlowにおけるReview AppのようなPull Requestごとにレビュー用の環境を自動生成する仕組みがあると、この探索的テストがとてもやりやすくなります。

インテグレーションテスト

忘れられがちなことだと思うのですが、このインテグレーションテスト(例えばAPIに対する呼び出しテスト)などはバグ検出率が低い一方で、リファクタリングを行おうとした場合に現実的に必須になります。
リファクタした箇所の単体テストを書いたとしても、そのテストケースも新たに作成したものであり、それが正しいことは手動で検証するしかないためです。
したがって、個人的には実はほとんどのケースで自動テストとして最優先に書くべきものだと思います。

こういったAPIのレグレッションテスト手法として「Golden Test」があります。この方法は、APIテストの初回実行時にレスポンス内容を保存し、2回目以降の実行時にその内容に変更がないかを検証するものです。この方法は、GoやFlutterのコミュニティでの採用例が見られます。

https://github.com/sebdah/goldie


また、上述のSucceeding with Agileで紹介される手法として、ユーザーストーリーで要求仕様をデシジョンテーブルとして定義し、それをそのまま組み合わせ条件のテストケースとしたブラックボックステストを行うと方法も有用と思います。

こちらもGo言語ならテーブル駆動テストとして記述できます。

単体テスト

単体テストはバグの検出効率が他のものに比べて最も高いですが、前述の理由からそれだけを最優先するのは教条的とも言えます。重要なのは、初期の設計段階でサンプルコードを書く際の単体テストを意識し、後からでもテストを追加しやすいアーキテクチャを維持することだと思います。

Testing HoneycombやTestting Torophyに近い考え方になりますが、上述の書籍で高橋壽一氏が述べられている通り、インテグレーションやE2Eのようなテストでは条件の組み合わせ爆発が起き条件の抜けもれを出さざるを得なくなるため、最終的には単体テストを多くしてカバレッジを高める方が、品質を高めるためには現実的だと思います。

最後に

HR Spannerの開発でも、これら以外も含めてDevOpsケイパビリティ向上を進めており、特に上流でのバグ検出や、自動化戦略に合わせたテスト容易性の向上は安定したデリバリに寄与していると感じています。

あとはなかなか変えられないインフラ部分へのThe Tweleve Factor App適用などができればいったんOKかな、というところです。

また、個人的にはFour Keysの向上はHR Spannerのような比較的小規模な製品より、弊社で言えばMiraizやdodaのような中・大規模な製品の方がより効果が高いのではないかと思います。

事例としても大規模のものが多いですし、開発規模が大きいほど「リリースサイクルが短いほど本番と開発の環境ギャップをなくなりリスク低減」するという効果が顕著で、開発リソースが多い分、潜在的なデプロイ頻度が高く、より早いフィードバックサイクルが見込めるはずだからです。

HR Spannerではフィーチャートグルの必要性は実感できているものの、通常のアジャイル開発でのスプリント(2週間)ごとのデプロイで頻度としては十分、というところで落ち着いています。(定義的にはハイパフォーマーですしね笑)

ただ、もちろん変更のリードタイムや変更障害率を中心にHR Spannerでも見ていますし、それに以外にも代表的なアジャイル指標である累積フロー図を使ったボトルネックプロセスの特定など行なっており、結局のところ定期的に全部見てみて課題があれば対応する、という動きをしています。

 

エンジニアリング統括部 サービス開発部 第3グループ エンジニア 岡部 利樹

岡部 利樹 Toshiki Okabe

エンジニアリング統括部 クライアントサービス開発部 HR_Spannerエンジニアリンググループ リードエンジニア

※2023年10月現在の情報です。