CS 学部(あるいは CS 系研究科)の学生は卒業時にどんなスキルを持つべきでしょうか?CS の大学院を修了する研究生は何を身につけるべきでしょうか?
専門科目で学ぶ知識以外に、ここでは CS 系が備えるべき「基本素養」についてきちんと議論したいと思います。

はじめに

私は学部では CS ではなく、大学院から CS を学びました。大学院に入る前のプログラミング学習ルートは非典型です(〈私がコンピュータサイエンスに興味を持つまで〉を参照)。大学 1 年のとき、先輩の助言でプログラミングに興味を持ち始め、その後は独学で入門知識の多くを身につけました。複数のソフトウェア会社でインターンをしたり OSS に貢献したりする機会もありましたが、大学 3 年後期〜4 年前期になってようやく CS 学科の授業を本格的に履修し、大学院に入ってから本当の意味で「CS の本科生」になりました。

この特殊な学習経路のおかげで、周囲の同級生の中に「重要だと思う基本素養が欠けている」人が少なくないことに気づけました。CS 学生が卒業までにこれらを身につけないのは、もったいないと思います。自画自賛に聞こえないように正直に言うと、私自身も欠けている部分があるので、自分への戒めでもあります。

私が考える基本素養は次の 5 点です。

  • 開発とデバッグのスキル
  • 良いコーディング習慣とスタイル
  • コードを読む力
  • 開発の協調とプロセス
  • コンピュータに関する基本知識全般

本記事以外にも、私の教育動画シリーズ「拯救資工系學生的基本素養」も参考にしてください

開発とデバッグのスキル

プログラミング自体は誰でも書けますが、上手く書くのは難しいです。CS 学生である以上、コーディング能力をきちんと鍛えるべきだと思います。C++、Python、JavaScipt などの言語の特性をできるだけ理解し、余裕があれば C++ PrimerEffective C++Effective Python といった上級の本も参照してください。検索すれば、強い人たちが独自の書籍リストを共有しています。さらに、良いコードを書くには多くの知識の組み合わせが必要です。標準ライブラリ(STD)の活用、データ構造とアルゴリズム、デザインパターン(Design Pattern)などです。

クラスメイトの中には、C++ の達人がいて手が届かないほど強い人もいるでしょう。言語特性を熟知し、他人の Spec になれるレベルです。そこまでの「神」になるのは難しいので必須ではありませんが、良い会社ほど同僚の言語理解は深いと私は感じます。これは一生食べていくための道具なのだから、流暢に使えるようになるべきです。

コードを書く以上、バグは避けられません。数日間デバッグして本当に死にたくなることもあります。ではどうデバッグしますか?まだ print を乱発していますか?デバッグツールを使えるようになり、さらにうまく使えば開発はずっとスムーズになります。GDB に限る必要はなく、今は IDE でも優れたデバッグ機能があります。概念は同じで、目的を達成できればよいのです。

print は簡単で便利ですが、デバッガでブレークポイント(Breakpoint)を置けるなら、欲しい情報をより簡単に得られます。バックトレース(Backtrace)でフレーム(Frame)を辿り、ポインタや値の受け渡しの変化を観察できるからです。効率が良いと思いませんか?どこが本当の原因かを素早く判断する力は重要です。

最後に各種開発ツールを活用しましょう。良いテキストエディタ(私は VSCode)や IDE、そして静的解析、自動整形、構文提案、自動補完など便利な拡張機能です。また、Windows、macOS、Linux のいずれでも開発する可能性があるので、各プラットフォームに適したツールを学ぶのも大切です。Vim を学ぶのも強くおすすめします(Emacs 勿戦🤣)。普段は IDE があっても、サーバ上で直接コードを修正する必要が出てくることがあります。そのとき Nano だと少し不便かもしれません。

良いコーディング習慣とスタイル

「10 万行のコードを書いていないなら CS 学生とは言えない」という話があります。私は少し疑っています。授業の課題量ではなかなか到達しないでしょう。ただ別の角度から言えば、「1 万時間で専門家になれる」という俗説があります。その時間はだいたい 10 万行のコードに相当するのかもしれません。しかし重要なのは、雑然としていて動けばいいだけのコードではなく、良いコードを書くことです。

良い習慣とスタイルは、簡潔なコード(Clean Code)とも呼ばれます。コードは自分だけが読むものではありません。他人が一目で分かること、そして数年後に自分が見返しても茫然としないことが重要です。美しいコードはコメントなしでも意図が伝わります。

書き方はテストの書きやすさにも直結します。設計されていないコードはテストが非常に難しく、そのためテスト駆動開発(Test Driven Development, TDD)という概念もあります。必ずしも TDD をやる必要はありませんが、「将来テストを書きやすいか」「デバッグしやすいか」を常に意識すべきです。答えが No なら、習慣とスタイルは改善の余地があります。

良い習慣を身につけるには、強い人のコードを読み続け、差分を考え続けるのが良いです。また、『Clean Code』のような本を読み、悪い例がどのように修正されるかから学ぶのも有効です。

コードを読む力

普段の課題や小さな個人プロジェクトは、せいぜい数百行、多くても千行程度でしょう。しかし有名な OSS は大規模で、数十万〜数百万行に達します。一般のソフトウェア会社が作る成熟した製品も、数百万行規模になることが多いです。そのときどうしますか?

Linux の pthread の仕組みを調べたり、システム系の開発をしたり、Linux のソースコードを少し修正したいと思うなら、まず Linux が何をしているかを読めなければなりません。Linux はそれ自体が数百万行です。Chromium は有名な OSS ブラウザエンジンで、多くのブラウザやアプリがそのコアを採用しています。Chromium ベースの会社で働くなら、Chromium のソースを読む必要があります。これらは「大規模プロジェクトに触れる可能性が高い」ことを示しています。目的に関係するコードを素早く見つけ、実行フローと文脈を理解する力は、練習が必要です。

この点で強いエンジニアがどれほどすごいかの例を挙げます。私は Servo に貢献していました(およそ 10 万行のプロジェクトです)。新規コントリビュータが初回の貢献でいきなりモジュールを 1 つ修正しました。私が初回貢献で数行しか触れなかった頃、その人はすでにプロジェクトを理解し、約 1,000 行の変更を貢献できていました。

この能力を養うには、小さなプロジェクトから始めて練習し、徐々に規模を大きくして、規模の違いによるアーキテクチャや配置の変化を体験するのが良いと思います。また、この記事 〈在 Linux 理解大型 C/C++ 專案的輔助工具〉 も参考になります。どんなツールが助けになるかを紹介しています。ただし最も重要なのは、結局は「練習」と「観察」です。

開発の協調とプロセス

私は CS 大学院に入る前に複数の会社でインターンをし、また OSS への参加も多かったため、ソフトウェア開発のプロセスや共同開発には慣れています。ソフトウェア企業では、Git + GitHub のようなバージョン管理フローが基本で、さらにテスト、品質管理、デプロイなども組み合わさります。CS の学生は最終的にソフトウェア企業で働くことが多く、会社がゼロから教えてくれるとは期待できないので、先に学んでおくべきです。

バージョン管理には多くの種類がありますが、主流はすでに Git + GitHub です。Git を学ぶメリットは何でしょうか?自分のプロジェクトをバージョン管理でき、失敗したら前の版に戻れます。共同開発では Git を使ってコードをマージできます。もう zip でソースをやり取りするのはやめましょう。

git clonegit commitgit pushgit branchgit checkoutgit merge は Git の基本中の基本です。さらに、少なくとも GitHub で fork して Pull Request を出す方法は知っておくべきです。台大でも交大でも、このフローを知らない学生が多いのに、グループ開発や TA としての指導は頻繁にあります。だから私は今後、しっかりしたチュートリアルを書こうと思っています。

テストを書くのは良い習慣だと思います。コードを変更するたびに動作することをどう保証しますか?テストで検証すればコードへの自信が増します。ただしテストが必ず漏れなくすべてのケースをカバーするわけではないので、テストも更新し続ける必要があります。単体テスト、統合テスト、E2E テスト、QA テストなど、テストの学問は奥が深いので、興味がある方は調べてみてください。

また、継続的インテグレーション/継続的デリバリー(CI/CD)もソフトウェア開発でよく出てくるキーワードです。興味があればこちらも学んでください。

コンピュータシステムに関する基本知識

コンピュータとプログラミング言語は「刀」と「刃」のようなものです。プログラムを上手く書く(刃を鋭くする)だけでなく、コンピュータの知識(刀を強くする)も必要です。計算機概論、計算機組織、計算機ネットワーク、OS、アルゴリズム、データ構造は CS 学生なら誰でも学びます。これらは CS 学生が持つべき重要な武器で、問題解決ではしばしば最も基礎的な原理やシステム下層の設計に立ち返る必要があります。

さらに、自然言語処理、機械学習、コンピュータグラフィックス、コンピュータビジョン、コンパイラ原理、異種計算、セキュリティなど、CS には本当に多くの分野があります。実際に使う機会がなくても、科学原理を理解して視野を広げるのは楽しいことです。

結論

本記事では、開発とデバッグ、良い習慣とスタイル、コードを読む力、協調とプロセス、コンピュータシステムの基礎という 5 つのコア能力を挙げました。著名なコンピュータサイエンティスト、ソフトウェアエンジニア、CS 教授のように強くなりたいと私は思っています。まずはこれらの基本素養を身につけることから始めます。

この文章が「現状への批判」だと誤解されたくはありません。私が挙げた能力は、すべて自分の痛みを伴う実体験から来ています。OSS に貢献するとき Git を使えずに何度も指摘され、差し戻しを受けて膨大な時間を費やしました。C 社では GDB を学ぶために同僚にしつこく付き合ってもらい、後になって「できなかった自分は本当に愚かだった」と感じました。S 社では Vim を習得するために同僚の貴重な時間をたくさん使ってしまい、実際には Vim を使う機会が多く、commit log を書くときにも必要だと知りました。複数社でインターンをした後、私は CS 出身ではないため専門知識の理解が浅く、知らないことが多くて自信を失っていることに気づきました。同時に言語の理解も浅く、書くものが周りよりずっと劣っていました。

「早く知っていれば…」という後悔はたくさんあります。誰かに嫌われて「お前は弱い・ダメだ」と思われる感覚が私は嫌いです。きっと皆さんも嫌でしょう。ならば、もう「早く知っていれば」を繰り返さないようにしませんか?

本記事は CS 学生への励ましでもあります。また読者は CS 学生に限りません。CS 分野に踏み込もうとするすべての人に、ここで挙げた能力は参考になるはずです。一緒に成長していきましょう。