エンジニア向け学習法
はじめに
こんにちは!開発課のIです。入社して1年経ちました。もともとは、Python、JAVAメインでソフトウェア開発をしていましたが、入社後はPHPで開発をしています。
今回のブログ記事では、私が何となく意識している「慣れていない・興味のある言語や技術で開発を進めるための学習」を言語化する良い機会だと思いましたので、共有いたします。
※それぞれの分野を詳細に解説するのではなく、あくまでも、「どのように学習し、何を学ぶか」を示す程度のものとなります。
本記事における「理解」とはどのような状態を指すのかを明記しておきます。
「理解」とは下記の条件を全て満たした場合の状態と定義します。
①その物事や対象の定義を示せる
②その物事や対象の具体例を2つ以上示せる
③その物事や対象の具体物を再現したり、応用したりすることができる
一般に、①②を満たす場合「形式的理解」と呼び、①②③を満たす場合「実践的理解」と呼びますが、本記事では「実践的理解」を単に「理解」と呼ぶことにします。
動機付け
学習する上で課題となるのが、モチベーションの維持です。おそらくここが最も重要です。私のモチベーションの保ち方は「内発的動機付け」と「外発的動機付け」の2種類に分けられます。そして、「内発的動機付け」と「外発的動機付け」は相互作用し、モチベーションの維持がされるというイメージです。
学習への内発的動機付け
自身の内側から沸き起こる興味や関心を増やすための方法です。強制力はなく、ストレスのない学習が期待できます。
面白そうな技術に触れる
- 最近流行っている技術(AIやVR、SNS、便利ツール)に触れることで、どのような仕組みで成立しているのか思考を巡らす。
- オシャレなデザインのアプリを眺めて「こんなアプリやネット空間を提供してみたいなぁ」と感心する。
- 技術記事を探索して、その技術を真似てみる
- 自分の技術では無理だと感じた場合、「どこから無理なのか」を調べてみる。そして、「意外とできそうだ」という感覚をもったり、「ここさえ分かれば実装できる」などの見通しをもったりしてみる。
便利なアプリを利用し、自分のアプリに組み込めないかを考える
- 業務ツールやOffice製品などで採用されている機能の仕組みを考える。
- 自分が利用しているツールで「あったらいいのに」という機能を実装してみる。
作ったアプリを触ってもらう
- 使いづらさなどのフィードバック、改修の必要感を実感し、「自分さえ分かっていれば良い」という仕様から脱却しようという意識を高める。
- 良い評価は素直に受け止め、その機能の抽象化を図り、他システムへの再利用性を大切にする意識を高める
学習への外発的動機づけ
自身の外側から学習を促すような刺激を与えるための方法です。自身のコンディションに左右されず、定期的な刺激が強制されます。
PCを起動すると開発環境が起動するように設定する
Windowsのスタートアップに起動バッチを仕込んでおき、自分が使う開発環境を起動するように設定しておくのがおすすめです。PCを起動してすぐにゲームやSNSをすることが減ります。
例)バッチファイルでWEBアプリケーションサーバを自動起動するなど書いておきます。
cd C:\xxx\python\app
.venv\Scripts\activate & SET FLASK_APP=app & py controller.py
毎日、PCで何かする時間をアラームにセットしておく
夕方~夜アラームをセットすることで、「毎日30分~1時間程度、何かする」を習慣化するのもおすすめです。(私の場合は23時に、動画を見ながらでもいいので、少しずつ開発しています)
自分が開発を始めやすい言語にする
私は数年前まで、プログラミング言語の基本さえ知りませんでした。ですが、職場や自分のPCにExcelのVBAがあり、業務効率を図る目的でVBAを始めました。その中で必要感をもちながらプログラミング言語を抵抗なく学び進められたことは、学習に大きく影響していたように思います。
自分のペースを探す
ここまでで、動機付けの方法を書きましたが、モチベーションだけで解決できない問題もあります。それは、自分の体力です。通常の仕事やプライベートと並行して何かを自発的に学ぶことは大変なことです。無理なく、継続して進めるべきです。
できるだけ小規模な成果物をこまめに出し続けて、できることが増えたという達成感を大切にする。
小規模な成果を組み合わせて大規模なアプリ構想が生まれてくることもあります。技術的に可能かどうか分からない大規模な成果を目指すよりも現実味のある目標となるでしょう。
- 新しい言語の環境構築をして「Hello World!」を出力して終わる。そこから先は明日。
- Windowsデスクトップアプリで、ただ単にボタンが押せるだけの意味のないアプリをexeファイルに出力してみる。機能実装は次回。
- 今まで問題なかった処理でエラーが出てきた。出力されたエラーを調べる。今までの状態に巻き戻し、エラーになる処理の検証は明日行う。原因が分かったら、コメントなどに調査成果として残しておく
- WEBアプリで1機能の実装を予定。バックエンドとフロントエンドの設計をして、まずは、バックエンドからDBのデータを表示する。(フロントまでは手をださない)
あまり、学習計画を立てすぎない
私の経験上、IT分野の学習において、学習計画通りに理解できたことはないです。
独学で新しい分野を理解するまでに時間がかかるのは当然ですし、予期しない部分で躓くことは頻繁にあります。また、システムやアプリの性質上、「エラーが起きているけど無視して保留」というのは、なかなかにリスクがあります。一時的にスキップすることはあっても、いつかは向き合わなければなりません。
そうなると、学習計画通りに進められなかったことを負い目に、モチベーションが下がることがあります。そして、学習計画を作り直すことに時間をさくことも本末転倒と言えるでしょう。仕事なら別ですが、個人でやるには時間がもったいないです。
しかしながら、がむしゃらに勉強しても、見通しがもてず、気が遠くなることもあります。大体の計画を立てておく程度でよいかと思います。
何を学ぶか
新しい言語や技術を学ぶときに、ただ闇雲にすすめたり、検索して出てきた記事を点々と学ぶのは効率的ではないでしょう。私の経験で学んだことや必ず抑えている学習内容を示しておきます。
普遍的技術の学習
IT全般知識
何か興味や学びたい分野ができたとき、その分野におけるIT用語を中心に学びます。そのIT用語の定義や具体例を抑え、形式的理解をしておくことで、その分野に強い言語やツールがネット検索しやすくなります。そこから「言語選定、開発環境選定」を行い、環境構築に結び付けるわけです。
例えば「AI」を学びたいとなれば、Python言語選定になりますし、その上でWEBアプリとしてリリースしたいとなればフレームワークに「Django」「Flask」などを選定するでしょう。開発環境として、AIは「GoogleColaboratory」「Jupyter notebook」で開発や検証するか、ローカルで初めからWEBアプリとして開発するなどの選択肢も出てくるでしょう。
また、OSの基本的な操作(WindowsだけでなくLinuxなども含む)や、環境構築方法(VirtualBox、Dockerの利用)なども色々な組み合わせがあります。
プログラミング全般の学習
プログラミング言語が決まった後学ぶ内容は大体、以下のもので充分です。
文法と記法を理解する
演算子(数値、文字列結合)、論理演算子
変数、配列の宣言(静的型付け言語であれば、型宣言を含む)
if else,for foreachなどの処理ブロック
関数メソッド宣言 function
私はこの段階で、「九九表」を出力したり、「素数判定関数」を作るなどして練習しています。理解するまで、ひたすらサンプルコードを書きます。
クラスとオブジェクトを理解する
プログラミングをする上で、処理をひたすら書き連ねるということは、メンテナンス性を著しく下げることになります。最近のプログラミング言語は大体「クラス」「オブジェクト指向」をサポートし、「再利用性」「単一責任性」「多様性」などを重視する傾向にあります。以下の内容を抑えておきます。
- クラス継承(オーバーライド[再定義]、隠蔽、ポリモフィズム[多様性])
- クラス変数、メンバ変数
- 修飾子(public,protected,private,staticあたり)
- 関数、メソッド(オーバーロード[同名関数の複数定義]、ラムダ式、無名[匿名]関数)
特にクラス継承の概念は非常に重要です。クラス継承により、同一の関数を呼び出す際に、異なる処理を実装したい場合(多様性)が様々な場面で出てきます。イメージだけでもとらえておくことをおすすめします。自身のコーディングにも役立ちますし、有名なライブラリでも頻繁に採用されています。ライブラリの処理シーケンスを読み解くためにも必須です。
以下の項目は余裕があるときに触れます。
マルチスレッド、マルチプロセスを理解する
DB操作やそれに伴うデータ操作で時間がかかる大規模な処理を行う場合に、マルチスレッドを採用することがあります。また、単一プロセスの制約を受けたくないこともあります。ゲームを作成する際には、1つのプロセスで再生できる動画や音源は1つという仕様がある場合などにBGM+キャラクタの声を実現させるために、マルチプロセスを採用することもあります。
デザインパターンを理解する
優れたクラス設計を抽象化したものやコンセプトをデザインパターンといいます。機能実装の目的に合わせて、設計コンセプトを選定する際に役立ちます。
例えば、複雑な初期化処理をもつ、クラスAとクラスBとを併用してシステムを組まなければならない場合、クラスAのオブジェクトとクラスBのオブジェクトを別々で生成して処理を書くこともできますが、これは「クラスAとクラスBの初期化処理の生成が負担」です。この初期化処理の負担を軽減するためのコンセプトとして「Builder」パターンというものがあり、「クラスAとクラスBの初期化処理を隠蔽」するためのクラスCを定義するというものです。これにより、初期化ミスをなくし、開発者は安心してクラスCを媒介に、クラスAとクラスBの初期化ができるのです。
デザインパターンは有名なもので23種類程度(GoFで調べてみましょう)あります。コンセプトや設計を意識する場合は学習してみることをおすすめします。
言語ごとの差異を知る
自分が学んだ開発言語以外にも興味がでてくることがあったり、別言語が必要になることがあります。しかし、全てゼロから学び直しということはありません。プログラミングの感覚や先ほど紹介した普遍的技術は同じです。故に、2つ目以降の言語は、言語ごとの差異を意識して学ぶだけで充分です。
私は「比較的最近導入された記法」はないかなどを調べます。例えば、「アノテーション」「デコレータ」という関数内の処理を関数外から装飾・改変する技術があります。よく「@」を使って記述されます。しかし、これはJavaやPythonにあってもPHPやJavaScriptにはないです。個人的には、かなり便利なので全プログラミング言語で実装してほしいです。他にはラムダ式の有無などもあります。
また、「ライブラリの充実具合」という観点も大切です。少し触れましたが、Pythonは「AI開発ライブラリ」がとても充実しています。Javaにはほとんどありません。逆にJavaは「トランザクション処理やマルチスレッド」などの処理の実装や厳密性(停止、終了、優先度まで管理できる)に強く、Pythonはこれらの処理の実装や管理が弱いです。
アプリケーションの構造を理解する
現状、主なアプリケーションの種類としては「インストール型アプリ(デスクトップアプリやスマホ、Androidアプリ)」「WEBアプリ」となるでしょう。これらのほとんどの場合、アプリケーションは「フロント(ユーザが触る部分)」「バックエンド(ユーザが触れない部分)」「データ(ユーザごとに保持したいもの)」に分けられます。フロントには「イベント」を登録しておき、そのイベントに合わせてフロントの関数やバックエンドの関数を呼び出します。この関係性を抑えておけば充分です。
これらの実装を開発言語のデフォルトのライブラリだけで行うのは(つまり、フルスクラッチは)大変です。その言語のフレームワークを知ることや、技術記事を読むことをおすすめします。
データの管理(永続化)を理解する
先ほどのアプリケーションの構造で触れた「データ」を扱うには次の3パターンあります。
SQLライブラリ
DBMS(データベース管理システム)を扱う言語(SQL)を操作するライブラリを導入する。データ抽出をするための機能が充実している。開発者の意図したSQLを直接実行できる。
O/Rマッパー
SQLライブラリをラッピングし、できる限りSQL言語の文法に依存せず、クラスやオブジェクトの関数呼び出しのみでDBMS操作を完結させるためのライブラリ。SQL言語に依存しないため、SQL言語の変更に強い。
例)PostgreSQLからMySQLへの変更などが容易(本来ならSQLの文法など全て見直し)
テキストファイル(もしくはJSON、YAMLファイル)
各言語のテキストファイルを管理するライブラリを利用する。SQLなどのインストールが不要。データ量が多い場合、SQLと比べて遅くなることや、特定のデータを抽出するには機能が乏しい。
アプリケーションの連携を理解する
アプリケーションの構造を意識すると当たり前のことですが、「データ」を共有してしまえばアプリケーションは簡単に連携できます。開発言語や環境の壁を超えることができるわけです。その連携手段は以下が主流でしょう。
(1)APIの連携
(2)DB、ファイルの連携
(1)はアプリケーションが連携用にリクエストを受け付けるようにしておき、要求に応じて、データを作成、提供、更新、削除をすることで連携を実現するようにします。(2)はAPIを用意せず直接データの作成、提供、更新、削除をします。ただし、この場合、データを操作するアプリケーションが複数存在することになるため、データの整合性を保証しなければなりません。また、DBやファイルの共有が許可されないことも当然あります。
比較的新しい技術の学習
スマホアプリ、AI、3D空間(VR)、WEBRTCなど、技術の進化は止まりません。これらの新しい技術を学ぶことは、仕事で使う技術とは別に触れておいて損はありません。しかし、それらを学ぶには、いくつか障壁があります。
- 日本語の記事が少ない
- 技術難易度が高め
これらの対策として、私が実践しているのは以下です。
- ChatGPT・CopliotなどのAIの活用
- 公式ドキュメントを読むか、チュートリアルを試す
新しい技術はだいたい英語の記事です。翻訳しながら読むか、AIに聞くのが早かったりします。しかし、AIの回答はそのAIが学習しているテキストデータの新しさに依存します。必ず公式ドキュメントを見に行って信憑性を確かめるようにします。逆に、普遍的な技術に関してはAIの回答による断片的な学習ではなく、先駆者が分かりやすくまとめた記事や書籍を中心に学ぶか、そのようなまとめ記事の抽出をAIにさせる方がよいです。
躓きや苦手な技術に向き合う
天才でなければ、学習の中で躓きは必ずあります。なぜかDBに接続できない、なぜか適用されないCSSなどあると思います。その躓きの対応として、私が実践しているものを紹介します。
- 課題やTODOとしてキープし、しばらく経ってから、もう一度挑戦してみる。(新しい情報なども時間とともに出てくる)
- その分野に詳しい人に聞く、もしくはAIに聞く。
- エラーを読む。スタックトレースの読み方や、デバッグの方法なども調べておきます。
- 必ず機能実装では、こまめにデバッグする。何十行もコーディングしてから処理実行すると、バグの原因が見えなくなります。
仮に躓きが解消されなくとも、その分野の難しさが理解できたと前向きにとらえ、その分野の開発者をリスペクトしましょう。
興味のない技術に向き合う
エンジニアとして、1つの分野に特化することは、良く言えば「専門家」で、悪く言えば「技術の偏り」と言えます。「専門家」でも他分野の最低限度の技術は理解しているでしょう。しかし、どうしても興味をもてない技術や分野はあると思います。その場合は、興味をもって取り組んでいる人に魅力的な部分を解説してもらうことや、その分野を学んで何ができるようになるかを解説している動画や記事を調べることが重要だと考えています。そうすると、その分野の魅力がわかるでしょう。大抵の場合マイナスイメージ(単に難しそうなイメージや面倒なイメージ)をもっているのが原因です。
参考書の選び方
新しい技術を学習するときに、私が意識している選び方を紹介します。私は以下の2冊を必ず読むようにしています。
作りながら学ぶ系
その言語でアプリケーションを作る際の、環境やフレームワーク、デプロイ方法などの組み合わせの実績ある一例が体形的に理解できます
逆引き辞典系
その言語でできる処理が、まとまっているため、見通しが持てます
※一つも言語獲得していない場合は、文法などが詳しく載っている参考書をもっていても損はないです。しかし、ほとんどはネットの記事や公式ドキュメントにあります。はじめから順を追って理解したい人にはおすすめです。
さいごに
長々と書きましたが、あくまでも、一個人の意見となります。私はIT分野で働く前は、数学教師を生業としてきました。そこで痛感するのは「早く覚えられた物事は、早く忘れる。時間をかけて覚えたことは、時間が経っても忘れない」ということです。数学の公式を暗記しても1か月後には忘れていることもあります。しかし、数学的な考えや意味など、何年もかけて培ってきたものは、そう簡単には忘れないです。これらの経験から考えると、エンジニアにとって忘れてはならないのは、学び続ける姿勢なのかもしれないと思い、ブログにしてみました。
誰かの助けになっていれば幸いです。最後まで読んでいただきありがとうございました。