Mã như:
public Thing[] getThings(){
return things;
}
Không có ý nghĩa gì nhiều, vì phương thức truy cập của bạn không làm gì ngoài việc trả lại trực tiếp cấu trúc dữ liệu nội bộ. Bạn cũng có thể chỉ cần tuyên bố Thing[] things
là public
. Ý tưởng đằng sau một phương thức truy cập là tạo ra một giao diện cách ly khách hàng khỏi những thay đổi bên trong và ngăn không cho họ thao túng cấu trúc dữ liệu thực tế trừ những cách kín đáo như giao diện cho phép. Như bạn đã phát hiện ra khi tất cả mã khách hàng của bạn bị hỏng, phương thức truy cập của bạn đã không làm điều đó - đó chỉ là sự lãng phí mã. Tôi nghĩ rằng rất nhiều lập trình viên có xu hướng viết mã như vậy bởi vì họ đã học được ở đâu đó rằng mọi thứ cần phải được gói gọn với các phương thức truy cập - nhưng đó là lý do tôi giải thích. Làm điều đó chỉ để "làm theo mẫu" khi phương thức truy cập không phục vụ bất kỳ mục đích nào chỉ là tiếng ồn.
Tôi chắc chắn sẽ đề xuất giải pháp đề xuất của bạn, thực hiện một số mục tiêu quan trọng nhất của việc đóng gói: Cung cấp cho khách hàng một giao diện mạnh mẽ, kín đáo, cách ly họ khỏi các chi tiết triển khai bên trong của lớp của bạn và không cho phép họ chạm vào cấu trúc dữ liệu nội bộ mong đợi theo những cách mà bạn quyết định là phù hợp - "luật đặc quyền ít cần thiết nhất". Nếu bạn nhìn vào các khung OOP phổ biến lớn, chẳng hạn như CLR, STL, VCL, thì mẫu mà bạn đề xuất là phổ biến, vì chính xác lý do đó.
Bạn có nên luôn luôn làm điều đó? Không cần thiết. Ví dụ: nếu bạn có các lớp người trợ giúp hoặc bạn bè về cơ bản là một thành phần của lớp nhân viên chính của bạn và không phải là "mặt trước", thì không cần thiết - đó là một sự quá mức cần thiết để thêm nhiều mã không cần thiết. Và trong trường hợp đó, tôi sẽ không sử dụng một phương thức truy cập nào cả - nó vô nghĩa, như đã giải thích. Chỉ cần khai báo cấu trúc dữ liệu theo cách chỉ nằm trong lớp chính sử dụng nó - hầu hết các ngôn ngữ đều hỗ trợ các cách thực hiện điều đó - friend
hoặc khai báo nó trong cùng một tệp với lớp worker chính, v.v.
Nhược điểm duy nhất tôi có thể thấy trong đề xuất của bạn đó là viết mã nhiều công việc hơn (và bây giờ bạn sẽ phải mã hóa lại các lớp tiêu dùng của mình - nhưng dù sao bạn cũng phải / phải làm điều đó.) Nhưng đó không thực sự là nhược điểm - bạn cần phải làm điều đó đúng, và đôi khi điều đó đòi hỏi nhiều công việc hơn.
Một trong những điều làm cho một lập trình viên giỏi trở nên tốt là họ biết khi nào công việc làm thêm có giá trị và khi nào thì không. Về lâu dài, việc đưa thêm vào bây giờ sẽ trả hết với cổ tức lớn trong tương lai - nếu không phải trong dự án này, sau đó cho những người khác. Học cách viết mã đúng cách và sử dụng đầu của bạn về nó, không chỉ là robot tuân theo các hình thức quy định.
Lưu ý rằng các bộ sưu tập phức tạp hơn các mảng có thể yêu cầu lớp kèm theo thực hiện thậm chí nhiều hơn ba phương thức chỉ để truy cập cấu trúc dữ liệu nội bộ.
Nếu bạn đang hiển thị toàn bộ cấu trúc dữ liệu thông qua một lớp chứa, IMO bạn cần suy nghĩ về lý do tại sao lớp đó được gói gọn, nếu không chỉ đơn giản là cung cấp một giao diện an toàn hơn - một "lớp bao bọc". Bạn đang nói rằng lớp chứa không tồn tại cho mục đích đó - vì vậy có lẽ có điều gì đó không đúng về thiết kế của bạn. Xem xét chia các lớp học của bạn thành các mô-đun kín đáo hơn và xếp lớp chúng.
Một lớp nên có một mục đích rõ ràng và kín đáo, và cung cấp một giao diện để hỗ trợ chức năng đó - không còn nữa. Bạn có thể đang cố gắng kết hợp những thứ không thuộc về nhau. Khi bạn làm điều đó, mọi thứ sẽ bị phá vỡ mỗi khi bạn phải thực hiện một thay đổi. Các lớp học của bạn càng nhỏ và càng kín đáo thì càng dễ thay đổi mọi thứ xung quanh: Hãy nghĩ về LEGO.
get(index)
,add()
,size()
,remove(index)
, vàremove(Object)
. Sử dụng kỹ thuật được đề xuất, lớp chứa ArrayList này phải có năm phương thức công khai chỉ để ủy quyền cho bộ sưu tập bên trong. Và mục đích của lớp này trong chương trình rất có thể không gói gọn ArrayList này, mà là làm một cái gì đó khác. ArrayList chỉ là một chi tiết. [...]