ブログトップ 記事一覧 ログイン 無料ブログ開設

Strategic Choice

2015-01-21

[]文芸的プログラミング

literate programming

どういうこと?

プログラムそのものを、ドキュメンテーションにする、というプログラミング手法です。

柱となっているのは「プログラマーが書くのはプログラムではなく、ドキュメントである」という単純な考え方です。

文芸的プログラミングでは、ドキュメントを記述するための言語が、プログラミング言語と密接に結び付けられています。ここでのドキュメントは、まず第一に、何がプログラミングされているのかを明らかにするための説明ですが、それは同時に、コンパイルされてプログラムに組み込まれる対象でもあります。ソースコードはドキュメントでもあり、ドキュメントはソースコードでもあるのです。

文芸的プログラムは、ほとんど物語のように書かれています。そのコードは、人間が筋道をたどりながら容易に読むことができます。言語の解析器に適した順序や制約に従って記述する必要はありません。

これは単にコメントとコードが対比された記述形式の言語というだけではなく、プログラミング方法そのものが従来と対比されたものであると言えます。文芸的プログラミングは、考え方自体が他の方法とまったく異なっています。

このようにして、コードを「(文章の)芸術」、すなわち「文学」「文芸作品」として、プログラミングしていきます。

どうして?

文芸的プログラミングには、次のような利点があります。

  • ドキュメントを別途書かない。
  • コードの説明や正当性の根拠を記述しながらプログラミングを進めていくので、プログラマーがコードについて別の角度から考えるようになる。
  • コードと説明情報が近接した位置に記述されるので、修正作業がしやすく、コードの変更時に説明情報が適切に更新される。
  • コードベース全体において、ドキュメントがただ1つだけ存在することが保証される。
  • 情報の記述が促進され、通常はソースコメントには記述されない種類の情報(アルゴリズムの説明、正当性の証明、設計上の決定の根拠など)もコードに含まれる。

文芸的プログラミングが、特に本領を発揮するのは、製品の保守段階においてです。そのソースコードでは、質の高い、量的にも充実した説明情報を直接参照できるので、通常のソースコードよりも、保守作業が格段に容易になります。

どうすれば?

プログラムを書くときに、その解説ドキュメントを同時に書いていきます。

プログラムとドキュメントを別々に書かずに、ひとつの文書に編み込んだものを書きます。後から、ジェネレータプログラムが、プログラムの部分とドキュメントの部分に分けて、それぞれコンパイラやドキュメント処理系にかかる形にします。

これを実現したものが、クヌース先生の「WEBシステム」です。このツールは、文芸的に書かれたプログラムファイルを解析し、特定の形式にレイアウトされたドキュメントと、通常のコンパイラの入力として使用可能なソースコードのどちらかを生成します。

補足

「文芸的プログラミング」の考え方が提示されたのは1980年代です。結果的に、その処理系が普及することはありませんでした。しかし、プログラムが、その作品の意図を伝え、自己説明的でなければならない、という考え方は受け継がれています。

また、折衷案的ツールとして、特別な形式で記述されているコメントをソースコードから抽出することによって、ドキュメントを生成するツールは、JavaDocに代表されるように、広く使用されています。

出展

本家

2014-12-19

[]セカンドシステム症候群

システムの「2番目のリリース」は、(悪い意味で)ヤバい。

どういうこと?

ファーストバージョンをリリースした開発者が設計する「セカンドバージョンのシステム」は、その開発者の設計するもっとも危険なシステムとなる傾向があります。

どうして?

ファーストバージョンでは、未知のことも多く、リスクが高いため、慎重な判断をすることが多くなります。よい機能を思いついても、「それは次回使おう」と、いったん保留されます。しかし、セカンドバージョンになると、知っていることも多く、自信もあるため、保留していたものを含め、機能を盛り込みすぎてしまいます。

機能を盛り込みすぎると、システムの実装が複雑になり、品質が悪くなります。機能そのものも複雑になり、使い勝手が悪くなるので、結局は使用されない機能となります。

また、保留していた機能を組み込んでも、ファーストバージョン時点では現実的であった機能や技術も、もはや必要とされていなくなったり、時代遅れになっているケースもあります。その部分は丸々無駄ということです。

どうすれば?

自制心を働かせ、「多機能主義」にならないようにします。

そのために有効なのは、改めて「利用者」を明確に定義し、イメージすることです。

開発者の持っている利用者のイメージは、意識的であれ無意識的であれ判断に影響を及ぼします。これが機能を追加したい欲望の「枷」になります。以下の問いを、改めて考えてみることです。

  • だれか?
  • 何を必要としているか?
  • 自分たちに何が必要だと考えているか?
  • 何を望んでいるか?

補足

「多機能主義」は、セカンドバージョンにその傾向がありますが、実はその限りではありません。例えばパッケージアプリケーションの場合などは、バージョンアップを経るごとに、どんどん「無駄に」多機能になってしまうことがあります。これは、利用者が不特定多数で、イメージしにくいことも原因と考えられます。

出典

2014-12-01

[]プログラマをコードから遠ざける例のアレ

アニメや漫画はあまり見ない方なのですが、ふとしたきっかけで「進撃の巨人」のアニメを見ました。その設定の斬新さや、緻密かつ衝撃的なストーリーに、あっというまに虜になりました。キャラクタも魅力的です。

その「進撃の巨人」で、主人公のあるセリフについて、この業界のアナロジーになっているなぁ、と思うところがありました。


簡単に「進撃の巨人」の世界を紹介します。設定だけなので、あまりネタバレはないと思います。

人類は、なぜか突如現れた大量の「巨人」たちによって捕食対象とされ、絶滅寸前までに追い込まれます。巨人は、知能はありませんが、巨大ゆえ圧倒的な体力があることに加え、ほぼ不死身*1です。人類との戦力差は圧倒的で、かろうじて絶滅を逃れた人類は、巨人が越えられない高さの「壁」を円筒状に構築します。現在、その壁の円の中で細々と暮らし、反撃の機会を伺っています。


主人公であるエレン・イェーガーは、自らに巨人に対抗しうる力を身につけるため、軍隊に志願し、訓練兵となります。3年間の巨人打倒の訓練後、卒業しますが、配属先には3部門あります。

  • 壁の外に出て、巨人の調査を行う、危険な任務の「調査兵団」。
  • 壁の中で、壁や街の警護を行う、比較的安全な「駐屯兵団」。
  • 王様の警護という名目のもと、壁の最も内側でマッタリ暮らす「憲兵団」。

慣例で、訓練成績上位10名が、優先的に、安全で快適な「憲兵団」に配属できることになっています。訓練兵はそれを目指して必死に巨人を倒す訓練に励みます。

主人公エレンは、訓練中の同期(アニ・レオンハート)との会話によって、このシステムの矛盾に改めて気づき、そのことで「憲兵団」志望の別の同期(ジャン・キルシュタイン)と口論になります。その内容です。

(エレン)「おかしいと思わねぇのか。巨人から遠ざかりたいがために、巨人殺しの技術を磨くって仕組をよ。」

(ジャン)「けど、それが現実なら甘んじる他にねぇな。」

(エレン)「だから、どうやって巨人に勝つっていうんだよ!!できるやつばっかが内側に引きこもりやがって。」

(ジャン)「俺に言われてもしらねぇよ。」

人類の最優先事項は「巨人の打倒」です。壁の中の資源は限られています。かといって、外に出れば巨人に食べられるだけです。どん詰まりです。しかし、なぜか、巨人に対抗しうる力を持った優秀なものほど、巨人から遠ざかる社会システムになっているのです。

腕の上がった人ほど、コードを書くことからリタイヤしていくのは、良いソフトウェア*2ができにくくなるので、とっても遺憾です。


主人公エレンは、(私怨もありますが、)人類のため、自由のため、巨人を「一匹残らず」駆逐することが目的です。成績上位だったにも関わらず、危険な調査兵団を志願し、実際に入団します。この「強い目的意識」というか、もう「気合」が、彼の魅力の一つです。「目的」があって、それを支える強い意志があって、目的に導かれた「手段」を選択をしています。

見習いたいです。

*1:ダメージを受けても数分で再生してしまいます。厄介です。

*2:私の「よい」の定義は「改善し続けるコトができる」です。

2014-11-28

[]テストコード:テストをやりすぎない

どういうこと?

テストのやり過ぎは、本来の目的を果たさないどころか、それを損なうことさえあります。

どうして?

テストのやり過ぎには、以下のような懸念があります。

  • テストのために、本物のコードの読みやすさを犠牲にするようになってしまう。
  • テストのカバレッジを、100%にしないと気が済まなくなる。
  • テストが神格化され、プロダクト開発の邪魔になる。

どうすれば?

テストをやり過ぎないようにします。

本物のコードをテストしやすいように設計するには、両者に利点がなければなりません。本物のコードは単純で疎結合なものにして、テストは読み書きしやすくすします。テストをしやすくするために、本物のコードにゴミを入れてはいけません。

コードの90%をテストするほうが、残り10%をテストするよりも楽です。最後の10%にはユーザインタフェースやどうでもいいエラーケースが含まれています。その部分はバグのコストが高くないので、テストが割に合いません。

現実的には、カバレッジが100%になることはありません。もしも100%になっていたとしたら、バグを見逃しているか、機能を実装していないか、仕様が変更されたことに気づいていないか、のどれかです。

バグのコストによって、テストコードにかける最適な時間は違ってきます。Webサイトのプロトタイプを作っているのであれば、テストは書かなくても問題ありません。ただ、宇宙船の制御装置や医療機器を作っているのであれば、テストに投資しなければなりません。

プロジェクトの一部にすぎないテストが、プロジェクト全体を支配している状況は異常です。おそらく、テストが、触れてはいけない神のようになっているのです。プログラマたちは、ある種の儀式としてテストを行っています。貴重なエンジニアリングの時間を犠牲にしていると自覚し、それを取り戻さなければなりません。

2014-11-27

[]テストコード:本物コードはテストに優しく

どういうこと?

本物のコードを書くときに、前もってテストを書いておいたり、前もって書かないまでも、後から書くテストを意識しておきます。

すると、面白いことに、テストしやすいような、テストに優しいコードを設計するようになります。そして、このことは、テストそのものへの好影響だけでなく、本物のコードの設計品質を飛躍的に向上させることになります。

どうして?

本物のコードは、テストに優しい設計を行うと、振る舞いごとにうまく分割されて、自然に構成されていきます。

プログラムをクラスやメソッドに分割するというのは、疎結合にしたほうがテストしやすいからです。プログラムが密結合していて、クラス間でメソッド呼び出しがたくさん行われ、メソッド呼び出しに多くの引数が必要だったらこうはいきません。プログラムが理解しにくいだけでなく、テストコードも汚くて読み書きしにくいものになっているはずです。

どうすれば?

コードを設計していて、「これをテストするのは難しそう」と思ったら、立ち止まって設計を考え直します。以下は、テストと設計の典型的な問題を示したものです。

特性テスト容易性の問題設計の問題
グローバル変数を使っている。グローバルの状態をテストごとに初期化する必要がある。
(そうしないとテスト同士が干渉してしまう。)
どの関数にどんな副作用があるのかわかりにくい。
関数を個別に考えることができない。
すべてが動くことを理解するにはプログラム全体を把握しなければいけない。
多くの外部コンポーネントに依存している。最初に足場を設定しなければいけないので、テストを書くのが難しい。
テストを書くのが楽しくないので、みんなテストを書こうとしなくなる。
依存しているものが落ちるとシステムが使えなくなる。
任意の変更にどんな影響があるのかを理解するのが難しい。
クラスのリファクタリングが難しい。
システムが考えなければいけない故障状態や回復経路が増える。
コードが非決定的な動作をする。テストは当てにならず、信頼できない。
テストが正常に動かないことがあるので、最終的に無視されるようになる。
プログラムが競合状態になったり、再現不可能なバグが発生したりする。
プログラムを論理的に判断できなくなる。
バグを追跡したり修正したりするのが非常に難しい。

一方、テストしやすい設計にしていれば、いい兆候です。以下は、有益なテストと設計の特性を示しています。

特性テスト容易性の利点設計の利点
クラスが小さい。
あるいは内部状態を持たない。
テストがしやすい。
メソッドをテストするのにセットアップがあまり必要にならない。
検査する状態が隠されていない。
状態の少ないクラスは単純で理解しやすい。
クラスや関数が1つのことをしている。完全にテストをするためのテストケースが少なくて済む。小さくて単純なコンポーネントがモジュール化されている。
システムは疎結合である。
クラスは他のクラスにあまり依存していない。
高度に疎結合化されている。
各クラスは独立してテストできる。
(複数のクラスを同時にテストするよりもずっと簡単。)
システムは並列的に開発できる。
クラスは他の部分を気にすることなく簡単に修正や削除ができる。
関数は単純でインタフェースが明確である。明確な動作をテストできる。
単純なインタフェースなのでテストが楽。
インタフェースがわかりやすくて再利用しやすい。