Tôi thấy những lợi ích của việc làm cho các đối tượng trong chương trình của tôi trở nên bất biến. Khi tôi thực sự suy nghĩ sâu sắc về một thiết kế tốt cho ứng dụng của mình, tôi thường tự nhiên thấy nhiều đối tượng của mình là bất biến. Nó thường đến điểm mà tôi muốn có tất cả các đối tượng của mình bất biến.
Câu hỏi này liên quan đến cùng một ý tưởng nhưng không có câu trả lời nào cho thấy đâu là cách tiếp cận tốt đối với tính bất biến và khi nào thực sự sử dụng nó. Có một số mẫu thiết kế bất biến tốt? Ý tưởng chung dường như là "làm cho các đối tượng trở nên bất biến trừ khi bạn thực sự cần chúng để thay đổi", điều này là vô ích trong thực tế.
Kinh nghiệm của tôi là sự bất biến thúc đẩy mã của tôi ngày càng nhiều hơn đến mô hình chức năng và sự tiến triển này luôn xảy ra:
- Tôi bắt đầu cần các cấu trúc dữ liệu liên tục (theo nghĩa chức năng) như danh sách, bản đồ, v.v.
- Thật vô cùng bất tiện khi làm việc với các tham chiếu chéo (ví dụ: nút cây tham chiếu đến con của nó trong khi trẻ tham chiếu cha mẹ của chúng) khiến tôi không sử dụng tham chiếu chéo nào cả, điều này một lần nữa làm cho cấu trúc dữ liệu và mã của tôi có nhiều chức năng hơn.
- Kế thừa dừng lại để có ý nghĩa và tôi bắt đầu sử dụng thành phần thay thế.
- Toàn bộ ý tưởng cơ bản của OOP như đóng gói bắt đầu tan rã và các đối tượng của tôi bắt đầu trông giống như các hàm.
Tại thời điểm này, tôi thực tế không sử dụng gì từ mô hình OOP nữa và chỉ có thể chuyển sang ngôn ngữ chức năng thuần túy. Vì vậy, câu hỏi của tôi: có một cách tiếp cận nhất quán để thiết kế OOP bất biến tốt hay luôn luôn là khi bạn đưa ý tưởng bất biến đến tiềm năng tối đa của nó, bạn luôn kết thúc việc lập trình bằng ngôn ngữ chức năng không cần bất cứ điều gì từ thế giới OOP nữa? Có hướng dẫn tốt nào để quyết định lớp nào sẽ bất biến và lớp nào có thể thay đổi để đảm bảo rằng OOP không bị sụp đổ?
Để thuận tiện, tôi sẽ cung cấp một ví dụ. Chúng ta hãy có một ChessBoard
bộ sưu tập các quân cờ bất biến (mở rộng lớp trừu tượngPiece
). Từ quan điểm OOP, một mảnh có trách nhiệm tạo ra các bước di chuyển hợp lệ từ vị trí của nó trên bảng. Nhưng để tạo ra các bước di chuyển, mảnh cần có một tham chiếu đến bảng của nó trong khi bảng cần phải có tham chiếu đến các mảnh của nó. Vâng, có một số thủ thuật để tạo các tài liệu tham khảo chéo bất biến này tùy thuộc vào ngôn ngữ OOP của bạn nhưng chúng rất khó quản lý, tốt hơn là không có phần nào để tham khảo bảng của nó. Nhưng sau đó, mảnh không thể tạo ra di chuyển của nó vì nó không biết trạng thái của bảng. Sau đó, mảnh trở thành một cấu trúc dữ liệu giữ loại mảnh và vị trí của nó. Sau đó, bạn có thể sử dụng một hàm đa hình để tạo ra các bước di chuyển cho tất cả các loại mảnh. Điều này là hoàn toàn có thể đạt được trong lập trình chức năng nhưng hầu như không thể trong OOP nếu không kiểm tra loại thời gian chạy và các thực tiễn OOP xấu khác ... Sau đó,