Bei der Entwicklung von Software habe ich häufig eine zentralisierte 'Kern'-Bibliothek mit handlichem Code, der von verschiedenen Projekten gemeinsam genutzt und referenziert werden kann.
Beispiele:
- eine Reihe von Funktionen zum Bearbeiten von Zeichenfolgen
- häufig verwendete reguläre Ausdrücke
- allgemeiner Bereitstellungscode
Einige meiner Kollegen scheinen sich jedoch von diesem Ansatz abzuwenden. Sie haben Bedenken wie den Wartungsaufwand für das erneute Testen von Code, der von vielen Projekten verwendet wird, sobald ein Fehler behoben ist. Jetzt überlege ich, wann ich das tun soll.
Was sind die Probleme, die die Verwendung einer "Kern" -Bibliothek zu einer schlechten Idee machen?
code-reuse
libraries
Alex Angas
quelle
quelle
Antworten:
Kernbibliotheken sind schlecht, wenn sie unter Feature Creep leiden, und sehr schlecht, wenn sie nicht gut gewartet werden.
Vielleicht finden Sie diesen Artikel für einen erweiterten Standpunkt interessant (dem ich voll und ganz zustimme):
http://www.yosefk.com/blog/redundancy-vs-dependencies-which-is-worse.html
Don Knuth: "Für mich ist 'wiederbearbeitbarer Code' viel, viel besser als eine unberührbare Black Box oder ein Toolkit ... Sie werden mich nie davon überzeugen, dass wiederverwendbarer Code keine Bedrohung darstellt."
quelle
Wenn Sie die Idee verwenden, dass eine Kernbibliothek schlecht ist, wenn mehrere Projekte davon abhängen, sollten Sie jQuery nicht für das Web, libxml in Ihren * nix-Apps oder einem anderen Framework oder einer anderen Bibliothek verwenden. Betrachten Sie das gesamte Ökosystem der modernen Entwicklung (DRY, OOP usw.) und jede einzelne App besteht aus einer Reihe von Bibliotheken und Frameworks.
Was schlecht sein kann, ist, wenn Sie keine Art von Unit-Tests haben, keinen Regressionstest und keine Art von API / ABI für Ihre Bibliothek verwenden. Wenn alle Ihre Anwendungen ordnungsgemäß getestet wurden, verfügt Ihre Bibliothek über ordnungsgemäße Tests, und Sie stellen sicher, dass Sie die API-Versionsnummer entsprechend aktualisieren, wenn Sie Funktionsaufrufe unterbrechen.
Für eine vollständige Abdeckung möchten Sie wahrscheinlich, wenn Änderungen an der Bibliothek vorgenommen werden, eine Reihe von Tests ausführen, die sicherstellen, dass die API nicht beschädigt wurde und dass die Ausführung des gesamten Codes fehlerfrei ist. Anschließend können Sie das neueste Bibliotheksupdate in Ihre Anwendung einfügen und dieselben Tests ausführen. Wenn Sie die API aktualisieren, sollte sie dokumentiert werden, damit Sie wissen, was Sie in Ihrer Anwendung tun müssen, um sie zu aktualisieren. In beiden Fällen können Sie beim Ausführen der Tests für Ihre Anwendung genauso sicher sein wie bei Ihren Tests, dass nichts kaputt gegangen ist.
Wenn Sie jquery, mootools oder eine andere Javascript-Bibliothek oder ein anderes Javascript-Framework verwenden, können Sie die neue Version nicht einfach blind verwenden. Leider können Sie dies manchmal nicht einmal mit einer kleineren Version 1.6.z tun.
quelle
Wenn Sie über umfassende Komponententests für die Kernbibliothek verfügen; das ist kein Problem. Es wird kein Code eingecheckt, es sei denn, alle Tests bestehen. Wenn Sie einen Fehler einführen, schreiben Sie einen Fehlertest, um den Fehler zu reproduzieren und zu beheben. Dann werden Sie auch immer auf diesen Fehler testen. Für immer.
Auch die von Ihnen beschriebene Funktionalität ist sehr einfach zu schreiben.
Als Nebenproblem möchten Sie möglicherweise mehr als eine Kernbibliothek haben, sodass Sie den RegEx-Code nicht einschließen müssen, es sei denn, Sie möchten.
quelle
Ich werde dies etwas anders angehen. Eine Kernbibliothek ist in vielen Fällen eine hervorragende Idee!
Wenn Sie zwei separate Projekte haben, sollten sich diese in zwei separaten Code-Repositorys befinden. Jetzt hängen sie von der gemeinsamen Funktionalität ab. Betrachten wir zum Beispiel Paketverarbeitungsanwendungen. Die allgemeine Funktionalität kann umfassen:
Nun benötigen verschiedene Paketverarbeitungsanwendungen möglicherweise eine andere Teilmenge davon. Sollten Sie eine Kernbibliothek mit einem Quellcode-Repository implementieren oder sollten Sie für jedes dieser Module 18 verschiedene Repositorys haben? Denken Sie daran, dass diese Module möglicherweise gegenseitige Abhängigkeiten aufweisen, sodass die meisten dieser Module beispielsweise von verschiedenen Modulen abhängen können.
Ich werde behaupten, dass eine Kernbibliothek der beste Ansatz ist. Es reduziert den Overhead vieler Quellcode-Repositorys. Es reduziert die Abhängigkeitshölle: Eine bestimmte Version von Speicherzuweisern benötigt möglicherweise eine bestimmte Version eines anderen Moduls. Und was ist, wenn Sie Speicherzuweiser Version 1.7 abhängig von Verschiedenes 2.5 und AVL-Baum Version 1.2 abhängig von Verschiedenes 2.6 wollen? Möglicherweise können Sie nicht gleichzeitig verschiedene 2.5 und 2.6 mit Ihrem Programm verknüpfen.
Implementieren Sie also die folgende Struktur:
Ich habe gesehen, dass der Wechsel von der Struktur zu dieser Art von Struktur:
Hat zu weniger Wartung und mehr Code-Sharing über Nicht-Copypaste-Mechanismen geführt.
Ich habe auch Projekte mit der folgenden Struktur gesehen:
... und die Abhängigkeitshölle und die Verbreitung von Repository-Nummern waren echte Probleme.
Sollten Sie jetzt eine vorhandene Open Source-Bibliothek verwenden, anstatt Ihre eigene zu schreiben? Sie müssen berücksichtigen:
Normalerweise verwende ich die Regel, dass alles unter 1000 Codezeilen, was nicht etwas erfordert, das über das Fachwissen des Programmierers hinausgeht, selbst implementiert werden sollte. Hinweis: Die 1000 Zeilen enthalten Unit-Tests. Daher würde ich es auf keinen Fall empfehlen, 1000 Codezeilen selbst zu schreiben, wenn 10 000 zusätzliche Zeilen für Komponententests erforderlich sind. Für meine Paketverarbeitungsprogramme bedeutet dies, dass ich nur folgende externe Komponenten verwendet habe:
Einige Dinge, die ich selbst implementiert habe, weil sie einfach sind, umfassen sogar Dinge wie:
... weil benutzerdefinierte Implementierungen davon starkes Inlining ermöglichen können, was zu einer verbesserten Leistung führt.
Ich mache keine Kryptographie; Wenn ich das tun würde, würde ich der Liste eine Art Kryptobibliothek hinzufügen, da das Schreiben von Kryptoalgorithmen für sich selbst anfällig für Cache-Timing-Angriffe sein kann, selbst wenn Sie durch gründliche Unit-Tests zeigen können, dass sie mit den offiziellen Algorithmen kompatibel sind.
quelle
Eine Kernbibliothek kann schlecht sein, wenn mehrere Projekte davon abhängen. Sie müssen nicht nur Änderungen an Ihrem Kern testen, sondern auch jedes einzelne abhängige Projekt einem Regressionstest unterziehen. Zweitens können sich Ihre Kern-APIs niemals ändern, da Sie jedes abhängige Projekt neu gestalten müssen. Je mehr Projekte Ihre Bibliothek verwenden, desto tiefer ist die Falle.
Ein weiteres Problem ist die Tendenz, alles "Gemeinsame" in Ihre Kernbibliothek zu werfen, es aufzublähen und es schwieriger zu machen, nach kleinen Stücken zu suchen. Ich sage nur, dass ich einmal von einem Ort gehört habe, der Angst hatte, eine der zahlreichen Kernbibliotheken zu berühren, der Aufwand für QS-Regressionstests so groß war.
Vielleicht können Sie stattdessen eine Code-Snippet-Ressource erstellen, mit der Projektteams den benötigten Code suchen und abrufen und sich von Wartungs- oder Regressionsproblemen trennen können? Das mache ich sowieso zu Hause.
quelle
Ein Punkt, der noch nicht erwähnt wurde, ist, dass jeder Code von etwas abhängig sein wird , selbst wenn es buchstäblich das einzige ist, was im ROM eines eingebetteten Mikrocontrollers ausgeführt wird. Wenn der Hersteller des Controllers ein Verhalten ändert, auf das sich der Code stützt, muss der Code entweder geändert werden, um mit Chips zu arbeiten, die nach der Änderung hergestellt wurden, oder Hersteller des Geräts, das den Code verwendet, müssen irgendwie Chips erwerben, die dies tun die Änderung nicht einbeziehen - möglicherweise eine Preisprämie für sie zahlen.
Die Verwendung einer Bibliothek zum Ausführen verschiedener Hardwarefunktionen kann bedeuten, dass Code jetzt von einer Bibliothek abhängig ist, obwohl dies zuvor nicht der Fall war, aber es kann auch Abhängigkeiten zwischen dem Code und der Hardware beseitigen. Beispielsweise könnte ein Chiphersteller versprechen, eine Bibliothek für alle gegenwärtigen und zukünftigen Chips bereitzustellen, die immer bestimmte E / A-Funktionen auf eine bestimmte Weise ausführen. Code, der diese Bibliothek zum Ausführen dieser E / A-Funktionen verwendet, würde vom Hersteller abhängig, um geeignete Versionen dieser Bibliothek bereitzustellen, wäre jedoch nicht länger vom Hersteller abhängig, um dieselbe Hardware-Implementierung dieser Funktionen zu verwenden.
Leider ist es oft schwer zu wissen, welcher Ansatz für zukunftssicheren Code richtig ist. Ich habe Fälle gesehen, in denen ein Chiphersteller die Funktionsweise einer Bibliothek geändert hat (um neue Chips aufzunehmen), selbst wenn sie für den Zugriff auf einen geänderten Chip verwendet wurde. Ich habe auch Fälle gesehen, in denen ein Chiphersteller die Funktionsweise seiner Hardware geändert hat, die bereitgestellten Bibliotheken jedoch entsprechend angepasst wurden, sodass Code, der Bibliotheksroutinen verwendet, weiterhin unverändert funktioniert, während Code, der direkt auf Hardware zugreift, angepasst werden musste.
Ähnliche Situationen bestehen bei Windows-Anwendungen. Microsoft liebt es manchmal, die Art und Weise zu ändern, in der Anwendungen ausgeführt werden müssen. Code, der bestimmte Bibliotheken für solche Dinge verwendet, kann einfach durch Aktualisieren der Bibliothek aktualisiert werden, während Code, der keine Bibliotheken verwendet, die für sie aktualisiert werden, manuell aktualisiert werden muss.
quelle
Ich wollte mich mit einer etwas anderen Einstellung dazu einmischen, obwohl ich die
Denis de Bernardy
Antwort und den verknüpften Artikel über das Minimieren von Abhängigkeiten im Vergleich zum Minimieren von Redundanzen liebe (sie spiegeln meine eigenen Gedanken zu diesem Thema wider, bei dem ich glaube, dass die Wiederverwendung von Code ein Balanceakt ist).Das größte Problem, das ich mit einer
core
Bibliothek habe, ist folgendes:Und ich denke, es ist sehr wahrscheinlich, dass die Antwort " nie " sein könnte. Die Leute könnten immer versucht sein, etwas hinzuzufügen, da es eine solch nebulöse Idee modelliert, insbesondere wenn sich diese Bibliothek nur während der Entwicklung der Software entwickelt, anstatt im Voraus mit Spannung erwartete Ziele zu haben. Und vielleicht ist das Hinzufügen zur Bibliothek nicht das Schlimmste auf der Welt, da es bestehende Abhängigkeiten von der Bibliothek nicht aufhebt. Angesichts dieser nebulösen Ziele könnte die Bibliothek jedoch zunehmend vielseitiger und hässlicher werden und unterschiedliche Funktionen bieten, an denen sich jemand interessiert Bei Verwendung der Bibliothek wird möglicherweise nur ein kleiner Teil davon gefunden, der für ihre Anforderungen geeignet ist.
Die Abhängigkeiten in Ihrer Codebasis sollten idealerweise in Richtung sehr stabiler Pakete fließen. Ein
core
Paket kann leicht sehr instabil werden, während große Teile Ihrer Codebasis Abhängigkeiten aufweisen.Daher denke ich, dass es sich lohnt, die Bibliothek in einheitlichere Bibliotheken aufzuteilen, die sich etwas Spezifischerem widmen als nur " Kernbibliothek mit allem, was Menschen häufig benötigen", damit sie mit einer besseren Koordination zwischen Ihren Teamkollegen in eine einheitlichere Richtung wachsen kann über genau das, was es tun sollte und, was noch wichtiger ist, nicht tun sollte, und möglicherweise einen Punkt der Stabilität erreichen, an dem es gut getestet ist und Sie nicht das Gefühl haben, dass noch etwas hinzugefügt werden muss, damit es relativ ist. " komplett "und stabil (wie in, unveränderlich).
quelle
Das Schreiben von Bibliotheken für grundlegende Dinge wie Zeichenfolgen und verknüpfte Listen ist in diesem Jahrtausend ziemlich dumm. Verwenden Sie eine im Lieferumfang der Batterien enthaltene Programmiersprache, in der die Kernfunktionalität bereits enthalten ist.
Wenn Sie nur zum Spaß Kernbibliotheken zur Laufzeitunterstützung schreiben möchten, entwerfen Sie eine neue Programmiersprache. Wenn Sie dies in einer Anwendung tun, entwickeln Sie im Wesentlichen eine Sprache aus ihrer Seite heraus.
Hat nicht schon jemand N verschiedene Kernbibliotheken in der von Ihnen verwendeten Sprache geschrieben? Das Erforschen vorhandener Frameworks und das Auswählen des am besten geeigneten Frameworks kann die Zeit besser nutzen als von Grund auf neu.
quelle