自分を攻略していく記録

自分がやりたいことを達成するには何をすればいいのか、その攻略していく過程をつらつらと

プログラミングの勉強をする前に知っておきたかったこと・知っておいてほしいこと

forやifを使ってプログラムを書いて、そのファイルを実行すると記述したことが実行されるで、それがどうやってゲームやアプリになっていくのか

大学生の頃に授業でJavaプログラミング言語)の課題を解いていて、ずっとそう思っていた。 if文for文プログラミング言語における基本的な文法)で簡単な数学の問題が解けても、それが一体どうやってゲームになったり、Webサービスやアプリになるのか全く検討がつかなかった。プログラミングの細かい文法だけ勉強しても全体感が全く掴めなかったので、結局その授業では大した理解が得られなかったのである。このような「プログラミング自体の勉強はやってみたけど、で、それで?」って現象は割とあるあるなんじゃないかなと思う。今となって思うのは全体感を掴まずに細かい文法を勉強をしてしまったのが原因だと思っている。

そうなってしまった当時の自分が知っておきたかった、と思うことを書いていく。具体的には、以下のようなこと。

  • ソフトウェアにおいて、プログラミングがどこでどう利用されているのか
  • 「プログラミングの勉強」と言うけど、自分が取り組みべきことは一体何なのか

以前、以下のブログを書いたが、このようにがっつり勉強しだす前に知りたかった内容にした。

diary.shuichi.tech

時間をかけることで結果的にプログラミングの全体感が分かったが、時間をかけないと難解だと思った。プログラミングを勉強してみたいという非技術職の人も含めこれからプログラミングを勉強してみたいと興味がある人にも参考になればいいなと思う。ただ、機械学習等の研究の文脈におけるプログラミングは、計算のツールの色が強く用途が異なる。ここではソフトウェア開発の領域におけるプログラミングについて考えていく。

TL;DR

  • 「プログラミング」はモノづくりのごく一部に過ぎず、プログラミング言語そのものよりもその背景にある考え方が大切
  • 非技術系の人がソフトウェアの理解のためにプログラミングを学ぶのは遠回りの可能性大
  • プログラミング学習には、「何か作ってみると良い」と言われて、どうしていいのか分からなくても大丈夫。できる人に、ブレイクダウンしてもらおう
  • 規模感によってエンジニアリングの役割は変わってくるのでそれを踏まえてインターン・転職先を探してみよう

ソフトウェアにおいて、プログラミングがどこでどう利用されているのか

プログラミングの教科書で出てくるような基礎的なプログラムと、実際にWebやアプリで動いているプログラムは結構異なって見える。プログラミングの教科書に出てくるようなプログラムは非常にシンプルで、偶数と奇数を判別するプログラムだったり正直使いみちがピンとこないケースが多い。一方で、Webやアプリは先人達のプログラムが何層にも積み重なった上に自分たちのコードを書いていく。雛形プログラムが存在し、そこに自分でカスタムしていくイメージになる。

では具体的にどんな感じでソフトウェアが構築されているのかかなりざっくりと見ていく。

ここではInstagramを例にとってみる。

InstagramはWebサイトとアプリ(iOSAndroid)の3つの利用方法がある。

f:id:ngo275:20190614013306p:plain:w600
InstagramのUI

ユーザが触れるWeb、iOSAndroid、これらを引っくるめて「フロントエンド」と呼ぶ。フロントエンドでは、フォローしている人の画像や動画、ストーリーを画面に表示する。Webやアプリの画面を表示するためには、データを取得しなければならないが、そのデータ取得の窓口になるのが「サーバ」と呼ばれるヤツだ。画面を更新しようとするとWi-Fi等を通じた通信が必要になるが、それはサーバにデータを問い合わせているからである。

f:id:ngo275:20190614020444p:plain:w600
流れ 1/2

次に、サーバはデータベースから必要な情報を検索する(Instagramほど巨大なサービスになるとこんなシンプルな構成ではないが、イメージはこんな感じ)。サーバは、自分がフォローしている人の画像や動画、コメントといった情報をデータベースから取得し、フロントエンドに返却して、フロントエンドはそれを画面に表示する。フロントエンドに対比して、サーバやデータベース等を引っくるめてバックエンドと表現される

f:id:ngo275:20190614020506p:plain:w600
流れ 2/2

大きな流れは上記の通りだが、これらの各登場人物の内部でそれぞれプログラミングが利用されている。プログラムが実行される環境には、iOSなのか、Androidなのか、Windowsなのか、様々なモノが存在し、プログラマはそれに応じてプログラミング言語を使い分けている。いろんな言語を習得している、と聞くとハードに感じるかもしれないが、日本語(標準語)をマスターすると関西弁や博多弁はなんとなくできるのと同様であるケースが多い(もちろん言語によるが)。

登場人物 言語 備考
Webフロントエンド JavaScript、HTML、CSS HTMLとCSSは厳密にはマークアップ言語と言われる
iOS Swift、Objective-C 最近はもっぱらSwiftが一般的
Android Kotlin、Java Kotlinが最近は人気
サーバ Java、Go、RubyPythonPHP、いろいろ JavaJavaScriptは全くの別物
データベース SQL 厳密にはプログラミング言語ではないけど分類のイメージ的にはここ

たとえば、ストーリーの機能を追加しようと思った時、Webフロントエンド・iOS・Androindでストーリーの画面に関するプログラムをそれぞれのプログラミング言語で書いておき、サーバ側もストーリーをフロントエンドに返却する窓口を作っておく必要がある。データベースに関しても、ストーリーを保存するための空間を確保する必要がある(こういったデータベースの変更をマイグレーションと呼ぶ)。それぞれのプログラミング言語で機能開発をすることになる。気をつけたいのは、Ruby on Railsのようなフレームワークだ。フレームワークとは、プログラミング言語とは違い、モノを作る上で頻繁に必要になる機能を集めた便利ツールである。Ruby on Railsは、Rubyというプログラミング言語を使って、簡単にWebサイトが構築できるが、Webフロントエンド、サーバ、データベースアクセス等全てがいい感じに処理されるようになっているので、それぞれの登場人物の関係性がよく分からなくてもそれぽくなってしまい、システム内部の理解がかえって難しいので注意が必要だ。

ソフトウェアエンジニアは、プログラムを書いたら、次に、各プラットフォームにそのプログラムを配置する必要がある。プログラムを書いて、それをアップロードして、ユーザからの入力(クリックとか)を待ち受けておくようにするのだ。Webサイトだったら自分でインターネットにプログラムをアップロードしてユーザからのリクエストを待ち受けるようにしておけばいいのだが、iOSAndroidの場合はユーザにアプリをインストールして貰う必要がある(Instagramのアプリを利用する時はApp StoreGoogle Playを通じてインストールをしなければならない)。このように、プログラムを各プラットフォームにセットする作業をデプロイと言う(英語で配置という意味)。

デプロイが完了すると、ユーザがそのサービスを利用できるようになり、ユーザ数の増加に応じて、機能の追加や、バグの修正をしていくことになる。その都度、プログラムを書いて、サーバなりにデプロイする。iOSのアプリをアップデートすると機能が増えていることがしばしばあるが、それは新しい機能の入ったプログラムをダウンロードしたからである。

ここではInstagramを例にとったが、ハードウェア(IoTとか)でも同様で、プログラムを実行するためのチップと電源があればそのチップにプログラムを焼いておくことで、好きなプログラムをハードウェア上で利用することができる。例えば、チップ(Arduinoとか)に温度計センサーを付けて、28度を超えると冷房のスイッチをオンにするというプログラムを書いてチップに焼いておくと、電源が供給されている限り、そのプログラムは実行される。

f:id:ngo275:20180505001828p:plain:w600
GPSを組み合わせたマイコンのイメージ

「プログラミングの勉強」と言うけど、自分が取り組むべきことは一体何なのか

プログラミングの勉強をしたいけど何をすればいいのか、としばしば質問されるが、これは難しい…。どうやってプログラミングを勉強するのか、といった方法論はネットでたくさん引っかかるしオンライン講座も充実しているので比較的どうにかなりやすいが、何を勉強するのか、という質問は難しいと感じる。

f:id:ngo275:20190619000313p:plain:w600
プログラミングはソフトウェアのごく一部の要素に過ぎない

上で書いてきたようにプログラミングがどこで利用されているのか見てみると、「プログラミング」はWebサービスやアプリといったソフトウェアを作る上で、部分的なものに過ぎないのが分かる。それを踏まえた上で、プログラミングの勉強について考えてみる。

技術系ではない人が技術のことの理解のためにプログラミングを勉強したい場合

技術系ではない人がテクノロジーのことをより理解するためにプログラミングをやってみるのはとても良いことだと思う。ところが、プログラミングの文法や書き方が分かることは、システムがどう動いているのかの理解にそこまで繋がらないのが正直なところだ。大学でプログラミングの課題が出た時はまさしくこの問題に直面した。「で、だから何?」問題だ。「AI、機械学習といえばPython」、「Web開発といえばRuby」といった流れでプログラミング言語を勉強してみるケースを見かけるが、それでAIやWebの仕組みを理解するのは到底厳しい。

プログラミングの勉強は、言ってみれば、公認会計士試験の勉強をするのと同様だと思っていて、ソフトウェアエンジニア(会計士)になりたいなら必須だが、テクノロジーやシステムの内部(財務諸表の読み方やファイナンスの仕組み)を学ぶためにプログラミング(公認会計士試験)を勉強するのはちょっと違うアプローチに感じる。監査業務はできないが、財務諸表を見てビジネスの様子が想像できる人は大勢いる。プログラミングも同様で、コーディングはできないが、アプリがどう動いていてどう作っていけばいいのか知っている人も大勢いる。エンジニアではない人が、エンジニアになりたくてプログラミングの勉強するのでない限り、プログラミングをやる必要性はそこまでないと思う。

f:id:ngo275:20190619000656p:plain:w600
プログラミングから始めるのはなかなか厳しい

学ぶのであれば、プログラミングより先に以下のような項目かと思う。

  • プログラミングの背景にある思想。プログラミングに重要なのはプログラミング言語そのものよりその背景にある考え方であるUNIXという考え方ーその設計思想と哲学という本が勉強になると思う。「オブジェクト指向」と呼ばれる思考方法も学ぶとプログラマの頭の中が分かるようになる。

  • ソフトウェア開発のフロー。アジャイルウォーターフォールの概念や、その違い。スクラム開発の概念等。実践はともかく、考え方については書籍(スクラム実践入門)から学ぶことができる。要件定義から始まって、仕様に落とし込み、タスクとして細かく落としていき、デプロイまでする。と言ったような流れが分かると普段ソフトウェアエンジニアと呼ばれる人が何をしているのかが分かる。

  • データベースについて。ER図や簡単なSQLの使い方等。ER図とは、データベースの設計図のようなものである。描けるようになる必要はないが、プログラミングをする上で重要なオブジェクト指向の概念に触れることができるし、普段触っているアプリが、どのようにデータベースに記録されているのか、ということはすごく勉強になる。それに関連してSQLやBigQueryを使った分析方法も知るとビジネスに生きてくる。ソフトウェアを提供している会社は必ず分析ツールを導入しており、自分たちのサービスがどれくらいどのように利用されているのか常に分析している。SQLやBigQueryはデータベース検索のための特殊な言語だと思えばよい。

  • APIについて。フロントエンドはサーバにデータを問い合わせるが、APIと呼ばれるインターフェースがその間に存在するのが一般的だ。サービスによってAPIの仕様が異なっており、システムの内部を理解する上で非常に勉強になる。昨今は銀行APIというワードが流行っているが、APIを理解しておくとそういう技術的なテーマも腹落ちしやすい。これに関連してJSONと呼ばれるフォーマットも知っておくと良いと思う。実際に暗号通貨の取引所が公開しているAPIを見て勉強すると面白いかもしれない。

  • (参考)UIUXについて。Webデザイナーが利用するようなデザインツールまで使える必要はないが、Googleが提唱しているマテリアルデザインや、Appleが提唱しているHuman Interface Guidelines等にも目を通しておくと良い。日本語訳もググればあるはず。

  • (参考)Gitフローについても知っておくと良いかも知れない。プログラマはGitと呼ばれるバージョン管理ツールでソースコードを管理するのが一般的だが、そのコンセプトが若干慣れにくい。スプレッドシートは複数人で編集可能だが、ソースコードも同様に複数人で編集可能で、それを簡単にするのがGitである。

これらのことはソフトウェアエンジニアだとプログラミング以外に求められる基本的な要件でもある。これらを理解してさらに追求したくなったらプログラミングを勉強していけばいいと思う。プログラミングの背景にある考え方が重要なのであってプログラミング言語そのものが重要なわけではないということに気をつけてほしい。

ソフトウェアエンジニアなるものに興味があってプログラミングの勉強をする場合

この場合は、プログラミングの勉強はもちろんだが、上で書いたようなことも学んだ方が良い。

プログラミングの勉強をしたいなら、何かモノを作りながら学ぶのが一番。という意見もよく聞くが、そもそもどういうモノがどれくらいの難易度で作れるのか分からない人にそうアドバイスするのは手厳しい感がある。すでにそういう作りたいモノが思い描けているのであれば良いのだが、思い描くだけでも意外と難しいのも事実。プログラミングが分かる人に、作ってみたいものや何ができそうなのかを話してみて、それに必要となる技術や難易度をブレイクダウンしてもらう(全体感を示してもらえる)のが良いと思う(周りにそんな人いないよ、という方がいましたらTwitterで連絡いただければ話を聞きます)。何を勉強すればいいのかが分かったら、あとは、Progateやオンライン講座で勉強していけば良いと思う。

大切なのは、ソフトウェアエンジニアの人が知っておくべきことはプログラミング以外の要素が想像以上に大きくて、プログラミングだけできてもダメだということ。僕は初めそれを知らなくて、プログラミングだけ勉強したが、結局良く分からなかった。

プログラミングを勉強した先について

ソフトウェアエンジニアに興味がある人が、プログラミングを勉強したとして、その後にどういう選択肢があるのか少し深掘りしてみる。フロントエンドとバックエンドに分けて説明したが、会社やプロジェクトの規模によって、個人がどこまで関与するかでエンジニアがやるべきことや求められることも大きく異なってくる。

  1. 数人規模の開発

  2. 十数人~数百人規模の開発

  3. 数百人~の開発

1の場合は、新しいサービスのアイデアのプロトタイプを作ったり検証、立ち上げのフェーズ。この規模感では、1人がやるべき領域が広くなり、SwiftでiOSアプリの開発をしつつ、サーバをGoで書く、と言ったこともある。大量のリクエストをうまくさばくと言うよりは、トラブルに柔軟に対応しつつ、最速でデプロイすることにフォーカスする。

2の場合は、ユーザがある程度付いてきて、サーバダウンもなく、多くのリクエストに対応できるように開発するステージ。新機能開発だけでなく、バグ修正、リファクタリングソースコードのお掃除)、テスト、とまんべんなくリソースを割かないといけない。1人が担う仕事が特化してきて、サーバの開発をする人はサーバ、フロントエンドを開発する人はフロントエンドにフォーカスするのが一般的。もちろん、スキルの幅が広いソフトウェアエンジニアであれば、人が足りていないところを柔軟にカバーする動きをすることはある。1の場合と比べて各領域に対してより深い知識理解が求められる。

3の場合は、SEのイメージになる。降りてきた仕様に対して納期までに完成させるのが最重要項目になる。個人に求められる技術力はそこまで高くはない。

1、2、3のどれがいいのかは個人の性格や好みによるところが大きいと思う。また、1から3のように他のセグメントに移動するのはそこまで楽なわけではない。余談だが、給与に関しては、実力主義だが給料が良いのは2で、スタートアップでリスク(そもそも会社がなくなるとか)があるものの上場や売却を狙うなら1、といったところ。3は昔ながらの人海戦術的なソフトウェア開発といった印象で、ちゃんとした場所を選ばないと結構大変そうなイメージである。

初心者からエンジニアとしてのキャリアを探すのであれば、こういった選択肢があるのを踏まえた上で、インターンシップ探しや、転職活動をするのが良いと思う。知人経由やTwitter経由でインターンシップを探したり転職先を探すケースはたまに見かけるが、必ずしもそういう人が周りにいるとも限らないと思う。そういうケースではWantedlyが一番良いのかな、と思う。現に、僕が正社員として初めて入社した先に連絡した媒体はWantedlyだった。当時、バイトの求人もなかったが、その会社や事業に興味があったので、とりあえず連絡してみて、面談をしてバイトをさせてもらえることになった。

www.wantedly.com

まとめ

プログラミング学習についてつらつらと書いてきたがまとめると、

  • 「プログラミング」はモノづくりのごく一部に過ぎず、プログラミング言語そのものよりもその背景にある考え方が大切
  • 非技術系の人がソフトウェアの理解のためにプログラミングを学ぶのは遠回りの可能性大
  • プログラミング学習には、「何か作ってみると良い」と言われて、どうしていいのか分からなくても大丈夫。できる人に、ブレイクダウンしてもらおう
  • 規模感によってエンジニアリングの役割は変わってくるのでそれを踏まえてインターン・転職先を探してみよう