Ленивые методы сущностей и закон Диметры

У меня есть сущность:

@Entity
@Table(name = "CARDS")
public class Card {

  @ManyToOne
  @JoinColumn(name = "PERSON_ID", referencedColumnName = "ID", nullable = false)
  private Person person;

  @OneToMany(mappedBy = "card")
  private List<CardStatus> cardStatuses;

И я свою службу могу назвать следующим кодом:

public Card getCardBlaBlaBla(Long id){

   Card card  = cardRepository.findaCard(id);

   Something something = card.getCardStatuses().get(0).getSomething();
}

card.getCardStatuses().get(0).getSomething()getCardStatuses равно LAZY

Мои вопросы - Нарушает ли этот вызов закон Диметры?

Закон Деметры Существует хорошо известная эвристика под названием Закон Деметры2, согласно которой модуль не должен знать о внутренностях объектов, которыми он манипулирует. Как мы видели в предыдущем разделе, объекты скрывают свои данные и раскрывают операции. Это означает, что объект не должен раскрывать свою внутреннюю структуру через средства доступа, потому что это означает раскрытие, а не сокрытие своей внутренней структуры. Точнее, Закон Деметры говорит, что метод f класса C должен вызывать только методы этих:

• C
• An object created by f
• An object passed as an argument to f
• An object held in an instance variable of C

Метод не должен вызывать методы для объектов, возвращаемых любой из разрешенных функций. Другими словами, разговаривайте с друзьями, а не с незнакомцами. Следующий код нарушает закон Деметры (среди прочего), потому что он вызывает функцию getScratchDir() для возвращаемого значения getOptions(), а затем вызывает getAbsolutePath() для возвращаемого значения getScratchDir(). final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();

Card - это структуры данных и не нарушает закон Диметры, но LAZY метод имеет логику (сделать выбор в БД).

Нарушает ли этот вызов закон Диметры или нет? Если да, то как я могу использовать его правильно?

У меня действительно много кода, например:

entityOblect.getChield().getChield().getSomething();

ИЗМЕНИТЬ

Из книги Cleand Code:

введите здесь описание изображения

ИЗМЕНИТЬ2

(c) Роберт С. Мартин - Чистый код

Active Record Active Records — это специальные формы DTO. Это структуры данных с общедоступными переменными (или с доступом к компонентам); но у них обычно есть методы навигации, такие как сохранение и поиск. Обычно эти активные записи являются прямыми переводами из таблиц базы данных или других источников данных. К сожалению, мы часто обнаруживаем, что разработчики пытаются обращаться с этими структурами данных как с объектами, помещая в них методы бизнес-правил. Это неудобно, поскольку создает гибрид между структурой данных и объектом. Решение, конечно, состоит в том, чтобы рассматривать Active Record как структуру данных и создавать отдельные объекты, содержащие бизнес-правила и скрывающие свои внутренние данные (которые, вероятно, являются просто экземплярами Active Record).


person ip696    schedule 20.07.2018    source источник


Ответы (1)


Это нарушает закон Деметры:

Something something = card.getCardStatuses().get(0).getSomething();

В одном операторе вы перемещаетесь по всем этим объектам:
Card -> List<CardStatus> -> CardStatus -> Something.

В идеале вы должны иметь это сообщение со стороны клиента:
Card -> Something.

А в классе Card возврат Something может быть реализован с помощью метода, выполняющего эту навигацию:
List<CardStatus> -> CardStatus -> Something.

В некотором роде последнее также нарушает закон Деметры, но на уровне, который мы могли бы считать приемлемым, потому что мы не должны рассматривать это отношение List<CardStatus> -> CardStatus как чужое отношение.

Это может дать:

Something something = card.getSomethingOfCardStatuses(0);

или чтобы избежать префикса get :

Something something = card.findSomethingOfCardStatuses(0);

И findSomethingOfCardStatuses() может быть определено в Card как:

public Something findSomethingOfCardStatuses(int statusNumber){
    // add some check for the index if required 
    // you could return Optional or an Exception according to your requirements
    return cardStatuses.get(0).getSomething();
}

Я знаю, что многие разработчики любят вручную копаться в полях сущностей, но лично я избегаю этого и стараюсь дать им несколько логических методов со значимыми именами и поведением. Это делает ядро ​​​​действительно яснее.

person davidxxx    schedule 20.07.2018
comment
то то, что вы сказали, это первое, о чем я подумал. Я абсолютно согласен. Но. Карта является сущностью. Создайте дополнительные методы в классе сущностей — правильно ли это? Я считаю, что сущность должна быть отражением таблицы и не более того. Нет? - person ip696; 20.07.2018
comment
Обычно у вас есть два пути: тупая модель данных или умная модель данных. Я всегда предпочитаю второе. Сущность может быть как представлением в ООП реляционной таблицы, так и классом, определяющим некоторую логику. Почему вы хотите сделать эти два аспекта исключительными между собой? - person davidxxx; 20.07.2018
comment
Я редактирую вопрос. добавить фрагмент из книги - person ip696; 20.07.2018
comment
Я думаю, что сущность - это структура данных и она не может иметь дополнительных методов и поведения. Если я добавлю какой-то метод к объекту - он будет гибридным (структура данных и объект с поведением). Я думаю, что сущность должна быть простой. - person ip696; 20.07.2018
comment
В примере автор приводит плохой вариант использования, когда он ссылается на умножение методов в объекте предметной области. Это не ваш случай. Я думаю, что часть гибридной структуры действительно не ясна в отношении ее границ и рисков. Например: добавление некоторых вспомогательных методов в структуру данных не означает добавление основной логики и не должно создавать никаких проблем в дизайне. Определенно, я предпочитаю объяснения Мартина Фаулера, которые предельно ясно рассказывают о структуре модели предметной области. Здесь вы создадите анемичную модель предметной области. : martinfowler.com/bliki/AnemicDomainModel.html - person davidxxx; 20.07.2018
comment
Я снова редактирую вопрос). Спасибо за ответ и ссылку. Я уважаю Роберта С. Мартина и Мартина Фаулера. Но мне кажется в этом вопросе они не согласны? или мой английский не позволяет мне все уловить? - person ip696; 20.07.2018
comment
Ах, да. например, я получаю классы Java (JAXB), которые были сгенерированы из XSD или WSDl - я не могу добавить некоторые методы для этого класса. Но эти классы иногда имеют сложную структуру с большой вложенностью. - person ip696; 20.07.2018
comment
Я знаю Robert C. Martin, но не в деталях, что он написал. Я пытался читать чистую кодовую книгу. Так что да, большинство вещей, которые он сказал, верны, но они составляют часть хороших практик, известных большинству хороших и опытных разработчиков. Поэтому я быстро остановил книгу. Поэтому я не могу сказать, верна ли ваша интерпретация разногласий авторов. Наконец, вопрос кажется слишком широким. - person davidxxx; 20.07.2018