Làm cách nào để đóng gói các lớp bên trong trong một API được viết bằng Java?


9

Chúng tôi phải viết một thư viện. Đương nhiên, nó chỉ nên có một API rất nhỏ (càng rộng càng cần càng nhỏ càng tốt). Nội bộ của thư viện có phần phức tạp. Do đó, họ cần cấu trúc.

Đối với cấu trúc hiện tại tôi thấy hai cách:

1. sử dụng các gói.

ưu: thư viện có thể được cấu trúc gọn gàng. Tất cả mọi thứ ở vị trí của nó.

Nhược điểm: việc sử dụng các lớp thông qua biên giới gói cần các lớp công khai và do đó mở rộng API của toàn bộ thư viện.

2. sử dụng các lớp bên trong tĩnh, tất cả trong một gói.

ưu điểm: chỉ rất ít những thứ công cộng (lớp học, phương pháp, v.v.) cần thiết.

Nhược điểm: Các lớp chỉ được ẩn để cấu trúc chúng. Đây sẽ là một trong số rất ít các trường hợp sử dụng có rất nhiều lớp bên trong tĩnh được sử dụng. Các nhà phát triển không quen với điều đó và có thể bỏ qua chúng.


Có cách nào tốt hơn để đạt được một API nhỏ trong thư viện có cấu trúc tốt không?

Chỉnh sửa: Tôi quên đề cập: đó là cho một thư viện Android. Do đó, không có java9.


Tại sao các lớp bên trong của bạn cần phải tĩnh?
David Arno

Không các lớp bên trong làm cho các đơn vị mã lớn hơn? Tôi có nghĩa là một lớp với một số lớp bên trong có thể trở nên rất dài.
Tulains Córdova

2
@ TulainsCórdova, điểm tốt, tôi đọc thuật ngữ "bên trong" là "nội bộ", mà tôi nghĩ Java gọi là "gói riêng tư". Cách thông thường để tạo một lib chắc chắn là có một gói, chứa một vài lớp công khai, với mọi thứ khác là nội bộ / gói riêng tư.
David Arno

Xin chào @frmarkus. Tôi đã cố gắng viết lại tiêu đề câu hỏi của bạn để cụ thể hơn và tránh "không rõ những gì bạn đang hỏi" phiếu bầu gần. Vui lòng chỉnh sửa lại nếu bạn nghĩ rằng nó diễn đạt sai câu hỏi thực tế của bạn.
Andres F.

1
@ TulainsCórdova: Có, các đơn vị mã có được đường lớn (3k dòng mã cho mỗi tệp). Đó là một vấn đề quan trọng khác của cách cấu trúc này.
Markus Frauenfelder

Câu trả lời:


1

Tôi thấy những gì bạn đang làm với 2. Bạn đang sử dụng các lớp làm gói và gói dưới dạng mô-đun để bạn có thể tự cô lập trong gói nhưng vẫn tổ chức trong gói bằng cách sử dụng các lớp.

Điều đó rất thông minh. Coi chừng khéo léo.

Điều này sẽ buộc bạn kẹt nhiều lớp trong cùng một tệp nguồn (mà bạn có thể thích) và đường dẫn sẽ có thêm một từ viết hoa.

Điều này cũng sẽ buộc bạn phải viết bất kỳ mã kiểm tra nào trong gói trừ khi bạn sử dụng sự phản chiếu để hack theo cách của bạn từ bên ngoài.

Khác sau đó, điều này sẽ làm việc. Nó sẽ chỉ có vẻ kỳ lạ.

Mọi người đã quen với các lớp bên trong đang được sử dụng như Entryset trong Hashtable. Nó là riêng tư vì vậy tôi không thể tạo ra nó nhưng nó thực hiện một giao diện công cộng vì vậy tôi chỉ nói chuyện với nó thông qua giao diện và có một cái gì đó lấy cho tôi.

Nhưng bạn đang mô tả các lớp bạn không muốn tôi nói chuyện thậm chí thông qua một giao diện. Vì vậy, không có giao diện cho tôi. Điều này có nghĩa là tôi không có gì để xem và bị nhầm lẫn (trừ khi bạn cung cấp cho tôi nguồn).

Vấn đề lớn nhất tôi thấy trước là những người mới khó hiểu này đang duy trì API. Bạn có thể ném tài liệu và nhận xét về họ nhưng không được siêu lớn khi họ không đọc hoặc tin tưởng một trong hai.

Bạn đã tạo ra một mô hình khác bù cho sự thiếu hụt trong ngôn ngữ. Java không có công cụ sửa đổi truy cập cấp quyền truy cập vào một nhóm các gói. Tôi đã nghe nói rằng một sửa đổi truy cập "mô-đun" đã được đề xuất nhưng không thấy dấu hiệu của nó xảy ra.

Công cụ sửa đổi truy cập mặc định (không có công cụ sửa đổi) có thể là những gì bạn sẽ sử dụng ở đây trừ khi bạn không bận tâm đến việc tôi lén lút thông qua thừa kế, trong trường hợp này được bảo vệ.

Modifier        Class     Package   Subclass  World
public          Y         Y         Y         Y
protected       Y         Y         Y         N
no modifier     Y         Y         N         N
private         Y         N         N         N 

Những gì bạn thực sự muốn là truy cập mô-đun. Bằng cách đó bạn có thể giữ các bài kiểm tra của mình trong một gói và mã trong một gói khác. Đáng buồn thay, chúng ta không có nó trong Java.

Hầu hết mọi người chỉ cần làm 1 và mở rộng API. Sử dụng đúng các giao diện giúp giảm áp lực thực hiện.

Hack những gì bạn muốn vào 1 thậm chí còn xấu hơn. Xem qua ngăn xếp cuộc gọi và ném ngoại lệ bất cứ khi nào những gì được gọi là từ gói bạn không thích. Eeew.


2

Bằng mọi cách, hãy tách mã của bạn thành các gói. Nó sẽ đi một chặng đường dài hướng tới việc cải thiện khả năng bảo trì.

Để ngăn người dùng cuối truy cập vào những thứ họ không nên, bạn cần tách API của mình thành giao diện và cách triển khai.

Bạn có thể làm điều đó theo nghĩa đen, bằng cách định nghĩa toàn bộ API theo các giao diện Java và cung cấp một số lớp nhà máy để tạo các đối tượng triển khai. Đây là những gì JDBC làm.

Hoặc bạn có thể thực hiện thông qua quy ước, bằng cách tạo internalcác gói và ghi lại các gói đó là phụ thuộc vào việc triển khai và có thể thay đổi mà không cần cảnh báo hoặc tương thích ngược.


1
Thật không may, đây là một hoàn thành không đi. Điều này để lại cho nhiều lớp học công cộng. Họ có thể có gợi ý (là nhà máy hoặc 'nội bộ'). Nhưng tôi phải áp dụng công cụ bổ sung cho họ (cho tất cả các lớp công khai), điều này không tốt.
Markus Frauenfelder

@frmarkus - Tôi nghĩ rằng (1) bạn đang mong đợi quá nhiều ngoài tầm kiểm soát truy cập hoặc (2) bạn cần suy nghĩ lại cấu trúc gói của mình để các lớp từ một gói không cần phụ thuộc vào các lớp từ một gói khác gói (nếu bạn có thể giữ mọi thứ như các lớp lồng nhau tĩnh thì điều này không khó).
kdgregory
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.