it-swarm.dev

Bibliotheken von Drittanbietern verwenden - immer einen Wrapper verwenden?

Die meisten Projekte, an denen ich beteiligt bin, verwenden mehrere Open-Source-Komponenten. Ist es im Allgemeinen eine gute Idee, immer zu vermeiden, dass alle Komponenten des Codes an die Bibliotheken von Drittanbietern gebunden werden, und stattdessen einen Kapselungs-Wrapper zu verwenden, um den Schmerz der Änderung zu vermeiden?

Zum Beispiel verwenden die meisten unserer PHP -Projekte direkt log4php als Protokollierungsframework, dh sie instanziieren über\Logger :: getLogger (), sie verwenden -> info () oder -> warn ( ) Methoden usw. In Zukunft wird jedoch möglicherweise ein hypothetisches Protokollierungsframework angezeigt, das in gewisser Weise besser ist. So wie es aussieht, müssten sich alle Projekte, die eng mit den Signaturen der log4php-Methode gekoppelt sind, an Dutzenden von Stellen ändern Dies würde offensichtlich einen großen Einfluss auf die Codebasis haben und jede Änderung ist ein potenzielles Problem.

Um zukunftssichere neue Codebasen aus dieser Art von Szenario zu erhalten, betrachte ich häufig eine Wrapper-Klasse (und implementiere sie manchmal), um die Protokollierungsfunktionalität zu kapseln und es einfacher, wenn auch nicht narrensicher, die Art und Weise zu ändern, in der die Protokollierung in Zukunft mit minimalen Änderungen funktioniert ;; Der Code ruft den Wrapper auf, der Wrapper leitet den Aufruf an das Protokollierungsframework weiter du jour.

Wenn ich bedenke, dass es bei anderen Bibliotheken kompliziertere Beispiele gibt, bin ich überentwickelt oder ist dies in den meisten Fällen eine kluge Vorsichtsmaßnahme?

BEARBEITEN: Weitere Überlegungen - Die Verwendung von Abhängigkeitsinjektion und Testdoppel erfordert praktisch, dass wir die meisten APIs ohnehin abstrahieren ("Ich möchte überprüfen, ob mein Code ausgeführt wird und seinen Status aktualisiert, aber keinen Protokollkommentar schreiben/auf eine echte Datenbank zugreifen"). Ist das nicht ein Entscheider?

79
lotsoffreetime

Wenn Sie nur eine kleine Teilmenge der API eines Drittanbieters verwenden, ist es sinnvoll, einen Wrapper zu schreiben. Dies hilft beim Einkapseln und Ausblenden von Informationen und stellt sicher, dass Sie eine möglicherweise große API nicht Ihrem eigenen Code aussetzen. Es kann auch hilfreich sein, um sicherzustellen, dass alle Funktionen, die Sie nicht verwenden möchten, "versteckt" sind.

Ein weiterer guter Grund für einen Wrapper ist, wenn Sie erwarten die Bibliothek eines Drittanbieters ändern. Wenn dies eine Infrastruktur ist, die Sie wissen nicht ändern werden, schreiben Sie keinen Wrapper dafür.

43
Oded

Durch das Umschließen einer Bibliothek eines Drittanbieters fügen Sie eine zusätzliche Abstraktionsebene hinzu. Dies hat einige Vorteile:

  • Ihre Codebasis wird flexibler für Änderungen

    Wenn Sie die Bibliothek jemals durch eine andere ersetzen müssen, müssen Sie nur Ihre Implementierung in Ihrem Wrapper ändern - an einer Stelle. Sie können die Implementierung des Wrappers ändern und müssen nichts anderes ändern. Mit anderen Worten, Sie haben ein lose gekoppeltes System. Andernfalls müssten Sie Ihre gesamte Codebasis durchgehen und überall Änderungen vornehmen - was offensichtlich nicht das ist, was Sie wollen.

  • Sie können die API des Wrappers unabhängig von der API der Bibliothek definieren

    Verschiedene Bibliotheken können sehr unterschiedliche APIs haben und gleichzeitig ist möglicherweise keine von ihnen genau das, was Sie benötigen. Was ist, wenn eine Bibliothek bei jedem Aufruf ein Token benötigt? Sie können das Token in Ihrer App überall dort weitergeben, wo Sie die Bibliothek benötigen, oder Sie können es an einem zentraleren Ort speichern, aber in jedem Fall benötigen Sie das Token. Ihre Wrapper-Klasse macht das Ganze wieder einfach - weil Sie das Token einfach in Ihrer Wrapper-Klasse behalten können, es niemals einer Komponente in Ihrer App aussetzen und die Notwendigkeit dafür vollständig abstrahieren können. Ein großer Vorteil, wenn Sie jemals eine Bibliothek verwendet haben, die kein gutes API-Design hervorhebt.

  • Unit-Tests sind viel einfacher

    Unit-Tests sollten nur eines testen. Wenn Sie eine Klasse einem Unit-Test unterziehen möchten, müssen Sie ihre Abhängigkeiten verspotten. Dies wird noch wichtiger, wenn diese Klasse Netzwerkanrufe tätigt oder auf eine andere Ressource außerhalb Ihrer Software zugreift. Durch das Umschließen der Bibliothek eines Drittanbieters ist es einfach, diese Anrufe zu verspotten und Testdaten oder was auch immer dieser Komponententest erfordert, zurückzugeben. Wenn Sie keine solche Abstraktionsebene haben, wird es viel schwieriger, dies zu tun - und meistens führt dies zu viel hässlichem Code.

  • Sie erstellen ein lose gekoppeltes System

    Änderungen an Ihrem Wrapper haben keine Auswirkungen auf andere Teile Ihrer Software - zumindest solange Sie das Verhalten Ihres Wrappers nicht ändern. Durch die Einführung einer Abstraktionsebene wie diesem Wrapper können Sie Aufrufe an die Bibliothek vereinfachen und die Abhängigkeit Ihrer App von dieser Bibliothek fast vollständig beseitigen. Ihre Software verwendet nur den Wrapper und es macht keinen Unterschied, wie der Wrapper implementiert ist oder wie er das tut, was er tut.


Praktisches Beispiel

Lass uns ehrlich sein. Die Leute können stundenlang über die Vor- und Nachteile von so etwas streiten - deshalb zeige ich Ihnen lieber nur ein Beispiel.

Angenommen, Sie haben eine Art Android App und müssen Bilder herunterladen. Es gibt eine Reihe von Bibliotheken, mit denen das Laden und Zwischenspeichern von Bildern zum Beispiel zum Kinderspiel wird Picasso oder der Universal Image Loader .

Wir können jetzt eine Schnittstelle definieren, die wir verwenden werden, um die Bibliothek zu verpacken, die wir letztendlich verwenden:

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

Dies ist die Oberfläche, die wir jetzt in der gesamten App verwenden können, wenn wir ein Bild laden müssen. Wir können eine Implementierung dieser Schnittstelle erstellen und mithilfe der Abhängigkeitsinjektion eine Instanz dieser Implementierung überall dort einfügen, wo wir den ImageService verwenden.

Nehmen wir an, wir entscheiden uns zunächst für Picasso. Wir können jetzt eine Implementierung für ImageService schreiben, die Picasso intern verwendet:

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();
    }
}

Ziemlich einfach, wenn du mich fragst. Wrapper um Bibliotheken müssen nicht kompliziert sein, um nützlich zu sein. Die Schnittstelle und die Implementierung haben weniger als 25 kombinierte Codezeilen, so dass es kaum ein Aufwand war, dies zu erstellen, aber wir gewinnen bereits etwas dadurch. Siehe das Feld Context in der Implementierung? Das Abhängigkeitsinjektions-Framework Ihrer Wahl kümmert sich bereits um das Injizieren dieser Abhängigkeit, bevor wir unseren ImageService verwenden. Ihre App muss sich jetzt nicht mehr darum kümmern, wie die Bilder heruntergeladen werden und welche Abhängigkeiten die Bibliothek möglicherweise hat. Alles, was Ihre App sieht, ist ein ImageService und wenn sie ein Bild benötigt, ruft sie load() mit einer URL auf - einfach und unkompliziert.

Der wahre Vorteil kommt jedoch, wenn wir anfangen, Dinge zu ändern. Stellen Sie sich vor, wir müssen Picasso jetzt durch Universal Image Loader ersetzen, da Picasso einige Funktionen nicht unterstützt, die wir derzeit unbedingt benötigen. Müssen wir jetzt unsere Codebasis durchkämmen und mühsam alle Aufrufe von Picasso ersetzen und dann Dutzende von Kompilierungsfehlern behandeln, weil wir einige Picasso-Aufrufe vergessen haben? Nr. Alles, was wir tun müssen, ist eine neue Implementierung von ImageService zu erstellen und unser Abhängigkeitsinjektionsframework anzuweisen, diese Implementierung von nun an zu verwenden:

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);
    }
}

Wie Sie sehen, ist die Implementierung möglicherweise sehr unterschiedlich, spielt jedoch keine Rolle. Wir mussten nirgendwo anders in unserer App eine einzige Codezeile ändern. Wir verwenden eine völlig andere Bibliothek, die möglicherweise völlig andere Funktionen hat oder sehr unterschiedlich verwendet wird, aber unsere App kümmert sich einfach nicht darum. Wie zuvor sieht der Rest unserer App nur die Schnittstelle ImageService mit ihrer Methode load(), und diese Methode spielt keine Rolle mehr.

Zumindest für mich klingt das alles schon ziemlich schön, aber warte! Es gibt noch mehr. Stellen Sie sich vor, Sie schreiben Komponententests für eine Klasse, an der Sie arbeiten, und diese Klasse verwendet den Namen ImageService. Natürlich können Sie nicht zulassen, dass Ihre Komponententests Netzwerkaufrufe an eine Ressource auf einem anderen Server senden, aber da Sie jetzt den Namen ImageService verwenden, können Sie load() einfach einen statischen Bitmap zurückgeben lassen, der für die Unit-Tests von verwendet wird Implementierung eines verspotteten ImageService:

public class MockImageService implements ImageService {

    private final Bitmap mMockBitmap;

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

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

Zusammenfassend lässt sich sagen, dass durch das Umschließen von Bibliotheken von Drittanbietern Ihre Codebasis flexibler für Änderungen wird, insgesamt einfacher und einfacher zu testen ist und Sie die Kopplung verschiedener Komponenten in Ihrer Software reduzieren - alles Dinge, die immer wichtiger werden, je länger Sie eine Software warten.

29
Xaver Kapeller

Wie würden Sie den Wrapper schreiben, ohne zu wissen, welche großartigen neuen Funktionen dieser angeblich in Zukunft verbesserte Logger haben wird? Die logischste Wahl ist, dass Ihr Wrapper eine Art Logger-Klasse instanziiert und Methoden wie ->info() oder ->warn() verwendet. Mit anderen Worten, im Wesentlichen identisch mit Ihrer aktuellen API.

Anstatt zukunftssicheren Code, den ich möglicherweise nie ändern muss oder der ohnehin unvermeidbar umgeschrieben werden muss, bevorzuge ich "past-sicheren" Code. Das heißt, in den seltenen Fällen, in denen ich eine Komponente erheblich ändere, das ist, wenn ich einen Wrapper schreibe, um ihn mit früherem Code kompatibel zu machen. Jeder neue Code verwendet jedoch die neue API, und ich überarbeite den alten Code, um ihn zu verwenden, wenn ich ohnehin Änderungen an derselben Datei vornehme oder wenn der Zeitplan dies zulässt. Nach einigen Monaten kann ich den Wrapper entfernen, und die Änderung war schrittweise und robust.

Anders ausgedrückt, Wrapper sind wirklich nur dann sinnvoll, wenn Sie bereits alle APIs kennen, die Sie zum Wrappen benötigen. Gute Beispiele sind, wenn Ihre Anwendung derzeit viele verschiedene Datenbanktreiber, Betriebssysteme oder PHP Versionen) unterstützen muss.

28
Karl Bielefeldt

Ich denke, dass das Verpacken von Bibliotheken von Drittanbietern für den Fall, dass morgen etwas Besseres eintritt, eine sehr verschwenderische Verletzung von YAGNI darstellt. Wenn Sie wiederholt Code von Drittanbietern auf eine für Ihre Anwendung spezifische Weise aufrufen, werden (sollten) Sie diese Aufrufe in eine Wrapping-Klasse umgestalten, um die Wiederholung zu vermeiden. Andernfalls verwenden Sie die Bibliotheks-API vollständig und jeder Wrapper würde genauso aussehen wie die Bibliothek selbst.

Angenommen, eine neue Bibliothek wird mit überlegener Leistung oder was auch immer angezeigt. Im ersten Fall schreiben Sie einfach den Wrapper für die neue API neu. Kein Problem.

Im zweiten Fall erstellen Sie einen Wrapper, der die alte Schnittstelle anpasst, um die neue Bibliothek zu steuern. Ein bisschen mehr Arbeit, aber kein Problem und nicht mehr Arbeit, als Sie getan hätten, wenn Sie den Wrapper früher geschrieben hätten.

24
kevin cline

Der Hauptgrund für das Schreiben eines Wrappers um eine Bibliothek eines Drittanbieters besteht darin, dass Sie diese Bibliothek eines Drittanbieters austauschen können, ohne den Code zu ändern, der sie verwendet. Sie können die Kopplung an etwas nicht vermeiden, daher lautet das Argument, dass es besser ist, an eine von Ihnen geschriebene API zu koppeln.

Ob sich die Mühe lohnt, ist eine andere Geschichte. Diese Debatte wird wahrscheinlich noch lange dauern.

Bei kleinen Projekten, bei denen die Wahrscheinlichkeit, dass eine solche Änderung erforderlich ist, gering ist, ist dies wahrscheinlich ein unnötiger Aufwand. Bei größeren Projekten überwiegt diese Flexibilität möglicherweise den zusätzlichen Aufwand für das Umschließen der Bibliothek. Es ist jedoch schwierig, vorher zu wissen, ob dies der Fall ist.

Eine andere Sichtweise ist das Grundprinzip der Abstraktion dessen, was sich wahrscheinlich ändern wird. Wenn die Bibliothek eines Drittanbieters gut etabliert ist und wahrscheinlich nicht geändert wird, ist es möglicherweise in Ordnung, sie nicht zu verpacken. Wenn die Bibliothek eines Drittanbieters jedoch relativ neu ist, besteht eine größere Wahrscheinlichkeit, dass sie ersetzt werden muss. Die Entwicklung etablierter Bibliotheken wurde jedoch häufig aufgegeben. Diese Frage ist also nicht leicht zu beantworten.

10
George Marian

Ich bin stark im Verpackungslager und nicht in der Lage, die Drittanbieter-Bibliothek mit der größten Priorität zu ersetzen (obwohl dies ein Bonus ist). Mein Hauptgrund, der das Verpacken bevorzugt, ist einfach

Bibliotheken von Drittanbietern sind nicht für unsere spezifischen Anforderungen konzipiert.

Und dies manifestiert sich in der Regel in Form einer Schiffsladung Code-Duplizierung, wie Entwickler, die 8 Codezeilen schreiben, um ein QButton zu erstellen und es so zu gestalten, wie es für die Anwendung aussehen sollte, nur für den Designer Um nicht nur das Aussehen, sondern auch die Funktionalität der Schaltflächen für die gesamte Software vollständig zu ändern, was letztendlich das Zurückgehen und Umschreiben von Tausenden von Codezeilen erfordert, oder um festzustellen, dass für die Modernisierung einer Rendering-Pipeline ein episches Umschreiben erforderlich ist, da die Codebasis niedrig gestreut ist. Ad-hoc-OpenGL-Code mit fester Pipeline überall, anstatt ein Echtzeit-Renderer-Design zu zentralisieren und die Verwendung von OGL ausschließlich für dessen Implementierung zu belassen.

Diese Designs sind nicht auf unsere spezifischen Designanforderungen zugeschnitten . Sie neigen dazu, eine massive Obermenge dessen bereitzustellen, was tatsächlich benötigt wird (und was nicht Teil eines Designs ist, ist genauso wichtig, wenn nicht mehr als das, was ist), und ihre Schnittstellen sind nicht darauf ausgelegt, unsere Anforderungen auf hoher Ebene speziell zu erfüllen Gedanke = eine Anfrage "Art und Weise, die uns jede zentrale Designkontrolle entzieht, wenn wir sie direkt verwenden. Wenn die Entwickler am Ende viel Code auf niedrigerer Ebene schreiben, als erforderlich sein sollte, um das auszudrücken, was sie benötigen, können sie ihn manchmal selbst ad-hoc verpacken, sodass Sie Dutzende von hastig geschriebenen und grob geschriebenen Codes erhalten. entworfene und dokumentierte Wrapper anstelle eines gut gestalteten, gut dokumentierten.

Natürlich würde ich starke Ausnahmen für Bibliotheken anwenden, bei denen die Wrapper fast Eins-zu-Eins-Übersetzungen dessen sind, was die APIs von Drittanbietern zu bieten haben. In diesem Fall ist möglicherweise kein übergeordnetes Design zu suchen, das die Geschäfts- und Designanforderungen direkter ausdrückt (dies könnte bei etwas der Fall sein, das eher einer "Dienstprogramm" -Bibliothek ähnelt). Aber wenn es ein viel maßgeschneiderteres Design gibt, das unsere Bedürfnisse viel direkter ausdrückt, dann bin ich stark im Verpackungslager, genauso wie ich es stark befürworte, eine übergeordnete Funktion zu verwenden und sie gegenüber dem Inlining von Assembly-Code wiederzuverwenden überall.

Seltsamerweise habe ich mich mit Entwicklern in einer Weise gestritten, in der sie so misstrauisch und pessimistisch gegenüber unserer Fähigkeit wirkten, beispielsweise eine Funktion zum Erstellen und Zurückgeben einer Schaltfläche zu entwerfen, dass sie lieber 8 Zeilen Code auf niedrigerer Ebene schreiben, die sich auf Mikroskopie konzentrieren Details zur Erstellung von Schaltflächen (die sich in Zukunft wiederholt ändern mussten) über das Entwerfen und Verwenden dieser Funktion. Ich sehe nicht einmal den Zweck, dass wir überhaupt versuchen, etwas zu entwerfen, wenn wir uns nicht darauf verlassen können, diese Art von Verpackungen auf vernünftige Weise zu entwerfen.

Anders ausgedrückt: Ich sehe Bibliotheken von Drittanbietern als Möglichkeiten, potenziell enorme Zeit bei der Implementierung zu sparen, und nicht als Ersatz für das Entwerfen von Systemen.

2
Dragon Energy

Zusätzlich zu dem, was @ Oded bereits gesagt hat, möchte ich diese Antwort nur für den speziellen Zweck der Protokollierung hinzufügen.


Ich habe immer eine Schnittstelle für die Protokollierung, musste aber noch nie ein log4foo - Framework ersetzen.

Es dauert nur eine halbe Stunde, um die Schnittstelle bereitzustellen und den Wrapper zu schreiben. Ich denke, Sie verschwenden nicht zu viel Zeit, wenn sich herausstellt, dass dies nicht erforderlich ist.

Es ist ein Sonderfall von YAGNI. Obwohl ich es nicht brauche, dauert es nicht lange und ich fühle mich sicherer damit. Wenn der Tag des Austauschs des Loggers wirklich kommt, bin ich froh, dass ich eine halbe Stunde investiert habe, weil ich dadurch mehr als einen Tag beim Austausch von Anrufen in einem realen Projekt sparen kann. Und ich habe noch nie einen Komponententest für die Protokollierung geschrieben oder gesehen (abgesehen von Tests für die Logger-Implementierung selbst). Erwarten Sie also Fehler ohne den Wrapper.

1
Falcon

Ich beschäftige mich genau mit diesem Problem in einem Projekt, an dem ich gerade arbeite. In meinem Fall ist die Bibliothek jedoch für Grafiken gedacht, und daher kann ich ihre Verwendung auf eine kleine Anzahl von Klassen beschränken, die sich mit Grafiken befassen, anstatt sie über das gesamte Projekt zu verteilen. Daher ist es ziemlich einfach, APIs später zu wechseln, wenn ich muss. Im Falle eines Loggers wird die Sache viel komplizierter.

Daher würde ich sagen, dass die Entscheidung viel damit zu tun hat, was genau die Bibliothek eines Drittanbieters tut und wie viel Schmerz mit einer Änderung verbunden wäre. Wenn es einfach wäre, alle API-Aufrufe zu ändern, lohnt es sich wahrscheinlich nicht. Wenn es jedoch sehr schwierig wäre, die Bibliothek später zu ändern, würde ich sie wahrscheinlich jetzt einpacken.


Darüber hinaus haben andere Antworten die Hauptfrage sehr gut abgedeckt, daher möchte ich mich nur auf diesen letzten Zusatz konzentrieren, über Abhängigkeitsinjektion und Scheinobjekte. Es hängt natürlich davon ab, wie genau Ihr Protokollierungsframework funktioniert, aber in den meisten Fällen ist kein Wrapper erforderlich (obwohl es wahrscheinlich von einem profitieren wird). Stellen Sie einfach die API für Ihr Scheinobjekt genauso ein wie für die Bibliothek eines Drittanbieters, und Sie können das Scheinobjekt zum Testen einfach austauschen.

Der Hauptfaktor hierbei ist, ob die Bibliothek eines Drittanbieters überhaupt durch Abhängigkeitsinjektion (oder einen Service Locator oder ein solches lose gekoppeltes Muster) implementiert wird oder nicht. Wenn auf die Bibliotheksfunktionen über ein Singleton oder statische Methoden oder etwas anderes zugegriffen wird, müssen Sie dies in ein Objekt einschließen, mit dem Sie bei der Abhängigkeitsinjektion arbeiten können.

1
jhocking

Meine Idee zu Bibliotheken von Drittanbietern :

Es gab einige Diskussionen kürzlich in der iOS-Community über Vor- und Nachteile (OK, meistens Nachteile) der Verwendung von Abhängigkeiten von Drittanbietern. Viele Argumente, die ich sah, waren eher allgemein gehalten - alle Bibliotheken von Drittanbietern wurden in einem Korb zusammengefasst. Wie bei den meisten Dingen ist es jedoch nicht so einfach. Versuchen wir also, uns auf einen einzelnen Fall zu konzentrieren

Sollten wir die Verwendung von UI-Bibliotheken von Drittanbietern vermeiden?

Gründe für die Berücksichtigung von Bibliotheken von Drittanbietern:

Es scheint zwei Hauptgründe zu geben, warum Entwickler die Verwendung einer Bibliothek eines Drittanbieters in Betracht ziehen:

  1. Mangel an Fähigkeiten oder Kenntnissen. Angenommen, Sie arbeiten an einer Foto-Sharing-App. Sie beginnen nicht damit, Ihre eigene Krypto zu rollen.
  2. Mangel an Zeit oder Interesse, um etwas zu bauen. Wenn Sie nicht über eine unbegrenzte Zeit verfügen (die noch kein Mensch hat), müssen Sie Prioritäten setzen.

Die meisten UI-Bibliotheken ( nicht alle! ) fallen in die zweite Kategorie. Dieses Zeug ist keine Raketenwissenschaft, aber es braucht Zeit, um es richtig zu bauen.

Wenn es sich um eine Kerngeschäftsfunktion handelt - machen Sie es selbst, egal was es ist.

Es gibt so ziemlich zwei Arten von Steuerelementen/Ansichten:

  1. Allgemein, ermöglicht es Ihnen, sie in vielen verschiedenen Kontexten zu verwenden, an die ihre Schöpfer nicht einmal gedacht haben, z. UICollectionView von UIKit.
  2. Spezifisch, für einen einzelnen Anwendungsfall, z. UIPickerView. Die meisten Bibliotheken von Drittanbietern fallen in die zweite Kategorie. Darüber hinaus werden sie häufig aus einer vorhandenen Codebasis extrahiert, für die sie optimiert wurden.

Unbekannte frühe Annahmen

Viele Entwickler führen Codeüberprüfungen ihres internen Codes durch, halten jedoch möglicherweise die Qualität des Quellcodes von Drittanbietern für selbstverständlich. Es lohnt sich, ein wenig Zeit damit zu verbringen, nur den Code einer Bibliothek zu durchsuchen. Sie werden möglicherweise überrascht sein, einige rote Fahnen zu sehen, z. Swizzling wird dort eingesetzt, wo es nicht benötigt wird.

Oft ist das Erlernen der Idee vorteilhafter als das Erhalten des resultierenden Codes selbst.

Du kannst es nicht verstecken

Aufgrund der Art und Weise, wie UIKit entworfen wurde, können Sie die UI-Bibliothek eines Drittanbieters, z. hinter einem Adapter. Eine Bibliothek wird mit Ihrem UI-Code verflochten und wird de facto zu Ihrem Projekt.

Zukünftige Zeitkosten

UIKit ändert sich mit jeder iOS-Version. Die Dinge werden brechen. Ihre Abhängigkeit von Drittanbietern ist nicht so wartungsfrei, wie Sie es vielleicht erwarten.

Schlussfolgerung:

Nach meiner persönlichen Erfahrung beschränken sich die meisten Verwendungen von UI-Code von Drittanbietern darauf, eine geringere Flexibilität gegen einen gewissen Zeitgewinn auszutauschen.

Wir verwenden vorgefertigten Code, um unsere aktuelle Version schneller zu versenden. Früher oder später stoßen wir jedoch an die Grenzen der Bibliothek und stehen vor einer schwierigen Entscheidung: Was tun als nächstes?

0
Mukesh

Die direkte Verwendung der Bibliothek ist für das Entwicklerteam freundlicher. Wenn ein neuer Entwickler beitritt, ist er möglicherweise mit allen verwendeten Frameworks vertraut, kann jedoch vor dem Erlernen Ihrer selbst erstellten API keinen produktiven Beitrag leisten. Wenn ein jüngerer Entwickler versucht, in Ihrer Gruppe Fortschritte zu erzielen, muss er lernen, dass Ihre spezifische API nirgendwo anders vorhanden ist, anstatt sich eine nützlichere generische Kompetenz anzueignen. Wenn jemand nützliche Funktionen oder Möglichkeiten der ursprünglichen API kennt, kann er möglicherweise nicht über die Ebene greifen, die von jemandem geschrieben wurde, der sie nicht kannte. Wenn jemand auf der Suche nach einem Job eine Programmieraufgabe erhält, kann er möglicherweise nicht die grundlegenden Dinge demonstrieren, die er oft verwendet hat, nur weil er all diese Male über Ihren Wrapper auf die erforderlichen Funktionen zugegriffen hat.

Ich denke, diese Probleme sind möglicherweise wichtiger als die entfernte Möglichkeit, später eine völlig andere Bibliothek zu verwenden. Der einzige Fall, in dem ich einen Wrapper verwenden würde, ist, wenn die Migration zu einer anderen Implementierung definitiv geplant ist oder die umschlossene API nicht ausreichend eingefroren ist und sich ständig ändert.

0
h22