見出し画像

コンピュータサイエンス学習マップ

前回と前々回で日本ではSI業界とWeb業界ばかりがクローズアップされる(未経験出身が多くプレイヤーの多いフィールドなのもあると思う)ものの、もっとソフトウェアエンジニアの活躍の場はあるし、認知度の高い"汎用的な領域"でなく"専門領域"に面白さを感じる人もいるのでは?というような話を書き、補足記事で学位の有無での選択肢を触れました。

今回は専門領域で最低限求められるコンピュータサイエンス(以下CS)の基礎知識、および実際の仕事に繋がる専門領域のそれぞれの学術分野の科目について、どういった前提知識が求められるか、ということを大学の授業前提科目(prerequisite)の観点から見ていきたいと思います。

特に独学系のエンジニアやスクールでWebの入口を学んだ方も、CSや数学に関係ないプログラムを書いてきた人の参考になると思います。また、CS卒の方や自然科学系の専攻卒の方も学び直しや思い出す機会になれば、と。

今回の記事が脱Webだけエンジニアへのきっかけや専門性の高い職種へ挑戦するための道標になることを願います。職業柄、色んな展示会を見に行ったりもしますが、メーカーとか専門領域で使われてるソフトウェアの技術力ってWebよりはるかに高いと思ったりもします。

履修マップ

まずは簡単にまとめたマップです。左に数学の土台になる知識、順に1~3年に区分されている授業が並びます。3年からはだいぶ専門性で分かれてきて、4年は修士と共通の授業があったり、専門性がかなり高くなるのと中なkボリュームが増えてきたので、一旦2年次までで区切りたいと思います。



CS履修マップ

⊕はorの意味



それぞれ項目分けて説明しますが、やはり重要な部分で言うと離散数学もしくは離散構造を基本として、データ構造へのルートでしょう。ここが応用分野への最初の重要なポイントでほとんどの項目が離散数学か離散構造を前提で求め、そこからデータ構造に繋がります。離散数学(構造)では論理的思考であったり証明方法を学びます。

次に重要なのはそこから続くアルゴリズム分析への矢印です。離散とデータ構造を学んだ上でアルゴリズム分析を経由するのがほとんどの応用分野への前提条件になります。ここでは機械学習入門くらいしか専門分野がマップに入っていませんが(機械学習に力を入れてるせいか、機械学習だけ専門分野でも入門編が早く設置されています)、この先の専門分野はほとんどがデータ構造とアルゴリズム分析が前提になっています。

逆に、なろう系インフルエンサー達のプロパガンダで人気のWEB開発は専門分野のパスと違い、CS概論IIとWEBデザインしか求められず、データベースすらそのあとにくるくらい専門性の低い科目となっています。知るべきことは多いけど浅い印象。英語で言うとディスカッションとかカンファレンス、エッセイで使うようなアカデミックな英語でなく、街中での会話やスラングのような感覚です。変化の速い若者言葉とかのような。前述の記事では言語の基本的な使い方とフレームワーク、ライブラリの使い方を覚えるだけだよね、と。ググってできる仕事的な書かれ方してます。非自然科学系の専攻から来た人がここにたどり着くのは道理かも知れません。ただ、ここを終着点とするのはいかがなものかと思います。

数学

まずは数学からは3科目が前提条件として。

大学レベル代数学

群・環・体などの代数学です。が、その基礎、というべきか。
主に数論的な部分と等式不等式、関数、一次関数、多項式関数、有理関数、指数関数、対数関数辺りが対象のようです。日本だと高校レベルと言えるかも知れない。大体数学IIの範囲ですかね。
https://cnx.org/content/col11759/latest にFreeの教科書があります。OpenStax College textとのこと。

初等関数

初等関数です。

離散数学

プログラミングと一番関りが深そうな数学離散値とは基本的に整数で、例えば、5段階評価の場合の各評価値の整数がそれで、対になる連続値は例えば車の速度。速度は35.0km/hからいきなり40km/hとかになることはなく、数値が繋がっています。離散値はグラフにするとカクカクと境目が直角の四角くなり、連続値は滑らかな線となります。連続値を離散値に変換するのを量子化(quantization)と言ったりします。

正直、小学校でプログラミング教育をするなら、離散数学の入門編をパズル的にやったらいいと思います。離散数学こそ論理的思考の中心となる考え方でコンピュータサイエンスの基礎であって、プログラミングは全然論理的じゃないコードでも動いてしまうし、場面によっては総当たりで動かしながら修正しても正解にたどり着けてしまう。現場で全く論理的じゃない感覚派のエンジニアに会ったことがある人も多いでしょう。文法さえ合っていれば動いてしまうのがプログラムです。離散数学の考え方、および証明手法を早めに身に付けることの方が論理的思考にしてもプログラミングの素養にしてもプラスになる気がします。

離散数学はこの辺がわかりやすいです。P≠NPなどの計算理論の世界にもつながる世界を楽しんでみてください。

もう少し踏み込むならオーム社の2022年の改訂版も。計算理論のオートマトンやチューリングマシンも取り上げてます。

大学一年レベル

コンピュータサイエンス概論I

CSの基礎的なコンセプトの概要であったり、問題解決の取り組み方であったり、ソフトウェアエンジニアリングについて、オブジェクト指向に関して、アルゴリズム設計やプログラム開発について、講義とLabで学びます。課題は主に基礎構文のプログラミングです。

プログラミングに関してはうちの大学ではかつてはC++で今はPythonでやってるようです。下記のような基礎を3か月かけて習います。プログラミングスクールだと1か月もかけずに通る単元かも知れません。

  • 変数とデータ型

  • 代入、入出力、キャスト

  • 条件、繰り返し(iteration)

  • 関数

  • 再帰

  • クラスとオブジェクト

  • 文字列操作、リスト

  • タプル、不変性と可変性

  • 参照と実体

  • ディクショナリとセット

Pythonになってからの課題は見えないのですが、C++時代の課題は見れて、これをまとめていたら時間がかかった&かなりスペース食うので、別記事とします。最初の課題からオーバーフローやアンダーフローを確認するものとかが入っていたりします。スタイルガイドに従わないと減点とかもあります。

コンピュータ・サイエンス概論II

概論の続編、入門編の続きです。主にプログラミングです。
それにしても大学でプログラミング能力身につかない、という人は1年の授業について行けてないのでは…どうやって卒業したんだよ、という感じです。CSの学生にとって基本的なプログラミング能力は言葉を話すのと同じレベルです。応用はまた別の話ですが。

ここでは下記の内容を扱います。

  • モジュール

  • 例外処理

  • 単体テスト

  • 継承、コンポジション、 ポリモーフィズム(多態性)

  • 検索、ソート、アルゴリズム分析

  • ファイル操作、pickleやjsonを使ったオブジェクトのシリアライズ

  • 再帰詳しめに

  • リンクドリスト、スタック、キュー

  • ジェネレイター

  • 第一級関数

  • デコレイター

シノニムまではいかないですが、基礎構文以外の言語仕様の部分とか基本的なプログラミング手法を学びます。

ここまでやったら、日本の経験だけの非自然科学系エンジニアと大差ない土台になると思います。ちなみに大学一年で身に付ける知識です。

Webデザイン

取ってない(大学院のための必修ではない)のですが、もはや2年前から一度も設けられてない授業でした。自分も高校時代に独習しましたが、HTMLとかCSSなので、記法を学ぶだけという感じで3か月も授業作るのは厳しいのでしょう。Webサイト管理の前提科目になってますが、そっちも開設されてないですね。クラウドの時代にはそぐわないから、ということでしょうか。

あれ、つまり、Web開発の前提科目が概論だけになってしまった…。

大学二年レベル

1年で現在用意されている科目はプログラミングの基礎中心で後は数学のバックグラウンドを整える感じみたいですが、ここから少し専門性が出てきます。

離散構造

離散数学をCS寄りでやるイメージの科目です。取ってないので公開情報からのみですが。これか離散数学がデータ構造の前提科目になります。また、ここで学ぶ証明の知識はアルゴリズム分析でもよく使われます。帰納法と背理法辺りがよく使われますが、併せて鳩ノ巣理論であったり、対角線論法なんてのも使われたりします。その辺も離散数学や離散構造で学ぶものなのかな、と。漸化式とかも扱うと思いますが、帰納法による帰の定義とかは式で表せたほうが良いでしょう。

シラバスから、カバーする内容として下記が挙げられています。

  • 論理式

  • 集合、順序構造、和集合

  • 帰納法以外の証明手法

  • 帰納法による証明

  • 再帰的定義

  • 組み合わせ

  • グラフ

離散数学に関しては前述を参考にして頂ければという感じですが離散構造は下記のようなテキストもあります。結構数学的で、特に前半は心が折れそうになるかも知れませんが、この一冊で学部レベルのコンピュータサイエンスの"理論的な部分"の基礎は結構網羅できるかも知れません。特に、経験だけ中堅エンジニアの方は一読をお薦めします。大学二年生で知るべき理論的な基礎です。

データ構造

コンピュータサイエンスの基礎の最初の柱です。
普段誰もが使っているリストや配列、マップですが、メモリ上どうなっているのでしょうか?それぞれの処理の速度など、特性を理解して利用しているでしょうか?

配列で最初にサイズがわからないケースの場合など、実は裏側でデータの再配置が行われたりします。配列は連続したメモリアドレスにデータが配置されるので、確保した領域を超えると連続性が保証できないため、領域を再確保してデータを再配置したりします。ただ、一定のサイズではなく…などなど。その場合の計算量がどうなる、とか。ハッシュを使った場合にハッシュに応じた場所にデータが配置されますが、被った場合はどうなるか。サイズが想定を超えたら?そういったことも学びます。

データ構造はAbstract Data Type(ADT)が定義されてたり、とかという話もあります。データ構造は別途記事を設けて連載で解説しようと思いますが、コースでは下記がカバーされています。

  • ADT(ついでにQueue, Stack, Deque)

  • ビックオー記法

  • 動的配列

  • 連結リスト

  • Iterator

  • 二分検索

  • 木構造

  • 二分木・二分探索木

  • 平衡探索木(AVL木)

  • 優先度付きキュー

  • ヒープ

  • Map

  • Hash Table

  • グラフ

課題では動的配列や連結リスト、Hash Table(hash関数は提供された)の骨組みを渡されて関数の中を埋めるやつをCで実装しましたが、今はPythonでやってるみたいですね。

他にも、競技プログラミングとかで知ってると便利なBinary Indexed TreeとかSegment Treeなんてのもあったりしますが、その辺は下記の本とか面白いと思います。

https://book.mynavi.jp/ec/products/detail/id=22672

データ構造や基本中の基本と言えますが、Googleの試験でもかなりの確率で聞かれるので、重要な項目と思って下さい。

コンピュータアーキテクチャとアセンブリ言語

意外といかついのが2年にいました。
アーキテクチャ系の入門クラスですね。
下記を扱うようです。

  • アセンブリ言語

  • アドレス

  • スタック

  • 引数渡し

  • 算術演算

  • 決定

  • マクロ

  • モジュール化

  • リンカー

  • デバッガー

ほぼ毎週のアセンブリ実装の課題を通して、レジスタの使われ方やスタックの積み方とか、ライブラリの作られかたとかを学ぶようです。2年時にこの辺ある程度理解してると確かに強いかも知れない。と言っても、上位クラスがあるので、ここでは触り程度かも知れません。

Web開発

流行りの"最強"というWeb開発は2年次にあります。前提科目はほぼありません。というか、実施されてないので実際は何もありません。専門性は非常に低いです。一時Railsとか使われてたっぽいけど、今はJsが主流みたい。
コンテンツは下記です。

  • Github

  • HTML

  • CSS

  • JavaScript基礎

  • JavaScriptでのDOM操作

  • JavaScriptでのイベントハンドリング

  • Node.js基礎

  • パッケージとnpm

  • サーバー/クライアント構築

  • Handlebars(テンプレートエンジン?)での動的なコンテンツレンダリング

  • 非同期サーバー・クライアントコミュニケーション

  • MongoDB

MySQLを使うところもあるみたい。基本的にはクライアン・サーバーとかを勉強するには立地すぎるWebフレームワークは向きません。CSとしては原理を理解して動かす、なので、その辺の匙加減もあってJsなのでしょう。

最後に

今回はコンピュータサイエンス学習マップの学部編2年次までをお送りしました。3年に踏み込むと2倍以上になりそうで、いつもより短めになりました(時間かかったけど)。今回は概略であって、各科目に関しては別で解説していければと思っていますが、今回記事を書いていて専門性とは何か、という事を考えました。

専門性の深さとは、その対象領域を学習したり論じたりするのに必要になる予備知識であったり、そこからくる情報の圧縮度ではないでしょうか。計算量が当たり前のように出てくる領域でアルゴリズム分析がわからないと話にならないですし、正しさを証明するためには証明するための手法を知っていないと難しいです。それ以外でも、並列処理を"正しく"動かすためにはメモリやキャッシュの知識や、それに伴うアセンブリの知識を求められたりします。

コンピュータサイエンスの基礎というのは、そういった予備知識や前提知識というものを付けることを目的に学ぶものかな、と。そこを土台に専門領域に進みます。なので、CS卒の人というのは結構身軽に複数の専門領域を行き来できます。基礎がない人は専門領域をまたいだ途端に土台から作り直しです。更に先進的な旬で価値のある技術は専門性が高く、多くの土台の上に立っていることも多いです。それはCSだけでなく数学領域にも踏み込んで、例えば機械学習は数学が半分くらいの柱になっていたりするので、数学専攻や物理専攻の方がCSの理論系でなく実装系の領域に強い人より理解が早かったりもします。

プロとして働いているなら、よりできることが多い方が良いと思うし、それ以上に、他の人ができない、知らないことがある方が価値のある人材と言えるし、そうなりたいと思うのが普通だと思ってしまうのはおかしいのでしょうか?何より、深入りするほど楽しくなる世界で、技術力で不可能を可能にしてきたのがITの世界です。楽しく働きたいなら知ってることやできる事が多い方が良いと思ってしまう世界線の人です。

僕も未経験から始めました。仕事を通じてモノづくりの楽しさに目覚め、本気でこの業界で働いて技術を楽しみつくしてやろう、とアメリカ留学して大学院を出ました。同じようにこの業界が楽しいと思える人、もっといろんなことができるようになりたい、と思う人の参考になる記事、また専門家だから書ける記事を書いていきたいと思います。

逆に、慣れた仕事を繰り返すだけでそこそこの給料をもらえればよい、という人は僕の記事は余計なお世話に聞こえるでしょう。ただ、同じようなことを繰り返すなら自動化しよう、というDRY(Don't Repeat Yourself)の原則がエンジニアの基本です。そういう仕事は自動化で消えるのを覚悟した方がよいです。

ちょっと今、プライベートがバタバタしていますが、続きは今月後半か来月頭を目途に書ければと思います。長い、かつ余計な事(個人的にはスパイスのつもりだけど)も多い記事ですが、ぜひまた読んでください。

この記事が気に入ったらサポートをしてみませんか?