Развивает ли класс с течением времени проблему равных реализаций? - PullRequest
3 голосов
/ 03 октября 2019

Если у нас есть класс, который при создании имел реализацию equals и hashCode.
Позже класс был дополнен новыми полями, и когда это произойдет, скорее всего, equals/hashCode также следует обновить.
Мой вопрос - это анти-паттерн? Могут ли быть некоторые проблемы, например, если класс находится в некоторой библиотеке, и есть некоторый код, который рассматривает старый контракт, например?

Ответы [ 3 ]

0 голосов
/ 03 октября 2019

Их нужно обновить, если контракт на равенство классов меняется, да. Допустим, вы добавляете middleName к классу User и хотите, чтобы равенство основывалось на имени, отчестве и фамилии, а не только на имени и фамилии. Однако добавление полей, не влияющих на равенство, не потребует изменений.

Единственный задействованный код - это код в equals() и hashcode(), поэтому, если вы не написали какой-то плохой код (например, не используетеequals, но сравнивая поля вручную), любой существующий код работает прозрачно.

0 голосов
/ 08 октября 2019

Да, это проблема при изменении любой реализации.

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

Однако, если обновление реализации действительно изменяет контракт, у вас не все в порядке.


Если ваш контракт на равенство в настоящее время:

"Два объекта равны, если они имеют одно и то же имя"

Два объектадолжно всегда быть равным, если они имеют одинаковые имена, поскольку разработчики будут разрабатывать на основе этого.

Если вы введете новое поле, например id, и обновите контракт, включив в негоэто поле:

"Два объекта равны, если они имеют одно и то же имя и идентификатор"

Системы, которые ожидали равенства по имени, теперь будут ломаться, если два объекта совместно используют одно и то жеимя, но имеют разные идентификаторы.

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


Если в вашем контракте указано:

«Два объекта равны, если все их свойства равны» *

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

0 голосов
/ 03 октября 2019

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

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

Однакокогда класс обновляется и используется сторонним кодом, который не может быть протестирован (например, класс является частью проекта maven, опубликованного в репозитории maven), сторонний код должен использовать версию класса / проекта для обеспечения совместимости. Лично я видел много случаев, когда проект maven обновляется, и новая версия содержит точно такую ​​же сигнатуру класса / метода с совершенно другой реализацией, которая нарушает код.

...