Java'da arayüz adlandırma [kapalı]


324

Çoğu OO dili arayüz adlarına büyük harf I ekler, Java neden bunu yapmaz? Bu sözleşmeyi izlememenin mantığı neydi?

Ne demek istediğimi göstermek için, bir Kullanıcı arayüzü ve bir Kullanıcı uygulaması olmasını istersem, Java'da iki seçeneğim olurdu:

  1. Class = Kullanıcı, Arayüz = UserInterface
  2. Class = UserImpl, Arayüz = Kullanıcı

Çoğu dilde:

Sınıf = Kullanıcı, Arayüz = IUser

Şimdi, kullanıcı uygulaması için her zaman en açıklayıcı bir ad seçebileceğinizi ve sorun ortadan kalktığını iddia edebilirsiniz, ancak Java şeylere ve çoğu IOC kapsayıcılarına bir POJO yaklaşımı zorluyor DynamicProxies'i yoğun olarak kullanıyor. Bu iki şey birlikte, tek bir POJO uygulamasıyla çok sayıda arayüzünüz olacağı anlamına gelir.

Yani, sanırım sorum şu şekilde kayboluyor: "Özellikle Java Frameworks'in gittiği yer ışığında daha geniş Arayüz adlandırma kuralını izlemeye değer mi?"


61
"Çoğu dilde nerede"? .Net dışında hangi diller var?
wds

2
Farklı dil topluluklarının farklı adlandırma kuralları vardır ve bu uzun, uzun süredir geçerlidir. Adlandırma kurallarının nasıl ortaya çıktığını bulmak bazen temel olarak folklor araştırmasıdır.
David Thornley

4
Eclipse, IFoo tarzı adlandırma ile Java kullanan önemli bir aykırı değerdir. wiki.eclipse.org/Naming_Conventions
David Leonard

2
Eğer (sıra Java) Android SDK içinde Arayüz isimleri bakmak varsa, bunların bir arayüz adının sonuna üzerine, gibi kelime arabirimine sahip olan bir kongre kullanılan göreceksiniz NetworkInterface, DialogInterfacevb
Sandalone

21
Bu soru bu kadar popüler ve çok sayıda insanın ilgisini çektiğinde nasıl "yapıcı değil olarak kapatılabilir"?
inor

Yanıtlar:


329

Arayüzlerde bir önek kullanmamayı tercih ederim:

  • Önek okunabilirliği incitir.

  • İstemcilerde arabirimleri kullanmak, programlamanın standart en iyi yoludur, bu nedenle arabirim adları mümkün olduğunca kısa ve keyifli olmalıdır. Uygulama sınıfları, kullanımlarını caydırmak için daha çirkin olmalıdır.

  • Soyut bir sınıftan bir arayüze geçerken, önek ile bir kodlama kuralı, sınıfın tüm oluşumlarını yeniden adlandırmayı ima eder - iyi değil!


12
Tamamen katılıyorum. Otomatik tamamlama kullanıyorsanız yazmak için bir anahtar daha. I. ile başlayan birçok dosya
Kalecser

85
İyi bir IDE, kodu tarif ettiğiniz şekilde değiştirmeyi kolaylaştırır. Ayrıca, soyut bir sınıftan bir arayüze geçerken, müşterilerinizin yine de derlemeleri gerekeceğinden eminim.
Allain Lalonde

63
Süper saatte burada ama: farketmez hiç bir IDE kolay bir şeyin adını değiştirerek yaparsa. Bir türün örneğini kullanan kod hiçbir zaman, bu türün bir arabirim mi, sınıf mı yoksa ne olduğuyla hiç ilgilenmemelidir. Bu nedenle, tür adında böyle bir ayrıntıyı ortaya koymak anlamsızdır ve anlaşılması için zararlıdır. Ortaya koyduğu tür ve sözleşme önemlidir!
ColinD

11
Ayrıca, eğer IFoo yoluna gidiyorsanız, uygulama için CFoo olmamalı ve elbette başarısızlık durumunda bir yöntem bir EFoo fırlatacaktır.
Robin

57
"Önek okunabilirliği acıtıyor" tamamen özneldir. Çoğu adlandırma kuralları gibi. Ekibinizin, kod tabanının tutarlı olması için ne yapılacağı konusunda anlaşmaya varması daha önemlidir.
dreadwail

121

Gerçekten arasında bir fark var mı:

class User implements IUser

ve

class UserImpl implements User

tüm konuştuğumuz konvansiyonları isimlendirmekse?

Şahsen ben arabirime Ikodlama yapmak istediğim için arabirimden önce DEĞİL tercih ediyorum ve adlandırma kuralı açısından daha önemli olduğunu düşünüyorum . Arayüzü çağırırsanız, IUsero sınıfın her tüketicisi onun bir IUser. Sınıfı çağırırsanız, UserImplsadece sınıf ve DI konteyneriniz Implparçayı bilir ve tüketiciler bir ile çalıştıklarını bilirler User.

Sonra tekrar, Impldaha iyi bir isim kendini göstermediği için kullanmaya zorlandığım zamanlar çok azdı ve uygulama arasında uygulamaya göre adlandırıldığından önemli olduğu için, örneğin

class DbBasedAccountDAO implements AccountDAO
class InMemoryAccountDAO implements AccountDAO

Sınıfı açmaya gerek kalmadan genel işlevselliği açıkladığından DAO'sunu bilmek isteyeceğinizi düşünüyorum. Bir projedeki sınıf dosyalarını inceliyorsam, * DAO
Patrick

6
DAO, veritabanı erişimi için iyi bilinen bir kalıptır, bu nedenle adda kalıba sahip olmak, sınıfın sadece adına bakarak ne yaptığını bilmeyi kolaylaştırır. PS mina.apache.org/changes-between-2x-and-1x.html
Esko Luontola

4
@marker, bir arayüzü belirtmek için I'e sahip olmak gibi bir şey değildir. DAO, sınıfın veya arabirimin, hesap verilerine erişmek için bir nesne olduğunu söyler; bu, nesnenin yaptığı şeydir. I sahip olmak size onun bir nesnenin kendisi ile ilgisi olmayan bir arayüz olduğunu söyler
tddmonkey

Bunu sunarken, öneki son ekine karşılık gelir.
Andrei Rînea

3
@Andrei: Hayır, semantik ("DAO") ve bir dil artefaktının gereksiz arayüzüne (arayüzdeki gibi "I"; yine de kodda "arayüz IFoo ...") belirtilen bir gerçek
Dirk

75

Java'nın genellikle IUser kuralını kullanmamasının birkaç nedeni olabilir.

  1. Nesneye Dayalı yaklaşımın bir parçası, istemcinin bir arabirim mi yoksa bir uygulama sınıfı mı kullandığını bilmeniz gerekmemesidir. Bu nedenle, List bile bir arabirimdir ve String gerçek bir sınıftır, her ikisinden de bir yöntem geçirilebilir - arabirimleri görsel olarak ayırt etmek mantıklı değildir.

  2. Genel olarak, istemci kodunda arayüzlerin kullanımını tercih edeceğiz (örneğin, ArrayList'e Liste'yi tercih edin). Bu nedenle, arayüzleri istisna olarak öne çıkarmak mantıklı değil.

  3. Java adlandırma kuralı, Macarca tarzı öneklerin gerçek anlamlarıyla daha uzun adları tercih eder. Böylece bu kod mümkün olduğu kadar okunabilir olacaktır: bir Liste bir listeyi temsil eder ve Kullanıcı bir IUser değil bir kullanıcıyı temsil eder.


72

Bahar da dahil olmak üzere birçok açık kaynaklı proje tarafından kullanılan başka bir sözleşme daha var.

interface User {
}

class DefaultUser implements User {
}

class AnotherClassOfUser implements User {
}

Ben şahsen "I" öneki gibi basit bir nedeni onun isteğe bağlı bir sözleşmeyi sevmiyorum. Bunu benimsersem IIOPConnection, IOPConnection için bir arayüz anlamına mı geliyor? Sınıf "I" önekine sahip değilse, o zaman onun bir arabirim olmadığını biliyor muyum ... burada cevap hayır, çünkü kurallar her zaman takip edilmez ve onları polislik kuralın kendisinin kaydettiği daha fazla iş yaratacaktır.


Bunu seviyorum, çünkü aynı zamanda sınıfları birleştirmek yerine harici bağımlılıklar için arayüzler kullanma moduna geçmenize yardımcı olur.
Matt Briggs

47

Başka bir afişin dediği gibi, genellikle arabirimlerin tür değil yetenekleri tanımlaması tercih edilir. "Kullanıcı" gibi bir şeyi "uygulamama" eğilimindeydim ve bu yüzden "IUser" genellikle burada açıklanan şekilde gerçekten gerekli değildir. Sınıfları sık sık isim ve arayüz olarak sıfat olarak görüyorum:

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

Bazen bir Sıfat mantıklı gelmez, ancak yine de genellikle davranışları, eylemleri, yetenekleri, özellikleri, vb. Türleri modellemek için arayüzler kullanırdım.

Ayrıca, gerçekten sadece bir Kullanıcı yapacak ve Kullanıcı olarak adlandıracak olsaydınız, bir IUser arayüzüne sahip olmanın anlamı nedir? Ortak bir arabirim uygulaması gereken birkaç farklı kullanıcı türüne sahip olacaksanız, arabirime bir "I" eklemek, uygulamaların adlarını seçmenize ne kazandırır?

Bence daha gerçekçi bir örnek, bazı kullanıcıların belirli bir API'ya giriş yapabilmeleri gerektiğidir. Bir Login arayüzü tanımlayabiliriz ve daha sonra SuperUser, DefaultUser, AdminUser, AdministrativeContact, vs suclasses içeren bir "User" üst sınıfına sahip olabiliriz, bunlardan bazıları Login (Loginable?) Arayüzünü gerektiği gibi uygular veya uygulamaz.


Bence "sıfatlar olarak arayüzleri" desteklemek için verdiğiniz örnekler çarpıktır, çünkü bu arayüzler daha çok mix-in (veya özellik) gibi tasarlanmıştır. Böylece, arayüzler hem sıfatlar hem de isimler için iyidir - ama muhtemelen indefinite transitive verbs 13 ^
50'de

Bu son yıllarda değişebilir. Kahin docu. tür olarak arayüzlere izin verir: [link] docs.oracle.com/javase/tutorial/java/IandI/interfaceAsType.html
karlihnos

38

Bob Lee bir sunumda şunları söyledi:

sadece bir uygulamanız varsa bir arabirimin amacı nedir.

yani, tek bir uygulama ile başlarsınız, yani bir arabirim olmadan. daha sonra karar verirseniz, burada bir arayüze ihtiyaç vardır, böylece sınıfınızı bir arayüze dönüştürürsünüz.

o zaman belli olur: orijinal sınıfınıza Kullanıcı adı verildi. arayüzünüz artık Kullanıcı olarak adlandırılmaktadır. belki bir UserProdImpl ve bir UserTestImpl var. uygulamanızı iyi tasarladıysanız, her sınıf (Kullanıcıyı başlatanlar hariç) değişmeyecek ve aniden bir arayüzden geçtiklerini fark etmeyecektir.

böylece netleşir -> Arayüz Kullanıcı uygulaması UserImpl.


18
Arabirimlerin kullanılması, Tahrikli Geliştirmenin Test Edilmesine yardımcı olur. Etki Alanı Modeli ve testlerle ilgili sayısız sorunla karşılaştık çünkü arayüzleri KULLANMAMAYA karar verdik. Bir arkadaşım bir zamanlar alıntı yaptı: "Her şey bir arayüz, sizi uzun vadede kurtaracak."
hooknc

4
Alaycı ve kolay proxy desteği. Eminim arayüz sağlamak için başka nedenler de vardır.
MetroidFan2002

3
Son zamanlarda bir meslektaşım için söylediğim gibi, şimdi bir arayüz tanıtmanın hiçbir maliyeti yoktur, ancak daha sonra size zaman kazandırabilir.
tddmonkey

2
Yakın ortama yakın gelecekte başka uygulamalarınız olabilirse, arayüz bir artı olacaktır.
Stef

3
"Gelecekte başka bir imaja ihtiyacım olabilir" argümanından hoşlanmıyorum. Bir YAGNI yaklaşımını tercih ediyorum: henüz gerçekleşmemiş şeyleri planlamayın.
David Lavender

24

C # 'da

public class AdminForumUser : UserBase, IUser

Java der ki

public class AdminForumUser extends User implements ForumUserInterface

Bu nedenle, arayüzler için java'da sözleşmelerin neredeyse önemli olduğunu düşünmüyorum, çünkü miras ve arayüz uygulaması arasında açık bir fark var. Tutarlı olduğunuz ve insanlara bunların arayüz olduğunu göstermek için bir şey kullandığınız sürece, istediğiniz herhangi bir adlandırma kuralını seçmenizi söyleyebilirim. Birkaç yıl içinde java yapmadım, ancak tüm arayüzler sadece kendi dizinlerinde olacaktı ve kongre buydu. Gerçekten hiçbir sorun yaşamadım.


22
Belki kötü Java kodlayıcıyım, ama C # stilini tercih ediyorum, tüm arayüzlerin 'I' öneki ile başladığı anlamına geliyor :)
davs

7
Siz ve başkalarının bu varsayılan konvansiyonu nereden aldığından emin değilim. Java kütüphanelerinde belli değil ...
ChiefTwoPencils

6

Deneyimlerime göre, "I" kuralı, özellikle arabirimin kendisi sınıfın soyut bir nosyonu değilse, bir sınıfa sözleşme yapmayı amaçlayan arabirimler için geçerlidir.

Örneğin, sizin durumunuzda, sadece IUsersahip olmayı planladığınız tek kullanıcının olup olmadığını görmeyi beklerim User. Farklı kullanıcı türlerine sahip olmayı planlıyorsanız - NoviceUser, ExpertUservb. - Bir Userarayüz görmeyi beklerim (ve belki de AbstractUserbazı ortak işlevleri uygulayan bir sınıf get/setName()).

Ben de yetenekleri tanımlayan arayüzleri beklenebilir - Comparable, Iterablevb - Böyle adlandırılmış değil gibi olmak IComparableya IIterable.


Sahip olmayı düşündüğünüz tek kullanıcı Kullanıcı ise, neden arayüz yerine Kullanıcı'yı kullanmıyorsunuz?
Carighan

3
Bazı istemci / sunucu mimarilerinde, istemci tarafının ağır sunucu uygulamalarına gerek kalmadan arabirimleri bilmesi gerekir.
David Koelle

5

İyi OO prensiplerine uygun olarak, kodunuz (mümkün / mümkün olduğu ölçüde) somut sınıflardan ziyade soyutlamalara bağlı olmalıdır. Örneğin, genellikle böyle bir yöntem yazmak daha iyidir:

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

Bundan daha:

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

Bu fikri izlerseniz, "IUser", "UserInterface" veya diğer varyasyonlar yerine "Kullanıcı" ve "BankAccount" (örneğin) gibi arayüz adları verirseniz kodunuzun daha okunabilir olmasını sağlarım.

Gerçek beton sınıflarına önem vermesi gereken tek kod parçası, beton sınıflarının yapıldığı yerlerdir. Diğer her şey arayüzler kullanılarak yazılmalıdır.

Bunu yaparsanız, "UserImpl" gibi "çirkin" somut sınıf adları, "nice" arabirim adlarını kullanarak nadiren devam edebilen kodun geri kalanından güvenle gizlenmelidir.


Ama neden sadece bir veya iki şey için arayüzlere ihtiyacınız olduğunda, programınızdaki her sınıf için eşleşen bir arayüz oluşturmaya çalışıyorsunuz?
LegendLength

3

= v = "I" öneki, hızlıca alıştığım Wicket çerçevesinde de kullanılıyor. Genel olarak, hantal Java sınıf adlarını kısaltan herhangi bir konvansiyona hoş geldiniz. Bununla birlikte, her şey dizinlerde ve Javadoc'ta "I" altında alfabetik olarak yazılmıştır.

Wicket kodlama uygulaması Swing'e benzer, çünkü birçok kontrol / widget örneği satır içi yöntem bildirimleriyle anonim iç sınıflar olarak inşa edilir. Can sıkıcı bir şekilde Swing'den 180 ° farklıdır, çünkü Swing uygulama sınıfları için bir önek ("J") kullanır.

"Impl" soneki, mantıklı bir kısaltmadır ve iyi uluslararasılaştırılmamıştır. En azından "İmp" ile gitmiş olsaydık, daha şirin (ve daha kısa) olurdu. "Impl" IOC, özellikle Spring için kullanılıyor, bu yüzden şimdilik onunla sıkışıp kaldık. Bununla birlikte, bir kod tabanının üç farklı bölümünde 3 farklı konvansiyonun ardından biraz şizo alır.


0

Bu gerçek anlamda daha geniş bir adlandırma kuralı mı? Daha fazla C ++ tarafındayım ve gerçekten Java ve torunlarında değilim. I kuralını kaç dil topluluğu kullanıyor?

Burada dilden bağımsız bir mağaza standart adlandırma kuralınız varsa onu kullanın. Değilse, dil adlandırma kuralına gidin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.