Как устранить жесткие зависимости от Java Beans - PullRequest
0 голосов
/ 06 марта 2019

У меня есть вопрос по поводу принципа DIP. В одном из руководств говорится, что мы не должны хранить ссылки на конкретный класс (если он изменится, мне придется изменить всех клиентов, которые его используют). Итак, что я могу следовать этому руководству, когда я использую POJO? Например:

У меня есть Bean-компонент Foo с некоторыми атрибутами (он может представлять объект Domain)

class Foo {  
   private String one;   
   private String two;

  //getters and setters
}

Несколько клиентов создают экземпляр этого объекта, например, чтобы сохранить его в базе данных

   class Client1 {   

      private FooDao dao;

      Client1(FooDao dao){     
         this.dao = dao;
      }  

      public void persist() {    
         //hard coding
         Foo foo = new Foo();   
         foo.setOne("something...");    
         dao.save(foo); }     
       } 

       class Client2 {   

         private FooDao dao;

          Client2(FooDao dao){   
            this.dao = dao;

           }  

        public void persist() {   
           Foo foo = new Foo();   
           foo.setOne("something...");   
           foo.setTwo("something...")    
           dao.save(foo); 
         }
       }

Если я добавлю или изменим какой-либо атрибут на класс 'Foo', каждый клиент должен будет измениться, поэтому следуйте этому руководству, как мне этого избежать?

Спасибо!

Ответы [ 3 ]

1 голос
/ 06 марта 2019

Я думаю, вы воспринимаете это немного слишком буквально.

Я имел удовольствие присутствовать на выступлении Венката Субраманиама, в котором говорилось о DIP.

Вы правы, когда говорите, что должны полагаться на абстракции, а не на конкременты, но в моих записях из этого выступления у меня есть сноска «возьми это с крошкой соли».

В вашемВ этом случае вам захочется принять это с недолгой солью, поскольку здесь достаточно сильный запах кода - вы открываете использование этого компонента всем потребителям, которые в нем нуждаются, что неявно создает зависимость от него.Это нарушает принцип одиночной ответственности , поскольку этот компонент используется в большем количестве мест, чем , вероятно, .

Поскольку кажется, что вы говорите о базе данныхабстракция, возможно, вы захотите заглянуть в DTO , который будет открыт между сервисами для передачи информации между ними, и позволит вашему бину обрабатывать внутренности.

К вашей точке ...

если он изменит [s], тогда мне придется изменить все клиенты, которые его используют

... это верно, если вы удалите функциональность.Если вы добавите новую функциональность, вы можете позволить своим нижестоящим клиентам просто игнорировать эту функциональность.Если вы хотите изменить существующую функциональность , вы должны разрешить клиентам путь к миграции.

1 голос
/ 06 марта 2019

Комментарий от @chrylis точный.Роберт Мартин рассматривает это в главе 6 «Чистый код: объекты и структуры данных».

Объекты скрывают свои данные за абстракциями и предоставляют функции, которые работают с этими данными.Структуры данных предоставляют свои данные и не имеют значимых функций.(стр. 95)

Определение ООП, где все является объектом, а структур данных нет, наивно.

Зрелые программисты знают, что идея о том, что всеэто объект это миф .Иногда вы действительно хотите хотите простые структуры данных с процедурами, работающими на них.(стр. 97)

А как насчет классов, которые предоставляют данные и поведение?

Путаница иногда приводит к неудачным гибридным структурам, которые являются наполовину объектами и наполовину структурами данных.У них есть функции, которые делают важные вещи, и у них также есть либо открытые переменные, либо открытые методы доступа и мутаторы, которые для всех намерений и целей делают закрытые переменные общедоступными, побуждая другие внешние функции использовать эти переменные так, как процедурная программа будет использоватьструктура данных.Такие гибриды затрудняют добавление новых функций, но также затрудняют добавление новых структур данных.Они худшие из обоих миров.Избегайте их создания.(стр. 99)

К первоначальному вопросу: принцип обращения зависимостей применяется к объектам, а не к структурам данных, таким как Java Beans.

0 голосов
/ 06 марта 2019

Вам необходимо определить функциональность метода, который вы хотели бы добавить.

interface Functionality {
public void persist();
}

Каждый класс, кроме менеджера, должен реализовать интерфейс:

 class Client1 implements Functionality{   
  //Your code..
}

Добавить максимумкласс уровня классы высокого уровня, которые не работают напрямую с классами низкого уровня:

Class ManageClients{
    Functionality func;

    public void setClient(Functionality f) {
        func= f;
    }


    public void manage() {
        func.persist();
    }
};
  • Класс ManageClients не требует изменений при добавлении клиентов.

  • Минимизированный риск повлиять на старую функциональность, присутствующую в классе ManageClients, поскольку мы не меняем ее.

  • Нет необходимости повторять модульное тестирование для класса ManageClients.

...