構造化プログラミングを知らない子供たち

それは私のことですがな*1

サイエンス社から『構造化プログラミング』の日本語訳が出版されたのが1975年で*2、それから30年以上経つ訳だけど、計算機科学とかソフトウェア工学とかそういった類の正規の教育を受けていないプログラマの中で構造化プログラミングについてそれなりにキッチリと勉強した人ってどれ位いるのだろうか?

年代や分野にもよるだろうけど、少なくとも比較的若手(20〜30代半ば?)の職業プログラマでは結構少数ではないか、と思う*3

というのも最近は、

的なノリが主流らしく、わざわざ構造化プログラミングを勉強する人は「趣味の人」的な扱いにされてしまう気がするのだ。それか「(全員じゃないけど)組み込みの人ですか?」扱いとか。

しかしここには幾つか死角があると思う。

  1. モジュール化の技法として考えた時、C++的なクラス指向なオブジェクト指向プログラミングと構造化プログラミングは真部分集合的な関係にある(オブジェクト指向の方が上位集合)。
    • 構造化プログラミングにおける「サブルーチンによるモジュール化」では解決できなかった「データ構造の取り扱いをどうするか?」という問題に対する解決策の1つ。
    • サブルーチン/プロシージャ/関数よりも大きな「データ構造と関連する処理」を纏めた何かをモジュールとして扱うと都合が良くて、そのモジュールの単位として抽象データ型が結構使えて、且つ抽象データ型の実現にSimula 67のクラスという機能を使うと都合がよいことに気づいたビアルネ・ストラウストラップがC++に採用した*4
  2. で、本来なら上位集合であるオブジェクト指向プログラミングを勉強すれば済むような気がするけど、一般的なオブジェクト指向プログラミング入門の情報には構造化プログラミングの集合にあたる部分の説明がスッポリ抜けていたりする。
  3. しかもここまでの話は「モジュール化の技法」として両者を捉えた場合の話で、それ以外ではオブジェクト指向プログラミングと構造化プログラミングは直交する概念だったりする。
  4. だからオブジェクト指向プログラミングの勉強だけでは構造化プログラミングを勉強したことにならない。
  5. では自学自習しようとすると、使い物になる資料が少なすぎる。
  6. それに周囲の「常識としての構造化プログラミング」となると、どこまで正しいか怪しい。

いや本当に、構造化プログラミングについてそれなりに正しく理解できている人ってどれくらいいるんだろう? モジュール化技法という視点では、構造化プログラミングを押さえておかないとオブジェクト指向プログラミングが台無しになる可能性があると思うんだけどなあ、経験的に*5

構造化プログラミングの効能と学ぶべき範囲

世間一般の建前としては、オブジェクト指向による開発が主流を占めていることになっている。なのでオブジェクト指向プログラミングを前提として構造化プログラミングを勉強することになる。

ずばり、「クラス内部やメソッドの設計や実装に構造化プログラミングを適用する」ということだ。個人的には、構造化プログラミングだけじゃなくて構造化設計に片足を突っ込むぐらいの範囲まで適用できると思う。

『ソフトウェアの構造化設計法』の訳者序文に、

また、最近流行のオブジェクト・プログラミングによるシステム開発においても、クラスやメソッドの設計において構造化設計の指針は十分有効に機能すると考えられる。

という記述がある*6。個人的には構造化プログラミングにも同じことが言えると考えている。(今日的な意味で)ミクロな領域においては、構造化プログラミングや構造化設計が有効だ。少なくとも良いメソッドを書けるようになれる。

ではどの辺りを勉強しておくとよいか? 目下修行中の身だけど、僭越ながら書いてみる。

  • 構造化プログラミング誕生の背景にある思想や基本方針(個別の各種技法以外の部分)。この辺りはソフトウェア工学の基本理念みたいな内容なので、知っておく価値がある。
  • 制御構造周りの話。特にE.W.ダイクストラが「連続、選択、反復」の3構造を入れ子にするスタイルに拘った理由
    • 要は「ソフトウェアが正しいかどうかの検証は人間がやらなきゃならない。で、最終的にソースコードを読むことになるから、ソースコードの見た目(静的構造)と実行時の実際の制御の流れを写像の如く一致させろ。でないとソースから処理の流れを理解することが難しくなってしまい、検証できなくなるぞ」ということ。
    • ソースコードの静的構造と実行時の制御の流れを一致させる為には、使用する制御構造を制限し、限られた制御構造を入れ子状に組み合わせることが有効。幸か不幸か構造化定理にて最小限の制御構造として「連続、選択、反復」があれば何とかなることは証明済みなので、その3つを使うことにする*7
    • この辺り、『岩波講座 情報科学12 算法表現論』の序章を読むと納得できる。もっとも序章のサンプルはFortranで書かれてる……。
    • 単純に「GOTOを使わなければおk」と考えたあなた、我々にはbreakもcontinueも例外もあることに気づきましょうよ。どれも用途限定のジャンプ処理だから、乱用は禁物。節度を持った利用を心がけましょう。特に例外についてはJoel Spolskyのような意見もあるぐらいで、ソースの静的構造とのギャップを生みやすい危険なものなので、くれぐれも取り扱いは慎重に*8
    • もう一つ書いておくと、例えソースコードの静的構造と実行時の制御の流れが一致していたとしても、その流れ自体が複雑怪奇だとしたら、処理の流れを理解することが難しくなってしまうので注意。だって元々の流れが複雑なんだもん。
  • トップダウン手法(段階的詳細化)――というか「解くべき問題領域に都合の良い仮想機械を考えて、その仮想機械の命令文とデータ型を使って簡潔に問題を解く」というメタファー。
    • もちろんそんな便利な仮想機械は存在しないから、使用した命令文をシミュレートする処理を別の仮想機械の命令文とデータ型で書き、必要なら使用したデータ型を分解する。これを繰り返していって、最終的に本来の言語で書けるようになったら完成――というのが段階的詳細化。
    • 今風に言い換えると「解くべき問題領域に最適なDSLを考えて、それを使って簡潔に問題を解く」とでもいうか。
    • 要は、解くべき内容と使用する言語との間に大きなギャップがあるので、その間に抽象化の層を幾つか重ねることでギャップを埋めよう、ということ。同時に、処理とデータ構造について、その内部構造の決定を先延ばしにする効果があることにも注目。
    • 「仮想機械の命令文」はサブルーチンに置き換えることができる。問題は「仮想機械のデータ型」を置き換える為の概念が構造化プログラミングに用意されていなかったことだと思う。だから仮想機械のデータ型を言語組み込みのデータ型にまで完全分解するしかなくて、後でデータ構造に変更が発生した時にデータがあちこちに散らばっていててんやわんやの大騒ぎになる、という欠点を抱えることになる。この欠点を補うのに都合が良いのがデータ抽象の考え方で、まあ1970年代には登場していたようだ。
  • サブルーチン/関数/プロシージャによる分割統治。
    • このあたりは構造化プログラミングだけでは足りない。構造化設計も少し齧るといい感じになる。
    • 特に人間の能力の限界と問題の複雑さを低減する為の指針とか。『ソフトウェアの構造化設計法』の第5章をナナメ読みするといい感じ。
    • あとモジュール強度と結合度。この場合「モジュール == サブルーチン等」なので、良いメソッドやルーチンの指針として使える。モジュール分割技法については保留。

注意点として、構造化プログラミングに嵌りすぎないこと。特にサブルーチンによるモジュール化は手続き型のパラダイムと相性が良すぎるので、手続き型の世界にどっぷりと浸かってしまう危険がある。

あんまり手続き型のパラダイムに浸かりすぎると、オブジェクト指向プログラミングへの移行で躓きやすくなるのが世の常だったりする。

書籍案内

構造化プログラミングの本は、多分書店とかでは入手できないと思う。古書を探すか、図書館で借りるか。図書館も、普通の図書館じゃなくて昔から計算機関連の研究室とかがあった大学の付属図書館辺りに限られてくる気がする。

範囲を構造化手法に広げると、もう少し入手しやすいけど。

『構造化プログラミング』

元ネタの本。3つの論文が収められている。

「構造化プログラミング論」
タイトル通り、構造化プログラミングの話。
「データ構造化序論」
「構造化プログラミング論」で出てきたような原則をデータ構造の設計にも適用してみようという話。問題を解く時、まずはプログラミング言語組み込みのデータ構造ではなく、より抽象的な概念を利用して、内部表現の決定を先延ばしにすることを述べている。で、色々な抽象的なデータ構造についても述べている。何というか、データ抽象の夜明け前的な内容だと思う。
「階層的プログラム構造」
Simula 67の話。詳細は書かない。読んで驚け。

経験に基づいて書くと、構造化プログラミングに関しては、下手な本やWebの記事を読むよりも元ネタにあたった方がよいと思う。幸いにも100ページ足らずの「構造化プログラミング論」だけで済む。

但し、意外と難しい。読むにはパワーが必要。なのでもう少しやさしめの本も挙げておく。

ソフトウェア工学実践の基礎――分析・設計・プログラミング』

これ、正確には構造化プログラミングじゃなくてデータ抽象とかオブジェクト指向についての本*9なのだけど、「構造化プログラミング --> データ抽象/抽象データ型 --> オブジェクト指向」の順に各パラダイムを段階を追って説明している。構造化プログラミングについても結構ページを割いている。

構造化プログラミングに関して、比較的「構造化プログラミング論」に沿った内容で分かりやすく且つ簡潔に説明している。それにCとPascalを使って実際にトップダウン手法でサンプルプログラムを書いているので、更に分かりやすい(後でデータ抽象やオブジェクト指向的アプローチで書き直している)。

自分自身、最初は「構造化プログラミング論」がイマイチ分からなくて、この本から入門した。

『岩波講座 情報科学12 算法表現論』

岩波講座 情報科学〈12〉算法表現論 (1982年)

岩波講座 情報科学〈12〉算法表現論 (1982年)

これの序章も『ソフトウェア工学実践の基礎』に比較的近い。スパゲッティ・プログラムから始まって構造化プログラミング、データ抽象、抽象データ型まで、Fortranで書かれた同一目的のサンプルソフトを肴に書いている。

重要なのは実際にスパゲッティなソースコードを提示して何がどう問題か示していること。スパゲッティなコードの悪い点を堪能できるので、そんなレガシーコードを目にする機会が無い人にオススメ。但しFortranだけど*10

序章以外は、また違った意味でオススメと評判。

『組込みソフトウェア開発のための構造化モデリング

組込みソフトウェア開発のための構造化モデリング 要求定義/分析/設計からソースコード作成までソフトウェア開発上流工程の基本を構造化手法に学ぶ

組込みソフトウェア開発のための構造化モデリング 要求定義/分析/設計からソースコード作成までソフトウェア開発上流工程の基本を構造化手法に学ぶ

構造化プログラミングの範囲では、例えば、

  • 処理をサブルーチン/関数/プロシージャで分割する方法
  • 良いサブルーチンの基準

は明確になっていない。

この辺りは構造化設計の話になってくるので、構造化設計を齧っておくとより良いメソッドを書けるようになる。

で、入門書としては薄くて安いこの本がオススメ。構造化手法全般の教科書的な本。一応組込み開発向けになっているけど、普通に構造化分析/設計の入門書として使える。

『ソフトウェアの構造化設計法』

こちらは構造化設計の原点に近い本で、構造化設計について詳しく書いてある。若干ながら構造化分析っぽいことも書かれている。DFDとか普通に出てくるし。

詳細に書かれているので、各種技法だけではなくて「何の目的でこの技法は存在するのか? そもそもそんな目的が存在する理由は?」といった点もカバーされている。その分、結構厚い。

『ソフトウェアの複合/構造化設計』

ソフトウェアの複合/構造化設計

ソフトウェアの複合/構造化設計

こちらも構造化設計の原点に近い本だけど、『ソフトウェアの構造化設計法』と違って、

  • 薄い
  • 安い
  • 入手しやすい

という利点がある。なのでこちらを先に読んでもよいかもしれない。

*1:「子供」じゃないはずだけど。

*2:原著の出版は1972年だった模様。

*3:「そもそも勉強する時間があるのか?」という点は考えないことにしておく。

*4:ただ同時にSmalltalkで「『メッセージ送信』と、『メッセージを受信したオブジェクトの振る舞い』で表現する」ということを実現する為の機能としてSimula 67からクラスとかを持ってきたものだから、色々とヤヤコシイ事態になって今日に至る……はず。

*5:当たり前の話だけど、大きすぎるメソッドはprivateなメソッドとかで分解しようよ、というか。

*6:日本語訳の出版は1986年。

*7:構造化定理と構造化プログラミングは提唱者も内容も別物であることに注意。構造化定理は「可能である」としか言っていない。「可能である」と「そうするべきである」の間には深い溝がある。

*8:ちなみに私は時と場合によっては躊躇無くgotoを使う派。まあエラー処理か多重ループからの脱出の時ぐらいだけど。

*9:少なくともオブジェクト指向を最終目標としている本だと思う。

*10:Ratforならまだ読めるのだけど。