Этот код нарушает принцип открытого-закрытого? - PullRequest
0 голосов
/ 15 февраля 2019

Я хочу знать, нарушает ли приведенный ниже код принцип открытого и закрытого доступа.

Animal является родительским классом Dog, однако Animal имеет аннотации Джексона, которые помогают ObjectMapper (де) сериализовать классы.Любой, кто расширяет Animal, должен будет редактировать только аннотации, присутствующие в Animal, чтобы убедиться, что (де) сериализация работает как задумано, оставляя класс нетронутым.

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME, 
  include = JsonTypeInfo.As.PROPERTY, 
  property = "type")
@JsonSubTypes({ 
  // all subclasses
  @Type(value = Dog.class, name = "dog")
})
public abstract class Animal {
    // fields, constructors, getters and setters
}

public class Dog extends Animal {

}

Ответы [ 3 ]

0 голосов
/ 15 февраля 2019

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

0 голосов
/ 15 февраля 2019

Открыть / закрыть означает, что класс должен быть открыт для расширения, но закрыт для модификации.

Другими словами ... если вы хотите изменить поведение класса, вы должны каким-то образом расширить его,но вы не должны изменять его.

Вы можете расширить класс с помощью

  • , создав подкласс.Обычно это делается с использованием, например, шаблона метода шаблона.
  • , определяющего интерфейс, который использует класс A, чтобы его поведение можно было расширить путем передачи ему другого экземпляра этого интерфейса, например шаблона стратегии.Хороший пример из реальной жизни - TreeSet(Comparator<? super E> comparator), поскольку его поведение сортировки можно изменить без изменения самого TreeSet.

С моей точки зрения, аннотация @JsonSubTypesне является частью поведения класса Animal.Это меняет поведение другого класса - объекта сопоставления.Таким образом, это не совсем нарушение.На самом деле это не означает, что даже если вы не измените поведение, вы должны прикоснуться к классу Animal и перекомпилировать его.

Это действительно странный дизайн аннотации.Почему разработчики json не позволили вам поместить аннотацию на подкласс, например, как это делает JPA, когда дело доходит до отображения иерархии.См. DiscriminatorValue

Странный дизайн, когда супертип ссылается на подтипы.Абстрактные типы не должны зависеть от конкретных.По моему мнению, это принцип, который всегда должен применяться.

0 голосов
/ 15 февраля 2019

Теоретическая точка зрения

Принцип открытия / закрытия как у целого ТВЕРДЫЙ равен Utopia.Мы должны постоянно обновлять наш код в этом направлении, но, вероятно, мы никогда не окажемся там, потому что это невозможно.Давайте прочитаем статьи ниже, чтобы увидеть, как классические конструкции getters и annotation могут быть дискуссионными.

  1. Принтеры вместо получателей
  2. Java-аннотацииБольшая ошибка

Практическая точка зрения

Как и любой практический программист, мне нравится использовать хорошие инструменты для решения проблем вместо того, чтобы самому реализовывать что-то новое.Когда меня просят сериализовать данную модель в JSON файлах, я проверяю, является ли она:

  1. с открытым исходным кодом
  2. Fast
  3. В процессе активной разработки
  4. Легко использовать

Когда мы говорим о Jackson и его аннотациях, я думаю, мы можем найти золотую середину между теорией и практикой.И это благодаря функции MixIn.Вы можете отделить модель от способа сериализации до JSON.Конечно, когда вы добавляете новый класс, который расширяет базовый класс, вам нужно заменить MixIn interface аннотациями, но это цена, которую мы должны заплатить.

Изменить или Почему я забыл ответить на вопрос?

Извините, я забыл ответить на вопрос, нарушает ли приведенный выше пример Open/Closed principle или нет.Во-первых, получите определение из Wikipedia article :

Класс закрыт, так как он может быть скомпилирован, сохранен в библиотеке, базовым и использован клиентскими классами.Но он также открыт, поскольку любой новый класс может использовать его как родительский, добавляя новые функции.Когда класс-потомок определен, нет необходимости менять оригинал или беспокоить его клиентов.

Приведенный выше пример нарушает When a descendant class is defined, there is no need to change the original часть.Даже если мы используем MixIn, необходимо изменить другую часть приложения.Более того, если ваше решение использует annotations в 99,99% случаев, вы нарушаете эту часть, поскольку необходимо каким-то образом настроить функциональность, которая скрыта за ними.

...