🌄

複雑なものを複雑なまま扱う

2024/12/13に公開

この記事は株式会社ココナラ Advent Calendar 2024 13日目の記事です。

こんにちは。
株式会社ココナラに所属しているKです。
今日は「複雑なものを複雑なまま扱う」というテーマで書いてみたいと思います。

はじめに

私たちは日々の業務の中で、複雑な問題に頻繁に直面します。
この複雑さを単純化しようと試みることは、時に問題解決を遠ざける可能性があります。
今回は、複雑なものを複雑なまま扱うという視点から、ソフトウェア開発におけるチームのあり方について考えてみたいと思います。

リソースという言葉

リソースという言葉に対して感じる違和感

リソースという言葉があります。
CPUやメモリなどを指してリソースと呼ぶこともあれば、何かにアサインされる人のことをリソースと呼ぶこともあります。

前者をリソースと呼ぶことに違和感はないのですが、後者に対してリソースという言葉が使われるたびに少し違和感を感じています。
私自身もたまに人のことをリソースと言ってしまうことはあるのですが、その後にはやはり違和感のようなものが残ります。

なぜ違和感を感じるのか

なぜ違和感を感じるのか、それは人をリソースとして考えることには以下2つの問題があると思うからです。

  • ソフトウェア/プロダクト開発は個人の能力の集積ではなく、チーム全体の協働から生まれる複雑な相互作用の結果、という重要な側面を覆い隠してしまう
  • リソースとして扱われる人の認知負荷を増大させてしまう

どちらについても、その結果として意図しない効率の悪化を引き起こします。

なぜリソースと呼ぶのか

詳細に入る前に、なぜ人のことをリソースと呼ぶのか考察してみます。

まず確実に言えることは、何か悪意があって人をリソースと呼んでいるわけではないということです。
おそらく私も含めて人に対してリソースと表現しているのは、ヒトという多種多様な生物をリソースという形に抽象化することで、考えるのが楽になるためでしょう。

例えば、以下のようにです。

  • 合計4日かかるタスクがある
  • 全てのタスクを2日で終えるには、2人のリソースで2日ずつ分担すればよい

難しいことをそのまま考えるのでなく、抽象化してシンプルに考えるというのは人間に備わっている能力の一つであり、その意味では必ずしも間違った行動ではありません。

リソースとして抽象化することの問題点

算数としては問題ない

算数としては、以下のように考えることは問題ありません。

  • 合計4日かかるタスクがある
  • 全てのタスクを2日で終えるには、2人のリソースで2日ずつ分担すればよい

しかしながら、ソフトウェア開発に関わった経験がある方は、上記を見てそうではないと感じるでしょう。
具体的には、以下のように感じるのではないかと思います。

  • 人によって、2日でできるとは限らない
    • その領域についてのドメイン知識の有無、技術スキルの有無、コードベースの理解度などによってかかる時間が大きく変わる
  • タスクには、クリティカルパスなどの前後関係があるはず
  • 2人の組み合わせや分担の仕方により、後続タスクへの影響が変わってくる

最後の項目(後続タスクへの影響)については少し補足が必要だと思いますので、補足します。

例えば、少し極端な例として以下の2人がいるとします。

  • Aさん: UXを考えるのが得意だが、コードを書くのが苦手
  • Bさん: コードを書くのが得意だが、UXを考えるのが苦手

そして、2つの機能をそれぞれで分担して2日かけて開発したとします。

  • 機能1: Aさんが2日かけて開発
  • 機能2: Bさんが2日かけて開発

この場合、コードを書くのが苦手なAさんが担当した機能1は後のQAで品質問題が発生する可能性が高く、UXを考えるのが苦手なBさんが担当した機能2はUX上の問題が発生する可能性が高いでしょう。
しかしながら、Aさん、Bさんを均一なリソースとして捉えた場合には、この可能性に気付くことができません。

それでも、この可能性の影響が無視できる程度に小さければ問題ないのですが、現実的には無視できず、むしろ影響が大きいことの方が多いです。

ソフトウェア/プロダクトは個人の能力の集積ではなく、チーム全体の協働から生まれる複雑な相互作用でできている

さらに続けましょう。

上記の例では以下のように仮定しましたが、現実はもっと複雑です。

  • Aさん: UXを考えるのが得意だが、コードを書くのが苦手
  • Bさん: コードを書くのが得意だが、UXを考えるのが苦手

例えば、以下のように人によって得意、不得意な項目というのは無数にあります。

  • スピードが速い
  • ミスが少ない
  • ドメイン知識がある
  • 技術に強い
  • 自身のタスクをきっちり完了させるのが得意
  • 他の人のタスクを巻き取るのが得意
  • ファシリテーションが得意
  • リスクを予測できる
  • ・・・

これらの多様な能力を組み合わせることで、単独の個人では実現できないような革新的なソフトウェア/プロダクトを生み出すことが、ソフトウェア/プロダクト開発の核心だと思います。

そして、この核心を実現するためには、AさんBさんがお互いの強みと弱みを理解し、それぞれの役割を認識している、ということが前提になります。
例えば、以下のような情報をお互いが持っていない状態では、これは実現できません。

  • 相手が何が得意で何が苦手なのか
  • 会話する際にどこまでを前提認識として省略できて、どこから話す必要があるか
  • 自分がどう動くのがチームとして最適なのか

チームが機能するには時間がかかる

相互理解が進み、チームが機能し、ソフトウェア/プロダクト開発の核心である相互作用が生まれるまでには時間がかかります。
このことを少し詳しく見てみましょう。

チーム段階の変遷を表したものとして、タックマンモデルとダイナミックリチーミングがあります。

タックマンモデル

タックマンモデルは、以下のようにチームの状態は線形的に段階を踏んで変化していくという考え方です。

  • タックマンモデル
    • Forming(形成期): 🌱
    • → Storming(混乱期): 🪴
    • → Norming(統一期): 🌲
    • → Performing(機能期): 🌸
    • → Adjourning(散会期): 🍂

ダイナミックリチーミング

一方、ダイナミックリチーミングでは、タックマンモデルとは異なり線形ではなく、各状態を行ったり来たりしながら変化するモデルが採用されています。

  • ダイナミックリチーミング
    • ←→ Birth(誕生): 🌱
    • ←→ Adolescence(思春期): 🪴
    • ←→ Maturity(成熟): 🌲
    • ←→ Creative Destruction(創造的破壊): 🍂

しかしながら、チームが機能し始めるには時間がかかるという点では、タックマンモデルと共通しています。
ダイナミックリチーミングの「Birth(誕生)」から「Adolescence(思春期)」の間には、「Poverty Trap(貧困の罠)」と呼ばれる壁があると言われています。

詳細については、他に良い記事がたくさんありますので、そちらをご参照ください。
本記事の文脈で重要なのは、相互理解が進み、チームが機能する状態になるのには時間がかかるという点です。

https://www.google.com/search?q=タックマンモデル

https://www.google.com/search?q=ダイナミックリチーミング

認知負荷の問題

人をリソースとして抽象化すると、チームが機能するまでには時間がかかるという傾向をより強めてしまいます。
このことを認知負荷の点から考えてみます。

コミュニケーションの認知負荷

仮に人をリソースとして捉え、その集合であるn人のリソースプールがあるとします。
そして、そのリソースプールの中からランダムにm人を選んでチームを組むとします。
その際、チームの組み合わせは以下のように膨大になります。

  • 10人の中からランダムで3人を選ぶ場合

    {}_{10} \mathrm{C}_{3} = 120通り
  • 10人の中からランダムで5人を選ぶ場合

    {}_{10} \mathrm{C}_{5} = 252通り
  • 20人の中からランダムで5人を選ぶ場合

    {}_{20} \mathrm{C}_{5} = 15,504通り

10人のメンバーから3人のチームを組む場合であっても、考えられる組み合わせは120通りにもなります。
このことから、例えリソースプールという集合が不変であったとしても、毎回異なるメンバーでチームを組むと実質別のチームであると言えそうです。

チームのメンバー構成が頻繁に変わる場合、メンバー間のコミュニケーションコストが大幅に増加し、結果的にプロジェクトの遅延や品質の低下につながる可能性があります。

この状態のチームは、常にForming(タックマンモデル)やBirth(ダイナミックリチーミング)の状態に留まり続けることになります。

その他の認知負荷

コミュニケーションだけでなく、個人のスキルや知識も、エンジニアの作業効率に大きく影響します。

例えば、あるタスクをAさんは1日で完了できるのに対し、Bさんでは1週間かかるといったケースはよく見られます。
これは、ドメイン知識、技術スキル、コードベースの理解度など、様々な要因が複雑に絡み合っているためです。

エンジニアは、新しいコードを書くよりも既存のコードを理解することに多くの時間を費やしています。
『プログラマー脳』という書籍によると、プログラマーは平均して勤務時間の60%をコードの理解に費やしているというデータもあります。

https://www.shuwasystem.co.jp/book/9784798068534.html

もちろん、この割合は置かれている状況や個人によって異なりますが、既存機能を理解して変更を加えることは、新しい機能を開発するよりもはるかに複雑で時間がかかる作業である、という点は多くの方が同意されるのではないかと思います。

つまり、個人が既に理解している領域と、全く新しい領域では、作業効率に大きな差が生じるということです。
Bさんがまだ理解していない領域に対して、Aさんと同じペースで作業を要求することは、Bさんの認知負荷を大幅に増やし、結果的に作業効率を低下させます。

しかしながら、個々人のスキルや経験値を無視し、全員を同じ能力を持つリソースとみなしてしまうと、このような状況を考慮することができません。
その結果、タスクの完了までの時間を正確に予測できず、プロジェクトの計画段階から遅延や品質の低下を引き起こす可能性があります。

複雑なものを複雑なまま扱う

これまで見てきたように、人をリソースとして扱ってしまうと、認知負荷を増大させ、意図せずとも効率を悪化させてしまいます。
では、どうすればよいのでしょうか。

その答えを探る前に、まずはシステム思考という考え方について説明します。

システム思考

複雑なものを複雑なまま扱う思考方法として、システム思考があります。

システム思考とは、問題を全体として捉え、要素間の相互作用や因果関係を分析することで、より良い解決策を見つけるための考え方です。
例えば、地球温暖化などの様々な要素が複雑に絡み合った結果、誰も望んでいないにもかかわらず生じてしまう問題を理解するのによく使われます。

https://ja.wikipedia.org/wiki/システム思考

症状ではなく原因に対処する

人をリソースとして扱ったまま以下のような改善活動を行っても、うまくいかない可能性が高いです。

  • 他の人をフォローする文化を作ろう
  • オープンコミュニケーションの文化を作ろう

それは、これらは原因ではなく症状に対しての対策だからです。
このことをループ図を使って表してみます。

ループ図は、システム思考で使用されるツールの1つで、システム内の要素間の関係性を視覚的に表すことで問題の本質を明らかにするのに役立ちます。

ループ図のツールとして、こちらを使用しています。

https://ncase.me/loopy/

症状に対処した場合

効率が悪化しているという症状に対して、改善を試みた場合のループ図はこのようになります。
図中の矢印は、要素間の因果関係を示しており、+は正の相関、-は負の相関を表しています。

ループ図

  • 人をリソースとして扱う文化は未熟なチームを生み出す
  • 未熟なチームでは認知負荷が高くなる
  • 認知負荷の高さは、効率を低下させる
  • 効率が低下すると、改善活動を行いたくなる
  • 改善活動を行うことで、いくらか改善する効果はあるが、以下2つの問題がある
    • 未熟なチームが生み出す認知負荷の高さは軽減されないので、限定的な効果に留まる
    • トップダウンで改善を進めた場合、改善活動自体がさらに人=リソースの文化を強め、さらに認知負荷を悪化させる

原因に対処した場合

一方、そもそもの原因である人をリソースとして扱う文化に対して改善を試みた場合のループ図はこのようになります。

ループ図

  • 人をリソースとして扱うことをやめることで、チームが機能しやすくなる
  • チームが機能しやすくなることで、認知負荷が下がる
  • 認知負荷が下がることで、効率がよくなる
  • 効率がよい状態が継続すると、さらに認知負荷が下がるという循環が生まれる

リソースとして扱わない場合に出てくる問題

ここまでの内容を見て、以下のように考える方もいるでしょう。

人をリソースとして捉えない方が良いことは、分かっている。
しかしながら、人が多種多様であるということを考慮しながら管理することは、現実的に難しい。

これはたしかにその通りです。
だからこそ、リソースとしてつい抽象化してしまいたくなるのだと思います。

解決策になりうるもの

では、どうすればこの問題を解決できるのでしょうか。

銀の弾丸ではないものの、2枚のピザルールとTeam Topologyが一定の解決策になりうるのではないかと考えています。

2枚のピザルール

2枚のピザルールとは、Amazonが提唱したチーム編成の考え方で、1つのチームを2枚のピザを十分に食べられる人数に抑えることで、チームの意思決定を迅速化し、自律的なチームを醸成することを目指すというものです。

https://aws.amazon.com/jp/executive-insights/content/amazon-two-pizza-team/

自律的なチームを作り、そもそも外部からの管理の必要性を最低限に抑えることで、管理が複雑という問題を避けることができる可能性があります。

さらなる問題

とはいえ、以下のように考える方もおられるかもしれません。

少人数の固定チームを作った方が良い、という理想論はわかる。
しかしながら、以下のような現実的な問題があるため、なかなかそう簡単にはいかない。

  • 多様なスキルが必要
    • ソフトウェア/プロダクト開発には、ドメイン知識、プログラミング言語やフレームワークに関するスキル、クラウドスキル、SREスキルなど、多岐にわたるスキルが求められる
    • これらのスキルを全て満たすメンバーでチームを組むのは容易ではない
  • 全体最適の阻害
    • 複数の固定チームを組む場合、それぞれのチームが事業の要請とは異なる方向に進み、全体最適を阻害してしまう可能性がある
    • 例えば、チームAの機能強化が求められている状況で、チームBが別の機能開発に注力してしまうといったことが起こりうる

これらの問題については、チームトポロジーが一定の解決策になりうるかもしれません。

チームトポロジー

チームトポロジーとは、ソフトウェア開発組織におけるチームの構造や役割を体系的に捉えるためのフレームワークです。

https://pub.jmam.co.jp/book/b593881.html

このフレームワークでは、チームを以下の4つのタイプに分類しています。

  • ストリームアラインドチーム
    • チームトポロジーの根幹となるチーム
    • 特定のビジネス領域に特化し、ユーザーに対してのデリバリー責任を持つ
    • 他の3チームは、ストリームアラインドチームをサポートするために存在している
  • プラットフォームチーム
    • ストリームアラインドチームが効率的に開発できるように、共通のプラットフォームやツールを提供するチーム
  • イネイブリングチーム
    • ストリームアラインドチームの能力ギャップを埋めるために、組織全体の能力向上を支援するチーム
  • コンプリケイテッド・サブシステムチーム
    • 特に複雑なシステムやドメインに特化したチーム

また、それらのチームの連携の仕方を3つのインタラクションモードとして定義しています。

  • コラボレーションモード
    • チームが共同で作業を進めるモード
  • X-as-a-Serviceモード
    • あるチームが他のチームにサービスを提供するモード
  • ファシリテーションモード
    • あるチームが他のチームの活動を支援するモード
多様なスキルが必要という問題の解決

チームトポロジーでは、プラットフォームチームが共通のプラットフォームを提供し、イネイブリングチームがスキルギャップを埋めることで、各ストリームアラインドチームが特定のスキルに特化できるようになります。
これにより、少なくともチーム結成時点では全てのスキルが揃ったチームである必要はなくなり、多様なスキルが必要という問題を軽減します。

全体最適の阻害という問題の解決

複数の固定チームを組む場合、それぞれのチームが事業の要請とは異なる方向に進み、全体最適を阻害してしまう可能性があります。
チームトポロジーは、以下のような仕組みでこの問題に対処します。

  • ストリームアラインドチームの明確な目的設定
    • ストリームアラインドチームは、特定のビジネス目標または顧客セグメントに直接結びつけられます。
    • これにより、チームは組織全体の目標に貢献するという共通認識を持ち、事業の要請から逸脱しにくくなります。
  • プラットフォームによる相互運用性向上
    • プラットフォームが提供する共通のプラットフォームは、各ストリームアラインドチームの開発基盤を統一し、相互運用性を高めます。
    • これにより、各チームが開発した機能やサービスをスムーズに統合することが可能となり、全体最適に繋がります。
  • イネイブリングによる最適化
    • イネイブリングチームは、組織全体のスキル向上やプロセス改善を支援することで、各チームの効率性を向上させます。
    • これにより、組織全体の効率性が向上し、全体最適に貢献します。

チームトポロジーに加えて、ダイナミックリチーミングのような手法を活用することで、一定の流動性を保ちつつ全体最適に近づけることができるのではないかと考えています。

まとめ

本記事では、リソースという言葉から感じる違和感を出発点として、複雑な問題を扱う上で、人を単なるリソースとして扱うのではなく、それぞれの個性や能力を活かせるようなチーム構造を構築することが重要という考察を行いました。

2枚のピザルールやチームトポロジーといった一般的なフレームワークは、そのようなチーム構造を設計するための具体的な指針となります。
これらのアプローチを取り入れることで、チームが機能し、より革新的なものを生み出すことができるのではないかと考えています。


明日は@h-shutoさんによる デザインシステムを育てたい(切実) です。

ココナラでは積極的にエンジニアを採用しています。

採用情報はこちら。
https://coconala.co.jp/recruit/engineer/

カジュアル面談希望の方はこちら。
https://open.talentio.com/r/1/c/coconala/pages/70417

Discussion