2019/08/02

プログラミング言語の学び方

Code Java ソース コード プログラム プログラミング 開発

2019 年 8 月 2 日 Emil Hozan 著

プログラミング言語に関する記事をすでにいくつか書き、もちろんそれは実際の経験に基づくものでしたが、その後も、さまざまな経験をし、新しい知識を習得することができました。前回の記事の執筆時以降に、新しい概念を学び、自分なりの学び方を確立することもできたため、新たに学んだことをまとめて、この新しい記事を書くことにしました。また、これまでの経験からわかったのは、マルウェアには限界がないため、さまざまなプログラミング言語と概念を知っておくことが重要だということです。JavaScript には、いくつもの不正目的での使い方があり、Python、Android アプリケーション、複数の言語(PHP と JavaScript)やコンポーネント(バックエンド SQL データベース)の使用によって構築されるバックエンドエコシステムにも同じことが言えます。

それでは、前置きはこれ位にして、新しいプログラミング言語の学び方についてわかったことをご紹介したいと思います。乱暴な言い方かもしれませんが、私はこれが正しい方法だと信じており、私がこれまでに学んだ多くの新しい言語に当てはまることなのです。以下の説明をお読みいただくにあたっては、私が言及するどの新しい言語のエキスパートでもないことを覚えておいていただく必要がありますが、この方法によって、プログラムをデバッグし、自ら調べながら、一定のレベルの知識を習得できたのは事実です。

知っておくべき重要な概念

変数を作成し、それぞれに値を割り当てる基本的な方法を理解し、プログラミングのロジック(if ステートメントの使い方やリストをループで処理する方法)を習得したら、どのプログラミング言語を習得する場合であっても、結果を出力し、解釈する方法を理解する必要があります。つまりこれは、デバッグの具体的な進め方ということに他なりません。

私はかつて、プログラミング言語やその概念を習得する、自分なりの方法を模索していました。調査、実行、応用を組み合わせることでさまざまなことを学ぶようにしていますが、ある程度の基礎を固め、そこを出発点として始めて知識を積み重ねていくというのが、私のお気に入りのやり方です。この基本的なプロセスでは、公式の文書、コードスニペット、特定のトピックに関する評価の高い StackOverflow(SO)の投稿などの多くの多くの文書や記事などを読む作業に費やされ、これらの多様なリソースから得られる知識が、プログラミングの習得に活かされることになります。

これを証明する最も良い例は、SO の投稿です。ユーザが質問を投稿すると、そっけない返事しか返ってこないこともありますが、いくつかの返事をつなぎ合わせることで答えが導き出されることもあり、そのような「実のある」返事は、とてもありがたく、自分の理解で抜け落ちている部分を埋めてくれるのに役立ちます。すべての返事がそうであるわけではないのは確かであり、さらに詳しく調べたり、検索用語を変えて調べたりする必要はありますが、自分が知りたいトピックに関連する投稿を読むことで、より多くのコンテキストが加わり、理解が深まります。

話が脱線する前に、本題に戻りましょう。学習を始めるにあたっては、どこからどのように始めるべきかを知っておくことが重要で、その後に、以前の記事で取り上げたプログラミング言語の基礎の習得へと進みますが、さらにその次に必要となるのが、この記事の中心的テーマである、デバッグ方法の習得ということになります。

デバッグの学習では、プログラムが失敗した場合に返されるエラーメッセージだけでなく、出力ステートメントを挿入する正しい場所と方法も理解する必要があります。関数間で渡されるデータ型に注意する必要があり、たとえば、データ型とそれらに対して実行できる操作は、文字列なのか、整数なのかによって異なります。整数データ型とまったく同じ操作を文字列データ型ですべて実行できるわけではありません。どのようなタイミングで出力し、どのようにデータ型をチェックし、それぞれのデータ型をどのように処理し、try/catch 句をどのように使用するか(後者を使用すると、不確実なロジックをより適切に制御できます)を理解しなければなりません。コードのブロックを try し、発生する可能性のあるエラーを catch または except で処理します。catch 句で使用すべき関数が何であるかがわかれば、デバッグを効率的に進めることができるでしょう。

個人的なプログラミング習得の実例

私が個人的に経験したいくつかの実例を紹介することにしましょう。Exobot のソースコードを以前にデバッグする機会があり、PHP 5.4(Exobot エコシステムの最初のプログラムで使用された言語)のいくつかの関数を新しいバージョンである PHP 7.0 に更新したことで、PHP に関するかなりの知識を習得することができました。どの Web ページでもそうであるように、紹介ページ(index ファイル)から始めました。このページを出発点として、print または echo ステートメントを挿入する方法を学び、index ページから呼び出される他のファイルについても少しずつ調べていきました。これらの分岐ファイルからさらに別のファイルを呼び出すこともあるため、その順序をよく理解し、デバッグのステートメントを正しい必要な場所に挿入するのは、かなり難しい作業でした。

さらには、私が知らなかった多くの関数を調べ、それぞれの役割と使い方も学びました。このような作業によって、PHP の旧バージョンから新バージョンまでの間にどの関数が「非推奨」になったのかを知り、この言語の知識を深めることができました。JavaScript ファイルにリンクされている HTML ファイルもあったため、それらをすべて詳しく調べる作業にかなり手こずりましたが、とても楽しいものでもありました。

その作業を進める過程においては、新しい言語を習得できただけでなく、マルウェア分析の知識も広がり、セキュリティに対する認識をさらに強くすることにもなりました。ウォッチガードの四半期ごとのインターネットセキュリティレポートの作成にあたり、我々は、マルウェアのサンプルを調査し、分析することで、マルウェアがどのように動作するか、また、それをどのように解決したり、対策としてどのように情報システムインフラストラクチャのセキュリティを強化したりすれば良いのかを検証しています。

それ以外の経験としては、たとえば、先日の Black Hat と DefCon では、CTF(Capture the Flag)チャレンジに参加し、バッジを開発しました。その過程で(少なくともバッジのコードを作成するために)C++ を習得する必要があり、楽しい経験でしたが、すでに経験のあった Python、JavaScript、あるいは PHP とはかなり異なるものでした。変数の作成方法については、いくつかの基本的な部分で違いがありましたが、ループと反復のロジックはかなり似ていました。

一番新しい経験としては、機密情報を不正取得できる概念実証の Android アプリケーションを作成しました。これも、C++ や先程のバッジのコーディングと同様、私にとって完全に未知の分野でしたが、新しいどのようなチャレンジにも、一生懸命取り組むというのが、私の信条です。これらの概念実証は、Exobot の Android の apk とも多少の関連性があり、これは古い Android バージョン用に書かれたものですが、当時から今までにセキュリティも強化され、かなりの進歩を遂げています。セキュリティが強化されたのは素晴らしいことですが、だからといって、悪意のある使い方を完全に排除できるわけではありません。以前の記事で紹介した手順を理解し、この記事の中心的テーマであるデバッグ方法を習得し、さまざまなリソース(前述の SO やさまざまなオンラインリサーチ)を活用することが、私にとっての有効なプログラミング言語の習得方法であることがわかりました。

まとめ

プログラミングを習得するには、多くの知識が必要です。ある日、目が覚めて勉強しようと思い立ち、その日のうちに達人になれるなどということはありません。少しずつ時間をかけて、新しい単元に取り組むよう、計画を立てることが重要です。この記事の本題であるプログラミングについて学ぶ際には、今後もそのことを忘れないようにしたいと思います。

基本を学び、文献を読み、サンプルコードが提供されている場合はそれを実際に試してみることから始めます。時間の節約にはなりますが、コピー&ペーストを繰り返すだけでは意味がありません。コピーする場合であっても、使用する変数名を実際に変更し、別のセクションのロジックをいくつか追加して試したりし、発生するエラーに注目し、エラーの原因を調査します。関連するいくつかのトピックの答えを探しながら読む作業を続けていくと、いくつかの点が少しずつ結ばれて 1 本の線になり、答えが見つかるものです。

この記事では、コードのデバッグ方法の習得を中心に解説しました。関数についてはある程度の説明が何らかのリソースに公開されており、ユースケースを紹介しているリソースも存在し、仮に見つからなかったとしても、古いコードの例を現在のリリースに適応させる方法がわかっていれば良いわけで、これはデバッグにも言えることです。コードのエラーをどのように処理し、それぞれのエラーが何を意味するのかを知ることで、処理が失敗した原因を特定し、失敗によるフラストレーションを解消できます。ここでの「失敗」という言葉の意味は、何かが失敗して継続できないということではなく、失敗を判断し、その理由を突き止める方法を学ぶということです。これらの失敗が、どうすれば失敗を回避し、成功させることができるかを学ぶ手掛かりとなるのです。