2009-04-02 4 views
13

Tôi chưa thực hiện công việc của doanh nghiệp bằng Java, nhưng tôi thường thấy số reverse-domain-name package naming convention. Ví dụ: đối với gói Java tràn ngăn xếp, bạn sẽ đặt mã của mình bên dưới gói com.stackoverflow.Tại sao các ngôn ngữ như Java sử dụng tên gói phân cấp, trong khi Python thì không?

Tôi vừa chạy qua một gói Python sử dụng quy ước giống như Java, và tôi không chắc chắn các đối số và chống lại nó là gì, hoặc liệu chúng có áp dụng cho Python giống như Java hay không. Lý do bạn thích cái nào hơn cái kia? Những lý do đó có áp dụng cho các ngôn ngữ không?

Trả lời

13

Nếu chính Guido thông báo rằng quy ước miền ngược phải được tuân theo, nó sẽ không được chấp nhận, trừ khi có những thay đổi đáng kể trong việc thực hiện import trong python.

Xem xét: python tìm kiếm đường dẫn nhập tại thời gian chạy với thuật toán không nhanh; java tìm kiếm một đường dẫn với thuật toán đầy đủ ở cả thời gian biên dịch và thời gian chạy. Đi trước, cố gắng sắp xếp thư mục của bạn như thế này:

folder_on_path/ 
    com/ 
     __init__.py 
     domain1/ 
      module.py 
      __init__.py 


other_folder_on_path/ 
    com/ 
     __init__.py 
     domain2/ 
      module.py 
      __init__.py 

Sau đó thử:

from com.domain1 import module 
from com.domain2 import module 

Chính xác là một trong những tuyên bố sẽ thành công. Tại sao? Bởi vì folder_on_path hoặc other_folder_on_path cao hơn trên đường dẫn tìm kiếm. Khi python thấy from com., nó lấy gói com đầu tiên có thể. Nếu điều đó xảy ra có chứa domain1, thì import đầu tiên sẽ thành công; nếu không, nó sẽ ném một số ImportError và bỏ cuộc. Tại sao? Bởi vì import phải xảy ra trong thời gian chạy, có khả năng ở bất kỳ điểm nào trong luồng mã (mặc dù thường xuyên nhất ở đầu). Không ai muốn một cây đi bộ đầy đủ tại thời điểm đó để xác minh rằng không có trận đấu có thể. Nó giả định rằng nếu nó tìm thấy một gói có tên là com, nó là góicom.

Hơn nữa, trăn không phân biệt giữa những điều khoản sau đây:

from com import domain1 
from com.domain1 import module 
from com.domain1.module import variable 

Khái niệm về xác minh rằng comcáccom sẽ là khác nhau trong từng trường hợp. Trong java, bạn thực sự chỉ phải đối phó với trường hợp thứ hai, và điều đó có thể được thực hiện bằng cách đi qua hệ thống tệp (tôi đoán một lợi thế của việc đặt tên các lớp và các tệp giống nhau). Trong python, nếu bạn cố gắng thực hiện nhập không có gì ngoài hỗ trợ hệ thống tệp, trường hợp đầu tiên có thể (gần như) trong suốt (init .py sẽ không chạy), trường hợp thứ hai có thể được thực hiện, nhưng bạn sẽ mất hoạt động ban đầu của module.py, nhưng trường hợp thứ ba hoàn toàn không thể đạt được. Mã phải thực thi cho variable để có sẵn. Và đây là một điểm chính: import thực hiện nhiều hơn việc giải quyết các không gian tên, nó thực thi mã.

Bây giờ, bạn thể nhận được ngay với điều này nếu mỗi gói python bao giờ phân phối đòi hỏi một quá trình cài đặt mà tìm kiếm các thư mục com, và sau đó là domain, và vân vân và vân vân, nhưng điều này làm cho bao bì đáng kể khó khăn hơn, phá hủy khả năng kéo-và-thả, và làm cho bao bì và tất cả-ra phiền toái.

+0

từ mô-đun nhập com.domain1 như d1m # v.v. –

+0

Điểm tốt về nhiều gói 'com' trong các thư mục đường dẫn khác nhau - Tôi chỉ xem xét các vấn đề chia sẻ một gói cha, nhưng các gói riêng biệt cùng tên thậm chí còn tồi tệ hơn. –

+0

Tìm kiếm Java các lớp trong thời gian chạy, không chỉ ở thời gian biên dịch, sử dụng cấu trúc thư mục. Nó được liên kết động. – Marian

5

Ý tưởng là giữ cho không gian tên xung đột miễn phí. Thay vì UUID không thể đọc được hoặc tương tự, tên miền ngược lại không thể theo cách của người khác. Rất đơn giản nhưng thực dụng. Ngoài ra, khi sử dụng libs của bên thứ ba, nó có thể cung cấp cho bạn manh mối về nơi họ đến (để cập nhật, hỗ trợ, v.v.)

+0

Ah, tôi đã quên Java không có cơ chế để nhập lại bản đồ (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4983159), do đó khả năng xảy ra xung đột. Đó có thể là lý do. – cdleary

+0

Hmm, điều đó thật tuyệt! nhập my.code.Enquiry; nhập your.code.Enquiry như của họEnquiry; thậm chí không nhất thiết phải có các xung đột tên/từ khóa biến đổi trong nội dung lớp vì nó nằm trong phần nhập. – JeeBee

10

Đó là cách tuyệt vời để ngăn chặn xung đột tên và tận dụng toàn bộ hệ thống tên miền hiện có , do đó, nó không yêu cầu thêm bộ máy quan liêu hoặc đăng ký. Nó đơn giản và rực rỡ.

Bằng cách đảo ngược tên miền, nó cũng cung cấp cho nó cấu trúc phân cấp, tiện dụng. Vì vậy, bạn có thể có các gói phụ ở cuối.

Nhược điểm duy nhất là độ dài của tên, nhưng đối với tôi, đó không phải là một nhược điểm ở tất cả. Tôi nghĩ rằng đó là một ý tưởng khá hay đối với bất kỳ ngôn ngữ nào có thể hỗ trợ nó.

Tại sao thư viện JavaScript không làm như vậy? Không gian tên chung của họ là một vấn đề lớn, nhưng các thư viện Javascript sử dụng các mã định danh toàn cầu đơn giản như '$', nó xung đột với các thư viện Javascript khác.

+0

JavaScript là một vấn đề hoàn toàn riêng biệt. Python có phạm vi mô-đun cấp tập tin và một cơ chế nhập khẩu mà JavaScript không có. – cdleary

+0

Ah Tôi không biết Python có thể làm điều đó. Nhận xét về Javascript vẫn có liên quan. Các đối tượng trong Javascript nằm trong phạm vi toàn cầu và do đó, làm các tên gói trong Java, do đó, sẽ được hưởng lợi từ một số quy ước đặt tên thông thường để ngăn chặn xung đột. – thomasrutter

+0

Đúng, điều đó có ý nghĩa - quy ước đặt tên được sử dụng để tránh va chạm trong nhập gói Java. Nhưng nó có cần thiết/hữu ích trong Python không? – cdleary

0

Java có thể làm điều đó như thế này, vì nó là một thực hành chuẩn Java được đề nghị và được cộng đồng Java chấp nhận rộng rãi. Python dos không có quy ước này.

+0

Tôi nghĩ python là hoàn hảo? :) – willcodejavaforfood

+0

Python * là * hoàn hảo; Java không thực sự cần điều này, họ chỉ cần chọn để làm điều đó. ;-) –

+1

Python hoàn hảo. Chỉ là Java đang sử dụng một quy ước sai;) – Oli

12

"Lý do bạn thích cái nào hơn cái kia?"

Kiểu của Python đơn giản hơn. Phong cách của Java cho phép các sản phẩm cùng tên từ các tổ chức khác nhau.

"Những lý do đó có áp dụng cho các ngôn ngữ không?"

Có. Bạn có thể dễ dàng có các gói Python cấp cao nhất có tên là "com", "org", "mil", "net", "edu" và "gov" và đặt các gói của bạn dưới dạng các gói phụ trong các gói này.

Chỉnh sửa. Bạn có một số phức tạp khi bạn làm điều này, bởi vì tất cả mọi người phải hợp tác và không gây ô nhiễm các gói cấp cao nhất với tàu tuần dương của riêng mình.

Python đã không bắt đầu làm điều đó vì xung đột không gian tên - như một vấn đề thực tế - hóa ra là khá hiếm.

Java bắt đầu thực hiện điều đó bởi vì những người phát triển Java đã thấy trước rất nhiều người không hề lựa chọn cùng tên cho các gói của họ và cần phải phân loại các xung đột và vấn đề quyền sở hữu.

Những người Java không biết trước cộng đồng Nguồn mở chọn những tên độc đáo lạ lùng để tránh va chạm tên. Tất cả những người viết một trình phân tích cú pháp xml, thú vị, không gọi nó là "trình phân tích cú pháp". Họ dường như gọi nó là "Saxon" hoặc "Xalan" hoặc một cái gì đó hoàn toàn xa lạ.

+0

+1 Đúng, tôi chưa bao giờ có xung đột giữa hai gói có cùng tên. Có thể bạn có hai gói có tên là 'django', và có thể sẽ khó nhập cả hai cùng một lúc. Dường như nó có thể là * không thể * trong Java vì nó không có tính năng tái nhập tên. – cdleary

+0

Với ánh xạ gói hệ thống tập tin của Python, việc sử dụng các gói cấp cao nhất như "com" và "org" sẽ thực tế * tạo ra các xung đột không gian tên. –

+0

@ Jeff S: Nghe có vẻ như là sự khởi đầu của một câu trả lời tuyệt vời! – cdleary

2

Python không có nó, nó chỉ là một phân cấp phẳng hơn nhiều. Hãy xem ví dụ os.path. Và không có gì ngăn cản các nhà thiết kế thư viện làm cho những nhà thiết kế sâu sắc hơn, ví dụ: Django.

Về cơ bản, tôi nghĩ Python được thiết kế dựa trên ý tưởng bạn muốn hoàn thành công việc mà không phải chỉ định hoặc nhập quá nhiều trước. Điều này giúp ích rất nhiều cho việc sử dụng kịch bản và sử dụng dòng lệnh. Có một số phần của 'The Zen of Python' giải quyết lý do cho điều này:

  • Đơn giản là tốt hơn phức tạp.
  • Phẳng tốt hơn lồng nhau.
  • Đẹp hơn là xấu xí. (Hệ thống Java trông xấu xí với tôi.)

Mặt khác, có:

  • Namespaces là một ý tưởng tuyệt vời honking - hãy làm nhiều hơn nữa của những người!
+0

Tôi nghĩ bạn đang trả lời * tiêu đề * của câu hỏi thay vì nội dung - tôi thực sự băn khoăn về phân cấp tên miền ngược. – cdleary

18

Python không làm điều này vì bạn gặp phải vấn đề - ai sở hữu gói "com" mà hầu như mọi thứ khác là gói phụ? Phương pháp thiết lập hệ thống heirarchy của Python (thông qua hệ thống heirarchy hệ thống tập tin) không chơi tốt với quy ước này chút nào. Java có thể thoát khỏi nó vì gói heirarchy được định nghĩa bởi cấu trúc của chuỗi ký tự được nạp vào câu lệnh 'package', vì vậy không cần phải là một gói "com" rõ ràng ở bất cứ đâu.

Ngoài ra còn có câu hỏi phải làm gì nếu bạn muốn phát hành công khai gói nhưng không sở hữu một tên miền phù hợp để bừa vào tên gói hoặc nếu bạn kết thúc việc thay đổi (hoặc mất) tên miền của mình đối với một số lý do. (Các bản cập nhật sau có cần tên gói khác không? Làm cách nào để bạn biết rằng com.nifty_consultants.nifty_utility là phiên bản mới hơn của com.joe_blow_software.nifty_utility? Hay, ngược lại, làm cách nào để bạn biết rằng đó là không phải là phiên bản mới hơn? bỏ lỡ gia hạn tên miền của bạn và tên được lấy cắp bởi một người cắm trại tên miền, và người khác mua tên từ họ, và họ muốn phát hành công khai các gói phần mềm, sau đó họ có sử dụng cùng tên mà bạn đã sử dụng không?)

Tên miền và tên gói phần mềm, dường như với tôi, giải quyết hai vấn đề hoàn toàn khác nhau và có các yếu tố phức tạp hoàn toàn khác nhau. Cá nhân tôi không thích quy ước của Java vì (IMHO) nó vi phạm sự phân tách các mối quan tâm. Tránh xung đột không gian tên là tốt đẹp và tất cả, nhưng tôi ghét ý nghĩ về không gian tên phần mềm của tôi được xác định bởi (và phụ thuộc vào) sự tương tác của bộ phận tiếp thị với một số quan chức của bên thứ ba.

Để làm rõ thêm điểm của mình, để trả lời bình luận của JeeBee: Trong Python, gói là thư mục chứa tệp __init__.py (và có lẽ là một hoặc nhiều tệp mô-đun). Phân cấp gói yêu cầu mỗi gói cấp cao hơn phải là một gói đầy đủ, hợp pháp. Nếu hai gói (đặc biệt là từ các nhà cung cấp khác nhau, nhưng ngay cả các gói không liên quan trực tiếp từ cùng một nhà cung cấp) chia sẻ tên gói cấp cao nhất, cho dù tên đó là 'com' hoặc 'web' hoặc 'utils' hay bất cứ cái gì, mỗi cái phải cung cấp __init__.py cho gói cấp cao nhất đó. Chúng ta cũng phải giả định rằng các gói này có thể được cài đặt trong cùng một vị trí trong cây thư mục, tức là các gói trang web/[pkg]/[subpkg]. Hệ thống tệp do đó thực thi rằng chỉ có một[pkg]/__init__.py - vì vậy chiến thắng nào sẽ thắng? Không có (và không thể) một câu trả lời đúng cho câu hỏi đó. Chúng ta cũng không thể hợp nhất hai tập tin lại với nhau một cách hợp lý.Vì chúng ta không thể biết gói khác có thể cần làm gì trong số __init__.py, các gói con chia sẻ gói cấp cao nhất không thể giả định khi làm việc khi cả hai được cài đặt trừ khi chúng được ghi cụ thể để tương thích với nhau (ít nhất là trong gói này) tập tin). Đây sẽ là một cơn ác mộng phân phối và sẽ làm mất hiệu lực toàn bộ số điểm của các gói làm tổ. Điều này không cụ thể đối với phân cấp gói tên miền ngược, mặc dù chúng cung cấp ví dụ rõ ràng nhất và (IMO) có vấn đề về mặt triết học - đó thực sự là vấn đề thực tế của các gói cấp cao được chia sẻ, thay vì các câu hỏi triết học, mối quan tâm chính của tôi ở đây.

(Mặt khác, một gói lớn duy nhất sử dụng các gói con để tổ chức tốt hơn là một ý tưởng tuyệt vời, vì các gói con đó là được thiết kế đặc biệt để hoạt động và sống chung với nhau. một gói khái niệm duy nhất không có xu hướng yêu cầu số lượng tệp lớn đủ để cần thêm lớp tổ chức.)

+0

Bạn không phải sử dụng tên miền ngược như tên gói (đó là một rắc rối ở Vương quốc Anh - chúng ta có sử dụng "uk.co.company", đó là tatty không?) Đó chỉ là một cách để thiết lập hệ thống không gian tên không chính thức , nó đã làm việc tốt cho đến bây giờ, tôi chỉ không nhìn thấy đối số của bạn. – JeeBee

11

Một nơi nào đó trên Joel về phần mềm, Joel có so sánh giữa hai phương pháp phát triển công ty: Phương pháp của Jerry, bắt đầu nhỏ và phát triển hữu cơ, và phương pháp Amazon tăng toàn bộ tiền và đặt cược rất rộng tuyên bố ngay từ đầu.

Khi Sun giới thiệu Java, đó là với sự phô trương và quảng cáo. Java được cho là sẽ tiếp quản. Phần lớn các phát triển phần mềm có liên quan trong tương lai sẽ là trên các ứng dụng Java được phân phối trên web. Sẽ có những ban nhạc bằng đồng và thậm chí cả ngựa. Trong bối cảnh này, nó là hợp lý để thiết lập, lên phía trước, một quy ước đặt tên đó là dựa trên internet, công ty thân thiện, và trên một quy mô hành tinh.

OK, nó đã không bật ra như Sun hy vọng, nhưng họ lên kế hoạch như thể họ sẽ thành công. Cá nhân, tôi coi thường các dự án có thể bị phá hoại bởi sự thành công.

Python là một dự án của Guido van Rossum ban đầu và đã khá lâu trước khi cộng đồng tin tưởng rằng nó sẽ tồn tại nếu van Rossum bị xe buýt đâm. Đã có, theo như tôi biết, không có kế hoạch ban đầu để tiếp nhận thế giới, và nó không được dự định như một ngôn ngữ applet web.

Do đó, trong các giai đoạn hình thành của ngôn ngữ, không có lý do gì để muốn có một hệ thống phân cấp rộng lớn cho một lược đồ đặt tên. Trong cộng đồng không chính thức đó, người ta đã chọn một tên dự án ít hay thay đổi và kiểm tra xem liệu có ai khác đã sử dụng nó hay không. (Đặt tên một ngôn ngữ máy tính sau khi một chương trình hài kịch của Anh có thể được coi là hay thay đổi chỉ để bắt đầu.) Không có nhu cầu nhận thức để phục vụ cho một kế hoạch đặt tên lớn nhưng không tưởng tượng và vụng về.

+1

+10 cho bối cảnh lịch sử và một viễn cảnh rõ ràng. Nhưng tôi chỉ có thể làm một +1 :) –

+0

Tôi sẽ làm một phần của mình để hỗ trợ +10 :) –

+0

"Cá nhân, tôi coi thường các dự án có thể bị phá hoại bởi sự thành công." Tôi chủ yếu là đồng ý (mặc dù 'coi thường' là khá mạnh), nhưng đồng thời, các công ty/dự án hứa hẹn sự cứu rỗi và One True Way cho tôi phát ban ... –