大学の授業では理論的な基盤を教えることが多く、実務的な知識はあまり教えないのが普通である。 しかし実際に研究・実験・就職をする場面になると、学校では教えない多くの知識が必要になる。 残念ながら、現在の大学にはこれらを体系的に教えるようなカリキュラムは存在せず、多くの学生は独学か、研究室の先輩などから教わることになる。 ここではそうした知識のうち重要と思われるものを記した。なお、プログラミング言語や業務システムに関する知識は除いてある。 また、知識は「○○を勉強せよ」などという漠然とした指示ではなく、できるだけ具体的な例を挙げた。
もちろん、これらに加えて大学の授業 (線型代数、アルゴリズム、統計、型理論など) も きちんと学ぶ必要がある。 企業などでは実践的な知識がなければ「使えない人」とみなされてしまうが、 実践的な知識だけあっても理論的な基盤がなければ「将来性のない人」になってしまう。 注意しよう。
情報系の学生にとって、英語の読み書きができない・遅いことは 致命的 なハンデである。 英語では情報量が圧倒的に多いうえに、更新も早く、議論も活発だからである。 日本語の情報は少ないうえに遅れており、技術的な議論もほとんどない。 YouTubeなどでも、英語ではかなり良質の教材が入手できるし、Wikipedia英語版も記事の品質が高い。
- 技術的・学術的な文書を読んで理解できること。
- 例: https://cs231n.github.io/ をざっと読んで、有用そうなセクションを発見せよ。
- API説明文書、StackOverflow の質問・回答が読めること。
- 例: https://docs.python.org/3/library/ から自分の目的のモジュールの使い方を調べよ。
- 英語で検索できること。
- 例:「正規表現 使い方」「SQL 文法」を英語で検索し、役に立ちそうなページを発見せよ。
- 数学的な表現を英語で読み書きできること。
- 例: 「xが正であると仮定すると、どんなxに対しても 2のx乗が1より大きい」を言葉だけで数式を使わずに英訳せよ。
- IRC・フォーラム (Redditなど) で、質問とお礼が書けること。
- YouTubeなどで英語の技術的なトークを理解できること。
たいていの大学では課程修了までに1つか2つのプログラミング言語を学習するが、 簡単な課題をこなしたのみでは実際的なプログラムは全く不可能である。どの言語を使うにせよ、 プログラミング言語と現実世界とのやりとりをする方法を学ばなければ現実のソフトウェアは書けないし、 アルゴリズムも自力でコードにできなければ理解したことにはならない。
- 最低ひとつのGUIフレームワークを使ったプログラム作成 (HTML5、Windows Forms、Java AWTなど)。
- ちなみにここでいう「プログラム」は実用的なものであり、Hello World!程度のものではない。たとえばカレンダーを使ったスケジュール管理帳などはよい例題である。
- 最低ひとつのデータベースの使い方 (SQLite, MySQL, PostgreSQL)、SQL文法の基礎。
- テーブルの設計からCRUD全般の実装までやること。GUIの例で示したスケジュール管理帳はSQLの例題としても使える。
- ハッシュテーブルおよびなんらかの探索木 (B-treeは面倒なので 2-3-treeなど) の自前の実装ができること。
- 動的計画法の実装ができること。
- 例: Dijkstraの最短経路アルゴリズム、あるいは編集距離の計算。
- 正規表現の書き方と、簡単なパターンを受理する構文解析器を自前で実装する方法。
- 例: 引用符つきのCSVをパーズする関数を書く。
- 木構造に対する再帰を使った深さ優先探索、およびキューを使った幅優先探索の実装方法。
- あるアルゴリズムのおおまかな計算量、メモリ使用量を見つもってO記法で書けること。
- Cにおける(スタックを用いた)引数渡しの方法と動的リンクの仕組みを理解していること。
- x86アセンブリに関する基本的な知識。
- 例:
objdump
/dumpbin
の逆アセンブル出力をおおまかに理解できるか?
- 例:
- マルチスレッド (pthread、Win32 thread あるいは Java thread) の使い方、スレッド間同期の方法。
- プロセスの実行時間・メモリ使用量、I/Oアクセス時間などの測定方法。
- デバッガの使い方。
- 例: ブレイクポイントの設定、変数の値確認、スタックフレーム間の移動。
計算機プログラムのほとんどは、つまるところデータの作成および処理をおこなうものであるから、 データの内部構造について知っておくと便利である。ある形式について、複数の異なる見方 (高水準の解釈、およびバイナリレベルの解釈)を知っておくと、そのデータを処理する プログラムの作成あるいは診断に役立つ。データ形式に関する知識は、機械学習やデータサイエンスを 志す人々にとっては、今後ますます重要になってくるだろう。
- 2進数、10進数、16進数の手計算による変換。
- 例: 10進数の99を手作業で2進数、16進数に変換せよ。
- 整数、浮動点小数のバイナリ表現。
- 例: -0.75はIEEE-754形式でどのように表現されるか?
- UnicodeとUTF-8(文字集合と符号化方式)の区別、BOMと改行コードの具体値。
- 無圧縮ビットマップ画像の格納方法。
- 例: カラーBMP画像を大津の方法を使って白黒2値BMPに変換せよ。
- 圧縮あるいはアーカイブファイル (zip, gzip, tar) の原理と作成方法。
- JPEG, MPEG など離散フーリエ変換を使った非可逆圧縮のおおまかな原理と制限。
- 実行可能バイナリ (ELFあるいはWindows PE形式) の大まかな構造。
- HTML/XML/JSONの基本的な文法。DTDとは何か。Entityを指定する方法。
UNIX/Linuxはただ「見た目の変わったOS」ではない。UNIX/Linuxを 日常的な文書作成などに利用する人もいるが、(Windowsと比べて) 一番の利点は 複雑なファイル管理や処理の自動化、および オープンな内部構造 である。 これはプログラム開発時や実験にとくに有用である。ソースコードを含めて内部の 多くが公開されているため、改造(カスタマイズ)して使うのが一般的である。
- カーネル、ディレクトリ、プロセスなどの基本的な概念。
- 基本的なコマンド、エディタおよび awk の使い方。
- 実行パス、標準入出力、環境変数とはなにか、またどうやって変更するか。
- シェルの基本的な使い方、シェル引数展開のしくみ。
- シェルスクリプトを使った変数、条件分岐、繰り返しの方法。
- Cコンパイラの使い方と Makefile の書き方。
- 最低ひとつ以上のスクリプト言語 (例: Python) で、自動処理をおこなう簡単なプログラムが書けること。
- Gitの使い方基本。
- 例: 新しいブランチを作成し、いくつかコミットを加えてもとのブランチに統合せよ。
コンピュータからみればネットワークは1つの入出力装置にすぎない。 最近のソフトウェアの多くはネットワークを使うことが前提として作られているものが多いが、 実際にはこれは非常に複雑な「装置」であるため、完全にブラックボックスとして扱うことは できない。ある程度の仕組みを理解しておくことが必要である。
- TCP/IPの4層のおおまかな原理、ルーティングの原理、NATおよびファイヤーウォールの仕組み。
- DNSの名前解決に関する知識。
- 例: ja.wikipedia.org のIPアドレスを再帰検索によって求める手順を説明せよ。
- WiFiつき家庭用ルータを設定できるだけの知識。
- 例: サブネットマスクの働きを説明せよ。
- 有名なプロトコル (DNS, HTTP, SMTP など) の基本的な動き。
- ネットワーク監視ツール (tcpdump, Wiresharkなど) の使い方。
- 公開鍵暗号およびDH鍵交換の仕組みと SSL証明書の確認方法。
- ソケットを使った非同期的な(複数クライアントを同時に受け付ける)プログラムの作成方法。
ソフトウェアの動作環境はOSに依存するので、プログラマはOSに関して ある程度の知識が必要である。また、パソコンを購入して自分用に整備するために システム管理の知識も必要である。(しかし、このためにPCを自作したり、RaspberryPiを買ったりする必要はない。)
- CPU、メモリ、PCIe、SATA、Ethernetなどの実物・ソケットを知っていること。
- 最低ひとつのLinuxディストリビューションのインストール方法。
- ユーザ名、現在時刻、IPアドレスなどの変更方法。
- 新しいディスクの接続およびフォーマット方法。
- /etc, /dev, /var などのディレクトリの用途と、各設定ファイル・ログファイルの位置。
- /procファイルの中身とシステム監視コマンド (top, vmstatなど) の読み方。
- Linuxブートプロセスのおおまかな理解 (BIOS/UEFI)。
- おもな各デーモンプロセスの役割、デーモンの起動と終了方法。
- SSHクライアントの使い方と、SSHサーバの設定方法。
こんにち、Webは汎用UIとしての位置を占めている。そのため、たとえWeb開発そのものが目標でなくても、 プレゼンテーション用に簡単なWebアプリが設計できることには大いに意義がある。
- HTTP(S)の基本的なステータスコードとその意味。
- 基本的なHTMLとCSSを手書きしてページ作成できること。
- HTML DOMの原理と JavaScript による簡単な制御プログラムが書けること。
- Cookieの使われ方、その他ユーザ特定の方法についておおまかな知識があること。
- 最低ひとつの Webサーバの実行方法、およびログの解析方法。
- なんらかのRESTful APIの動きとそれを利用する簡単なスクリプトの作成。
- 例: GitHub, Twitchなどから特定のユーザ情報を取得してみる。
日本では何かとハードウェアを偏重する傾向があるが、ソフトウェアの専門家を目指すのであれば、 ハードウェアの知識は実はそれほどなくてもよい。たとえば電子回路に関する知識はほとんど必要ない。 が、ハードウェアの性能がソフトウェアの設計に大きく影響してくる場合があり、そこは把握している必要がある。
- 平均アクセス時間 (メモリ、ディスク、ネットワーク) を知っていること。
- バスの原理と、よく知られたシリアル通信の規格 (USB, Ethernet) のおおまかな理解。
いまのところ、上に挙げたような知識すべてを体系的に学習できるような書籍は (英語でも日本語でも) 存在しない。しかし、こうした知識はどれもWeb上に散在している 資料から学習できるので、まず最初にすべきことは「英語の特訓」ということになるだろう。 基本的には、センター試験レベルの英語力があれば十分なので、あとはひたすら資料を見つけて 英語で読む、というプロセスを繰り返すのがよいと思われる。もちろん実践もしなければ身につかないから、 実際に手を動かしながら進むことになるだろう。大学4年間のあいだにやることはたっぷりある。
そして卒業後はもちろん、この業界を目指すものの定めとして、次々と生まれる新しい技術を生涯学習しつづけることになる。 ようこそ情報系の世界へ。