Hazırda Bekletme nedir? Hibernate Core uygulamasının temelleri
Yayınlanan: 2013-04-17Hazırda Bekletme, açık kaynaklı bir Java kalıcılık çerçevesi projesidir. HQL ve SQL kullanarak güçlü nesne ilişkisel eşleme ve sorgu veritabanları gerçekleştirin.
Genel olarak, yaygın olarak kullanılan kitaplıklar iyi tasarlanmış ve uygulanmıştır ve onlardan bazı en iyi kodlama uygulamalarını öğrenmek çok ilginçtir.
Hazırda bekletme çekirdek kitaplığının içine bir göz atalım ve bazı tasarım anahtarlarını keşfedelim.
Bu yazıda Hibernate Core, JArchitect
tarafından tasarımının ve uygulanmasının derinliklerine inmek için analiz ediliyor.
Özelliğe Göre Paket
Package-by-feature
paket, özellik kümesini yansıtmak için paketleri kullanır. Tek bir özellikle (ve yalnızca o özellikle) ilgili tüm öğeleri tek bir dizine/pakete yerleştirir. Bu, yüksek kohezyona ve yüksek modülerliğe ve paketler arasında minimum bağlantıya sahip paketlerle sonuçlanır. Birbirine yakın çalışan öğeler yan yana yerleştirilir.
Hazırda bekletme çekirdeği, her biri belirli bir özellik hql, sql ve diğerleri ile ilgili birçok paket içerir.
kaplin
Düşük bağlantı arzu edilir, çünkü bir uygulamanın bir alanındaki bir değişiklik, tüm uygulama boyunca daha az değişiklik gerektirecektir. Uzun vadede bu, bir uygulamaya yeni özellikler eklemek ve değiştirmekle ilişkili çok fazla zaman, çaba ve maliyeti azaltabilir.
Arayüzlerin kullanılmasından elde edilen üç temel fayda şunlardır:
- Bir arayüz, yeniden kullanımı teşvik eden bir sözleşmeyi tanımlamanın bir yolunu sağlar. Bir nesne bir arabirim uygularsa, o nesne bir standarda uymak zorundadır. Başka bir nesneyi kullanan bir nesneye tüketici denir. Arayüz, bir nesne ile tüketicisi arasındaki bir sözleşmedir.
- Arayüz ayrıca programların anlaşılmasını kolaylaştıran bir soyutlama düzeyi sağlar. Arayüzler, geliştiricilerin çok sayıda ayrıntılı ayrıntıya girmek zorunda kalmadan kodun genel davranışı hakkında konuşmaya başlamalarını sağlar.
- Bir arabirim, bileşenler arasında düşük bağlantıyı zorunlu kılar; arabirim tüketicisini arabirimleri uygulayan sınıflardaki herhangi bir uygulama değişikliğinden korumayı kolaylaştıran şey.
Hazırda Bekletme Çekirdeği tarafından tanımlanan tüm arayüzleri arayalım, bunun için kod tabanını sorgulamak için CQLinq
kullanıyoruz.
1 |
from t in Types where t . IsInterface select t |
Birincil hedefimiz düşük eşleşmeyi zorlamaksa, arayüzleri kullanırken, onları kullanmanın faydasını öldürebilecek yaygın bir hata vardır. Arayüzler yerine somut sınıfların kullanılmasıdır ve bu sorunu daha iyi açıklamak için aşağıdaki örneği ele alalım:
A sınıfı, hesap() yöntemini içeren Arabirim IA'yı uygular, tüketici sınıfı C bu şekilde uygulanır.
1 2 3 4 5 6 7 8 9 10 11 |
public class C < br > { … . public void calculate ( ) { … . . m_a . calculate ( ) ; … . } A m_a ; } |
IA arayüzüne atıfta bulunmak yerine C Sınıfı, A sınıfına atıfta bulunur, bu durumda düşük bağlantı avantajını kaybederiz ve bu uygulamanın iki önemli dezavantajı vardır:
- IA'nın başka bir uygulamasını kullanmaya karar verirsek, C sınıfının kodunu değiştirmeliyiz.
- A'ya IA'da mevcut olmayan bazı yöntemler eklenirse ve C bunları kullanırsa, arabirimleri kullanmanın sözleşme avantajını da kaybederiz.
C#, IA'dan gelen bir yöntemin hiçbir zaman somut sınıflara bir başvurudan değil, yalnızca arayüze bir başvurudan çağrılmasını sağlamak için dile açık arabirim uygulama yeteneğini tanıttı. Bu teknik, geliştiricilerin arayüz kullanmanın avantajını kaybetmesini önlemek için çok kullanışlıdır.
JArchitect ile bu tür hataları CQLinq
kullanarak kontrol edebiliriz, fikir, diğer yöntemlerle doğrudan kullanılan somut sınıflardan tüm yöntemleri aramaktır.
1 2 3 4 5 6 7 8 9 |
from m in Methods where m . NbMethodsCallingMe > 0 && m . ParentType . IsClass && ! m . ParentType . IsThirdParty && ! m . ParentType . IsAbstract let interfaces = m . ParentType . InterfacesImplemented from i in interfaces where i . Methods . Where ( a = > a . Name == m . Name && a . ParentType ! = m . ParentType ) . Count ( ) > 0 select new { m , m . ParentType , i } |
Örneğin SessionFactoryImpl'den SessionFactoryImplementor arabirimini uygulayan getEntityPersister yöntemi bu sorunla ilgilidir.
Doğrudan SessionFactoryImpl.getEntityPersister'ı çağıran yöntemleri arayalım.
1 2 3 |
from m in Methods where m . IsUsing ( "org.hibernate.internal.SessionFactoryImpl.getEntityPersister(String)" ) select new { m , m . NbBCInstructions } |

SessionImpl.instantiate gibi yöntemler, arabirimden geçmek yerine doğrudan getEntityPersister'ı çağırır; bu, arabirim kullanmanın avantajını bozar. Neyse ki hazırda bekletme çekirdeği, bu sorunu yaşayan pek çok yöntem içermiyor.
Harici kavanozlarla bağlantı
Harici lib'ler kullanıldığında, tüm uygulamayı etkilemeden üçüncü taraf lib'i başka bir kişiyle kolayca değiştirip değiştiremeyeceğimizi kontrol etmek daha iyidir, bizi üçüncü taraf lib'i değiştirmeye teşvik edebilecek birçok neden vardır.
Diğer lib şunları yapabilir:
- Daha fazla özelliğe sahip olun
- Daha güçlü
- Daha güvenli
Hql sorgularını ayrıştırmak için kullanılan antlr lib
örneğini ele alalım ve antlr'den daha güçlü başka bir ayrıştırıcının yaratıldığını hayal edelim, yeni ayrıştırıcı ile antlr'yi kolayca değiştirebilir miyiz?
Bu soruyu cevaplamak için, hazırda bekletme modundan hangi yöntemlerin doğrudan kullandığını araştıralım:
1 2 3 |
from m in Methods where m . IsUsing ( "antlr-2.7.7" ) select new { m , m . NbBCInstructions } |
Ve hangileri dolaylı olarak kullandı:
1 2 3 4 |
from m in Projects . WithNameNotIn ( "antlr-2.7.7" ) . ChildMethods ( ) let depth0 = m . DepthOfIsUsing ( "antlr-2.7.7" ) where depth0 > 1 orderby depth0 select new { m , depth0 } |
Birçok yöntem, hazırda bekletme çekirdeğini onunla yüksek oranda eşleştiren doğrudan antlr'yi kullanır ve antlr'yi bir başkasıyla değiştirmek kolay bir iş değildir. bu gerçek, hazırda bekletme tasarımında bir sorunumuz olduğu anlamına gelmez, ancak üçüncü taraf lib kullanırken dikkatli olmalıyız ve üçüncü taraf lib'in uygulama ile düşük düzeyde eşleştirilmiş olup olmadığını iyi kontrol etmeliyiz.
uyum
Tek sorumluluk ilkesi, bir sınıfın değişmek için bir ve yalnızca bir nedeni olması gerektiğini belirtir. Böyle bir sınıfın uyumlu olduğu söylenir. Yüksek bir LCOM
değeri genellikle zayıf bir şekilde uyumlu bir sınıfı belirler. Birkaç LCOM metriği vardır. LCOM, değerlerini [0-1] aralığında alır. LCOMHS (HS, Henderson-Sellers anlamına gelir) değerlerini [0-2] aralığında alır. LCOMHS metriğinin genellikle uyumlu olmayan türleri algılamak için daha verimli olarak kabul edildiğini unutmayın.
1'den yüksek LCOMHS değeri endişe verici olarak değerlendirilmelidir.
Genel olarak, uyumla daha çok ilgilenen sınıflar, birçok yöntem ve alana sahip sınıflardır.
Bir çok metoda ve alana sahip tipler arayalım.
1 2 3 4 |
from t in Types where ( t . Methods . Count ( ) > 40 | | t . Fields . Count ( ) > 40 ) && t . IsClass orderby t . Methods . Count ( ) descending select new { t , t . InstanceMethods , t . Fields , t . LCOMHS } |
Bu sorguyla yalnızca birkaç tür ilgilenir ve hepsi için LCOMHS 1'den küçüktür.
Ek Açıklamaları Kullanma
Açıklama tabanlı geliştirme, Java geliştiricilerini hantal yapılandırmanın acısından kurtarır. Ve kaynak kodunu standart koddan kurtarmamız için bize güçlü bir özellik verin. Ortaya çıkan kodun ayrıca hata içerme olasılığı daha düşüktür.
Hazırda bekletme çekirdeği tarafından tanımlanan tüm açıklamaları arayalım.
1 |
from t in Types where t . IsAnnotationClass && ! t . IsThirdParty select t |
Hazırda bekletme modunu geliştiriciler tarafından kullanımı kolaylaştıran birçok açıklama tanımlanmıştır ve yapılandırma dosyalarının baş ağrısından kaçınılmıştır.
Çözüm
Hibernate Core, öğrenmek için açık kaynak projelerine iyi bir örnektir, içine bir göz atmaktan çekinmeyin.