深夜だから個人的なプログラミング学習方法を書くよ！

現在午前2時。深夜の変なテンションになったので、寝る前にプログラミング学習について思うところを書きます。
現在プログラミング学習をしている方、これからしようかなと思っている方の役にたてば幸いです。
なお、筆者はトレーニング事業でWeb系のコーディングやプログラミングを教えていた経験があります。

# プログラミングに必要な能力は理系じゃなくて文系
すいません、見出し長かったので削りました。正しくは「**現代において主要な高級言語のプログラミングに必要な能力は高度なコンピューターサイエンス等の理系能力じゃなくて、現実の事象を正しく言語化できる文系能力**」です。
もちろん、気象計算とかめっちゃ専門的な処理やCG周りとかだと数学とかの知識も必要になるんですが、共通して必要なのはこの言語化できる能力です。

これは外国語の学習と非常に似たものがあります。おそらく、皆さん基本的な英語は理解できると思います。レストランで注文したり、英語で書かれたピーターラビットの絵本くらいは読めると思います。
でも、英語で書かれたハリーポッターはどうでしょう？ 読んで正確に理解できる人はそう多く無いと思います。
では書くのは？
ハリーポッターレベルの英文を書けますか？ おそらく書くのは読むよりももっと難しいと思います。
プログラミング言語も同じで読むよりも書く方が難しく、正確に理解したり高度なものを書こうと思うと様々な概念や構文、関数などの語彙が必要になってきます。
また、ひとつの言語が使える様になると、同じ系統の言語の学習が楽になるのも一緒です。

どのようにこれら文系能力が重要か？、どうやったら効率よく学習できるか？ を説明する前に、まず僕の個人的なプログラミング学習の歴史とバックグラウンドをご紹介。

## 幼少期

- 本読みまくり
- 小さい頃から機械いじりが好き
- ビデオデッキとかラジオとか壊れたらまず分解するタイプ
- 好奇心旺盛
- 興味をもったらとことん
- 学校の勉強（興味ない事）は面倒臭いから可能な限りやらない
- 作文はボチボチ得意だった

## 中学〜高校

- 「コンピューターって、なんか未来っぽいし、色々出来そうで面白そう！」と思ってプログラミングを勉強しようと思ってC言語の本を買って読むが、全く頭に入らない。**変数**と**分岐**と**ループ**と**ポインタが鬼門**って事しか頭に入らなかった。
- 雑誌の付録に付いていた**Vine Linux**をコンパイルしたくて、C言語で書かれてたビデオドライバーをよくわからずにネットの情報見ながらコピペで書き換えたり、シェアウェアの利用制限外したくてバイナリエディタでいじったりしてた。
- 中二は性感帯と女体についてめっちゃ勉強した
- 中学校は中間期末テストと行事くらいしか行ってない。あとはダラダラ遊び呆けてた。
- 高校一年以降マトモに勉強してない（20代後半まで三角関数知らなかったし、ベクトルが配列ってのを最近知ったw）
- 高校の夏休みの宿題の化学のレポートは「**日本で自生している植物に含まれるアルカロイド**」

## 成人後

- 就職してからもプログラミングに対する憧れは消えず、Javaとか勉強してみるも全く頭に入らず。サンプルコードをビルドしてみる程度で終わる。
- 仕事で楽をするために、エクセルの関数を使い始める。
- 仕事で楽をするために、ファイルメーカーでオリジナルアプリを作り始める。ここでデータベースのレコードをループで回して処理する事を覚える。まだSQLは知らない。
- 仕事で給料を上げるために、PHPでWebアプリを書き始める。この時MySQLやらSQL、HTML、CSS、Linux、Apacheとかを知る。Tomcat、JSPはまだ謎。
- 仕事でさらに給料を上げるために、Windows Server, Active Directory, LAN, L7スイッチ、DNS、SIP、IPテレフォニー、ネットワーク設計やらセキュリティやら暗号やら関連技術を幅広く舐める。F5凄かった。L3スイッチの相性に泣かされた。YAMAHAのルーターとパナのL3は優秀。Cisco高いし難しいよ。
- 転職を機にプロジェクト管理、PMBOK、受託開発、Javascript、Action Script、python, Java, フレームワークを覚える。
- 転職を機にP2Pやら動画配信やらLinux系組み込み機器をいじる。この辺りでCG系やって座標計算とか三角関数とか覚えた。
- 独立してObjective-C、scalaでARモバイルアプリ作ったり、オープンソースCMSのローカライズやコミッターとかをやる。

とまあ、「**仕事で楽をするために**」あたりからの成長曲線が凄い訳です。
何が言いたいかと言うと、**ほわっとした興味本位や好奇心**では太刀打ちできないぞ！って事です。**強い動機付け**が必要です。あと、**専門教育は必ずしも必要では無い**という事です。
あと「**怠惰**な人間である」という事は非常に重要です。「**いかに自分が楽をするために努力できるか？**」は良いプログラマの必須条件です。
お刺身に菊の花を延々乗せる仕事を苦じゃ無いと思う人は向いてないです。

# 目に見えて動くプロダクトをいきなり作ろう
この強い動機付けを支えてくれるのが**目に見える結果**です。
よくプログラミング学習本とかに書いてあるFizzBuzzとかの演習問題を書いても、「**で？**」ってなると思います。

> 変数xに1を代入してwhileループで1づつインクリメントして、1から10までprintしてみましょう

とか、「**いや、1から10表示して何の役に立つん？**」となると思います。
それよりも、Webアプリだったら最初から画像掲示板とかブログとか目に見えて自分が欲しいと思うものを作ると、「**もっと良くしたい**」「**こういう画面が欲しい**」など細かい動機付けに助けられて学習を継続する事ができます。
あと、僕は飽きっぽいのでなるべく短期間に集中して一気に作る様にしています。

## プログラミングは手段、目的をまず先に
プログラミングは、あくまで何かの課題を解決するための手段のひとつです。その手段の学習自体が目的となってしまうと、モチベーションを保てない事が多いので、自分がモチベーションを持てる目的から始めましょう。
それを実現するためには、どんなソフトウェアが欲しいか？それを作るのに適している言語は何なのか？という風に、一歩一歩目的へ向けて歩くのではなく、目的から逆引きで学習しましょう。
WebアプリならPHPやJava、Ruby、モバイルアプリならKotlinやSwift、ゲームならUnity+C#、今流行りのAI関連ならpythonでしょうか。

### 最初の言語はなるべく開発環境の構築がいらないものを選ぶ
この最初に学習するプログラミング言語を選択する際に重要なのが、「**環境構築**」です。 JavaならEclipse系のIDE（統合開発環境）とJavaランタイム、SDKのインストール、各種関連ライブラリの追加や設定ファイルの記述など、コードを書き始めるまでの下準備が必要です。
多くの初学者がここでつまづきます。いや、僕らですら結構つまずきます。

この環境構築は一度つまづくと、初心者にはその問題解決はほぼ不可能です。バージョン違いのSDK入れたり消し忘れたりパス通す先間違えたりと泥沼です。
なので、最初は環境構築が可能な限り不要な言語を選びましょう。JavaScriptやPHPなんかはコンパイルやビルドも不要なのでオススメです。フレームワーク使うのも最初はやめましょう。あとで良いです。
JavaScriptもPHPも記述したファイルをレンタルサーバとかにアップロードすれば動きます。必要な下準備は月額500円~1,000円程度の[レンタルサーバ](https://www.xserver.ne.jp/agency_via/?cd=XA5YJ6&type=server)を借りるだけです。

PHPの場合、ローカルでLAMP環境に近い状態を構築できるXAMPPも有名ですが、オススメしません。XAMPPですら最初のうちはうまく動かせなかったりするもんです。

スマホのネイティブアプリを作りたいと思っても、下ごしらえが大変なので最初はスマホ用のWebアプリから始めた方が良いかもしれません。
おそらくWebアプリならPHPとかよりもまずHTMLとCSSを学ばないといけない事に気づくはずです。

### エディタ（コードを書くソフト）はVisual Studio Code
**とにかくWindows標準のメモ帳とか**はダメです。文字コードなどの問題で文字化けとかにハマります。
あとJavaとかで無い限りは最初からIDE使うとかも避けましょう。IDEの設定でハマります。
**コードを書いて動かす**こと以外には出来るだけ手間をかけないようにしましょう。　なお、エディタの文字コード設定は**UTF-8**一択です。

- [Visual Studio Code](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)

## 正しいやり方は二の次、最優先は「動く事」
コードを書き始めは、美しいコードや、無駄の無いコード、正しいコードにとらわれない様にしてください。**まず動く**事が最優先です。**動かないコードはゴミ**ですが、動くクソコードは**ゴミみたいな立派なプロダクト**です。
安心してください、皆さんが思っているよりも世の中はクソコードで溢れています。世のプログラマ達は時間や予算の制約と戦いながらクソコードを産み出し、それと戦っているのです。 大事なのは「**もっと良くしたい**」と思いながら日々改善する事です。
僕も常に過去に書いたコードは書き直したいと思っています。
でも、まずは**動くコード**が最優先です。
追記: ちなみに[コレ](https://qiita.com/tao_s/items/6a9eaa1a8094a3b342e9)が僕が過去に書いたクソコードです。

### コピペはOK、でも理解してないコードはダメ
学習の最初は、コピペの集まりでツギハギだらけのコードでも動けばOKです。
でも、**自分が理解していないコード**は**1行**たりとも書いてはいけません。
コピペしたコードにどんな事が書いてあるのか？その関数はどういう動きをしてどんな結果を返すのか？その変数には何が入っているのか？を常に理解しながら書かないとダメです。
だからコピペするコードはまず読んで理解しましょう。理解してからコピペです。

# 次は0からコードを書こう
コピペや汚いコードで動く様になったら、そのコードを0から書き直してみましょう。おそらく冗長で無駄な処理がこんもり書いてあると思います。
ここで必要になるのが冒頭の**文系能力**です。
プログラミングの方式には関数型言語や手続き型言語など[色々ある](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%91%E3%83%A9%E3%83%80%E3%82%A4%E3%83%A0)のですが、初心者がとっつきやすいのは伝統的な手続き型言語だと思います。この時、言語化能力が非常に重要になります。
なんか前にも書いた気がするんですが、プログラミングとは一種の「**翻訳作業**」です。自然言語の手順書をコンピュータが計算できる計算式に翻訳する作業です。
この**翻訳**に文系の能力が重要になってくるんですね。

## コメントから書く
これは僕がプログラミング教える時によく使うやり方なんですが、初心者は経験が少なく、英語学習で言う所の文法や語彙が少ない状態なので、いきなり英文で書けと言われても書けない状況に似ています。
なので、まずは日本語で書いて、それを翻訳していくやり方です。

例えば、画像掲示板を作ろうとして、画像をアップロードする処理を書くとします。
PHPの基本的な構文は理解していて、自身の経験として画像掲示板を利用したことがあるという前提です。
その処理を日本語で書くと、だいたいこんな感じで生徒さんは書きます。

```php
//画像をアップロードする
```

これをステップごとに分解していくんですね。
画像をアップロードするのには、まず何が必要だろう？、アップロードしたらどうする？、とかです
そうすると、コメントはこんな感じになります。

```php
//ファイルのアップロードフォームを表示する
//ユーザーが画像を選択する
//フォームをサーバに送信する
//サーバは受け取ったファイルを保存する
//画面にアップロードされた画像を追加して表示する
```

このコメントをそれぞれのステップごとにコードに置き換えていくわけです。
ちょうど、日本語で書かれた文章を段落ごとにわけ、それぞれを英語に翻訳していくのに似ています。
また、ここで「画像をアップロードする」という処理を**正しく分解**し、**適切な日本語に置き換える**能力が冒頭で書いた重要な文系の力になります。

これをざっくりコードに置き換えると、

```php
//ファイルのアップロードフォームを表示する
echo '<form action="?" method="post" enctype="multipart/form-data"><input type="file" name="file"><button type="submit">送信</button></form>';
//ユーザーが画像を選択する <-ここはユーザの操作なのでコードいらない
//フォームをサーバに送信する <-ここはユーザの操作なのでコードいらない
//サーバは受け取ったファイルを保存する
move_uploaded_file($_FILES["file"]['tmp_name'],"/var/www/html/img/".$_FILES["file"]['name']);
//画面にアップロードされた画像を追加して表示する
echo '<img src="/var/www/html/img/'.$_FILES["file"]['name'].'">';
```

こんな感じですね。
ただ、このコードでは、脆弱性がありますし、各種バリデーションも行なっていません。最後のechoでimgタグを表示していますが、最初の表示では``$_FILES``が空なので画像が表示されません。
でも、そういったことはこのコードを実際に動かしてみて「あれ？エラーが表示されるな」とか「これどう書くんだろう？」と調べた時にディレクトリトラバーサルやXSS、CSRFについての知識を得ます。
そうして自分の知識をアップデートし、必要なコードを書く時に、またその処理をコメントで書いて、コードに置き換えていきます。

## 実はこのコメントは詳細設計
このやり方をした時に、このコメント達は実は詳細設計書とほぼ同じ意味を持っています。
上記のやり方ではごく一部の処理について例を挙げましたが、この「**まず日本語で書いてみる**」はアプリケーション全体のところからやります。
「画像掲示板」というアプリケーションを分解し、それぞれの画面、処理を日本語で書いていく、これができると立派な設計書ができあがります。
あとはそれに沿ってやり方を調べて、コードを書いて、テストしてデバッグして修正していけば立派な画像掲示板ができあがります。

# 重要なのは「抽象→具象」の言語化能力
この様に、どんなプログラミング言語でも抽象的な現実のものを具体的な処理に落とし込んでいくという能力は非常に重要になります。
昨今ブームのAIも、月に行った宇宙船が積んでいたプログラムもこれは一緒です。
0と1が最小単位の世界で、0と1を組み合わせて計算するだけで人工知能や動画の送信、再生、未来の予測までするなんて、凄いですよね。
でも、これもそれも全部人が人間社会にあるものを0と1で表現しようとした結果であり、そこにはこの**言語化**という作業が大きな役割を担っているんで、文系の人とかプログラミング学習に挫折してる人は「**プログラミング=理系**」と思わずに何でも表現できちゃう素晴らしいコンピューターの世界を楽しんでください。

以上。
うわ、2時から書き始めてもう5時だ...orz

————

# 追記
深夜に書き殴った投稿なのに、たくさん見て頂いている様なので宣伝させてください。

https://eccube-tokyoug.connpass.com/

代々木でEC-CUBEの勉強会やってます。興味ある方はぜひ参加してください。

あと、ECサイトとかの売上上げるお仕事してるので、お仕事も大募集中です〜

https://www.xross-cube.com/contact

https://www.xross-cube.com/ec-cube_help

[EC-CUBEお勧めサーバ](https://shop.xserver.ne.jp/agency_via/?cd=XA5YJ6&type=server)