it-swarm.asia

Java) arayüzleri uygularken varsayılan vs Impl

Okuduktan sonra Paket isimleri tekil mi yoksa çoğul mu olmalı? Bana hiç evcil hayvanımın üzerlerinden birini kapsayan uygun bir tartışma görmedim: arayüzlerin uygulamalarının adlandırılması.

Diyelim ki çeşitli şekillerde uygulanması amaçlanan bir arabiriminiz Order var, ancak proje ilk oluşturulduğunda yalnızca ilk uygulama var. Yanlış ikilikten kaçınmak için DefaultOrder veya OrderImpl veya başka bir varyanta mı gidiyorsunuz? Ve daha fazla uygulama ortaya çıktığında ne yaparsınız?

Ve en önemlisi ... neden?

35
Gary Rowe

İsimlerin anlamı aktarma fırsatı vardır. Neden bu fırsatı Impl ile atmalısınız?

Her şeyden önce, sadece bir uygulamanız olacaksa, arabirimden uzaklaşın. Bu adlandırma sorununu yaratır ve hiçbir şey eklemez. Daha da kötüsü, siz ve diğer tüm geliştiriciler her zaman yalnızca arabirimi kullanmaya dikkat etmezseniz API'lardaki tutarsız yöntem imzalarında sorunlara neden olabilir.

Bununla birlikte, her arayüzün vardır veya olabilir iki veya daha fazla uygulama olduğunu varsayabiliriz.

  • Şu anda yalnızca bir taneniz varsa ve diğerinin farklı olabileceğini bilmiyorsanız, Varsayılan iyi bir başlangıçtır.

  • Şu anda iki tane varsa, her birini amacına göre adlandırın.

    Örnek: Son zamanlarda somut bir sınıfımız vardı Bağlam (bir veritabanına referansla). Çevrimdışı olan bir bağlamı temsil edebilmemiz gerektiği anlaşıldı, bu nedenle Context adının yeni bir arayüz için (eski API'ler için uyumluluğu korumak için) kullanıldığı ve yeni bir uygulama oluşturulduğu, OfflineContext . Ama bilin bakalım orijinalin adı ne? Bu doğru, ContextImpl (yikes).

    Bu durumda, DefaultContext muhtemelen iyi olurdu ve insanlar anlayacaktı, ancak olabildiğince açıklayıcı değil. Sonuçta, çevrimdışı değilse, nedir? Biz de gittik: OnlineContext .


Özel durum: Arabirimlerde "I" önekinin kullanılması

diğer cevaplar arabirimlerinden biri, arabirimlerde I önekinin kullanılmasını önerdi. Tercihen, bunu yapmak için gerek yok.

Bununla birlikte, özel uygulamalar için hem bir arayüze ihtiyacınız varsa, hem de sık kullanılan bir birincil somut uygulamanız ve sadece bir arayüzden vazgeçmek çok basit, o zaman arayüze "I" eklemeyi düşünebilirsiniz (yine de, sizin ve ekibiniz için hala doğru değilse tamamen iyidir).

Örnek: Birçok nesne bir "EventDispatcher" olabilir. API'ler açısından bunun bir arayüzle uyumlu olması gerekir. Ancak, temsilci seçme için bir basic olay dağıtıcısı da sağlamak istersiniz. DefaultEventDispatcher iyi olurdu, ancak biraz uzun ve sık sık adını görecekseniz, olabilir somut sınıf için temel adı EventDispatcher kullanmayı ve IEventDispatcher özel uygulamalar için:

/* Option 1, traditional verbose naming: */
interface EventDispatcher { /* interface for all event dispatchers */ }
class DefaultEventDispatcher implements EventDispatcher {
  /* default event dispatcher */
}

/* Option 2, "I" abbreviation because "EventDispatcher" will be a common default: */
interface IEventDispatcher { /* interface for all event dispatchers */ }
class EventDispatcher implements IEventDispatcher {
  /* default event dispatcher. */
}
60
Nicole

Adlandırmaya arayüzün kullanım durumuna göre karar veririm.

Arabirim ayırma için kullanılıyorsa, uygulamalar için Impl seçerim.

Arayüzün amacı davranışsal soyutlama ise, uygulamalar somut olarak yaptıklarına göre adlandırılır. Arayüz adını sık sık buna ekliyorum. Arayüz Validator olarak adlandırılırsa, FooValidator kullanırım.

Default çok kötü bir seçim. İlk olarak kod tamamlama özelliklerini kirletir, çünkü isimler her zaman onunla başlar. Diğer bir şey, bir varsayılanın zaman içinde değişebilmesidir. Dolayısıyla, varsayılan olarak ilk olabilecek şey, kullanımdan kaldırılan bir özellikten bir süre sonra olabilir. Yani ya varsayılanlar değişir değişmez sınıflarınızı her zaman yeniden adlandırmaya başlarsınız ya da yanıltıcı isimlerle yaşarsınız.

15
SpaceTrucker

Nicole'ün cevabına katılıyorum (özellikle arayüz muhtemelen çoğu durumda gerekli değildir), ancak tartışma amacıyla OrderImpl ve DefaultOrder dışında bir alternatif daha atacağım: uygulamayı Orders.create() gibi statik bir fabrika yönteminin arkasına gizleyin. Örneğin:

public final class Orders {
  public static Order create() {
    return new Order() {
      // Implementation goes here.
    };
  }
}

Bu yaklaşımla, uygulama anonim bir iç sınıf olabilir veya adında Default veya Impl olan özel bir sınıf olabilir veya tamamen başka bir şey olarak adlandırılabilir. Hangi seçim yapılırsa, arayanın ilgilenmesi gerekmez, bu yüzden şimdi ve daha sonra değiştirmeye karar verdiğinizde/değiştirdiğinizde daha fazla esneklik elde edersiniz.

Pratikte bu modelin bazı harika örnekleri Java.util.Collections ve Java.util.concurrent.Executors yöntemleri gizli uygulamaları döndüren yardımcı sınıflar. Etkili Java (maddede 1)) bahsedildiği gibi, bu model API'nın "Kavramsal ağırlığı" nı daha küçük tutmaya yardımcı olabilir.

8
Andrew McNamee

Her zaman OrderImpl için gidiyorum çünkü sadece Order arayüzünden hemen sonra alfabetik olarak görünüyor.

3
Ben Hoffstein

Varsayılan'ın bazı durumlarda mantıklı olabilmesine rağmen, uygulamayı tanımlamanın daha yararlı olacağını düşünüyorum. Arayüzünüz UserProfileDAO ise, uygulamalarınız UserProfileSQLDAO veya UserProfileLDAPDAO veya bunun gibi bir şey olabilir.

1
jiggy

mümkünse, ne yaptığını/nasıl yaptığını isimlendirin.

genellikle en kötü yaklaşım, nasıl kullanılması gerektiğinin isimlendirilmesidir.

Uygulama için temel sınıf olarak kullanılması gerekiyorsa, BaseX veya AbstractX'i kullanabilirsiniz (soyutsa (ancak yaptığı şeyde squeze etmeye çalışın, çünkü eğer bir şey yapmazsanız, yaratmayacaksınız, zaten Mümkün olan en basit işlevselliği sağlıyorsa ve bu işlevsellik yeterli olduğunda doğrudan kullanılması (genişletilmemesi) bekleniyorsa, bunu SimpleX veya BasicX olarak adlandırabilirsiniz.

Başka bir uygulama sağlanmadıkça kullanılırsa, DefaultX olarak adlandırın.

0
user470365

Sınıf hakkında arayüzden daha somut veya spesifik olanı anlamaya çalışın ve bunu isme dahil edin.

Kalıcı veri için bir arayüzünüz olduğunu varsayalım, Foodao. Kalıcılık düz bir dosyaya, bir XML belgesine, bir elektronik tabloya, bir ilişkisel veritabanına, ilişkisel olmayan bir veritabanına vb. Olabilir. Sınıf herhangi bir SQL veritabanına veri devam ediyorsa FooSql Foodao uygular.

İlişkisel veritabanı satıcısına özgü kodunuz varsa, FooMssql, FooOracle veya FooDb2'yi deneyin. Ya da, belki FoodaoMssql veya FoodaoPostgre amaçlarınıza daha uygun olabilir.

Mesele şu ki, sadece benzersiz bir tanımlayıcı oluşturma amacına hizmet eden harfleri eklemeyin; isme daha anlamlı bir şey vermeye çalışın. Bunun iki iyi etkisi var. Yalnızca bir uygulayıcı sınıfınız olsa bile, bir sonraki geliştiriciye daha fazla anlam kazandırır. Yalnızca bir uygulayıcı sınıfla başlasanız bile, kendinizi başka bir uygulamaya ihtiyaç duyduğunuzda bulursanız, kendinizi ..Impl ve ..Impl2 veya ..Impl ve ..Mongo gibi adlarla bulamazsınız.

0
Chris Golledge

Arabirimi I (IWhatever) önekiyle adlandırabilir ve sonra Whatever uygulayabilirsiniz.

Resmi Java kod kuralları arabirimler için bu tür adlandırma hakkında bilgi vermez, ancak bu tür adlandırma tanıma ve gezinmeye yardımcı olur.

0
user1449