オブジェクト指向基礎学習Ⅰ ~オブジェクト指向へ至る背景~ オブジェクト指向基礎学習Ⅰ ~オブジェクト指向へ至る背景~ 平成20年6月24日 森田 彦
学習内容 プログラミング言語教養編 プログラミング言語発展の歴史(概観) 最も早く普及した言語「FORTRAN」発展の経緯 構造化プログラミングの提唱
Ⅰ.プログラミング言語発展の歴史(概観) <内容> 言語発展の歴史を概観する。 代表的な言語をその性質により分類してみる。 <注目点> どういう風に使い分けしているのか? なぜ、一つに統一できなかったのか?
プログラミング言語発展の歴史 時間 オブジェクト指向言語 低水準言語 高水準言語 手続き型言語 超高水準言語 言語以前 機械語 アセンブリ言語 Delphi 手続き型言語 C++Builder FORTRAN JBuilder PL/1 COBOL ビジュアル開発環境 ALGOL ALGOL68 PASCAL Ada Object PASCAL BASIC C言語 C++ Lisp Java 超高水準言語 Prolog Smalltalk 参考:河村一樹、斐品正照
Ⅱ.最も早く普及した言語「FORTRAN」発展の経緯 <内容> FORTRANの起源および発展の概観 分岐処理の記述の発展 繰り返し処理の記述の発展 <学習する理由> 古い言語の発展の経緯を知ることで、オブジェクト指向プログラミングが生まれた背景を理解できるようになるから。
FORTRANの起源 発表後、FORTRANは進化し続けている。 その進化の方向性に注目! 1954年、IBM社バッカス(Backus)らにより開発開始:ソフトウェア開発のコストが急増→使いやすい高水準プログラミング言語の必要性 1957年 IBM社の汎用大型コンピュータIBM704のプログラム処理言語として実装 当初はIBM Mathematical FORmula TRANslating System と命名 →FORTRAN その性能や設計内容が高く評価される。 科学技術計算に適している。 発表後、FORTRANは進化し続けている。 その進化の方向性に注目!
FORTRANの発展① 原型 ー 型宣言のない世界 <プログラム例> 1234567890 ----------------------------------------- A=3.5 B=1.5 J=(A+B)/2 WRITE(6,100) A,B,J 100 FORMAT(2F4.1,I3) STOP END プログラムは7~72列の間に記述する。 12345678901 -------------------------- 3. 5 1. 5 2 <実行結果> I,J,K,・・・,Nで始まる変数:整数型 それ以外 :実数型 きわめて簡単な文法規則! 数式を書く様にプログラムを書ける!
FORTRANの発展② 副プログラムの導入 SUBROUTINE HEIKIN(A,B,C) C=(A+B)/2 RETURN END 1234567890 ---------------------------------------------- A=3.5 B=1.5 CALL HEIKIN(A,B,C) WRITE(6,100) A,B,C 100 FORMAT(2F4.1,F5.2) STOP END 1234567890123 -------------------------- 3. 5 1. 5 2. 5 <実行結果> プログラムの見通しが良くなる。
FORTRANの発展③ 型宣言の導入 1962年、FORTRANⅣ発表→型宣言を導入 <暗黙の型宣言> ALGOL60プロジェクトの影響 1234567890 -------------------------------------------- REAL A,B INTEGER J A=3.5 B=1.5 J=(A+B)/2 WRITE(6,100) A,B,J 100 FORMAT(2F4.1,I3) STOP END 1234567890 ------------------------------------------ A=3.5 これもOK B=1.5 J=(A+B)/2 WRITE(6,100) A,B,J 100 FORMAT(2F4.1,I3) STOP END I,J,K,・・・,Nで始まる変数:整数型 それ以外 :実数型 <暗黙の型宣言> ALGOL60プロジェクトの影響
FORTRANの発展④ 文字列型の導入 1978年、FORTRAN77発表→文字列型の導入 <実行結果> 1234567890 -------------------------------------------- REAL A,B INTEGER J CHARACTER MOJI*7 MOJI=‘Result:’ A=3.5 B=1.5 J=(A+B)/2 WRITE(6,100) MOJI,A,B,J 100 FORMAT(A,2F4.1,I3) STOP END 1234567890123456789 -------------------------------- Result : 3. 5 1. 5 2 <実行結果>
分岐処理の記述の発展① IF と GO TO の世界 分岐処理の表現(初期) プログラムの見通しが良くない! テストの得点を入力し、50点以上なら「合格」、50点未満なら「不合格」と表示するプログラム IF と GO TO の世界 INTEGER TEN READ(5,*) TEN IF(TEN.GE.50) GO TO 10 WRITE(6,*) ‘不合格’ GO TO 20 10 WRITE(6,*) ‘合格’ 20 STOP END 始め Tenの入力 Ten≧50 No Yes ‘合格’と表示 ‘不合格’と表示 終り プログラムの見通しが良くない!
分岐処理の記述の発展② 分岐処理の表現(改良) 無駄な文番号を排除→ GO TO文を排除 テストの得点を入力し、50点以上なら「合格」、50点未満なら「不合格」と表示するプログラム IF THEN~ ELSE~ END IF 文の導入 INTEGER TEN READ(5,*) TEN IF(TEN.GE.50) THEN WRITE(6,*) ‘合格’ ELSE WRITE(6,*) ‘不合格’ END IF STOP END 始め Tenの入力 Ten≧50 No Yes ‘合格’と表示 ‘不合格’と表示 終り 無駄な文番号を排除→ GO TO文を排除
多分岐処理の記述 発展(CASE文) 無駄な文番号がなくなり見通しが良くなった。 FORTRAN90で導入 select case (N) case default 上記以外の場合の処理 end select 無駄な文番号がなくなり見通しが良くなった。 FORTRAN90で導入
繰り返し処理の記述の発展① 繰り返し処理の表現(初期) IF と GO TO の世界 プログラムの見通しが良くない 1~Nまでの和を求める。 INTEGER N,SUM,I READ(5,*) N SUM=0 I=1 10 CONTINUE IF(I.GT.N) GO TO 20 SUM=SUM+I I=I+1 GO TO 10 20 CONTINUE STOP END I≦N Nの入力 始め 終り No Yes SUM←0 SUM←SUM+i i ← i+1 I ← 1 プログラムの見通しが良くない
繰り返し処理の記述の発展② 繰り返し処理の表現(改良) DO文 の導入 さらに・・・ DO文の導入→GO TO文の排除 1~Nまでの和を求める。 DO文 の導入 INTEGER N,SUM,I READ(5,*) N SUM=0 DO 10 I=1,N SUM=SUM+I 10 CONTINUE STOP END I≦N Nの入力 始め 終り No Yes SUM←0 SUM←SUM+i i ← i+1 I ← 1 INTEGER N,SUM,I READ(5,*) N SUM=0 DO I=1,N SUM=SUM+I END DO STOP END さらに・・・ DO文の導入→GO TO文の排除 プログラムの見通しが良くなる
DO WHILE文の導入 INTEGER SUM,I SUM=0 I=0 DO WHILE(SUM<=100) I=I+1 例)SUM=1+2+・・・を、SUMが100を超えるまで繰り返す。 INTEGER SUM,I SUM=0 I=0 DO WHILE(SUM<=100) I=I+1 SUM=SUM+I END DO Java言語のwhile文と同等! FORTRAN90で導入 その後FORTRAN95を発表→進化し続けている。
Ⅱ.構造化プログラミングの提唱 提唱の背景-GOTO文の魔力 ダイクストラの主張 構造化のメリット 言語仕様への影響 プログラムのモジュール化へ ソフトウェア危機
GOTO文の魔力 2.処理Bの前にCが必要に→処理Cを挿入 3.完成 1.処理A,Bの実行 処理A 処理B 処理C 処理A 処理B 処理A 当時の編集環境では手間がかかる。 GOTO文を用いると・・・ 処理A 処理B 処理C 作成時の順番を維持できる→(当時としては)開発効率が上がる。 しかし、読みにくい。→ミスを誘発する。 処理の順番通りに記述した方が読みやすい。
スパゲッティ・プログラム(BASICの例) 10: INPUT A 20: IF A>0 THEN 50 30: PRINT “正ではない” 40: GOTO 60 50: PRINT “正の数” 60: END 10: INPUT A 20: IF A>0 THEN 50 25: IF A=0 THEN 45 30: PRINT “負の数” 40: GOTO 60 45: PRINT “0である” 46: GOTO 60 50: PRINT “正の数” 60: END 思いつくままに、GOTO文を使ってプログラムを拡張。→ 迷路のようなプログラムに。
ダイクストラの主張 分かりやすいプログラムを書こう! 構造化定理:1つの入り口と1つの出口を持つようなアルゴリズムは、「連接」、「分岐」、「繰り返し」の基本構造を(処理の順に)つなげることで記述できる。→ダイクストラが証明 あらゆる処理(アルゴリズム)はGOTO文なしに記述可能。 → 1968年 Dijkstraが主張。→構造化プログラミング(運動)の始まり。 分かりやすいプログラムを書こう!
構造化プログラミングのメリット プログラム開発の効率が向上する。 処理の順番に記述されるので、プログラムが読みやすい。 フローチャートによるプログラム設計が可能 バグの少ないプログラムの開発が可能 構造化により、無駄な処理が少なくなる。 プログラム開発の効率が向上する。
言語仕様への影響 プログラミング言語は、連接、分岐、繰り返しを表現する機能がなければならない。 C:条件 S:処理 と表すと・・・ 分岐の表現 if C then S1 else S2 多分岐 case C of (C1:S1;C2:S2;・・・Cn:Sn) 繰り返しの表現 while C do S (for文はカウンタ変数を用いる特殊な用途のために特別に用意。全ての処理はwhile文で記述可能) これらの機能が備わって行く過程は、FORTRANの発展過程に顕著。
プログラムのモジュール化 構造化プログラミングの最終的な主張。 構造化プログラミング→プログラムを基本構造(連接・分岐・反復)を(処理の順に)つなげて表現する。 幾つかの基本構造→ひとまとまりの処理→モジュール モジュール→ サブルーチン(FORTRAN)、関数(C言語)、メソッド(Java)など。 プログラムはモジュールの組み合わせで表現できる。 プログラムの基本構造は、モジュールを(処理の順に)つなげて表現できる。個々の処理の詳細はモジュール内部で記述。 構造化プログラミングの最終的な主張。
プログラムのモジュール化 例 問題 学生のテスト成績を読み込み成績順に表示する。 <プログラムの構造> データの読み込み データのソート プログラムのモジュール化 例 問題 学生のテスト成績を読み込み成績順に表示する。 <プログラムの構造> データの読み込み データのソート データの表示 Integer Tokuten(200) CALL ReadData(Tokuten) CALL SORT(Tokuten) CALL Display(Tokuten) <メインルーチン> プログラムの基本構造はメインルーチンで記述 処理の詳細はモジュール(サブルーチン)で記述 <ポイント> プログラムの基本構造が分かりやすくなる。→見通しが良くなる。
モジュール化に基づく構造化プログラミングの工程 要求される処理を幾つかの処理(モジュール)に分割 モジュールの命名 モジュールを適切な順に配置 各モジュールの処理内容の記述 全体 部分 トップダウン的思考が必要!
参考) モジュール化に基づく構造化プログラミングの例 参考) モジュール化に基づく構造化プログラミングの例 カレンダープログラム:日付を入力すると、それが何曜日かを表示。
メインプログラム 年月日を与えると曜日を計算してくれるモジュール(メソッド)を定義 void jButton1_actionPerformed(ActionEvent e) { int Year=Integer.parseInt(jTextFieldY.getText()); int Month=Integer.parseInt(jTextFieldM.getText()); int Day=Integer.parseInt(jTextFieldD.getText()); String Youbi; Youbi=YoubiCalc(Year,Month,Day); //曜日を求める jLabelAns.setText(Youbi+“です。”); //結果表示 } 年月日を与えると曜日を計算してくれるモジュール(メソッド)を定義
YoubiCalc(Year,Month,Day)メソッド String YoubiCalc(int Year, int Month, int Day) { String WDay; int N= DayCount(Year,Month,Day) % 7; switch (N) { case 0: WDay="日曜日"; break; case 1: WDay="月曜日"; ・・・ } return WDay; 曜日はある基準日(例えば2000年12月31日:日曜日)からの日数で決まる。 年月日を与えると基準日からの日数を計算するモジュール(メソッド)を定義
DayCount(Year,Month,Day)メソッド int DayCount(int Year,int Month,int Day) { int DaySum=0; for (int i=2001;i<Year;i++) {//1年前の12/31までの日数 if( Uruu(i) ) { DaySum=DaySum+366; } else{ DaySum=DaySum+365; } for (int i=1;i<Month;i++) { //一月前の月末までの日数 ・・・ DaySum=DaySum+Day; //当該月の日数を加える return DaySum; 閏年を判定する必要がある。 当該年が閏年かどうかを判定するモジュール(メソッド)を定義
以上を振り返ると・・・ プログラムの完成! メインプログラム YoubiCalc(Year,Month,Day)メソッドの定義 DayCount(Year,Month,Day)メソッドの定義 Uruu(Year)メソッド の定義 プログラムの完成!
読みやすさ / 書きやすさの視点から構造化プログラミングを見ると・・・ 「IF+GO TO」文の世界→思いつくままに記述できる。→書きやすい(特別な訓練なしでも書ける)。 しかし、後から見ると読みにくい。→開発効率に限界 一方、構造化プログラミングの世界では・・・ 基本構造さらにはモジュールの組み合わせで(処理順に)記述する。→記述する際にプログラムの全体構造を把握しておく必要がある。→慣れるまで訓練(教育)が必要。 出来上がったプログラムは読みやすい。→開発効率は上がる。 構造化プログラミングの普及→教育の必要性増大 書きやすさから読みやすさへ
ソフトウェア危機 次週のポイント! 構造化プログラミング→ソフトウェアの生産性向上 しかし、既存のソフトウェアの再利用性については十分な向上が得られなかった。 ソフトウェアの需要増に、ソフトウェアの生産が追いつかない→ソフトウェア危機 特に、GUI環境の普及に伴って、その傾向が顕著に! 「使う方は天国、作る方は地獄」 より効率の良い、プログラム開発形態は?→オブジェクト志向プログラミングが注目される。 プログラムの拡張の容易さ、あるいは再利用性の向上(差分プログラムの徹底)がキーポイント! オブジェクト指向言語でどのように改善されるか? 次週のポイント!
プログラムのモジュール化 例 問題 学生のテスト成績を読み込み成績順に表示する。 <プログラムの構造> データの読み込み データのソート プログラムのモジュール化 例 問題 学生のテスト成績を読み込み成績順に表示する。 <プログラムの構造> データの読み込み データのソート データの表示 Integer Tokuten(200) CALL ReadData(Tokuten) CALL SORT(Tokuten) CALL Display(Tokuten) <メインルーチン> プログラムの基本構造はメインルーチンで記述 処理の詳細はモジュール(サブルーチン)で記述 <ポイント> プログラムの基本構造が分かりやすくなる。→見通しが良くなる。
モジュールの再利用(問題点) 問題 学生のテスト成績を読み込み成績順に表示する。 問題 学生のテスト成績を読み込み成績順に表示する。 テストの得点だけではなく、学生の氏名も読み込むように拡張すると・・・。 修正に手間がかかる。 既存部分はいじらず、新たに必要になった部分のみを加えるような修正はできないか→差分プログラムの徹底 Integer Tokuten(200) Character Shimei(200) CALL ReadData(Tokuten,Shimei) CALL SORT(Tokuten,Shimei) CALL Display(Tokuten,Shimei) サブルーチンの書き直しが必要 サブルーチン内部の理解が必要
FORTRAN用パンチカード 1 2 穴の開いている位置で、英数字などの記号を表現。 カード1枚が1行に対応。
プログラム(アルゴリズム)の基本構造 連接 分岐 繰り返し 条件が成立すれば処理A、そうでなければ処理Bを実行 Yes No 処理A 処理B 処理C 条件 処理A Yes No 条件が成立すれば処理A、そうでなければ処理Bを実行 条件が成立している間は、処理Aを繰り返し実行 処理A,B,Cを順に処理
プログラミング言語以前 最初のコンピュータ(電子計算機)ENIAC 真空管で動作する電子計算機 1946年 ペンシルベニア大学のモークリーとエッカートが開発 米国陸軍の弾道計算に利用 巨大(18000本の真空管)で消費電力も膨大(175kW) 計算の手順(プログラム) 配線の組み替えとスイッチの組み替えで実施→プログラミング言語なし。
プログラミング言語の登場 ノイマン型コンピュータの登場 1949年英国のEDSAC完成 配線の組み替えとスイッチの切り替え→プログラムとして作成し、記憶装置に記憶させる プログラム→機械語で記述 機械語 コンピュータが直接理解できる言語→2進数で表現
機械語 2進数を1バイトずつ2桁の16進数で表現 例:188+17の答を求める 9D BC 11 9D:加算命令 BC:188 11:17 プログラミングは大変
アセンブリ言語 変数名の発明 1950年代前半に登場 例:188+17の答を求める 初期のアセンブラ ADD BC 11 ADD→9Dに翻訳する必要がある→アセンブラというソフトが処理(現在のコンパイラと同じ) 初期のアセンブラ メモリ内のアドレスの指定をプログラマが担当 MOVE A [+120]: Aレジスタの現在値を120バイト後方のアドレスへコピーする(代入する) 変数名の発明 MOVE A data1 → アドレス計算からプログラマを解放 →翻訳処理ソフトが担当
FORTRAN 1957年 IBM社の汎用大型コンピュータのプログラム処理言語として実装 FORmula TRANslation Systemの略 その後大いに発展 FORTRANⅡ(’58)副プログラム→FORTRANⅣ(’62)型宣言→FORTRAN66(’66)→FORTRAN77(’77)文字列→FORTRAN90(’91)組み込み関数追加 科学技術計算に適している
COBOL COmmon Business Oriented Language 1959年開発 事務処理に適している データ処理(ファイルアクセス)に優れている英文を書くようにプログラミングできる。 最も広汎に使われたプログラミング言語 ’80年代までは→COBOLができなければSEになれない!
PL/1 Programming Language 1 プログラミング言語の用途が分化 科学技術計算 FORTRAN 事務処理計算 COBOL 両者を包含した言語は可能か?→IBMとSHARE(IBMのユーザ団体)が開発→1964年に開発 汎用的な利用が可能 言語処理系が巨大化
ALGOL ALGOrithmic Language 1958年開発(ALGOL58) 科学技術計算向けの言語 厳密な構文規約を採用 プログラミング言語の構造として優れている 1960年 ALGOL60制定 他のプログラミング言語(CやPASCALなど)に大きな影響を与える。 1968年 ALGOL68発表→言語規模の巨大化
BASIC Beginner’s All-purpose Symbolic Instruction Code 10: A=10 30: C=A+B 40: print C 1964年 米国ダートマス大学で開発 初心者のための教育用言語 言語仕様が簡単 コンパイラではなくインタプリタを使用 当初は汎用コンピュータ→パソコンに移植→大いに普及
PASCAL 1971年 Wirth(ヴィルト)により発表 ALGOL60の後継言語 特徴 構造化プログラミングの実現、適切なデータ構造 構造化プログラミングの実現、適切なデータ構造 系統的なプログラミング教育に最適 → 既存の言語とは異なる視点で開発 言語仕様の範囲を広げ過ぎない→言語処理系の効率化→ALGOL68の反省 C言語などに影響
C言語 main() { int a,b,c; a=10; b=20; c=a+b; printf(“%d\n”,c); } 1973年 米国AT&Tのベル研究所のRitchie(リッチー)がUNIX開発用に設計 1967年 Richards(リチャーズ)がBCPLを開発→Thompson(トンプソン)がUNIX記述用に更新・開発→B言語 その次の言語→C言語 特徴 システム記述言語でもある(それまではアセンブリ言語が主流)→システム記述から一般の処理まで広汎にカバー →自由度の高い汎用的な言語 90年代→Cが分からないシステムエンジニアはいらない。
Ada 1980年米国の国防総省の軍規格となる 軍で使用している各種コンピュータシステムの管理が煩雑→言語仕様が数百種類にも及ぶ→統一的に管理できないか? 軍独自の仕様に基づいた新しいプログラミング言語を → 公募によりフランスのIchbiah(イシビア)らが開発した言語を採択
Lisp LISt Processor 1950年代末~’60年代 米国マサチューセッツ工科大学のMcCarthy(マッカーシー)がリスト処理用の言語として開発 関数型言語 関数の組み合わせによってプログラミングを行う f(x)、g(x1,x2,・・・)
Prolog PRogramming in LOGic 1972年 フランス、マルセイユ大学のColmerauer(コルメラウァー)らによって開発 論理型言語 1階述語論理による論理記述とその推論機構が基本 例:「人間は死ぬ」、「ソクラテスは人間である」 → 「ソクラテスは死ぬ」
オブジェクト指向言語 1968年 米国のDahl(ダール)とNygaard(ニガード)によってSimula67開発→Algol60を拡張したシミュレーション言語 1972年 ゼロックス社のAlan Key(アラン・ケイ)らがSmalltalk-72を開発→次世代コンピュータDynabook用のプログラミング言語 1980年 Smalltalk-80を発表 クラス階層と継承を実装→最も純粋なオブジェクト指向言語
既存言語のオブジェクト指向化 C言語→C++言語 1980年からAT&T社のStroustrup(ストローストープ)が開発→1991年にはVersion3に PASCAL→Object PASCAL ビジュアル環境化 C++ → C++Builder、Viasual C++など Object PASCAL → Delphi
Java言語 1995年 米国サンマイクロシステムズ社が発表 開発の考え C++のオブジェクト指向機能を純化 1995年 米国サンマイクロシステムズ社が発表 開発の考え C++のオブジェクト指向機能を純化 C++の一部機能(難解な部分)を排除 特徴 Javaの実行環境があれば、どのOSや機種でも動作する。→携帯端末や家電製品も想定 →急速に注目・普及 2000年代→ Java言語の分かるシステムエンジニアが必要!