Versiebeheer in C#

In deze zelfstudie leert u wat versiebeheer betekent in .NET. U leert ook welke factoren u moet overwegen bij het versiebeheer van uw bibliotheek en het upgraden naar een nieuwe versie van een bibliotheek.

Bibliotheken ontwerpen

Als ontwikkelaar die .NET-bibliotheken heeft gemaakt voor openbaar gebruik, hebt u waarschijnlijk in situaties waarin u nieuwe updates moet implementeren. Hoe u dit proces doet, is veel belangrijk, omdat u ervoor moet zorgen dat er een naadloze overgang van bestaande code naar de nieuwe versie van uw bibliotheek is. Hier volgen verschillende aandachtspunten bij het maken van een nieuwe release:

Semantische versiebeheer

Semantic versioning (SemVer for short) is een naamconventie die wordt toegepast op versies van uw bibliotheek om specifieke mijlpaalgebeurtenissen aan te geven. In het ideale geval moeten de versiegegevens die u uw bibliotheek geeft ontwikkelaars helpen de compatibiliteit met hun projecten te bepalen die gebruikmaken van oudere versies van dezelfde bibliotheek.

De meest eenvoudige benadering van SemVer is de 3-componentindeling MAJOR.MINOR.PATCH, waarbij:

  • MAJOR wordt verhoogd wanneer u incompatibele API-wijzigingen aanbrengt
  • MINOR wordt verhoogd wanneer u functionaliteit toevoegt op een achterwaarts compatibele manier
  • PATCH wordt verhoogd wanneer u achterwaarts compatibele bugfixes maakt

Er zijn ook manieren om andere scenario's op te geven, bijvoorbeeld versies van voorlopige versies, bij het toepassen van versiegegevens op uw .NET-bibliotheek.

Compatibiliteit met eerdere versies

Wanneer u nieuwe versies van uw bibliotheek vrijgeeft, is compatibiliteit met eerdere versies waarschijnlijk een van uw belangrijkste problemen. Een nieuwe versie van uw bibliotheek is compatibel met een eerdere versie als code die afhankelijk is van de vorige versie, kan werken met de nieuwe versie wanneer deze opnieuw wordt gecompileerd. Een nieuwe versie van uw bibliotheek is binair compatibel als een toepassing die afhankelijk is van de oude versie, zonder hercompilatie, met de nieuwe versie kan werken.

Hier volgen enkele aandachtspunten bij het behouden van compatibiliteit met eerdere versies van uw bibliotheek:

  • Virtuele methoden: wanneer u een virtuele methode maakt die niet virtueel is in uw nieuwe versie, betekent dit dat projecten die deze methode overschrijven, moeten worden bijgewerkt. Dit is een enorme belangrijke wijziging en wordt sterk afgeraden.
  • Methodehandtekeningen: bij het bijwerken van een methodegedrag moet u ook de handtekening wijzigen, moet u in plaats daarvan een overbelasting maken zodat code die in die methode aanroept, nog steeds werkt. U kunt altijd de oude methodehandtekening manipuleren om de nieuwe methodehandtekening aan te roepen, zodat de implementatie consistent blijft.
  • Verouderd kenmerk: u kunt dit kenmerk in uw code gebruiken om klassen of klasseleden op te geven die zijn afgeschaft en die waarschijnlijk in toekomstige versies worden verwijderd. Dit zorgt ervoor dat ontwikkelaars die gebruikmaken van uw bibliotheek beter zijn voorbereid op wijzigingen die fouten veroorzaken.
  • Optionele methodeargumenten: wanneer u eerder optionele methodeargumenten verplicht maakt of de standaardwaarde wijzigt, moet alle code die deze argumenten niet levert, worden bijgewerkt.

Notitie

Het optioneel maken van verplichte argumenten moet zeer weinig effect hebben, met name als het gedrag van de methode niet wordt gewijzigd.

Hoe eenvoudiger u het voor uw gebruikers maakt om een upgrade uit te voeren naar de nieuwe versie van uw bibliotheek, hoe groter de kans dat ze een upgrade uitvoeren.

Toepassingsconfiguratiebestand

Als .NET-ontwikkelaar is er een zeer hoge kans dat het bestand aanwezig is in de app.config meeste projecttypen. Dit eenvoudige configuratiebestand kan een lange weg gaan naar het verbeteren van de implementatie van nieuwe updates. Over het algemeen moet u uw bibliotheken zodanig ontwerpen dat informatie die waarschijnlijk regelmatig wordt gewijzigd, in het app.config bestand wordt opgeslagen, op deze manier wanneer dergelijke informatie wordt bijgewerkt, het configuratiebestand van oudere versies alleen moet worden vervangen door het nieuwe bestand zonder dat de bibliotheek opnieuw hoeft te worden gecompileerd.

Bibliotheken gebruiken

Als ontwikkelaar die .NET-bibliotheken gebruikt die zijn gebouwd door andere ontwikkelaars, weet u waarschijnlijk dat een nieuwe versie van een bibliotheek mogelijk niet volledig compatibel is met uw project en dat u uw code vaak moet bijwerken om met deze wijzigingen te werken.

Gelukkig voor u, C# en het .NET-ecosysteem worden geleverd met functies en technieken waarmee we onze app eenvoudig kunnen bijwerken om te werken met nieuwe versies van bibliotheken die belangrijke wijzigingen kunnen veroorzaken.

Omleiding van assemblybinding

U kunt het bestand app.config gebruiken om de versie van een bibliotheek die door uw app wordt gebruikt, bij te werken. Door een bindingsomleiding toe te voegen, kunt u de nieuwe bibliotheekversie gebruiken zonder dat u uw app opnieuw hoeft te compileren. In het volgende voorbeeld ziet u hoe u het bestand app.config van uw app bijwerkt om de 1.0.1 patchversie te gebruiken van ReferencedLibrary in plaats van de 1.0.0 versie waarmee het oorspronkelijk is gecompileerd.

<dependentAssembly>
    <assemblyIdentity name="ReferencedLibrary" publicKeyToken="32ab4ba45e0a69a1" culture="en-us" />
    <bindingRedirect oldVersion="1.0.0" newVersion="1.0.1" />
</dependentAssembly>

Notitie

Deze aanpak werkt alleen als de nieuwe versie van ReferencedLibrary binair compatibel is met uw app. Zie de sectie Compatibiliteit met eerdere versies hierboven voor wijzigingen waar u op moet letten bij het bepalen van de compatibiliteit.

Nieuw

U gebruikt de new wijzigingsfunctie om overgenomen leden van een basisklasse te verbergen. Dit is een manier waarop afgeleide klassen kunnen reageren op updates in basisklassen.

Neem het volgende voorbeeld:

public class BaseClass
{
    public void MyMethod()
    {
        Console.WriteLine("A base method");
    }
}

public class DerivedClass : BaseClass
{
    public new void MyMethod()
    {
        Console.WriteLine("A derived method");
    }
}

public static void Main()
{
    BaseClass b = new BaseClass();
    DerivedClass d = new DerivedClass();

    b.MyMethod();
    d.MyMethod();
}

Uitvoer

A base method
A derived method

In het bovenstaande voorbeeld kunt u zien hoe DerivedClass de MyMethod methode die aanwezig is, BaseClassverbergt. Dit betekent dat wanneer een basisklasse in de nieuwe versie van een bibliotheek een lid toevoegt dat al bestaat in uw afgeleide klasse, u de new wijzigingsfunctie op het afgeleide klasselid kunt gebruiken om het lid van de basisklasse te verbergen.

Wanneer er geen new wijzigingsfunctie is opgegeven, verbergt een afgeleide klasse standaard conflicterende leden in een basisklasse, hoewel er een compilerwaarschuwing wordt gegenereerd, wordt de code nog steeds gecompileerd. Dit betekent dat het toevoegen van nieuwe leden aan een bestaande klasse ervoor zorgt dat die nieuwe versie van uw bibliotheek zowel bron als binair compatibel is met code die ervan afhankelijk is.

overschrijven

De override wijzigingsfunctie betekent dat een afgeleide implementatie de implementatie van een basisklasselid uitbreidt in plaats van deze te verbergen. Het lid van de basisklasse moet de virtual wijzigingsfunctie erop toepassen.

public class MyBaseClass
{
    public virtual string MethodOne()
    {
        return "Method One";
    }
}

public class MyDerivedClass : MyBaseClass
{
    public override string MethodOne()
    {
        return "Derived Method One";
    }
}

public static void Main()
{
    MyBaseClass b = new MyBaseClass();
    MyDerivedClass d = new MyDerivedClass();

    Console.WriteLine("Base Method One: {0}", b.MethodOne());
    Console.WriteLine("Derived Method One: {0}", d.MethodOne());
}

Uitvoer

Base Method One: Method One
Derived Method One: Derived Method One

De override wijzigingsfunctie wordt geƫvalueerd tijdens het compileren en de compiler genereert een fout als er geen virtueel lid wordt gevonden dat moet worden overschreven.

Uw kennis van de besproken technieken en uw begrip van de situaties waarin u deze kunt gebruiken, zal een lange weg gaan naar het versoepelen van de overgang tussen versies van een bibliotheek.