「構造化プログラミング」の版間の差分

削除された内容 追加された内容
Cewbot (会話 | 投稿記録)
m Bot作業依頼: {{Cite journal}}のパラメータ一を小文字にする - log
編集の要約なし
(同じ利用者による、間の10版が非表示)
1行目:
'''構造化プログラミング'''(こうぞうかプログラミング|{{lang-en-short|''structured programming''}})は、コンピュータプログラムに構造」の考え方を導入して記述をより簡素明快にし、ソフトウェアの開発効率と品質の向上と[[ソフトウェア危機|開発の効率化]]目指し図っコンピュータ・プログラミング技である。今日の「構造化プログラミング」は一般に誤解を招く言葉になっており、以下の3つの解釈が存在している。
{{Otheruses|ダイクストラらによるソフトウェア工学的手法としての「構造化プログラミング」| goto文論争 |goto文}}
 
# 1969年に計算機科学者の[[エドガー・ダイクストラ|ダイクストラ]]が発表した論文<ref name="structured_programming" />。構造化プログラミング(''structured programming'')という言葉はこれが初出となる。内容はプログラムの構造設計に関するものであり、抽象から細部へのトップダウン設計、抽象データ+抽象ステートメントのモジュール、細部ジョイントといった考え方が提唱されていた。
'''構造化プログラミング'''(こうぞうかプログラミング|{{lang-en-short|''structured programming''}})は、コンピュータ・プログラムに構造を導入して記述をより簡素明快にし、ソフトウェアの品質の向上と[[ソフトウェア危機|開発の効率化]]を目指したコンピュータ・プログラミング技術である。
#1966年に計算機科学者の[[コラド・ベーム|ベーム]]とヤコピーニが発表した論文。内容はコーディングに関するものであり、順次、選択、反復の三つの手段であらゆる計算処理を行えると提唱し、その数学的証明が添えられていた。本来はベームとヤコピーニの証明と呼ぶべきものだが、後年に幾つかの事情から[[構造化定理|構造化定理(''structured theorem)'']]として紹介された為にダイクストラの構造化プログラミングとの混同を招く事になった。
#1958年に公開された「[[ALGOL|ALGOL 58]]」などを先例とし、また上述の[[構造化定理]]がその定義名の由来になったと思われる[[プログラミングパラダイム]]の一つ。goto文を多用する非構造化プログラミング(''unstructured programming'')の対義語である。順次、選択、反復といった制御フローとサブルーチンをブロック単位で記述し、それらを直列または入れ子状に配置する事でプログラムの構造化を実現するという考え方である。プログラミング言語を分類する際のカテゴリ名として使われる事が多い。
 
今日の構造化プログラミングに対する一般的な認識は(3)になっている。しかし、(1)(1)の[[エドガー・ダイクストラ|ダイクストラ]]が提唱した理論が本来の意味での構造化プログラミングであり稿では(1)(1)について説明する。(2)と(3)(2)については「'''[[構造化定理]]'''」が該当記事なる。
今日の「構造化プログラミング」は複数の誤解を招く言葉となっており、本来の定義とソフトウェア技術者を含む世間の用法の間に差異が生じている。この様な事情から構造化プログラミングには以下の3つの解釈が存在している。
 
== 一般認識としての構造化プログラミング ==
# 1969年に計算機科学者の[[エドガー・ダイクストラ|ダイクストラ]]らによって提唱され反響を呼んだソフトウェア工学理論<ref name="structured_programming" />。ここで構造化プログラミング(''structured programming)の名称が初めて使われ、広く知られるようになった。''
正確な定義をさて置くと、国内における構造化プログラミングの一般認識はコーディングレベルのテーマであり、プログラム文にブロック単位の制御構造(''control structures'')を導入する事を意味する。ブロックとは括弧記号またはBEGIN&ENDなどで区切られた一行以上のステートメントのかたまりであり、それぞれは直列または入れ子状に配置される。視覚的に判別しやすいブロックの起点と終点が自動的にフロージャンプの位置指定になるので、結果的に無差別ジャンプのgoto文を使わないで済むようになる。制御構造には以下の四種がある。
#1966年に計算機科学者の[[コラド・ベーム|ベーム]]らが発表した[[構造化定理|構造化定理(''structured program theorem)'']]によるプログラミング理論。
#1958年に公開された「[[ALGOL|ALGOL 58]]」を先駆けとする構造化プログラミング言語を用いた開発環境。名称が確立される以前からソフトウェア技術者の間では漠然と実践されていた。
 
#'''順次'''(''sequence'')ステートメントを順々に処理する。
今日の構造化プログラミングに対する一般的な認識は、(2)と(3)が示す「順次、選択、反復といった制御フローをブロック単位で表現し、それらを直列または入れ子状に配置する事でプログラムの構造化を実現する」という事になっている。
#'''選択'''(''selection'')条件式の結果に従って次に実行するステートメントまたはブロックを選択してフロー分岐する。
#'''反復'''(''repetition'')特定の状態の間、ステートメントまたはブロック内を繰り返す。状態の確認は反復起点時または反復終点時の二通りある。
#'''サブルーチン'''(''subroutine'')これをコールした次のステートメントに復帰(''return'')する事を前提にして対象ブロックの起点にジャンプする。終点に達すると自動的に復帰する他、任意の途中位置でも復帰できる。
 
また制御構造の補助構文は、上述のサブルーチンからの'''復帰'''(''return'')、現行反復ブロック終点の次のステートメントにジャンプする'''離脱'''(''break-out'')、現行反復ブロック終点にジャンプして結果的に起点に戻る'''中断'''(''discontinue'')の三種が標準とされる。
しかし、(1)の[[エドガー・ダイクストラ|ダイクストラ]]が提唱した理論が本来の意味での構造化プログラミングであり、本項では(1)について説明する。(2)と(3)については「'''[[構造化定理]]'''」が該当記事となる。
[[ファイル:Structured_program_patterns.png|中央|サムネイル|700x700ピクセル|順次、選択、反復の描写図(青はNSダイアグラム、緑はフローチャート)]]
 
== 概要 ==
1969年度[[北大西洋条約機構]]ソフトウェア工学評議会のワーキングペーパーに計算機科学者[[エドガー・ダイクストラ]]は「構造化プログラミング」と題した一文を寄稿している<ref name="structured_programming" />。その論旨はいわゆる[[ソフトウェア危機]]の解決策として従来の[[ボトムアップ設計]]から[[トップダウン設計とボトムアップ設計|トップダウン設計]]への移行を推奨するものであった。[[ソフトウェア工学]]の中で[[トップダウン設計とボトムアップ設計|トップダウン設計]]の必要性が公に提唱されたのはこれが初回とされる。
ダイクストラは1969年のワーキングペーパー<ref name="structured_programming" />で構造化プログラミングについて以下のように語っている。
 
論文の前半では、プログラムサイズの肥大化に伴い、各プログラム部品およびそれらを組み合わせた際のプログラム正当性(''program correctness'')を証明(''demonstration'')する為のテスト回数が指数的に増加して完遂が不可能になるという[[ソフトウェア危機]]の問題について触れられている。ダイクストラは、各部品を下から一つ一つ積み上げてプログラム全体を完成させるという1960年代当時の標準的な開発手順では、膨大化したテスト回数の作業量に対する人手が到底追い付かなくなる事を実際の工程数計算を例に出して警鐘を鳴らした。
# '''良く構造化されたプログラム(well-structured programs)''':プログラムのサイズが大きくなっても正しさを証明できる構造にすること。[[構造化定理]]とは無関係。
# '''段階的抽象化(step-wise abstraction)''':プログラムの意味のある部分をくくり出して抽象化文にすること。抽象化文は現在で言えば、関数やメソッドに相当する。これによって、プログラムの可読性が向上する。ダイクストラは段階的抽象化をするプログラムは[[構造化定理]]と同様の制御構造を使うべきと述べているが、このワーキングペーパーでそのような制御構造に触れているのはここだけであり、構造化プログラミングが構造化定理とあまり関係ないことがわかる。
# '''[[段階的詳細化法|段階的詳細化]](step-wise refinement)''':1969年のワーキングペーパーにこの言葉は登場しないが、段階的抽象化の説明の最後に「抽象的プログラムから始めるのもこの手法の1つの側面」と書いており、段階的詳細化のことに他ならない。段階的抽象化とは逆に抽象的な設計から始めて詳細化していくことによって設計を容易にする。
# '''抽象データとその上で動作する抽象化文の共同詳細化(joint refinement)''':現在の[[オブジェクト指向]]のクラスに近い考えである。抽象データ=メンバ変数、抽象化文=メソッドと言うことである。抽象データとその上で動作する抽象文を組み合わせて詳細にしていくのである。
# '''プログラムの階層化''':ダイクストラは共同詳細化の結果(オブジェクト指向のクラスに似たもの)を真珠に例えて、プログラムの階層化を説明した。ダイクストラは、階層化されたプログラムを真珠のネックレスに例えた。真珠のネックレスは真珠を交換して、変更を容易にしたり、真珠の再利用も可能である。
 
後半では'''抽象'''(''abstraction'')と'''細部'''(''refinement'')という二つの対になる言葉が定義され、プログラム全体をピラミッド風に階層分割して上の方を抽象化、下の方を細部化とした。ダイクストラは、下の方の部品から上の方の統合枠に向かって作り上げていく従来の開発手順を'''段階的抽象'''(''step-wise abstraction'')と呼び、テスト結果と進捗状況を明確にする堅実な手段であるとしながらも、あえてこれとは逆方向の開発手順を提唱した。細部からの開発手順は各部品間の依存関係を生みやすく、これがテスト回数の指数的な増加につながり、ひいてはソフトウェア危機の元凶になっていると見なしたからである。抽象から細部に向かうという上から下への(''from top to bottom'')開発手順は当時馴染みが無かったので、if文のthen節とelse節をそれぞれ抽象化した例えで実現可能な事が説明された。順次、選択、反復のいわゆる制御構造(''control structures'')に触れられたのはこの文節だけである。
以上のように[[構造化定理]]とはあまり関係のないことであるが、現在でも構造化プログラミングと構造化定理は混同されている。
 
抽象階層からプログラムを構築する為の手段として、[[ALGOL]]プログラムのInteger型の扱いを参考にしたダイクストラは、'''細部ジョイント'''(''joint refinement'')というプログラム概念を提示した。これは抽象階層では仕様決定できない実装データ(=細部データ)を扱うための仕組みである。細部ジョイントが表わすデータは'''''抽象データ'''''(''abstract data structures'')と定義され、それを抽象階層向けに出力ないし入力する仲介ルーチンは'''抽象ステートメント'''(''abstract statements'')とされた。抽象データとそれに関連する抽象ステートメントをひとまとめにしたいわゆる[[モジュール]]をダイクストラは'''真珠'''(''pearl'')と呼んだ。細部ジョイントはオブジェクト指向における[[インタフェース (抽象型)|インターフェース]]、真珠は[[クラス (コンピュータ)|クラス]]に相当するものと考えてよい。同論上で[[Simula|Simula67]]のclass構文も引き合いに出されている。
 
各真珠は互いに依存関係がない独立したモジュールなので連結または分離時の副作用が無く、これによりテスト回数の指数的な増加を回避できるとされた。真珠は細部ジョイントによって抽象から細部に向けて順々に連結されてプログラム全体を構築する。細部ジョイントを糸に見立てたこの数珠繋ぎの「構造化」をダイクストラは'''真珠のネックレス'''(''necklaces strung from pearls'')と呼んだ。真珠は細部ジョイントから随時切り離して必要に応じた別の真珠に交換する事も出来るので、テスト回数を増やす事なく移植や仕様変更にも柔軟に対応できるものとされた。いずれの眼目もプログラムの正当性(''correctness'')を証明(''demonstration'')する為のテスト作業量を軽減する事にある。これがダイクストラの唱える構造化プログラミングの趣旨である。
 
== 歴史 ==
46 ⟶ 51行目:
 
== 誤解 ==
=== Millsミルズによるgoto-lessプログラミング ===
{{See also|goto文}}歴史的経緯から、構造化プログラミングはIBMの{{仮リンク|ハーラン・ミルズ|en|Harlan Mills}}(Harlan Mills)の提案に由来するgoto-lessプログラミングとして一部分を切り取られた形で広く知られている<ref name="goto_nested_loop">{{cite journal|和書|last=金藤|first=栄孝|last2=二木|first2=厚吉|year=2004|title=多重ループからの脱出でのgoto文の是非:Hoare理論の観点から|journal=情報処理学会論文誌|issue=3|page=770-784|naid=110002712129|volume45}}</ref><ref name="goto_finite_state_machines">{{cite journal|和書|last=金藤|first=栄孝|last2=二木|first2=厚吉|title=有限状態機械に基づくプログラミングでのgoto文使用の是非 : Hoare論理の観点から|journal=情報処理学会論文誌|volume=45|issue=9, 2004|pages=2124-2137|naid=110002712260}}</ref><ref name="box_structured">H.D.Mills, R.C.Linger, a.R.Hevner, “ボックス構造化情報システム”, ''ソフトウェアエンジニアリング論文集80's'', Tom DeMarco, Timothy Lister編著, 児玉公信 監訳, 翔泳社, 2006, pp.187-219. </ref>。むしろそれこそが「構造化プログラミング」(あるいは「goto有害論」)であると信じて書かれている文献も多い<ref name="languages_for_structured_programming">{{cite journal|last=筧|first=捷彦|year=1975|title=ストラクチャード・プログラミング用言語|journal=情報処理|volume=16|number=10|page=856-863|publisher=情報処理学会|naid=110002720279}}</ref>。
 
岩波情報科学『算法表現論』<ref group="注釈">木村泉・米澤明憲共著だが、該当部の担当は木村による。</ref>p. 58 から言葉を借りるならばその実態は「プログラマー(職業としてではなく職種としての)に <code>if …</code> や <code>if … else …</code> や <code>while …</code> だけを使用させ,<code>goto</code> の使用を禁止すれば,ダメな連中でも少しはましなプログラムを書いてくるだろう」というもので、「広く影響を及ぼしたが,内容は Dijkstra(ダイクストラ)流とはほとんど無関係」である。
 
=== 三つの構造化文 ===
==== 事実 ====
まず、以下のことに関してダイクストラが主張した、というのは事実である。
 
ダイクストラは“Go To Statement Considered Harmful”<ref name="go_to_statement_considered_harmful" />および“Structured Programming”<ref name="structured_programming" />において、好ましい構造として手続きプロシージャ出し(サブルーチン)の他に順次」「選択」「反復・分岐の3つを挙げた。[[ニクラウス・ヴィルト|ヴィルト]]はこれらを構造化文(structured statement)と呼んだ <ref name="systematic_programming">N.ヴィルト, ''系統的プログラミング/入門'', 野下浩平, 筧捷彦, 武市正人 訳, 近代科学社, 1978. </ref>。goto文を避けて構造化文を用いるようプログラマーに教えることが、構造化プログラミングの伝統的な知恵である<ref name="sp_in_introductory_programming_courses">C.A.R.Hoare, "Structured programming in introductory programming courses", ''Structured Programming'', Infotech state of the art report, 1976, pp.257-263, Infotech International. </ref>。
 
;順次
:'''順接'''、'''順構造'''とも言われる。プログラムに記された順に、逐次処理を行なっていく。[[プログラム (コンピュータ)|プログラム]]の記述と[[コンピュータ]]の動作経過が一致するプログラム構造である。
;反復
:一定の条件が満たされている間処理を繰り返す。
;分岐
:ある条件が成立するなら処理Aを、そうでなければ処理Bを行なう。
 
また、“Structured Programming”<ref name="structured_programming" />や“Structured Programming with go to Statements”<ref name="structured_programming_with_go_to_statements" />においては抽象データ構造の重要性も主張されている。加えて1972年、[[オルヨハン・ダール]]、ダイクストラ、[[アントニー・ホーア|ホーア]]による書籍“Structured Programming”<ref name="structured_programming_72">O.-J. Dahl and E. W. Dijkstra and C. A. R. Hoare, ''Structured Programming'', Academic Press, London, 1972</ref>においてはSimulaによるクラスを使ったプログラムの階層化の考え方も紹介されている。これらの考え方は後の本格的なオブジェクト指向へと発展する。例えばC++の開発者である[[ビャーネ・ストロヴストルップ]]はオブジェクト指向について解説した記事“What Is Object-Oriented Programming?”<ref name="what_is_object-oriented_programming">Bjarne Stroustrup, “What Is Object-Oriented Programming?”, In ''IEEE Software'', Vol. 5, Issue. 3, IEEE Computer Society Press, Los Alamitos, CA, USA, 1988, pp. 10-20</ref>において抽象データ構造の発展としてオブジェクト指向を解説し、そのための手段としてSimulaの機能を紹介している。
74 ⟶ 72行目:
 
ダイクストラも“Go To Statement Considered Harmful”においては最後の段落で、goto文の(論理的な)余分さを証明したようだと軽く触れたのみであり、作られるフローチャートは元のものより正しさの証明が簡単になるとは思えないためジャンプを含まないフローチャートの機械的な作成は推奨しないとした。
 
== ダイクストラによるプログラムの正しさの検証手法 ==
コンピュータは与えたプログラムに応じてそれを計算し結果を出力するという装置であるが、プログラムに誤りがあると、当初の意図した命題(仕様)を肯定しないものとなる{{#tag:ref|たとえば、一律に個々の構成要素が正しい確率を p とすると、N 個の構成要素からなるプログラム全体が正しい確率 P は、安直に計算すれば、
: P = p<sup>N</sup>
となり、 N が大きいプログラム(大規模なソフトウェア)においては、誤りの混入により命題(仕様)を肯定しない可能性は飛躍的に高まることがわかる。|group="注釈"}}。
 
プログラマは、正しいプログラムを作り出すばかりでなく、納得のいくやり方で正しさを証明することも仕事の一つであるという立場を取っていた<ref>[[#構造化プログラミング(1975) |構造化プログラミング(1975)]] p.6</ref>ダイクストラは、プログラムの正しさの納得のいく証明を遂行するための手法を導入した<ref>これは計算機や大規模プログラムを一種のブラックボックス化された機械装置とみなしてテストによって正しさを確認する手法ではない。ダイクストラは、テストはプログラムに対する疑いを全て取り除くには不十分であることを主張していた。[[#構造化プログラミング(1975)|構造化プログラミング(1975)]] p.5 <br />
これについてダイクストラは「テストはバグの存在を示すには有効だが、バグが存在しないことは証明できない」という表現を好んで用いた。
 
*E.W.ダイクストラ, “謙虚なプログラマ”, ''ACMチューリング賞講演集'', 木村泉 訳, 共立出版, 1989, pp.23-43.
*[http://www.cs.utexas.edu/users/EWD/transcriptions/EWD02xx/EWD273.html E.W.Dijkstra, "The Programming Task Considered as an Intellectual Challenge", 1969.]
*[http://www.cs.utexas.edu/users/EWD/transcriptions/EWD02xx/EWD288.html E.W.Dijkstra, "Concern for Correctness as a Guiding Principle for Program Composition", 1970.]
*[http://www.cs.utexas.edu/users/EWD/transcriptions/EWD03xx/EWD361.html E.W.Dijkstra, "Programming as a discipline of mathematical nature", 1973.]
</ref>。ただし、その検証<ref>D.グリースはプログラムの正しさの証明を、抽象的なレベルでは正当性証明、具体的なレベルではプログラムの検証と言葉を使い分けているが、ここでは厳密な区別はしない。
 
*金山裕 編, "構造的プログラミング −批判と支持−", ''bit'', Vol.7, Issue 7, 1975, pp.6-13, 共立出版.</ref>を実行するためには対象となるプログラムは「うまく構造化」されていなくてはならず、その「うまく構造化」されたプログラムを開発する手法が'''構造化プログラミング'''である{{#tag:ref|すなわち、プログラム検証と構造化プログラミングとは不可分の関係にある。|group="注釈"}}<ref>所与のプログラムの正しさを後付けで証明することは、はじめから証明を意識して作られたプログラムの場合より難しいことが経験的に知られている、と言われる。
 
*E.W.Dijkstra, "Programming methodologies, their objectives and their nature", ''Structured Programming'', Infotech state of the art report, 1976, pp.205-212, Infotech International.</ref>。
 
; ダイクストラの三つの知性の道具
 
# 数え上げ推論(enumeration):一人の人間の能力でできる範囲でプログラムの命令の妥当性を一つ一つ確認していく作業
# 数学的帰納法(mathematical induction):while文など計算機特有の多数の繰り返し文についてのみ数学的帰納法を用いて確認する作業
# 抽象(abstraction):プログラムのブロックなどに名前をつけ、さらに中身を見ないで正しいと仮定することで検証作業を後回しにする操作
 
=== プログラムの正しさに関する様々な意見 ===
構造化プログラミングの支持者らは、プログラムの正しさの重要性と証明の方法や表明(assertion)の使い方について熱心に説いた<ref name="the_science_of_programming" /><ref name="structured_programming_72" /><ref name="how_to_solve_it_by_computer">R.Geoff Dromey, ''How to Solve it by Computer'', Prentice Hall, 1982. </ref><ref name="the_craft_of_programming">[http://www.cs.cmu.edu/~jcr/craftprog.html John C. Reynolds, ''The Craft of Programming'', Prentice-Hall, 1981.]</ref>。
ダイクストラは、プログラミングと同時にプログラムの証明を(わずかに証明を先行して)進めることを推奨している<ref name="a_discipline_of_programming">E.W.ダイクストラ, ''プログラミング原論 ― いかにしてプログラムをつくるか'', 浦昭治訳, サイエンス社, 1983. </ref>。そのようなアプローチでプログラムの正当性の問題にあたれば、複雑な問題であっても知的管理が可能であると述べた{{#tag:ref|ダイクストラはプログラミングと証明を並行するのに適した、最弱事前条件をによる検証方法を考案した。ホーア論理は作り終わったものは証明できるが、これから作るプログラムについては指標を与えてくれない<ref name="software_cleanroom">二木厚吉 監修, ''ソフトウェアクリーンルーム手法'', 日科技連, 1997. </ref>。|group="注釈"}}。
 
また、プログラムの証明に対する反論も存在する。マイケル・ジャクソンは、個々のプログラムに証明を付けることは現実的には難しいだろうと述べている<ref name="bit1979_software_design">マイケル・ジャクソン, 吉村鉄太郎, 山崎利治, 大野徇郎, "ソフトウェア設計哲学", ''bit'', Vol.11, Issue 2, 1979, pp.4-12, 共立出版.</ref>{{#tag:ref|ジャクソンは構造化プログラミング手法の一つであるジャクソン法で有名なコンピュータ・コンサルタント。|group="注釈"}}。
 
==脚注==
130 ⟶ 98行目:
* プログラム検証
 
=== '''関連人物 ==='''
 
* [[エドガー・ダイクストラ]]
* [[アントニー・ホーア]]