プログラミングのプの字も知らない文系エンジニアが普通のエンジニアになるまで

# はじめに

僕がプログラミングのプの字も知らない状態でエンジニアとなり、6年ほどが経過しました。

この記事では、僕のようにプログラミングなんてしたこともない状態でIT業界に飛び込んでしまった文系エンジニアへ向けた、「普通のエンジニア」になるためにしといて良かった・しておけば良かったと思うことを自分の経験を振り返りって書いていこうと思います。（厳密に「文系」でなくても、情報系や理数系以外の勉強がメインだった理系の方もおそらく同じように読めるかと思います）

すでにエンジニアとして就職した方、これから就職を考えている学生の方などが1, 2年後のエンジニア生活を想像する上での参考になれば幸いです。

なお、この記事にプログラムは一切登場しません。すべて文章による説明のみですので、読み物的に軽く読んでいただければと思います。

# 自己紹介

* プログラミングのプの字も知らない状態でIT業界にエンジニアとして飛び込んでしまった社会人7年目のエンジニアです。
* Web系の企業で、Servletを使ったWebアプリケーションの運用・保守（たまに開発）をしています。
* Androidアプリの開発もたまにやってます。[趣味でアプリを公開しています](https://play.google.com/store/apps/details?id=jp.chujo.missnote&hl=ja)。
* 興味・関心などについては[Qiitaに投稿している他の記事](http://qiita.com/chooyan_eng/items)をご参照ください。

では書いてみます。

# はじめに

特に情報工学を専門に勉強してきた人たちと違い、我々文系エンジニアには体系的な知識や経験が大学4年分（もしくはそれ以上）も足りません。ですので、社会人エンジニアとして成果を出そうと思ったらこれから彼ら以上に勉強し、追いつき追い越す必要があります。

会社で覚えたことさえやってれば勉強しなくても仕事をやっていける、という世界ではありませんので、これができないようであればこのページは閉じていただき、割と真剣に他の職種を検討することをオススメします。

とはいえ、勉強のしかたについては工夫の余地があります。

まず、エンジニアの仕事は情報工学の深い知見さえあればできるのかというと、そうでもありません。なぜなら、仕事の目的は知識を競うことでも、新しい発見をすることでもなく、会社の利益を上げることだからです。

利益を上げるにはユーザーにサービスを購入してもらう必要があります。そして、ユーザーの大部分は__エンジニアではありません__。そのため、ユーザーはそのサービスが技術的にどうなのかに関心がなく、「技術的に優れたものはサービス的にも優れている」と常に言えるわけではありません。

ユーザーにとって大事なのは「お金を払ってでも使いたい」サービスかどうかです。技術は「お金を払ってでも使いたい」サービスを実現する道具の一つでしかありませんので、何か技術的な勉強をする時は「これを勉強することがサービスの価値向上につながるのか」を常に意識し、一番効果的なものを集中して身につけていくことで、知識の総量は少なくても十分に成果を出せるエンジニアになれるはずです。

僕はWeb系の会社のエンジニアですので、この記事でもWeb系の文系エンジニアが成果を出すために必要な要素を意識して書いていきます。

# 主記憶装置・補助記憶装置・中央演算処理装置

まず学ぶべきは、主記憶装置・補助記憶装置・中央演算処理装置、つまりメモリ・ハードディスク・CPUです。
プログラミング言語ではありません。

## プログラミングを学ぶ前に
プログラミングはコンピューターへの命令文を書く作業です。
そのため、まず初めにやらなければならないのは、そもそもプログラムによって動かされるコンピューターそのものの仕組みの理解です。

趣味でプログラミングするだけならここを飛ばしていきなり 「printf って書いたら "Hello World!" が表示された！やったー！」 としてしまっても問題ないのですが、仕事としてお金を稼ぐプログラムを書くのであればコンピューターが何をどうやって"Hello World"を表示しているのかの理解が必須になります。特にメモリについてはプログラミング中もよく気にすることがありますので、「メモリはデータの保存領域を一列のマス目に細かく区切り、番号（アドレス）が振られたそれぞれのマス目に少しずつデータを保存している。」くらいのざっくりとした理解だけでもイメージできているとプログラミングがだいぶ楽になります。

## 変数は「箱」？

例えば、プログラミングの入門書にまず初めに出てくる「変数」ですが、だいたいは「箱に名前をつけたて値（データ）を保存したもの」と説明されたりします。僕はこの説明のしかたは不正確なだけでなく、このイメージがあるために正確な理解を妨げる、という意味で結局は効率の悪い教え方なのではないかと思っています。

「箱」というコンピューターの世界に存在しないものを持ち出してイメージするよりも、「メモリのマス目に値を保存し、そのマス目のアドレスを保持するもの」と、実際にコンピューターの中で起きていることを簡略化したイメージで覚えた方が、圧倒的に理解が早く、正解に近いはずです。

## 仕事としてのプログラミング
プログラミングは目に見えない概念的な部分が大きくイメージしづらいため、市販の入門書などではそれを分かりやすくするために身近に存在する、コンピューターとは関係のないものを使って説明することが多いのですが、それは「分かった気になる」だけであり、結局は実際にどのようなことが機械の中で起こっているのかを理解できません。

簡単なじゃんけんゲームが作りたいならそれでも良いのですが、仕事として、24時間稼働し続けるサーバーアプリケーションや100万件のデータを毎日処理するプログラム、ユーザーが好き勝手に操作するAndroidアプリなどを作るのであればそれでは不十分です。機械そのものの理解やプログラムの挙動への理解が足りないために原因不明のバグを生んでしまったり、そもそもプログラミング言語の文法（ポインタ等）を理解することも難しくなるでしょう。

## 急がば回れ
繰り返しになりますが、プログラミングとはコンピューターを自由自在に操る命令文を書くことです。小難しいからと省略されがちな機械の仕組みを多少なりとも理解しておけば、プログラミング言語の文法や挙動を理解する助けになるだけでなく、バグなどの問題が発生した場合の原因究明や解決などもしやすくなり、より品質の高いシステムを作ることができるようになるでしょう。

僕が会社で研修を受けたときは、ここは重要なステップであるということで最初にコンピューターの理解に5日間使い、そのあとにC言語の文法を5日間かけて構造体やポインタまで習った記憶があります。結果的に、最初の5日間があったおかげで難しいと聞いていた「ポインタ」は特に難しいと思うことなく理解することができました（もちろんポインタの文法的な書き方や考え方だけの話ですが）。

# C言語で学ぶ

さて、コンピューターの仕組みを大まかに理解したら、ようやくプログラミングの勉強に入ります。
プログラミングを勉強する、というとまず話題になるのが「何の言語で勉強するか」なのですが、僕はC言語が最適だと思っています。

## なぜC言語なのか

確かにjavascriptやrubyなどのスクリプト言語は簡単に書けて簡単に実行できるので、ちょっとプログラミングを触ってみたい、という場合には最適なのですが、それぞれが独特な思想や文法を持っているために「その言語でしか通用しない考え方」が多数含まれています。そして悪いことに、初めてプログラミングを勉強する場合は何が「独特」なのかを判断する術がありません。

実際の仕事でどの言語を使うことになるのかはいざ配属されてみないと分からないことが多いため、勉強する段階では「つぶしが効く」言語を選択するのが重要です。

C言語は、（Web系で）一般的に使われるJavaやjavascript、ruby等の言語に比べると機械語に近く、他の言語では我々が知らなくても良い部分でよろしくやってくれている部分についても自分で書かなければならないことが多いため、上述した「コンピューターの仕組み」を理解しながら書くことを強制されます。そのためC言語きちんと書くことはコンピューターの仕組みをきちんと理解することにつながり、自然と他の言語を正確に理解するのが比較的容易になるのです。

僕が研修で使ったのがC言語なので若干の贔屓が含まれているかもしれませんが、それでもC言語は一度学んでおくべき言語だと思っています。繰り返しますが、目標にすべきはとりあえず動くじゃんけんゲームではなく24時間安定稼働するシステムなのです。

## C言語の文法

話の流れとしてはC言語の書き方の説明になるのですが、C言語の文法については他にいくらでも良い参照先がありますので、割愛します。
僕はこんなのを見ていました、というものだけリンクを貼る程度にしておきます。

* [苦しんで覚えるC言語](http://9cguide.appspot.com/)（通称「苦C」）
    * 苦CはC言語を「ちゃんと」使えるようになることを目標にするC言語初心者のためのサイトです。市販の入門本よりも詳しく、正確に、比喩でお茶を濁すことなく説明されています。その分分かりづらい場合もあるかもしれませんが、ここでちゃんと勉強しておくと後々の仕事に活きるはずです。Webサイトなので無料なのも良いです。
* [やさしいC](https://www.amazon.co.jp/dp/479737098X)（通称「やさC」）
    * 丁寧なC言語の入門書です。苦Cで辛くなったらこちらで口直しすると良いかもしれません。

## できればメモ帳で

プログラムは結局は文字の羅列です。そのため、専門のソフトなどなくてもWindows標準のメモ帳さえあれば書くことができます。書いたプログラムの実行も、コマンドプロンプトがあれば可能です。

仕事でプログラミングをする際は「統合開発環境（"Integrated Development Environment" 略して"IDE"）」という、プログラムの作成から実行までをしやすくまとめて開発を効率化できる専門のソフトを使って開発を進めることが多いのですが、今は勉強ですのでIDEを使わず、上記の通りメモ帳で書いてコマンドプロンプトで実行するというスタイルで勉強してみることをオススメします。

プログラミングを学ぶ上では「お約束」のような記述や定番の書き方がたくさん出てきます（「おまじない」と言ったりします）。IDEを使うと例えば「自動補完」という機能でそのようなお決まりの記述を勝手に入力してもらうことができるのですが、初心者がこれをやってしまうとそのような記述が何のために必要なのか分からないままになってしまいます。

しかし、「おまじない」の部分は常に同じことを書いていれば良いのかというと実際はそんなことはなく、複雑なアプリケーションになればなるほど、今まで「おまじない」としていた部分で工夫を加えなければならないことが多くなります。

なぜ「おまじない」が必要なのか、「おまじない」がないと何が起こるのかも含めて勉強し、極力「おまじない」扱いの記述を少なくすることが、スキルを向上する上では欠かせません。「おまじない」を「おまじない」のままにしないためにも、まずは自分で一文字一文字打ち込み、それぞれの行がどんな役割を果たしているのかを意識して勉強することが大切かと思います。

## とにかくいろいろ作ってみる

C言語でプログラミング一般的な部分を勉強するわけですが、座学だけでは内容的にも精神的にも限界があります。動物の子供は遊ぶことで現実世界を生き抜く力を養うそうですが、エンジニアも同じで、とにかく好きなプログラムを自分で試行錯誤しながら作ってみることで、本を読んだり人に聞いて覚える以上の効果を得ることができます。

例えば簡単なクイズゲームなら if文 による分岐の使い方を覚えることができますし、じゃんけんゲームなら乱数によるランダムな手の選択方法を覚えることができます。過去の手から次の手を予測、なんてのも面白いでしょう。

重要なのは、「作り方がまだ分からないから作らない」ではなく「分からないことは調べながらなんとか作る」というスタンスで作ってみることです。現代のエンジニアにはGoogleという偉大な先生がついていますので、分からない場合はどんどん調べて自分のプログラムに取り入れてみましょう。

ちなみに「簡単でいいから何か作ってみる」はどのレベルのエンジニアも新しい技術を覚える際にやっていることです。また、「分からないことはググる」も、エンジニアにとって最も大事な考え方のひとつです。自由に、楽しみながら作ることがモチベーションアップにもつながりますので、どんどん作りたいものをイメージし、調べて試行錯誤しながら形にしていきましょう。

もしもすぐに思いつかない場合は、「Fizz Buzz」という昔から言語の練習のネタとしてよく使われるプログラムがありますので、これを作ってみても良いでしょう。最近だと「ズンドコきよし」なんてプログラムが流行ったりもしました。それぞれググって調べてみてください。

---

# 閑話休題　〜エンジニアにとっての「勉強」〜

ちょっと長くなってきたのでここで休憩です。
（現実世界ではここまでコンピューターの理解とC言語で1ヶ月ほどが経過したところでしょうか。）

ここまで、「勉強」という言葉をたくさん使ってきましたが、その単語の意味するところは学生までとはだいぶ変わります。

学生（特に高校生）までは、「勉強」というと英単語を覚えたり、数学の公式の使い方を覚えたりと「覚える」ことで「正解の決まった問題を解く」ことを指していたのですが、エンジニアの勉強では「覚える」必要もなければ「正解」があるわけでもありません。

そもそも、エンジニアが知るべき範囲は人の脳が覚えていられるほど狭いものではありません。プログラミング言語や開発効率を上げるためのフレームワークやツール、さらにはコンピューターの仕組みやインターネットの知識、暗号化の仕組みなど、Webアプリケーション一つを作り上げるだけでも一生かかっても完璧には理解しきれない分量の情報が存在します。

そのため、「勉強」で意識することは「覚える」ことでなく、「こんなことをしたければここを調べれば良い」といった索引のようなものを作っていくことです（と、スゴいエンジニアと信頼されていた先輩が言っていました）。細かいことは本やインターネットがちゃんと覚えていてくれます。自分は「そのような情報が存在する」ことだけを理解していれば良いのです。

また、エンジニアの課題に「正解」はありません。先輩も、上司も、何をどうすれば正解か分からない状態で、「きっとこうすれば課題が解決するだろう。なぜならこうこうこういう理由だからだ。」といったことを自分で考え、結論を出し、それを信じて前に進みます。

こうなると大事なのは「知識」ではなく「考える力」です。今存在する選択肢を数え、それぞれの選択肢を選んだ場合の未来を予測し、一番望ましいと思われる選択肢を判断し、それを実現するために手を動かします。プログラミングは、そのプロセスの中の「手を動かす」という部分であるに過ぎません。エンジニアは、プログラミングの文法を覚えるだけではなく、論理的に、説得力のある説を組み立てる頭の使い方もこのような勉強を通して同時に鍛える必要があるのだと思います。

---

# Javaで作る

さて、C言語でプログラミングの基礎が分かってきたら、次は実務に向けてJavaを勉強します。

と言っても必ずしもJavaである必要はありません。僕が研修後に配属先で使っていたのがJavaだからこの記事ではJavaを選んだだけで、ここからは状況に応じて他の言語でも良いと思います。

ただし、JavaはここまでC言語で実行してきたようなコンソール上で動く文字だけのプログラムの他にも、Servletによるサーバ開発、Android用のアプリ開発にも応用できる上、そもそもJavaで開発されたシステムが世の中の多数を占めている関係で、特にWeb系の実務としてはC言語以上に「潰しの効く」言語です。そのため、可能であればJavaでの開発を経験しておくと良いでしょう。

## C言語と比べてみる

C言語の基礎を学んでからJavaを勉強し始めると、様々な新しい概念が登場することに驚くでしょう。クラスや継承、例外処理やアノテーションなど、「また1から勉強し直しじゃん！」と思うことが多々あるかと思いますが、その通りです。

では最初からJavaを学んでおけばよかったかと言うと、そうではありません。先ほどjavascriptやrubyが独特な言語だと言いましたが、Javaも「クラスが必ず必要」、「JVMで動く」など、十分に独特な特徴を持っている言語です。

結局プログラミング言語はそれぞれ独自の特徴や考え方があり、使いどころや機能も違うため、「これだけやっておけば大丈夫！」なんて言語はありません。それよりも、複数の言語を学ぶことでそれぞれを比較し、何がその言語特有のもので何がプログラミング一般的なものなのかを知ることの方が大切だと考えています。

言語の違いを「ちょっとした『方言』の違い」のように捉えていると、それぞれの言語の正確な理解ができず、どんなときにどの言語を選ぶべきかの判断も誤ってしまいます。そうならないためにも、新しく言語を学ぶ際は「１から勉強し直し」くらいの意気込みで臨むと良いでしょう。

そのあたりは、[「コーディングを支える技術」](https://www.amazon.co.jp/dp/477415654X)という本に丁寧に書かれています。内容も文章による説明の比率が大きいため、ここまで勉強してきた知識があれば十分に頭に入ってくるのではないかと思います。

## 実務としてのプログラミング

僕はC言語で3ヶ月間研修を受け、配属されてからJavaの研修をOJTという形で1ヶ月ほど受け、徐々に仕事としてのプログラミングをするようになりました。

と聞くと、配属前の方は「え？まだアプリみたいな画面も何も作れないのにもう実践？」と思うかもしれませんが、実際のプログラムは何もアプリだけではありません。確かにアプリそのものを作る業務もありますが、それと同じように「アプリに表示するデータを作る」「サービスの運用を改善するツールを作る」など、サービスを実現するための開発はユーザーの目に見えないところにもたくさんあるのです。

また、「開発」は何も全くの０から新しいものを作る仕事だけではなく、すでにある先輩の書いたソースコードの機能追加やバグ修正など、ベースがあるものに部分的に手を加えていくような仕事もあったりします（というかその方が多いです）。基本的なプログラムの書き方を覚えたら、あとはGoogle大先生と先輩の助けを借りながら実際のサービス（の一部）で使われるものを作っていくのです。

そう考えると、「実践」とは言っても実際にやっていることの半分は「勉強」だったりします。これはどのレベルのエンジニアでも同じです。人ひとりの頭が知っている、もしくは覚えていられることなんてたかが知れていますので、結局は調べたり人に聞いたりしながら開発していくことになるのです。その意味では、仕事でより重要なのは暗記による豊富な知識ではなく、新しい内容でも自分で調べて理解する力や、人への上手な聞き方だったりするのです。

## 先輩のソースコードを読む

配属が決まったら、ぜひ先輩のソースコードを読みましょう。「実務って実際何を作るのかよくわからない」という不安が解消されるだけでなく、自分の知らない書き方や考え方を発見し、それを勉強のネタにすることができるからです。

また、「ソースコードを読む力」は実践でもとても役に立ちます。例えばバグが発生した場合、エンジニアはどこが原因なのかをソースコードを読みながら考える必要があります。そんな時に見た事のないソースコードが読めるか読めないかで、バグの修正までの時間や直し方の妥当性、今後同じようなバグが発生するリスクなどが大きく変わるのです。

（ちなみに、「そんなの作った人に聞けば良いじゃん」と思うかもしれないですが、エンジニアは１ヶ月前に自分が書いたコードなんて覚えていない事が多いです。僕も、「ホントにこれ自分が書いたの？」と思うことがよくあります。１ヶ月前の自分は他人、というのがエンジニアの中での一般的な考え方です。）

バグではなくても、今動いているシステムに何か機能を追加しようと思ったら、今動いている部分に影響を出さないようにうまく機能を追加する必要があるでしょう。そんな時にも、ソースコードを読んで理解する力はとても役にたちます。

先ほど書いた通り、仕事の半分は勉強です。「新人である自分には分からないから読まない」ではなく、積極的に読んで、実際に書いた人に質問し、自分の力として取り込んでいってください。

## 最初は画面を作らない

これは配属的に可能であればですが、最初はアプリやWebページなどのいわゆる「画面」部分を作るプログミングは避けた方が良いと思っています。僕が１年目に先輩に言われたことですが、画面のプログラミングはそのプラットフォームでしか通用しない考え方や書き方が多く、また「こう表示したければこう書く」みたいなパターンも多く、純粋にプログラミングの技術を向上させるには適していないためです。

確かに、作ったものが直接目に見えてユーザーに使ってもらえる、というのは魅力的ではあるのですが、今後の成長も考え、まずは地味でも「ファイルからデータを読み込んで整形し、データベースに保存する」というような画面が必要ない、完全にコンピューターの中で完結するようなプログラムを書くことをオススメします。

# そして普通のエンジニアへ・・・

ここまで１年ほど、この記事に書いたことをやりながら、仕事で言われたものが作れるようになってきたら、ようやく「普通のエンジニア」になったと言えるでしょう。

このあたりから「文系」「理系」の意識がなくなり、同じ「エンジニア」として同じレベルで日々技術を磨いて成果を出すことが求められてきます。「え？君って文系だったの？」と言われるようなことがあれば、それはつまり他の人から見て情報工学を専攻してきた人と変わらない成果を出せている、ということです。「そうなんですよー」と自然に返しつつ心の中でガッツポーズしておきましょう。

しかし、ここでようやくスタートラインです。次は「スーパーなエンジニア」になることを目指して、引き続き勉強を続けましょう。

とは言ってもやることは今までと変わりません。サービスをより良くできそうな技術を見つけては詳細を調べ、サンプルプログラムを書いて遊んでみて、何となく理解したら実際に仕事で使って見る、ということを人に言われなくても繰り返せるようになれば、より成果の出せるエンジニアになれるはずです。僕の配属当時の先輩も、それができる方が多かったことを覚えています。

幸いエンジニアが新しい技術を見つけたり、より理解を深めたりするためのサービスは数多くありますので、ぜひ積極的に利用してみてください。大概は無料です。

以下にいくつか紹介します。

* [Qiita](http://qiita.com/)
    * このサービスです。技術的な内容に特化したブログなため、すべての記事一覧を眺めているだけでもだいぶ参考になります。
    * 一般的なブログサービスだと技術に関係のない「今日はこんなランチしましたー」のような記事や明らかなアフィリエイト目的の記事も混ざってしまうことを考えると、「技術的な記事しか投稿できない」のはとても大きなメリットです。
* [Github](https://github.com/)
    * 世界中のエンジニアのソースコードや議論を見ることができます。オープンソースのツールやフレームワークなどのリポジトリは見ていてとても勉強になることが多いです。
    * Githubに自分の書いたソースコードを上げてみたり、オープンソースのプロジェクトにプルリクを送ってみたり、というのがイケてるエンジニアになるためには大事だそうです。（僕はまだできず。。。）
* [Stackoverflow日本語版](http://ja.stackoverflow.com/)
    * 技術的な内容専門の質問サイトです。元々は[英語版](http://stackoverflow.com/)のみでしたが、少し前に日本語版ができました。が、情報量は世界中の人が使う英語版の方が圧倒的です。
    * 何かエラーが発生したとき、その内容でググるとだいたいこのサイトが出てきますので、英語版を含めてサイトの見方に慣れておくとスムーズに開発を進めることができます。
* [Twitter](https://twitter.com/)
    * まずは「Java」などの言語で検索して、人気のありそうなアカウントをいくつかフォローすると良いでしょう。タイムラインを見ていればその技術に絞ってツイートし続ける人（もしくはBot）が大体見つかります。

# 最後に

この記事の途中でも書きましたが、仕事としてエンジニアをやっていると意外と「文系」「理系」を意識する・されることはありません。エンジニアとして大事なのは「今まで何を勉強してきたか」ではなく、「今何ができるか」であり、さらに社会人としては「それを使って何を作れるか」が大事になるからです。

エンジニアは常に勉強し、新しい知識を手に入れたり今ある知識をさらに深めたりする努力がいつまでも必要になります。それは大学時代に何を勉強をしていたかは関係ありません。

そして、エンジニアの勉強はテストで点を取るための勉強ではありません。新しいもの、役に立つものを自分の手で自由に作り出すための勉強です。この記事では何度「勉強」という言葉を使ったかわかりませんが、エンジニアの勉強は学生時代のような机に向かってうんうん唸りながら勉強ではなく、新しい発見や体験が次から次へと得ることができる、とても楽しいものです。

ぜひ、昨日とは違うことができるようになることを常に楽しみながら継続して勉強することで、「え、君って文系だったの？まさか！」と言われてみてください！

最後に、[Soft Skills](https://www.amazon.co.jp/dp/1617292397/)という、「稼げる」エンジニアになるための心構えや実践すべきことが書かれた書籍を紹介して終わります。

この本は、エンジニアとして豊かな生活ができるようになるための考え方や習慣が、筆者（主にエンジニアの教育的なことをやっているらしい）の経験を通して書かれています。ブログを書く、自分で目標を立てて勉強する、といった真面目な話から、フィットネスに通う、といったちょっと変わった（でも実際は大事な）ことまで、とても分かりやすく書いてあります。

内容も細分化されていて、どこからでも読めるようになっていますので、ちょっと気分が向いた時に数ページ読む、といった読み方もできます。

[日本語版](https://www.amazon.co.jp/dp/B01GDS0994)もありますので、１冊買って少しずつ読んでみると役に立つでしょう。