NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

注目のタグ

    社内で学んだエラーの対処法&“良いコード”の書き方

    はじめに

    はじめまして!今年度入社した正岡です。
    現在、Webサイトの構築・運用を担当しています。
    配属後は約2か月間、Javaの研修を受けてきました。研修では、インストラクターのサポートを受けながら、実際にコードを書く経験を通じて多くのことを学びました。

    この記事では、コーディング中に実際につまずいたポイントを、私の体験をもとにご紹介します。

    これからエンジニアを目指す方や、現在コーディングに取り組んでいる若手エンジニアの方々が、きっと一度は経験するであろう内容です。少しでも参考になれば嬉しいです!

    最初にぶつかった壁:エラーが読めない!

    配属前の研修ではJavaの基礎的な学習をしてきたのですが、配属後の研修で少し複雑なコードを触るようになると、パッと見て理解できないエラーに遭遇するようになりました。

    エラー例
    Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3 at ArrayErrorExample.printElement(ArrayErrorExample.java:14) at ArrayErrorExample.processArray(ArrayErrorExample.java:10) at ArrayErrorExample.main(ArrayErrorExample.java:5)

    エラーは解決するためのヒント

    私はこのようなエラーが出ると、正直「どうしよう…」と拒否反応を起こしてしまいます。同じように感じる人も多いでしょう。
    最初は直感でコードを修正してみるものの、うまく動かないことがほとんど。

    そこでインストラクターに相談すると、必ずこう聞かれます。
    「エラー文をしっかり読んで理解した?」
    読んではいるけれど、理解できていない状態でした。

    そんなとき、インストラクターから言われた一言が印象的でした。
    「エラーは解決するためのヒントだよ」
    この言葉をきっかけに、私はエラーの読み方を意識するようになりました。

    構造的に読むためには、エラー文の構成要素を押さえることが重要です。ここを理解できると、エラーの意味が掴みやすくなります。

    エラーの読み方

    プログラミングでエラーが出たとき、ただ「赤字で怒られた!」と焦るのではなく、エラー文を構造的に読む力を身に着けることが重要です。
    構造的に読むにあたってエラーの構成要素を確認する必要があります。

    エラー文は主に次の3つの要素で構成されています。

    エラーの3要素

    1. エラーの種類
    2. エラーメッセージ
    3. スタックトレース

    ここでは、以下の簡単なJavaの型エラーを例に、エラー文のどこがどの要素に該当しているのかを解説します。

    public class ArrayErrorExample {
        public static void main(String[] args) {
            var example = new ArrayErrorExample();
            // 中間メソッドを挟むことで、スタックトレースが複数行になる例を示す
            example.processArray();
        }
    
        void processArray() {
            int[] numbers = {1, 2, 3};
            printElement(numbers, 5); // 存在しないインデックスでエラー発生
        }
    
        void printElement(int[] arr, int index) {
            System.out.println(arr[index]);
        }
    }
    

    エラー文
    Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3 at ArrayErrorExample.printElement(ArrayErrorExample.java:14) at ArrayErrorExample.processArray(ArrayErrorExample.java:10) at ArrayErrorExample.main(ArrayErrorExample.java:5)

    1. エラーの種類

    java.lang.ArrayIndexOutOfBoundsException

    このエラーは何か?
    配列のインデックスが範囲外になったときに発生するエラーです。

    エラーの種類からわかること
    原因のカテゴリ:配列操作の問題
    性質:実行時エラー(Unchecked Exception)なので、コンパイル時には検出されない

    エラーの修正にどうつながる?
    エラーの種類を知ることで、どんな操作が問題だったか(配列の範囲外アクセス)をすぐに推測できます。

    2. エラーメッセージ

    Index 5 out of bounds for length 3

    エラーメッセージからわかること
    要素数3の配列に対して、存在しないインデックス「5」を指定したためです。

    エラーの修正にどうつながる?
    具体的な値がわかるので、コードのどこで間違ったインデックスを使ったかを特定できます。

    3. スタックトレース

    at ArrayErrorExample.printElement(ArrayErrorExample.java:14) at ArrayErrorExample.processArray(ArrayErrorExample.java:10) at ArrayErrorExample.main(ArrayErrorExample.java:5)

    どこでエラーが起きたか
    実際にエラーが発生したのは printElement メソッド(ArrayErrorExample.javaファイルの14行目)です。

    スタックトレースからわかること

    • 最初の行: 実際にエラーが起きた場所 printElementメソッド(ArrayErrorExample.javaファイルの14行目)
    • 次の行: そのメソッドを呼び出した場所 processArrayメソッド(ArrayErrorExample.javaファイルの10行目)
    • 最後: mainメソッド(ArrayErrorExample.javaファイルの5行目)

    エラーの修正にどうつながる?
    修正すべき場所を正確に特定できるだけでなく、呼び出しの流れを把握できます。

    まとめ:エラー文の「構造」をつかんで解決に導く

    エラー文は「種類 → 原因 → 発生場所」の順で読むことで最短距離でエラーの特定が可能となります。

    このようなエラーに遭遇するたびに都度調べるのではなく、エラーの種類と意味を一般化して理解することで、それ以降の開発での対応力を高めることができました。



    次にぶつかった壁:動くだけで満足してしまう「汚いコード」

    やっとエラーに慣れて、エラーが出ても対処できるようになり、とりあえず「動くコード」は書けるようになったと思っていました。

    しかし、インストラクターのコードレビューで数十ヵ所の指摘を受け、正直驚きと落胆がありました。
    そのときに気付かされたのは、「動くコード」と「良いコード」は全く別物だということです。

    指摘された主なポイント

    • アクセス修飾子の指定不足
    • 異常値に対する例外処理の未実装
    • 型推論varの未使用
    • 変数やメソッドの命名
    • 不要なファイル(classファイル)の指摘
    • 変更容易性の考慮不足

    読みやすいコードを書くための工夫

    1. アクセス修飾子を明確にする

    アクセス修飾子は、クラスやメソッド、フィールドの「見える範囲」を決めるものです。
    すべてpublicにしてしまうと、意図しない箇所から利用され、バグや保守性の低下につながります。

    改善ポイント

    • 外部から呼び出す必要がなければ、privateを選ぶ
    • 必要に応じてpublic / protectedを使う

    2. 例外処理を実装する

    「動くコード」だけでは、予期しない入力やエラーで簡単に動かなくなります。
    例外処理をしないと、原因が分からずデバッグに時間がかかります。

    改善ポイント

    • try-catchでエラーを捕捉し、適切なメッセージや処理を行う
    • 業務ロジックに応じてカスタム例外を作成する(例:InvalidUserInputException)
    • 例外を握りつぶさない(catch (Exception e) {}ではなく、catch内でエラーメッセージの表示など適切な処理を行う)

    3. var を上手に利用する

    varはJava 10以降で導入された型推論機能です。
    型を明示しなくてもよいため、コードの冗長な記述が減り、保守性が向上します。

    varなし

    List<String> names = new ArrayList<String>();
    

    varあり

    var names = new ArrayList<String>();
    

    改善ポイント

    • 明確な型が分かる場合のみ var を使用する
    • 複数の型や戻り値には明示的な型を記述する

    4. 命名規則を守る

    命名規則を守ることでコードの可読性と保守性を高め、チーム全体で共通の理解を得ることができます。
    a, b, cなど意味不明な名前は、作った本人しかわからないので避けましょう。

    改善ポイント

    • 変数名は「役割が分かる」名前にする(priceよりtotalPrice)
    • メソッド名は「動詞+目的語」の構成にする(calculateTotalPrice()など)

    5. 不要なファイルを適切に管理する

    ビルド成果物(.classファイルなど)や一時ファイル、個人設定ファイルなどがリポジトリに含まれると、本来管理したいソースコードや設定以外の余計なデータまでバージョン管理されてしまい、共同作業やデプロイなどの運用上の障害につながります。

    また、パスワードやAPIキーなど機密情報を誤ってアップロードしてしまうリスクもあるため、ファイル管理には十分注意が必要です。

    改善ポイント

    • .gitignoreを設定して、ビルドディレクトリや個人の開発に依存する設定ファイルなどは除外する
    • コミット前に git status や git diff で、追加・変更されたファイルや内容を確認する

    6. 変更容易性を意識する

    コードは一度書いたら終わりではなく、必ず変更されます。
    変更に強いコードは保守性が高く、チーム開発では必須の考え方になります。

    改善ポイント

    • ハードコードを避け、定数や設定ファイルを活用する
    • メソッドは小さく分割し、単一責任を守る

    まとめ:目指すべきは「動く」ではなく「良い」コード

    読みやすさ・保守性・安全性を意識することで、レビュー指摘は減っていきました。動くコードが書けるようになったことはスタートラインに過ぎず、「動く」だけでは本当に良いコードとは言えないということを強く実感しています。

    良いコードは、将来の変更やチーム開発に強く、長期的な品質を支える基盤になります。

    そのためにも、「レビューは成長のチャンス」と捉え、指摘された改善点を次に活かす姿勢が重要だと学びました。




    全体のまとめ

    コードを書き始めると、誰もが一度はつまずくポイントがあります。私も配属後にその壁にぶつかりました。
    しかし、エラーの正しい捉え方を身につけることで、問題解決のスピードが上がり、コードレビューを通じて「動くこと」だけでなく「読みやすさ」や「保守性」にも意識を向けられるようになりました。

    一度で完璧なコードを書くのは難しいですが、エラーやレビューを通じて学び、次に活かすことで確実に成長できます。

    これからさらに成長していくために、以下の2点を意識していきたいと思います。

    • エラーを恐れず、ヒントとして活用すること
    • レビューを受け止め、指摘内容を抽象化して次に生かすこと

    この2つを意識しながら、より良いコードを書けるよう努力していきます。

    執筆者:正岡 史也 システムエンジニア