Go-Bibliotheksdesignprinzipien: Von Repositories zu Ressourcen
Programmieren umfasst das Erstellen von Anwendungen und den Bibliotheken, die sie unterstützen. Eine Bibliothek ist eine Sammlung von teilbaren Ressourcen, hauptsächlich Quellcode. Die Unterscheidung zwischen Begriffen hilft bei der Gestaltung robuster Komponenten.
Ein Repository enthält Code-Dateien in einer Dateisystemstruktur. Ein Package in Go ist eine Gruppe von .go-Dateien, die eine einzelne Aufgabe ausführen, mit einer obligatorischen package-Deklaration am Anfang jeder Datei. Ein Module fasst Packages zusammen, mit Abhängigkeiten, die in go.mod festgelegt sind.
Eine Bibliothek ermöglicht das Teilen von Code ohne Duplizierung. Beispiel: Eine MaxInt-Funktion, die in verschiedene Packages foo und baz kopiert wird, ist ineffizient ohne eine einzige Quelle der Wahrheit. Packages lösen das Kompilierungs- und Importproblem.
package foo
func MaxInt(a, b int) int {
if a > b {
return a
}
return b
}
Komponentenisolation verhindert Kenntnis von anderem Code, und Dekomposition vereinfacht die Interaktion mit dem Compiler.
Ressourcen in Bibliotheken
Bibliotheken umfassen nicht nur Code, sondern auch externe Ressourcen: dynamische und statische.
Dynamische Ressourcen hängen von der Laufzeit ab. Ein Beispiel ist der GPU-Zugriff über CUDA im cu-Package von Gorgonia:
d := cu.CurrentDevice()
ctx := cu.NewContext(d, cu.SchedAuto|cu.MapHost)
mem, err := ctx.MemAlloc(1024)
Hier ist ctx ein GPU-Deskriptor für GPGPU-Aufgaben. Sein Zustand ist zur Kompilierzeit unbekannt.
Statische Ressourcen sind dem Compiler bekannt. Ein Beispiel sind Shakespeares Texte im willshakes-Package:
package willshakes
const AllsWellThatEndsWell = `Akt 1 Szene 1
GRÄFIN.
Indem ich meinen Sohn von mir gebe, begrabe ich einen zweiten Gatten.
...`
const MacBeth = `Akt 1 Szene 1
ERSTE HEXE.
Wann treffen wir drei uns wieder
...`
Zugriff über: willshakes.MacBeth. Ähnlich für Schriftarten oder Datensätze wie MNIST.
Klassifizierung von Bibliotheken
Bibliotheken werden nach ihren Ressourcen klassifiziert:
- Code-Bibliotheken: Geteilter Quellcode in Packages/Modules.
- Treiber-Bibliotheken: Wrapper über Treiber (cu für CUDA, go-gl für OpenGL).
- Ressourcen-Bibliotheken: Statische Daten (willshakes) oder Lader (mnist in Go).
| Typ | Beispiel | Charakteristik |
|------|---------|----------------|
| Code | Utility-Package | Statischer Code |
| Treiber | cu | Dynamischer Zugriff |
| Ressource | willshakes | Eingebettete Konstanten |
Treiber fügen Abstraktionen für sprachübergreifende Interaktion hinzu.
Eigenschaften einer guten Bibliothek
Eine gute Bibliothek erleichtert zwei Dialoge: mit der Maschine (Compiler/Laufzeit) und mit dem Entwickler.
Kriterien:
- Isolation: Komponenten kennen keine externen Bibliotheken.
- Dekomposition: Klare funktionale Grenzen.
- Komposition: Einfache Integration in Anwendungen.
- Vorhersagbarkeit: Verhalten entspricht der Dokumentation.
- Leistung: Minimaler Overhead ohne Kompromisse.
Vermeiden Sie package main in Bibliotheken – konzentrieren Sie sich auf Utilities. Testen Sie Randfälle, gewährleisten Sie Thread-Sicherheit.
Wichtige Erkenntnisse
- Eine Bibliothek ist eine teilbare Ressource, nicht nur ein Repository oder Package.
- Trennen Sie statische (Konstanten) und dynamische (Treiber) Ressourcen.
- Gewährleisten Sie Isolation, damit Entwickler sich auf eine einzelne Aufgabe konzentrieren können.
- Verwenden Sie Go-Packages für die Kompilierung und Modules für Abhängigkeiten.
- Gestalten Sie für Komposition: einfacher Import und Nutzung.
— Editorial Team
Noch keine Kommentare.