「トランジション採用」でフリーランスの正社員転換を支援 他
- 隔週月曜更新!フリーランス・副業ニュース
プログラミングや開発で使用するソフト、コマンドラインの操作や開発環境のセットアップ……そのほかにもさまざまな知識が要されるエンジニアの仕事。
駆け出しのエンジニアにとっては難しく、何度も失敗や間違いをしてしまうこともあるでしょう。
今回は言語を問わず、多くの初心者エンジニアが失敗しがち・間違えがちなことを7つピックアップしてみました。
目次
正規表現とは「文字列のパターンをひとつの決まった形式に従って表現すること」を指します。
正規表現は以下のような場面で用いられます。
この正規表現ですが、エンジニア初心者の方がもっとも学習を後回しにしがちな項目のひとつではないでしょうか。
正規表現はプログラミング言語そのものではなく、独自の文法で記述する形式言語(機械やプログラムのために構文の形式そのものが特定の意味を示す言語)ですが、どのプログラミング言語を扱う場合でも必ず登場する基本的な知識です。初心者のうちはコピペで済ませてしまうことの多い正規表現ですが、文法を理解すればさまざまな場面で活用できます。しっかりと学習して、自分のものにしていきましょう。
また特に初心者が間違えやすい正規表現の文法に「欲張る正規表現」と「欲張らない正規表現」があります。
実際の正規表現で、これらを比較してみましょう。
文字列"https://foo.com/page/1"の一部分を以下の正規表現で抽出する # 欲張る正規表現(?マークなし) "https:\/\/.+\/" →"https://foo.com/page/"が抽出される # 欲張らない正規表現(?マークあり) "https:\/\/.+?\/" →"https://foo.com/"が抽出される
このように、ほんのわずかな書き方の違いで正規表現は意味を変えてしまいます。
Gitとは、ソースコード等のバージョン管理を行うシステムです。バージョン管理を行うことで、ソースコードの過去の変更履歴を追ったり、複数人がひとつのコードを同時に編集し、後に全員の変更をきれいに取り込んだりできます。
ほとんどの開発案件で必須のGitですが、初心者エンジニアがGitをよく理解していないまま見よう見まねで使用してしまい、リモートリポジトリに自分の変更を反映できていなかったり、コンフリクトを誤った方法で解消してバグを生んでしまうといったケースはあるあるでしょう。
初心者が起こしがちなGit操作のミスは多くの場合、Gitの基本構造である「作業ディレクトリ」「ローカルブランチ」「リモート追跡ブランチ」「リモートリポジトリのブランチ」の違いを理解していないことが原因です。
Gitにはコミットやプッシュ、マージやプルなどの基本的なコマンドの他、フェッチやリセット、リベースやリバートなどさまざまなコマンドがあります。しかし、上記4つの構造を理解すればこれらコマンドについてもより理解が深まり、適切な操作を行えるようになるでしょう。
Gitの構造を意識して、上手にコードのバージョン管理や共有を行いましょう。
▲Gitで初心者が「あれ、プルできないぞ?」となりがちなdetached branch
一般に、コードの影響範囲は小さい方が良いとされています。外部に依存せず、影響範囲が最低限で独立性の高い処理同士で構築されたコードは、処理を追うのが容易なため喜ばれます。
逆に、複数の異なる処理やグローバル変数が互いに依存しており、「同じメソッドでもそれを実行する順序やタイミングが異なるだけで返却する値が大きく変わってしまう」という状況のコードは、処理を追うのが困難です。ちょっとした改修のはずが、思わぬ箇所にコードの改修が影響して、バグを生んでしまった経験のある方も多いのではないでしょうか。
コードは書く時間より、読む時間のほうが長くなるものです。短時間で書いた品質の低いコードのせいで、後になって書いたときの何倍もの時間をそのコードの解読に費やすケースもあります。また、こういった可読性の低いコードが少しずつ増えていくと、やがてそのシステムのコードは誰も触れないブラックボックスとなり、拡張性を失ってしまいます。
バグを生みにくい可読性の高いコードを書くには、外部依存は最低限に抑えることが大切です。拡張性の高い、機能の追加や改修を行いやすいシステムを維持するためにも、むやみな外部依存は行わず、独立性の高いコードを書くよう心がけましょう。
どのプログラミング言語の駆け出しエンジニアにも共通するありがちな間違えに「ビルド前後の外部ファイルのパス」があります。
実装したプログラムが外部のなんらかのファイルを参照するとき、ビルド前は正しくファイルを参照できたはずなのに、ビルド後はなぜか「ファイルがありません」とエラーが出てしまうことがあります。これはビルド前後でプロジェクトのディレクトリ構成が変わり、適切な相対パスが変わってしまうことが原因です。目的のファイルが配置されているディレクトリの階層がビルド前後で変化したり、あるいはプログラムの実行ファイル自身が異なる階層に移動するなどの要因が考えられます。
これは各プログラミング言語のフレームワーク(アプリケーションの開発を容易にするための枠組みを提供するソフトのこと)を使用し始めた頃の初心者が陥りがちな事象です。というのも、フレームワークにはこういったビルド前後の階層の変更を伴うものが多くあります。
大抵の場合において、外部ファイルのパスに関する問題は、フレームワークが提供するなんらかの適切な方法に従うことで解決できます。そしてその方法はほとんどの場合、フレームワークの公式ドキュメントで解説されています。
初心者のうちは公式ドキュメントより、わかりやすく解説してくれている個人ブログなどに頼ってしまいがちです。しかし最新版の仕様を正しく理解し、外部ファイルのパスなどの問題に適切に対処するためには、公式ドキュメントをしっかりと読むことが大切です。
公式ドキュメントは日本語に翻訳されていないことも多いですが、これを読めるか読めないかでその後のエンジニアとしての成長も大きく変わっていきます。公式ドキュメントから逃げず、正しい言語・フレームワーク仕様を調べる癖をつけましょう。
▲ビルド前後のパスの差異を、プログラム側で吸収するよう実装することも
プログラミングにおいて、適切な命名はコードの可読性を高めます。自分以外の誰が読んでも、その変数やメソッドの仕様が分かる命名が理想的です。
そして真偽値の判定メソッドや、その判定結果を格納する変数の命名で、初心者がやりがちなのが「どういった場合に真なのかが分からない命名」です。
例えば次のような命名が挙げられます。
# 状態"foo"についての真偽値を格納する変数 fooFlag # 状態"foo"についての真偽値判定を行うメソッド checkFoo()
上記の命名では「これは真偽値に関する変数・メソッドなのだな」ということは分かりますが、「どんな時に真で、どんな時に偽なのか」が分かりません。これでは実装した本人以外がコードを見たとき、これらの変数・メソッド名がどんな実装になっているかについて逐一コードを追って確認しなければならないでしょう。
fooについての真偽値を示すのであれば、たとえば次のような命名にすべきです。
# 状態"foo"についての真偽値を格納する変数(状態が"foo"なら真) isFoo # 状態"foo"についての真偽値判定を行うメソッド(状態が"foo"ではないときに真を返却) isNotFoo()
このように、状態に関わる変数・メソッド名であれば「be動詞 + 状態」で書くことで、「どんな状態なら真か」がひと目で分かるようになります。
また、上記命名は「状態」についての真偽値に関するものでしたが、「動作」や「存在」についての真偽値を命名するなら、次のようになります。
# 動作"write"についての真偽値(writeできるなら真) canWrite # "message"の存在についての真偽値(Messageが存在するなら真) messageExists
このように命名のつけ方によって、コードの可読性は大きく変わります。たかが命名とあなどらず、誰が読んでも分かりやすい命名をするよう心がけましょう。
作成したコードは、それが正しく動作するかどうかを確認するためにテストする必要があります。テストには「単体テスト」や「結合テスト」などさまざまな形式のものがありますが、これを作成するとき初心者にありがちなのが、テストケース(テストパターン)の想定漏れです。テストケースが漏れていたためにコードの不具合を発見できず、リリース後に先輩エンジニアにバグを発見されてしまった経験がある人もいるのではないでしょうか。
開発において、テストケースの網羅はコーディング以上に大切です。テストケースを網羅できていれば、どのような機能をどのような仕様で実装すればいいのかも自ずと分かります。また逆に、テストケースを網羅できておらず、コーディングもテスト作成者と同じ人が担当していた場合、どこかにバグが潜んでいる可能性は高いです。
▲出典:Tech Village
テストケースを網羅するためのもっとも基本的なアプローチとして「マトリクスの作成」が挙げられます。マトリクスとは、テストする対象の条件を書き出して表にしたものです。テスト対象に関連する全ての条件を行と列の表にして、全ての条件の組み合わせを可視化することで、テストケースを網羅しやすくします。
テストケースの網羅は、見逃さないようただ注意するだけではなかなかうまく行かないものです。人間である以上、どんなに注意しても見逃しは発生する可能性があります。マトリクスで条件の組み合わせを可視化して、パターン漏れがないかをしっかりと確認しましょう。
なお、これができるようになれば、同じアプローチで「コーディング中の例外処理のパターン網羅」もできるようになります。どれだけのパターンを想定できるかでシステムの堅牢性は変わるため、マトリクスの作成は丁寧に行いましょう。
テストケース作成で気をつけるべき3つのポイント。ソフトウェアテストを効率よく行う方法
Workship MAGAZINE
技術的な話ではありませんが、駆け出しエンジニアは優秀な先輩エンジニアに対し「あれだけ優秀な人なら、技術のことなら何でも知っているだろう」と思いこみがちです。これは実際に先輩エンジニアの側になってみれば分かりますが、決してそんなことはありません。
エンジニアとしてまだ歴の浅いうちは目の前の技術に精一杯で、周りにどのような技術があるのかあまり見えていません。また初心者エンジニアの自分には困難なことを、いとも簡単に実装する先輩エンジニアに対して「知らないことなど無いのではないか」と思えるときもあるでしょう。
しかし、駆け出し当初にはとても難解に思えた実装も、公式ドキュメントをよく読み、手を動かしながら確認していけば思いのほかあっさりと習得できるものです。それができるようになる頃には、初めのうちは難解に思えていたその他の実装もまた、さして特別なものではなかったのだと気づくでしょう。
一方でエンジニアとして力がついてくると、エンジニアの世界には途方もない知識・技術体系があることが理解できるようになります。あまりにも幅が広く、奥深いため、特定の技術だけならまだしも、すべての分野を完全に習熟することはまず不可能です。ある専門分野で優れていた先輩エンジニアが、他の分野では素人同然というのは普通のことです。
このような事情から、遠く先にいるように思える優秀な先輩エンジニアも、実際は「なんでも」知っているわけではありません。一歩ずつ着実に腕を磨いていけば、今はまだ初心者のエンジニアでも、きっといつか肩を並べて対等に仕事できるようになるでしょう。
エンジニアとして歴の浅いうちは、さまざまな間違いや失敗をします。単なるプログラミング言語の文法上の間違いはもちろんのこと、今回ご紹介した正規表現やGitのコマンドなどといった「開発では必須だが、プログラミングそのものから少し外れた技術」は、特に初心者のうちは経験が浅く分からないことが多いでしょう。
しかしそれは、先輩エンジニアの誰もが辿ってきた道です。テストパターン漏れによるバグの見過ごしや、可読性の低いコード実装なども、さまざまな失敗を経験していく中で、少しずつ改善できるようになっていきます。間違えや失敗を糧にして、自らの技量を高めていきましょう。
なお、次回からはプログラミング言語別に、初心者エンジニアが間違えそうなことをご紹介していきます。お楽しみに!
こちらもおすすめ!▼
2024年 東京都内の優良プログラミングスクール20選
Workship MAGAZINE
オンラインのプログラミング学習サービス27選
Workship MAGAZINE