リーダブルコード 未来の自分を助ける 01

全てのエンジニアにお勧めしたい本。それが「リーダブルコード」です。

www.oreilly.co.jp

本シリーズ:リーダブルコードの解説 各記事のリンクはこちらをクリック リーダブルコード 未来の自分を助ける 01 - こだわりデベロッパーズノート
リーダブルコード 未来の自分を助ける 02 - こだわりデベロッパーズノート
リーダブルコード 未来の自分を助ける 03 - こだわりデベロッパーズノート
リーダブルコード 未来の自分を助ける 04 - こだわりデベロッパーズノート
リーダブルコード 未来の自分を助ける 05 - こだわりデベロッパーズノート
リーダブルコード 未来の自分を助ける 06 - こだわりデベロッパーズノート

読みやすく、理解しやすいコードを書くための方法がまとめられた本です。 本名の通り「Readable(読める) Code」ということですね!!

リーダブルコードが訴えていること

コードは理解しやすくなければいけない

この考えがこの本の中心となります。この考えを達成するための考え方、方法を様々な角度から述べています。

「読みやすいコード、理解しやすいコード」を書く。そのための技術がこの本にギッシリと詰まっています。

本ブログでは日々の業務でコードを記述している若手エンジニアに明日から即効果がある部分を抽出して解説していきたいと思います。

では、まず最初に「理解しやすいコード」が持つ価値からはじめましょう!

理解しやすいコードの価値

「理解しやすいコードを書いた方が良い」と言われると、「はい。そうですね」としか答えられないわけですが、とは言っても仕事としてコードを書いている以上、動くコードを書かないと仕事が完了できません。

だとしても、理解しやすいコードを書くために労力を割くことには価値があります。なぜなら、理解しやすいコードを書くことで「品質」だけでなく、「生産性」も向上するからです。

品質だけじゃない!生産性も向上する!

エンジニアの仕事では、実はコードを書く以上にコードを読むことに時間を消費します。

目の前のコードが何をしているのか?を把握しないことには書くコードを決めることができません。 そのため、「理解しやすいコード」を書くことで「コードを読む」時間が圧縮されて「生産性」が向上します。

コードを書く時間と読む時間の割合は状況によって変わりますが

書く:読む」が「10%~40%:90%~60%

と言う感じでコードを書く担当の人でも、コードを読む時間の方が多くなります。

コードを読む時間が減れば生産性が上がる

プロジェクトに参加する人数が多いほど、上流に近いエンジニアほど、コードを読む時間の割合が増えます。

プロジェクトに参加する人数が多いと、自分以外の書いたコードが沢山出来上がります。そのため、コードを読む時間が増えます。ここで理解しやすいコードを書くことができれば、全員のコードを読む時間が圧縮できるため生産性向上に効いてきます。

上流に近いエンジニアは設計を考えるためにコードを読む時間が増えます。上流のエンジニアは給料(いわゆる単価)も高くなりますので、コードを読む時間が圧縮できるとこれまた生産性向上に効いてきます。

品質は生産性にどの程度影響するのか

理解しやすいコードを書くことを心がけることでコードの品質が高くなります。

理解しやすいコードが品質と生産性を同時に向上することは前述の通りです。しかし、品質が生産性に及ぼす影響がどれ位あるのか?は説明が難しいです。

これに対して、2022年の研究で品質がビジネスに与える影響を「時間」という数字で計測した論文が発表されました。

arxiv.org

この論文を非常にざっくりまとめると以下になります。

  1. コードの品質をコード分析ツール「CodeScene」で計測する
  2. 「最も低品質と判断されたコード」と「最も高品質と判断されたコード」を比較
  3. 悪いコードは、良いコードに対して15倍のバグ発生数
  4. 悪いコードは、良いコードに対して開発時間が「平均2倍」、「最大9倍」

つまり、同じ機能を同じ時間で書ける人がいたとすると、理解しやすいコードを書ける人は、理解しやすいコードが書けない人よりも平均で2倍、最大で9倍も生産性が高いと言えるわけですね。

単純に開発時間でも2倍~9倍の生産性となるのに、その後のバク発生数が15倍違うとなると、コード品質の重要性が良く分かりますね!

内容紹介

1章 理解しやすいコード

  • 1章 理解しやすいコード
    • 1.1 「優れた」コードって何?
    • 1.2 読みやすさの基本定理
    • 1.3 小さなことは絶対にいいこと?
    • 1.4 「理解するまでにかかる時間」は競合する?
    • 1.5 でもやるんだよ

1章では、本書の中心となっている「理解しやすいコード」とは一体どのようなものなのか?を解説しています。

先に結論を言うと「読んで理解するまでにかかる時間が短いコード」を「理解しやすいコード」と定義しています。

ここで言う「理解する」とは、そのコードを読んで理解した人が「変更を加えることができる」、「バグを見つけることができる」という意味です。

コードを読んでいると「何をしているか?は分かるんだけど、何でしているのか?が分からない」ということがままありますが、これは「理解できない」ということですね。

コードの小ささと理解しやすさはイコールじゃない

本章では「理解しやすい」が「コードを小さくする」と同義になりやすいことに対しての注意喚起もしています。

コードを小さくすることが目的ではなく、「読んで理解するまでにかかる時間を短くする」手段として、コードを小さくするんだよ。ということです。

そのため、読んで理解するまでにかかる時間が短くなるのであれば

  • あえて行数を分けて冗長に記載する
  • コメント行を追加する

のように、読むことにかかる時間が増えたとしても、理解するまでにかかる時間が減るのであれば「ヨシッ!」になります。

リーダブルコードの具体例

リーダブルコードに記載されている具体例を引用します。

行数は増えるけど理解する時間は減る

assert((!(bucket = FindBucket(key))) || !bucket->IsOccupied());
bucket = FindBucket(key);
if (bucket != NULL) assert(!bucket->IsOccupied());

コメントをつけるとコードは長くなるけど理解する時間は減る

// "hash = (65599 * hash) + c" の 高速 版
hash = (hash << 6) + (hash << 16) - hash + c;

まとめ

本記事では、リーダブルコードの中心となる「理解しやすいコード」の意味や、「理解しやすいコード」がもたらす価値について解説しました。

次回からは「理解しやすいコード」を作成するためにリーダブルコードが掲げる具体的な手法の解説をしていきます。

try-catch-finallyのfinallyでthrowしない

前回の記事で「finallyブロックではreturnしない」ことを記載しました。これは「finallyブロックにreturn文を書くと戻り値が上書きされて直感的な動作ではなくなる」からです。

これとは別に、もう一つ同じように結果が上書きされて直感的な動作ではなくなるものがあります。それが「finallyブロックから呼び出し元に例外を投げる」です。

前回の記事を読んでいない方はぜひ前回の記事も参照ください。

tech-kodawari-japan.hatenablog.com

finallyブロックから呼び出し元に例外を投げない

finallyブロックの目的は利用したリソースのclose処理を実行することです。 しかし、リソースのclose処理は例外が発生するものが沢山あります。 そのため、finallyブロックでtry-catchをネストしてclose処理で発生した例外をcatchして対処します。

この時、close処理で発生した例外をcatchせずにthrows宣言を利用して呼び出し元へ投げると「例外の上書き」が発生します。

実際にコードを実行して動作を見てみましょう。

public static void main(String[] args) {
    // どの例外が発生するのか検証
    try {
        String actual = finallyThrow();
        System.out.println(actual);
    } catch (Exception e) {
        System.out.println("4. mainメソッドの例外ハンドリングで出力");
        System.out.println(e.getMessage());
        System.out.println(getStackTrace(e));
    }
}

private static String finallyThrow() throws Exception {
    try {
        System.out.println("1. 例外が発生する可能性のある処理");
        boolean isError = true; // 例外有無の制御用
        if (isError) {
            throw new Exception("処理中に例外発生");
        }
    } catch (Exception e) {
        System.out.println("2. catch:例外をキャッチして例外処理を実行");
        throw new Exception("catchして例外を投げる", e);
    } finally {
        System.out.println("3. finally:リソースのクローズなどを実行");
        // finallyの処理で発生した例外を呼び出し元に投げる(やってはいけない)
        boolean isFinallyError = true; // 例外有無の制御用
        if (isFinallyError) {
            throw new Exception("finallyで例外発生");
        }
    }

    // メソッドの戻り値
    return "methodのreturn";
}

// stackTraceを文字列にして返す
private static String getStackTrace(Exception e) {
    // close処理は割愛しています。
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    e.printStackTrace(pw);
    pw.flush();
    return sw.toString();
}

上記サンプルコードでそれぞれfinallyブロックの例外有無による違いを見てみます。

例外発生後にリソースがcloseできたパターン

1. 例外が発生する可能性のある処理
2. catch:例外をキャッチして例外処理を実行
3. finally:リソースのクローズなどを実行
4. mainメソッドの例外ハンドリングで出力
catchして例外を投げる
java.lang.Exception: catchして例外を投げる
    at inspection.FinallyThrow.finallyThrow(FinallyThrow.java:29)
    at inspection.FinallyThrow.main(FinallyThrow.java:11)
Caused by: java.lang.Exception: 処理中に例外発生
    at inspection.FinallyThrow.finallyThrow(FinallyThrow.java:25)
    ... 1 more

こちらは特に問題なく、業務処理の中で発生した例外が呼び出し元メソッドに投げられ、それをcatchしたmainメソッドでは、どこでどのような例外が発生したのかがちゃんと分かるスタックトレースが出力されています。

例外発生後にリソースのcloseで例外を投げたパターン

1. 例外が発生する可能性のある処理
2. catch:例外をキャッチして例外処理を実行
3. finally:リソースのクローズなどを実行
4. mainメソッドの例外ハンドリングで出力
finallyで例外発生
java.lang.Exception: finallyで例外発生
    at inspection.FinallyThrow.finallyThrow(FinallyThrow.java:35)
    at inspection.FinallyThrow.main(FinallyThrow.java:11)

finallyブロックから呼び出し元に例外を投げた場合、「業務処理で発生した例外の上書き」が起こります。

コンソールの出力を確認しても、業務処理で発生した例外について何も情報が出ておらず、finallyブロックのclose処理で発生した例外しか情報が出ていません。

try-catchを利用するということは、業務処理の中で例外が発生することが想定されます。 そして、想定通り業務処理で例外が発生したのであれば欲しい情報は「想定通り発生した業務例外の情報」であって、「例外により行ったclose処理の情報」ではありません。

そのため、finallyブロックで例外が発生した場合は呼び出し元に例外を投げるのではなく、finallyブロック内でちゃんとcatchして対処しましょう。

try-with-resourcesは例外どうなるの?

AutoCloseableインタフェース、もしくは、Closeableインタフェースを実装しているクラスは「try-with-resources」を利用することでJavaVMがリソースのclose処理を実行してくれます。リソース解放が「プログラマの責務」から「JavaVMの責務」となりますので活用しましょう。

さて、「try-with-resources」を使うと勝手にJavaVMが開放してくれるのは嬉しいのですが、JavaVMがリソースを解放しようとして例外が発生した時、その例外はどうなるのでしょうか。

先に結論から言うと「close処理で発生した例外は抑制」されます。そのため、例外の上書きは発生しません。「try-with-resources」を利用した場合、リソースの開放漏れ、リソース解放時の例外に対してプログラマは何もしなくて良いです。

素晴らしいですね!!責務がちゃんとJavaVMに移っています。プログラマは細かいことは気にしなくて良くなっています!

本当にリソースがちゃんと開放できたのか知りたい

「try-with-resources」を使うとJavaVMが勝手にやってくれるとは言ったものの、場合によってはリソースの開放をちゃんと見届けたい事もあるかもしれません。

例えば、

プロジェクトで固有のリソースクラスを作成していて、そのリソースの開放が失敗してしまうと結構大きなリソースリークが発生する可能性がある。だからちゃんとリソースが開放できたかを把握したい。

こんな場合はどうすればよいのでしょうか?

そんな時は「Throwable.getSuppressed()」を実行しましょう。抑制された全ての例外を取得することが可能です。 close処理でどんな例外が発生していたかをチェックすることができますので、ちゃんとリソースが開放されているか見届けることができます。

詳細は以下に公式ドキュメントのリンクを貼ります。気になった方は参照ください。

Throwable (Java SE 17 & JDK 17)

Chapter 14. Blocks, Statements, and Patterns

The try-with-resources Statement (The Java™ Tutorials > Essential Java Classes > Exceptions)

finallyブロックで例外をcatchして対処する

最後にちゃんとfinallyブロックで例外に対処した場合も見てみましょう。

public static void main(String[] args) {
    // どの例外が発生するのか検証
    try {
        String actual = finallyCatch();
        System.out.println(actual);
    } catch (Exception e) {
        System.out.println("5. mainメソッドの例外ハンドリングで出力");
        System.out.println(e.getMessage());
        System.out.println(getStackTrace(e));
    }
}

private static String finallyCatch() throws Exception {
    try {
        System.out.println("1. 例外が発生する可能性のある処理");
        boolean isError = true; // 例外有無の制御用
        if (isError) {
            throw new Exception("処理中に例外発生");
        }
    } catch (Exception e) {
        // 例外をキャッチした後にエラーを表す戻り値を返す
        System.out.println("2. catch:例外をキャッチして例外処理を実行");
        throw new Exception("catchして例外を投げる", e);
    } finally {
        System.out.println("3. finally:リソースのクローズなどを実行");
        // finallyの処理から例外が発生したけど例外をcatchして対処する
        try {
            boolean isFinallyError = true; // 例外有無の制御用
            if (isFinallyError) {
                throw new Exception("finallyで例外発生");
            }
        } catch (Exception e) {
            System.out.println("4. finallyの例外ハンドリングで出力");
            System.out.println(e.getMessage());
            System.out.println(getStackTrace(e));
        }
    }

    // メソッドの戻り値
    return "methodのreturn";
}

// stackTraceを文字列にして返す
private static String getStackTrace(Exception e) {
    // close処理は割愛しています。
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    e.printStackTrace(pw);
    pw.flush();
    return sw.toString();
}

実行結果

1. 例外が発生する可能性のある処理
2. catch:例外をキャッチして例外処理を実行
3. finally:リソースのクローズなどを実行
4. finallyの例外ハンドリングで出力
finallyで例外発生
java.lang.Exception: finallyで例外発生
    at inspection.FinallyCatch.finallyCatch(FinallyCatch.java:37)
    at inspection.FinallyCatch.main(FinallyCatch.java:11)

5. mainメソッドの例外ハンドリングで出力
catchして例外を投げる
java.lang.Exception: catchして例外を投げる
    at inspection.FinallyCatch.finallyCatch(FinallyCatch.java:30)
    at inspection.FinallyCatch.main(FinallyCatch.java:11)
Caused by: java.lang.Exception: 処理中に例外発生
    at inspection.FinallyCatch.finallyCatch(FinallyCatch.java:25)
    ... 1 more

finallyブロックで発生した例外をcatchしてコンソールに情報を出力しました。 ちゃんと例外に対処してからfinallyブロックを終了したため、mainメソッドのcatchブロックでは業務処理で発生した例外を処理できています。

まとめ

finallyブロックから呼び出し元に例外を投げてしまうと業務処理で発生した例外を上書きしてしまいます。

finallyブロックで発生した例外はちゃんとハンドリングしましょう。また、finallyブロックで例外を出すことを予防するため、finallyブロックにロジックを記述することは極力避けてリソースのclose処理だけ行いましょう。

めんどくさいことを考えたくないので「try-with-resources」を活用しましょう!

try-catch-finallyのfinallyでreturnしない

finallyブロックにはreturn文を書かない

Javaで例外処理を実装する場合、「try-catch-finally」を利用します。

この際、finallyブロックにはreturn文を記述してはいけません。

「try-catch-finally」は以下の順番で処理が実行されます。

  1. tryブロックの中に記載した処理が実行される。
  2. 例外が発生した場合にcatchブロックで例外に対応した処理が実行される
  3. finallyブロックが必ず最後に実行される。

そのため、「finallyブロックでreturn文を記述」した場合、「tryブロックのreturn」と「catchブロックのreturn」は「処理が上書き」されて実行されません。

実際にコードを実行して動作を見たほうが分かりやすいのでやってみましょう。

finallyブロックでreturnしないパターン

public static void main(String[] args) {
    // 何がリターンされるか検証
    String actual = finallyNonReturn();
    System.out.println("4. mainメソッドで戻り値を受け取る");
    System.out.println(actual);
}

private static String finallyNonReturn() {
    try {
        System.out.println("1. 例外が発生する可能性のある処理");
        boolean isError = false; // 例外有無の制御用
        if (isError) {
            throw new Exception("処理中に例外発生");
        }

        // メソッドの戻り値
        return "methodのreturn";
    } catch (Exception e) {
        System.out.println("2. catch:例外をキャッチして例外処理を実行");
        // 例外をキャッチした後にエラーを表す戻り値を返す
        return "catchのreturn";
    } finally {
        // finallyで何らかの処理を実行
        System.out.println("3. finally:リソースのクローズなどを実行");
    }
}

finallyブロックでreturnをしていない場合は特に問題ありません。

コンソールへの出力はそれぞれ以下の通りとなります。

例外なし

1. 例外が発生する可能性のある処理
3. finally:リソースのクローズなどを実行
4. mainメソッドで戻り値を受け取る
methodのreturn

例外あり

1. 例外が発生する可能性のある処理
2. catch:例外をキャッチして例外処理を実行
3. finally:リソースのクローズなどを実行
4. mainメソッドで戻り値を受け取る
catchのreturn

特に違和感なく思った通りの動作ですね。

finallyブロックでreturnするパターン

public static void main(String[] args) {
    // 何がリターンされるか検証
    String actual = finallyReturn();
    System.out.println("4. mainメソッドで戻り値を受け取る");
    System.out.println(actual);
}

private static String finallyReturn() {
    try {
        System.out.println("1. 例外が発生する可能性のある処理");
        boolean isError = false; // 例外有無の制御用
        if (isError) {
            throw new Exception("処理中に例外発生");
        }

        // メソッドの戻り値
        return "methodのreturn";
    } catch (Exception e) {
        System.out.println("2. catch:例外をキャッチして例外処理を実行");
        // 例外をキャッチした後にエラーを表す戻り値を返す
        return "catchのreturn";
    } finally {
        System.out.println("3. finally:リソースのクローズなどを実行");
        // finallyで何らかの処理をしたのでその結果を返す(やってはいけない)
        boolean isFinallyReturn = true;
        if (isFinallyReturn) {
            return "finallyのreturn";
        }
    }
}

finallyブロックに記述したreturn文が実行されると「戻り値の上書き」が発生します。

実際に動かして、コンソールへの出力を見てみましょう。

例外なし、finallyでreturnあり

1. 例外が発生する可能性のある処理
3. finally:リソースのクローズなどを実行
4. mainメソッドで戻り値を受け取る
finallyのreturn

例外あり、finallyでreturnあり

1. 例外が発生する可能性のある処理
2. catch:例外をキャッチして例外処理を実行
3. finally:リソースのクローズなどを実行
4. mainメソッドで戻り値を受け取る
finallyのreturn

見ての通り「戻り値の上書き」が発生しました。

正常終了したら「methodのreturn」、例外が発生したら「catchのreturn」が返ってくるのが直感的な動きです。 しかし、finallyブロックにreturnを記述することで、直感的ではない戻り値の上書きが発生するようになります。

このような直感的ではない動作を作り込んでしまわないように、finallyブロックでは以下のことに気を付けて記述しましょう。

  1. finallyブロックにreturn文を書かない
  2. finallyブロックはリソースの開放のみを行う
  3. finallyブロックには処理を書かない(処理を書くとreturnを書きたくなっちゃう)
  4. 何か処理を書きたいのであれば、finallyブロックを抜けた後に書く
  5. JavaSE7以降であれば「try-with-resources」を積極的に利用する

そもそも、finallyブロックの目的は、使用しているリソースのclose処理を行うことです。 そのため、リソースのclose処理以外にfinallyブロックを利用しないようにしましょう。

利用しているリソースがAutoCloseableインタフェース、もしくは、Closeableインタフェースを実装しているものであれば「try-with-resources」を利用することで、リソースのclose処理をJavaVMにお任せすることができます。こうすることで、リソースのclose処理を「プログラマの責務」から「JavaVMの責務」に移すことができますので積極的に使っていきましょう!

「try-with-resources」を使っていればfinallyブロックを書く必要がありませんし、リソースのclose漏れも自動的に防げます!!

2023卒 新人研修で利用した書籍 バック編

今年、弊社「株式会社こだわり」では初めてとなる新卒採用を実施いたしました。 それに伴い、採用した新人にどのような研修を行うか?が大きな課題となりました。

自分たちでゼロから全て作成するという方法もありますが、世の中には既に初学者向けの評価が高い書籍が沢山存在します。 良い本が沢山あるのだから、活用しない手はない!!ということで評価の高い初学者向けの技術書を活用する方針を取りました。

弊社に引き合いが多い分野が「Webアプリケーションのバックエンドエンジニア」となるためその方向性で書籍を選定しました。 そのうちの1冊がこちらになります。

書籍紹介

弊社に引き合いがある「Webアプリケーションのバックエンド」で案件が豊富にある技術スタックは「Java + Spring Boot」になります。

そのため、新人研修で教える技術を以下に定めて書籍を探していました。

  • 言語:Java
  • WebアプリケーションフレームワークSpring Boot
  • テンプレートエンジン:Thymeleaf
  • ORM:Spring Data JPA

これらの技術に合致する初学者向けの書籍として本書は非常にお勧めできます。

本書のお勧めしたい点

  • サンプルコードを中心とした実装ベースの書籍であり研修とマッチする。
  • 実装に対して詳細な解説があり分かりやすい。
  • 説明の裏付けとして公式ドキュメントを重視している。
  • 実装に複数の方法がある場合どれが良いか理由と合わせて記載されている。
  • Spring Boot 3に対応している。本書以外はSpring Boot 2対応の書籍が多い。
  • Spring Web MVCとThymeleafを学ぶことができMVCの概念を理解できる。
  • Spring Data JPAの基本的な知識とCRUD操作を取り扱っている。
  • Spring Testを用いたJUnitによる単体テスト、MockMvcによるE2Eテストを取り扱っている。

新人エンジニアが身に付けると良い技術や概念が本書にギュッと詰まっています。 これからSpring Bootを触る方は経験年数に関係なく全員が本書を読んだ方が良いと感じるほどに素晴らしい書籍です。

ただし、本書ではWebアプリケーションには付き物である「Session」と「Cookie」に関する説明がありません。 そのため「Session」と「Cookie」に関しては別途資料を作成して研修を行いました。

本書の応用編に当たる以下の書籍では「RestAPI」を取り扱っています。 最近はWebアプリケーションも「SPA + RestAPI」が増えておりますので、入門書で「Session」を取り扱わないのも時代の流れなのかもしれませんね。

注意点

とても良い書籍ですが注意点もありまして、本書は「Java、HTML、CSS、HTTP」の基本的な技術を抑えていることが前提となっています。 そのため、未経験で本当に何も知らない人が本書から学習を始めるのはかなり難しいでしょう。

弊社の新人研修でも、「Java、HTML、CSS、HTTP、Webブラウザ、Webアプリケーション」の研修を行ってから本書を用いたバックエンドの研修に入りました。

本書の構成

  1. はじめに
  2. 環境構築
  3. Spring Bootとは
  4. Spring Initializrとは
  5. Spring MVC
  6. Spring Data JPA
  7. IoCコンテナとは
  8. AOPとは
  9. Spring Security
  10. Spring Test
  11. アプリのパッケージ化
  12. 付録
  13. あとがき

このうち、実際に研修で利用したのは「3章、5章、6章、7章、10章」になります。

取り扱った内容

3章 Spring Bootとは

Spring Bootで起動したWebアプリで「Hello World!」

Spring Bootを利用したプロジェクトの作り方、Spring Bootを利用して起動したWebアプリケーションで「Hello World」の表示を行います。 新しい技術を身に付ける際には「Hello World」から!!これはもうお約束中のお約束ですね!!

5章 Spring MVC

Spring Web MVCを用いたWebアプリケーション

本章ではデータをモデルクラスの形で取り扱う方法を学びます。 リクエストで送信されたパラメータをモデルで受け取り、サーバサイド処理の結果レスポンスとして返すデータのモデルをViewに渡します。 このように、Model、View、Controllerを自分で実装してMVCアーキテクチャに則ったWebアプリを実装します。

6章 Spring Data JPA

Spring Data JPAを利用したDBアクセス

DBのテーブルに対応するモデルを作成して「@Entityアノテーション」や、エンティティに指定するアノテーションを利用してエンティティクラスからテーブルを作成します。 また、併せてバリデーションを指定するアノテーションを利用することで、エンティティの定義を制御する方法や、入力値のバリデーションチェックを行う方法を学びます。 本書ではJPAを利用した基本的なCRUD操作を一通り実装します。

しかし、実務で利用する「ロングトランザクションにおける楽観ロック」や、「入力値による動的SQLの作成」は取り扱っていません。 そのため、これらに関しては本書が終わった後に別途研修を追加で行いました。

7章 IoCコンテナとは

IoCコンテナの概念と「@Scopeアノテーション」を利用したBeanの生存期間

スコープを設定することでDIされたインスタンスがどのタイミングで生成されるかを制御できます。 明示的にスコープを指定しない場合、スコープがsingletonになり単一のインスタンスとなります。 このようなBeanには状態を持たせない!というのは大事ですね。

10章 Spring Test

JUnitを利用した単体テストとMockMvcを利用したE2Eテスト

CI/CDをちゃんと回して品質を維持するためにも、JUnitとMockMvcを利用したテストは非常に役に立ちます。 最近はテストコードを作らない現場はほぼないと思いますので新人研修でもテストコードに関する研修は大事だと思います。

割愛した章

4章 Spring Initializrとは

Spring Initializrは実務であれば環境構築手順書があることが殆どで、自分で考えて実施することはほぼ無いため飛ばしました。

8章 AOPとは

AOPトランザクション管理、ロギングなど利用することが多い技術です。 しかし、本当にAOPと向き合う必要があるのはフレームワークをどのように利用していくかというコードベースを考えるタイミングです。 そう考えると、既にあるコードベースの上で実装を行う新人にはちょっと過剰な詰め込みになるかな?と思い割愛しました。

9章 Spring Security

Spring Securityを利用した認証、認可の実装方法を取り扱います。 しかし、新人が認証、認可というセキュリティに直結する部分をいきなり任されることは考えにくいでしょう。 また、認証済みユーザを利用する実装は参考となる既存コードが豊富にあることが予想できます。 であれば、それ以外の部分に時間を割いた方が良いと判断しました。

総括

Spring Bootを始めたい、触りたいと思っている人全員にお勧めできる良書です!!

これだけ内容が良いにも関わらず、「Amazon Kindle版の値段はたったの980円」ですし、「Kindle unlimitedで無料」です。

読んでいて特に良いと思った点は「公式ドキュメントをとても重視している」ことです。

調べ物で検索をした際、現在の検索エンジンの仕様では、何度も閲覧されてきた古いやり方が上位に出てくることが多いです。 こんな時、ちゃんと公式ドキュメントを読んで情報の裏取りをすれば、古くて非推奨となっている方法をそのまま踏襲してしまうことを予防できます。

同様に、公式ではない有用なハックの方法が世の中には沢山あり、ハックしなくては実現できないことも多々あります。 しかし、まずは公式が提示する方法の中で解決策を探ることがとても大事だと思います。 せっかく公式が方法を用意していても、それを利用せず安易にハックしてしまうとバージョンアップが大変になってしまいます。

公式が作成しているドキュメントが、この世界で最も信頼できるドキュメントであるはずです。 だから、公式ドキュメントを重視している本書は非常に信頼できます。

2023卒 新人研修で利用した書籍 フロント編

今年、弊社「株式会社こだわり」では初めてとなる新卒採用を実施いたしました。 それに伴い、採用した新人にどのような研修を行うか?が大きな課題となりました。

自分たちでゼロから全て作成するという方法もありますが、世の中には既に初学者向けの評価が高い書籍が沢山存在します。 良い本が沢山あるのだから、活用しない手はない!!ということで評価の高い初学者向けの技術書を活用する方針を取りました。

弊社に引き合いが多い分野が「Webアプリケーションのバックエンドエンジニア」となるためその方向性で書籍を選定しました。 そのうちの1冊がこちらになります。

書籍紹介

この本を選んだ理由

  • Webアプリのバックがメインでありフロントは網羅的な書籍が良い。
  • 本書はHTML、CSSJavaScriptを網羅的に扱っていて要求にマッチ。
  • 名前の通り「基本」から取り扱っており、未経験者も読みやすい。
  • 実際にコードを作成して学ぶ本なので、ハンズオン形式の研修ができる。
  • 基本を学んだ後には、レスポンシブWebデザイン、Bootstrap、Ajax、Vue.jsと基本から一歩踏み込んだ情報もある。

他にもフロントに関する評価が高い書籍は色々とありました。 しかし、評価が高い本はデザインに踏み込んでいる本が大多数でした。

今回の研修ではあくまでもメインは「Webアプリのバックエンド」です。 とは言っても、バックエンドだからとHTML、CSSJavaScriptを全く知らないわけには行きません。 そのため、UIデザインの知識より、広く網羅的にHTML、CSSJavaScriptが学べる本が欲しかったという形です。

本書の構成

  1. Webの開発環境を整えよう
  2. HTMLとCSSのきほんを学ぼう
  3. スマートフォン対応のきほんを学ぼう
  4. CSSフレームワークのきほんを学ぼう~Bootstrapでフォームを作る
  5. JavaScriptのきほんを学ぼう
  6. イベントドリブンのきほんを学ぼう~DOMを使ってストップウォッチを作る
  7. Ajax通信のきほんを学ぼう~jQuery、Vue.jsにもチャレンジ!
  8. Appendix
  9. Index

取り扱った内容

1章 Webの開発環境を整えよう

VSCodeを用いたフロント開発環境の作成

VSCodeは仕事で触ることが多いエディタです。 新人の方はメモ帳しか触ったことが無く、高機能なエディタは初めてという方が多かったです。 ここでVSCodeを実際に動かす経験ができるのはとても良いですね。

2章 HTMLとCSSのきほんを学ぼう

HTMLとCSSを利用したフロントの作成

サンプルと説明が豊富にあるため、初めてHTMLを利用する人にも説明しやすい構成となっています。 新人研修の際は、せっかくVSCodeを利用していますので「Microsoft公式のLive Preview」をインストールして作成したHTMLのプレビューを見ながら作れるようにしました。

3章 スマートフォン対応のきほんを学ぼう

リキッドレイアウト、レスポンシブWebデザイン、CSSアニメーションの実装

サンプルに則り作成を進めることで、実際のECサイトにありそうなかっこいい商品紹介ページができ、新人の方にエンジニアリングの楽しさを体感してもらうことができます。 本章まではHTMLとCSSを全て手書きしているため、どこに何を記載したらどのように見えるのか?どのように動くのか?がすぐに分かるようになっているのがとても良いです。

4章 CSSフレームワークのきほんを学ぼう

CSSフレームワークのBootstrapを利用

3章で学んだレスポンシブWebデザインがBootstrapのグリッドシステムを利用することで簡単に実現できることが説明されます。 2章、3章を通して自分でCSSを書いていたことから、Bootstrapがとても巨大なCSSの塊であることも理解できるようになっています。

5章 JavaScriptのきほんを学ぼう

JavaScriptを利用した動的表示の実装

静的なHTMLだけでは実現できない、JavaScriptを利用した動的な表示の仕方を学びます。 弊社新人研修のタイミングでは、既に新人の方々にJavaの基礎研修を行っていたため、本章を問題なく進めることができました。 初学者が本書籍を読んでいる場合は、本章からプログラムロジックが出てくるためちょっと苦戦するかもしれません。

6章 イベントドリブンのきほんを学ぼう

DOMを利用した画面描画とイベントドリブンの実装

DOMとイベントドリブンは初学者にはやや難しい概念となります。 そのため、新人研修の際、DOM操作やイベントドリブンに関しては本書籍だけではなく、別途資料を作成して研修を進めました。

7章 Ajax通信のきほんを学ぼう

jQueryやVue.jsを利用したAjax通信

本章は読み合わせるだけとしました。この章ではAjaxを行うためにjQuery、Vue.jsを取り扱っています。 Vue.jsなどのJSフレームワークを利用する場合、フロントはフロントエンジニアが担当することが多いです。 今回の新人研修はメインターゲットが「Webアプリのバックエンド」であるため、フロントにどのような技術が存在しているか?を紹介するに留め、フロント技術の深堀は行いませんでした。

総括

未経験者を含む新人研修に活用する本として申し分ない本です。

題名の通り「きほんのきほん」を教える本となっていますので、より専門的な知識が欲しい場合は本書籍では不足する部分があります。

本書籍の記載が「基本」→「応用」という形になっています。そのため、新人研修でもまずは基本を抑えて、その後に応用に進む形になります。 ちゃんと基本が理解できていれば応用も進める内容となっていますが、実は基本がまだちゃんと理解できていなかったために応用で躓くことがありました。

これは、応用に入った際に基本の理解ができているか?がチェックできているということになります。研修であれば躓いたときに基本に立ち返って深堀して理解を進めることができます。

サンプルが豊富にあり、実際に物を作りながら理解を進める書籍となっていますので新人研修で活用できる良い書籍です!