WEB+DB PRESS plusシリーズコーディングを支える技術
――成り立ちから学ぶプログラミング作法

[表紙]コーディングを支える技術――成り立ちから学ぶプログラミング作法

紙版発売
電子版発売

A5判/264ページ

定価2,717円(本体2,470円+税10%)

ISBN 978-4-7741-5654-5

電子版

→学校・法人一括購入ご検討の皆様へ

書籍の概要

この本の概要

本書は,プログラミング言語が持つ各種概念が「なぜ」存在するのかを解説する書籍です。
世の中にはたくさんのプログラミング言語があります。そしてプログラミングに関する概念も,関数,型,スコープ,クラス,継承など,さまざまなものがあります。多くの言語で共通して使われる概念もあれば,一部の言語でしか使われない概念もあります。これらの概念は,なぜ生まれたのでしょうか。本書のテーマは,その「なぜ」を理解することです。
そのために本書では,言語設計者の視点に立ち,複数の言語を比較し,そして言語がどう変化してきたのかを解説します。いろいろな概念が「なぜ」生まれたのかを理解することで,なぜ使うべきか,いつ使うべきか,どう使うべきかを判断できるようになるでしょう。そして,今後生まれてくる新しい概念も,よりいっそう理解しやすくなることでしょう。

こんな方におすすめ

  • 一通りコードを書けるが,きれいなコードを書けている自信は持てない社会人1~2年目の新人プログラマ,学生

著者の一言

関数やクラスなど,プログラミング言語のいろいろな概念が「なぜ」生まれたのかを解説する本です。「なぜ」を知ることで,どう使えばよいか判断できるようになります。また,新しい概念も理解しやすくなります。

本書に関するお知らせ

本書に関連する記事を公開しております。

この書籍に関連する記事があります!

はじめに
世の中にはたくさんのプログラミング言語があります。読むべきドキュメントもたくさんあります。しかしあなたの使える時間は有限です。すべてを学ぶことはできません。
なぜ言語設計者はこの文法を作ったのか
世の中にはたくさんのプログラミング言語があります。そしてプログラミングに関する概念も,関数,型,スコープ,クラス,継承など,さまざまなものがあります。

目次

  • はじめに
  • 謝辞
  • 本書の構成
    •  サンプルコードのダウンロード

第1章 言語を深く効率的に学ぶには

1.1 比較から学ぶ

  • 決め事は言語によって異なる
  • C言語とRubyにおける真偽値
  • Javaにおける真偽値

1.2 歴史から学ぶ

  • 言語設計者の意図を理解する
  • どの言語を学ぶべきかは誰にもわからない
  • 言語に依存しない普遍的な知識を学ぶ

1.3 まとめ

第2章 プログラミング言語を俯瞰する

2.1 プログラミング言語誕生の歴史

  • ケーブルをつなぐ
  • プログラム内蔵方式へ
  • FORTRANの登場

2.2 プログラミング言語の生まれた目的

  • 無精 ──プログラマの三大美徳の一つ
  • 言語により異なる「楽さ」の意味
    •  何を楽にしたいのか
    •  どんなプログラムを書くのを楽にしたいのか

2.3 まとめ

第3章 文法の誕生

3.1 文法って何だろう?

  • 演算子の優先順位
  • 文法は言語設計者が決めたルール

3.2 スタックマシンとFORTH

  • 計算の流れ
  • 計算順序をどう表現する?
  • 現代にも生きるスタックマシン

3.3 構文木とLISP

  • 計算の流れ
  • 計算順序をどう表現する?
  • 現代にも生きる構文木
  • 【Column】理解を確認するためにはまずアウトプット

3.4 中置記法

  • 構文解析器
  • 【Column】何を学べがよいかがわからない理由
  • ルールの競合

3.5 まとめ

第4章 処理の流れのコントロール

4.1 構造化プログラミングの誕生

4.2 ifが生まれる前

  • ifはなぜあるのか
  • if……elseはなぜあるのか
    •  アセンブリ言語での表現方法
    •  C言語での表現方法
    •  if……elseを使うメリット

4.3 while ──繰り返しのifを読みやすく表現

  • whileを使った表現方法
  • whileを使わない表現方法

4.4 for ──数値を増やしながらのwhileを読みやすく表現

  • forを使った表現方法
  • forを使わない表現方法
  • foreach ──処理の対象で繰り返しを制御

4.5 まとめ

第5章 関数

5.1 関数の役割

  • 理解 ──組織のたとえ
  • 再利用 ──部品のたとえ
  • プログラムにおける再利用の特徴

5.2 戻る命令

  • 関数の誕生
  • 戻る先を記録する専用のメモリ
  • 【Column】名前
  • スタック

5.3 再帰呼び出し

  • 入れ子構造のデータを効率的に処理
  • 入れ子構造を扱う方法
    •  forでは表現できない
    •  再帰呼び出しを使う
    •  再帰呼び出しの実行の流れ

5.4 まとめ

第6章 エラー処理

6.1 プログラムも失敗をする

6.2 失敗をどうやって伝える?

  • 返り値で失敗を伝える
    •  失敗を見落とす
    •  エラー処理のせいでコードが読みづらい
    •  ジャンプでエラー処理をまとめる
  • 失敗したらジャンプする
    •  UNIVAC Iの場合
    •  COBOLの場合
    •  PL/Iの場合

6.3 失敗しそうなコードを囲む構文

  • John Goodenoughの主張
  • CLUへの導入
  • C++への導入
  • Windows NT 3.1への導入

6.4 出口を1つにしたい

  • なぜfinallyを導入したのか
  • 対になる処理を確実に行いたい
    •  finallyによる解決
    •  finallyのないC++での解決
    •  D言語のscope(exit)による解決

6.5 どういうときに例外を投げるか

  • 関数呼び出し時に引数が不足している場合
  • 配列の範囲外を取得しようとした場合
  • 間違えたらすぐに例外を投げてほしい

6.6 例外の伝搬

  • 例外が伝搬する問題点
  • Javaの検査例外
  • 検査例外が普及しない理由
  • 【Column】具体的な知識と抽象的な知識
  • 【Column】噛み砕く

6.7 まとめ

  • 【Column】必要なところからかじる

第7章 名前とスコープ

7.1 名前はなぜ必要だったか

  • どうやって名前を付けるか
  • 名前の衝突
  • 衝突を回避するには
    •  長い変数名を付ける
    •  スコープを利用する

7.2 スコープの進化

  • 動的スコープ
    •  どのように動作するか
    •  問題点
  • 静的スコープ
    •  動的スコープは対応表がコード全体から読める
    •  静的スコープは関数ごとに対応表を分ける

7.3 静的スコープは完成形?

  • 【Column】ほかの言語でのスコープは?
  • ネストした関数の問題
  • 外のスコープへの再束縛の問題
    •  Pythonでの解決方法
    •  Rubyでの解決方法

7.4 まとめ

第8章 型

8.1 型とは何か

8.2 数値をオンとオフで表現する方法

  • 位取りの発明
  • 7セグメントディスプレイ
  • そろばん

8.3 1つの位に必要なランプはいくつか?

  • 10進法から2進法ヘ
  • 8進法と16進法
    •  8進法
    •  16進法

8.4 実数はどうやって表現しよう

  • 固定小数点数──小数点がどこに付くか決める
  • 浮動小数点数──どこからが小数部かの情報自体を値に含める
    •  どのような考え方か
    •  IEEE 754で定められた浮動小数点数のしくみ
    •  問題点

8.5 型は何のため?

  • ないとどう困るのか
  • 初期のFORTRANでの型
  • 言語処理系に変数の種類を教える
  • 暗黙の型昇格
    •  整数同士,浮動小数点数同士の演算
    •  片方が整数で片方が浮動小数点数の演算
    •  問題点
    •  書き方で区別する言語

8.6 型のいろいろな展開

  • ユーザ定義型とオブジェクト指向
  • 仕様としての型
    •  公開と非公開を分ける
    •  インタフェースへの発展
    •  型ですべての仕様を表現する世界が来るか
  • 総称型,ジェネリクス,テンプレート
    •  C++の場合
    •  Javaの場合
    •  Haskellの場合
  • 動的型付け
    •  どのように実現しているか
    •  メリットとデメリット
  • 型推論
    •  Haskellと型推論のないC言語の比較
    •  Haskellの型推論
    •  Scalaの型推論
    •  強い型でバグのないプログラムが作れるか

8.7 まとめ

  • 【Column】おおまかにつかんで徐々に詳細化する

第9章 コンテナと文字列

9.1 いろいろな種類のコンテナがある

9.2 なぜいろいろな種類のコンテナがあるのか

  • 配列と連結リスト
    •  配列に値を挿入する場合
    •  連結リストに値を挿入する場合
    •  連結リストの模式図
  • 連結リストの長所と短所
  • 【Column】O記法──計算時間とデータ量の関係を簡潔に表す
  • 言語による違い

9.3 辞書,ハッシュ,連想配列

  • ハッシュテーブル
  • 要素を取り出す時間
    •  木の場合
    •  ハッシュテーブルの場合
  • 万能のコンテナはない

9.4 文字とは何か

  • 文字集合と文字符号化方式
  • コンピュータ以前の符号化
    •  モールス符号
    •  ボーコード
  • EDSACの文字コード
  • ASCIIとEBCDICの時代
  • 日本語エンコーディング
    •  ISO-2022-JP
    •  Shift_JIS
    •  EUC-JP
  • Shift_JISがプログラムを壊す
  • マジックコメント
  • Unicodeによる統一

9.5 文字列とは何か

  • 長さの情報を持つPascal文字列,持たないC文字列
    •  NUL文字で文字列の終わりを表現する
    •  NUL文字にまつわる不具合の例
  • 1文字16bitのJava文字列
  • Python 3で行われた設計の変更
  • Ruby 1.9の挑戦

9.6 まとめ

第10章 並行処理

10.1 並行処理とは何か

10.2 細かく区切って実行する

10.3 処理を切り替える2通りの方法

  • 協調的マルチタスク──切りの良いところで交代する
  • プリエンプティブマルチタスク── 一定時間で交代する

10.4 競合状態を防ぐには

  • 競合状態の3条件
  • 共有しない──プロセスとアクターモデル
    •  プロセスではメモリを共有しない
    •  共有しないアプローチは成功したか
    •  アクターモデル
  • 書き換えない──const,val,Immutable
  • 割り込まない
    •  協調的なスレッドを使う──ファイバー,コルーチン,グリーンスレッド
    •  割り込まれると困る処理中は印を付ける──ロック,ミューテックス,セマフォ

10.5 ロックの問題点と解決策

  • ロックの問題点
    •  デッドロックが発生してしまう
    •  合成できない
  • トランザクショナルメモリによる解決
  • トランザクショナルメモリの歴史
    •  ハードウェアによる実装
    •  ソフトウェアによる実装
  • トランザクショナルメモリは成功するか

10.6 まとめ

第11章 オブジェクトとクラス

11.1 オブジェクト指向とは何か

  • 言語によって違う「オブジェクト指向」の意味
  • オブジェクトは現実世界の模型
  • クラスとは

11.2 変数と関数を束ねて模型を作る方法

11.3 方法1 モジュール,パッケージ

  • モジュール,パッケージとは何か
  • Perlのパッケージでオブジェクトを作る
  • モジュールだけでは足りない
  • データ置き場は個別に
  • 引数に個別のハッシュを渡す
  • 初期化の処理もパッケージに入れる
  • ハッシュとパッケージを結び付ける
  • 11.4 方法2 関数もハッシュに入れる

    • ファーストクラス
    • 関数をハッシュに入れる
    • 複数のカウンタを作る
    • 共有してよいモノをプロトタイプに移す
      •  プロトタイプの動作
      •  new演算子で効率的に記述する
    • これがオブジェクト指向?

    11.5 方法3 クロージャ

    • クロージャとは
    • なぜクロージャと呼ぶ?

    11.6 方法4 クラス

    • Hoareの考えたクラス
    • C++のクラス
    • 仕様としての役割
    • クラスが持つ3つの役割

    11.7 まとめ

    第12章 継承によるコードの再利用

    12.1 継承とは

    • 継承に対するさまざまな考え方
      •  一般化/特殊化
      •  共通部分の抽出
      •  差分実装
    • 継承は諸刃の剣
    • リスコフの置換原則

    12.2 多重継承

    • 1つのモノを複数の分類に
    • 実装の再利用に便利な多重継承

    12.3 多重継承の問題点──またしても衝突!

    • 解決策1 多重継承を禁止する
      •  委譲
      •  インタフェース
    • 解決策2 メソッド解決順序を工夫する
      •  深さ優先探索の問題点
      •  C3線形化で順序を決める
    • 解決策3 処理を混ぜ込む(Mix-in)
      •  Pythonの場合
      •  Rubyの場合
    • 解決策4 トレイト
      •  名前が衝突したときの振る舞い
      •  提供するメソッドと要求するメソッド
      •  ほかにもいろいろな機能が……
      •  トレイトが広まりつつある

    12.4 まとめ

    • 【Column】端から順番に写経する

著者プロフィール

西尾泰和(にしおひろかず)

サイボウズ・ラボのエンジニア。個人やチームの生産性をどうすれば高めることができるかを研究し,未来のグループウェアの研究開発をしている。プログラミング言語の多様性と進化にも強い関心があり,2013年に出版した『コーディングを支える技術』はベストセラー,重版を経て,韓国語版が出版された。