【質問#130】プログラミング言語の覚え方について

質問・悩み相談の回答です。

質問

ツイッターで日生冷路土という名前の者です。

自分は今インターンでjavaを学んでいるのですが、専門学校時代ゲーム制作を学んでいたせいか動的には強いですが静的には弱いプログラムを打つようになりました。

また、レベルも初歩をようやく脱したレベルで、どうしたら早く一人前になれるのか試行錯誤しながら学んでおります。
そこで気になっている事があるのですが、学生は概念から覚えるのに対し、いざITの仕事に就くと開発ツールやフレームワーク、ライブラリなどの便利な機能を駆使して開発を短縮すると、学生の時に学んだものはあまり実践では活かされないないのではないかと思うのですがどうでしょうか?

javaが無料から有料に変わったり、一からある機能を作れるまでという会社側の方針四苦八苦しています。トライアンドエラーしやすい方が自分にとってはやりやすいのですが、覚え方を変えたほうがいいなどのアドバイス等はあるでしょうか?

最期に自分の背景などを軽くご説明しますが、専門学校時代はC++を学んでおりました。Webクリエイター認定試験初級持ちです。

回答

省略されてる(あまり詳しく書かれていない)と思しき箇所がいくつか見受けられるので、こちらの方で勝手に推測させて回答させて頂きます。もし違うよ、ということでしたら指摘して頂ければ、再度回答いたします。

動的には強いですが静的には弱いプログラム

動的、静的の意味がよく分かりませんでした。動的/静的型付け言語?ということでしょうか?それとも、ビジュアル要素が強くて画面が本当に「動く」というところを指しているということでしょうか?データベースからの入出力がメインになるような業務向けシステムのようなものではなく、ダイナミックにデータや表示UIが変化していくようなアプリ、みたいな。「ゲームを学んでいたせいか動的には強い」とあるので多分後者という前提で解釈させていただきます。

学生は概念から覚える

「概念」も何を指していらっしゃるのか、ちょっと分かりませんでした。「学生は」なので、専門学校で多分学ぶであろうプログラミング言語そのものの知識(構造化プログラミング、オブジェクト指向、データ構造など)という言語によらない基礎知識だったり、もしくは何らかのプログラミング言語の入門書に書いてあるような基礎的な内容のことを指していると解釈させていただきます。

javaが無料から有料に変わったり

質問の本筋からは外れますが、これは少し誤解がある(表現)と思います。OracleJDKは今後有償によるサポートとバイナリの配布が始まりますが、OpenJDKの開発はこれからも続き、無償で利用できます。AdoptOpenJDKなどではLTS(長期サポート版)もリリースされる予定です。

一からある機能を作れるまでという会社側の方針四苦八苦しています。トライアンドエラーしやすい方が自分にとってはやりやすいのですが、覚え方を変えたほうがいいなどのアドバイス等はあるでしょうか?

すみません、これもちょっとよく分かりませんでした。「何も無いまっさらな状態から1機能を作れ」とトップダウン的な仕様を与えられるよりも、トライアンドエラーを繰り返してボトムアップ的なアプローチで何らかの機能を実装するほうが性にあっている、ということでしょうかね。とりあえずそう解釈させて頂きます。

専門学校時代はC++を学んでおりました。Webクリエイター認定試験初級持ちです。

Webクリエイター認定試験というのは恥ずかしながら始めて知りましたが、調べたところHTML5/CSSなどの理解を問うような問題が出る試験のようですね。

というわけで、質問にお答えしていきます。

学生は概念から覚えるのに対し、いざITの仕事に就くと開発ツールやフレームワーク、ライブラリなどの便利な機能を駆使して開発を短縮すると、学生の時に学んだものはあまり実践では活かされないないのではないかと思うのですがどうでしょうか?

学生時代(専門学校)では当然ですが基礎から教えられることでしょう。そのプログラミング言語はどういう文法で、どういう機能があり、どういう場面でどういう設計をすべきか…というのを重視されます。しかしながら、IT関係の現場では「とにかく良さそうなライブラリを見つけてドキュメントを読み、使い方を覚えてサクッとそれを利用してシステムを組み上げる」みたいなスキルが重要視されることも多々有ります。業界によって多少の差はあると思いますが。

さて、そのような環境で学生の時に学んだプログラミング言語の基礎知識は生かされないかというと、私はそうではないと思います。

こないだTwitterで今回のケースにすごくマッチしたことを言っているひとが居たのですが(引用したかったが失念してしまった)、それは「車輪の再発明は良くないけれども、その背景には車輪くらい作れて当然だよな?という前提がある」というような言葉でした。これはまさにその通りだと思います。

具体的にお伝えしましょう。Webクリエイター認定試験を取っているとありますので、例えばおそらくご存知だと思いますが、jQueryという今はもう古典みたいな扱いをされているDOM操作・ユーティリティライブラリがあります。これが出てきた時代はまだJavaScriptも方言がひどかったり出来ることも少なかったりしてたときですが、そんな中でやりたい処理をズバッと一行で書けるjQuery(やprototype.js)はまさに「神」と言うにふさわしいライブラリだったように思います。

しかしながらたまに、jQueryで無茶苦茶な事をするソースコードも私はよく見てきました。具体的には複雑で大量のDOM操作を数msで繰り返すようなものなどですね。結果、ブラウザが極端に重くなったりデータによっては描画がちらついたりします。このコードは、jQueryが内部でなにをやってるか想像がつく人ならばまず絶対書かないようなコードでした。つまり、内部実装を予想できる人ならば「こうコードを書くと重いだろうから避けよう」と判断がつくところそれを出来ない人がいる。

SQLやデータベース設計でもよく有ります。リレーショナルデータベースやデータ構造(索引の仕組み)などの知識がほとんどない人が、不適切なインデックスを貼ったり、主キーすら設定しないテーブルを作ったり、nullばっかりのテーブルだったり全然正規化してなかったりとか。そういうスキーマに対してクエリの処理途中で組み合わせ爆発を起こして億単位のタプルを生成するSQLを書く人がよく居るんですよね。数行変更すれば計算量がO(n^m)からO(n)くらいまで減るのに、それが出来ない。そもそも自分のコードに問題があることすら理解できない。みたいな。

そういうことにならないようにするためには、今使っているライブラリやツール、サブシステムの気持ちを理解することが重要です。気持ちっていうのはつまり、それらがどういう仕組みでどのように動いているかという基礎知識で、専門学校その他で教えられる知識にほかなりません(専門学校で勉強したことが無いので間違ってるかも知れませんが)。

以上をもっと平易に簡潔にまとめますと、

「動けばいい良い」というソフトを作るなら、学校で勉強したことは必要なく、目的を実現できるライブラリとドキュメントの知識が重要になる。しかし、バグを出さないとか、大量のデータ、負荷でもちゃんと動く(スケールする)とか、設計変更に強いとか、可読性が高いとかいうコードを書くならばコンピュータとプログラミング言語の基礎を知った上で応用できる能力が必要になる。

ということになるかと思います。

そういえば、ソート使うならソートアルゴリズムくらいそらで書けるようにしとけ、みたいなのは自分は何度か言われたような気がしますね。

トライアンドエラーしやすい方が自分にとってはやりやすいのですが、覚え方を変えたほうがいいなどのアドバイス等はあるでしょうか?

トライアンドエラーによって学習を進めるほうが容易であるならば、私は無理に変える必要はなく、それで良いと思います。しかしながら先程書きましたように、「このライブラリはどのような仕組みになってるのか想像出来ない」ということが無いよう、疑問を持ったらそこから掘り下げていくことがとても大切だと思います。そうして前提を積み重ねないと、トライアンドエラーのみによって作られたソフトウェアはほぼ確実に「動けばそれでいい」というタイプの品質になり、データが増えたり想定してないケースが発生したりした時に酷いことになります。

プログラマをやるなら表面的なことだけでなく、アルゴリズムやデータ構造、計算量、その他コンピュータの基礎知識や関連する数学の基礎知識を有しているのは当然だと私は思います。少なくとも、それを知らなくてもある程度覚える努力はすべきでしょう。あくまでも私の意見であって質問者の方や読者に同意を求めているわけではないですが。

ただ、アルゴリズムもデータ構造も知らんし、自分が書いたコードの計算量の見積もりもできない、ブール代数もまともに知らないみたいな人はこの業界にたくさん居るのも事実です。そして、各種学校や、あるいは独学で勉強したことによって基礎がちゃんと出来てる人はそれが良くないと指摘して修正する力を持っているというのも事実として言えると思います。

質問者の方はおそらくまだまだ若いと推察しますので、もしこの業界でプログラマ(やそれに関連する仕事)をやって生きていくのであれば、学校で勉強したことを忘れず、むしろその基礎周辺をもっともっと掘り下げ、広げていって基礎も応用も出来るプログラマになっていただきたいと思います。