2009-03-22 32 views
26

Tôi đã chạy một số số liệu về dự án Java của mình và dường như có rất nhiều chu kỳ phụ thuộc giữa các gói. Tôi đã không thực sự biết cách tổ chức các công cụ thành các gói, vì vậy tôi đã làm những gì có ý nghĩa với tôi, mà dường như là sai.Làm thế nào để tổ chức các gói (và ngăn chặn các chu kỳ phụ thuộc)?

Dự án của tôi là một khuôn khổ mạng nơron. Mạng nơron có Neurons, được kết nối với nhau bằng Kết nối. Họ cần phải phụ thuộc vào nhau. Tuy nhiên, cũng có nhiều loại Neuron khác nhau, vì vậy tôi nghĩ nên đặt tất cả chúng vào trong gói 'nơ-ron' của riêng mình. Rõ ràng là một kết nối không phải là một Neuron vì vậy nó không phải là trong gói, nhưng kể từ khi họ đề cập đến nhau, bây giờ tôi có một phụ thuộc vòng tròn.

Đây chỉ là một ví dụ, nhưng tôi có nhiều tình huống như thế này. Làm thế nào để bạn xử lý các loại tình huống?

Ngoài ra, tôi đọc các lớp trong gói cao hơn trong phân cấp gói không được coi là tham chiếu đến các lớp trong gói sâu hơn. Điều này có nghĩa là một lớp NeuralNetwork trong gói 'nn' không thể tham khảo Neuron trong gói 'nn.neurons'. Các bạn có theo nguyên tắc này không? Và nếu tôi chuyển NeuralNetwork thành 'nn.networks' hay gì đó thì sao? Trong trường hợp đó, nó sẽ đề cập đến một gói anh chị em thay vì một đứa trẻ. Đó là thực hành tốt hơn?

Trả lời

12

Các antcontrib VerifyDesign task sẽ giúp bạn làm những gì bạn muốn:

Ví dụ, nếu có ba gói trong cây một nguồn

* biz.xsoftware.presentation 
* biz.xsoftware.business 
* biz.xsoftware.dataaccess 

và tự nhiên trình bày chỉ nên phụ thuộc vào gói kinh doanh và doanh nghiệp phải phụ thuộc vào dataaccess. Nếu bạn xác định thiết kế của mình theo cách này và vi phạm bản dựng sẽ bị lỗi khi tác vụ kiến ​​verifydesign là được gọi. Ví dụ: nếu tôi đã tạo một lớp học trong biz.xsoftware.presentation và lớp đó phụ thuộc vào một lớp học trong biz.xsoftware.dataaccess, thì tòa nhà sẽ không thành công. Điều này đảm bảo thiết kế thực sự tuân theo những gì được ghi lại (đến một số mức độ ít nhất). Đây là đặc biệt tốt đẹp với các bản dựng tự động

Vì vậy, khi bạn đã quyết định cách sắp xếp mọi thứ, bạn có thể thực thi các yêu cầu trong thời gian biên dịch. Bạn cũng có được quyền kiểm soát tốt để bạn có thể cho phép một số trường hợp nhất định phá vỡ các "quy tắc" này. Vì vậy, bạn có thể cho phép một số chu kỳ.

Tùy thuộc vào cách bạn muốn làm việc, bạn có thể thấy rằng gói "utils" có ý nghĩa.

Đối với trường hợp cụ thể mà bạn trích dẫn ... Tôi có thể làm điều gì đó như thế này:

  • gói nn chứa Nueron và kết nối
  • nn.neurons gói chứa các lớp con của Nueron

Neuron và kết nối là cả hai khái niệm cấp cao được sử dụng trong NeuralNetowrk, vì vậy việc đặt tất cả chúng lại với nhau có ý nghĩa. Các lớp Neuron và Connection có thể tham chiếu với nhau trong khi lớp Connection không cần biết về các lớp con của Neuron.

+1

Gần đây tôi đã phát triển công cụ tương tự sử dụng các lớp chú thích thay vì tệp cấu hình trung tâm: https: // github.com/ruediste1/jabsaw – ruediste

5

Tôi không nghĩ rằng các phụ thuộc theo chu kỳ như phụ thuộc bạn mô tả có trạng thái là. Miễn là các khái niệm phụ thuộc lẫn nhau ở cùng một mức trừu tượng và liên quan đến cùng một phần của kiến ​​trúc, có thể không cần thiết phải ẩn các khái niệm này khỏi nhau. Neurons và Connections phù hợp với hóa đơn này trong sự hiểu biết của tôi.

Điểm chung để giảm các khớp nối như vậy là trích xuất các giao diện và thậm chí có thể đặt chúng trong một mô-đun riêng biệt. Đơn giản chỉ cần tổ chức bởi các gói bên trong một dự án duy nhất không cho phép bạn ẩn chi tiết triển khai đầy đủ. Một mô hình phổ biến mà cho phép bạn thực sự ẩn hiện thực là như sau:

Khách hàng Mã ----> Giao diện < --- Thực hiện

Trong mô hình này, bạn ẩn "Thực hiện" mô-đun từ mã khách hàng , có nghĩa là mã trong mô-đun "Mã khách hàng" thậm chí không thấy mã triển khai.

Việc lồng các gói phục vụ một số mục đích: Một số dự án có thể có mô hình miền được sắp xếp theo gói. Trong trường hợp này, các gói phản ánh một số nhóm miền, và các tham chiếu có thể đi lên/xuống các gói. Khi nói đến những thứ như triển khai dịch vụ, mô hình được đề xuất của bạn khá phổ biến và một điều tốt để làm theo. Càng sâu hơn trong hệ thống phân cấp gói, bạn sẽ nhận được lớp cụ thể hơn.

+0

có, verifydesign article KHUYẾN CÁO đi qua trường hợp sử dụng ở đây http://www.devx.com/opensource/Article/33729 –

4

Chúng ta đang nói về loại mã nào? Nếu bạn chỉ có 10-20 lớp, bạn có thể không cần (và không nên) tổ chức quá nhiều mã của bạn thành các gói chỉ vì lợi ích của nó.

Khi dự án của bạn phát triển, sự khác biệt đầu tiên bạn muốn thực hiện là tách mã giao diện người dùng khỏi mô hình dữ liệu cơ bản và logic. Có một lớp tách biệt sạch sẽ là rất quan trọng để có thể làm thử nghiệm đơn vị thích hợp.

Nếu bạn gặp khó khăn trong việc loại bỏ các phụ thuộc vòng tròn, có thể trường hợp các lớp thực sự là phụ thuộc lẫn nhau và phải nằm trong cùng một gói.

Bắt các lớp trừu tượng ngay có lẽ là một trong những khía cạnh quan trọng nhất khi thiết kế cấu trúc mã tổng thể.

5

Bạn xử lý các loại tình huống như thế nào?

Phụ thuộc thông thường không phải là xấu. Trong thực tế, điều này đôi khi có thể là một trường hợp "chữa bệnh tồi tệ hơn bệnh": giải nén một giao diện làm tăng mức độ phức tạp của mã của bạn và thêm một lớp khác của sự hướng dẫn. Điều đó có lẽ không đáng giá cho các mối quan hệ rất đơn giản.

9

Trước hết, bạn quan tâm đúng đắn vì phụ thuộc vòng tròn giữa các gói không tốt. Các vấn đề phát sinh từ nó tăng tầm quan trọng với quy mô của dự án, nhưng không có lý do để giải quyết tình trạng này đúng lúc.

Bạn nên tổ chức các lớp học của mình bằng cách đặt các lớp mà bạn sử dụng lại cùng nhau trong cùng một gói. Vì vậy, nếu bạn có ví dụ AbstractNeuron và AbstractConnection, bạn sẽ đặt chúng trong cùng một gói. Nếu bây giờ bạn đã triển khai HumanNeuron và HumanConnection, bạn sẽ đặt chúng trong cùng một gói (được gọi là ví dụ * .network.human). Hoặc, bạn có thể chỉ có một loại kết nối, ví dụ BaseConnection và nhiều Neurons khác nhau. Nguyên tắc vẫn như cũ. Bạn đặt BaseConnection cùng với BaseNeuron. HumanNeuron trong gói riêng của nó cùng với HumanSignal vv VirtualNeuron cùng với VirtualSignal, vv Bạn nói: "Rõ ràng là một kết nối không phải là một Neuron nên nó không phải là trong gói ..". Điều này không rõ ràng, cũng không chính xác.

Bạn nói rằng bạn đã đặt tất cả các nơron của mình trong cùng một gói. Điều này không đúng, trừ khi bạn sử dụng lại tất cả các triển khai của bạn cùng nhau. Một lần nữa, hãy xem sơ đồ tôi đã mô tả ở trên. Hoặc dự án của bạn quá nhỏ, bạn đặt tất cả trong gói duy nhất hoặc bạn bắt đầu tổ chức các gói như được mô tả. Để biết thêm chi tiết, hãy xem The Common Reuse Principle:

CÁC LỚP TRONG MỘT GÓI ĐƯỢC TẠM DỪNG. NẾU BẠN BỎ LẠI MỘT SỐ LỚP TRONG MỘT GÓI, BẠN BỎ LẠI HỌP TẤT CẢ.

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