Effective Javaの存在しない世界、それがIneffective Javaだ
最近はJavaで開発するとなるとSpringBootなどのフレームワークを使用してアプリケーションを構築することが多いと思います。
SpringBootは本当によくできています。DIや、AutoConfigureなどコードの記述量を減らす素晴らしい仕組みがたくさん用意されています。
Javaをよく知っているプログラマーはアーキテクトとしてフレームワーク周りの設計や実装を行うことが多いでしょう。テンプレートメソッドパターンなどを使用して、大量生産しやすいアーキテクチャを作り上げます。あとは、各機能を実装するプログラマーにバトンタッチし、画面や業務処理がフレームワークに沿う形で作り上げられていきます。
しかし、業務処理は当然必要です。みなさんの現場においてそういった大量かつ並行で書かれるコードの品質はいかがでしょうか?
私の周りでもそのあたりの問題を抱えていて、これは開発現場で正しく気づけるエンジニアが必要だと考え、社内向けにJava教育を始めました。本記事はその教育中のコードレビューで気づいた、**「そっか、こういうことを理解していないんだ」**ということをまとめてみました。バグを見つけたときにありがちな、「なんでこんなクソコード書いているの?」という管理者の皆さんに教育、レビューの大切さに気づいて貰えればと思います。おそらく、そういう職場にはEffective Java/Readable Codeなどの書籍はないか、ホコリを被っていませんか。教育はとても大事なのです。
なんでもかんでも、HashMapを使ったり、ロジック中にログを吐くのはそういうことを知らないのが理由だったりします。
Java教育ってどんなの
2クール開催した
- 2018年6月-9月 26名 週1回 全16回
- 2018年11月-2019年2月 15名 週1回 全8回
毎週講義(2時間)して、演習を出して、プルリクエストをもらって、レビューして返すという感じです。講義の間はSlackでフォローしてました。
教材はカサレアルさんの教材を購入して実施しました。一般的な書籍買うよりかは高額ですが解説する順序がうまく組み立てられているのがとても良いです。常にペアプロとかできる環境なら、テキストはいらないと思いますが、今回のような社内教育だとうまくハマったと思っています。
対象者はこんな人
- Javaを業務で書き始めた1年目
- 実はJavaを書いているけどという3-4年目ぐらい
- 別の言語からJavaに転向してきた10年目など様々です。
それではプルリクエストで見かけた、これは知っておくべきという内容を一挙紹介します。順位は私の感覚です。
「こんなん絶対知ってるで」という人は周りのNewbieにぜひ聞いてみてください。あなたの周りにも多分いるはずです。習ってないものは知らないんです。
Ineffective Java
項目1 toString()ってなに?
このメソッドの役割を知らないという人が多かったのは驚きでした。
すでにtoString()がオブジェクトに実装済みであるにも関わらず、 object.getXXX() + object.getYYY()
と書かれたコードを見たことはないでしょうか?
これはtoString()の意味を知らないという状況が裏にあったのです。皆さんの周りの若手にも聞いてみてください。
項目2 左辺の型の宣言が常に右辺の型と同じ
ArrayList<String> list = new ArrayList<>();
もちろん、左辺はList<String>
とするべきですよね。しかし、インターフェースとかポリモーフィズムとかそういう考慮がないと左辺は右辺と同じ型で宣言してしまいます。
そういう状態の人にOCPとかいってもちんぷんかんぷんになりますので、継承->インターフェース->コレクション->ポリモーフィズムという風に順を追って説明してあげることが必要です。
これだけで、左辺を正しく自分で考えて定義するようになるでしょう。
(左辺とか右辺とかという用語が正しいのかは不明)
項目3 とにかくラッパーに変換
Long.valueOf(Files.size(pathA)).equals(Long.valueOf(Files.size(pathB)));
どこかでコピってきたんでしょうね。もしくは、ラッパーにするとなんか安心感が出るのかもしれません。プリミティブをプリミティブのまま扱うことを正しく理解する必要があります。
これを理解することで、オブジェクトを無駄に生成することが悪手であることをじわじわと学ぶことができるでしょう。
項目4 不必要なコメント
こんなコード見たことありますよね。Eclipseの自動生成コメントが残っている
、変数の説明とかどうでもいいコメント
前者のケースはそもそもコードを書くのに必死過ぎて、コメントが目に入らない。後者はコメントは大事という教育だけ受けて放置されて育った例でしょう。
これはペアプロなどをしていると一瞬で気づけるのですが、そうでない場合は誰にも学ばないのでそれがずっと続いていきます。正しく教えてあげましょう。基本、コメントは要らないよ。業務的にイレギュラーなことをやる場合は必要だよ。そうしないと後の保守フェーズでコメントがもとでバグ出るかもしれないよ と。
項目5 ここif文いらないよ
public boolean isLessThan1KB(String file) throws Exception {
// Pathオブジェクト生成
Path path = Paths.get(file);
if (Files.size(path) < 1024) {
return true;
} else {
return false;
}
}
これはとても多いです。if文以降は、 return Files.size(path) < 1024;
で書き換えられます。
一回書いたコードは動けばそれで終わりと考える場合にこういう書き方が多いです。なんか冗長だなと感じるためには、上位者のコードレビューが必須です。
項目6 なぜか戻り値を見ない
public void delLine(String line) {
lines.remove(lines.indexOf(line));
}
List #removeメソッドには戻り値があります。戻り値を無視してそのまま使用するケースが散見されます。これはネット上のどこかにそういう書き方があるのかもしれません。
この裏には初心者はエラー処理が苦手だということが大いにあります。例外、エラーハンドリングなど、そのあたりを理解すると自然と解消されていくでしょう。
項目7 try-with-resourcesに馴染めない
今でも現場のJDKは6だという方に多いです。いつまで昔の書き方を続けるんでしょう。これはtwrに関わらず、for文、Stream、lambdaなど全てに同じ状況でしょう。
Java8をきちんと勉強し直すことをおすすめしましょう。Java11から始める新人にとって、この人達は脅威でしかありません。
項目8 ネストしたがる
if(xxx == true) {
//処理
} else {
//処理
}
必ずこういう風に書いてしまう生真面目なプログラマー。世界にはガード節というものがあるんだよと教えてあげたい。ガード節を使うともっともっとスッキリすることがほとんど。
ネストだらけのコードに普段からまみれていることが原因の1つ。わかる。一個ネスト減らしても違いわからないよね でも、これはきちんとレビューしてあげると一発で理解してもらえるので、即効性は極めて高い。
項目9 equals()の意味がわからない
これはそもそも非常に難しい。Java中級者でもとっさに説明しろと言われても難しいかもしれない。しかしである、これがわからないと怖くて、TreeMapとか使えないのです。だって、任意のオブジェクトが正しくソートされるかわからないのですから。だから、いつもHashMap野郎になってしまって、get()してからこねくり回してしまう。
equals()を実装すると当然hashCode()も実装するんだよ。そうしないとなんかおかしい事象がたくさん発生するよ。このことが正しく理解できると、この理解以上にコードはより洗練されるのです。これこそまさに Effective Javaなのです。
項目10 イミュータブル??
不変オブジェクトを知らない。これは初級から中級へ上がるのにとても大切な知識です。いつのまにか潜むバグを根絶するためにオブジェクトの状態を推量できる能力。これがJava中級者なのだろうと思います。どうすれば不変オブジェクトを作れるのか?それはどういうときに使うのか。それがわかればクラス設計の幅が大きく広がるでしょう。逆にこれをしらないといつまでも通り一遍の設計しかできない。
あと、イミュータブルと直接関係ないですが、final List<String> stringList;
のようなListなのにfinalとはどういう意味かを正しく説明できないケースもあるのでこれも正しく理解することは超大事。
Ineffective JavaからEffective Javaのある世界へ
初級から中級への架け橋のような内容が多く登場してきましたが、こういったことの多くはEffective Javaを読むことで成長することができます。初級者の人は中級者の人にわからないことを質問しましょう。中級者の人は初級者の人を誘って輪読会を開催しましょう。
Effective Java 3rd Edition
Java8を学び直すならこちらがおすすめ
Javaプログラマーなら習得しておきたい Java SE 8 実践プログラミング