Ну, в этом есть пара аспектов. Во-первых, изменяемые объекты без ссылочной идентичности могут вызывать ошибки в нечетное время. Например, рассмотрим компонент Person
с методом equals
на основе значений:
Map<Person, String> map = ...
Person p = new Person();
map.put(p, "Hey, there!");
p.setName("Daniel");
map.get(p); // => null
Экземпляр Person
теряется на карте при использовании в качестве ключа, потому что его hashCode
и равенство основаны на изменяемых значениях. Эти значения изменились за пределами карты, и все хеширование устарело. Теоретики любят говорить об этом, но на практике я не нашел, чтобы это было слишком большой проблемой.
Другим аспектом является логическая «разумность» вашего кода. Это сложный термин для определения, охватывающий все, от читаемости до потока. В общем, вы должны быть в состоянии посмотреть на кусок кода и легко понять, что он делает. Но что более важно, вы должны быть в состоянии убедить себя, что он делает то, что делает правильно . Когда объекты могут независимо изменяться в разных «доменах» кода, иногда становится трудно отслеживать, что и где («пугающее действие на расстоянии»). Это более сложная концепция, но она часто встречается в больших и более сложных архитектурах.
Наконец, изменяемые объекты убийцы в одновременных ситуациях. Всякий раз, когда вы обращаетесь к изменчивому объекту из отдельных потоков, вам приходится иметь дело с блокировкой. Это снижает пропускную способность и значительно усложняет поддержку вашего кода . Достаточно сложная система делает эту проблему настолько непропорциональной, что ее практически невозможно поддерживать (даже для экспертов по параллелизму).
Неизменяемые объекты (в частности, неизменяемые коллекции) позволяют избежать всех этих проблем. Как только вы разберетесь с тем, как они работают, ваш код превратится в нечто, что будет легче читать, легче поддерживать и с меньшей вероятностью не получится непредсказуемым и непредсказуемым образом. Неизменяемые объекты еще проще тестировать не только из-за их легкой насмешки, но и из-за шаблонов кода, которые они стремятся применять. Короче говоря, это хорошая практика повсюду!
С учетом вышесказанного, я вряд ли фанат в этом вопросе. Некоторые проблемы просто не моделируются, когда все неизменно. Но я думаю, что вам следует попытаться подтолкнуть как можно больше своего кода в этом направлении, если, конечно, вы используете язык, который делает это разумным мнением (C / C ++ делает это очень трудным, как и Java) , Короче говоря, преимущества в некоторой степени зависят от вашей проблемы, но я бы предпочел неизменность.