2010-05-29 31 views
7

Tôi đang làm việc chăm chỉ trong việc đóng gói API để sử dụng công cộng. Vì vậy, tôi đang cố gắng giới hạn các phương pháp chỉ tiếp xúc với những phương pháp mà tôi muốn công khai và hỗ trợ. Bên dưới này tất nhiên có vô số các phương thức truy cập giới hạn.Các lớp API nội bộ của tôi có nên là tất cả trong một gói không?

Sự cố là tôi có rất nhiều mã nội bộ cần truy cập các phương thức bị hạn chế này mà không cần đặt các phương thức đó thành công khai. Điều này tạo ra hai vấn đề:

  • tôi không thể tạo giao diện cho giao tiếp giữa các lớp như này sẽ làm cho những phương pháp nội bộ của tôi công cộng.
  • Tôi không thể truy cập các phương pháp được bảo vệ hoặc mặc định trừ khi tôi đặt đa số các lớp nội bộ của mình trong cùng một gói .

Vì vậy, tôi có khoảng 70 hoặc 80 lớp nội bộ trong các gói được tách biệt rõ ràng NHƯNG với các công cụ sửa đổi truy cập quá mức cho phép. Bạn có nói rằng một gói duy nhất là ít hơn của hai tệ nạn hoặc là có một cách tốt hơn để có thể che giấu các phương pháp nội bộ của tôi trong khi vẫn giữ các gói chi tiết hơn?

Tôi muốn tìm hiểu cách thực hành tốt nhất tại đây.

Tôi đã nhận thức được This

+0

Tôi nghĩ câu hỏi là chủ quan một chút: cá nhân tôi, không thích các quyết định thiết kế dẫn đến tổ chức nội bộ nghèo nàn, như trường hợp tất cả các gói-trong-một-gói của bạn. Nhưng cách đúng đắn để làm những điều như vậy không xuất hiện trong tâm trí ngay bây giờ. – incarnate

Trả lời

7

Có hai giải pháp cho câu hỏi của bạn không liên quan đến việc giữ tất cả các lớp học trong cùng một gói.

Cách đầu tiên là sử dụng mẫu Friend Accessor/Friend Package được mô tả trong (Thiết kế API thực tế, Tulach 2008).

Cách thứ hai là sử dụng OSGi. Có một bài báo here giải thích cách OSGi thực hiện điều này.

Câu hỏi liên quan: 1, 2, 34.

+0

Đây là một câu trả lời tuyệt vời và liên kết đến gói bạn bè chỉ là giải pháp mà tôi đang tìm kiếm. – Chris

+0

Tôi rất vui vì tôi có thể giúp đỡ. Tôi cũng cần một giải pháp cho giới hạn dường như nghiêm trọng này của Java. Mẫu này phải là một ứng cử viên lý tưởng để mở rộng Java bằng cách sử dụng Jetbrains MPS hoặc công cụ phát triển theo mô hình khác. –

+0

Vâng, bạn vẫn phải làm cho công cụ truy cập trừu tượng nội bộ công khai (do đó là một phần của API). Tệ hơn, một người dùng xấu có thể cung cấp AccessorImpl của riêng mình, do đó buộc gói nội bộ của bạn sử dụng API của riêng mình thay thế. Điều này sẽ làm việc cho đến khi lớp Item được khởi tạo và kích hoạt IllegalStateException. – charlie

2

Một ví dụ có thể là Servlet API như bạn thấy họ đã tách ra API servlet chung và http thành hai gói.

Nếu bạn tách mã của mình trong một số api.jarimplementation.jar bạn có thể sử dụng giao diện để triển khai mà không hiển thị với người dùng api.jar. Nếu các đối tượng của các lớp không phụ thuộc vào gói của chúng, phải cộng tác theo bất kỳ cách nào, các phương thức của khóa học phải được hiển thị (ít nhất là trong quá trình thực hiện).

+0

+1 Cảm ơn thông tin. Tôi biết rằng tôi có thể gói các vấn đề đi nhưng thực sự tôi muốn hạn chế người dùng có cả api và các lọ thực hiện từ việc có thể truy cập các phương thức thực hiện không giao diện theo cách không dự định. – Chris

1

vâng, bạn không thể bảo vệ nội dung triển khai nội bộ khỏi quyền truy cập. Có một số công nghệ (như OSGi), cung cấp giải pháp cho rằng trong thời gian chạy/khởi động ứng dụng. Đây là một lỗ hổng mô-đun hóa thiết kế ngôn ngữ java (nhưng cũng rất khó để thêm vào sau đó do tính tương thích thấp).

Tôi thích quy ước để thêm các hiện vật có thể nhìn thấy công khai vào gói /api và nội bộ tới /nội bộ. Cuối cùng bạn kết thúc với.

 

# this package is allowed to be accessed by api-users 
com.foo.users.api 
# this is completely internal logic (api implementation) 
# should only be touched by the api-module itself. 
com.foo.users.internal 
 

Bằng cách này, bạn có thể tách biệt và cũng có thể chạy mã phân tích mã tĩnh.

Giống như với servlet-api đã đề cập ở trên, bạn thậm chí có thể chia nhỏ hơn nữa api so với impl cho các lọ khác nhau. Nhưng điều này liên quan đến nỗ lực nhiều hơn để xây dựng vòng đời và duy trì các mô-đun, vì vậy tôi sẽ chỉ làm điều đó ở nơi một phân chia thời gian chạy hoàn chỉnh có ý nghĩa (như trong jsr-spec so với impl).

Các vấn đề liên quan