Chienomi

プログラミング事始め 〜 スクールなんかいかなくていいからXYZしろ

プログラミング::beginners

なにか知らないが、スクールなんか行くな、簡単に自習で身につけられるという言説が飛び交っているらしい。 (「スクールなんか行かなくていいから〇〇しろ」という)

それ自体が間違っているという話ではないのだが、「こうすれば良い」という主張はあまりに的外れなものが多い。

そこで、私がこの20年の、コンピュータ教導の研究成果を踏まえて多くの人にとって適切な習得メソッドを紹介しよう。

より厳密なものはMimir Yokohamaのサイト内で言及しているが、あちらは責任を持って言える範囲で書かれているので提案の類は難しい。 私自身は習得に関わる個人差は同一メソッド内の調整で賄えず、根本的にその人に合わせたメソッドを必要とすると考えているし、だからこそMimir Yokohamaのサービスはメソッドも教材もその人に合わせたスペシャルになっている。

だからこの記事で書いたことが誰にとっても正解などということはありえないのだが、教導時に基本的なところにはなる考え方なので、参考にしてもらえると幸いだ。

具体的手順

PCを選ぶ

あなたがパソコンマニアでないのであれば、3, 4日かけてパソコンを選ぶところから始めよう。

なぜ3, 4日もかけるのか? それはコンピュータハードウェアに対する基本的な知識と、要件と適応を分析する能力を求められるからだ。

これは、あなたがパソコンマニアであったとしても十分に選択可能とは限らないという点を考慮しておくべきだろう。

例えば私が普段使っているラップトップはThinkPad X1 Gen5であるが、プロセッサはCore i5, RAMは8GB、ディスプレイはFHD、ストレージは交換して1TB SATA (2280)を採用している。 タイミングとしてはThinkPad X1 Carbon Gen6の発表があった頃の購入だ。 これは次のような観点である

  • ThinkPadはLinuxとの親和性が高く、強固で、キーボードが非常に打ちやすい
  • 授業などで人に画面を見せる機会もあるし、使い勝手の面からいっても13.3inchが最高とは言えず、14inchのほうが良い。さらに軽量であることが望ましいのでX1一択
  • そもそも私は普段デスクトップで作業しており、計算量的に重いケースではSSH経由でデスクトップを使う仕組みになっているので、ラップトップに計算力を求めていない
  • 一方、マイレージ性能は重要になるので、Core i7よりもCore i5のほうが消費電力の少ない運用が可能になる
  • ラップトップでマルチタスキングはあまりしないものだし、スクリプトやサーバーなどメモリを使い続けるプログラムも走らせない。メモリは8GBで十分
  • Windows 10のストレージ要求が大きいことも考えると、Linuxと共存させるにあたってストレージは多く必要
  • NVMeのほうが高速であるが、消費電力(=発熱量)に対して見合ったタスク効率はないのでSATAのほうが望ましい
  • WQHD液晶は良いものではあるが、消費電力が大きく、要件に対してはネガティブである
  • ThinkpPadは登場時は定価だが、モデル末期は安い (58% offで買った)

ちなみに、直販モデルでシルバーボディだとかいう選択もあるけど、このあたりまでくるとかなり難しいのでおいておこう。

もちろん予算問題もあるが、性能要件に対して「必要なのは何か、優先度は高いのはなにか」といったことを考えていかなければならない。 それには構成されるハードウェアに対する知識が必要になる。

ここでいきなり自作しようと考えるべきではない。考慮しなければならない問題が膨大になってしまう。

最初に選択すべきはラップトップか、デスクトップかだ。 これは、「デスクトップのほうが常に良い」ということを前提として考え、

  • 携行の必要性
  • 電源の確保
  • 設置場所の確保と面積
  • 排熱と熱対策
  • 消費電力

といった問題によってデスクトップを選択し得ないのであればラップトップになる。

計算量は基本的に「時間あたり計算量」と「タスク効率」という点で考える。 時間あたり計算量に関しては「多くの計算」をする場合に「多くのデータ」が前提になる可能性が高く、「保有データ量」「通信速度」「通信容量」「ストレージ容量」によっても計算量の上限が決まってくることに注意が必要だ。 実際、現行のRyzen9 3950Xは私のクソ実装ですらデータ増加量よりも計算力のほうが高く、実用的にRyzen Threadripperは必要ない(あっても使う方法がない)ということが分かっている。

タスク効率は「総量的なタスクにおいて操作上のマルチタスクによって埋めることができない待ち時間の量」と「早く完了することによって全体が好転する時限的タスクにおいて完了するまでの時間」の要件である。

もちろん、ここに来ている以上、 あなたはLinuxerである、もしくはLinuxerになる人物である はずだから、Linuxでの利用において支障がないかということも考えなくてはいけない。

そして、長く愛着をもって使える道具かどうかということも考えよう。

Linuxを選ぶ

Manjaro Linuxが良い。 以上。

実際のところManjaro Linuxを選ぶメリットは非常に大きく、私は以前は環境によって使い分けていたのだが、今やi686環境がBerry Linuxになっている程度でx86_64環境はすべてManjaro Linuxになってしまった。

もちろん、強いこだわりがあるのならArch Linuxを使っても構わない。

もちろん、あまりにも強いこだわりがあってどうしようもないなら、Gentoo Linuxを使っても構わない。

もちろん、 宗教上の理由でどうしてもUbuntuを使わなければならないと戒律で縛られており、鋼の意思が破戒僧となることを拒むのであれば、 どうにもやむなくUbuntuを使うのも良いだろう。

Linuxを導入する

Manjaro Linuxのインストール作業については、Mimir Yokohamaに記事があるほか、YouTubeに動画としても上げている

ただし、どちらもバックアップ手順がない。

最近のWindows 10は素直なバックアップと復元が難しくなっているので、スタートメニューから「回復」で検索し、「回復ドライブの作成」によってレスキューUSBペンドライブを作るのがスマートで良いやり方だ。

必要に応じてリカバリー領域を残すという方法でもいい。例えば、Windows側でWindowsのパーティション(C:になるNTFS領域)を縮小し、「パーティションを置き換える」という形でManjaro Linuxをインストールすればリカバリー領域が残る。

Linuxに慣れる

コンピュータを自然に使うことすらできない者がプログラミングなどと片腹痛い。 まずは日常的な利用が問題なくできる、それが大事だ。

この「日常的な利用」が具体的に何を指すかはその人によって大きく異なってくる。 最近は大部分がwebであることが多く、あとはメール, Slack, Discord, LINEといったコミュニケーションツールが占めていることが多いだろう。 Slack及びDiscordはウェブ版を持っているので、webを完全に除外するならばさらに少ないかもしれない。メールもGMailだったりするかもしれないし。

ウェブブラウザはMozilla Firefox(Stable/Beta/Nightly), Google Chrome(Stable/Beta), Chromium(Stable/Beta), Vivaldi(Stable/Snapshot), Brave(Stable/Beta), Opera(Stable/Beta/Develop), SeaMonkey, Palemoonなどがある。 他にもWindowsだと馴染みのないものだと、Midori, Falkon, Otter Browser, Dillo, w3m, Elink, Link, Lynxなど。 Internet ExplorerやMicrosoft Edgeを愛してやまない人であれば困るかもしれないが、基本的に困ることはないだろう。Linuxで支障のあるウェブサイトも非常に少ない。

メールソフトは結構選択肢が少ない。 Sylpheed, Claws Mail, Mozilla Thunderbird, Evolution, Trojita, Kmail, Balsa, Mutt, geary, くらいだろうか。 細かく言えばもっといろいろあるのだが(Balsaを入れたくらいなら入れてもいいかもしれないが)、基本的にはここらへんが選択肢になる。 Mozilla Thunderbirdのユーザーはそのまま使えばいいし、OutlookユーザーはEvolutionがいいだろう。 なお、GMailはウェブを使ったほうが機能豊富である。

Slack, Discord, Skype, Telegramはデスクトップアプリが存在する。 LINEに関してはChrome拡張版を使うことになるが、通話はできない。 Kakao Talkのクライアントはない。あんな怪しげなもの投げ捨ててしまえ。

オフィスソフトの利用についてはLibreofficeまたはFreeOfficeを使うか、あるいはOffice 365 for the Webを使うといったところが選択肢。

グラフィックスツールはGimp(フォトレタッチ), Inkscape(ベクターイラストレーション), Krita(お絵描き)など。

音楽プレイヤーはAudacious, Clementine, Amarok, Rhytemboxなど。

メディアプレイヤーはmpv, MPlayer, VLC Media Player, SMPlayer, Totemなど。

画像ビューワ/ブラウザはたっっっくさんある。私は主にViewniorを使っているけれど、ほんとにたっっっくさんある。

ドキュメントビューワはEvince, Xreader, Atril, epdfview (以上Popplerエンジン), Xpdf (XpdfまたはPopplerエンジン), Okular (Ghostscriptエンジン), qpdfview (qpdfエンジン), Acroread (Adobe公式)といったところ。

その他私が利用頻度が高いソフトウェアというと、シェルとツール類を除外すると

  • ffmpeg (メディア変換)
  • ImageMagick (画像変換)
  • Pandoc (ドキュメント変換)
  • VSCode (コーディングとドキュメント)
  • Pidgin (マルチプロトコルメッセンジャー)

となる。

Linux的に活用する

日常的にWindowsに頼らずともよくなったら、今度はLinuxらしい活用をしていく。たとえば

  • 自由なタイリング (CinnamonならWindowsキーとカーソルキーの組み合わせ)
  • 任意の場所をつかんでのウィンドウの移動 (Alt+左ドラッグ)
  • 任意の場所をつかんでのウィンドウのりサイズ (Alt+右ドラッグ。GNOMEはWin+右ドラッグ)
  • コマンドでのアプリケーションの起動 (だいたいAlt+F2でランチャが起動できる)
  • シェル

といったところ。

なお、Mimir Yokohamaの授業の経験から言えば、ここに到達するまでだいたい1コマから3コマ、時間にして2-6時間といったところである。 がんばってなるというよりは、実際にLinuxを使うと何も困らず、Windowsより快適なのでWindowsを使わなくなるという人が多い。

シェルを理解する

この観点は他所で聞く話とは大きく違うだろうから突っ込んで解説する。

シェルを学ぶことは、 単なる暗記や試験問題のような話とは大きく違う。

シェルには重要な概念が詰まっているのだ。

  • コマンドラインインターフェイス
  • ファイルディスクリプタと標準入出力
  • ユーザーインターフェイス
  • 環境変数
  • プロセス間通信
  • プロセスモデルと並列性
  • プロセス
  • 機能の組み合わせ

これらが理解できていないと、プログラミングの話をしたときにしょっちゅう「ん????」となる人が出来上がってしまう。 結局、基礎ができていないと実力というのはハリボテになってしまって、適切性の判断ができないのだ。

これについての説明はあまりにも長くなるのでここには書かない。だいたいMimir Yokohamaでは1から4コマ分の授業で履修する内容であり、一方シェルにおける基本機能を使えるようになり、その機能が具体的にどのようなものなのかということを理解しようとすれば自然と入ってくる内容でもある。

良さそうな言語を選ぶ

うちへの問い合わせでも「業務で〇〇を使うから」というのを毎回のように聞くのだが、 何を学ぶかということはそのようなことで決めるようなものではない。

プログラミング言語は日常レベルですら思考形成に影響を与えるものであるから、あなたの思考様態と親和性が高い言語を選択すべきである。 それがあなたにとっての「ネイティブ言語」になるものであり、他の言語は「外国語」として思考で翻訳するのだ。

もちろん、 私の推しはRubyである。 実用上(就職含めて)使い勝手が良いのはPython。

とりあえずコレは決めておかないと話が進まないのでRubyだと仮定して話を進める。

開発環境を作る

開発環境を作る話はYouTubeに上げてある。

Rubyに関してはエディタとRuby処理系をインストールするだけで、多くの環境ではRubyはデフォルトでインストールされているからそれも必要ないだろう。

Perl, Ruby, Python, Goに関しては用意の手間は非常に少ない。 PHPは若干考えなければならない要素があり、クライアントサイドJavaScriptはより用意の手間が少ない。

CやC++などは用意したほうがよいものが多い可能性がある。 Javaは考えなければいけない要素が多い。

エディタはVSCodeでおよそ間違いがないだろう。 Eclipseなどは非本質的な要素を大幅に増やすため推奨しない。 基本的なところではお好みのエディタ(e.g. Gedit, Xed, Pluma, Kwrite, Kate, Mousepad)でも構わない。 VSCodeのほうが楽に書けるのは確かだが、初期段階ではむしろシンプルなアプリケーションのほうがとっつきやすい面もあるだろう。

ただし、シンタックスハイライトの問題を考えるとやっぱりVSCodeが良いということもある。 その意味ではVimも有力だ。

そして、フォントの導入も忘れずに。 お勧めのフォントはつい先日記事にしたが、Windows Terminalに標準採用されたCascadia Codeも魅力的。

Manjaroのリポジトリにある主なコーディングフォントは

  • Fira Code
  • Fira Mono
  • Inconsolata
  • Fantasque Sans Mono
  • Terminus
  • Cascadia Code
  • IBM Plex
  • Proggy
  • Roboto Mono

である。HermitはAURから落ちた関係でなくなってしまった。

フォント関係のAURパッケージはメンテナンス状況が怪しいものが多いので、あまり期待しないほうが良い。

カラーテーマの選択も大事だ。試行錯誤を繰り返して手に馴染むようにしよう。

Hello world

私は実際に初歩として”Hello, world!“を書いたことがないので、それが入門に適切だとは思わないが、はろわもただ単に

#!/bin/ruby

puts "Hello, world!"

と書き写しておしまいだとなんの意味もない。

はろわですらもちゃんとやればいろいろと考える要素があるものなのだ。

Shebangについては過去の記事で解説している

そして、はろわを「実現するための効率的な方法」というだけの話であればこれで十分であるわけなのだが、ここは学習であるから、「できたからおしまい」では意味がない。はろわを題材にいろんな表現ができるかと問われればどうだろう。

さて、ここからはちゃんと考えて理解する前提で(だから解説はしない)いろいろなパターンを行こう。まずはKernel.putsだけでなくKernel.print

print("Hello, world!\n")

Kernel.printf

printf("%s\n", "Hello, world!")

IO#putsKernel.sprintf

STDOUT.puts sprintf("%s", "Hello, world!")

catを使う

IO.popen("cat", "w") {|cat| cat.write "Hello, world!" }

自らがcatになり、自らのSTDINに予め流し込む

r, w = IO.pipe
STDIN.reopen(r)
w.puts "Hello, world!"
w.close
exec "cat"

配列リテラルと配列の結合

hw = %w:Hello, world!:
puts hw.join(" ")

文字列とenumオブジェクトとイテレータ

hw = "Hello, world!\n"
hw.each_char {|c| print c }

正規表現と文字列置き換え

print 'hello, world'.sub(/^./) {|c| c.upcase }.sub(/$/, "\n")

地獄へ突き落とす

hw = "Hello, world!"
hw.sub!(/l([^l]*)$/, '\1')
hw[4] = ""
puts hw

こうした実現方法や遊び方がぽんぽん出てくる、というのは言語への理解度やプログラミング自体の熟練度に直結してくる。 最初は難しいだろうが、頭をひねって「こんなこともできるな」と 遊ぶことが大事なのだ。

その先は

何を目指すかによる。

だが、まずは言語の基本的な機能、構文などを理解するところから始めることになるだろう。 それにあたり、私が実際にやっているのが、「三山崩しを作る」ことだ。

三山崩しには比較、コレクション、計算、ステート、トグル、入出力など基本的な要素が詰まっており、言語の基本構文を一通り理解していることが求められる。 その割に比較的小さく書くことができ、内容自体は簡単なものであるためちょうどよいと思う。

初期段階ではごくシンプルなゲーム(じゃんけんとか、マルバツゲームとか、そういうレベルのゲーム)を色々と作ってみるのもいいだろう。 SESがすっかり声高になってしまった今は職業訓練の話ばかりが目立つようになってしまったが、プログラマはゲームを作って育つものだったのだ。

小さなちょっとしたトイプログラムが思ったようにサクッと書けるようになり、バグもあまり出さないようになれば、ごく単純なユーティリティプログラムを書くのがお勧めではある。 だが、ユーティリティプログラムというのもあまり他では使わない要素が色々とあって、この段階になるとその人にとっての正着であるとは限らなくなっている。 ただ、自身にとって役に立つプログラムを全く書けない人のプログラムが役に立とうはずもないので、一度は書いたほうがいいだろう。

プログラミングの初歩を履修した後は、目標に向かって着実なステップを歩めば良い。

職業訓練じゃねぇんだぞ

何度も何度も何度も言っているが、 プログラミング学習は職業訓練とイコールではない。 職業訓練の話をしたいのなら、「プログラミングの習得」なんてお題を大きくしないでちゃんと「職業訓練としてのプログラミング」と言えという話だし、増して職業プログラマはSESだけではないにも関わらず1、SESで欲しい人材像を書くという流れになっている。

ハッキリ言って、最高にくだらない。

なぜ事を大きく見せようとするのか。なぜ自分が属するものが世界の全てであるかのように言いたがるのか。 矮小で近視眼的なことを偉大な真理であるかのような大言壮語を好むのか。 そもそもSESにおいて真実どれだけプログラミングができるかなどということは些事ではないか。

これはプログラミングを習得する話であり、それ以外の要素はない。 何のために習得するのか、あるいはそれによって何を為そうとするとするのかは各々の自由であり、ここまでの内容はそれらを左右する、あるいはそれらによって左右されるような類のものではない。

繰り返すが、これは純粋にプログラミングを習得するにあたり、その学習の端緒につくための話だ。

プログラミング習得の真髄は

楽しむことだ。

プログラミングは楽しい行為である。

故に好奇心のままに飽くなき探究を続けられる者のみが真髄に至れる。 そして、例え真髄に至れないとしても、プログラミングの道を歩むために求められる原動力は他にない。

だから、「おまじない」などと言われて納得しているようではダメだし、サンプルとして書かれたものを書き写して満足しているようではダメだ。

Vimの話

Vimの習得は純然たる趣味であり、Vimが好きでないのであれば必要ない。

Viに関してはUnixシステムを管理する上で必要となるし、最低限使えるほうが良いのは確かだが、別に.xprofileとかに

export EDITOR=mousepad

とか書いておくことで支障がないのであればそれで良いだろう。

私自身はViに関してはそこそこ得意なほうだが、Vimを好んで使っていたということがないので、Vimの機能には比較的疎い。だが、少なくともEmacsよりは得意だし、ZshもViモードで使っている。

スクールと学習法について

ごく個人的な話になるが、私が聞き及んだ限りではスクールに関してあまりいい印象はない。

ただし、これは明確なバイアスがある。スクール経験があり、かつMimir Yokohamaに相談する人は、スクールにおいて満足する経験が得られなかった人であるからだ。もし、スクールで十分な学習をしたと考えているのであれば相談しないだろうし、満足する体験であったら同スクールでの受講を続けるなどするだろう。

だからMimir Yokohama経由で聞くスクールの話としては、前提としてスクールに満足していない、不満があるということであるから、よい印象を持つはずがない。

また、私の周りにスクール出身の凄腕がいない、という点も大きい。 私の周りの凄腕はだいたい

  • OSSの世界で技術で殴り合ってきたサバイバー
  • 企業の中でとんでもねぇ技術をやってきたエリート
  • 大学で研鑽を重ね、ブートキャンプで鍛え上げられたドクター

である。

私のプログラミングの習得過程はちょっと特殊で、2歳で本で自習をはじめてから、コードを触り続けて覚えた。 「プログラミングできるようになりたかったらソースコードを読め」という言い方は私は嫌いなのだが、実際のところ「ソースコードで覚えた人」である。

ただ、私は幼少期に題材となるソースコードが本としてあり、より本格的に取り組み始めた時期はPerl/CGIが流行していた時期だから、アマチュアによる玉石混交の規模のあまり大きくないソースコードが山のようにあった。 目的は明確だったし、動かすのも簡単だった。当時だってセキュリティの問題は存在したが、セキュリティ上の問題があったとしてもそこまで深刻な話にはなりづらかった。 この状況から、気軽に書くことができたし、故に気軽に書かれたものが多く、当時の未熟な私でも「ここはもっとこうした方がいい」「こうではダメなのか」と思いつくことができ、書くことができた。 これは学習には良い環境だったのだ。

そこからすれば現在は、「技術トレンドはこれ」「この技術でないとダメ」「〇〇は時代遅れ」みたいな余計な圧がやたらに多く、インターネットのリスクが上がりすぎて(さらに言えば社会的・法的な圧も厳しくて)磨かれる環境も乏しくなった。 コンテンツの増加によって学びやすくなったという主張も見かけるが、私個人の意見としては学びづらくなったと考えている。

ソースコード学習は有力だとは思うが、学習に適したソースコードを必要とし、また向き不向きがあることを考えれば「これぞ決定版」とはならない。

Mimir Yokohamaは単に「書ける」ということではなく、体系的にプログラミングと、それに関わる周辺技術や概念などに対する根本的理解を獲得することで理解を深めよう、という考え方である。 実践的であるとか即時的であることよりも、確かな地力を得ることで「着実に伸びる」育成を目指している。