Я бачу переваги того, щоб зробити об’єкти в своїй програмі незмінними. Коли я по-справжньому глибоко замислююся над гарним дизайном для свого застосування, я часто природно діходжу до багатьох моїх об'єктів, непорушних. Часто доходить до того, що я хотів би, щоб усі мої об’єкти були незмінні.
Це питання стосується тієї ж ідеї, але жодна відповідь не підказує, що є хорошим підходом до незмінності та коли насправді використовувати його. Чи є якісь непогані моделі дизайну? Загальна ідея, здається, "зробить об'єкти непорушними, якщо ви абсолютно не потребуєте їх змін", що марно на практиці.
Мій досвід полягає в тому, що незмінність все більше і більше приводить мій код до функціональної парадигми, і це прогресування завжди відбувається:
- Мені потрібні стійкі (у функціональному сенсі) структури даних, такі як списки, карти тощо.
- Вкрай незручно працювати з перехресними посиланнями (наприклад, вузол дерева, на який посилаються його діти, тоді як діти посилаються на батьків), що змушує мене взагалі не використовувати перехресні посилання, що знову робить мої структури даних та код більш функціональними.
- Спадщина перестає мати сенс, і я замість цього починаю використовувати композицію.
- Цілі основні ідеї OOP, як інкапсуляція, починають розпадатися, і мої об'єкти починають виглядати як функції.
На даний момент я практично нічого не використовую з парадигми OOP і можу просто перейти на суто функціональну мову. Отже, моє запитання: чи існує послідовний підхід до гарного непорушного дизайну OOP чи завжди так, коли ви переймаєте непорушну ідею до її найповнішого потенціалу, ви завжди закінчуєте програмування на функціональній мові, нічого більше не потребуючи у світі OOP? Чи є якісь вказівки щодо вирішення, які класи повинні бути незмінні, а які слід залишати незмінними, щоб OOP не розпадався?
Просто для зручності я наведу приклад. Будемо мати ChessBoard
як незмінну колекцію незмінних шахових фігур (розширюється абстрактний класPiece
). З точки зору ООП, фрагмент відповідає за генерування дійсних рухів зі свого положення на дошці. Але для генерування рухів шматок потребує посилання на свою дошку, тоді як дошка повинна мати посилання на свої шматки. Ну, є кілька хитрощів, щоб створити ці незмінні перехресні посилання залежно від вашої мови ООП, але вони керуються болем, краще не мати деталі для посилання на її дошку. Але тоді шматок не може генерувати свої рухи, оскільки він не знає стан дошки. Потім фрагмент стає просто структурою даних, що утримує тип фрагмента та його положення. Потім можна використовувати поліморфну функцію для генерування рухів для всіх видів творів. Це цілком досяжно у функціональному програмуванні, але майже неможливо в OOP без перевірки типу виконання та інших поганих практик OOP ... Потім,