見出し画像

Effective java 3版 読書会 1日目

対象範囲:第2章 オブジェクトの生成と消滅
     項目1~7(項目8は時間の都合上未実施)
参加者:こなやん、yodaiyoridoriまさややぎたkassyi
形式:オンライン(discord)
   課題本を事前に読み、実業務と照らし合わせて記述内容の
   議論をする。

項目1 コンストラクタの代わりにstaticファクトリメソッドを検討する
staticファクトリメソッドは、任意のオブジェクトを返せるのが利点
特に、WebApiでリクエスト種別ごとにオブジェクトを作って返す時に便利
オブジェクトを作る代理を作って、サブクラスを返すこともできる。
普段、意識せずに使っていることもありそう。
コンストラクタとこれを同時に使うことがあるかとの質問は、今までの経験上見たこと無いとの回答

P7の2段落目「プログラマは・・・インタフェースで表されたAPIを正確に知っている」の意味が良く分からなかった。
APIの取得の難易度が軽減されているから?

項目2 多くのコンストラクタパラメータに直面したときにはビルダーを検討する
ビルダーパターンの使用は、コンストラクタのパラメータが多数有るときに便利
でも、クラス変数を使えば良いのではとの指摘有り。
画面遷移時にパラメータを別画面に渡す時に使ったことがある。
分かりやすさを考慮して適宜使えば良いのではとの結論

項目3 privateのコンストラクタかenum型でシングルトン特性を強制する
業務では、シングルトン自体余り使わない模様
使用用途としては、キャッシュを管理する所やDBとかで使うかも
enumでシングルトンを記述することを推奨しているが、コードレビューや他人が見たときに混乱を招きそうなので多分使わないとの結論

項目4 privateのコンストラクタでインスタンス化不可能を強制する
コンストラクタをprivateにすると、インスタンス化を防止できるという内容
特筆する議論は無し。

項目5 資源を直接結び付けるよりも依存性注入を選ぶ
クラスが他の資源を使用する場合は、シングルトンではなく以下を実施すべき
(間違い)コンストラクタで外部クラスをインスタンス化する
(正解)コンストラクタに外部クラスのインスタンスを渡す
⇒下記にyodaiさんによる解説追記

シングルトンのテストは、外部アクセスが不可なためやり辛いが、
リフレクションを使用すると可能
Junitでリフレクションをテストコードに入れてPriveteのメソッドに入れる
それには、パワーモヒートというライブラリが有る

項目6 不必要なオブジェクトの生成を避ける
Stringなどのオブジェクトの再生成には気を付ける必要が有る。
また、Longとlongなど、ボクシングされた基本データ型との打ち間違いには気を付ける。

項目7 使われなくなったオブジェクトの参照を取り除く
Javaもメモリーリークがあるので気を付ける必要がある。
ツールを使って調査する場合、変化が激しければ分かり易いが
じわじわと変化する場合は分かり辛い。

yodaiさんによる項目5の解説

コンストラクタで外部クラスをインスタンス化ーよりー
コンストラクタに、外部クラスのインスタンスを渡してあげる、感じですね
たとえばー

interface ExternalServer {
   // 外部サーバに接続
   void connect();
   // 何かを送信
   void send(byte[] content);
   // 切断
   void disconnect();
}

みたいな外部接続先を表すインターフェースがあって、HTTPで何かを送信したり、Socketで何かを送信するコンクリートなクラスがあります

public class HTTPServer() implements ExternalServer {
}
public class SocketServer() implements ExternalServer {
}

ここで、外部に何かを送信しなきゃならないビジネスロジックがあるときに、

public class BusinessLogic {
   private ExternalServer server;
   public BusinessLogic() {
       this.server = new HTTPServer();
   }

とかコンストラクタで生成してしまうと、BusinessLogicはHTTPでしか送信できない、ってなってしまいます。
そこで、

    public BusinessLogic(ExternalServer server) {
       this.server = server;
   }

というふうに外でクラスのインスタンスを生成して渡してあげると、HTTPでも送信できるし、Socketでも送信できるし、というふうにうまく切り替えることができます。
なんというか疎結合にしてあげる、って感じです。
というのと、ビジネスロジックはビジネスロジックで、とにかく何か送信したい!ExternalServerのインターフェースに対してコードを書くけど、外部サーバがどんなものであるかは知らないよ!
えーとインターフェースに対してコードを書くだけでよくなります。
あとはー
BusinessLogicの単体テストも、ExternalServerのスタブクラスを作ってあげて実際に外とやり取りしなくてもよくなったり、HTTPServer、SocketServerに接続するテストも、BusinessLogicを使わなくてよくなりますー
関心ごとの分離ってやつです。

シングルトンのテストについて(解説:yodaiさん)

シングルトンのテストは、外部アクセスが不可なためやり辛いというところで、シングルトンで取得したインスタンスを使うクラスのテストがしづらいというか、外部からシングルトンの内部で持っているインスタンスは、システムで一意になる、という性質があります。
(システムで一意にしなきゃならないインスタンスを管理するのがシングルトンなので・・・)
なので、テストのときには、シングルトンから取得したもの微妙に変えて異常系をテストしたい、となったときにちょっと都合が悪いというか、Mockito使ってこんなことをしなきゃならなかったりします。

リンク

協力:Tech Baton
https://tech-baton.studio.design/



この記事が気に入ったらサポートをしてみませんか?