Peinlicherweise habe ich vor ein paar Jahrzehnten in einer Teamumgebung eine "gemeinsame" Bibliothek eingeführt, die als solche bezeichnet wird. Ich verstand damals nicht wirklich die Dynamik dessen, was in einem locker koordinierten Team in nur wenigen Monaten passieren konnte.
Als ich es einführte, dachte ich, ich hätte es klargestellt und auch dokumentiert, dass es für Dinge, über die wir uns alle einig sind, täglich nützlich ist, dass es eine minimalistische Bibliothek sein soll und dass die Bibliothek von nichts anderem als dem abhängen sollte Standardbibliothek, damit die Bereitstellung in neuen Projekten so einfach wie möglich ist. Ich dachte damals, dass es unsere eigene kleine Erweiterung der Standardbibliothek für Dinge ist, die wir in unserem speziellen Bereich täglich nützlich fanden.
Und es fing gut genug an. Wir begannen mit einer mathematischen Bibliothek ( common/math*
) von Routinen, die wir alle tagtäglich verwendeten, da wir in Computergrafiken arbeiteten, die oft schwer mit der linearen Algebra zu tun hatten. Und da wir oft mit C-Code interagierten, haben wir uns auf einige nützliche Utility-Funktionen geeinigt, die sich von find_index
denen unterscheidenstd::find
In C ++ würde anstelle eines Iterators, der die Funktionsweise unserer C-Funktionen nachahmt, ein Index für ein Element zurückgegeben, das sich in einer Sequenz befindet. Diese Dinge sind ein wenig eklektisch, aber minimalistisch und weit verbreitet genug, um jedem vertraut und praktisch zu bleiben , und sofortige Vertrautheit ist ein äußerst wichtiges Kriterium, da ich darin sehe, dass alles versucht wird, was "allgemein" oder "Standard" ist, denn wenn es wirklich "allgemein" ist, sollte es aufgrund seiner Breite die vertraute Qualität haben Annahme und tägliche Nutzung.
Aber im Laufe der Zeit sind mir die Gestaltungsabsichten der Bibliothek entgangen, als die Leute begannen, Dinge hinzuzufügen, die sie persönlich benutzten, von denen sie lediglich dachten, dass sie jemand anderem von Nutzen sein könnten, nur um niemanden zu finden, der sie benutzt. Und später begann jemand, Funktionen hinzuzufügen, die von OpenGL für allgemeine GL-bezogene Routinen abhängig waren. Weiterhin haben wir Qt übernommen und die Leute haben angefangen, Code hinzuzufügen, der von Qt abhängt, so dass die gemeinsame Bibliothek bereits von zwei externen Bibliotheken abhängig war. Irgendwann fügte jemand allgemeine Shader-Routinen hinzu, die von unserer anwendungsspezifischen Shader-Bibliothek abhängig waren, und zu diesem Zeitpunkt konnte man sie nicht einmal in einem neuen Projekt bereitstellen, ohne Qt, OGL und unsere anwendungsspezifische Shader-Bibliothek einzubringen und zu schreiben Ein nicht triviales Build-Skript für Ihr Projekt. So wurde es zu diesem eklektischen, voneinander abhängigen Durcheinander.
Aber ich habe auch durch die Debatte darüber, was in diese Bibliothek aufgenommen werden sollte und was nicht, herausgefunden, dass das, was als "allgemein" angesehen wird, leicht zu einer sehr subjektiven Idee werden kann, wenn Sie keine sehr strenge Regel festlegen, die besagt, was "allgemein" ist Was jeder täglich für nützlich hält. Wenn die Standards gelockert werden und es schnell zu einer Verschlechterung kommt, von Dingen, die jeder täglich für nützlich hält, bis hin zu Dingen, die ein einzelner Entwickler für nützlich hält und die möglicherweise für einen anderen von Vorteil sind. In diesem Moment verwandelt sich die Bibliothek sehr schnell in ein eklektisches Durcheinander .
Wenn Sie diesen Punkt erreicht haben, können einige Entwickler Dinge hinzufügen, weil sie die Programmiersprache nicht mögen. Sie mögen möglicherweise nicht die Syntax einer for-Schleife oder eines Funktionsaufrufs. Ab diesem Zeitpunkt fängt die Bibliothek an, sich mit Dingen zu füllen, die nur der grundlegenden Syntax der Sprache widersprechen, und ersetzt ein paar Zeilen einfachen Codes, die nicht wirklich sind Duplizieren einer Logik bis zu einer einzigen knappen Zeile exotischen Codes, die nur dem Entwickler bekannt ist, der eine solche Abkürzung eingeführt hat. Dann könnte ein solcher Entwickler beginnen, der gemeinsamen Bibliothek, die unter Verwendung solcher Abkürzungen implementiert wurde, mehr Funktionalität hinzuzufügen. An diesem Punkt werden bedeutende Teile der allgemeinen Bibliothek mit diesen exotischen Abkürzungen verwoben, die dem Entwickler, der sie eingeführt hat, schön und intuitiv erscheinen, aber für alle anderen hässlich und fremd und schwer zu verstehen sind. Und an diesem Punkt denke ich, dass Sie wissen, dass jede Hoffnung, etwas wirklich "gemeinsam" zu machen, verloren geht, da "gemeinsam" und "unbekannt" gegensätzliche Vorstellungen sind.
Es gibt also alle möglichen Arten von Würmern, zumindest in einer locker koordinierten Teamumgebung, mit einer Bibliothek, deren Ambitionen so umfassend und verallgemeinerungsbedürftig sind wie nur "häufig verwendete Sachen". Und obwohl das zugrunde liegende Problem vor allem die lockere Koordination gewesen sein könnte, würden sich zumindest mehrere Bibliotheken, die einem eher singulären Zweck dienen sollen, wie eine Bibliothek, die mathematische Routinen und nichts anderes bereitstellen soll, wahrscheinlich nicht so stark verschlechtern Designreinheit und Abhängigkeiten als "gemeinsame" Bibliothek. Im Nachhinein denke ich, dass es viel besser wäre, sich auf die Seite von Bibliotheken zu setzen, die viel klarere Designabsichten haben. Ich habe im Laufe der Jahre auch festgestellt, dass enge Absichten und enge Anwendbarkeit radikal unterschiedliche Ideen sind.
Ich bin zugegebenermaßen ein bisschen unpraktisch und kümmere mich vielleicht ein bisschen zu sehr um die Ästhetik, aber die Art und Weise, wie ich meine Vorstellung von der Qualität einer Bibliothek (und vielleicht sogar von "Schönheit") wahrnehme, wird mehr nach ihrem schwächsten Glied beurteilt als nach Es ist am stärksten, ähnlich wie wenn Sie mir das appetitlichste Essen der Welt präsentieren, aber auf dem gleichen Teller etwas verrotten lassen, das wirklich schlecht riecht, dann möchte ich den gesamten Teller ablehnen. Und wenn Sie in dieser Hinsicht wie ich sind und etwas machen, das alle Arten von Ergänzungen als etwas "Gemeines" einlädt, werden Sie vielleicht auf diese analoge Platte stoßen, auf der etwas verrottet. Deswegen finde ich es auch gut, wenn eine Bibliothek so organisiert und benannt und dokumentiert ist, dass dies nicht der Fall ist. ' t im laufe der zeit immer mehr zusätze einladen. Und das kann sogar auf Ihre persönlichen Kreationen zutreffen, da ich hier und da mit Sicherheit ein paar faule Sachen erschaffen habe, die sich viel weniger "verfärben", wenn sie nicht auf den größten Teller gelegt werden. Das Aufteilen von Dingen in kleine, sehr singuläre Bibliotheken führt zu einer besseren Entkopplung von Code, wenn auch schon aufgrund der Tatsache, dass es weitaus unpraktischer ist, alles zu koppeln.
Die Code-Deduplizierung wurde über die Jahre in mich hineingehämmert, aber ich denke, ich sollte es diesmal versuchen.
Was ich in Ihrem Fall vorschlagen könnte, ist, die Code-Deduplizierung zu vereinfachen. Ich sage nicht, große Schnipsel schlecht getesteten, fehleranfälligen Codes oder dergleichen zu kopieren und einzufügen oder große Mengen von nicht-trivialem Code zu duplizieren, der mit ziemlicher Wahrscheinlichkeit in Zukunft Änderungen erforderlich macht.
Aber vor allem, wenn Sie die Einstellung haben, eine "gemeinsame" Bibliothek zu erstellen. Ich gehe davon aus, dass es Ihr Wunsch ist, eine allgemein anwendbare, wiederverwendbare und möglicherweise ideale Bibliothek zu erstellen, die Sie heute genauso nützlich finden wie in einem Jahrzehnt danach Dann kann es manchmal sein, dass Sie eine Kopie benötigen oder möchten, um diese schwer fassbare Qualität zu erzielen. Denn die Vervielfältigung könnte tatsächlich als Entkopplungsmechanismus dienen. Wenn Sie einen Videoplayer von einem MP3-Player trennen möchten, müssen Sie zumindest einige Dinge wie Batterien und Festplatten duplizieren. Sie können diese Dinge nicht teilen oder sie sind untrennbar miteinander verbunden und können nicht unabhängig voneinander verwendet werden, und an diesem Punkt sind die Leute möglicherweise nicht mehr an dem Gerät interessiert, wenn sie nur MP3s abspielen möchten. Einige Zeit nachdem Sie diese beiden Geräte getrennt haben, werden Sie möglicherweise feststellen, dass der MP3-Player von einem anderen Akkudesign oder einer kleineren Festplatte als der Videoplayer profitiert. An diesem Punkt duplizieren Sie nichts mehr. Was anfangs als Duplikation begann, damit sich dieses voneinander abhängige Gerät in zwei separate, unabhängige Geräte aufteilen kann, kann sich später als Ergebnis von Designs und Implementierungen herausstellen, die nicht mehr redundant sind.
Es lohnt sich, die Dinge aus der Perspektive eines Bibliotheksbenutzers zu betrachten. Wollen Sie wirklich wollen , zu verwendeneine Bibliothek, die Code-Duplikationen minimiert? Wahrscheinlich werden Sie dies nicht tun, da dies natürlich von anderen Bibliotheken abhängt. Und diese anderen Bibliotheken sind möglicherweise von anderen Bibliotheken abhängig, um das Duplizieren ihres Codes zu vermeiden, und so weiter, bis Sie möglicherweise 50 verschiedene Bibliotheken importieren / verknüpfen müssen, um einige grundlegende Funktionen wie das Laden und Abspielen einer Audiodatei zu erhalten, was sehr unhandlich wird . Wenn eine solche Audiobibliothek absichtlich einige Dinge hier und da dupliziert, um ihre Unabhängigkeit zu erreichen, wird die Verwendung in neuen Projekten so viel einfacher, und es besteht die Möglichkeit, dass sie seit dem Gewinn nicht mehr so oft aktualisiert werden muss. ' Es ist nicht erforderlich, Änderungen an den abhängigen externen Bibliotheken vorzunehmen, die möglicherweise einen viel allgemeineren Zweck erfüllen als das, was die Audiobibliothek benötigt.
Manchmal lohnt es sich also, absichtlich ein wenig zu duplizieren (bewusst, nie aus Faulheit - eigentlich aus Fleiß), um eine Bibliothek zu entkoppeln und unabhängig zu machen, weil sie durch diese Unabhängigkeit ein breiteres Spektrum an praktischer Anwendbarkeit und Anwendbarkeit erreicht gleichmäßige Stabilität (keine afferenten Kupplungen mehr). Wenn Sie die bestmöglichen wiederverwendbaren Bibliotheken entwerfen möchten, die von einem Projekt zum nächsten und über die Jahre hinweg Bestand haben, dann schlage ich vor, hier ein wenig zu duplizieren, um den Umfang auf ein Minimum zu beschränken. Und natürlich schreiben Sie Unit-Tests und stellen Sie sicher, dass diese wirklich gründlich getestet und zuverlässig sind. Dies gilt nur für die Bibliotheken, für die Sie sich wirklich die Zeit nehmen möchten, sich auf einen Punkt zu verallgemeinern, der weit über ein einzelnes Projekt hinausgeht.