プログラム設計書とは何か? ドキュメントには何を書くべきか?

プログラミングできない元請けがプログラム設計書をレビューするという矛盾 - yvsu pron. yas
その「プログラム設計書」が何を指してるのかわからないから土壇場で混乱する - @katzchang.contexts
下のリンクより:

*1:「ほとんどプログラムと対応するようなロジックが記述されているようなもの」と言われても、俺としては「よくわからない、見せてほしい」と聞きたいところです。

ひがさんの趣旨と合っているかはわかりませんが、たとえば私が開発中*1プログラミング言語Diksamのコンパイラには、以下のような関数があります。関数の引数の型チェックのための関数です。
http://kmaebashi.com/programmer/devlang/diksam_src_0_2/S/11.html#68

dkc_compare_parameter(ParameterList *param1, ParameterList *param2)
{
    ParameterList *pos1;
    ParameterList *pos2;

    for (pos1 = param1, pos2 = param2; pos1 && pos2;
         pos1 = pos1->next, pos2 = pos2->next) {
        if (strcmp(pos1->name, pos2->name) != 0) {
            return DVM_FALSE;
        }
        if (!dkc_compare_type(pos1->type, pos2->type)) {
            return DVM_FALSE;
        }
    }
    if (pos1 || pos2) {
        return DVM_FALSE;
    }

    return DVM_TRUE;
}

これに対し、以下のようなドキュメントを書け、という人がいます。本当です*2

パラメタの比較(パラメタリスト *パラメタリスト1, パラメタリスト *パラメタリスト2)

for (パラメタ1 = パラメタリスト1, パラメタ2 = パラメタリスト2; パラメタ1 != NULL && パラメタ2 != NULL;
     パラメタ1 = パラメタ1->次, パラメタ2 = パラメタ2->次) {
    (ここまで書いて力尽きたので以下略)

これはいくらなんでも極端な例だろう、と思う人がいるかもしれません。でもちょっと「プログラム設計書 サンプル」でGoogleしてみると、こんなのが見つかります。
http://www.hotdocument.jp/gallery/Doc2007/DocCs_html/function/Function_2_3.html

処理説明
・width、heightにxをセットする。
・nameにnをセットする。
・コンストラクタの終了処理をする

これをプログラムに直すと、

  width = x;
  height = x;
  name = n;

ですかね。あんまり変わらないように思います。ていうかこんなふうにハンパに自然言語で書こうとすると曖昧さが発生してかえってわけわからなくなりそうな。「コンストラクタの終了処理」って何だ。
以下のページから、いろいろなメソッドの「設計書」が辿れるようです。
http://www.hotdocument.jp/gallery/Doc2007/DocCs_html/source/Source_2.html

さて、

http://d.hatena.ne.jp/oredoco/20080415/1208222548

たとえば、はてなのシステムだけど、メールを送信するモジュールが共通化されて

いないようなんです。はてなスターから送られるメールと、それ以外のメールで

仕様が違うようで、はてなスターから送られるメールは、私の環境では文字化けするんです。

(中略)

はてなが駄目なのは「プログラム設計書」が無いからじゃないかな。

上で挙げたような「プログラム設計書」がいくらあったって、はてながメール送信のプログラムを二重に実装した、という事態は、避けられなかったんじゃないでしょうか*3。もっと上位のレベルで見た「モジュール相関図」のようなものがないと。

上で挙げたサンプルに戻りますが、これはAbsTwoDShapeというクラスのコンストラクタのようです。

TwoDShapeは二次元の図形だとして、AbsTwoDShapeのAbsはまさかAbsoluteじゃあるまいし、Abstractのことかなあ。Triangleもあるようだし、スーパークラスとしての(?)抽象的なShapeなのかなあ、AbstractなShapeならなぜコンストラクタがいるのかなあ、大きさだけわかっているShapeってなんだろう? と疑問は山ほど沸いてきますが、そういう肝心のことはさっぱりわかりません。

ドキュメントがまるっきり不要だなんて言っている人はたぶんいないと思うんですよ。みんな、ソースコードを見ればすぐわかるようなことしか書いてないドキュメントは不要だと言っているだけで。

ドキュメントには、以下のようなことを書くべきでしょう*4

  • プログラムの概念や考え方を説明する。このようなことは、ソースだけでは説明しにくい。
  • プログラムが「本来」どう動くべきかを定義する。あるプログラムの動きについて、それがバグであるのか使用であるのかは、ドキュメントで定義されていなくてはならない。

ソースコード1行に1行が対応してしまうような「プログラム設計書」は、そもそも設計書ではなく、設計なしで、別の言語でいきなりコーディングしているようなものなんです。でも、設計書というとそんなのしか思い浮かばない人が実は世間には結構な割合でいます。本当です。「ソースそのものより少し粒度を荒く、ソース3行に対し1行ぐらいの割合で…」などと言う人もいますが、関数やメソッドの目的や外部仕様より先に、内部的な処理フローが出てきてしまう時点で、そういう人はそもそも設計とは何であるかが根本的にわかってないのだと私は思っています。

ところで、話は変わりますが、プログラムの概念や考え方を説明する、というドキュメントにおいて、定型化できる部分はあんまりないと思います。それは、たとえばRubyソースコード完全解説が普通に本の形式になっており、WordやExcelで作られた定型フォーマットの集まりではないことからもわかるでしょう。Joel on Software p.86にも、「テンプレートは有害である」との節があります*5

テンプレートがなければ何書いていいかわかんないよ、と思うかもしれませんし、それでは書く人によりばらつきが出る、とも思うかもしれませんが、コードはともかく「設計」のレベルでは、人によりばらつきが出るのは当たり前なんじゃないですかね。それでもわかりやすく書くことが、設計者には求められている、ということなのであって*6

*1:…には見えないかもしれませんが、一応遅々として進んではいるのでそのうち公開します。ええと、遅くとも連休明けには。

*2:さすがに最近はあまり見かけませんが…

*3:うちでもはてなスターは文字化けしてますが、これが「悪いこと」かというとまた別の話ですけどね。いまどきUTF-8のメールが受け取れないほうがおかしい、という考え方もあるでしょうし、「動いているプログラムは触るな」の大原則から、トラックバック通知とかは元のままにしたのかもしれません

*4:と、これは「センス・オブ・プログラミング」p.128に書いてあるのでした。宣伝。

*5:とはいえ実のところ私は、機能仕様書(外部仕様)ではそれなりにテンプレートが役に立つと思うのですが。

*6:必ず書かなければならない、必須項目のようなものはもちろんありますけどね。