Shin x Blog

PHPをメインにWebシステムを開発してます。Webシステム開発チームの技術サポートも行っています。

誰のためのソースコード?

「誰のためのデザイン?」の旧版と改訂・増補版を読みました。

以前に旧版を読んだのですが、その記憶もあやふやなくらい前だったので、あらためて読み直し、その面白さゆえに改訂・増補版も購入してこれも読み終えました。

Web システム開発を生業としているので、日々ユーザとのインタラクションが発生するプロダクト開発に関わっているわけで、ユーザがどのように製品を認知し、使うかという内容は参考になりました。

それとは別にソフトウェア開発という観点で、ソースコードを読む時に人がどのように認知するのかという点でも興味深いものでした。このエントリでは、自分なりに整理したソースコードと概念モデルについて残しておきます。

ソースコードとメンタルモデル

ある程度、経験のあるプログラマであれば、ソースコードを見るだけで想起されるイメージがあります。例えば、for を見れば繰り返しを思い浮かべるでしょうし、if を見れば条件分岐を思い浮かべるでしょう。これは、読み手自身にコードを理解するメンタルモデルが存在するからです。

for や if を文と見るか、式と見るかは書かれたプログラミング言語が何か、またそのメンタルモデルを持つかどうかによります。Scala のように for に繰り返し以外の動作がある言語もあります。こうしたものは、前提となる知識を理解しておかないと読む手は理解できません。

object Sample extends App {
  val s = for {
    i <- Some(1)
    j <- Some(2)
  } yield (i + j)

  println(s) // Some(3)
}

デザインパターンを利用したコードは、その概念モデルを理解している読み手に対してはコードの理解を助けます。しかし、そうではない場合、ただ冗長で理解しづらいコードのように映るかもしれません。

つまり、ソースコードを理解するには、コードの概念モデルと読み手のメンタルモデルが一致する必要があります。

ソースコードの概念モデル

ソースコードには書き手の概念モデルが反映されます。この概念モデルと読み手のメンタルモデルが一致する、もしくは読み手が理解できれば、ソースコードの内容を把握して利用できます。読み手はソースコードの概念モデルを理解することが重要です。

ソースコードが持つ概念モデルは「実行モデル」「プログラマモデル」「ユーザモデル」の3つに分けられると考えました。

実行モデル

実行モデルは、コンピュータがソースコードを解釈し、実行する(実行可能な状態にする)ためのモデルです。多くの場合、コンパイラやランタイムの概念モデルといえます。これ理解できなければ、コードがどのように動作するのかをイメージできません。このモデルは一般的なもので、プログラミング言語のマニュアルや技術書などで広く公開されています。同じ言語やプラットフォーム、フレームワークなどでは同じモデルとなるので、一度学習すれば他のソフトウェアでも流用できます。また、実際に実行したり、自動テストを実行するなどで検証が比較的容易です。

プログラマモデル

プログラマモデルは、プログラマがソースコードを理解するためのモデルです。分かりやすい変数名を付ける、関数やクラス構造に分ける、デザインパターンを適用する、レイヤ分けなどのアーキテクチャを構成するなどです。いわゆる可読性、保守性の高いコードを書くためのモデルです。これは、読み手のメンタルモデルによって、理解しやすいかは変わってきます。我々は、書籍「リーダブルコード」や「Effective XXX」のような情報で共通認識を持っているので、それを理解している人であればそれに従うことで同じモデルを利用できます。しかし、そうではないメンタルモデルを持つチームでは、また異なるモデルをコードで表現する必要があります。

ユーザモデル

ユーザモデルは、ソフトウェアを利用して実現したい機能や対象とするドメインなどを示すモデルです。要求モデルやドメインモデルといったものです。重要なモデルですが、ソースコード自体にこのモデルが反映されているかは実装次第です。ソースコードのみから読み取るのが難しい場合も多く、ドキュメントや口頭による説明など他の手段で共有します。

ユーザモデルは問題領域のモデル、実行モデルとプログラマモデルは解決領域のモデルともいえます。

誰のためのソースコード?

ソースコードを理解するには、ソースコードと読み手のメンタルモデルが必要になります。よく「可読性の高いコード」という表現をしますが、可読性を決めるのはソースコードだけではなく、読み手のメンタルモデルも大きく影響します。

これは大切な視点で、特にプロダクションコードであれば、同じチーム外の人が理解する必要はなく、一般的にはリーダブルコードで無くても、その特有の概念モデルが共有できれていれば良いという考え方もできます。もちろん、後から入る人の事も考えて、一般的な書き方にしておく方が得策です。しかし、すでにそうではないコードがある場合、コードを直す以外にチームへの概念モデル共有をしっかりやるという方法も考えられるということは一つの考え方として認識しておくと良いでしょう。

デザインパターンや 戦術的 DDD パターンが良いと聞いて、自分たちのソフトウェアに反映しようとしても中々うまくいかない、自分は理解できるがメンバーには理解されないということもパターンの概念モデルと各自が持つメンタルモデルの齟齬によって起こると言えます。

さいごに

ソースコードは、コンピュータをどう動かすかということを示すものですが、これを書くのも読むのも人です(今のところ)。つまり、人がソースコードをどう理解するのかという視点はソフトウェア開発の現場では重要なことです。自分の中で課題として考えていたことが、こうした視点で本書を読むことで、ある程度整理することができました。

他にも多くのインスピレーションを与えてくれる本なので、これからも何度となく開くことになるでしょう。願わくば、いつでも読めるように電子書籍版を発売してほしいところです。

人は勝手に独自のストーリーを描く生き物なので、本書を読んでも、このエントリを読んでも、あなたが持つメンタルモデルによって、また異なるイメージを描くでしょう。うまく私の概念モデルが伝わると良いのですが。

誰のためのデザイン? 増補・改訂版 ―認知科学者のデザイン原論

誰のためのデザイン? 増補・改訂版 ―認知科学者のデザイン原論

  • 作者:D. A. ノーマン
  • 出版社/メーカー: 新曜社
  • 発売日: 2015/04/23
  • メディア: 単行本

メモ

  • 学習された無力感、教えられた無力感
  • 行動遂行のサイクル
    • ゴール、意図の形成
    • 行為の詳細化
    • 行為の実行
    • 外界の状況の知覚
    • 外界の状況の解釈
    • 結果の評価
  • ポジティブな情動、ネガティブな情動
  • ヒューマンエラーではなくデザインエラー
  • ポジティブ心理学
  • 短期記憶、長期記憶、外部記憶
    • 短期記憶=スタック、長期記憶=ヒープ、外部記憶=ストレージに例えられる
    • [旧版] 三目並べのデシジョンツリー。浅いか or 狭いものが分かりやすい
  • デザインにおいて成功の秘訣は、何が本当の問題かを理解すること
  • 漸進的なイノベーションは毎年何百万も起こるが、急進的なイノベーションは遥かに少ない。
    • 急進的なイノベーションを求めがちだがそれには時間がかかる。漸進的なイノベーションを積み重ねるのも大切。
  • 認知と情動。本能レベル、行動レベル、内省レベル
    • 例: ブランドイメージや利用経験によるプラスの内省的な情動により、使いにくさや悪い経験といったマイナスの情動を覆す
    • スパゲッティコードを見ると、本能レベル or 行動レベルでマイナスの情動を引き起こす?
  • エラー
    • スリップとミステイク
    • スリップの型
  • 高次の記述と低次の詳細記述
  • 強制選択機能
  • スイスチーズメタファー
  • 人間中心デザイン(HCD)
    • 反復サイクルは、アジャイルやリーンスタートアップと同様(本文にも書かれている)