Versionshantering, det vill säga, vad händer när ett publikt gränssnitt ändras i en tjänst, är en fråga som jag har stött på ett flertal gånger. I det här inlägget tänkte jag diskutera och visa på vissa aspekter av denna hantering.
INLEDNING
Egenligen skall det inte, i de bästa av världar, ändras ett publikt gränssnitt. Det skall vara låst när det väl är publiserat och kunder (speciellt om de är utanför vår kontroll) har börjat använda dem. Men hur lätt är detta att uppnå?
För att diskutera vad som händer när man ändå gör förändringar i ett gränssnitt, så har jag skapat ett litet exempel. Det är en webbtjänst som innehåller en metod, AddNewCustomer, vilken har en parameter in och en parameter ut. (Alltså enligt den dokumentcentrerade principen när man bygger webbtjänster.) Både metoden och parametrarna, eller meddelandena, är beskrivna med hjälp av Wsdl och Xsd. Första versionen av meddelandena ser ut på följande sätt:
<xs:element name="AddNewCustomerRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="Name" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="AddNewCustomerResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="ReturnCode" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:element>
Meddelandena är väldigt enkla. Inmeddelandet består endast av ett element, Name, och utmeddelandet består också av en parameter, ReturnCode.
Följande .net-kod använts för att ifrån en klient anropa webbtjänstens metod:
VersioningService.AddNewCustomerRequest _request = new
VersioningTestClient.VersioningService.AddNewCustomerRequest()
_request.Name = "Kalle Anka";
VersioningService.Customer _service = new
VersioningTestClient.VersioningService.Customer();
VersioningService.AddNewCustomerResponse _response;
_response = _service.AddNewCustomer(_request);
TESTER
1. Vad händer om vi lägger till ett element i inmeddelandet?
När vi har gjort detta så händer igenting på klienten. Den slutar alltså inte att fungera. Även om vi skulle uppdatera klientens wsdl-information för webbtjänsten, så händer ingenting. Grunden för detta är att det som skickas över är beskrivet som xml, vilket innebär att det inte är några problem att lägga till nya element till meddelandet. Vi kommer att få problem om vi ändrar namn på ett element, alltså i mitt fall Name till Namn, eller om vi tar bort element ifrån meddelandet.
Denna slutsats känns vid första anblicken rätt bra ut och i många fall räcker detta. Men det finns ändå vissa bitar som inte känns lika bra. Det blir inte lika strukturerat och kontrakten blir lite "informella". Om inmeddelandet ändras, så vet inte klienten längre vilka delar som är obligatoriska respektive valfria. Klienten blir mer osäker också på vilken version av webbtjänsten som den använder.
2. Sätt att motverka detta
För att lösa detta så kan jag se tre olika sätt:
a) Använd ändå mer generella meddelanden in och ut. Ett sätt är att skicka ren xml fram och tillbaka och sedan tolka det själv.
b) Skapa ny metod istället för att ändra parametrar i en metod. Exempelvis kan man skapa en ytterligare metod som heter AddNewCustomer11(), för version 1.1. c) Använd möjligheter i xsd som beskriver inparametern på ett sätt som gör det möjligt att ha flera versioner i samma definition. Detta kan se ut på följande sätt:
<xs:element name="AddNewCustomerRequest">
<xs:complexType>
<xs:sequence>
<xs:choice>
<xs:element name="Version10">
<xs:complexType>
<xs:sequence>
<xs:element name="Name" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Version11">
<xs:complexType>
<xs:sequence>
<xs:element name="Name" type="xs:string" />
<xs:element name="Address" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
Som vi ser här så beskrivs i samma meddelande att man antingen skall skicka in en parameter med namnet Name eller två parametrar med namnen Name och Address. Denna möjlighet kan beskrivas med xsd element choice. Det blir lite mer avancerad kod på klientsidan för att hantera ett sådant här meddelande.
Vilket skulle jag välja?
En svår fråga och som så mycket annat spelar många fler faktorer in än de som vi har beskrivit ovan. Det bästa vore naturligtvis att kontrakten hölls heliga, det vill säga att de inte ändrades. Jag känner tveksam till att skicka xml-dokument fram och tillbaka.
Jag håller frågan öppen just nu. (Var det detta som du ville höra?)
Comments