Dela via


Design för utveckling

Utvecklingsdesign är nyckeln till ständig innovation

Alla framgångsrika tillämpningar förändras med tiden – det kan handla om att åtgärda fel, lägga till nya funktioner, införa nya tekniker eller göra befintliga system mer skalbara och elastiska. Om alla delar i en tillämpning är nära sammanlänkade blir det mycket svårt att införa ändringar i systemet. En förändring i en del av tillämpningen kan orsaka fel i en annan, eller få ändringarna att spridas till hela kodbasen.

Det här problemet gäller inte enbart stora och oflexibla tillämpningar. En tillämpning kan brytas ned i tjänster, men ändå uppvisa den typ av nära kopplingar som gör systemet stelbent och känsligt. Om tjänsterna i stället utformas för vidareutveckling kan teamen förnya och skapa nya funktioner kontinuerligt.

Mikrotjänster blir ett populärt sätt att uppnå en evolutionär design, eftersom de tar upp många av de överväganden som anges här.

Rekommendationer

Framtvinga hög sammanhållning och lösa kopplingar. En tjänst är sammanhängande om den erbjuder funktioner som hänger samman logiskt. Tjänsterna löst kopplade om du kan ändra en tjänst utan att ändra den andra. Hög sammanhållning innebär i allmänhet att ändringar i en funktion kräver ändringar i andra relaterade funktioner, där alla relaterade funktioner finns i en tjänst. Om du upptäcker att uppdatering av en tjänst kräver samordnade uppdateringar av andra tjänster, kan det vara ett tecken på att dina tjänster inte är sammanhängande. Ett av målen med domändriven design (DDD) är att identifiera dessa gränser.

Kapsla in domänkunskap. När en klient använder en tjänst ska ansvaret för at framtvinga affärsreglerna för domänen inte ligga på klienten. I stället ska tjänsten kapsla in all kunskap om domänen som ligger på tjänstens ansvar. Annars måste varje klient framtvinga affärsreglerna, och resultatet blir att domänkunskapen sprids över olika delar av tillämpningen.

Använd asynkrona meddelanden. Asynkrona meddelanden är ett sätt att frikoppla meddelandeproducenten från konsumenten. Producenten är inte beroende av att konsumenten svarar på meddelandet eller genomför en viss åtgärd. Med en pub-/sub-arkitektur vet producenten kanske inte ens vem som förbrukar meddelandet. Nya tjänster kan förbruka meddelanden enkelt utan att det medför några ändringar för producenten.

Bygg aldrig in domänkunskap i en gateway. Gatewayer kan vara användbara i en arkitektur med mikrotjänster för funktioner som routning av begäranden, översättning av protokoll, belastningsutjämning eller autentisering. Gatewayen bör dock vara begränsad till den här typen av infrastrukturfunktioner. För att undvika att den blir alltför beroende bör den inte implementera någon domänkunskap.

Exponera öppna gränssnitt. Undvik att skapa anpassade översättningslager mellan tjänster. En tjänst bör i stället exponera ett API med ett väldefinierat API-kontrakt. API-gränssnittet ska vara versionsbaserat, så att du kan utveckla det med bibehållen bakåtkompatibilitet. På så sätt kan du uppdatera en tjänst utan samordna uppdateringar för alla överordnade tjänster som är beroende av tjänsten i fråga. Offentliga tjänster ska exponera ett RESTful-API via HTTP. Backend-tjänster kan använda ett meddelandeprotokoll i RPC-format av prestandaskäl.

Designa och testa mot servicekontrakt. När tjänster uppvisar väldefinierade API-gränssnitt kan du utveckla och testa mot dessa API-gränssnitt. På så sätt kan du utveckla och testa en enskild tjänst utan att alla dess beroende tjänster berörs. (Naturligtvis kan du fortfarande utföra integrerings- och belastningstester mot de verkliga tjänsterna.)

Abstrakt infrastruktur separat från domänlogiken. Blanda inte samman domänlogiken med infrastrukturrelaterade funktioner för exempelvis meddelanden eller beständighet. Annars kräver ändringar i domänlogiken att även infrastrukturlagren uppdateras, och tvärtom.

Avlasta övergripande frågor till en separat tjänst. Om flera tjänster till exempel måste autentisera begäranden kan du flytta funktionen till en egen tjänst. Sedan kan du utveckla autentiseringstjänsten, till exempel genom att lägga till ett nytt autentiseringsflöde, utan att röra någon av de tjänster som använder den.

Distribuera tjänster oberoende av varandra. När DevOps-team kan distribuera en enskild tjänst oberoende av andra tjänster i tillämpningen kan uppdateringar genomföras både snabbare och säkrare. Felkorrigeringar och nya funktioner kan lanseras i jämnare takt. Utforma både tillämpningen och lanseringsprocessen så att oberoende uppdateringar underlättas.