セッターとゲッターとOOPについて


これはビジネスプロジェクトです.

建築


ビジネスオブジェクト


過去に、我々のアーキテクチャは「ビジネスオブジェクト」と呼ばれているクラス(それも若干の他の名前を持っています、しかし、考えは同じです)で構成されました、それは論理(機能)と店価値(別名フィールド)を含むクラスのタイプでした.
例えば、顧客を管理するシステムがあるとしましょう.
public class Customer {
    private String age;
    private String name;
    private String prefix;
    // setter and getters goes here...

    public void showMe() { // some logic
        System.out.println("My name is "+name);
    }
}
これは細かいプロジェクトの細かい作品.このような授業についての本やマニュアルを見つけるのは珍しいことではない.しかし、彼らはスケーラブルでありません、そして、それは若干のトラブルを提示します.そこで、このクラスを2つに分けました.

貧血オブジェクト


それは論理を欠くべきである値を格納するクラスです.
public class Customer {
    private String age;
    private String name;
    private String prefix;
    // setter and getters goes here...

}
それは、データベースの我々のクラスです
年齢
名称
接頭辞
10
ジョン
博士
20
アナナ
ドクター.
30
ポール
ジュニア
そして、それは休息サービスを介して私たちのクラスです
{"age":10,"name":"John","prefix":"Phd"}
それは論理を持つことができました、しかし、それは推薦されません.

サービスクラス


モデルクラスとは異なり、サービスクラスは、フィールド(メソッド/関数)を含む間、フィールドを欠いています.
public class CustomerService {    
    public void showMe() {
        System.out.println("My name is "+name);
    }
}

なぜ我々はクラスを分割?


デバッグしやすくコードを維持するのが簡単です.また、プロジェクトを拡大し、他のコードを破ることなく、新しい機能を追加するのに役立ちます.
例えば、データベースに接続するメソッドを追加したいとしましょう
public class CustomerMySql {   // usually it is called CustomerRepo etc.
    public List<Customer> listAll() {
        // our code
    }
}
それは何ですか.サービスクラス.実際には、私たちはできるだけ多くのサービスクラスを持つことができます.
したがって、サービスクラスもカテゴリごとに分離します.
  • リポジトリ、dao、dalクラス(データベースに接続する)
  • Webサービスクラス.
  • ロジッククラス(検証、ファクトリなど)242479182
  • その他.
  • また、なぜ?デバッグやコードを維持するのは簡単だからです.問題があるとしましょう、私たちのシステムはデータベースに顧客を挿入することができません.そこで、名前空間(MySQL)を見つけ、顧客から始まるクラスを見つけ、メソッドを見つけます.

    質問:しかしセッターとゲッターはどうですか?


    まあ、私たちのモデルのクラスでは、ロジックを追加している、ほとんどの時間が無駄なロジック!
    論理
    public class Customer {
        // ....
        public String getAge() {
            return age;
        }
    
        public void setAge(String age) {
            this.age = age;
        }
    }
    
    私たちはそれを隠すためにLombok(それは非常に推薦される)を使用することができました、しかし、それはまだ論理です.
    @Getter @Setter // lombok
    public class Customer {
        private String age;
        private String name;
        private String prefix;
        // we don't need setter and getter.
    }
    
    ロンボックはコンパイル時に動作するので、コンパイル前にコードを追加するのと同じですが(コードはとにかく追加されます).

    質問:しかし、OOP


    しかしOOPはカプセル化を必要とします.

    OOPは法律ではなく、そのガイドラインです.

    質問:セッターとゲッターの問題は何ですか?


    コードの明快さ.
    それは、我々がセッターとゲッターでモデルを使う方法です.
    Customer cus=new Customer();
    cus.setName("John");
    System.out.println("The age is "+cus.getAge());
    
    そしてそれはパブリックフィールドとのバージョンです.
    Customer cus=new Customer();
    cus.name="John";
    System.out.println("The age is "+cus.age);
    

    質問:我々はパブリックフィールドと論理を追加できませんでしたか?


    次のコードを言いましょう
        public void setName(String name) {
            this.name = name;
            this.prefix="Junior";
        }
    
    したがって、名前を変更すると接頭辞も変更します.セッターで論理を加える問題とゲッターは、明白でありません.
    例えば、
    Customer cus=new Customer();
    cus.setPrefix("Dr.");
    cus.setName("John");
    
    // it will return Junior John instead of Dr. John. 
    
    セッターとゲッターに論理を加えることは、通常悪です.
    また、デバッグとテストが簡単なサービスクラスでロジックを書くことができました.

    質問:値をカプセル化する必要があります。


    はい、それはセッターとゲッターによって解決されません!
    例えば、私たちのモデルが新しい分野を持っていると言いましょう
    public class Customer {
        private String age;
        private String name;
        private String prefix;
        private Category category;
        // setter and getters
    }
    public class Category {
        private String nameCategory;
        // setter and getters
    }
    
    例えば、カテゴリ内の名前を変更したいとしましょう.
    Customer cus=new Customer();
    cus.setName("John");
    cus.getCategory().setNameCategory(""); // Using get to set a value @_@.
    
    それで、我々のゲッターはカプセル化を欠いています(我々はGETを使っているフィールドを修正しています)、しかし、それはきれいでありません.

    質問:次に、どのように値をカプセル化できますか?


    まず、すべての(Javaが他の言語のためにも適用されます)開発者はプリミティブ対オブジェクトと値と参照の違いの違いを理解する必要があります.
    私たちはまた、クローンを作成することによって値をカプセル化することができました、しかし、我々は明白な理由のためにありません.
    また、それが不変でなければならない値を読むならば、なぜ我々はそれを修正していますか?そして、我々がSRP(単純な責任原則)を適用するところで、我々は同時に1つの仕事をします:あるいは、我々は値を変更するか、両方ともでなく値を読みます.

    セッターとゲッターなしでは単体テストはできませんでした。


    よく聞く

    生成されたコードの単体テストを行わないでください.また、些細なコードの単体テストを行いません.これはコードのカバレッジに影響を与えるが、コードカバレッジだけではなく、何か価値の尺度ではない(本当に)です.多くの開発者は、コードカバレッジを人工的に増やすことによってシステムを再生する.

    セッターとゲッターなしでインターフェイスを使用できませんでした。


    インターフェースはコードを再利用できるので便利です.

    Some java coders create one Interface = One class and it is SO WRONG but I'm not talking about it.


    ソリッド( i =インタフェース)について

    ソリッドはガイドラインではなく、ルールです.
    しかし、インターフェースについては、次のモデルがあるとしましょう.
  • 客(年齢、名前、接頭語)
  • 従業員(年齢、名前、会社)
  • それで、継承でないならインターフェースをつくるのは意味があるかもしれません.(ヒント:本当にではない).
  • 人(年齢、名前)
  • だから私たちのクラスは
    public class Customer implements Person {
       // implementation
    }
    public class Employee implements Person {
       // implementation
    }
    
    public interface Person {
        String getName();
        void setName(String name);
        String getAge();
        void setAge(String age);
    }
    
    
    ただし、インターフェイスの使用に依存が追加されます.
    さて、顧客の年齢を持ちたくないとしましょう.インターフェイスを変更すると、クラスの従業員を変更します.
    インターフェイスは、彼らが明確な目的で使用されている場合は右ですが、それはまたダブルエッジの剣です.
    また、インターフェイスでコードをデバッグするのは難しいです.
    このコードが失敗したとしましょう.
       SomeInterface object;
       // it fails somewhere here.
    
    質問:オブジェクトのクラスは何ですか?

    しかし


    すべてのオブジェクトが似ているわけではない.たとえば、ビジュアルオブジェクト、ボタン:

    ビジュアルオブジェクトの場合、モデル+サービスクラスペアを使用しませんが、Bussiness Objectクラス(フィールドと関数を持つクラス)を使用しません.なぜ?彼らが貧血モデル+サービスクラスよりよく合うので.
    public class MyButton {
        private String Title;
        private int width;
        private int height;
        private int top;
        private int left;
        // setter and getter also functions
    }
    
    セッターとゲッターにロジックを加えることもできました.
    public class MyButton {
        //....
        public int getXRight() {
            return left+width; // we can use a getter with logic without a field.
        }
        public void setWidth(int width) {
            if(width<100) {
                width=100;
            }        
            this.width = width;
        }
    }
    

    Also


    時々、コードを標準化したいと思います.つまり、1つのクラスのスタイルと別のクラスの別のスタイルを見たくありません.
    たとえば、コンテキストによっては正しいです.
    class Model1 {
        public int field1;
        public int field2;
    }
    class Model2 {
        public int field3;
        public int field4;
    }
    
    そしてそれも正しい
    class Model1 {
        private int field1;
        private int field2;
        // setter and getter goes here.
    }
    class Model2 {
        private int field3;
        private int field4;
        // setter and getter goes here.
    }
    
    しかし、そうではありません.
    class Model1 { // with setter and getters
        private int field1; 
        private int field2;
        // setter and getter goes here.
    }
    class Model2 { // with public fields
        public int field3;
        public int field4;
    }
    

    その他


    ライブラリにはsetterとgetterの使用が必要です.JSFはセッターとゲッターに頼っていました(しかし、我々は公共の場を使うことができませんでした).

    So, there is not a one-solution-fits-all.


    Javaについて。


    Javaランタイムエンジンは卑劣で、セッターとゲッターを理解します.結果コードを最適化するので、通常のセッターとゲッター(追加ロジックなし)を追加すると、JREはパブリックフィールドと同じように動作します.

    ファイナルワールド.


    しかし、私たちは公共の場でモデルクラスを使うことができますか?はい.Cはこのやり方で動作します(CはOOPではありません).
    struct account {
       int age;
       char *name;
       char *prefix;
    };
    
    私たちは通常、setterとgetterを自動的に生成します(リファクタリングやロンボブーを通じて)自動的に使用しますが、JITコンパイラはとにかく削除します.

    JITは自動的に生成されたほとんどのセッターとゲッターを削除し、自動的にahemので、なぜ追加されますか?

    人々は、我々が開発者であることを忘れています。



    例えば、私は自分自身を繰り返す
    object.getField().getOtherField().getOhNoesAnotherField().setFinalField("Some Name"); 
    
    (公用)
    object.field.otherField.ohNoesAnotherfield.finalField="Some Name"; 
    
    それは書くだけでなく、理解するのも短いです.

    As a note code like this one:


    object.getField().getOtherField().someMethod<Class,OtherClass>(arg,moreargs); // is cringe
    
    Cは、プロパティを作成することによってカプセル化に対するあらゆるプロカプセル化を満足させることによってそれを解決しました.Cでは、
    object.Field.OtherField.OhNoesAnotherField.FinalField="Some Name"; 
    
    Javaはそれを持っていません、そして、それは恥です.


    我々は顧客を表示したいと言うが、我々は新しい列(ID)を必要とする、それが自動的に生成する必要がありますし、ビュー/テンプレート層で生成することはできませんでした.
    ID
    年齢
    名称
    接頭辞
    1
    10
    ジョン
    博士
    2
    20
    アナナ
    ドクター.
    3
    30
    ポール
    ジュニア
    我々のモデルクラスを新しいセッターとゲッターで毒す必要はありません.
    public class CustomerUI extends Customer {
        private int id;
        public int getId() {
            id=id+1;
            return id;
        }
    }
    
    したがって、このクラスは視覚的な問題を解決するために特別に機能します.我々は、いくつかのロジックを保持しながら、顧客クラスのセッターとゲッターを削除することができます