Я вижу преимущества создания неизменных объектов в моей программе. Когда я действительно глубоко задумываюсь над хорошим дизайном для своего приложения, я часто, естественно, считаю, что многие из моих объектов неизменяемы. Часто приходит момент, когда я хочу, чтобы все мои объекты были неизменными.
Этот вопрос касается той же идеи, но ни один ответ не говорит о том, что является хорошим подходом к неизменности и когда на самом деле его использовать. Есть ли хорошие шаблоны дизайна? Общая идея, по-видимому, заключается в том, чтобы «сделать объекты неизменяемыми, если вам абсолютно не нужно их менять», что на практике бесполезно.
Мой опыт показывает, что неизменность все больше и больше приводит мой код к функциональной парадигме, и такое развитие всегда происходит:
- Я начинаю нуждаться в постоянных (в функциональном смысле) структурах данных, таких как списки, карты и т. Д.
- Работать с перекрестными ссылками крайне неудобно (например, узел дерева ссылается на своих потомков, а дети ссылаются на своих родителей), что вообще не позволяет использовать перекрестные ссылки, что снова делает мои структуры данных и код более функциональными.
- Наследование перестает иметь смысл, и вместо этого я начинаю использовать композицию.
- Все основные идеи ООП, такие как инкапсуляция, начинают разрушаться, и мои объекты начинают выглядеть как функции.
На данный момент я практически ничего не использую из парадигмы ООП и могу просто переключиться на чисто функциональный язык. Таким образом, мой вопрос: существует ли последовательный подход к хорошему неизменяемому дизайну ООП или всегда так, что, когда вы берете неизменную идею в полную силу, вы всегда заканчиваете программированием на функциональном языке, больше не нуждающемся в мире ООП? Существуют ли хорошие рекомендации для определения того, какие классы должны быть неизменяемыми, а какие должны быть изменяемыми, чтобы ООП не развалилось?
Просто для удобства приведу пример. Давайте иметь ChessBoard
как неизменную коллекцию неизменных шахматных фигур (расширение абстрактного классаPiece
). С точки зрения ООП фигура отвечает за генерацию действительных ходов из своей позиции на доске. Но чтобы генерировать ходы, фигура должна иметь ссылку на свою доску, а доска должна иметь ссылку на свои фигуры. Ну, есть несколько хитростей для создания этих неизменяемых перекрестных ссылок в зависимости от вашего языка ООП, но ими сложно управлять, лучше не иметь части, чтобы ссылаться на свою доску. Но тогда фигура не может генерировать свои ходы, поскольку она не знает состояния доски. Тогда кусок становится просто структурой данных, содержащей тип куска и его положение. Затем вы можете использовать полиморфную функцию для генерации ходов для всех видов фигур. Это вполне достижимо в функциональном программировании, но почти невозможно в ООП без проверок типов во время выполнения и других плохих практик ООП ... Тогда