Üçüncü taraf kitaplıklarını kullanma - her zaman bir sarıcı kullanın?


78

İçinde bulunduğum çoğu proje birkaç açık kaynaklı bileşen kullanıyor. Genel bir ilke olarak, kodun tüm bileşenlerini üçüncü taraf kütüphanelerine bağlamaktan kaçınmak ve bunun yerine değişim acısını önlemek için enkapsüle edici bir sargıdan geçmek iyi bir fikir midir?

Örnek olarak, PHP projelerimizin çoğu doğrudan log4php'i logging çerçevesi olarak kullanıyor, yani \ Logger :: getLogger () yöntemiyle başlatıyorlar, -> info () veya -> warn () yöntemlerini kullanıyorlar. Gelecekte, Ancak, bir şekilde daha iyi olan varsayımsal bir kayıt çerçevesi görünebilir. Olduğu gibi, log4php yöntem imzalarını yakından birleştiren tüm projeler, yeni imzalara uyacak şekilde düzinelerce yerde değişmek zorunda kalacaktı. Bunun elbette kod temeli üzerinde geniş bir etkisi olacaktır ve herhangi bir değişiklik potansiyel bir sorundur.

Bu tür senaryolardan geleceğe yönelik yeni kod tabanları için, günlüğe kaydetme işlevini kapsüllemek ve basit olmasa da kolay hale getirmeyi kolaylaştırarak, günlüğe kaydetmenin en az değişiklikle çalışmasını değiştiren bir sarıcı sınıfını sık sık düşünüyorum (ve bazen de uygular) ; kod sarıcıyı çağırır, sarıcı aramayı günlük çerçeveye du jour'a iletir .

Diğer kütüphanelerle daha karmaşık örnekler olduğunu aklımda tutarak, aşırı mühendislik yapıyorum mu yoksa bu çoğu durumda akıllıca bir önlem midir?

EDIT: Daha fazla dikkat edilmesi gerekenler - bağımlılık enjeksiyonunu ve testini iki katına çıkarmak pratik olarak çoğu API'yi zaten soyutlamamızı gerektiriyor ("Kodumun çalışıp çalışmadığını kontrol etmek istiyorum, ancak bir günlük yorumu yazmak / gerçek bir veritabanına erişmek istemiyorum"). Bu bir karar verici değil mi?


3
log4XYZ çok güçlü bir markadır. API'sı, bağlı bir listenin API'sinin ne zaman geçeceğini değiştirmeyecek Her ikisi de şimdi uzun zamandır çözülmüş bir problemdir.
İş


1
Yalnızca dahili olarak kullanıyorsanız, sararsanız da olmasanız da, bilinen çalışma ile daha sonra olası çalışma arasında bir takas gerçekleştirmeniz yeterlidir. Bir karar çağrısı. Ancak diğer yanıt verenlerin konuşmayı ihmal ettiği görülmüş bir şey, bunun bir API bağımlılığı mı yoksa uygulama bağımlılığı mı olduğudır. Başka bir deyişle, bu üçüncü taraf API’sindeki sınıfları kendi genel API’niz üzerinden sızdırıyor ve kullanıcılara mı açıyorsunuz? Bu durumda, artık farklı bir kütüphaneye taşınmak zor bir iş değil, sorun şu ki kendi API'nizi kırmadan bu mümkün değildir . Bu çok kötü!
Elias Vasylenko

1
Daha fazla referans için: Bu kalıba, harici altyapının (harici lib dediğiniz) bir arayüzün arkasına gizlendiği soğan mimarisi denir
k3b

Yanıtlar:


42

Üçüncü taraf API’sinin yalnızca küçük bir alt kümesini kullanıyorsanız, bir sarmalayıcı yazmak mantıklı olacaktır; bu, büyük bir API’yi kendi kodunuza maruz bırakmamanızdan emin olmanız için, kapsülleme ve bilgi gizlemeye yardımcı olur. Ayrıca, herhangi bir işlevsellik emin yardımcı olabilir yok kullanmak istiyorum "gizli" dir.

Eğer bir sarıcı için bir başka iyi bir neden bekliyoruz üçüncü taraf kitaplığı değiştirmek için. Bu, değişmeyeceğinizi bildiğiniz bir altyapı parçasıysa, bunun için bir sarmalayıcı yazmayın.


İyi noktalar, ancak çok iyi anlaşılan nedenlerden dolayı (test edilmesi zor, refaktöre zor, vb.) Yakından bağlı kodun kötü olduğu öğretildi. Sorunun alternatif bir ifadesi "eğer birleşme kötü ise, neden bir API ile eşleşmek uygundur?"
lotsoffreetime 11:11

7
@lotsoffreetime Bir API'ye bağlanmadan kaçınamazsınız. Bu nedenle, kendi API'nizle birleştirmek daha iyidir. Bu şekilde, kütüphaneyi değiştirebilir ve genellikle sarmalayıcı tarafından sağlanan API'yi değiştirmenize gerek kalmaz.
George Marian

@ george-marian Belirli bir API kullanmaktan kaçınamıyorsam , temas noktalarını kesinlikle en aza indirebilirim. Sorun şu ki, bunu her zaman yapmaya mı çalışmalıyım yoksa aşırıya kaçmak mı?
lotsoffreetime 11:11

2
@lotsoffreetime Bu cevaplaması zor bir soru. Bu amaçla cevabımı genişlettim. (Temel olarak, çok fazla ifs.)
George Marian

2
@lotsoffreetime: Çok fazla boş zamanınız varsa, o zaman ikisini de yapabilirsiniz. Ancak, bu şartlar haricinde bir API sarıcı yazmamaya karşı tavsiye ederim: 1) orijinal API çok düşük seviyededir, bu nedenle belirli projenize daha iyi bir şekilde ihtiyaç duymanız için daha yüksek düzeyde bir API yazarsınız veya 2) kütüphaneleri değiştirmek için yakın bir zamanda, mevcut kütüphaneyi sadece daha iyi bir tane ararken bir basamak taşı olarak kullanıyorsunuz.
Yalan Ryan

28

Gelecekte geliştirilen bu gelişmiş logger'ın sahip olduğu süper harika yeni özelliklerin ne olduğunu bilmeden, ambalajı nasıl yazarsınız? En mantıklı seçim, sarmalayıcınızın bir tür günlükçü sınıfını başlatmasını ve ->info()veya gibi yöntemleri olmasını sağlamaktır ->warn(). Başka bir deyişle, mevcut API'nizle esas olarak aynı.

Asla değiştirmem gerekmeyecek ya da kaçınılmaz bir yeniden yazma gerektirebilecek gelecekteki kanıt kodundan ziyade, "geçmiş kanıt" kodunu tercih ederim. Ben önemli ölçüde bir bileşen değiştiririm nadiren de olsa, bir işte ben son kod ile uyumlu hale getirmek için bir sarmalayıcı yazarken. Bununla birlikte, herhangi bir yeni kod yeni API'yi kullanır ve aynı dosyada herhangi bir değişiklik yaparken veya zamanlama izinleri olarak kullandığımda eski kodu yeniden kullanmam. Birkaç ay sonra, ambalajı çıkarabilirim ve değişiklik kademeli ve sağlamdı.

Başka bir deyişle, paketleyiciler gerçekten yalnızca sarmanız gereken tüm API’leri bildiğiniz zaman anlamlıdır. İyi örnekler, uygulamanızın şu anda birçok farklı veritabanı sürücüsünü, işletim sistemini veya PHP sürümünü desteklemesi gerekiyorsa.


"... sarmalayıcılar gerçekten yalnızca, sarmanız gereken tüm API'leri zaten bildiğinizde anlamlıdır." Paketleyicideki API ile eşleşiyor olsaydım bu doğru olurdu; belki de "kapsülleme" terimini paketleyiciden daha güçlü kullanmalıyım. Bu API çağrılarını "bu yazı ile bir şekilde bu şekilde çağır" yerine "çağrı foo :: log ()" komutunu kullanarak soyutlamak olur.
lotsoffreetime 11:11

"Bu ileri sürülen gelişmiş logger'ın sahip olacağı harika süper özelliklerin ne olduğunu bilmeden, ambalajı nasıl yazarsınız?" @ kevin-cline, daha yeni bir özellik yerine, daha iyi performans gösteren gelecekteki bir kaydediciden bahseder. Bu durumda, sarılacak yeni bir API yok, sadece farklı bir fabrika yöntemi.
lotsoffreetime 11:11

27

Bir üçüncü taraf kütüphanesini sararak, üstüne ek bir soyutlama katmanı eklersiniz. Bunun birkaç avantajı var:

  • Kod tabanınız değişikliklere karşı daha esnek hale gelir

    Kitaplığı başka bir kitapla değiştirmeniz gerekirse, uygulamanızı yalnızca paketleyicinizde - tek bir yerde değiştirmeniz gerekir . Paketleyicinin uygulamasını değiştirebilir ve başka herhangi bir şeyle ilgili bir şeyi değiştirmek zorunda kalmazsınız, başka bir deyişle, gevşek bir şekilde birleştirilmiş bir sisteme sahipsiniz. Aksi halde, kod kodunuzun tamamından geçmeniz ve her yerde değişiklikler yapmanız gerekecektir - ki bu kesinlikle istediğiniz şey değildir.

  • Paketleyicinin API'sini kitaplığın API'sinden bağımsız olarak tanımlayabilirsiniz.

    Farklı kütüphaneler çok farklı API'lere sahip olabilir ve aynı zamanda hiçbiri tam olarak ihtiyaç duyduğunuz şey olmayabilir. Bazı kütüphanelerin her çağrıyla birlikte iletilmek için bir jetona ihtiyacı varsa? İstediğiniz yerde kütüphaneyi kullanmanız gereken yerlerde belirteci geçebilir veya daha merkezi bir yerde güvende tutabilirsiniz, ancak her durumda belirteci kullanabilirsiniz. Sarmalayıcı sınıfınız tüm bunları tekrar basitleştirir - çünkü yalnızca simgeyi sarmalayıcı sınıfınızın içinde tutabilir, uygulamanızın içindeki herhangi bir bileşene asla maruz bırakmaz ve ihtiyaçtan tamamen soyutlayabilirsiniz. İyi API tasarımını vurgulamayan bir kitaplık kullandıysanız büyük bir avantaj.

  • Ünite testi çok daha kolaydır

    Ünite testleri sadece bir şeyi test etmelidir. Bir sınıfı sınamak istiyorsanız, bağımlılıklarını alay etmek zorundasınız. Bu sınıf, ağ çağrıları yapar veya yazılımınızın dışındaki başka bir kaynağa erişirse, bu daha da önemli hale gelir. Üçüncü taraf kütüphanesini satarak bu çağrıları alay etmek ve test verilerini ya da ünite testinin gerektirdiği şeyleri geri vermek kolaydır. Eğer böyle bir soyutlama katmanınız yoksa, bunu yapmak çok daha zor hale gelir - ve çoğu zaman bu çirkin bir kodla sonuçlanır.

  • Gevşek bir şekilde bağlanmış bir sistem yaratıyorsunuz

    Paketleyicinizdeki değişikliklerin, yazılımınızın diğer bölümleri üzerinde hiçbir etkisi yoktur - en azından paketleyicinin davranışını değiştirmediğiniz sürece. Bu sarıcı gibi bir soyutlama katmanı ekleyerek, kitaplığa yapılan çağrıları basitleştirebilir ve uygulamanızın o kitaplığa bağımlılığını neredeyse tamamen kaldırabilirsiniz. Yazılımınız yalnızca ambalajı kullanacak ve ambalajın nasıl uygulandığına ya da ne yaptığını fark etmeyecek.


Pratik Örnek

Dürüst olalım. İnsanlar saatlerce böyle bir şeyin avantajlarını ve dezavantajlarını tartışabilir - bu yüzden size sadece bir örnek göstereyim.

Bir çeşit Android uygulamanız olduğunu ve görüntüleri indirmeniz gerektiğini varsayalım. Orada Picasso veya Universal Image Loader gibi görüntüleri yüklemeyi ve önbelleğe almayı kolaylaştıran bir kütüphane var .

Artık kullanacağımız kütüphaneyi kaydırmak için kullanacağımız bir arayüz tanımlayabiliriz:

public interface ImageService {
    Bitmap load(String url);
}

Bu, görüntü yüklememiz gerektiğinde artık uygulama boyunca kullanabileceğimiz arayüz. Bu arayüzün bir uygulamasını oluşturabilir ve bu uygulamanın bir örneğini kullandığımız her yerde enjekte etmek için bağımlılık enjeksiyonunu kullanabiliriz ImageService.

Picasso'yu kullanmaya karar verdiğimizi varsayalım. Artık ImageServicePicasso’yu dahili olarak kullanan bir uygulama yazabiliriz :

public class PicassoImageService implements ImageService {

    private final Context mContext;

    public PicassoImageService(Context context) {
        mContext = context;
    }

    @Override
    public Bitmap load(String url) {
        return Picasso.with(mContext).load(url).get();
    }
}

Bana sorarsanız oldukça yalındır. Kütüphanelerin etrafındaki sarıcı, yararlı olması için karmaşık olmak zorunda değildir. Arayüz ve uygulama 25'den az birleştirilmiş kod satırına sahiptir, bu yüzden bunu yaratma çabası neredeyse hiç olmadı, ama zaten bunu yaparak bir şey kazandık. ContextUygulamadaki alana bakın mu? Seçtiğiniz bağımlılık enjeksiyon çerçevesi zaten bizim bağımlılığımızı kullanmadan önce bu bağımlılığın enjekte edilmesine dikkat edecektir ImageService, uygulamanızın şimdi resimlerin nasıl indirildiği ve ne gibi bağımlılıkların olabileceği ile ilgilenmek zorunda değildir. Uygulamanızın gördüğü bir ImageServiceşeydir load()ve bir url ile çağırdığı bir görüntüye ihtiyaç duyduğunda - basit ve anlaşılır.

Ancak asıl fayda, şeyleri değiştirmeye başladığımızda gelir. Picasso'yu Universal Image Loader ile değiştirmemiz gerektiğini hayal edin, çünkü Picasso şu anda kesinlikle ihtiyacımız olan bazı özellikleri desteklemiyor. Şimdi bizim kod tabanımızı taramak zorundayız ve ve Picasso'ya yapılan tüm çağrıları sıkıca değiştirip, bir kaç Picasso çağrısını unuttuğumuz için düzinelerce derleme hatasıyla mı uğraşmak zorundayız? Hayır. Yapmamız gereken, bundan ImageServicesonra bu uygulamayı kullanmak için yeni bir uygulama oluşturmak ve bağımlılık enjeksiyon çerçevemize söylemek:

public class UniversalImageLoaderImageService implements ImageService {

    private final ImageLoader mImageLoader;

    public UniversalImageLoaderImageService(Context context) {

        DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .build();

        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
                .defaultDisplayImageOptions(defaultOptions)
                .build();

        mImageLoader = ImageLoader.getInstance();
        mImageLoader.init(config);
    }

    @Override
    public Bitmap load(String url) {
        return mImageLoader.loadImageSync(url);
    }
}

Gördüğünüz gibi uygulama çok farklı olabilir, ancak farketmez. Bizim app başka bir yerde tek bir kod satırını değiştirmek zorunda değildi. Tamamen farklı özelliklere sahip olabilecek ya da çok farklı şekilde kullanılabilecek tamamen farklı bir kütüphane kullanıyoruz ancak bizim uygulamamız umrunda değil. Bizim app geri kalanı sadece aynı yöntemiyle ImageServicearayüzü görür load()ve bu yöntem uygulandığı sürece artık önemli değil.

En azından benim için bu zaten zaten çok güzel ses, ama bekle! Hala daha fazlası var. Üzerinde çalıştığınız bir sınıf için birim testleri yazdığınızı ve bu sınıfın kullandığını düşünün ImageService. Elbette, birim testlerinizin başka bir sunucuda bulunan bazı kaynaklara şebeke araması yapmasına izin veremezsiniz, ancak şimdi kullandığınızdan beri, bir alay uygulayarak birim testleri için kullanılan bir statikin ImageServicekolayca load()geri dönmesine izin verebilirsiniz :BitmapImageService

public class MockImageService implements ImageService {

    private final Bitmap mMockBitmap;

    public MockImageService(Bitmap mockBitmap) {
        mMockBitmap = mockBitmap;
    }

    @Override
    public Bitmap load(String url) {
        return mMockBitmap;
    }
}

Üçüncü taraf kütüphanelerini silerek özetlemek gerekirse, kod tabanınız değişikliklere karşı daha esnek hale gelir, genel olarak daha basit, test edilmesi daha kolay ve yazılımınızdaki farklı bileşenlerin eşleşmesini azaltırsınız - bir yazılımı koruduğunuzda daha da önem kazanan her şey.


1
Bu, aynı zamanda dengesiz bir API için de geçerlidir. Temel kitaplığımız değiştiği için kodumuz 1000 yerde değişmiyor. Çok güzel cevap.
RubberDuck

Çok özlü ve net cevap. Web üzerinde ön uç çalışmaları yapıyorum. O manzaradaki değişikliklerin miktarı delilik. İnsanların değişiklik olmayacağını "düşünmeleri" hiçbir değişiklik olmayacağı anlamına gelmez. YAGNI'dan bahsettim. Yeni bir kısaltma eklemek istiyorum, YDKYAGNI, İhtiyacınız olmayacağını bilmiyorsunuz. Özellikle web ile ilgili uygulamalar. Kural olarak, her zaman yalnızca küçük bir API'yi gösteren kütüphaneleri sararım (select2 gibi). Daha büyük kütüphaneler mimarinizi etkiler ve onları sarmak, mimarinizin değişmesini beklediğiniz anlamına gelir, olabilir, ancak bunu yapması daha az olasıdır.
Byebye

Cevabınız süper yardımcı oldu ve kavramı bir örnekle sunmak, kavramı daha da netleştirdi.
Anil Gorthy

24

Yarın daha iyi bir şey olursa, bugün üçüncü taraf kütüphanelerini silmenin YAGNI'nin çok israf edici bir ihlali olduğunu düşünüyorum. Üçüncü taraf kodunu tekrar tekrar uygulamanıza özgü bir şekilde çağırıyorsanız, tekrarı ortadan kaldırmak için bu çağrıları bir sarma sınıfına geri vermelisiniz (gerekir). Aksi halde kütüphane API'sini tamamen kullanıyorsunuzdur ve herhangi bir sarıcı kütüphane gibi görünecektir.

Şimdi, üstün performans gösteren ya da her neyse yeni bir kütüphanenin ortaya çıktığını varsayalım. İlk durumda, yeni API'nin sarıcısını yeniden yazmanız yeterlidir. Sorun değil.

İkinci durumda, yeni kütüphaneyi sürmek için eski arayüzü uyarlayan bir sarıcı yaratırsınız. Sarmalayıcıyı daha önce yazmış olsaydınız, biraz daha fazla iş, ama sorun olmaz ve yaptığınızdan daha fazla iş olmaz.


4
YAGNI'nin mutlaka bu durumda geçerli olduğunu sanmıyorum. Gelecekte ihtiyaç duymanız gerekebilir diye işlevsellik oluşturma ile ilgili değil. Mimarlığa esneklik kazandırmakla ilgilidir. Bu esneklik gerekli değilse, evet, YAGNI uygulanır. Bununla birlikte, bu belirleme gelecekte değişiklik yapmanın muhtemelen acı verici olacağı durumlarda yapılmaya meyillidir.
George Marian

7
@ George Marian: Sorun zamanın% 95'inde, değişim için hiçbir zaman esnekliğe ihtiyaç duymayacaksınız. Gelecekteki yeni bir kütüphaneye üstün performans göstermesi gerekiyorsa, aramaları değiştirmek / değiştirmek ya da ihtiyacınız olduğunda bir sarıcı yazmak oldukça önemsiz olmalıdır. Öte yandan, eğer yeni kütüphaneniz farklı işlevlerle geliyorsa, sarmalayıcı şimdi bir sorun haline gelir, çünkü şimdi iki probleminiz vardır: yeni kodu kullanmak için eski kodu taşımak ve ambalajı muhafaza etmek.
Yalan Ryan

3
@lotsoffreetime: "İyi tasarım" ın amacı, uygulamanın kullanım ömrü boyunca toplam maliyetini en aza indirmektir. Hayal edilecek gelecekteki değişiklikler için dolaylı katmanlar eklemek çok pahalı bir sigortadır. Hiç kimsenin bu yaklaşımdan tasarruf sağlayacağını görmedim. Sadece müşteriye özel gereksinimlere daha iyi zaman harcayan programcılar için önemsiz bir çalışma yaratır. Müşterinize özel olmayan bir kod yazıyorsanız, çoğu zaman zaman ve para harcıyorsunuzdur.
kevin cline

1
@George: Bu değişiklikler acı verirse, bunun bir süreç kokusu olduğunu düşünüyorum. Java'da, eski sınıflarla aynı adlara sahip yeni sınıflar oluştururdum, ancak farklı bir pakette, eski paket adının tüm oluşumlarını değiştirir ve otomatik sınamaları yeniden başlatırım.
kevin cline

1
@kevin Bu daha fazla iş ve dolayısıyla sargıyı güncellemekten ve testleri yapmaktan daha fazla risk taşıyor.
George Marian

9

Bir üçüncü taraf kütüphanesinin etrafına bir sarmalayıcı yazmanın temel nedeni, bu üçüncü taraf kütüphanesini, kullanılan kodu değiştirmeden değiştirebilmenizdir. Bir şeye eşleştirmekten kaçınamazsınız, bu nedenle argüman yazdığınız bir API ile birleştirmenin daha iyi olacağı anlamına gelir.

Bunun çabaya değip değmeyeceği farklı bir hikaye. Bu tartışma uzun süre devam edecek.

Böyle bir değişimin gerekli olabileceği ihtimalinin düşük olduğu küçük projeler için muhtemelen gereksiz bir çaba söz konusudur. Daha büyük projeler için, bu esneklik kütüphaneyi sarmak için harcanan ekstra çabadan daha ağır basabilir. Ancak, bunun önceden böyle olup olmadığını bilmek zordur.

Buna bakmanın başka bir yolu, değişmesi muhtemel olanı soyutlamanın temel prensibidir. Bu nedenle, üçüncü taraf kütüphanesi iyi kurulmuşsa ve değiştirilmemesi muhtemel ise, kitapların sarılmaması iyi olabilir. Ancak, üçüncü taraf kütüphanesi nispeten yeni ise, değiştirilmesi gerekme ihtimali daha yüksektir. Bununla birlikte, yerleşik kütüphanelerin gelişimi birçok kez terk edilmiştir. Yani, bu cevaplanması kolay bir soru değil.


Bir API alayını enjekte edebilmek için yapılan bir birim testi durumunda, test edilen birimi en aza indirmeye hizmet eder, "potansiyel değiştirme" bir faktör değildir. Bunu söyledikten sonra, bu hala benim düşünceme en yakın olan en sevdiğim cevap. Bob Amca ne derdi? :)
lotsoffreetime 11:11

Ayrıca, küçük projeler (ekip yok, temel özellik vb.), Bunun gibi iyi uygulamaları ihlal edebileceğiniz ve bununla bir dereceye kadar kurtulabileceğiniz kendi kurallarınız vardır. Ama bu farklı bir soru ...
lotsoffreetime

1

@Oded’in daha önce söylediklerine ek olarak , bu cevabı yalnızca özel günlük kaydı amacıyla eklemek istiyorum.


Günlük kaydı için her zaman bir arayüze sahibim ancak log4foohenüz bir çerçeveyi değiştirmek zorunda değildim .

Arayüzü sağlamak ve sargısını yazmak sadece yarım saat sürer, bu yüzden gereksiz olduğu ortaya çıkarsa çok fazla zaman kaybetmezsiniz.

Özel bir YAGNI vakası. İhtiyacım olmasa da fazla zaman almıyor ve kendimi daha güvende hissediyorum. Eğer logger değiş tokuş günü gerçekten gelirse, yarım saat yatırım yaptığım için mutlu olurum çünkü gerçek bir dünya projesinde çağrıları değiş tokuş yapmaktan bir günden fazla tasarruf edeceğim. Ve asla kayıt için bir ünite testi yazmadım veya görmedim (logger uygulamasının kendisi için yapılan testler dışında), bu yüzden sarıcı olmadan hataları bekleyin.


Log4foo'yu değiştirmeyi beklemiyorum, ama yaygın olarak biliniyor ve örnek teşkil ediyor. Bu iki cevabın şimdiye kadar nasıl tamamlayıcı olduğu da ilginç - "her zaman tamamlanma"; "sadece durumunda sarın".
lotsoffreetime 10:11

@Falcon: Her şeyi sarar mısın? ORM, log arayüzü, çekirdek dil sınıfları? Ne de olsa, kimse daha iyi bir HashMap'a ne zaman ihtiyaç duyulacağını asla söyleyemez.
kevin cline

1

Şu anda üzerinde çalışmakta olduğum bir projede bu konuyla uğraşıyorum. Ancak benim durumumda kütüphane grafikler içindir ve bu yüzden, tüm projeye serpiştirmeye karşı grafiklerle uğraşan az sayıdaki sınıfa kullanımını kısıtlayabiliyorum. Böylece gerekmesi halinde API'leri daha sonra değiştirmek oldukça kolay; Bir logger durumunda, konu çok daha karmaşık hale gelir.

Bu yüzden, kararın 3. parti kütüphanesinin tam olarak ne yaptığını ve bunun değiştirilmesinin ne kadar acı verici olacağı ile ilgisi olduğunu söyleyebilirim. Tüm API çağrılarını değiştirmek ne olursa olsun kolay olurdu, o zaman muhtemelen yapmaya değmez. Ancak kütüphaneyi daha sonra değiştirmek gerçekten zor olurdu, o zaman muhtemelen şimdi saracağım.


Bunun ötesinde, diğer cevaplar ana soruyu çok iyi ele almıştı, bu yüzden sadece bağımlılık enjeksiyonu ve alay konusu nesneler üzerine odaklanmak istiyorum. Tabii ki, kayıt çerçevenizin tam olarak nasıl çalıştığına bağlıdır, ancak çoğu durumda hiçbiri sarıcı gerektirmez (muhtemelen birinden faydalanmasına rağmen). Sahte nesnenizin API'sini 3. taraf kütüphanesiyle tamamen aynı yapın ve ardından test etmek için sahte nesnede kolayca geçiş yapabilirsiniz.

Buradaki ana faktör, 3. parti kütüphanenin bağımlılık enjeksiyonuyla (veya bir servis bulucu veya gevşek bir şekilde bağlanmış bazı modellerle) uygulanıp uygulanmadığıdır. Kütüphane işlevlerine tekil veya statik yöntemlerle veya başka bir şeyle erişilirse, bağımlılık enjeksiyonunda çalışabileceğiniz bir nesneyi sarmanız gerekir.


1

Kampı çok zor kullanıyorum ve üçüncü taraf kütüphanesini en büyük önceliğe ikna edemiyorum (bunun bir bonus olmasına rağmen). Kaydırma tercihinde benim temel gerekçem basit

Üçüncü parti kütüphanelerin edilir değil bizim özel ihtiyaçları için tasarlanmış.

Ve bu, genellikle, yalnızca bir tekne yükü kod çoğaltması biçiminde kendini gösterir, geliştiriciler gibi sadece 8 oluşturmak için 8 satırlık bir kod yazıp QButton, uygulamanın arama biçimini, sadece tasarımcının sadece görünüşü istemesini istemesi aynı zamanda, binlerce satır kodun geri yazılmasını ve yeniden yazılmasını gerektiren biten tüm yazılım için düğmelerin işlevselliğini tamamen değiştirmesi ya da bir oluşturma boru hattının modernleştirilmesinin epik bir yeniden yazmayı gerektirdiğini, çünkü kod tabanının düşük seviyeli geçici sabit kaldığını belirlediğini - boru hattı OpenGL kodu, gerçek zamanlı bir işveren tasarımını merkezileştirmek ve OGL'yi kesinlikle kullanımı için kullanmak yerine bırakmak yerine her yere yayıyor.

Bu tasarımlar özel tasarım ihtiyaçlarımıza göre tasarlanmamıştır . Gerçekte neye ihtiyaç duyulduğunun (ve bir tasarımın parçası olmayan, neyin ondan daha önemli olmadığı) büyük bir süperset sunma eğilimindedirler ve ara yüzleri, ihtiyaçlarımızı özel olarak yüksek düzeyde "birine sunmak için tasarlanmamıştır. Düşünce = bir istek "eğer onları doğrudan kullanırsak, bizi tüm merkezi tasarım kontrolünden mahrum bırakan bir tür. Geliştiriciler, ihtiyaç duyduklarını ifade etmek için gerekenden çok daha düşük seviyeli kodlar yazarlarsa, bazen kendilerini geçici bir şekilde sararırlar, bu yüzden onlarca acımasızca yazılmış ve kabaca sonuçlanır. iyi tasarlanmış, iyi belgelenmiş bir tane yerine tasarlanmış ve belgelenmiş ambalajlayıcılar.

Elbette, paketleyicilerin, üçüncü taraf API'lerinin sunduğu şeylerin neredeyse bire bir çevirileri olduğu kütüphanelere güçlü istisnalar uygulardım. Bu durumda, iş ve tasarım gereksinimlerini daha doğrudan ifade eden aranacak daha üst düzey bir tasarım olmayabilir (bu, bir "yardımcı program" kütüphanesine daha çok benzeyen bir şey için geçerli olabilir). Ancak, ihtiyaçlarımızı doğrudan ifade eden çok daha özel bir tasarım varsa, o zaman, daha yüksek seviyeli bir işlev kullanmak ve satır içi montaj kodu üzerinde yeniden kullanmaktan kesinlikle yanayım. her yerde.

İşin garibi, geliştiricilere, bir düğme oluşturma ve onu mikroskobik odaklanmış 8 satırlık bir alt seviye kod yazmayı tercih etme fonksiyonunu tasarlama kabiliyetimiz hakkında çok güvensiz ve çok karamsar göründükleri şekilde çarptım. Söz konusu işlevin tasarlanması ve kullanılmasıyla ilgili düğme oluşturma (gelecekte tekrar tekrar değiştirilmek zorunda kalan) ayrıntıları. Bu türden sarıcıları makul bir şekilde tasarlama konusunda kendimize güvenemezsek, ilk başta hiçbir şey tasarlamaya çalışmamın amacını bile görmüyorum.

Başka bir deyişle, üçüncü taraf kütüphanelerini, tasarım sistemlerinin yerini almanın yerine, uygulamada zamandan tasarruf etme potansiyeli olan yollar olarak görüyorum.


0

Üçüncü Parti Kütüphaneler hakkındaki fikrim:

Meydana gelmiş iOS toplumda son zamanlarda bazı tartışma üçüncü taraf bağımlılıkları kullanmanın artıları ve eksileri (Tamam, çoğunlukla aleyhte) hakkında. Gördüğüm birçok argüman geneldi - tüm üçüncü taraf kütüphaneleri bir sepette gruplandırıyordu. Yine de çoğu şeyde olduğu gibi, o kadar basit değil. Öyleyse, tek bir davaya odaklanmaya çalışalım.

Üçüncü taraf UI kitaplıklarını kullanmaktan kaçınmalı mıyız?

Üçüncü taraf kütüphanelerini göz önünde bulundurma nedenleri:

Geliştiricilerin bir üçüncü taraf kütüphanesini kullanmayı düşünmesinin iki ana nedeni var gibi görünüyor:

  1. Beceri veya bilgi eksikliği. Diyelim ki bir fotoğraf paylaşım uygulaması üzerinde çalışıyorsunuz. Kendi şifrenizi yuvarlayarak başlamazsınız.
  2. Bir şey inşa etmek için zaman ve ilgi eksikliği. Sınırsız bir zamanınız olmadığı sürece (henüz hiçbir insanın sahip olmadığı) öncelik vermek zorundasınız.

Çoğu UI kütüphanesi ( hepsi değil! ) İkinci kategoriye girme eğilimindedir. Bu şey roket bilimi değildir, ancak doğru şekilde inşa etmek zaman alır.

Temel bir iş işlevi ise - ne olursa olsun, kendin yap.

Neredeyse iki tür kontrol / görüş vardır:

  1. Jenerik, hatta örneğin onların yaratıcılarının tarafından düşünmemiştim birçok farklı bağlamlarda bunları kullanmak için izin UICollectionViewdan UIKit.
  2. Spesifik, tek kullanımlık bir kullanım için tasarlanmıştır, örn UIPickerView. Üçüncü taraf kütüphanelerinin çoğu ikinci kategoriye girme eğilimindedir. Dahası, genellikle optimize edilmiş oldukları varolan bir kod tabanından çıkarılırlar.

Bilinmeyen erken varsayımlar

Geliştiricilerin birçoğu, kendi iç kodlarını kod incelemeleri yapar ancak üçüncü taraf kaynak kodunun vereceği kaliteyi alıyor olabilir. Sadece bir kütüphanenin koduna göz atarak biraz zaman harcamakta fayda var. Bazı kırmızı bayraklar gördüğünüzde şaşırmaya başlayabilirsiniz, örneğin ihtiyaç duyulmadığında kullanılan swizzling.

Genellikle fikri öğrenmek, sonuçta elde edilen kodu elde etmekten daha faydalıdır.

Gizleyemezsin

UIKit'in tasarlanma biçimi nedeniyle, muhtemelen bir adaptörün arkasındaki üçüncü taraf UI kitaplığını gizleyemeyeceksiniz. Bir kütüphane UI kodunuzun projenizin fiili bir parçası haline gelmesiyle iç içe geçecektir.

Gelecek zaman maliyeti

UIKit, her iOS sürümüyle birlikte değişir. İşler kopacak. Üçüncü taraf bağımlılığınız beklediğiniz kadar bakım gerektirmez.

Sonuç:

Kişisel deneyimlerime göre, üçüncü taraf UI kodunun çoğu kullanımı bir süre kazanç sağlamak için daha küçük esneklik alışverişine neden oluyor.

Mevcut sürümümüzü daha hızlı göndermek için hazır kod kullanıyoruz. Er ya da geç, yine de, kütüphanenin sınırlarına ulaştık ve zor bir karar vermeden önce durduk: sonra ne yapmalı?


0

Kütüphaneyi doğrudan kullanmak, geliştirici ekibi için daha kolay. Yeni bir geliştirici katıldığında, kullanılan tüm çerçevelerde tam olarak deneyimli olabilir, ancak evde yetiştirilen API'nizi öğrenmeden önce verimli bir şekilde katkıda bulunamayacaktır. Daha genç bir geliştirici grubunuzda ilerlemeye çalıştığında, daha fazla genel jeneriklik kazanmak yerine, belirli API'nizi başka hiçbir yerde bulunmayacağını öğrenmek zorunda kalır. Birisi orijinal API'nin faydalı özelliklerini veya olanaklarını biliyorsa, onlardan haberdar olmayan bir kişi tarafından yazılmış katman üzerinden ulaşamayabilir. Birisi iş ararken bir programlama görevi görecekse, birçok kez kullandığı temel şeyleri gösteremeyebilir, çünkü tüm bu zamanlar sarıcınız üzerinden gerekli işlevselliğe eriştiği için.

Bu sorunların daha sonra tamamen farklı bir kütüphane kullanma konusundaki uzak ihtimalden daha önemli olabileceğini düşünüyorum. Bir sarıcı kullanacağım tek durum, başka bir uygulamaya geçmek için kesinlikle planlanmış olması veya sarılmış API'nin yeterince dondurulmaması ve değişmeye devam etmesidir.

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.