プログラマとして成長するための10の心得
プログラミングには問題がつきもの!?
プログラミング学習をしていて、どうしても理解出来ない処理に出くわす、または、エラーや例外が解決できないことに悩まない人はいないでしょう。
特に初学者であるほど、知識が単純に不足しているために、どうしても気づけないこともあります。
そういった場合には、習熟している人に聞くのが一番早いですが、中々そういった環境が整っている人はいないでしょう。
また、質問するにも明確な原因を特定できず、”結局何がわからないの?”と言われてしまうことも多々あります。
まず、自分で問題を整理して、様々な切り口から自分でコーディングできる力を育てていきましょう。
参考になるものが海外の技術コミュニティーサイトに上がっていたので、和訳しながらお伝えしたいと思います。
参考サイト
10の心得
プログラミングの問題に取り組んでいる新人開発者からのフィードバックの中には、どこから手をつけたらいいのかわからないというものがあります。
あなたは問題、ロジック、構文の基本などを理解しています。他の人のコードを見たり、指導してくれる人がいれば、それに従うことができます。
しかし、構文やロジックは理解していても、最初は自分でやることに不安を感じたり、自分の考えをコード化するのに苦労したりすることもあるかもしれません。
ここでは、プロセスとサンプル問題に取り組むためのヒントを紹介します。
1. 少なくとも3回は問題を読む
まず、わからない/解決できない問題と自分が解いていると思っている問題には違いがあります。
問題の最初の数行を読み始めて、過去に見たことのあるものと似ているからといって、残りの部分を想定してしまうのは簡単です。
たまに友人に説明してみて、私の説明の理解度が課題の問題と一致しているかどうかを確認することもあります。
途中で問題を誤解していたことに気づくのは避けたいものです。
最初に余分な時間を取ることは、それだけの価値があります。
問題をよりよく理解すればするほど、それを解決するのは容易になります。
数値の配列を受け取り、偶数のみの配列evenNumbers
を返す単純な関数selectEvenNumbers
を作成しているとしましょう。偶数がない場合は、空の配列evenNumbers
を返します。
function selectEvenNumbers() { // your code here }
ここでの私の思考は、、
- 偶数が何であるかをコンピュータはどうやって見分けることができる?
- この関数に渡すものは何?
- その配列には何が含まれている?
- 1つ以上の数字配列の要素のデータ型は?
- この関数の目的は何ですか?この関数の最後に何を返せばいいのでしょうか?
といくつかの疑問を元に処理を書いていきます。
単純な処理であっても、これだけの問いをもってコードに起こしていくのです。
しっかりと思考のフローを客観視し、人に説明できるよう書き出し、理解が確かなものか確認しましょう。
2. 少なくとも3つのサンプルデータを使って、問題を手動で処理してみる
紙を取り出して、問題を手作業で処理してください。
使用できるサンプルデータのセットを少なくとも3つ考えてください。コーナーケースとエッジケースも考慮してください。
・コーナーケース:通常の動作パラメータの外で発生する問題または状況。
・エッジケース:極端な(最大または最小の)動作パラメータでのみ発生する問題または状況。
各パラメータが指定された範囲内にあるかにかかわらず、特に複数の環境変数または条件が同時に極端なレベルにある場合を考えるようにしましょう。
特にエッジケースの確認は大切です。
場合分けの際の境界付近では、ミスが生じやすく注意が必要です。
エラーや例外が生じた際にも、要チェックなポイントです。
3. ステップをシンプルに最適化
パターンを探して、一般化できるものがないかどうかを確認してください。
ステップ数を減らすことができないか、繰り返しているステップがないかを確認してください。
関数 selectEvenNumbers を作成します。 偶数を格納する空の配列evenNumbersを新規に作成します。
- 配列 [1, 2] の各要素を通過する
- 最初の要素を見つける
- 2で割れるかどうかで偶数かどうかを判断し、偶数であれば偶数に加算する。
- 次の要素を探す
- ステップ#4を繰り返します。
- この配列の要素がなくなるまで、ステップ#5と#4を繰り返します。
- 配列の中に何かがあるかどうかに関わらず、配列evenNumbersを返します。
このアプローチは、あなたが数学的帰納法を思い出させるかもしれません。
- n = 1, n = 2, ...に対して真であることを示す。
- n = k の場合に当てはまるとします。
- n = k + 1 の場合に真であることを証明する。
4. 疑似コードを書く
大まかな手順をまとめた後でも、コードに変換できる疑似コードを書き出しておくと、コードの構造を定義する際に役立ち、コーディングが非常に楽になります。
疑似コードを一行ずつ書き出します。
これは紙に書いても、コードエディタでコメントとして書いても構いません。
もしあなたが始めたばかりで、真っ白な画面を見るのが面倒だったり、気が散ってしまう場合は、紙の上で行うことをお勧めします。
疑似コードには一般的に特定のルールがあるわけではありませんが、プログラミング言語のある側面を十分に理解しているという理由だけで、ある言語の構文を入れてしまうこともあります。
構文にとらわれず、ロジックとステップに焦点を当ててください。
ここでは、偶数を格納した配列を用意する関数を取り上げて、考えてみましょう。
まず、疑似コードの例を示します。
function selectEvenNumbers 配列evenNumbersを作成し、空の配列と設定 for それぞれの要素 in 配列内 その要素があるかどうかを確認 if 要素が偶数の場合 それを配列evenNumbersに追加 return 偶数の配列
この疑似コードを元により近いプログラミング的な書き方に起こして行くのです。
それぞれの処理を自分で書き出して、一行一行を理解するのは遠回りのようにも感じます。
しかし、基礎を整えて、特定のプログラミング言語で写経のように移すより、アルゴリズムとして理解することは長い目で見て有意義です。
5. 疑似コードをコードに翻訳してデバック
疑似コードの各行を実際のコードにした結果、以下のようになりました。 (// は、その行が疑似コードの中にあったものです。)
// function selectEvenNumbers function selectEvenNumbers(arrayofNumbers) { // 配列evenNumbersを作成し、空の配列と設定 let evenNumbers = [] // for それぞれの要素 in 配列内 for (var i = 0; i < arrayofNumbers.length; i++) { // if 要素が偶数の場合 if (arrayofNumbers[i] % 2 === 0) { // それを配列evenNumbersに追加 evenNumbers.push(arrayofNumbers[i]) } } // return 偶数の配列 return evenNumbers }
混乱を避けるために疑似コードを削除します。
function selectEvenNumbers(arrayofNumbers) { let evenNumbers = [] for (var i = 0; i < arrayofNumbers.length; i++) { if (arrayofNumbers[i] % 2 === 0) { evenNumbers.push(arrayofNumbers[i]) } } return evenNumbers }
時々、新しい開発者は構文に夢中になってしまい、前に進むのが難しくなることがあります。
構文は時間が経てば自然に身につくものであり、コーディングの際に後から正しい構文の資料を参照することは恥ずかしいことではありません。
6. あなたのコードを最適にそして、シンプルに
プログラミングを進めていくと、シンプル化と最適化が繰り返されるテーマであることと、気づいていくでしょう。
“Simplicity is prerequisite for reliability.”
"シンプルであることは信頼性の前提条件である"
— Edsger W. Dijkstra: オランダのコンピュータ科学者であり、コンピュータ科学の多くの研究分野における初期の先駆者でもある。
ここでは、心に留めておくべき質問をいくつかご紹介します。
シンプル化と最適化の目標は何ですか?
どのようにしてコードをより読みやすくすることができますか?
余分なステップはありませんか?
必要のない変数や関数はありませんか?
いくつかのステップを繰り返していませんか?
エッジケースを処理する良い方法はありますか?
目標は、チームのスタイルや個人的な好みによって異なります。色々な問いかけをしながら進めていきましょう。
"プログラムは人が読むために書かれなければならず、機械が実行するためには付随的にしか書かれていない"
— ジェラルド・ジェイ・サスマンとハル・アベルソン、"コンピュータプログラムの構造と解釈 "の著者
様々な切り口から、状況に応じてふさわしい、コード作成を進めていきましょう。
チーム開発を考えて、、とか、初心者は気にしなくてよいと考えてしまいますが、何より自分にとって読みやすいコードが書けないといずれ挫折することになります。
7. デバック
このステップは、プロセス全体を通して行う必要があります。
全体を通してデバッグを行うことで、構文エラーやロジックのギャップを早期に発見することができます。
統合開発環境 (IDE) とデバッガを活用してください。
私はバグに遭遇したときは、コードを一行一行トレースして、何か期待通りにいかなかったことがないかどうかを確認します。
私が使っているテクニックをいくつか紹介します。
コンソールをチェックして、エラーメッセージの内容を確認する。
→チェックすべき行番号を指摘してくれることもあります。これはどこから手をつけたらいいかの大まかな見当をつけてくれますが、問題がこの行ではない場合もあります。コードの塊や行をコメントアウトして、これまでのコードを出力する。
→必要に応じて、いつでもコードのコメントを外すことができます。予想外のシナリオがある場合は、他のサンプルデータを使用する。
→コードがまだ動作するかどうかを確認しましょう。全く異なるアプローチを試している場合は、異なるバージョンのファイルを保存する。
→やはり、元に戻したくなったときに、今までの作業を失うのは避けたいですからね。
"最も効果的なデバッグツールとは、やはり慎重に考え、適切に配置されたprint文と組み合わせることです。"
- ブライアン・W・カーニガン、プリンストン大学コンピュータサイエンス教授
8. コメントを書く!
一ヶ月後に一行一行の意味を覚えているとは限りません。
また、あなたのコードを書いている他の誰かも、その意味がわからないかもしれません。
だからこそ、後になって問題を回避して時間を節約するために、役に立つコメントを書くことが重要なのです。
このようなコメントは避けましょう。
// これは配列です。これは配列です。
// これは変数です。
何が起こっているのかを理解するのに役立つ、簡潔でハイレベルなコメントを書くようにしています。
これは、より複雑な問題に取り組むときに便利です。
特定の関数が何をしているのか、その理由を理解するのに役立ちます。
明確な変数名、関数名、コメントを使用することで、あなた(および他の人)は理解できるようになるはずです。
常に以下は念頭において、コメントをつけましょう。
- このコードは何のためにあるのか?
- 何をしているのか?
9. コードレビューからフィードバックを得る
チームメイトや教授、他の開発者からフィードバックを得ましょう。
Stack Overflow をチェックしてみましょう。他の人がどのように問題に取り組んでいるかを見て、彼らから学びましょう。
問題へのアプローチにはいくつかの方法があります。
それが何なのかを知ることで、あなた自身がそれを思いつくことができるようになり、より早く上達できるようになるでしょう。
"たとえどんなにゆっくり綺麗なコードを書いても、根本から台無しになればもっと遅くなる。"
- ボブ・マーティンおじさん、ソフトウェアエンジニア、アジャイル宣言の共著者
10. 訓練、訓練、訓練!
経験豊富な開発者であっても、常に練習して学んでいます。
有益なフィードバックを得たら、それを実装しましょう。
問題をやり直したり、似たような問題をやってみましょう。
自分を追い込み続けてください。
問題を解決すればするほど、開発者としての腕は上がっていきます。
成功を祝い、自分がどれだけ進歩したかを忘れないようにしましょう。
プログラミングは、何事もそうですが、時間が経てば自然と簡単にできるようになるということを忘れないでください。
"自分がここまで来たことに誇りを持ちましょう。自分がどこまで行けるかを信じてください。しかし、旅を楽しむことを忘れないでください。"
- マイケル・ジョセフソン、ジョセフ・アンド・エドナ・ジョセフソン倫理研究所の創設者
最後に
今回は初心者から中級者まで、プログラミングに取り組む際に心がけるべきポイントを紹介してみました。
海外では、日本以上にプログラミング教育が活発な国が多いので、教育面において参考にしていくのは良いですね。
入社して半年が経過しましたが、まだまだわからないことだらけです。
それでも、自分なりに必要となることや、今時間を積み重ねておくべきことをやれているように感じます。
実際に一人前のプログラマになることを目指して、Android/iOS開発は毎日必ず手を動かして感覚をなくさないようにしています。
With COVID19の中で新卒のキャリアをスタートさせましたが、少しながら日々に自分の成長 があります。
今年から社会人になった皆さん、大変な中ではありますが、通勤や娯楽にかけていた時間を学びの時間として、今後も一緒に成長を続けて行きましょう!
とりあえず。。。
メモ代わりに書いていますが、これから理解が深まれば書き足していきます。 いつか誰かのお役に立てると嬉しいですね。
初学者から一人前まで、、、 ここでは一人前のプログラマの定義を
「自力で様々なツールを活用しながら、ある程度思い通りの実装ができること」
とします。
また、人生においてプログラミングに向き合う時間として、現時点で2000時間取り組めればある程度の基盤が備わると仮定しています。 (言語やツールに依存しない思考法や情報収集能力)
プログラミングは大学で学んで来ましたが、特に根詰めてやってきていないので、ノーカウントとして取り組みます。
現在までの学習時間
およそ520時間 どんどん更新していきます。