1.オブジェクトと依存関係-DAO分離


1.2分離DAO


1.2.1注目点の分離


オブジェクト向けの世界では、ビジネスニーズに応じてオブジェクトの設計が変更される可能性があります.
すなわち,実装オブジェクトのコードが変わる可能性がある.
また、アプリケーションに依存するオペレーティング環境やテクノロジーも変更または廃棄されます.
オブジェクトを設計する際に最も重要なのは、将来の変化にどのように対応するかです.
これも,オブジェクト向けの設計やプログラミングが従来のプログラム化プログラミングよりも面倒な理由である.
これは、
  • のオブジェクト向け設計の変化に効果的に対応できるからである.
  • 変化に対応する最善の対策:変化幅を最小限に抑える.
  • 変更時に必要な作業量を削減しました.
  • この変更は他の場所で問題を起こしてはならない.
  • このようにするには、分離と拡張の設計を考慮する必要があります.
  • ぶんり
    変更と発展は一度に一つの注目点に集中して発生する.
    ここでは、開発者は1つの注目点を1つの場所に集中します.
    つまり、同じことに関心を持っているものを集めて、違うことに関心を持っているものを分けるということです.(興味分離)

    1.2.2コネクタの抽出の作成


    UserDaoが注目している問題


    前章のUserDaoの1つのadd()メソッドでは3つの注目点が見られる.

  • DBへの接続を取得します.
    さらに細分化し、DBタイプ、ドライバタイプ、ログイン情報、接続作成方法などを定義する必要があります.

  • Statementの作成と実行
    1つの関心事は,パラメトリックユーザオブジェクトの情報をStatemにバインドし,DBを介してそのStatemを実行する方法である.

  • タスクを終了すると、実行中に使用したリソースを閉じます.
  • なお、現在のUserDaoには異常処理はありません.

    重複コードの抽出方法


    DB接続をインポートする部分はUserDaoのAdd()メソッドとget()メソッドに重複するコードが存在する.
    後で、このセクションのコードをgetConnection()という独立したメソッドとして作成できます.
    public void add(User user) throws ClassNotFoundException, SQLException {
        Connection c = getConnection();
        ...
    }
    
    public void get(String id) throws ClassNotFoundException, SQLException {
    	Connection c = getConnection();
        ...
    }
    
    public Connection getConnection() throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.cj.jdbc.Driver");
    
        // Connection 을 가져온다.
        Connection c = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/toby?useSSL=false", "root", "password"
        );
    
        return c;
    }
    後でドライバクラスまたはDataBase URL情報を変更した場合は、getConnection()メソッドのコードを変更するだけです.
    他のコードが興味を持つ方法には影響しないだけでなく,興味のある内容は独立して存在するため,修正も簡単になった.

    変更の検証:再構築とテスト


    メソッド抽出技術
    複数の特定の機能を担当する場所から重複データを抽出
    再構築:外部動作の操作やスキルを変更することなく、内部構造を変更して既存のコードを再構築します.
    getConnection()メソッドの生成などを再分解した後、機能に問題がないことをテストで確認する必要があります.
    前章のmain()メソッドを使用してテストできます.
  • 現在、メインメソッドテストが複数回実行されている場合、2回目から無条件に異常が発生します.
  • usersテーブルのプライマリ・キーid値が重複しているためです.
  • ソリューション:ユーザー・テーブルのデータを削除した後、main()テストを実行すればよい.
  • 1.2.3 DB接続の作成とは独立


    2つの異なるクライアントN社とD社が存在すると仮定する.
    この2つのクライアントは、異なるタイプのDBを使用します.
    UserDaoソースコードをNとDに提供しない場合、各クライアントのDBタイプに応じてUserDaoを使用できますか?

    継承による拡張


    UserDaoコードはもう1つのレベルを分離すればよい.
  • UserDaoコードのgetConnection()を抽象メソッドとして作成します.
  • では、N社とD社がUserDaoクラスを継承し、それぞれNuUserDaoとDUserDaoというサブクラスを作成します.
  • public abstract class UserDao {
        public void add(User user) throws ClassNotFoundException, SQLException {
            Connection c = getConnection();
        ...
        }
    
        public void get(String id) throws ClassNotFoundException, SQLException {
            Connection c = getConnection();
        ...
        }
    
        public abstract Connection getConnection() throws ClassNotFoundException, SQLException ;
    }
    public class NUserDao extends UserDao{
        @Override
        public Connection getConnection() throws ClassNotFoundException, SQLException {
        ...
    	}
    }
    
    public class DUserDao extends UserDao{
        @Override
        public Connection getConnection() throws ClassNotFoundException, SQLException {
        ...
    	}
    }
    以上のコードにより,関心のある問題を分離できる.
  • DAOのコア機能-データの登録とインポート方法-
  • DB接続方法注目点
  • 現在ではUserDaoは簡単な変更性を超えており,拡張しやすいといえる.
  • の新しいDB接続方法を適用する場合は、UserDaoを継承により拡張するだけでよい.
  • テンプレートメソッドアレイ
    スーパークラスに基本論理のインフラストラクチャを作成し、その機能の一部を抽象メソッドまたは上書き可能な保護メソッドとして作成し、必要に応じてサブクラスでこれらのメソッドを実装して使用します.
    UserDaoのサブクラスのgetConnectionメソッドは、Connectionクラスのオブジェクトをどのように作成するかを決定するメソッドと見なすことができます.
  • は、このようにしてサブクラスで特定のオブジェクト作成方法を決定することをファクトリメソッドモードと呼ぶ.
  • 「UserDaoでファクトリメソッドモードを適用してgetConnection()を分離する」

    継承によって注目点を分離する問題


  • Javaではクラスの多重継承は許可されません.
    後でサブクラスがUserDaoだけでなく他のスーパークラスも継承する場合、問題が発生します.

  • 継承を通じて、上、下の関係は想像以上に密接になっている.
    サブクラスはスーパークラスの機能を直接使用できません.
    したがって、スーパークラスの内部に変更が発生すると、すべてのサブクラスを同時に変更する必要があるという問題が発生します.

  • 最大の欠点は,拡張機能DB接続を生成するコードを他のDAOクラスに適用できないことである.
  • ソース:github