TL;DR
はじめに
Livesense Advent Calendar 19日目を担当する Yoichiro Hiranoです。今年10月からジョインさせていただき、転職会議チームで開発を行っています。
もともとフロントエンド周りの開発業務を行っていましたが、ここ2ヶ月半の間はひたすらバックエンド開発を行ってきました。全く触れたことのない技術を使った、全く経験のない領域の開発をキャッチアップしながら行ってきたので、短期間ではありますが多くのことを学ぶことができました。
今回はその中で私が実践した技術の学習方法と「複数言語や専門領域外の知識を得る有用性」について話したいと思います。
筆者のそれまでの保有スキル
- フロントエンド開発を3年ほど経験
- バックエンド開発はGoogle Firebaseを使ったミニマルなサーバーレス構成のものを1年ほど経験
- リレーショナルデータベースやSQL操作の経験はゼロ
- 言語経験はほぼJavaScript,TypeScriptのみ
行った業務(アウトプット)と学んだ知識
Railsを使ったWebページ作成
求人情報の一覧を表示するページを新規に作成しました。マークアップやフロントエンドJSは経験があったものの、Ruby on Railsを使ったWebシステムをここで初めて実装し、Ruby, Ruby on Rails1, RSpecなどの技術やMVCフレームワークの実践法を学びました。
API作成
既存DBからデータをGETするREST APIエンドポイントを作成しました。ここではRuby on Railsを使いつつ、 Active Record を使ったDB連携を学習しました。
テーブル作成、SQLチューニング
リクエストの度にサーバで算出していたリアルタイム性不要なデータをDBに格納しようということで、テーブルを新規に作成しました。
DBのテーブル新規作成からインデックスと外部キーの指定、データ更新に至るまで一通りのテーブル操作をSQL知識0の状態から実装しました。
同時に、10以上のテーブルを結合するSQLを修正し、そのパフォーマンスを向上するために試行錯誤する経験もしました。N+1問題、インデクシング、駆動表と内部表など未知の問題に次々遭遇したので、実感値としてはこれが一番大変でした(この辺はチームメンバーの方に協力いただき大変助かりました)。
日次バッチ作成
上述のテーブルを日次で更新する、Argo Workflow で実行するバッチ処理を追加しました。
すでに運用されているKubernetesの各種設定ファイルに記載を追加するだけだったので作業自体は容易でした。ここではそれまで全く知らなかったKubernetes is 何?というところと、理解が曖昧だったDockerについて改めて学習しました。
学習(インプット)方法
Ruby
Ruby on Rails チュートリアルを読んでハンズオンをこなしました2。RubyやRailsだけでなく、MVCフレームワークやテスト駆動開発なども含めた結構盛り盛りな内容で、Web開発経験があれば適宜取捨選択して読み進められそうですが、初学者は消化不良になりそうだなと思いました。ちなみに解説動画もあるようですが、個人的にはドキュメントベースで十分かなという印象でした。
また学習初段階では、すでに知っているJavaScriptとの対応を意識しながら「JSでこう書くのはRubyだとこう書く」というのを穴埋めしていく形で「自作Rubyメモ」を作っていきました。個人的にはこの方法は学習速度が相当早い実感があり、すでに特定の言語を習得済みであれば試してみるといいかもしれません。ただ、JSにない文法についてはそもそも知らないので、ある程度インプットしたあとはチュートリアルやオブジェクト指向スクリプト言語 Ruby リファレンスマニュアルを参考に知識を補完していきました。
Rails, Active Record
Ruby on Rails ガイドを読み込みました。Ruby on RailsチュートリアルでもRailsには触れられていますが、あくまでチュートリアルなので体系的な知識を得るにはこちらが参考になりました。Active Recordやルーティング周りなどはとりあえずこれ読んでおけば大丈夫かなと思います。実コード例がちょっと少ないのでそこだけ自分で調べて補填してました。あとコンテンツ量多すぎてすべては読めていないです。
SQL, MySQL
SQLについては、かつて基本情報技術者試験を受けたときに読んだキタミ式イラストIT塾 基本情報技術者(リンクは令和3年版) を読み直しました。ただごく基本的な操作しか解説されてないので、そこからはネットの記事等を漁ってキャッチアップしていきました。
MySQLについては日本語の公式ドキュメントが充実しており、そちらを参照しながら学習を進めました。
Docker, Kubernetes
この辺りは必要なタスクをこなすために最低限の知識をインプットした程度で、まだ分かっていないことも多いです。
Docker、Kubernetesって何?みたいなところはイラストでわかるDockerとKubernetes Software Design plusを読んで学習しました。コンテナ技術についても丁寧に(若干冗長なくらい)解説されています。もともとコンテナ技術に関してはブログ記事を読む程度で「分かっているようでよく分かってない」レベルだったので、概念レベルの理解にはこれが一番参考になりました。スラスラ読めるのでオススメです。
その他、参考にした記事を挙げておきます。
得た知見と伝えたいこと
自作メモを作り、知識をアウトソーシングしよう!
学習方法で軽く触れましたが、私はなにか新しい技術や知識を学ぶ時、とにかくメモを残していきます。この**「自作メモづくり」は最強の技術学習方法**だと思っています。今回もこのおかげで短期間で知識をキャッチアップし、効率良く業務を遂行できたと言っても過言ではありません。各々のやり方で似たようなことをしている方も多くいると思いますが、やってない人にはぜひ試してほしいという思いも込めて、今回は私のやり方をご紹介します。
メモという「記憶」の充実度が開発効率に直結する
なぜ自作メモを作ることが最強なのかというと、
①メモする(言語化してアウトプットする)ことで理解が深まる
②メモが「第二の脳」3として機能する
からです。特に②が、エンジニアとしての作業効率向上に大きく貢献すると思っています。
新しく得た知識を検索をかけられるメモ帳アプリなどに逐一書き残し、知識が蓄積されてくると、そのメモは参照可能な「記憶」の役割を果たします。それは自分の脳の記憶よりよほど正確で、思い出すのが容易な(検索可能な)「記憶」になります。
そうして後日「これどうやって書くんだっけ」「前もこんなエラー出たな」みたいになった時は、まず自作メモを参照します。メモに過去の実装やつまずいたことが書き込まれていれば、知りたいワードを検索するだけで、その時の正確な記憶と経験を蘇らせることができます。
こうすることで、曖昧な記憶を思い起こそうとして悩む時間をゼロにすることができますし、結局忘れたから調べなおそうとなったときにも、ググって調べるよりはるかに速く探している答えにたどり着くことができます。一度学んだこと、経験したことに対するアクセスが格段に速くなるんですね。目的の情報にいかに早くたどり着ける(環境を作っておく)かがコーディングを効率的にするためには重要なので、それにこの自作メモが最適、というわけです。
自作メモの作り方
具体的には、私は次のような感じでメモを作成しています。
- チュートリアルやドキュメント、調べた記事、調査したエラー内容をコピペする
- 基本的な文法や概念
- エラーのログ
- その他「これまた使いそうだな」と思うことはとりあえずメモっとく
- 実際に実装したコードなどをスニペットとして一緒に貼り付けておく
- 見返したときに「あぁこの時のこれか」となり思い出すスピードが上がる
- 自分の理解を深めるためのメモや思ったことを追記する
- 体裁はとりあえず後回しにしてとにかく書き残す
- あとで検索して自分で分かればOK
- メモ作成自体に労力をかけすぎない
- 知識を「覚えよう」とはせずとにかく書き残す
こうして実際に今回作ったメモの一例が以下のようになります。Typoraというメモアプリを使っています。
こんな感じで新しい知識を得るたびメモを蓄積し充実させていけば、その後の開発効率は格段に向上するはずです。
複数言語を習得しよう!
「言語は複数学んどこう、だって学習コスト低いし学べること多いしオトクじゃん」というのが、今回の一番の気付きであり伝えたいメッセージです。
言語の学習コストは二言語目からめっちゃ下がる
Rubyを学んだあとの一番の所感は「新しい言語の習得って案外ラクだな」でした。
当たり前といえば当たり前ですが、条件分岐など基本的な制御構造は言語を問わず共通のため、その具体例をすでに知っていれば「あぁJavaScriptでこう書くやつはRubyだとこう書くのね」とすんなり理解できます4。DRYやYAGNIといったお作法的なところも言語共通です。言語よりもむしろ、新しいパラダイムや概念を含む技術を学ぶ方が大変なことも実感しました。今回で言うとActiveRecord(ORM)やSQLチューニングとかですね。
私はこれまで、新しい言語を学ぶことに対して「結構ハードルが高い作業だ」という印象を持っていました。最初にプログラミングを学んだ時と同様の労力と時間がかかるのでは、と。なので、業務的な必要性もあいまって、すでに習得済みでグイグイ人気が高まるTypeScriptにこだわり、食わず嫌い的に他の言語を学ぶことを避けてきました5。その一方で、いろんな言語を扱える人を勉強会や転職ドラフトなどで見るたび「コイツTUEEEE…」と畏怖していました。
今回の経験を経て、もちろんその言語の業務経験がスキルであることに変わりはないですが、複数言語を扱えること自体のハードルはそれほど高くない、という印象に変わったのは大きな発見でした。
既知の言語や周辺技術に対する理解も深まる
複数言語を学んだことで「すでに知っていたプログラミングのパラダイムや抽象概念に対する理解がより深まった」とも感じています。
最近読んだ本 の受け売りになりますが、人間の知的能力の発展は
- 具体的な知識の量的拡大
- それら知識の抽象化(一般化や概念化)
の2つの方向性で表すことができます。これによれば、複数の具体的な事象から共通の抽象概念を見出すことでも、知的能力を向上させることができます。
※出典:細谷 功 「具体⇔抽象」トレーニング 思考力が飛躍的にアップする29問 (Kindle No.388)
これはプログラミング言語にもあてはめることができます。
プログラミングには共通する制御構造(条件分岐、反復操作など)やパラダイム(オブジェクト指向、関数型プログラミングなど)があり、一方で言語はそれらの具体的な記述・表現方法です。抽象概念として制御構造やパラダイムがあり、その下位に具体的な方法として言語がある、という関係性ですね。
たとえば「JavaScriptのクラス文はRubyにもあって、それはこう書く」ということが分かると、クラスという概念をJavaScriptとRubyは共通で持っている、ということが分かります。上述した学習コストの低さも、抽象概念に対する一定の理解と、その具体例をすでに知っていることに起因します。
「JavaScriptもRubyもオブジェクト指向言語なんだから、そんなの自明じゃん」と言われればそれまでなのですが、、最初にプログラミング言語を学んだときって、そうは言いつつも具体的な表現方法の理解に終止すると思うんですよね。「どうやらクラスというものがあるらしくて、このコードはそれを表してる」みたいな。少なくとも私はそうでした。
複数言語を学ぶことで 「この記述は別言語でも使ってるあのパラダイムを表現している」「この記述は言語特有の仕様だ」みたいなことが、学んでいる言語についても既知の言語についても一歩踏み込んで分かりようになります。何が言語的な表現の違いで、何がパラダイム的・概念的な違いなのかが見えてきて、それまでなんとなく分かったつもりだった概念への理解も自然と深まっていきます。そのフローを経て初めて、それぞれの言語の特徴や得意とする分野や使いドコロを実感を持って理解できる、と個人的には思いました。これは言語に留まる話ではなく、技術全般に言えるのではないかなと思います。
さいごに
長くなってしまいましたが、Webエンジニアとしてスキルの幅を拡げたい人、Rubyやバックエンド/インフラ技術をこれから勉強しようと思っている人の参考になれば幸いです。
知識をメモし、言語は複数学び、より快適で視座の高いエンジニアライフを送りましょう!