機械語の時代(1940年代)
以下のような16進数の機械語をそのままコンピュータに読み込ませて実行させている時代です。
1 2 |
A10010 8B160210 |
もちろんですが、スーパープログラマーしか実装はできませんでした。
アセンブリ言語の時代
無機質な機械語を人間がわかりやすい記号に置き換える実装です。このアセンブリ言語こそがプログラミング言語の最初の一歩と言われています。
1 2 3 |
MOV AX,X MOV DX,Y ADD AX,DX |
アセンブリ言語で記述したプログラムは、アセンブラという別のプログラムに読み込ませて機械語を生成します。
この言語の登場により、間違いも減り、修正も非常に楽になりました。
ただ、わかりやすくなったとは言え、命令をほんの少し間違えただけでプログラムが暴走してしまいました。
特徴
- CPUが直接解釈できるような20~30種類程度の命令しか使えないが、CPUやメモリを自由に操れる。
- 高級言語では実現できないサイズが非常に小さい、高速なプログラムを作れる可能性がある。
- 高級言語で1行で済むような命令も数百行書かなければならない場合もある。
- 高級言語に当たり前にあるような型や制御構文、構造体、配列、関数等は使えない。
用途
- OS(Linux等)を開発したい場合
- コンピュータに接続する周辺機器を細かに制御したい場合
- 家電等のPC以外の機械の中で動作するプログラムを作成したい場合
高級言語の時代(1950年代後半以降)
数学の計算式のような形で表現できるようになり理解しやすくなった。プログラミングの生産性や品質は大幅に向上しました。
FORTRAN(1957年〜)
1 |
Z=X+Y |
COBOL(1960年〜)
今でも使われている。
特徴
- 低級言語と違って、メモリ領域に自由にアクセスすることはできない。
- 変数等を扱う場合は、メモリのアドレスはOSによって自動で割り当てられて、プログラマがそれを利用することができない。
構造化プログラミングの時代(1970年〜)
1960年代後半に「20世紀末には、世界の総人口がプログラマになってもソフトウェアの需要に追いつかない」というソフトウェア危機が宣言された。この危機に対応するために生産性向上のために構造化プログラミングという概念が生まれました。
構造化プログラミングの基本的な考え方
GOTO文を廃止し、順次実行、条件分岐、繰り返しの三つのみ使って表現すること。
1970年当時は、メモリもCPUも貧弱だったので1バイトでも1ステップでも短くということでGOTO文を使ってしまうプログラムが多かったのです。スパゲッティプログラムが乱立しました。
構造化プログラミングも当初は叩かれましたが、プログラムサイズの増大や、実行速度の遅延を招くという批判がありましたが、ハードウェア性能の向上に伴いそのような批判はされなくなっていき、わかりやすいプログラムを記述することが求められる時代になっていきました。
サブルーチンの独立性を高めること
呼び出し側と、呼び出される側で渡す引数の数を最小限の物にするという考え方です。
グローバル変数を廃止する。
プログラム全体からアクセスができるためデバッグ時に不正な変数であることがわかると全体に影響がないか見ないといけなくなる。
なので、以下の概念が登場したのです。
- ローカル変数(サブルーチンから抜け出すときに消える)
- 引数の値渡し(呼び出し元の変数に影響を与えない)
C言語
構造化言語の中で最も有名な言語。構造化言語の機能に加えて、アセンブリ言語でしかできなかったビット演算や、メモリ領域を効率的に使用するためのポインタなどのきめ細やかな機能があった。UNIXの開発言語に使われるなどアプリケーションプログラミングだけじゃなく、システムプログラミングにも使われた。
関数ライブラリとして関数を実装した。
C言語は例えば、printf関数などは言語仕様ではなく関数ライブラリとして提供している。なので言語コンパイラを改良しなくても言語仕様レベルの改修が行えるようになりました。これは現在主流の言語であるJavaなどでも引き継がれている考え方です。
構造化プログラミングの課題
GOTO文を排除したり、サブルーチン化することで保守性や再利用性は上がりましたが、まだ課題は残されていました。
グローバル変数問題
ローカル変数はサブルーチンを実行するとすぐ消えてしまうので、サブルーチンを超えて値を保持したい場合は、どうしてもグローバル変数に頼らざるお得ませんでした。
貧弱な再利用性
再利用できるのはサブルーチンのみでした。これはアプリケーション全体から見れば効果は限定的でした。
オブジェクト指向プログラミング の時代(1990年代〜)
実は、オブジェクト指向自体は1967年のSimula67で既に登場していました。ただ、当時はハードウェア性能がイマイチだったりしてあまり頭角を表すことはありませんでした。
1990年代のインターネットブームの影響でJavaが登場してからは一気にプログラミング業界内で主役になりました。
クラス
関連性の強いサブルーチンとグローバル変数を1つにまとめて粒度の大きいソフトウェア部品を作ること。従来はバラバラだったサブルーチンとグローバル変数をまとめることができる。クラスのメリットについては下記の記事でまとめています。
ポリモーフィズム、継承
サブルーチンでは対応できない重複コードを一本化する仕組み。
「共通メインルーチン」を作れる。(構造化プログラミング時代には「共通サブルーチン」はあったが、「共通メインルーチン」という概念はなかった。)
フレームワークや、クラスライブラリなどの大規模な再利用部品もポリモーフィズムがあったから導入可能になりました。
関数型プログラミングとオブジェクト指向のハイブリット時代(2010年以降〜)
Javaも2014年にリリースされた8からサポートし始めました。関数型言語を適用すると従来のコードに比べて1/2から1/10くらいのコード量になります。開発や保守も楽になります。関数を再利用の基本単位にしているので、クラスより粒度の小さい、小回りの利いた部品を作れる。
特徴
関数でプログラムを組み上げる。
オブジェクト指向では、構造化プログラミングと同じくクラスに属さない関数を作るのはNGと言われてきた。
構造型言語(C言語)での関数
ひとまとまりの手続きのこと。「引数を指定して関数を呼び出す。」
関数型言語での関数
数学の関数とほぼ同じ意味になる。「引数に関数を適用する。:要は純粋に引数を戻り値に変換する仕組み」になる。
全ての式が値を返す。
従来の言語が命令文(statment)と呼ぶのに対して、後者は式(expression)と呼ぶ。
式、式の評価、ラムダ式
関数を値として使える。
高階関数の特徴
関数と引数を柔軟に組み合わせられる。
部分適用、カリー化、関数の合成
副作用がない。
変数の再代入を許さなかったり、遅延評価(関数が必要になった際に初めて評価する)方式を取るなど。
場合分けと再帰でループを記述する。
パターンマッチ、再帰
コンパイラが型を自動で推測する。
型推論、多相性
この記事へのコメントはありません。