シンプルさの必要性

2012年4月23日にテキサスの Austin で行われた RailsConf 2012 での Rich Hickey (@richhickey) さんによる基調講演、Simplicity Matters を書き起こして翻訳しました。
Rich Hickey さんは Clojure や Datomic の作者です。
この翻訳は Creative Commons Attribution ShareAlike 3.0 ライセンスに基いて公開します。

Rich Hickey 講演
e.e d3si9n 訳

Rich Hickey

談: こんにちは。ご招待いただきありがとうございます。
聞く所によると RailsConf はいつもコミュニティーからかなり外れた人を選ぶらしく、今回は僕ということになりました。
僕の電話ボックスは外に駐車してあります。(会場、笑)
だけど、今日は言語の壁を越える話題を持ってきました。Simplicity、つまりシンプルさについてです。

シンプルさは信頼性の前提条件だ

Simplicity is prerequisite for reliability
Edsger W. Dijkstra

談: シンプルさは僕がとても重要だと思っていることです。
この文の主語として他に何か別の言葉を入れることができるか考えてみて下さい。
Simplicity よりも適切な言葉は無いと思います。

語源

Simple: one fold/braid

談: シンプルと easy という 2つの言葉について少し話したいと思います。
これらはよく混同して使われますが、それは止めましょう。
最初の言葉は「シンプル」です。意味は一折り (one fold)、一より、またはひねりです。
対義語は「complex (複雑さ)」で、この意味は多くの物を組み合わせたり、編み合わせたという意味です。

Easy: lie near

談: 区別するべきなのは「easy (簡単さ)」で、僕の好きな語源は「近くにある」というものです。昔、旅が難しかった頃は近くにあるということはそこに行ったり、使ったりするのが簡単だったということでしょう。シンプルとは異なる概念です。

シンプル

スライド:

  • 一折り、一より
    • 一つの役割
    • 一つのタスク
    • 一つの概念
    • 一次元

談: 「一折り、一より」と言っても僕たちはソフトウェアを折るわけでは無いので少し話を広げてみましょう。

例えば、あるソフトウェア、もしくはソフトウェア内のコンポーネントが一つの役割 (one role) だけをはたす、一つのタスク (one task) だけをこなす、セキュリティ、アクセス管理、認証、計算など一つの概念 (one concept) だけを受け持ったり、一次元であると考えることができます。

スライド:

  • しかし、以下の意味では無い
    • 一つのインスタンス
    • 一つの演算
  • インターリーブが無いのが大切であって数の問題ではない
  • 客観的

談: だけど、「一つ」という事に固執してしまうのは避けて下さい。
「一つのものしか無い」という意味では無いし、一つの演算だけを持ったクラスやインターフェイスという意味では無いし、シングルトンという意味でもありません。インターリーブが無いのが大切であって数の問題ではありません。

シンプルさと簡単さの主な違いは、シンプルさは客観的だということです。これに関してはこれから見てきますが、何かを観察してどのように絡まっているかを考えるということは、ソフトウェアの分野で僕たちが行うことです。これは誰もが客観的に観察できるもので主観的ではありません。

Easy

スライド:

  • 近くにある、手近にある
    • ハードドライブにある、ツールセット、IDE、apt get、gem install にある
  • 理解度、スキルセットに近い
    • 親しみやすい
  • 能力に近い
  • 相対的

談: 次に、easy についても「近くにある」をソフトウェアでの文脈に翻訳する必要があります。「馬に乗らなくてもいいからこのライブラリは easy だ」という意味ではありません。

まずは物理的な近さから考えてみましょう。「今使っているツールキットの一部か」「通常インストール済みであるか」「一緒に働いている人たちのツールキットに入っているか」「手近にあるか」というようなことです。

次に、もう一つの近さとして親しみやすさというものがあります。「これは既に自分が知っていることか」「これは既に知っていることに似ているか」「これは既に知っていることのバリエーションの一つか」。これは物事を簡単にします。「これは既に知っているアレにソックリだけど、ココだけがちょっと違う」。これは簡単です。

さらに近さを考えられる3つ目の近さがあって、それは「やっていることが自分の能力に近い」ということです。これは寄せるのが難しく、また重要なものです。(何か非常に複雑なものを理解しないままインストールすることはできます。それは「近くにある」と言えるでしょう。それは自分が既に知っているものに似ているように見えるけど、全く異なる事を行うかもしれません。それは「難しい」と感じるでしょう。) しかし、最も難しいのは複雑すぎて操作するのに脳に重い負担をかけるものです。別の言い方をすると、それは知的能力を越えてしまっているということです。

これを口にするのは恥ずかしいので、なかなか話題に上ることがありません。僕たちは知的労働の分野に従事しているため、考えることが僕たちの仕事です。だから、

「これは僕が考えるのには難しすぎる」

とはなかなか言いたくありません。だけど、どれだけの複雑さを扱えるというと、実際は皆だいたい差はありません。僕たちはこのキャパシティに限界があることについてもっと率直になるべきです。
もし達成しなければいけない何かが僕たちの能力から遠い所にあるとすると、それはどう頑張っても簡単になることはありません。どうするべきでしょう?

シンプルさと比べたときに easy であることの大きな違いは、それが相対的であることです。自分の経歴や知識によっては何かが難しいと思うかもしれません。他の人の経歴や既にある知識によっては親しみやすいと思うかもしれません。何かが「簡単である」という場合、常にこの相対的な側面がつきまといます。自分にとって難しいことでも、他の人にとっては簡単かもしれません。

限界

スライド:

  • 理解できないものの信頼性を上げることはできない
  • 一度にいつくかの事しか考えることができない
  • 絡みあったものは一緒に考えないといけない
  • 複雑さは理解度を土台から崩す

談: 3つ目の近さについてもう少し。あるものを理解しづらくする原因は何でしょうか?

まずは基本的な限界から始めましょう。暗記できる数字は 7±2桁だという話は聞いたことがあるでしょう。これは数に限度があるという意味ではジャグリングの限界に似ています。(前にこれに似た話をして限界は12個だと言ったらシルク・ドゥ・ソレイユで21個のボールをジャグリングしているのを見たことがあると誰かに言われたことがあります。その人がコードを書くなら是非雇うべきですね。) 僕らは一度にいくつかの事しか考えることができません。

シンプルでは無いものが主な問題となります。複雑さを「複数のものが結び合わさったもの」として考えたとき、何か複雑なものをについて考えなければいけないとします。例えば、機能を追加したり、他のものと組み合わせたり、ある問題を修正するなどの理由があるでしょう。それを引っ張り出したときに他のものと結び合わさったものが出てきたら、機能を追加したり、問題を修正するためには、それらの全てを頭に読み込む必要があります。それらの全てを一緒に考える必要があるからです。

そのため、複雑さ、または「複数のものを結び合わせる」ということは、僕たちの理解能力を土台から崩すものです。もし理解することができなければ、どうやって効果的に変更を加えたり修正したりすることができるでしょうか?

変更

スライド:

  • もっとやれ、違うふうにやれ、より良くやれ
  • ソフトウェアの変更は解析や決定を必要とする
  • プログラムを論理的に考える能力は不可欠となる
    • テスト、型、ツール、開発プロセスよりも

談: 変更 (change) というのは重要な言葉です。

プロジェクトの開始当初はスタートアップであったりグリーンフィールドであったりして、晴れていて、スタンドアップ・ミーティングの初日で、開発手法や、マニフェストや、使ってみたかったベスト・プラクティスや、良いアイディアがあって、クライアントもやる気満々で、全てがうまくいきます。
そして一週間が過ぎ、二週間、三週間、四週間と時間が経ちます。何が変わったでしょう?
スタンドアップ・ミーティングに新たな参加者が来ました。それは部屋の隅でどんどん大きくなっていく象です。象の名前は「既に書いたソフトウェア」です。この「既に書いたソフトウェア」という名前の象が僕たちの今後を完全に支配します。

僕たちは「もっとやれ」と誰かに言われるわけですよね。まず最初に「何かやれ」と言われてやった第一イテレーションは楽勝でした。
しかし、前に進むためには既にあるもの、つまり象、を捕まえてそれにもっと何かをやらせたり、違うふうにやったり、より良くやらせたりする必要があります。このソフトウェアを操って、新しい事をさせるには、まずそれを理解しなければいけないという問題があります。

僕の主張は、ソフトウェアが一定の規模以上なら、この段階で僕たちは完全に複雑さに支配されてしまうということです。どんな開発プロセスを使っているとか、どんな良いテストをしているとかは関係ありません。複雑さという象が今後何ができるかを支配します。
より多くの事をできるようするには複雑さを抑える必要があります。

他のテクニックや開発プロセスは素晴らしいし、重要だと思いますが、複雑さは圧倒的なのです。たとえベスト・プラクティスを実践している人たちでも、週毎、イテレーション毎の生産性が突然コンクリートの壁にぶち当たってしまう体験があるでしょう。その人たちの変更を妨げる理由は正にこの象なのです。

シンプルさ = 機会

スライド:

  • 設計上の機敏さは勝つ
    • その他の場合は象を押しながら
  • デザインとは分解
  • 再利用、置換、移動、組み合わせ、拡張

談: しかし、シンプルさを複雑さの象を予防するだけの防御機構だけだと思ってほしくはありません。

僕はシンプルさはデザインにおける機会をもたらすものだと思っています。
設計上の機敏さ (architectural agility)、つまり根本的にシンプルなシステムを構築することによって得られる機敏さ、は他の全ての機敏さを圧倒するというのが僕の主張です。(どんな開発プロセスを使っているかは関係ありません。もし複雑さの象がいた場合は、開発プロセスは象を押すのに使われることになります。象押しの上達には限界があるでしょう。)
もしシンプルなシステムを構築したならば、他の事をやらせることもできるでしょう。

アーキテクチャという言葉ですが、

「それをやってたのは 90年代だから」

という人もいますが、やらなければあなたは莫大な時間を無駄にしています。この理由は「デザイン」という言葉に汚名を着せてしまったからだと思います。ここで言っているのは「ものの見た目」の話ではなくて「ものの振る舞い」の話です。デザイン、設計と言うと「全てがどうなるかを決める壮大な計画」を思い浮かべがちですが、良いデザインはそういうものではありません。良いデザインは何かを分解することです。良いデザイナーが行うほとんどの作業は

「これはゴチャゴチャしすぎている」

と言いながら2つのものに分離することです。良いデザイナーはそれを直観的に行います。デザインとは分解することです。
それを行うと、変更のための真の機会をもたらします。

全てを分解して、シンプルなコンポーネントだけがあるとすると、別の文脈において利用しようと思ったら、他のものも引っ張って来なくてもいいためそれは簡単なことです。何かをやっているコンポーネントを取り出して、別のやり方でやりたいと思っても、それも簡単です。シンプルさが簡単さと機敏さをもたらしてくれています。

シンプルなシステムを作れば、部品を置き換えるのは率直な作業です。システムの一部を取り出して別のサーバで走らせるのも簡単です。別のサーバ群でも、別のホスティングサービスでも、もしくは全く別の位置的特性を持つソフトウェアを作ることも、象を引っ張って来なくてもいいため率直な作業です。
別の部品を組み合わせて、別の問題を解決することも同様です。既にパーツは作ってあって、新しい問題が出てきたときに「既にあるパーツを2つと新しい部品を一つが問題を解決する」というような考え方がシンプルさに基づいたデザインを採用しているとできるようになります。
そのため、シンプルさを追求することは機会を追求することだと僕は考えます。

LISP プログラマは全ての価値を知るが、何のコストも知らない

LISP programmers know the value of everything and the cost of nothing.
Alan Perlis

談: これは古い皮肉ですが、これから現代風に書きかえるので、説明したくありません。LISP とは関係ありません。

プログラマは全ての利点を知るが、何のトレードオフも知らない

Programmers know the benefits of everything and the tradeoff of nothing.

談: 実はこういうことです。
僕たちは、自分自身と自分のための開発の手軽さに執着していて「僕はここに座ったままこのボタンだけを押せば、全てが勝手に行われて、全てがインターネットから落ちてきて、僕は 3D バイザーをして快適な椅子に座っているんだ」という感じです。
そして採用したいテクノロジーやツールやライブラリを考えるときも、

「利点だ。これを使えば 10秒早くなる」

「誰かが良い特性のことを言っていた」

というようなことに焦点を置いて、一緒に何が付いてくるのかまでには考えが及ばないことが多いと思います。

僕たちは自意識過剰だと思います。自分の事に夢中でカルチャーのためのカルチャー、つまりメタカルチャーまであります。しかし、本当に僕たちが考えるべきは、実際に作るソフトウェアのことではないでしょうか。

Foo Fighters

Foo Fighters

談: Foo Fighters を例に取ってみましょう。
Foo Fighters の悩みの多くが音楽がどれだけ難しいかだとします。

「ドラム習いなくないし」

「ギターは弦で指が痛くなるし。ギターはもう弾きたくないから、何か、既に自分が知っているものから遠くない easy なものがほしい」

Kazoo Fighters

Kazoo Fighters

談: だから Foo Fighers の代わりに Kazoo Fighters になりました。(会場、笑)
これには2つの問題があります。第一に、誰がこれを聴こうと思うでしょう。これはママゴトで、良い結果を生みません。
第二の問題は、自分に問いかけて欲しい質問ですが、「このバンドに入りたいと思う人がいるでしょうか? 常に最も easy な方法ばかりとるバンドに入りたいと思う人がいるでしょうか? あなたはこのバンドに入りたいですか?」僕は嫌です。

プログラマ vs プログラム

スライド:

  • 僕たちは自分たちの事に焦点を置いている
    • プログラマの便宜性
    • プログラマの置換性
  • プログラムに焦点を置くべき
    • ソフトウェアの品質、正しさ
    • メンテナンス性、変更
  • gem install hairball

談: つまり、プログラマとプログラムの間には衝突があります。その必要は無いと思いますが、現実問題として利害の衝突があります。
現在、僕たちは自分自身の事と便宜性に焦点を置いています。

これは、自分自身に甚大な損害を出す行為です。僕たちの雇用者は、僕たちが均一性と親しみやすさが大好きなことを逆手にとることができます。何故なら、僕たちが皆で同じ部屋に集まって、同じ事をやって、同じ文化で、類似性の一体感にひたっているということは、それだけ僕たちを置き換えるのが簡単だということだからです。

彼らは大量のプログラミング言語や様々なテクニックやツールや考え方は欲しくありません。彼らが欲しいのは一つの言語やテクニックだけです。一つだけならばあなたを置き換えることができるからです。願い事も思わぬ結果になるかもしれないから、気をつけた方がいいという言い回しがありますね。

僕たちが焦点を置くべきは僕たちが作るプログラムです。もし焦点を置かないなら何故作っているのでしょう。(プールサイドでマルガリータを飲むなど他のことやっていても幸せになれます。それは仕事じゃないし、生産的な社会の一員とは言えないでしょう。) 僕たちは何かを作るのが仕事です。何が作られているのかにもっとこだわりを持つべきだと思います。

焦点を置くべきはプログラムの品質、正しさ、僕たちがメンテナンスしたり変更を追加できる能力です。
何をしたいかを選ぶとき

「これは、今現在の自分自身のためになるから僕はこれが好きだ」

という考えで選んでないか気を付けるべきです。

簡単なものならいっぱいあります。gem install hairball。複雑さはすぐ手近にあります。インターネットから何かを下ろしてきて自分は一時的に満足かもしれないけど、後々プログラムには何が起こるでしょう。

コンプレクト

スライド:

  • 絡み合わせる、編む
  • やってはダメ
    • コンプレクトさせることが複雑さの元
  • 最初から避けるのが一番

談: 毛玉(hairball) というのはいい喩えだと思います。毛玉とは何でしょう。これは絡まりあった毛の固まりです。
これは、「絡み合わせる、編む」といった意味のコンプレクト (complect) という素晴らしい言葉が表す基本的な概念に関係しています。
僕はこの言葉が大好きです。悪い設計上の決断によって他の人がソフトウェアを台無しにしそうになったら

「君は物事をコンプレクトしている」

と言いましょう。「編んでる」というのはうまくいきませんが、「コンプレクトする」は使えると思います。何よりも言葉の響きが悪いのがいい。

「僕のものがコンプレクトされたよ。休暇に行って帰ってきたら、別のものと一緒に完全にコンプレクトされてた」(会場、笑)

だから、これはやっちゃダメです。複雑さはここから来ます。語源もそうだし、結果もこの行為から来ます。
2つ以上のものを結んでしまうと、それがどんなに簡単に思えても、複雑さが発生します。これをやればやるほど信頼性が高く、更新することが可能なソフトウェアを作るのは難しくなります。

それを防ぐには、それを感知する感性が必要になります。

簡単にするには

スライド:

  • インストールして手近にする
    • 使う許可をもらう
  • 習ったり、使ってみて親しむ
  • 知的能力は?
    • あまり大きな変化は期待できない
  • シンプル化 (simplify) することで問題を簡単にする

談: では、どうやって物事を簡単にすることができるでしょう。
僕は簡単は悪だとは言っていません。簡単さのうち 2つは率直なものだと思います。

何かが手近に欲しければ、それを選択すればいいだけの話です。何か斬新なものを使いたければ、自分が今まで使ったことが無いという事や、自分のツールセットに入っていなかったり、周りに使っている人がいなかったり、会社がまだ承認していなかったりするという壁を乗り越えなければいけないかもしれませんが、それはインストールすればいいだけの話なので十分できることです。

もう一つできることは、自分から親しみやすくしてしまうことです。新しいことを習ったり、本を読むことができます。何でも親しみやすいものばかり選んでいては何も新しいことを習うことはできません。その悪循環から抜け出す必要があります。これらは自分で制御できる範囲のものです。

しかし、最後の部分はどうでしょうか? もし直面している問題がとても難解なものだとしたらどうでしょう。あなたはもっと賢くなることができるでしょうか。「猫でももっと賢くなる方法」「24日でもっと賢くなる方法」を読めばいいのでしょうか? 24時間? 二週間? 残念ながら、僕たちがもっと賢くなるには限界があります。僕たちの賢さはお互いあんまり変わりません。皆同じぐらいに賢いと思います。

だから、ユーザのためにより洗練された事をする必要があったり、より面白いソフトウェアを書く必要があったり、より難しい問題を解く必要があったりして何かもっと複雑な問題に取り組む必要があるとき、その問題を僕たちの方に近づける必要があります。問題には固有の複雑さがあるかもしれませんが、その実装が限りなくシンプルであることを確実にすることで、問題側を僕たちに近づけることができます。これがキーポイントです。

僕は物事が簡単であって欲しいと思っていますが、3つの意味全てにおいて簡単であるべきだと思います。最初の2つだけを考えていると、横から3つ目がやってきて複雑なものができあがってしまいます。

全く同一のプログラムを著しくシンプルなコンポーネントを用いて作ることができる

談: 今回の基本的なポイントはここです。僕たちは、今書いているプログラムと全く同一のものを、劇的にシンプルなものを使って作ることができます。
劇的にシンプルな言語、ツール、テクニック、方法論などです。もっと過激にシンプルなものです。例えば、Ruby と比べてより過激にシンプルなものを使うことができます。何故そうしないのでしょうか?

あなたのツールキットには何が入ってますか?

スライド:

複雑 シンプル
状態、オブジェクト
メソッド 関数、名前空間
変数 自動参照
継承、switch、パターンマッチ アドホック多相性
構文 データ
命令型のループ、fold 集合関数
アクター キュー
ORM 宣言的なデータの操作
条件文 ルール
非一貫性 一貫性

談: ちょっと具体例で考えてみましょう。僕たちには色々な選択肢があります。

例えば、オブジェクトに基づいたステートフルなプログラムを書くことができますが、代わりにほとんど場合において値の操作を行い、必要に応じて状態を持つプログラムを書くこともできます。そうするべきです。

僕たちはステートフルなメソッドを使うこともできますが、代わりにただの関数を使うことできます。ただの関数は、メソッドに比べて非常に「シンプル」なものです。そのため、テストしやすいし、理解しやすいし、メンテナンスもしやすいし、他のものと組み合わせるのも容易です。

変数はとても複雑なもので、できる限り回避すべきものです。使っている言語によってはこの選択は無いかもしれません。

継承、込み入った switch 文、パターンマッチングを書くたびに、あなたはシステムに複雑さを加えています。代わりに多相性の構文を使うべきです。

次は特に面白いものです。構文 (syntax) は内在的に複雑なものです。なぜなら「構文」という言葉は「順序や位置に意味を関連付ける」という意味だからです。構文を持つというのはそういうことです。だから DSL のようなものを書くときは複雑さを加えているということを意識するべきです。結果として DSL を書くことを選ぶかもしれませんが、複雑さの影響を分かった上で行うべきです。

ループは複雑さの一形態です。なぜなら、それは変数を作業とコンプレクトしているからです。Ruby には each という高レベルな構文があるため、ループを書かなくてもいいのが便利です。

アクターの話はしないでおきましょう。

ORM は、この世で最も複雑なものの一つです。皆が使っているからという理由で無批判に繰り返し使うことを選んでいますが、これはとても複雑なものです。すごく多大な時間を無駄にしていないか、考える必要があります。

条件文はルールによって置き換えることができます。

クールで新しい結果整合性 (eventual consistency) を持ったデータベースも見てみましょう。結果整合性はとても複雑で、難解なものです。本当に必要でなければ選択するべきではありません。

シンプルさ ― 作業量を極力まで減らす技術 ― は不可欠だ

Manifesto

談: これは絶句してしまいます。完全に間違いです!

どこが間違っているか、お分かりだと思います。この定義のシンプルさは「あなた」が主役ですが、これまでみてきた通り、シンプルさはあなたとは関係ありません。シンプルさはあなたが作った成果物がどれだけ絡まっているかの度合いの話であって、あなたは関係ありません。

作業量を減らすという観点から見れば、gem install hairball は、hairball が行うものを書かなくても良くなったので一時的な作業量を減らします。しかし、gem を書くのが得意な人でも「gem このプロジェクトから全ての hairball のインスタンスを除去して欲しい。何を考えていたんだ、僕たちは」というのは無理でしょう。(世の中にはたくさん gem があるので、もしかしたらそういうのもあるかもしれませんが。)

というわけで、これは間違っているし、ひどいアドバイスです。シンプルさの主役はあなたではありません。また、シンプルさは生易しい作業ではありません。しかし、そこから得られる利益は大きなものです!

本当にシンプルなシステムを持つ人、つまり本当にシンプルな部品から構成されたシステムを持つ人は、最大限の変更を最小限の作業で成し遂げることができるでしょう。その人はあなたを打ち負かすでしょう。その人は絶対に gem install hairball をすることはしないし、その人はより多くの時間を事前にシンプル化することに費やすでしょう。その人は、あなたが象を押している間に変更を加える能力があるので、あなたの取り分をかっさらっていくでしょう。

シンプルさは芸の目的ではないが、無我の境地に立って、物事を真の姿でとらえることでシンプルさに到達することができる。

Simplicity is not an objective in art, but one achieves simplicity despite one's self by entering into the real sense of things.
Constaintin Brancusi

談: これはシンプルさについてのずっと良い考えです。シンプルさそのものは目的ではないかもしれません。それは物事を分解して本質に迫っていく過程で生まれるものです。では、本質とは何でしょうか? シンプルさの考察をどのように行えばいいのかを 2つの具体例を使って説明して、締めくくりたいと思います。

リストと順序

スライド:

  • 何かの列
  • 順序に意味があるか?
    • [first-thing second-thing third-thing ...]
    • [depth width height]
  • set[x y z]
    • 順序に意味がないことは明らか

談: 最初に見ていきたいのはリストと順序の問題です。問題なんかあったでしょうか?

リストは皆、「何かの列」として知っていると思います。しかし、何かの列を見たときにすぐに質問が浮かぶと思います。「このリストの順序は重要か?」という質問です。意味的に同じようなものが並んでいるのか、3つの異なるもののタプルなのかということです。最初のリストは均一なものですが、2つ目のリストは深さ、幅、高さを表していて、意味的な構造を持っています。これをプログラムの別の所で使おうとすると「最初の数は何だっけ? 深さ、幅、高さ? 幅、深さ、高さ?」という問題が発生します。もし順序に意味があれば、複雑さがシステムに導入されたことになります。

もし使っている言語に集合のようなものがあれば、順序に意味が無く、重複も無いことを明示することができるので、それを使いましょう。

順序を気にする理由は?

スライド:

  • 各要素が次のものとコンプレクトされる
  • 使われている全てのポイントに感染する
  • 変更を妨げる
    • [name email] -> [name phone email]
  • 「こんなコードは書かない」

談: 順序に気を使う理由は何でしょう?

それは複雑さの原因となるからです。それぞれの要素が次の要素とコンプレクトするからです。

この欠点はどこに現れるでしょう?

それを使っている全てのポイントに現れ、感染します。変更を加えようとすると分かります。例えば、プログラムのどこかで名前とメールアドレスのリストを渡すことにしたとしましょう。その動作を利用したものを大量に書いたとします。次に、機能を追加する必要があって電話番号を真ん中に入れたいとします。
次に何が起こるかは想像するまでもないでしょう。どんなに高性能な IDE を使ってリファクタリングしても関係ありません。これは本質的に複雑で、バグと問題の元となります。

もちろん、今日ここにいる皆は

「こんなコードは書かない」

「僕たちには連想コンテナがあるし、こんなことは絶対にやらない」

と思っているでしょう。しかし、このようなタプルを作るのを言語の機能として提供している言語もあって直積型 (product type) と呼ばれています。(僕にはこれが機能だとは思えません。)
しかし、こんなコードは書かないとしても、順序という本質的な問題は実際にあることで、いたる所に見つけることができます。

野生の順序

スライド:

複雑 シンプル
位置的な引数 名前付きの引数かマップ
構文 データ
直積型 連想レコード
命令型プログラム 宣言型プログラム
Prolog Datalog
呼び出し連鎖 キュー
XML JSON、Clojure リテラル

談: 具体例から順序という概念を持ち上げて、他に現れていないか探してみましょう。

例えば、関数への位置的な引数はこの問題の一例です。もし真ん中に引数を加えようと思えば同じ問題が発生します。これを防ぐ方法としては、名前付きの引数やマップを使うことができます。僕は必ずしも全ての言語が名前付きのパラメータ呼び出しをする必要があると言っているわけではありません。Clojure は位置的な引数を使います。しかし、これを使う時に複雑さを受け入れていることを意識する必要があります。(これは簡潔さとのトレードオフです。)

構文が本質的に複雑なものであるということは既に言いました。普通のデータを渡すことで意思が通じるなら、専用の構文を導入するよりもうまくいくでしょう。

直積型の代わりにマップやハッシュテーブルを使うことができます。

シンプルさという面ではどんな命令型のプログラムも宣言型のプログラムには負けるでしょう。それは順序のせいです。「これをアレに代入して、それにこれを代入して、そこに別の物を持ってきて何かを行う」というような命令型のプログラムを考えます。この文の順序を変えると、壊れてしまいます。SQL で書かれたプログラムの順序を変えても壊れません。(遅くなるかもしれませんが、それはまた別の問題です。)

Datalog と比べて Prolog にもこの問題があります。

もう一つよくある興味深い問題としては、関数の呼び出し連鎖があります。「a が b を呼び出して、それが c を呼び出して、それが d を呼び出す」という具合です。これは順序付けされたリストで、順序に意味があります。
これは「a は受け取ったデータを処理してキューに入れる。b はキューからデータを読み取る」というプログラムに比べると変更しづらいものです。キューに基づいたプログラムを変更する方が簡単です。なぜなら、a に変更を加えること無く別のものがキューを読むように変えればいいだけだからです。a に影響はありません。だからと言って、全てのものの間にキューを挟む必要はありませんが、複雑さを軽減する設計上の道具としてキューはとても重要なものです。

XML も良い例です。XML はテキストファイルをサポートするように設計されているため、順序に意味があります。テキストでは文の順序を変えては意味が通じないため、順序に意味があります。しかし、僕たちはこれをデータのために使うべきでしょうか?

XML のために書かれたパーサはデータ処理に向いているでしょうか? いや、全く向いていません。皆は JSON の方が、見た目が悪いカギカッコが無いからシンプルだとか思っているかもしれませんが、そんなことはありません。JSON や Clojure リテラルのようなものが XML の代わりに直観的に選ばれる理由は、マップを持っていれば、それがマップであるということがすぐに分かるからだと思います。プログラムに読み込んだときに、順序に意味があるのか、複数の要素が出てくるのかというような疑問はありません。「これはマップ」、「これはリスト」という具合にすぐ分かります。それは順序の無いデータ記述プロトコルです。そのためパーサもシンプルになります。

他にも色々あるので、自分のプログラムの中に順序問題がないか探してみて下さい。

マップ (ハッシュテーブル) だよ!

スライド:

  • 第一級連想データ構造
  • 構文的なサポート
    • リテラル、アクセス、シンボルを使ったキー
  • ジェネリックな操作
  • 使おう

談: どうやって解決すればいいでしょう? マップを使えばいいだけのことです。ハッシュテーブルとも呼ばれていますね。これは常に使うべきです。使うことを選べばいいだけです。第一級連想データ構造は最高です。

連想コンテナに対する構文的なサポートを持つ言語を使うべきです。皆さんは既に持っているので、ここで言っても仕方がありませんが。構文的なサポートを持たない言語を使っている人たちは本当に苦しむことになります。
これを利用してジェネリックに操作を書くことができます。できる限り、連想コンテナを選んで使いましょう。

情報はシンプルなものだ

スライド:

  • 台無しにしない
  • マイクロ言語の後ろに隠さない
    • 情報に特定のメソッドを持つクラス
    • ジェネリックなデータ合成の妨げ
    • ロジックがその時流行のデータ表現と結びつく
  • データはデータとして表す

談: では、2つ目の問題を見ていきましょう。情報問題です。実際は、情報非問題です。情報そのものはシンプルなものですが、僕たちがそれを台無しにしてしまうため、問題が発生します。

僕たちはデータを何も達成しない馬鹿なクラスでラッピングします。九割の場合は、ハッシュテーブルを使って汎用データを取り扱うクラスを作ったほうがうまくいきます。システムはシンプルになるし、データ処理は汎用的になるし、あなたが書いたクラスを知らなくてもいいユーティリティを書くこともできるし、連想情報をありのままの形で取り扱うことができます。「名前と住所がある」というように情報はシンプルなものです。そこに他の物を乗せるべきではありません。

乗せてしまうと、色々問題が発生します。データ表現とロジックが結びつきます。ジェネリックにデータを処理する能力を失います。データ表現とその時流行りのクラス名とつながってしまいます。「このハッシュテーブルを処理できるからやってみるか」という方が良い方法です。

カプセル化

スライド:

  • 実装の詳細のためのもの
  • 情報は実装を持たない
    • 誰かが付け足すまでは。なぜ?
  • 情報は表現を持つ
    • 何かを選ぶ必要がある

談: よく聞く理由というか言い訳はカプセル化です。

カプセル化は実装の詳細のためのものであって、情報には実装の詳細はありません。少なくとも、あなたが動詞を付け足して汚くするまでは本来の情報には実装の詳細は無いので、隠蔽するべきものは何もありません。マップを直接返そうが、アクセス用の関数を作ったとしても情報の表現を外に公開することからは逃れることはできません。「カプセル化」してもそれは変わらないし、それは実際にはカプセル化ではありません。

情報のラッピング

スライド:

  • 情報クラス
IPersonInfo {
  getName();
  ... 動詞や他のひどいもの ...
}
  • それを使ったサービス
IService {
  doSomethingUseful(IPersonInfo); ...
}

談: これは情報をラッピングした場合の例です。ここではセミコロンのある言語を例に考えます。まず情報をラッピングするクラスを作って、そこに動詞を付けます。そして別のサービスを作ってそれを使います。ここでは何が起こっているでしょうか?

移動できるか?

スライド:

  • リトマステスト - そのサブシステムを移動させることはでるか?
    • プロセス外、異なる言語、別のスレッド
  • あまり多くを変えないで移動させたい
    • 透過性を求めているわけではない

談: これによってどのような問題が発生したかを調べる必要がありますが、それは「移動できるか?」という質問を答えることで分かるようになります。

ある方法で行なっているものがあるとして、それをどこか別の場所に移動させることはできるでしょうか。他のものが呼び出すことができるサービスに変えることはできないでしょうか。サブシステムを取り出して移動させることはできないでしょうか。

最初から「システム群のシステム」を作るべきという方法を主張してる人を見たことがあります。第一イテレーションから 6つのサービスを作るのです。僕はその人に

「それはちょっと行き過ぎた事前準備じゃないかな。まずコンポーネント群のシステムを作って、後でシステム群のシステムに変えていけばいいんじゃないか」

という事を言いましたが、その人が言うには使っている言語とその人の使い方のため仕方が無いことなのだと教えてくれました。これは図らずも問題を明らかにする考えだと思いました。つまり、動詞指向のものを渡して回っているために、コードを後から変えることが難しくなっている例だからです。

サブシステムが持つべきもの

スライド:

  • 明確な境界線
  • 演算インターフェイス (動詞) の抽象化
  • エラー処理の一般化
  • データを受け取り、返す
    • IPersonInfo ― おっと!
  • 再び、マップ (ハッシュテーブル)

談: 僕たちがサブシステムに求めるものは何でしょう?

まず明確な境界線が必要です。あとは、演算を抽象化してサービスが動詞を持つようにすべきです。エラー処理も何かが必要でしょう。しかし、最も重要なのはデータを受け取り、返すことです。こうすれば移動に伴う問題は発生しません。

僕たちは普段は動詞付きのオブジェクトのようなものを作ってプログラムを書いていますが、誰かが

「別のサーバに置くべき」

と言うと即座にそのようなスタイルを止めます。それはどうしてでしょう? 僕たちは即座に

「それは RESTful で、データ構造を受け取って、データ構造を返して、それは JSON だ」

と言います。これらの素晴らしいアイディアがこういう局面で良い物なら、プログラムの内部では良い物でないのでしょうか? 実際の所それらは、プログラムの内部でも良い物です。使っていない理由はオブジェクト指向で染み付いた慣習です。しかし、こっちの方がより良い方法なのです。こちら側にコードを移せば、常にデータだけを相手にプログラムを書くためより率直なものとなります。
先ほどみたように、ここで出てくる問題の多くはマップやハッシュテーブルを使うことで解決できます。

シンプルさは選択肢だ

スライド:

  • 用心と感受性と細心の配慮を要する
  • シンプルさと簡単さや親しみやすさを等価に扱うことは間違い
    • 「もつれ」のことを考える訓練をする
  • 信頼性のためのツール (テスト、リファクタリング、型システム) はプログラムがシンプルであるかどうかは無関心
  • シンプルな構築物を選択する

談: まとめに入りますが、シンプルさは自発的に選ばなければいけない選択肢です。

シンプルさはツール群や開発手法などによって副次的にもたらされることは絶対にありません。これは実際に行わなければいけない作業です。これは最も重要な作業です。
なぜなら、これを行うことで他の作業が著しく、根本的に簡単になるからです。

シンプルさに対する感性を磨く必要があります。順序問題について考えたり、情報をラッピングしていないか考えたりすることで上達することができます。

シンプルさと簡単さを分けて考える必要があります。「もつれ」に対する感性も磨くべきでしょう。「もつれ」を見つけたり、「もつれ」について誰かと会話をしてみましょう。スタンドアップ・ミーティングの一部を使って「昨日もつれを作らなかったか」「僕たちは何かコンプレクトしなかったか」考えてみて下さい。立ち止まって、「次に行おうとしていることは既にあるものをコンプレクトしないだろうか」と、誰かと話してみて下さい。これを語るための語彙は今日得られたと思います。

ツールに頼りきりになってはいけません。ツールはこの作業を代行してくれません。他に良い特長があるかもしれませんが、シンプル化という作業は行なってくれません。ツールはシンプルということには無関心です。
そのため、あらかじめシンプルな構築物を選択する必要があります。あなたの言語には多くのシンプルではないものがあります。必要に迫られない限りそれらを選ばない必要があります。

シンプルさの必要性

スライド:

  • 複雑さは理解の妨げとなる
    • そのため耐障害性の妨げとなる
  • シンプルさは変更を可能とする
    • 真の機敏さの主な源となる
  • シンプルさ = 機会
  • (シンプルな) ものを作って下さい

談: 僕はシンプルさは不可欠なものだと思います。
シンプルさは、僕たちが普段直面する 2つの根本的な問題を解決します。

第一の問題は複雑さです。複雑さを最小に抑える必要があります。これを実現する唯一の方法はシンプル化なので、これは自明でしょう。

第二は機会についてです。シンプルさは変更を可能とします。僕はこれが真の機敏性 (agility) の主な源となると思っています。機敏性とは何かを実行するという意味です。やり直すという意味ではありません。再実行するという意味でも、元に戻すという意味でもありません。実際に実行することを意味します。

「僕はここにいるけど、あそこへ行きたい」

と思ったときに、即座に動けるのが機敏性です。今あるものを全て分解したり、捨てたりしてから、次のものに取りかかるということではありません。直接実行できるのが機敏性であるため、象を引っ張りまわしているうちは絶対に「アジャイル」であることは無いでしょう。

これで終わりです。シンプルなものを作って下さい。