プログラムの基本をざっくりまとめてみる
[到達したい状態]
- プログラムがどのように実行されるのかを説明できる。
[やること]
- プログラム関連の基礎的な本を読む
- センスオブプログラミング
- プログラムはなぜ動くのか
図書館でセンスオブプログラミングを借りてきたからまずはこの本を読もう。
その前に一旦これを読む
デジタルデータとは?
- デジタルデータとは、0と1で表現できるデータのこと。
- 文章、写真、映像、音声など現実にあるさまざまな形式の情報はデジタルデータに変換できる。
- コンピュータはデジタルデータを高速に処理することができ、かつ保存することができる。
- コンピュータ内部の全ての情報はデジタルデータとして保存されている。
- コンピュータに命令を下すソフトウェアも,デジタルデータで表現されている。
デジタルデータの表現方法について
- デジタルデータの量はbitやbyteと呼ばれる単位で表される。
- bitは0か1のどちらかなので、1bitで2通りの情報を表すことができる 。
- 1byteは8bitなので、256通りの情報を表すことができる。
- 英数字1文字をデジタルデータで表したい場合、A ~ Z、a~z、0~9で62通りあるので、1byteで余裕で表現することができる。
- 日本語1文字をデジタルデータで表したい場合、ひらがなと漢字を合わせて256通り以上あるので、1byteでは済まないことが理解できる。日本語1文字を表現するにはおそらく2byte(2の16乗)以上のデータ量が必要。
デジタルデータとバイナリの違い
エンジニア界隈だと、デジタルデータのことをバイナリデータと呼んでいる気がする。デジタルデータはさまざまな形式の情報を表すものであり、バイナリはコンピュータ内でのデータ表現形式の一つである。なので、デジタルデータのことをバイナリデータと言ってもあながち間違いではないのか。
コンピュータとは
- コンピュータとは、デジタルデータを受け取り、それを処理して、結果を生成するための電子機器
- コンピュータはハードウェアとソフトウェアで構成されている
- コンピュータはハードウェアとソフトウェアがないと機能しない
- ハードウェアとは、コンピュータの物理的な装置のこと
- ハードウェアは大きく分けて5種類に分けることができる
- 入力装置
- 入力装置は、人間が入力した命令(データ)をデジタルデータに変換して、コンピュータに入力する役割を担う。
- キーボード、マウス、マイク、ペンなどが代表的な入力装置
- CPU
- CPUは、デジタルデータの処理を担う。
- CPUは、ソフトウェアに定義されている命令を解釈して実行する
- メモリ(主記憶装置)
- メモリは、CPUで命令を実行する際に必要となる情報を一時的に記憶する役割を担う
- メモリは、電気的に情報を記録する(正確にいうと2進数で情報を管理している)。電力が供給されないとデータを保持できないため、PCの電源が切れるとメモリに記録されていたデータは消えてしまう
- メモリに対して読み書きを行う場合、メモリの内のどこの情報かを表すアドレスを指定する必要がある。
- ハードディスク(補助記憶装置)
- ハードディスクは、永続的にデータを保持します。
- ハードディスクは、磁気や電源を切ってもデータが消えない仕組みの記憶装置である。
- データの読み書きの速度は主記憶に比べて遅い
- 記憶容量はbyteという単位で表され、1byteはアルファベット1文字分に相当する
- ハードディスクの円盤は、同心円上の「トラック」とトラックを放射上に分かれたセクタに分けられる。
- データをハードディスクに保存する際には、「どのトラックのどのセクタに書き込むのか」を考える必要がある。OSはそういうめんどくさいことの面倒を見てくれて、さらにOSがファイルやディレクトリといったファイルシステムというインターフェースを提供してくれる。ファイルやディレクトリをアプリケーションプログラムで扱い、アプリケーションからOSに命令することで、OSが面倒くさいこと(どのトラックのどのセクタにデータを書き込むのか)をよしなにやってくれる。インターフェースが提供されるおかげで利用者は面倒くさいことを実装レベルで考えなくて済む。インターフェースに入力を渡して呼び出せば良いだけになる。
- 出力装置
- 出力装置とは、デジタルデータの出力を行う装置のこと。
- コンピュータ内のデータをさまざまな形式で出力する。
- 代表的な出力装置としては、デジタルデータを映像として画面に出力するディスプレイ。デジタルデータを音として出力するスピーカーなどがある。
- 入力装置
- ソフトウェアとは、ハードウェアがどのように処理を実行するかの手続きを定義したデジタルデータのこと
- ソフトウェアは大きく分けて2種類に分けることができる
- OS(基本ソフトウェア)
- OSはハードウェアの基本的な動作を定義して、ハードウェアを動作させる役割を担っている
- アプリケーション(応用ソフトウェア)
- アプリケーションは、OSによって定義されたハードウェアの基本的な動作を利用して、ハードウェアの機能をどのように活用するかを定義している
- アプリケーションの代表的な例としては、ChromeやWord、Photoshopなど。
- ソフトウェアを、ハードウェアの動作を定義・管理するOSと、ハードウェアをどのように使うかを定義するアプリケーションに分けることで、利用者はアプリケーションの追加・変更のみでコンピュータを拡張することができる。
- しかし、アプリケーションはOSの機能を利用して動作するため、アプリケーションはOSに依存している。そのため、あるOS用で作られたアプリケーションは他のOSでは動かない
- OS(基本ソフトウェア)
めちゃくちゃ視野が広がった気がする。
要するにコンピュータって、入力されたデジタルデータを処理して、デジタルデータの形式を変換して出力するだけのシンプルな構成なんだな。
そして、OSはハードウェアの基本的な動作を管理していて、アプリケーションはOSによって定義されたハードウェアの機能をどのように使うかを定義しているっていうのがすごくシンプルだけど本質な気がする。
アプリケーションって複雑なことやっているイメージだけど、要するに入力装置で入力された命令(データ)をデジタルデータに変換して、そのデジタルデータをハードウェアのメモリとCPUを使って処理して、ハードウェアの出力装置を利用してデジタルデータの形式を変換して出力しているってだけなんだな。めちゃくちゃシンプルだな。
アプリケーションってなんかすごいことしているイメージだったけど、要するにOSに定義されたハードウェアの機能をどのように使うかを定義しているだけなんだな。ハードウェアをどのように使うかを定義しているだけ。結局、人間はアプリケーションソフトウェアを通じてハードウェアをどのように使うかを定義しているだけなんやな。なるほどねえ
以上のことを踏まえてみて、プログラムの構成を抽象化すると、入力、処理、出力に分けることができるな。すごい
もっと厳密に言い換えるとOSの中にカーネルが存在していて、そのカーネルがハードウェアを管理しているのか。
プログラミング言語について
- 先ほども書いたがアプリケーション自体はソフトウェアなので、デジタルデータで構成されている
- ソフトウェアとは、ハードウェアがどのように処理を実行するかの手続きを定義したデジタルデータのこと
- 人間がアプリケーションを作るにはプログラミング言語を使う。プログラムをコンパイル(もしくはビルド)してバイナリ形式のデータ(デジタルデータ)へと変換することで、コンピュータが実行できるようになる。
- アプリケーションの動作は当たり前だがOSに依存する。そのため、プログラミング言語を用いてアプリケーションを作成するときは、そのアプリケーションが実行できるOSで行う必要がある。
ファイル
- ファイルとは、アプリケーションなどを利用して作成されたデジタルデータをまとめて保存したもの
- ファイルは文章、画像、音声、映像などさまざまなものをデジタルデータ化して保存できる
- アプリケーションそのものもファイルとして保存されている。アプリケーションはソフトウェアであって、ソフトウェアはハードウェアがどのように処理を実行するかの手続きを定義したデジタルデータなんだから、ソフトウェアがファイルとして保存されるのは当たり前か。
- アプリケーションではそれぞれ扱えるファイルの形式が決まっている
- アプリケーションで生成したデータを保存する場合、同じ種類のデータでも、利用目的によって保存形式を使い分けることができる。
センスオブプログラミング読もう
本で説明されていた意識した方が良いこと
- コード群を見て、どんな目的があってこの処理をしているのかを説明できる、考えることができる
- コードの表面的な情報はあまり大事ではない。
- 実装から目的を表すインターフェースがちゃんと想像できるなら、実装レベルの話は必要なくて、目的を考えた抽象レベルの考え方ができている。
- 抽象レベルでコードを理解していないから、別の言語でプログラムを表すことができないのか。コードの表面上から得られる情報しか理解していない。なんでそのコードが書かれているか、コード群が表す目的を理解していない。目的さえわかれば、あとはそれを言語に落とし込めばいいだけ。
- プログラムの流れを制御するよりも、適切なデータ構想を選択できていることが大事
- データ構造の選定をミスると、プログラム全体に大きな影響を与えるため。
データ構造に関しては、現代だとテーブル設計が該当するな。
テーブル設計をミスると、アプリケーション側でどんなに良いコードを書いてもテーブルの影響を受けてしまう。そして、拡張性がなくてビジネスのスケールがしづらくて競合に負けるとかも全然ある。
美しいプログラムとは、何をしているかを日本語で簡潔に説明できるってのはすごく分かるな。ちゃんと目的ベースでうまく抽象化されている気がする。
コンピュータではなぜ2進数が使われているのか
- コンピュータではなぜ2進数が使われているのかというと、数を電気が流れたかどうかで表現することができるため。
- コンピュータは電気を用いて計算をしている。
- そのためには、まず数を電気でどうやって表すかを知る必要がある。
- ある地点aからある地点bに対して電気で数を知らせることをまずは考える。地点aと地点bの間に電線は何本でも貼っても良いとする。
- 電線を3本使って、一の位、十の位、百の位を表す。1という数を5Vとすると、地点aから電気を送って、地点bで電圧を測れば地点bにどんな数が送られたのかが計測できる。
- しかし電圧を測るのがそもそもめんどくさいし、電圧は位置によって変わったりもする。なので、電圧を正確に測ろうとすると結構めんどくさい。
- 1桁を0と1で表す2進法だと、電気が流れたか流れていないかで、数があるかないかを判断できる。電圧を測る必要がない。そのため、電気を用いて計算するコンピュータにおいては2進法が採用された
- コンピュータは電気を用いて計算をしている。
仮想記憶
- 現代的なOSは仮想記憶という機能を持っている。
- 仮想記憶は物理メモリとハードディスクによって構成されている。
- 仮想記憶と仮想アドレスはプロセスごとに割り当てられる
- 物理的なメモリは連番でアドレスが振られている。このようなアドレスは物理アドレスと呼ばれる。
- アプリケーションaとアプリケーションbがLinux OS上で動かしている場合、それぞれのアプリケーションが物理アドレスを指定してメモリへの書き込みを行ったら、最初にメモリの指定したアドレスに保存したデータが上書きされる可能性がある。
- そのようなことを防ぐために、OSは各プロセスに対して、仮想アドレス空間を割り当てている。仮想アドレス空間とは、仮想メモリのアドレスの範囲である。仮想アドレス空間では、各アプリケーションプログラムから見えるアドレスは仮想アドレスである(物理アドレスと一致しない)。
- 他のプロセスのアドレス空間には直接アクセスすることができない。そのため、同じアドレスを指定してメモリ上のデータを書き換えるとかは不可能。
ソースコードとは
- ソースコードとは、プログラミング言語によって記述された、プログラムを表現する文字列である。
- ソースコードが記述されたファイルを、ソースファイルと呼ぶ
- CPUが解釈・実行するプログラムは、機械語で記述されている。機械語にすることで、CPUが実行することができる。
- ソースプログラムを機械語のプログラム(オブジェクトプログラム)に変換するにはコンパイル作業が必要。
- オブジェクトプログラムのままではまだ実行できない。なぜならライブラリなどのコードが含まれていたりするため。
- オブジェクトプログラムとライブラリをリンクさせる必要がある。この作業をリンカが担っている。リンカはリンク作業をすることによって、最終的には実行ファイルを生成する。
インタープリタ
- インタープリタとは、ソースプログラムを直接解釈&直接実行できる仮想的なCPUのようなプログラムのこと。
- 注意点として、インタープリタはコンパイラのように機械語への翻訳はしない。あくまで解釈して実行するだけ。
- インタープリタ自体は何らかのコンパイル方式の言語で記述されている。
- インタープリタを機械語にコンパイルして、CPUで実行することで、インタープリタが機能する。
変数
- コンピュータにおいて、プログラムで使うような一時的なデータはメモリに格納される
- 変数とは、メモリ中のあるアドレスに対して名前をつけたものである。
- 変数のアドレスを取得したいなら、ポインタで取得すれば良い。
変数や関数の命名について
- 「自分が何をしようとしているのか』をきちんと理解しないと、適切な名前はつけられない。
- プログラムの読みやすさという点において、名前は極めて重要な意味を持つ。
- 変数名をすぐに適切に決められない場合、変数が何を表現するかを、はっきり認識できていない。
- 関数名も同様で、関数名がすぐに適切に決められない場合、関数が何を目的とする関数かをはっきり認識できていない。
- つまり、変数名や関数名がすぐに思い浮かばないなら、自分が何をしようとしているのかよくわかっていない可能性がある。
- そのような場合、一旦手を止めて考え直した方が良い。
これは知らなかったな。名前を適切にパッと思いつかない時点で、自分が何をしようとしているのかがすごくぼんやりしているのか。なるほど。。
どんな目的で何をどうやって作るか、どんな仕様で作るかをまず決める必要があるな。
センス・オブ・プログラミング読み終わった。
この著者の文はほんとわかりやすいな。
プログラムはなぜ動くのかを読もうと思ったが、やっぱやめた。
なんか詳しく書きすぎていて、本当に大事な欲しい情報(プログラムはどのように実行されるのか)がわかりづらいんよな。
そもそもプログラムはどうやって実行されているのかざっくり理解する
- プログラムのファイルはハードディスクに存在している。
- ビルドを実行して、機械語で書かれた実行ファイルを作成する。この実行ファイルもハードディスクに保存される。(ビルドはコンパイル処理 + リンク処理)
- プログラムを実行するときは、OSが実行ファイルをメモリに展開する。プログラムはメモリに展開されるとプロセスとして実行される。プロセスは状態を保持しており、プロセスのライフサイクル(生成〜消滅)を管理している
- プロセス内にはスレッドが存在していて、準備ができたスレッドから順番にCPUコアに割り当てられて、処理が実行される。どのスレッドをどのCPUコアで実行するかは、スケジューラが決定する。スケジューラはOSの一部として実行されるプログラムであり、実行すべきタスクやプロセスを管理している。(要はどのスレッドをどのCPUコアに割り当てるののも、OSが決めていると解釈できる)
↓ 参考記事