Warum interne Bibliotheken für interne Anwendungen entwickeln?

10

Ich habe Schwierigkeiten zu verstehen, warum Sie interne Bibliotheken entwickeln sollten, die ausschließlich für die Entwicklung interner Anwendungen verwendet werden. Ich weiß zu schätzen, dass wenn ich Software verwenden möchte, die jemand außerhalb des Unternehmens geschrieben hat, er mir seine Header-Dateien und .a oder .so-Dateien senden kann und ich sie einfach mit meinem Projekt verknüpfen kann (vorausgesetzt, sie werden in derselben Umgebung kompiliert). .

Aber warum sollte eine interne Bibliothek entwickelt werden, um mit einer internen Anwendung verknüpft zu werden, wenn ich Zugriff auf die Header- und Implementierungsdateien habe und sie einfach in meinen Quellbaum aufnehmen und alle zusammen kompilieren kann?

Mit anderen Worten: Wenn ein Quellcode geschrieben wird, wie entscheiden Sie, ob er in eine Binärbibliothek kompiliert und mit Ihrer Anwendung verknüpft oder nur in die Quelldateien des Projekts aufgenommen und regelmäßig kompiliert werden soll?

Wenn ich in jedem Projekt "Dateien einschließen" sage, möchte ich nicht jede Datei kopieren und in den Quellbaum des aktuell entwickelten Projekts einfügen. Ich meine, ein Verzeichnis / eine Bibliothek (getrennt von jedem Projekt) zu entwickeln, die allgemeinen Quellcode enthält, der auf die übliche Weise in die Dateien eines Projekts aufgenommen werden kann, dh #include.

ps Ich spreche hier von der C / C ++ - Entwicklung für mehrere Desktopanwendungen.

Andrew Murtagh
quelle

Antworten:

25

Es gibt zahlreiche Gründe, Bibliotheken und gemeinsam genutzte Bibliotheken (in DLL- oder SO-Dateien) auch für den internen Gebrauch zu erstellen :

  1. Die projektübergreifende Wiederverwendung ist viel sauberer
  2. Aufgabentrennung - Ein Teil Ihres Codes ist möglicherweise besser für verschiedene Entwickler oder Teams geeignet
  3. Sie können von Verbesserungen in den Bibliotheken anderer Teams profitieren, ohne den spezifischen Code suchen zu müssen
  4. Schnellere Erstellungszeiten: Wenn die Bibliothek stabil ist, muss sie nicht neu erstellt werden.
  5. Speicherplatz - Sie können nur die Bibliothek und die Header im Projekt haben
  6. Wenn Sie gemeinsam genutzte Bibliotheken verwenden, können Sie Speicher sparen, indem nur eine Kopie in den Arbeitsspeicher geladen wird, selbst wenn mehrere Programme diese verwenden
  7. In der Regel erhalten Sie eine bessere Dokumentation und Prüfung der Bibliotheken
  8. Saubereres Design und saubereres Code - Das Nachdenken über die Strukturierung von Dingen in Bibliotheken sollte zu verwandten Funktionsgruppen in jeder Bibliothek führen, und Sie neigen dazu, generischen Code in den Bibliotheken von den Anwendungsspezifikationen in der App zu trennen .
  9. Wenn Sie proprietäre Algorithmen in Bibliotheken haben, können Sie den Zugriff auf die Quelle einschränken, z. B. nicht zulassen, dass Auftragnehmer oder Outsourcing-Teams an die Quelle gelangen.
  10. Der Bibliothekscode kann unter einer anderen Lizenz als die Anwendung stehen, für die er ursprünglich geschrieben wurde. Einige Unternehmen sind sogar Open Source-Bibliotheken bekannt, auf die sie stolz sind - sie haben in der Open Source-Community großes Lob erhalten und manchmal wichtige Verbesserungen beigetragen zurück.

Einige Unternehmen haben sogar eine Buchhaltungspraxis, bei der Projekte, die Bibliotheken erstellen, bei jeder Wiederverwendung eine Erstattung erhalten.

Steve Barnes
quelle
1
In einer Variante von Punkt 9 können Sie die Bibliothek unter einer anderen Lizenz als dem Hauptanwendungscode freigeben.
Michael Borgwardt
@MichaelBorgwardt - Guter Punkt, der Punkt 10 oben auffordert.
Steve Barnes
Wenn Sie Code als separate Bibliothek haben, können Sie auch Verknüpfungen während der Programmierung vermeiden, z. B. "Ich füge hier nur diesen zusätzlichen Parameter hinzu.", Und Sie finden bessere Möglichkeiten, die erforderlichen Funktionen zu implementieren.
Valdas
11

Einige andere mögliche Gründe, die für größere, nicht triviale Projekte gelten können:

  • Kompilierungszeiten: Das Kompilieren riesiger monolithischer C ++ - Projekte mit Tausenden von Dateien, Tausenden von Klassen, Funktionen usw. kann sehr lange dauern (was die Produktivität beeinträchtigt, wenn Sie jedes Mal neu kompilieren möchten, wenn Sie einige Codezeilen ändern). Statisch verknüpfte und dynamisch verknüpfte Bibliotheken werden unabhängig voneinander kompiliert und müssen nicht neu kompiliert werden, wenn sich ihre Quelle nicht geändert hat.

  • Logische Trennung verschiedener Module oder Subsysteme : Große Systeme sind in der Regel einfacher zu verwalten, wenn unterschiedliche Funktionsbereiche in separaten Modulen angeordnet sind und Entwickler nicht mit der Suche in riesigen Ordnern / Projekten mit Tausenden von Dateien / Klassen konfrontiert sind.

  • Grenzen zwischen Entwicklern / Teams : Entwickler, die gleichzeitig separate neue Funktionen erstellen, können das Potenzial für Zusammenführungskonflikte verringern, wenn jeder Entwickler in verschiedenen Modulen arbeiten kann.

  • Code, der nicht in eine Live-Umgebung freigegeben werden darf : Zum Beispiel Unit-Test-Bibliotheken oder Mock-Bibliotheken, die für Entwicklertests verwendet werden, um eine Live-Systemkomponente (Hardware, APIs, Remote-Systeme, Datenbanken usw.) zu ersetzen.

  • Compiler-Flags : Wenn Sie sich in der sehr unglücklichen Lage befinden, in die API eines Drittanbieters zu integrieren, die ein seltsames Compiler-Flag erwartet, kann die Bibliothek eine "Dekontaminationsschicht" sein, die sich zwischen der API des Drittanbieters und dem Rest der Anwendung befindet.

  • Optionale Funktionen / Optimierung : In großen Systemen kann eine Anwendung warten, bevor bestimmte dynamisch verknüpfte Module zur Laufzeit in den Speicher geladen werden, wenn sie für die Grundfunktionalität der Anwendung nicht kritisch sind.


Im Allgemeinen handelt es sich bei vielen internen Projekten häufig um kleine Mikro-Apps, die nicht davon profitieren, in separate Bibliotheken aufgeteilt zu werden. Wenn Sie als Einzelentwickler an einem winzigen Projekt arbeiten, müssen Sie sich (noch) keine Gedanken über die Aufteilung Ihres Codes in Bibliotheken machen. Vergessen Sie nicht das YAGNI-Prinzip .

Ben Cottrell
quelle
3
@downvoter - kannst du den Grund für die Downvote erklären? Feedback zu Antworten ist nützlich, um die Qualität dieser Website für alle zu verbessern.
Ben Cottrell
4

Ihre ursprüngliche Frage könnte hier bei den meisten dieser anderen Antworten zu einem Missverständnis geführt haben. Da Sie nicht beabsichtigen, vorhandenen Code projektübergreifend zu kopieren , sondern dieselben Quelldateien aus verschiedenen Projekten als Referenzen einzuschließen , werden alle Argumente für "doppelten Code" sowie viele andere Argumente sinnlos.

Beachten Sie, dass dies manchmal (- nicht immer -) eine sinnvolle Technik ist . Wenn Sie alle Quelldateien, die Sie projektübergreifend wiederverwenden möchten, in einem separaten Include-Ordner ablegen, haben Sie bereits eine Bibliothek erstellt - eine Quellcodebibliothek, keine binäre Bibliothek. Insbesondere in C ++ ist es beim Erstellen generischer Bibliotheken mit Vorlagen nicht ungewöhnlich, dass nur Header-Bibliotheken vorhanden sind, für die lediglich ein einfaches Include erforderlich ist, und keine separaten Verknüpfungsvorbereitungen.

Ihre eigentliche Frage ist also, wann Sie Quellcode-Bibliotheken erstellen oder wann Sie vorkompilierte Binärbibliotheken bevorzugen. In dieser älteren Antwort auf dieser Site habe ich einige Vor- und Nachteile von Nur-Header-Bibliotheken besprochen. Vielleicht hilft es Ihnen. Der Hauptvorteil von Quellcode-Bibliotheken besteht darin, dass sie nicht mit derselben Laufzeit und / oder kompatiblen Compiler- / Linker-Flags kompiliert werden müssen wie die Anwendung, die sie verwendet. Die Nachteile sind die zusätzlichen Kompilierungszeiten und die Anforderung, Zugriff auf den Quellcode bereitzustellen (was offensichtlich kein Problem für die Art von "internen" Projekten ist, an die Sie denken).

Doc Brown
quelle
Es ist wahr, dass ich eine Quellcodebibliothek gemeint habe, die mehreren Projekten gemeinsam ist, in der Sie nur auf die Dateien verweisen, die Sie über die typische # include-Direktive benötigen. Ich kannte den Begriff dafür erst, als Sie ihn sagten, und ich werde ihn bearbeiten Frage jetzt. Ihre verknüpfte Antwort ist auch sehr hilfreich.
Andrew Murtagh
@ AndrewMurtagh: Die Tatsache, dass Sie MichaelBorgwardts Antwort so schnell akzeptierten, hat mich erstaunt, denn was er schrieb, scheint entweder ein Missverständnis von ihm oder von mir zu sein.
Doc Brown
Nun, er hat die anfängliche Verwirrung geklärt, die ich hatte, wann ich Code, der mehreren Projekten gemeinsam ist, in einem einzigen Paket zusammenfassen sollte (sei es in Binärbibliotheken oder Quellcodebibliotheken), aber zugegeben, ich sprach von einem einzigen Quellverzeichnis Code, der projektübergreifend gemeinsam genutzt werden kann und nicht jede Datei kopiert und in jedes Projekt einfügt, wenn ich sie benötige.
Andrew Murtagh
2

Ich stimme anderen Kommentatoren zu, wenn sie schreiben, dass Sie keinen Code duplizieren sollten. In Ihrem Fall scheinen Sie (oder die Personen, mit denen Sie arbeiten) Bibliotheken für Code zu erstellen, der an keiner anderen Stelle dupliziert wird.

In diesem Fall warne ich vor vorzeitiger Verallgemeinerung . Es gibt oft Zeiten, in denen man den Eindruck hat, dass ein Teil des Codes wiederverwendbar ist. Ohne die genauen Details darüber zu kennen, wie der zweite Anwendungsfall solchen Code verwendet, ist es jedoch sehr einfach, zusätzliche Zeit für "Wiederverwendbarkeit" -Funktionen aufzuwenden, die in den zusätzlichen Fällen nicht wirklich nützlich sind, oder Annahmen zu treffen, die sich als falsch erweisen der zweite Fall.

Das Schreiben einer "Bibliothek" für einen Anwendungsfall kann zu einer sehr teuren Übung werden, ohne dass sich dies auszahlt. Ich bin mehrmals davon gebissen worden.

Beispielkosten:

  1. Zeit / Energie für die Berücksichtigung "allgemeiner" Anwendungsfälle
  2. Zeitaufwand für die Verteilung der "Bibliothek" an Ihren "Client" (Ihren eigenen Code)
  3. Zukünftiger Druck, die "Bibliothek" zu nutzen, auch wenn sie nicht vollständig mit dem nächsten Anwendungsfall übereinstimmt

Meine allgemeine Regel lautet: Machen Sie keinen Code zu einer Bibliothek, es sei denn, ich habe mindestens zwei separate Stellen, an denen der Code benötigt wird.

Sam
quelle
2
Ich habe fast genau die gleichen Gründe gesehen, die von einigen Entwicklern verwendet wurden, als warum ihr Code alle in einer einzigen Quelldatei mit> 20.000 Zeilen enthalten ist. In Kombination mit skurrilen Namen und schlechten Kommentaren haben Sie bald Code, den Sie schneller umschreiben als pflegen können.
Steve Barnes
Toller Punkt: Ich bin sicher nicht dagegen, wartbaren, lesbaren Code zu schreiben. Separate Dateien, bekannte Methoden / Klassen und Paketstrukturen sind wichtige Komponenten der Wartbarkeit. Mein Punkt ist nur, dass die Kosten für das Schreiben und Verteilen einer Bibliothek sehr hoch sind, wenn es nur einen einzigen Anwendungsfall für die "Bibliothek" gibt.
Sam
1
Umgekehrt behaupte ich nicht, dass Sie in jedem Fall unbedingt eine Bibliothek verpacken und verteilen müssen, nur dass das Schreiben und Strukturieren, als ob Ihr Code eines Tages zu einer Bibliothek werden könnte, normalerweise einen kleinen Aufwand wert ist und sich oft auszahlt, selbst wenn der Code nie wird als Bibliothek verteilt.
Steve Barnes
1

Warum sollte eine interne Bibliothek entwickelt werden, um mit einer internen Anwendung verknüpft zu werden, wenn ich Zugriff auf die Header- und Implementierungsdateien habe und sie einfach in meinen Quellbaum aufnehmen und alle zusammen kompilieren kann?

Denn wenn Sie "sie nur in meinen Quellbaum aufnehmen", duplizieren Sie Code .

Das Problem dabei ist, dass Sie weder von Verbesserungen (einschließlich kritischer Bugfixes) des Projekts profitieren, von dem Sie den Code kopiert haben, noch von Verbesserungen, die Sie vornehmen.

Sie könnten denken, dass Sie dieses Problem lösen können, indem Sie einfach die neueste Version des Codes regelmäßig in Ihren Quellbaum kopieren, vielleicht sogar automatisiert, indem Sie ein Submodul in Git oder etwas Ähnlichem verwenden. Aber dann wird Ihre Build-Unterbrechung aufgrund inkompatibler API-Änderungen ständig unterbrochen. Eine Bibliothek hingegen verfügt über eine "offizielle" öffentliche API, von der die Entwickler wissen, dass sie nicht ohne Zusammenarbeit mit Clients geändert werden kann.

Schließlich kann es technische Gründe geben - könnte es notwendig sein, einen Teil des Codes als Bibliothek beizubehalten, damit er optional geladen oder bei Bedarf sogar geladen und entladen werden kann, und so die Speichernutzung zu reduzieren, wenn die Funktionalität nicht benötigt wird?

Michael Borgwardt
quelle
1
Soweit ich weiß, besteht der Hauptgrund dafür, dass ein Teil des Codes in eine Bibliothek umgewandelt wird, darin, dass er für verschiedene Projekte verwendet wird (auch wenn alle intern entwickelt wurden), damit dieser Code nicht dupliziert, aktualisiert oder verwaltet wird separat? Und wenn Sie nur ein einzelnes Projekt entwickeln möchten, müssen Sie keine Bibliothek erstellen (es sei denn, Sie beabsichtigen, es zu einem späteren Zeitpunkt in weiteren Projekten zu verwenden).
Andrew Murtagh
@ AndrewMurtagh: Ja, genau so würde ich es ausdrücken. Obwohl es auch technische Gründe geben kann; Ich bin mit der C / C ++ - Entwicklung nicht so vertraut. Vielleicht ist es erforderlich, einen Teil des Codes als Bibliothek beizubehalten, damit er optional geladen oder bei Bedarf sogar geladen und entladen werden kann, und so die Speichernutzung zu reduzieren, wenn die Funktionalität nicht benötigt wird.
Michael Borgwardt
Ich glaube, dass dies durch gemeinsam genutzte Bibliotheken möglich sein kann. Vielen Dank für die Klarstellung, ich werde Ihre Antwort als akzeptiert markieren.
Andrew Murtagh
Nahezu jedes VCS des letzten Jahrzehnts unterstützt externe Referenzen oder Submodule. Dadurch wurde das Problem mit doppeltem Code und Bugfix behoben. Könnte weitere Informationen darüber enthalten, warum dies keine praktikable Lösung ist, wenn Sie immer noch glauben, dass es sich um gültige Probleme handelt.
Sirisian
Denken Sie auch an die Wartung. 1) Die Bibliothek kann unabhängig und parallel gepflegt werden. 2) Ist der Code leicht zu ersetzen? 3) Kleine Codebasen sind für kleine Teams einfacher zu verwalten und für alle verständlicher. 4) Wenn die Markteinführungszeit entscheidend ist, bevorzugen Sie schnellere Builds. Code in libs ist Code, den Sie in der Pipeline (IMO) nicht immer wieder kompilieren. 5) Es ist zuverlässiger wiederverwendbarer Code ... Sie haben es geschafft ;-)
Laiv
1

Ich möchte auf die Kosten eingehen, die Ihre Lösung auf längere Sicht hat.

Das Hinzufügen einer Bibliothek zu einem Projekt hat natürlich einen gewissen Overhead, alles oben, wenn es das erste ist: Workflows müssen geändert werden, manchmal sogar die Infrastruktur, und einige Teammitglieder mögen es möglicherweise (zuerst) nicht. Die Vorteile Ihrer Lösung liegen also auf der Hand, da sie jetzt weniger Kosten verursacht .

Wenn Ihr Projekt wächst, steigen jedoch auch die Kosten für die "Pseudobibliothek". Angenommen, Sie haben eine "Pseudobibliothek", Adie von einer Anwendung und einem Unit-Tester verwendet wird. Jedes Mal, wenn Sie eine CPP hinzufügen A, müssen Sie sie beiden Projekten hinzufügen, da sie sonst nicht verknüpft werden.

Was ist, wenn Ihre "Pseudobibliothek" von einer anderen "Pseudobibliothek" verwendet wird B? Sie müssen Ihre neue CPP in einer Reihe von Projekten mehr hinzufügen. Und wenn Sie Bwechseln, um eine andere Bibliothek zu verwenden? Sie müssen die cpps Ain allen Projekten nur abhängig von löschen B.

Dies alles wäre kostenlos, wenn eine echte Bibliothek verwendet würde. Die Frage ist also, wie viele cpps benötigt werden, um den Umzug in eine echte Bibliothek zu rechtfertigen.

Aber warten Sie, es gibt noch mehr Sicherheiten: Ein Entwickler mag diese blöde Arbeit nicht, alle Projekte zu jagen, die den neuen CPP benötigen, und fügt seinen Code / seine Klassen irgendwo in bereits vorhandene Dateien ein, was in nicht gut ist auf lange Sicht.

Die Verwendung der "Pseudobibliothek" kann also ein erster Schritt sein, um ein monolithisches Projekt aufzubrechen. Sie sollten jedoch nicht zu lange warten, um es zu einer echten Bibliothek zu machen, um seine Vorteile nutzen zu können.

ead
quelle
0

Aber warum sollte eine interne Bibliothek entwickelt werden, um mit einer internen Anwendung verknüpft zu werden, wenn ich Zugriff auf die Header- und Implementierungsdateien habe und sie einfach in meinen Quellbaum aufnehmen und alle zusammen kompilieren kann?

Wenn die Bibliothek immer nur von einer Anwendung verwendet wird, benötigen Sie sie wahrscheinlich nicht als separate Bibliothek.

Wenn die Bibliothek von 3.500 Anwendungen verwendet wird , benötigen Sie sie unbedingt als separate Bibliothek.

Was ist, wenn es einen Fehler in der Bibliothek gibt und Sie ihn beheben müssen? Oder einige gesetzliche oder regulatorische Änderung kommt das bedeutet , Sie haben , um die Art und Weise ändern sich die Bibliothek funktioniert?

Wenn es sich in einer separaten Bibliothek befindet, können Sie die Bibliothek (möglicherweise) reparieren, erneut testen und erneut bereitstellen, und jede Anwendung profitiert von der Korrektur.

Wenn es sich nur um Quellcode handelt, der für jede Anwendung "lokal" ist, müssen Sie jede Anwendung einzeln ändern, neu erstellen, erneut testen und erneut bereitstellen . Das ist eine viel größere (dh teurere) Übung.

Phill W.
quelle