知らんけど。

主にプログラミングについて書きます

ソフトウェア開発と認知負荷

これは ゆるWeb勉強会@札幌 Advent Calendar 2023 - Adventar の7日目の記事です!

自分はフロントエンドエンジニアをしています。

2023年は色々な場面で認知負荷と戦いました。 UI/UXデザイン、コード、マネジメント、色々なことをうまくやるには認知負荷を下げることが大事だなぁと感じたので、その辺りについて書きます。

コードと認知負荷

認知負荷の高いコードベース

アプリケーションやコードの複雑さと戦うために、我々はコードの mentenability を上げます。 コードは、modulability や testability や readability など様々な特性を良い方へと改善することで、結果的に maintainability が良くなります。

modulability や testability は、コードの持つ特性としては比較的観測しやすい特性と言えそうです。 modulability であれば「他のロジックと共通的に使用できている」など、testability であれば「信頼できるテストが書かれている」など、実際に modulable である testable であることがコードに現れます。

readability などは understandability (理解容易性)に抱合されると思いますが、これらはどうでしょう。 これによる影響が現れるのは人の頭の中・心の中であったりする上、人によって差があり、実際にどの程度の理解容易性があれば良いのか、どうすれば理解容易と言えるのかは、指標を定義しにくいものです。「これで充分」と言えるゴールがない。Linter などを利用すれば、ある程度 readability を良くできます。とはいえ、アプリケーションの本質的な複雑さや、本質的でないものの難しいために複雑になってしまっている箇所は多くあり、そういった部分の認知負荷を下げるのは困難です。また、特に他人の書いたコードは、どんなに understandability が良い状態であったとしてもそれ以外の人にとっては(特に初見では)認知負荷が高いです。

コードの認知負荷を軽減するためにしたこと

初見のコードについては特に、コードを読み始める前の段階で何らかの取っ掛かりがあれば、認知負荷を軽減することができると考えました。

自分は普段、フロントエンドのコードベースを相手にしており、TypeScriptを使っています。 TypeScript のコードベースの認知負荷を下げるため、 TypeScript Graph というファイル間の依存関係グラフを mermaid のダイアグラムで視覚化するツールを作りました。 これによって、コードベース内のプログラムの構造についての認知負荷を下げることができます。

github.com

TypeScript Graph が出力した依存関係グラフ

また、コードの認知負荷が最も影響するタスクとしてレビューがあります。 レビューでは他人の書いたコードを読まねばならず、認知負荷との戦いになります。 そこで、PullRequest で変更のあったファイルの周辺の構造のみを TypeScript Graph で視覚化してPRのコメントに投稿する、danger-plugin-typescript-graph という danger.js のプラグインと、 delta-typescript-graph-action という GitHub Action を作りました。この2つはどちらも同じ機能を実現していますが、 danger-plugin は GitHub Action が使用できない環境のために実装しています。

github.com

github.com

delta-typescript-graph-action で投稿されたコメント

自分の業務では danger-plugin-typescript-graph を使用していますが、導入したのが最近であるため効果の程はまだわかりません。 個人的には、PullRequestのレビュー時の初期認知負荷軽減に役立っていると感じています。 また、依存の方向など構造に誤りが無いかを容易にチェックできる点も良いです。

マネジメントと認知負荷

認知負荷の高いプロジェクトマネジメント

なぜウォーターフォールがうまく機能しないのか。 色々な理由があるでしょうが、その一つに認知負荷があると考えています。

新規開発や大きな変更を計画的に行うため、何ヶ月もかけて念入りに要件定義や設計を行ってから開発(実装タスク)を開始することがあります。
このようなプロジェクトでは、設計書がプログラマーの手に渡る頃には、認知負荷が高い状態になっていますね。

そして、認知負荷が高いプロジェクトでは、考慮漏れや実装漏れなどなど不具合が多発します。

大きなプロジェクトの認知負荷を軽減するためにしたこと

数ヶ月かけて行うようなプロジェクトでは、プロジェクトをユースケースに分解して、優先度の高いもの(コスパの良いもの)からリリースするようにしました。 ユースケース一つであればやることは明確で、仕様も設計も実装も、それらのマネジメントも、分解前と比べて認知負荷は低いものとなっているはずです。

アジャイル開発のように常にユースケースごとにインクリメントしながら開発したいところですが、それをするには常にエンジニアに話が来るよりも前に対処せねばなりません。 この問題を解決するには、現場全体のプロセスも改善する必要があります。 自分の環境はまだそこには至れておらず、これから改善していきたいと考えています。

タスクマネジメントの認知負荷を軽減するためにしたこと

タスクが多くあり、しかも複雑に絡み合っている場合があります。 自分もそういう状況になりました。その際、プロダクトバックログや看板ではなく、 mermaid のフローチャートダイアグラムでタスク管理をしてみました。
例えば以下のような感じです。(だいぶ細かいタスク粒度ですが)

スクフローチャート

これにより、各タスクの繋がりやクリティカルパスが視覚的に理解できるようになり、次にどのタスクに取り掛かるべきかを開発者自身が判断できるようになります。 また、単なるリストよりも状況を把握しやすく無用な不安を取り除く効果がありました。

💭 こういう見せ方を実現している良い感じのタスク管理ツールがあればぜひ教えてください!

UI/UXデザインと認知負荷

認知負荷の高いUI

エンジニアは、UI/UXデザインについて無知な状態でも、デザイナーと議論しなければならないことがあります。 UI/UXデザインについて無知であると、「わかりやすい」「わかりにくい」など感覚的な意見しか述べることができず、根拠を持って議論することができないでしょう。

自分もそのような状況に陥りました。 そこで、デザインについての知識をつけるべく「UX デザインの法則」という本を読んでみたのですが、これがとても良い書籍でした。

www.oreilly.co.jp

書籍では10の心理学的法則を紹介し、それぞれがどのようにUXに関わるかが説明されています。 また、書籍の元になっている Home | Laws of UX では他にもいくつかの心理学的法則が紹介されています。

lawsofux.com

認知に関わる心理学的法則

Home | Laws of UX で紹介されている心理学的法則うち、直接的に認知に関わる法則を列挙します。

ヤコブの法則

ユーザーは他サイトで多くの時間を費やしているので、あなたのサイトにもそれらと同じ挙動をするように期待している。

フィッツの法則

ターゲットに至るまでの時間は、ターゲットの大きさと近さで決まる。

ヒックの法則

決定にかかる時間は、とりうる選択肢の数と複雑さで決まる。

ミラーの法則

普通の人が短期記憶に保持できるのは、7(±2)個まで。

実はこの「マジカルナンバー 7」は重要ではない。重要なのは、人の短期記憶は、文字であれ単語であれ「何らかのチャンクを」7(±2)個記憶できること。つまり、コンテンツを小さなチャンクに分けることで、ユーザーの認知負荷を下げられる。とのこと。

美的ユーザビリティ効果

見た目が美しいデザインはより使いやすいと感じられる。

フォン・レストルフ効果

似たものが並んでいると、その中で他とは異なるものが記憶に残りやすい。

共域の法則

明確に定義された境界線を持つエリアを共有している要素は、グループとして認識される傾向がある。

近接性の法則

近くにあるもの、近接しているものは、同じグループとして知覚されやすい。

プレグナンツの法則

人は曖昧なイメージや複雑なイメージを、できるだけ単純な形として認識し、解釈する。

類似性の法則

人間の目は、デザインの中の似たような要素を、たとえそれらの要素が離れていても、完全な絵、形、グループとして認識する傾向がある。

連続性の法則

視覚的に繋がりのある要素は、つながりのない要素よりも関連性が高いと認識される。

シリアル・ポジション効果

ユーザーは、シリーズの最初と最後の項目を最もよく覚えている傾向がある。

UI/UXデザインの認知負荷軽減のためにしたこと

これらの心理学的法則に鑑みると、自分が関わるプロダクトにおいて自分が気になったのは以下2点でした。

  • プロダクトにおける複数の異なる概念それぞれを、UIコンポーネントの見た目で識別できない
  • プロダクトにおける同一の概念が、プロダクト内の複数の箇所で異なる見た目で提供されている

これには、プレグナンツの法則類似性の法則が関わっていると考えました。

プロダクト内の複数の異なる概念それぞれはUIコンポーネントの見た目で識別できるべき

プロダクト内のすべての概念に適用するのは難しいので、これは極論かとは思います。 しかし少なくとも重要な概念は見た目で、しかも瞬時に、認知可能であると良さそうです。

以下は、異なる概念A,B,Cを表すデザインです。

見た目で識別しにくい複数の異なる概念

それぞれ少し違います。

そしてプレグナンツの法則 は以下のようなものです。

人は曖昧なイメージや複雑なイメージを、できるだけ単純な形として認識し、解釈する。

よく見ると異なる見た目ではありますが、プレグナンツの法則によればこれらのイメージは単純な形で認識されてしまい、ユーザーは「同じ概念である」または「同じような概念である」と誤認してしまうことでしょう。

そのため、以下のように明らかに異なるものであることを強調した方が良いはずです。

見た目で識別しやすい複数の異なる概念

プロダクトにおける同一の概念はプロダクト内のどこでも同じ見た目であるべき

これも極論です🙏🏻
シチュエーションによって異なる見た目とすることが有効な場合もありますよね。

ただ、類似性の法則は以下の通りで、

人間の目は、デザインの中の似たような要素を、たとえそれらの要素が離れていても、完全な絵、形、グループとして認識する傾向がある。

これに鑑みると、プロダクト内では極力、同じ概念のものを同じ見た目で提供することで認知負荷を下げることができると言えます。


現在自分は、これら心理学的法則に則ったUIにすべきという考えを啓蒙しています。 そしてその考えは賛同を得られており、そう遠くない未来にはプロダクトの認知負荷を下げられると確信しています。

おわりに

UI/UXに関わる心理学的法則、認知に関わる心理学的法則をお読みになられたエンジニアの方は、すでに気づいているのではないでしょうか。

認知に関わる心理学的法則はコードの認知にも関わるのです。

この記事で紹介した心理学的法則のほとんどがUI/UXに限定されない「汎用的な心理学的法則」であるため、人の認知に汎用的に適用できます。 これらの法則を意識してコードベースを構築し、コードを書くことで、より認知負荷の低いコードベースとなり、メンテナビリティの良いコードベースとなるはずです。

そしてまた、マネジメントの認知負荷低減がコードベースの認知負荷低減につながる可能性があること、さらにはUIの認知負荷低減がコードベースの認知負荷低減につながる可能性があることにも気づいているのではないでしょうか。

マネジメント面で認知負荷が低ければ、複雑な事を考えずにすみ、コードをシンプルに保てるのではないだろうか。

UXを良くするためにUIの認知負荷を下げると、自然と概念ごとにUIコンポーネントが作られ、概念ごとにAPIができるのではないか。 そして、それはデザインシステムとなり、ドメイン知識となり、フロントエンドもバックエンドも認知負荷の低い、整理されたコードベースとなるはずではないか。

理想論ではあるかもですが、自分はソフトウェア開発の活動全般において、認知負荷を下げることが大事なのだと確信しています。 今後も認知負荷を下げるためにはどうすれば良いのかを学び、より良い開発者体験を実現していきたいと考えています。

「認知負荷を下げることがすべてを解決する」と悟りを開いたフロントエンドエンジニア
ChatGPTに画像生成してもらってます。誤字は気にしないであげてください。