# Das Reuse-Release-Equivalence Prinzip
In diesem Blog werden wir auf eines der wichtigsten *Package Design Principles* anschauen: Das *Release/reuse equivalence principle*. Das Prinzip besagt:
Ein Körnchen der Wiederverwendung ist ein Körnchen welches veröffentlicht werden muss.
Damit werden zwei Konzepte angesprochen: Einerseits sollte man so viel Code veröffentlichen, wie man selbst oder andere wiederverwenden können. Es macht keinen Sinn ein Paket zu veröffentlichen, welches von niemandem eingesetzt wird, da es ein ziemlicher Aufwand ist, ein Packet zu veröffentlichen und anschliessend auch zu unterhalten.
Andererseits sollte man auch nur so viel Code wiederverwenden, wie mach tatsächlich veröffentlicht. Ein Code kann noch so perfekt wiederverwendbar gedacht sein, wenn man ihn nicht veröffentlicht, kann man ihn auch nicht wiederverwenden. Dabei sollte man sich vor der Veröffentlichung die folgende Frage stellen: Ist man in der Lage den Code zu veröffentlichen und in der Zukunft auch zu verwalten. Hat man diese Kapazitäten nicht, sollte man von einer Veröffentlichung absehen.
Ist man sich des Aufwands einer Veröffentlichung bewusst, kann man auch einfacher die Grösse und die Anzahl von Paketen entscheiden.
Anschliessend wollen wir uns mit den beachtenswerten Punkten bei einer Veröffentlichung auseinandersetzen:
## Versionierung
Um ein Paket wirklich verwendbar zu machen, muss die Versionierung beachtet werden. Es ist also wichtig, dass möglichst von Beginn an bereits ein VCS (wie Git oder [[Fossil]]) zu verwenden. Damit das Paket auch für andere Nutzer verfügbar ist, sollte man das Repository bei einem entsprechenden Anbieter hosten.
### Semantische Versionierung
Einer der grössten Probleme mit denen man zu kämpfen hat ist die Rückwärtskompatibilität. Grundsätzlich folgen daher die meisten Paketverwalter eine Versionierungsstrategie namens *"semantic versioning"* (Semantische Versionierung):
- Wenn neue Features zu einem Paket hinzugefügt werden, muss dafür eine neue *minor version* veröffentlicht werden (z.B.: x.1.x -> x.2.x).
- Wenn alte Sachen entfernt und Rückwärts-inkompatible Änderungen eingeführt werden, muss eine neue *major version* veröffentlicht werden (z.B.: 1.x.x -> 2.x.x).
- Wenn Bugs entfernt werden, sollten diese als *patch version* veröffentlicht werden (z.B.: x.x.1 -> x.x.2).
Semantische Versionsnummern müssen immer drei inkrementierende Nummern enthalten. Jeder der Teile hat eine Bedeutung zur Version, deshalb auch der Name (Anders als beispielsweise zufällige Nummern).
#### Major Versionen
Die erste Major Version ist normalerweise 0. Diese Version sollte als lückenhaft und experimentell aufgenommen werden. Bei dieser Version kann keine Rückwärtskompatibilität gewährleistet werden. Ab Version 1 sollte das Paket stabilisiert und entsprechend zuverlässig sein. Ab diesem Punkt repräsentiert jede neue Major Version eine rückwärtsinkompatible Änderung.
#### Minor Versionen
Auch die Minor Version startet bei 0, wobei es hierbei keine spezielle Bedeutung hat. Minor Versionen können Erweiterungen enthalten oder veraltete Teile als solche markieren (wobei diese erst bei der nächsten Major Version entfernt werden).
#### Patch Versionen
Wie die anderen beiden beginnt auch die Patch Version bei 0. Eine solche enthält entweder Bug-fixes oder Refactorings von bestehendem Code.
## Für Rückwärtskompatibilität entwickeln
Wenn semantische Versionierung verwendet wird, bedeutet Rückwärtskompatibilität, dass die gleiche Funktionalität unter sowohl den Minor Versionen wie auch den Patch Versionen garantiert wird. Die Entwicklung für Rückwärtskompatibilität sollte ab dem ersten Major Release ein Teil der Strategie sein.
### Faustregeln
#### Wirf nichts weg
Wenn etwas zum Code hinzugefügt wird, sollte geschaut werden, dass es in der nächsten Version noch existiert. Dazu gehören:
- Klassen
- Methoden
- Funktionen
- Parameter
- Konstanten
Eine Klasse *existiert*, wenn sie automatisch geladen werden kann. Sie müssen also nicht immer in der gleichen Datei exisiteren, aber der *Class Loader* muss in der Lage sein sie zu finden.
#### Wenn etwas umbenannt wird, füge einen Proxy hinzu
Klassen umzubenennen ist möglich. Es muss jedoch geschaut werden, dass die alte Klasse immer noch intialisiert werden kann. Dazu muss also eine Proxy Klasse mit dem alten Namen erstellt werden, welche die neue Klasse erbt.
#### Füge @deprecated Annotationen hinzu
Wenn ein Teil des Codes veraltet ist, sollte er nicht direkt entfernt werden. Stattdessen sollte er als veraltet markiert werden und erst bei der nächsten Major Version entgültig entfernt werden.
#### Füge neue Parameter nur am Ende und immer mit einem Standartwert hinzu
Wenn ein neuer Parameter zu einer bereits bestehenden Funktion hinzugefügt werden muss, ist es wicht, dass er am Ende steht und immer einen Standartwert hat. So kann sichergestellt werden, dass auch die alten Aufrufe noch Funktionsfähig sind.
## Fazit
Eigenen Code als Paket zu veröffentlichen hat durchaus seine Vorteile. Es ermöglicht nicht nur die eigene Wiederverwendung, sondern auch die Verwendung durch andere Entwickler, welche sich so Zeit sparen können. Es ist jedoch mit einem gewissen Aufand verbunden, da sich die Nutzer auf eine gewisse Stabilität und Transparenz verlassen können müssen. Um diese Stabilität und Transparenz zu gewährleisten, muss vom Entwickler auf Praktiken wie die Semantische Versionierung setzen und das Paket mit Rückwärtskompatibilität als Ziel entwickeln. [^1]
[^1]: Noback, Matthias: "The Release/reuse equivalence principle." *Principles of Package Design: Preparing your code for reuse*, Zeist, Niederlande: Apress, 2018, pp. 115 - 144