Đặt tên giao diện trong Java [đã đóng]


324

Hầu hết các ngôn ngữ OO đều đặt tiền tố tên giao diện của chúng bằng chữ I viết hoa, tại sao Java không làm điều này? Lý do cho việc không tuân theo quy ước này là gì?

Để giải thích ý tôi là gì, nếu tôi muốn có giao diện Người dùng và triển khai Người dùng, tôi có hai lựa chọn trong Java:

  1. Lớp = Người dùng, Giao diện = Người dùng
  2. Lớp = UserImpl, Giao diện = Người dùng

Ở đâu trong hầu hết các ngôn ngữ:

Lớp = Người dùng, Giao diện = Người dùng

Bây giờ, bạn có thể lập luận rằng bạn luôn có thể chọn một tên mô tả nhất cho việc triển khai của người dùng và vấn đề sẽ biến mất, nhưng Java đang đẩy mạnh cách tiếp cận POJO vào mọi thứ và hầu hết các thùng chứa IOC đều sử dụng DynamicProxies. Hai điều này có nghĩa là bạn sẽ có nhiều giao diện với một triển khai POJO duy nhất.

Vì vậy, tôi đoán câu hỏi của tôi tập trung vào: "Có đáng để tuân theo quy ước đặt tên Giao diện rộng hơn, đặc biệt là khi các Khung công tác Java dường như đang hướng tới?"


61
"Ở đâu trong hầu hết các ngôn ngữ"? Những ngôn ngữ nào ngoài .Net?
wds

2
Các cộng đồng ngôn ngữ khác nhau có các quy ước đặt tên khác nhau, và điều này đã đúng trong một thời gian dài. Tìm hiểu làm thế nào các quy ước đặt tên có nguồn gốc đôi khi về cơ bản là nghiên cứu văn hóa dân gian.
David Thornley

4
Eclipse là một ngoại lệ đáng kể sử dụng Java với cách đặt tên theo kiểu IFoo. wiki.eclipse.org/Naming_Conventions
David Leonard

2
Nếu bạn có một cái nhìn vào những cái tên của giao diện trong Android SDK (Java cũng), bạn sẽ thấy rằng họ đã sử dụng ước của việc có từ giao diện trên phần cuối của một tên giao diện, giống như NetworkInterface, DialogInterfacevv
sandalone

21
Làm thế nào câu hỏi này có thể "đóng như không mang tính xây dựng" khi nó rất phổ biến và được nhiều người quan tâm?
vào

Câu trả lời:


329

Tôi không thích sử dụng tiền tố trên các giao diện:

  • Tiền tố làm tổn thương khả năng đọc.

  • Sử dụng giao diện trong máy khách là cách tốt nhất để lập trình, vì vậy tên giao diện phải ngắn gọn và dễ chịu nhất có thể. Các lớp triển khai nên xấu hơn để không khuyến khích sử dụng chúng.

  • Khi thay đổi từ một lớp trừu tượng sang một giao diện, một quy ước mã hóa với tiền tố tôi ngụ ý đổi tên tất cả các lần xuất hiện của lớp --- không tốt!


12
Hoàn toàn đồng ý. Thêm một khóa để gõ nếu bạn sử dụng tự động hoàn thành. Rất nhiều tệp bắt đầu bằng I.
Kalecser

85
Bất kỳ IDE tốt nào cũng làm cho việc thay đổi mã theo cách bạn mô tả dễ dàng. Ngoài ra, khi thay đổi từ một lớp trừu tượng sang một giao diện, tôi khá chắc chắn rằng khách hàng của bạn sẽ cần phải biên dịch lại bằng mọi cách.
Allain Lalonde

63
Siêu trễ ở đây, nhưng: Nó không quan trọng ở tất cả nếu một IDE làm thay đổi tên của một cái gì đó dễ dàng. Mã sử ​​dụng một thể hiện của một số loại sẽ không bao giờ, không bao giờ quan tâm nếu loại đó là một giao diện hoặc một lớp hoặc những gì. Như vậy, việc tiết lộ một chi tiết như vậy trong tên của loại là vô nghĩa và có hại cho sự hiểu biết. Loại và hợp đồng mà nó tiết lộ là những gì quan trọng!
ColinD

11
Ngoài ra, nếu bạn đang đi theo con đường của IFoo, thì đó không nên là CFoo cho việc triển khai và tất nhiên khi thất bại, một phương pháp sẽ ném một EFoo.
Robin

57
"Tiền tố làm tổn thương khả năng đọc" hoàn toàn chủ quan. Như hầu hết các quy ước đặt tên. Điều quan trọng hơn là nhóm của bạn giải quyết thỏa thuận về những việc cần làm để cơ sở mã phù hợp.
dreadwail

121

Có thực sự có một sự khác biệt giữa:

class User implements IUser

class UserImpl implements User

nếu tất cả chúng ta đang nói đến là quy ước đặt tên?

Cá nhân tôi không thích đi trước giao diện Ivì tôi muốn mã hóa giao diện và tôi cho rằng điều đó quan trọng hơn về mặt quy ước đặt tên. Nếu bạn gọi giao diện IUserthì mọi người tiêu dùng của lớp đó cần phải biết IUser. Nếu bạn gọi lớp UserImplthì chỉ có lớp và thùng chứa DI của bạn biết về bộ Implphận đó và người tiêu dùng chỉ biết họ đang làm việc với a User.

Sau đó, một lần nữa, những lần tôi bị buộc phải sử dụng Implbởi vì một cái tên tốt hơn không xuất hiện rất ít bởi vì việc triển khai được đặt tên theo cách thực hiện bởi vì đó là điều quan trọng, ví dụ:

class DbBasedAccountDAO implements AccountDAO
class InMemoryAccountDAO implements AccountDAO

Tôi nghĩ rằng bạn muốn biết DAO vì nó mô tả chức năng chung mà không cần phải mở lớp. Nếu tôi đang xem qua các tệp lớp trong một dự án, thật dễ dàng để thấy tất cả các DAO bằng cách tìm kiếm * DAO
Patrick

6
DAO là một mẫu nổi tiếng để truy cập cơ sở dữ liệu, do đó, có mẫu trong tên giúp dễ dàng biết lớp này làm gì chỉ bằng cách nhìn vào tên của nó. PS Sẽ tốt hơn nếu tuân theo ký hiệu lạc đà một cách nghiêm ngặt ("AccountDao"), chẳng hạn như trong mina.apache.org/changes-b between
Esko Luontola

4
@marker, không giống như tôi có một giao diện. DAO cho bạn biết rằng lớp hoặc giao diện là một đối tượng để truy cập dữ liệu tài khoản, đó là những gì đối tượng làm. Có một cái tôi nói với bạn một giao diện, không liên quan gì đến chính đối tượng ngoại trừ ngữ nghĩa của ngôn ngữ
tddmonkey

Khi bạn trình bày nó, tiền tố của nó và hậu tố.
Andrei Rînea

3
@Andrei: Không, đó là ngữ nghĩa ("DAO") so với trang trí không cần thiết của một tạo tác ngôn ngữ ("Tôi" như trong giao diện; một thực tế, được đề cập trong mã dù sao "giao diện IFoo ...")
Dirk

75

Có thể có một số lý do Java thường không sử dụng quy ước IUser.

  1. Một phần của cách tiếp cận hướng đối tượng là bạn không cần phải biết khách hàng đang sử dụng giao diện hay lớp thực hiện. Vì vậy, ngay cả Danh sách là một giao diện và Chuỗi là một lớp thực tế, một phương thức có thể được truyền qua cả hai - không có nghĩa gì để phân biệt trực quan các giao diện.

  2. Nói chung, chúng tôi thực sự sẽ thích sử dụng các giao diện trong mã máy khách (ví dụ như List cho ArrayList). Vì vậy, nó không có ý nghĩa để làm cho các giao diện nổi bật như ngoại lệ.

  3. Quy ước đặt tên Java thích các tên dài hơn với ý nghĩa thực tế với các tiền tố kiểu Hungary. Vì vậy, mã đó sẽ dễ đọc nhất có thể: Danh sách đại diện cho một danh sách và Người dùng đại diện cho người dùng - không phải là Người dùng.


72

Ngoài ra còn có một quy ước khác, được sử dụng bởi nhiều dự án nguồn mở bao gồm cả Spring.

interface User {
}

class DefaultUser implements User {
}

class AnotherClassOfUser implements User {
}

Cá nhân tôi không thích tiền tố "Tôi" vì lý do đơn giản đó là quy ước tùy chọn. Vậy nếu tôi chấp nhận điều này thì IIOPConnection có nghĩa là một giao diện cho IOPConnection không? Điều gì sẽ xảy ra nếu lớp không có tiền tố "I", sau đó tôi có biết nó không phải là giao diện không .. câu trả lời ở đây là không, bởi vì các quy ước không phải luôn luôn tuân theo và việc kiểm soát chúng sẽ tạo ra nhiều công việc hơn mà chính quy ước lưu lại.


Tôi thích điều này, vì nó cũng giúp bạn trong chế độ sử dụng giao diện cho các phụ thuộc bên ngoài thay vì ghép các lớp.
Matt Briggs

47

Như một poster khác đã nói, thông thường nên có giao diện xác định các khả năng không phải là loại. Tôi có xu hướng không "triển khai" thứ gì đó như "Người dùng" và đây là lý do tại sao "Người dùng" thường không thực sự cần thiết theo cách được mô tả ở đây. Tôi thường xem các lớp là danh từ và giao diện là tính từ:

class Number implements Comparable{...}  
class MyThread implements Runnable{...}
class SessionData implements Serializable{....}

Đôi khi một Tính từ không có ý nghĩa, nhưng tôi vẫn thường sử dụng các giao diện để mô hình hóa hành vi, hành động, khả năng, thuộc tính, v.v., chứ không phải các loại.

Ngoài ra, nếu bạn thực sự chỉ tạo một Người dùng và gọi nó là Người dùng thì điểm của việc có giao diện IUser là gì? Và nếu bạn sắp có một vài loại người dùng khác nhau cần triển khai một giao diện chung, thì việc thêm "I" vào giao diện sẽ giúp bạn tiết kiệm trong việc chọn tên của các triển khai?

Tôi nghĩ một ví dụ thực tế hơn là một số loại người dùng cần có thể đăng nhập vào một API cụ thể. Chúng ta có thể định nghĩa giao diện Đăng nhập và sau đó có lớp cha "Người dùng" với SuperUser, DefaultUser, AdminUser, AdminContact, v.v., một số trong đó sẽ hoặc không thực hiện giao diện Đăng nhập (Có thể đăng nhập?) Khi cần thiết.


Tôi nghĩ rằng các ví dụ bạn cung cấp để hỗ trợ "giao diện là tính từ" bị sai lệch, vì các giao diện đó được dự định giống như các hỗn hợp (hoặc đặc điểm). Do đó, giao diện tốt cho cả tính từ và danh từ - nhưng có lẽ không dành cho indefinite transitive verbs 8 ^ P
Stevel

Điều này có thể được thay đổi trong những năm qua. Các tài liệu tiên tri. cho phép các giao diện dưới dạng các loại: [link] docs.oracle.com/javase/tutorial/java/IandI/interfaceAsType.html
karlihnos

38

Bob Lee đã nói một lần trong một bài thuyết trình:

điểm của giao diện là gì nếu bạn chỉ có một triển khai.

Vì vậy, bạn bắt đầu với một thực hiện tức là không có giao diện. sau đó, bạn quyết định, cần có một giao diện ở đây, vì vậy bạn chuyển đổi lớp của mình sang một giao diện.

sau đó nó trở nên rõ ràng: lớp ban đầu của bạn được gọi là Người dùng. Giao diện của bạn bây giờ được gọi là Người dùng. có thể bạn có UserProdImpl và UserTestImpl. nếu bạn thiết kế ứng dụng của mình tốt, mọi lớp (trừ những ứng dụng khởi tạo Người dùng) sẽ không thay đổi và sẽ không nhận thấy rằng đột nhiên chúng được chuyển qua một giao diện.

để nó được rõ ràng -> Giao diện Người dùng thực hiện UserImpl.


18
Sử dụng giao diện sẽ giúp Kiểm tra phát triển theo hướng. Chúng tôi đã gặp phải nhiều vấn đề với Mô hình miền và thử nghiệm vì chúng tôi quyết định KHÔNG sử dụng giao diện. Một người bạn của tôi từng trích dẫn: "Mọi thứ đều là giao diện, nó sẽ giúp bạn tiết kiệm trong thời gian dài".
hooknc

4
Mocking và hỗ trợ proxy dễ dàng. Tôi chắc chắn có những lý do khác để cung cấp giao diện là tốt.
MetroidFan2002

3
Như tôi đã nói gần đây với một đồng nghiệp, bây giờ không tốn kém gì để giới thiệu một giao diện nhưng có thể giúp bạn tiết kiệm nhiều thời gian sau này.
tddmonkey

2
Nếu bạn có thể có các triển khai khác trong tương lai gần trung bình, giao diện sẽ là một điểm cộng.
Bắt đầu

3
Tôi không thích lập luận "Tôi có thể cần một ẩn ý khác trong tương lai". Tôi thích cách tiếp cận của YAGNI: không lên kế hoạch cho những điều chưa xảy ra.
David Lavender

24

Trong C #, nó là

public class AdminForumUser : UserBase, IUser

Java sẽ nói

public class AdminForumUser extends User implements ForumUserInterface

Do đó, tôi không nghĩ các quy ước gần như quan trọng trong java đối với các giao diện, vì có sự khác biệt rõ ràng giữa kế thừa và thực hiện giao diện. Tôi muốn nói chỉ cần chọn bất kỳ quy ước đặt tên nào bạn muốn, miễn là bạn nhất quán và sử dụng một cái gì đó để cho mọi người thấy rằng đây là các giao diện. Đã không thực hiện java trong một vài năm, nhưng tất cả các giao diện sẽ chỉ nằm trong thư mục riêng của họ và đó là quy ước. Không bao giờ thực sự có bất kỳ vấn đề với nó.


22
Có thể tôi là người viết mã Java tồi, nhưng tôi thích kiểu C # hơn, có nghĩa là tất cả các giao diện bắt đầu bằng tiền tố 'I' :)
davs

7
Tôi không chắc bạn và những người khác sẽ nhận được quy ước được cho là này từ đâu. Điều đó không rõ ràng trong các thư viện Java ...
ChiefTwoP Pencil 7/215

6

Theo kinh nghiệm của tôi, quy ước "Tôi" áp dụng cho các giao diện nhằm cung cấp hợp đồng cho một lớp, đặc biệt khi bản thân giao diện không phải là một khái niệm trừu tượng của lớp.

Ví dụ, trong trường hợp của bạn, tôi chỉ mong đợi xem IUserliệu người dùng duy nhất bạn từng có là ai User. Nếu bạn dự định có nhiều loại người dùng khác nhau - NoviceUser, ExpertUserv.v. - Tôi sẽ thấy một Usergiao diện (và, có lẽ, một AbstractUserlớp thực hiện một số chức năng phổ biến, như get/setName()).

Tôi cũng mong chờ giao diện để xác định khả năng - Comparable, Iterable, vv - được đặt tên như vậy, và không giống như IComparablehay IIterable.


Nếu người dùng duy nhất bạn từng có là Người dùng, tại sao không sử dụng Người dùng thay vì giao diện?
Carighan

3
Trong một số kiến ​​trúc máy khách / máy chủ, phía máy khách cần biết các giao diện mà không cần triển khai máy chủ hạng nặng.
David Koelle

5

Theo các nguyên tắc OO tốt, mã của bạn nên (càng xa thực tế / càng tốt) phụ thuộc vào trừu tượng hơn là các lớp cụ thể. Ví dụ, nói chung là tốt hơn để viết một phương thức như thế này:

public void doSomething(Collection someStuff) {
    ...
}

hơn cái này:

public void doSomething(Vector someStuff) {
    ...
}

Nếu bạn làm theo ý tưởng này, thì tôi sẽ bảo đảm rằng mã của bạn sẽ dễ đọc hơn nếu bạn đặt tên giao diện như "Người dùng" và "BankAccount" (ví dụ), thay vì "IUser", "UserInterface" hoặc các biến thể khác.

Các bit duy nhất của mã cần quan tâm đến các lớp bê tông thực tế là những nơi mà các lớp bê tông được xây dựng. Mọi thứ khác nên được viết bằng các giao diện.

Nếu bạn làm điều này, thì các tên lớp cụ thể "xấu xí" như "UserImpl" sẽ được ẩn an toàn khỏi phần còn lại của mã, có thể tiếp tục sử dụng các tên giao diện "đẹp".


Nhưng tại sao phải làm một giao diện phù hợp cho mọi lớp trong chương trình của bạn khi bạn chỉ cần giao diện cho một hoặc hai thứ?
Truyền thuyết Chiều dài

3

= v = Tiền tố "I" cũng được sử dụng trong khung Wicket, nơi tôi đã quen với nó một cách nhanh chóng. Nói chung, tôi hoan nghênh bất kỳ quy ước nào rút ngắn các tên lớp Java cồng kềnh. Tuy nhiên, có một rắc rối là mọi thứ đều được xếp theo thứ tự chữ cái trong "I" trong các thư mục và trong Javadoc.

Thực hành mã hóa wicket tương tự như Swing, trong đó nhiều trường hợp điều khiển / widget được xây dựng dưới dạng các lớp bên trong ẩn danh với các khai báo phương thức nội tuyến. Khó chịu, nó khác 180 ° so với Swing trong đó Swing sử dụng tiền tố ("J") cho các lớp thực hiện.

Hậu tố "Impl" là một từ viết tắt và không quốc tế hóa tốt. Nếu chỉ có ít nhất chúng ta đã đi với "Imp" thì nó sẽ dễ thương hơn (và ngắn hơn). "Impl" được sử dụng cho IOC, đặc biệt là Spring, vì vậy hiện tại chúng tôi đang bị mắc kẹt với nó. Mặc dù vậy, nó nhận được một chút schizo sau 3 quy ước khác nhau trong ba phần khác nhau của một cơ sở mã.


0

Đây có phải là một quy ước đặt tên rộng hơn trong bất kỳ ý nghĩa thực tế? Tôi hiểu nhiều hơn về phía C ++ và không thực sự hiểu về Java và hậu duệ. Có bao nhiêu cộng đồng ngôn ngữ sử dụng quy ước I?

Nếu bạn có một quy ước đặt tên tiêu chuẩn cửa hàng độc lập với ngôn ngữ ở đây, hãy sử dụng nó. Nếu không, đi với quy ước đặt tên ngôn ngữ.

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.