技術選定と、組織のかたちと、セキュリティ

技術選定について最近の私生活や労働を通して考えたことを、つらつらと書き下した文章(ポエム)です。 他者に伝えることではなく、頭の中におぼろげに存在する考えを言語化して客観視することを目的に書いた雑記なので、 誰かにとっては当たり前なことも、誰にも当てはまらないことも書いてあるかと思います。 またここで述べることは、こうやって書き下した時点での僕の考えに過ぎないので、明日僕は全く別の考えを持って行動しているかもしれません。 いわばこれは僕の思考のスナップショットです。 諸々、ご容赦ください。

技術選定そのもの

ソフトウェアの開発においては、どこからが開発者の作るものの責務であり、どこからがその下のレイヤの責務であるかを(あるときには能動的な思考より、またあるときには受動的な思考により)明確にする、という知的活動を繰り返していくことになります。 この営みは、開発するソフトウェアに関する前提を定める営み、とも言い換えられます。

例えばユーザ空間で動く、そこまで高いパフォーマンスが求められるわけではないソフトウェアを書いているのであれば、開発者はハードウェア資源の管理のことはあまり気にしないでしょう。この時開発者は、OS の提供する抽象化層と上手く会話をしながら所望の機能を実現するのが自身の責務であり、そこから先は OS の仕事である、という前提を(無自覚かもしれませんが)導入しています。

また FaaS 上で動作することを前提とした API エンドポイントをソフトウェアを開発・運用することを考えます。 この際の開発者の責務は、既にパースされ、構造化されたリクエストを受け取り、それを元にレスポンスを生成するような関数を FaaS プロバイダに提供するところまでです。 一方そこから下 —— 例えばユーザからの通信を受け取ったときに、適切にアプリケーションランタイムを起動し、開発者から提供された関数に通信を流すというような仕組み —— を提供し、健やかに動かし続けるのは、FaaS プロバイダの責務になります。

このような 「前提の設定」 1 は、ソフトウェア開発だけではなく、システム開発においてもその初期に求められることです2。 例えば Web システムを開発しようとすると、何を永続化ストレージとするのか、認証認可の仕組みは開発する Web アプリケーションの中に持たせるのか、サーバサイドで動く Web アプリケーションはどんな言語でどんなフレームワークを用いて作るのか、……というような、様々な前提を定義していくことになります。 そして定められた前提同士を上手くつなげたり、その前提に立脚する新たな何かを作ることで、開発を進めていくのです。

ここからは、このような「前提の設定の営み」、つまり 「あるシステムの仕様が与えられたときに、それを満たすようなシステムを構成するために、前提とするものを列挙する営み」 のことを、技術選定 と呼んでやることにします。

技術選定の自由度

前項で定義した技術選定とやらは、兎にも角にも自由度が高く、厄介なものです。 システムを構成する手段は一つではないためです。

例えば「アンケートフォームをユーザに見せ、答えを回収し、その結果を(加工した上で)なんらかのデータストレージに蓄積したい。そのデータは管理者が簡単に閲覧できるようにしたい。」というニーズがあり、これを解決するシステムを作ろうとしたとします。 このとき Google フォームに少し GAS を連携させてやる、というのは選択肢の一つです。 この選択肢は一見貧相にも見えるかもしれませんが、SaaS に強く依存することでダウンタイムをあまり気にする必要がなくなるという点で、(要件を満たせている限りは)立派な選択肢である、と筆者は考えます。

一方自前で RoR や Django 製のアプリケーションを一つ作ってやり、その上でサーバサイドのロジックを担保してやってもいいでしょう。 要件や開発者のスキルセットによっては、フレームワークを使わないべた書きの PHP で実装してやる、というのも選択肢になりうるかもしれません。 またユーザのブラウザ上で表示される Web ページを構成するのには、HTML+JS+CSS をベタ書きしてもいいですし、React + styled-components のようなやり方を取るものいいでしょう(最近の筆者は専ら後者のやり方を取っています)。 こうして作ったアプリケーションを PaaS や FaaS に乗せるのか、それとも何処かで VM を借りて乗せるのか、オンプレの環境を構築するのか、というところも自由です。

自由度からくる評価への動機

しかし自由度が高いからといって、どんな選択肢をとってもよい、ということではありません。 技術選定という選択は、後の「運用」「改善」の 2 つの営みに大きな影響を与えるからです。

例えば先だって例示したアンケートを回収・表示するためのシステムを Google フォーム + GAS で実現したとします。 このときシステムの健やかな動作を担保するのは、そこまで難しいことではありません。システムそのものの運用に関する心配ごとは少ないでしょう、 ただこのシステムは、あくまで既存の SaaS が提供している機能で実現できる機能しか実現できませんから、どこかで技術的な壁にぶつかる可能性があります。

一方このシステムを自前で Web アプリケーションを作ることで実現したのなら、工数さえかければ大抵の機能追加をできるでしょう。 しかしこの場合は初期の開発コストとその後の運用コストが一定大きくなることが容易に予想できます。 いくら注意してコードを書いても、障害は起こってしまうものです。

このような背景から、技術選定において、数ある選択肢たちの中から「最適なもの」を選びたいという気持ちが芽生えてきます。 よく「技術選定は難しい」と言われますが、その難しさの本質はこの「何が最適か」を考える部分であるように思います。

4 つの評価軸

しかしここでいう「最善」を定義するためには、各選択肢を評価してやる必要があります。

そして評価のためには、評価基準が定義されていなくてはなりません。 基準のない中で何かを比べるのは「悩む」と同じ程度の知的活動であり、ある基準のもと何かを比べてみて、ようやく「考える」のフェーズに到達するものです。 逆に技術選定は、まずこの評価基準についての認識をチーム内で揃えてやるところからスタートするべきである、と筆者は考えます。

また評価基準はできるだけ明確であることが好ましいでしょう。 評価基準が明確であればあるほど、(組織の全員が満足できるような選択肢でなくとも)納得感を形成しやすいからです。

では具体的な評価基準としては何を採用するのが好ましいのでしょうか。 この問いに対する答えは人によって異なるでしょう。

筆者の場合、普段は @timakin さんの『理想の技術選定』という記事 で挙げられている以下の 4 つの評価軸を採用しています。 非常に明瞭でよい言語化だと思います。

  • サービス要件の担保
  • 経済性
  • 開発生産性
  • 技術信頼性

評価軸を支配する変数

しかしこの 4 つの軸は、いくつかの(技術選定により得られた)「前提」のセットを相互比較するための 指標 に過ぎません。 「技術選定の結果得られたパターン A は、パターン B に比べて経済的である」だとか、 「パターン A, B, C は、経済性の観点から見ると順に ◎ ○ △ と評価され、開発生産性の観点から見ると順に ○ △ ◎ と評価される」というような感じで用いられるものです。

となると、今度は、これらの軸たちがどう決まっているのか —— つまり、これら 4 つの軸が依存している変数とはなんなのか、というところが気になってきます。 この変数に関する認識が甘ければ、これらの指標を正しく見積もることも難しいからです。 そこでここからは、各軸の評価において筆者が意識している、各軸を支配する変数についてを、順に紹介したいと思います。

まず サービス要件の担保 は、およそ「その技術選定の結果、所望のシステムは実現しうるか」という趣旨の軸です。 そのため特筆すべき変数もなく、ちゃんと事前に定義したことが実現できるのであれば、一律最高評価を与えることにしています。

一方 経済性 という軸について考えると、この背後には次のような変数があります。

  • 組織の資金力
    • 残キャッシュや与信、調達見込み等
  • サービスが価値を発揮する状態になるまでに必要な人件費
    • チームメンバの教育にかかる工数も含む
  • プロダクトの利益構造からくる、そのプロダクトの運用にかけていい費用3

大まかにいうと、開発に投資する余力と、イニシャルコスト、そして単位時間あたりのランニングコスト、の 3 つが変数になるわけです。 これらの数値はシステムの仕様(=何を作るか)がある程度の精度で定まっていれば、大雑把にでも見積もることができるものですから、技術選定の段階で概算値を持っておくとよさそうです。 そしてこれらの数値をもとにすると「経済性」という総合的な指標を、ある程度の解像度で評価してやることができます。

次に 開発生産性 という軸の背後にあるのは、以下のような変数たちです。

  • 学習に必要な時間
  • オンラインに存在するドキュメントの量
  • 関心の分離により期待される、並列作業の効率化度
  • DRY (Don’t Repeat Yourself) の実現のしやすさ
  • テストコードの書きやすさ

このうち前半 2 つについてはかなり定量的に評価しやすいものです。 一方最後の 3 つについては、個人開発や過去の経験があれば定量的に評価できるものの、プロダクト初期においては定性的な評価が限界であるように思います。 なお関心が分離しやすいアーキテクチャほど、その分離の境界にはきちんとしたインターフェイスが定義されており、開発のオーバーヘッドが大きくなります。 そしてこのオーバーヘッドが開発スピードに与える影響は、大きな組織ほど無視しやすく、小さな組織ほど無視しにくいものです。 したがって 3 つ目の「関心の分離により期待される、並列作業の効率化度」というのは、組織規模によって変動する値である、と考えるべきです。

最後の軸である 技術信頼性 については、これらの変数あたりが、大雑把に情報を集めやすく使い勝手もよいです。

  • 開発母体のレピュテーション
  • GitHub 上でのスターの数・コントリビュータの数
  • GitHub 上での Issue や Pull Request の処理フロー・スピード
  • ダウンロード数(npm などの場合容易に確認できる)
  • GA 後に経過した時間

ソースコードの LOC や構造の綺麗さなんかも大まかに評価しておくと、社内でメンテナンスが続けられるようなシロモノか事前に分かるので、少しだけ安心感が得られるかもしれません。 ただ小さな組織ではメンテナンスまで手が回らないことが容易に想像できますから、小さな組織の開発においては、上述のような支持母体に関する指標を確認しておく方が好ましいでしょう。

以上が各軸の変数として筆者がよく検討するものたちです。 このように、筆者は普段の技術選定において、極力絶対的な評価をしやすい変数を利用するように心がけています。 組織開発の場合、その選択が説明可能 (Explainable) であること、が非常に大切だと考えているからです。 数字が具体的であればあるほど、その背後にある論理が明確であればあるほど、合意は形成しやすいものです。

「組織のかたち」

前項で検討した評価軸を支配する変数を眺めてみると、技術選択を評価するための軸は、組織に関する情報(組織規模、平均的な能力値、…)と強く結びついていそうだ、という示唆が得られます。 少し象徴的な表現をすると、技術選定は「組織のかたち」と強く紐づくものだ、ということです。

またこのような検討に鑑みると、巷にあふれる「ベストプラクティス」の類を咀嚼することなく自組織に導入していくのは好ましくない、と筆者は考えます。 その時の組織のかたちにをよく整理し、それに基づいて適切に評価を行った上で、自組織にはレガシーな開発手法がマッチすると考えるのであれば、それはそれでいいと思うのです。 逆に「バズワードだから」「楽しそうだから」に基づく技術選択も、その選択主体となる組織が、そういう行動規範を持っているのであれば、それはそれで組織のかたちとよく向き合えていると思います。いいんじゃないでしょうか。

まとめると、技術選定において大事なのは、「組織のかたち」に代表される諸変数を適切に洗い出し、そこから各評価軸についてを懇ろに検討した上で選択を下すことなのだろう、と思うのです。

余談: MVP とセキュリティ

少しだけ余談をば。

近年は Auth0 や Okta のような IDaaS(ID as a Service)の登場・発展や、Pomerium のような所謂 IAP(Identity-Aware Proxy)プロダクトの発展により、認証認可に関するコンポーネントを自作しないという選択肢 —— すなわち、技術選定の段階で認証認可を「前提」の中に据える、という選択肢が生まれてきています(といってもそこまで新しい話ではありませんが)。

またこのようなプロダクトの利用はどんどん簡単になってきています。 例えば GCP の場合、GCE/GAE をバックエンドとして L7LB を使っているのなら、それと一緒に Cloud IAP を有効化してやるだけで GSuite 組織を利用した AuthN / AuthZ が行えます。 これは非常に手軽ですが、社内向けに展開するアプリケーションの保護ならこの程度で十分でしょう。 Firebase を採用するなら、Firebase Authentication を使うのも一つの手です。 また SPA(Single Page Application)を作りたいのであれば、適当に Auth0 と契約し、auth0-spa-js を使ってやれば、あまりややこしいことを考えることなく4 AuthN / AuthZ を実装することができます。 簡単な RBAC であれば Auth0 サーバ上でスクリプトを走らせる機能(Rules や Hooks と呼ばれる機能)によっても実現することができます。

いまプロダクト開発初期のような、MVP(Minimum Viable Product)を作ることに注力したい時期においては、セキュリティについて考える頭のゆとりがあまりないものです。 むしろセキュリティ、というのは面倒な存在です。 そう考えると、このようなセキュリティに関する部分を「前提」の側に移せるように技術選定をする、というのは理にかなった方針なのではないかと思います。 サービス要件を担保しつつ、開発生産性を向上させることが期待でき、かつ一定技術信頼性の担保も(とくに有償のサービスであれば、サポートも含めて)期待できるからです。

勿論サービスの要件(例えば個人情報の取扱いに関する要件等)によっては、プロプライエタリなソフトウェアの利用が難しい場合もあるかもしれません。 しかし技術選択においてセキュリティ面の関心を分離しておくと、開発における「ややこしい点」「怖い点」を減らしやすいものです。 技術選定の際の選択肢の一つにするために、この辺りのソフトウェア・プロダクトを大まかに洗い出しておくといいかもしれません。

結びに

本稿においては、以下についての筆者の一連の考えを整理しました。

  • 技術選定という営みがどのようなものとして整理できるのか
  • その選定の結果の評価にはどのような評価軸を導入できるのか
  • 各評価軸の背後にはどのような変数があるのか

なお冒頭で述べたように、本稿はあくまでポエムです。 なのでこれが「ベストな技術選択の仕方だ!」というのを提示することはしません。 しかし読んでくださったあなたの頭の整理や、新たな気づきの源泉にならないとも限らないので、これを公開してみた次第です。

ところで、敬愛なる Rhymester さんの楽曲『The Choice Is Yours』(シングル『The Choice Is Yours』や他ベストアルバム等に収録されています)には、「そいつは自分たちの選択 マジ面倒 / だがそれもできないんじゃ もうジ・エンド」という一節があります。いい韻ですね。 いまこの曲は勿論技術選定についての曲ではありませんが、技術選択においても、同じことが言えると筆者は思っています。 技術選定は面倒な営みであるものの、他者の語るベストプラクティスを見て右へ倣えを続けるだけでは、道を踏み外しうるものです。 うまく参考にし、考え方を吸収し、あくまで自組織の選択として技術選定を行いたいものです。

  1. ここで「前提」と「設定」という二語は、それなりに母音を共有しています。「ここで私は韻を踏みました」という主張をできるほどの一致度ではありませんが、ほぼ韻を踏んでいる感じの二語ですね。 

  2. ここでは相互接続されたソフトウェア群のことをシステムと呼んでいます。かなり雑な言い方ですが、世の中ではこの辺の言葉が非常に雑に使われているようなので、許してほしいです。 

  3. サーバレスな技術を採用する場合、この辺の予測可能性 (Predictability) がかなり低下するように筆者は感じています。「雑に使っても、費用面がネックがなることはない」という実体験に基づく感覚はあるのですが、このような言語化されていない感覚は、マネージャー層を説得する材料としては利用しにくいものです。とくに関係値が十分でない相手に対して説明する場合には。 

  4. ややこしいことも考えられるだけの知識がないと、落とし穴に気が付かない可能性もありますから、もちろん十分基礎的な理解を得てから利用したいものです。 

Written on August 7, 2020