webForumDet fria alternativet

Singleton eller inte?

.NETur .NET

58 svar · 2 971 visningar · startad av Lukaspojken · sida 3 av 3

Frågan, av Lukaspojken

Jag börjar fundera på om man inte ska börja köra singleton på sina servicar och repositories men jag är osäker på om det kan skapa problem. Jag vill alltså undvika behöva skriva två rader kod, dvs: OrderRepository repository = new OrderRepository(); Order order = repository.GetById(orderId); Så här känns bättre: Order order = OrderRepository.GetInstance().GetById(orderId); Men

Läs frågan i sin helhet →
Medlem sedan jan. 20022 440 inlägg
#41

Phorpher skrev:

Hmm. Varför slutade ni få de felen bara för att ni skötte identifieringen genom ett Singelton? Eller var det någon egenutvecklad id-metod som gav felen?

Ett alternativ vore kanske att registera en "mobilidentifierings-service" i en DI-container och sätta livslängden på servicen till en Singleton (t.ex. i Unity med ContainerControlledLifetimeManager.)

Den ursprungliga versionen var ett statiskt xml dokument i Global.asax allt är bättre än det. Väntar på att wurfl ska släppa ett nytt identifikations-api. Testversionen de släppte nyligen fungerade sämre än förra versionen.

Medlem sedan aug. 20003 575 inlägg
#42

CatZ skrev:

För att återkoppla till ämnet! Ända gången jag använder en singelton är för att hålla ett 10 MB stort xml dokument i minnet (http://wurfl.sourceforge.net/). Kom inte på någon bättre lösning. Alla detections vi gjorde utan singelton resulterade i att massvis med besökare kändes igen som samma mobiltelefon och jag ville inte gärna instantiera obegränsat med 10MB stora xml dokument i minnet.

Jag utmanar er att försöka hitta en annan lösning på det problemet! :e

Någonstans så blir ju allting statiskt, frågan är bara var man vill lägga det.
Kör du DI blir det ju statiskt i din configfil, eller där du säger vilka instanser som skall användas var.

Hade man kunnat skicka runt samma instans runtomkring in i olika konstruktorer?

Det jag ser som nackdel med Integrationswrappern som Lukaspojken pratar om är att man bestämmer implemmentationen i integrationswrappern, och sådana kanske man har flera i de olika lagren?

Kör man med DI med någon di-container och med interface så bestämmer man ju implemmentationerna antingen utanför i en config fil eller i toppen i någon confurigationsklass.

Jag håller inte heller med i argumentationerna att det skulle vara mer arbete med DI än vad det är med en eventuell integrationswrapper. Och att löskopplade system skulle vara mycket mer komplexa än motsatsen tvärtom tycker jag.
En av styrkan med löskopplade system är ju att komplexiteten minskar.

När man i första inlägget här frågar om hur man skall lösa det med flera samtidiga användare/trådar och där det minst komplexa svaret enligt mig är DI.
Självklart kommer ju något vara singleton/statiskt men man behöver inte sprida ut det över alla sina klasser utan bör låta det ligga högst upp.

Medlem sedan maj 20011 312 inlägg
#43

-> Phorpher
Integrationswrappern är något jag tagit fram under årens lopp. Kanske är det så att integrationswrappern är något nytt som ingen annan tänkt på innan. Men att wrappa olika lösningen är inte något nytt men att kombinera wrappning och funktionalitetsutökning kanske är det. Nä, jag vet inte...

-> Nickemannen
>Nickemannen: Det jag ser som nackdel med Integrationswrappern som Lukaspojken pratar om är att man bestämmer implemmentationen i integrationswrappern, och sådana kanske man har flera i de olika lagren

LP: Sker det ofta att du har olika implementationer? Om så är fallet då kanske man bör se det hela som att lösningen har tex två integrationskopplingar snarare än en. Men det känns som man krånglar till det i onödan men det borde gå att lösa.

>Nickemannen: Jag håller inte heller med i argumentationerna att det skulle vara mer arbete med DI än vad det är med en eventuell integrationswrapper.

LP: Jag har inte sagt att det är mer arbete med DI än med en integrationswrapper.

>Nickemannen: Och att löskopplade system skulle vara mycket mer komplexa än motsatsen tvärtom tycker jag.

LP: Testa att löskoppla till ett absurdum så får du se vad som händer :) Jag har inte sagt att det är "mycket mer komplexa". Det jag sagt är att det blir renare med en integrationswrapper samt att du får en hel del annan mervärde på köpet. Det blir inte helt lös kopplat men du får en helt acceptabel nivå på det.

Angående singleton lösningen så hade Greg Young en intressant lösning:

public class Repositories {
public static IOrderRepository Orders { get { return new OrdersRepository(); }}
}

Repositories.Orders.GetById();

Om jag förstått det hela rätt så pratar Martin Fowler om någon liknande lösning när han pratar om "registry". Ska ta och bläddra i boken lite ikväll och se om det finns något intressant... Fast jag skipar nog interfacet :)

Medlem sedan mars 20007 896 inlägg
#44

Lukaspojken skrev:

Angående singleton lösningen så hade Greg Young en intressant lösning:

public class Repositories {
public static IOrderRepository Orders { get { return new OrdersRepository(); }}
}

Repositories.Orders.GetById();

Om jag förstått det hela rätt så pratar Martin Fowler om någon liknande lösning när han pratar om "registry". Ska ta och bläddra i boken lite ikväll och se om det finns något intressant... Fast jag skipar nog interfacet :)

Återigen så kommer det att skapas ett nytt OrdersRepository vid varje anrop till Repositories.Orders. Bara för att metoden är statisk, betyder det inte att samma objekt returneras varje gång. Med många anrop till Repositories.Orders.* kommer du att äta minne, bara så att du är på det klara med det. ;)

F.ö. så är det en nästan identisk lösning som Gladh gav i sitt första svar.

Medlem sedan aug. 20003 575 inlägg
#45

Lukaspojken skrev:

-> Phorpher
Integrationswrappern är något jag tagit fram under årens lopp. Kanske är det så att integrationswrappern är något nytt som ingen annan tänkt på innan. Men att wrappa olika lösningen är inte något nytt men att kombinera wrappning och funktionalitetsutökning kanske är det. Nä, jag vet inte...

-> Nickemannen
>Nickemannen: Det jag ser som nackdel med Integrationswrappern som Lukaspojken pratar om är att man bestämmer implemmentationen i integrationswrappern, och sådana kanske man har flera i de olika lagren

LP: Sker det ofta att du har olika implementationer? Om så är fallet då kanske man bör se det hela som att lösningen har tex två integrationskopplingar snarare än en. Men det känns som man krånglar till det i onödan men det borde gå att lösa.

>Nickemannen: Jag håller inte heller med i argumentationerna att det skulle vara mer arbete med DI än vad det är med en eventuell integrationswrapper.

LP: Jag har inte sagt att det är mer arbete med DI än med en integrationswrapper.

>Nickemannen: Och att löskopplade system skulle vara mycket mer komplexa än motsatsen tvärtom tycker jag.

LP: Testa att löskoppla till ett absurdum så får du se vad som händer :) Jag har inte sagt att det är "mycket mer komplexa". Det jag sagt är att det blir renare med en integrationswrapper samt att du får en hel del annan mervärde på köpet. Det blir inte helt lös kopplat men du får en helt acceptabel nivå på det.

Angående singleton lösningen så hade Greg Young en intressant lösning:

public class Repositories {
public static IOrderRepository Orders { get { return new OrdersRepository(); }}
}

Repositories.Orders.GetById();

Om jag förstått det hela rätt så pratar Martin Fowler om någon liknande lösning när han pratar om "registry". Ska ta och bläddra i boken lite ikväll och se om det finns något intressant... Fast jag skipar nog interfacet :)

DI betyder inte att man löskopplar till absurdum? Finns ingen som säger att vi vill göra det.

Vad menar du när du pratar om en "renare lösning" vad är en renare lösning för dig?

Okej om du gör så så sitter du fortfarande på pottkanten över hur du skall få din DBConnection / transaktionshantering in till din repository.
Då måste du ha en statisk variabel någonstans som ditt repository känner till som direkt blir trådberoende.

Och om det inte blir mer arbete med DI som du säger att det inte blir varför då inte använda DI istället eftersom vi i tråden har kommit fram till att det lättare går att testa med DI, samt byta ut komponenter lättare även om vi kanske aldrig vill göra det.

Vi kan ställa frågan såhär, vad vinner man på att använda sig av en integrationswrapper istället för DI, F12 punkten har vi vad finns det mer?

Med den lösningen du gav nu utöver Spin's poäng så bryter du mot OpenClosed. om du nu hade velat köra med den lösningen kanske

Repositorys.GetRepository<OrderRepository>(), där du lägger till alla repositories i en lista så slipper du iallafall all DRY kod :) men man kan ju inte F12:a lika lätt när du inte debuggar.

Medlem sedan maj 20012 812 inlägg
#46

Nickemannen skrev:

Någonstans så blir ju allting statiskt, frågan är bara var man vill lägga det.

Det är väldigt stor skillnad på att ha en statisk config fil, eller en singelton klass i sin applikation! Det är ju som att jämföra äpple med päron, det går bara inte.

spin skrev:

Med många anrop till Repositories.Orders.* kommer du att äta minne, bara så att du är på det klara med det.

Så länge det inte händer något i OrdersRepository konstruktorn som tar väldigt lång tid eller förbrukar mycket minne, så spelar det inte så mycket roll om du skapar en ny instans vid varje anrop. Referensen till objekt släpps så fort som objektet inte "finns" längre, och GC kan städa upp efter dig. Men visst är man riktigt petig så kan det påverkar på prestandan, men det finns garanterat andra ställen som säkert behöver sig en genomkörare först...

Däremot så strider koden mot: Law of Demeter.

The LawOfDemeter specifies a style guideline: "Only talk to your immediate friends." E.g. one never calls a method on an object you got from another call nor on a global object.

lukaspojken skrev:

Fast jag skipar nog interfacet

Det är ju synd, för det är det enda som är positivt med den lösningen :)

lukaspojken skrev:

kombinera wrappning och funktionalitetsutökning kanske är det.

Låter som din integrationswrapper är väldigt komplex och där med strider mot S.R.P och/eller S.O.C, men det är ju omöjligt att veta utan att se koden, så det är rena spekulationer från min sida.

- M

Medlem sedan dec. 19996 522 inlägg
#47

Jag är nyfiken på hur jag kan tdd:a med en integrationswrapper och vad jag tjänar på det jämfört med köra DI och exempelvis RhinoMocks som mockramverk. Pseudokod please. Tråden började med ett påstående om att du inte enhetstestat repositorys så mycket så jag misstänker och om du inte enhetstestat repositorys tidigare att det inte går via din integrationswrapper, vilket i sin tur leder mig till det jag skrev tidigare om att det är helt olika typer av test och kräver sin egen lösning.

För jag har faktiskt inte fattat hur din integrationswrapper fungerar,har jag fattat det rätt om det handlar om integrationstest, där du testar anropskedjor osv, du testar ihopkopplade objekt?

Medlem sedan mars 20007 896 inlägg
#48

Gladh skrev:

spin skrev:

Med många anrop till Repositories.Orders.* kommer du att äta minne, bara så att du är på det klara med det.

Så länge det inte händer något i OrdersRepository konstruktorn som tar väldigt lång tid, så spelar det inte så mycket roll om du skapar en ny instans vid varje anrop. Referensen till objekt släpps så fort som objektet inte "finns" längre, och GC kan städa upp efter dig.

Ja, visst städar GC upp - men man kan aldrig förutsäga när städningen sker egentligen. Jag säger inte att det kommer att bli en flaskhals, då det antagligen inte kommer att ta upp speciellt mycket minne per skapat objekt. Däremot tycker jag att det är dålig programmeringssed att göra så, både enligt min logik och enligt Law of Demeter. :)

Om man vänjer sig vid den typen av programmering, och i ett kommande projekt t.ex. läser in en fil på ett par MB i konstrutorn för (i det här fallet) OrdersRepository - kan det bli en flaskhals. Man ska inte räkna med att GC städar upp efter en så fort en referens inte kommer att användas igen - däremot kan man räkna med att referensen städas bort vid godtycklig tidpunkt. :)

Medlem sedan maj 20012 812 inlägg
#49

spin skrev:

både enligt min logik och enligt Law of Demeter.

Nja, det beror på vad du syftar på. För L.O.D säger inget om att du instansierar klassen varje gång, den tycker bara inte om att du gör en massa .-anrop efter varandra.

Skall jag vara riktigt ärlig, så brytar jag faktiskt mot L.O.D när jag skall hämta ut rätt objekt med hjälp av DI, men det är bara för att jag är lat och inte vill ha en massa kod i mina konstruktorer. Så det blir rätt ofta kod som detta.

...
public void User() : this(UnityFactory.GetContainer.Resolve<IUserRepository>) {}
public void User(IUserRepository userRepository){...}
...

Jag vet! Hemskt inte sant... Men så är jag pragmatisk också!!!

spin skrev:

Man ska inte räkna med att GC städar upp efter en så fort en referens inte kommer att användas igen - däremot kan man räkna med att referensen städas bort vid godtycklig tidpunkt.

GC städar inte upp så fort som referensen försvinner, GC städar upp när den tycker att det behövs, och det spelar faktiskt ingen roll om din applikation använder 10 MB eller 100MB ram minne om det ändå finns 1 GB ledigt :)

- M

Medlem sedan aug. 20003 575 inlägg
#50

Gladh skrev:

Nickemannen skrev:

Någonstans så blir ju allting statiskt, frågan är bara var man vill lägga det.

Det är väldigt stor skillnad på att ha en statisk config fil, eller en singelton klass i sin applikation! Det är ju som att jämföra äpple med päron, det går bara inte.

Sant jag skrev inte singleton utan statiskt :) menade absolut inte att det var samma sak.

Medlem sedan maj 20011 312 inlägg
#51

--> Till Alla: Jag svarar på eventuellt två inlägg till sen får vi nog inte ut mer av denna tråd... :) Men jag måste redan nu tacka alla här för all bra feed back jag fått! Det har varit en intressant diskussion...

--> Gladh
>Gladh: Så länge det inte händer något i OrdersRepository konstruktorn som tar väldigt lång tid eller förbrukar mycket minne, så spelar det inte så mycket roll om du skapar en ny instans vid varje anrop. Referensen till objekt släpps så fort som objektet inte "finns" längre, och GC kan städa upp efter dig. Men visst är man riktigt petig så kan det påverkar på prestandan, men det finns garanterat andra ställen som säkert behöver sig en genomkörare först...

LP: Tack för du reda ut det! För det händer ju i princip aldrig något i en repository konstruktor. Det jag vill få ned är som sagt antalet kodrader i mina servicar. Jag tycker att kodöverblicken ökar. Om man ska köra en mega loop eller om det är prestandakritiskt så kan man köra sköta instansieringen på det klassiska sättet.

Angående, "Law of Demeter", om jag lägger CreateInstance-metoden i repository strider jag då mot denna lag?

>Gladh: Låter som din integrationswrapper är väldigt komplex och där med strider mot S.R.P och/eller S.O.C, men det är ju omöjligt att veta utan att se koden, så det är rena spekulationer från min sida.

LP: Så länge den inte skapar problem utan ett mervärde så gör det inte så mycket att det strider mot olika principer och lagar. En så länge har jag inte haft några problem och som vi pratade om innan så kommer det inte vara några större problem att byta integrationslösning om man använder sig av en wrapper.

Men jag är inte helt övertygad ännu att köra CreateInstance-metoden men det känns väldigt lockande. Jaja, vi kanske kan avrunda diskussionen nu...

--> erka
>erka: Jag är nyfiken på hur jag kan tdd:a med en integrationswrapper och vad jag tjänar på det jämfört med köra DI och exempelvis RhinoMocks som mockramverk. Pseudokod please. Tråden började med ett påstående om att du inte enhetstestat repositorys så mycket så jag misstänker och om du inte enhetstestat repositorys tidigare att det inte går via din integrationswrapper, vilket i sin tur leder mig till det jag skrev tidigare om att det är helt olika typer av test och kräver sin egen lösning.

LP: Kör du TDD så är nog DI att föredra för då får du en gemensam testimplementation.

>erka: För jag har faktiskt inte fattat hur din integrationswrapper fungerar,har jag fattat det rätt om det handlar om integrationstest, där du testar anropskedjor osv, du testar ihopkopplade objekt?

LP: Det handlar inte om integrationstest. Säg för enkelheten skull att du anropar GetOrderById i din OrderRepository. Denna metod kan returnera ett mockobjekt eller ett objekt från tex databasen. Detta innebär att när du skriver ditt enhetstest för GetOrderById så kan du använda samma testmetod för dels ditt enhetstest som ditt integrationstest. På byggservern kör du sedan integrationstester medan lokalt enhetstester.

--> Nickemannen
>Nickemannen: DI betyder inte att man löskopplar till absurdum? Finns ingen som säger att vi vill göra det.

LP: Om du läser mitt svar så var det ett svar på att du inte tyckte att löskopplade system är mycket mer komplexa än motsatsen. Jag bara drog det ett steg ytterligare för att visa att du har fel för extremt löskopplade system kan bli ganska komplexa och det finns inte bara en nivå på DI utan det finns många olika nivåer man kan implementera det på.

>Nickemannen: Vad menar du när du pratar om en "renare lösning" vad är en renare lösning för dig?

LP: En renare lösning är för mig att tex domänen påverkas så lite som möjligt av saker som inte berör domänen. Lös koppling och testbarhet har tex inget med domänen att göra.

>Nickemannen: Och om det inte blir mer arbete med DI som du säger att det inte blir varför då inte använda DI istället eftersom vi i tråden har kommit fram till att det lättare går att testa med DI, samt byta ut komponenter lättare även om vi kanske aldrig vill göra det.

LP: ??? Det känns som du inte har läst tråden riktigt...

>Nickemannen: Vi kan ställa frågan såhär, vad vinner man på att använda sig av en integrationswrapper istället för DI, F12 punkten har vi vad finns det mer?

LP: Du får läsa några av de senaste svar jag skrivit till Gladh så slipper jag skriva det om igen.

Medlem sedan maj 20012 812 inlägg
#52

lukaspojken skrev:

Angående, "Law of Demeter", om jag lägger CreateInstance-metoden i repository strider jag då mot denna lag?

Detta strider inte mot LOD.

public static class Repository{
public static IOrderRepository CreateOrderRepository(){
 return new OrderRepository();
}
}
IOrderRepository orderRepository = Repository.CreateOrderRepository();
orderRepository.GetById(...);

Detta gör:

Repository.CreateOrderRepository().GetById(...);

Och jag misstänker att det är det sista som du vill göra, så ja då strider det mot LOD.

lukaspojken skrev:

Så länge den inte skapar problem utan ett mervärde så gör det inte så mycket att det strider mot olika principer och lagar.

De olika principerna och "lagarna" har kommit till genom många års utvecklande, de är inte något nytt. De fanns långt innan .NET's tid, bara att många som utvecklat i .NET har inte använt sig av dessa tidigare.

Och som med allt annat så, vet man bara varför man gör något och inser "risken" man tar så är det okej att bryta mot dem, men de finns där av en anledning och det är att när man bryter mot dem så försvårar man förändringar av koden och gör sin kod mer komplex än den behöver vara.

- M

Medlem sedan dec. 19996 522 inlägg
#53

Det handlar inte om integrationstest. Säg för enkelheten skull att du anropar GetOrderById i din OrderRepository. Denna metod kan returnera ett mockobjekt eller ett objekt från tex databasen. Detta innebär att när du skriver ditt enhetstest för GetOrderById så kan du använda samma testmetod för dels ditt enhetstest som ditt integrationstest. På byggservern kör du sedan integrationstester medan lokalt enhetstester

Varför det, det är ju två typer av olika test med olika ansvar, och således olika test, enhetstest bör testa en liten del av en klass helt atomärt från övriga, eller testa beteende för en viss specifik funktion. Jag misstänker du inte kan sätta expectations på dina mockar, vilket isjälva verket isf. gör dem till stubbar och inte mockar http://martinfowler.com/articles/mocksArentStubs.html#TestsWithMockObjects. Integrationstest ska testa kedjor så innebär det att ditt test har olika ansvar beroende på ett värde i en config-fil? Du kan inte testa beteende inom en klass med din wrapper?

Sedan finns det ju en hel annan sida av denna diskussion, http://www.artima.com/weblogs/viewpost.jsp?thread=7588, ny tråd kanske :)
I will *ship shit*
- whenever it provides value to the client
- openly and with the client's knowledge

Medlem sedan sep. 200888 inlägg
#54

>>johannormen: DI är även smidigt i tester där man vill "koppla" bort objekt >som man inte vill skall ingå i själva testerna. Ex DB access, Viss Loggning >m.m. m.m.

>I detta fallet tycker jag en integrationswrapper är smidigare att använda än >DI. En integrationswrapper har också en mycket större >återanvändningsbarhet än ett interface. Den öppnar upp en hel del andra >möjligheter också.

Lite förklaringar.

DI = Dependecy Injection eller IoC (Inversion of control)

DI är inget direkt desingmönster så som integrationswrapper är utan en teknik för att lösa flera olika saker.

Exempelvis för att slippa skriva koden som skickas in i ex en Set, i en konstruktor etc.

Du kan mkt väl BYGGA din itegrationswrapper med DI tekniken.

Istället för att ex göra.

var x = CreateSomthing.DoTHings(min lilla söta sak som ex DoThing anropar);

public x DoThings(Foo x)
{

 retiurn x.Execute();

}

DI är en mer eller mindre automatisk injection som du själv slipper skriva om och om igen för att dels bli av med reduntant kod men även för att få andra fördelar som byta ut saker och ting baserat på olika criterier som du själv kan styra över.

DI ha ringet med att man skall använda det för testning, DI är en tekink du kan använda dig avför att förenkla testning genom att skicka in objekt som ev kanske inte gör nått eller returnerar fake.

I din domän använder du DI till mkt mer än så.

1.. För löskoppla beroenden
2... För minimera skrivandet av onödig kod som du ev måste skriva om o om igen... ex inputparams, input av objekt in i klasser etc...
3... Fungerar utmärkt för Facortyklasser
4... Fungerar utmärkt för wrappers
etc... etc...

DI = teknik
Integrationswrapper = Desing Mönster där man kan använda DI för göra det enklare och mer löskopplat och smidigt...

Medlem sedan maj 20011 312 inlägg
#55

-> erka
>erka: Varför det, det är ju två typer av olika test med olika ansvar, och således olika test, enhetstest bör testa en liten del av en klass helt atomärt från övriga, eller testa beteende för en viss specifik funktion.

LP: När man använder sig av en integrationswrapper så tester enhetstestet tex metoden GetById i OrderRepository men den skipar integrationskopplingen. Men du kanske inte enhetstestar dina repository-metoder utan enbart kör integrationstester, eller? Och så är fallet så tror jag vet varför man inte enhetstester dessa och det är för att repositories är alltför hårt knutna till integrationslösningen. Dessa går alltså bara att integrationstesta om man inte använder sig av en integrationswrapper.

->johannormen
Jag vill bara förtydliga mig. Jag menar inte att en integrationswrapper ska ersätta all form av DI. Det jag menar är att i de fall man använder sig av klassisk implementering av DI för att undvika integrationstester (för att de är långsamma) eller för att göra lös koppla integrationsdelar så är inte DI nödvändigtvis det bästa sättet att göra detta på. En integrationswrapper har en hel del mervärde som en klassisk implementation av DI inte ger en. Jaja, nu har jag tjatat om detta för mycket... :)

Medlem sedan dec. 19996 522 inlägg
#56

Jag enhetstestar alltid mina repon utan problem, jag kör även integrationstest för testa större flöden, repon ej knutna till integrationslösningen. Sedan testar jag min OR-mappers mappningsinformation som andra separata enhets test i en form av integrationstest mot en inmemory sqlite databas. Sedan har vi en testresurs som skriver funktions och integrationstest som testar större flöden i applikationen. Helt olika typer av test som kräver olika personer som gör det, olika fixtures, och exekveras i helt olika kontext. Det är min poäng, jag tror inte på "one test to rule them all"-metodiken. Jag har sett en del lösningar som påminner om det du beskriver och de har tenderat att bli en soppa i slutänden,om det beror på dåliga utvecklare eller metoden är en annan fråga.

Hur gör du med expectations på mockade objekt, för att testa beteende, eller fungerar dina mockar bara som stubbar?

Medlem sedan maj 20011 312 inlägg
#57

>erka: Jag enhetstestar alltid mina repon utan problem, jag kör även integrationstest för testa större flöden, repon ej knutna till integrationslösningen.

LP: Men är det inte så att du har två repo-klasser, dvs en för implementation och en för tex icke-integrationstest? I mitt fall har jag bara en repo-klass och integrationswrappern avgör om den ska implementeras eller tex returnera ett test objekt.

>erka: jag tror inte på "one test to rule them all"-metodiken.

LP: Det är inte detta jag menar utan det jag menar är att samma enhetstest av tex en repp-metod skulle både kunna användas för enhetstest och integrationstest, dvs man slipper ha två tester. För det har du väl idag? Sedan får man givetvis komplettera med ytterligare tester.

>erka: Jag har sett en del lösningar som påminner om det du beskriver och de har tenderat att bli en soppa i slutänden,om det beror på dåliga utvecklare eller metoden är en annan fråga.

LP: Är det användningen av integrationswrapper som du menar blir en soppa? Sånt kan även hända med de lösningar du kör med om det används på ett felaktigt sätt.

Medlem sedan dec. 19996 522 inlägg
#58

Nej jag har bara en repoimplementation, all kod testad med atomära enhetstester (följer uncle bobs principer) utan träffa db, betendet som testas. Sedan test som kör mot riktig databas och testar kedjor av integration. Dessa är i en helt annan svit som körs vid ett specifikt automatiserat bygge, för att de tar för lång tid att köra lokalt, feedback loopen är för lång.

Ja vill det ska vara olika tester, olika sviter, testen har olika syften och ska vara separata test.

Medlem sedan maj 20012 812 inlägg
#59

Om jag har förstått integrationswrappern rätt så gör den följande (om vi fokuserar på test).

Istället för att i testprojektet sätta upp några mock-varainter av repositoryt, så kan man lägga dessa mock-varianter i integrationswrappern. Man kan även lägga dessa i en databas, så de hämtas därifrån ifall personen som skriver testet inte har tillgång till koden för integrationswrappern? Korrekt?

Då det är integrationswrappern som tar hand om beslutet vilken kod som skall köras, mockadeobjekt eller riktigdata så måste det finnas en parameter med som berättar för integrationswrappern om den skall returnera testdata eller riktigdata och den ligger i konfigfilen? Korrekt?

Säg att jag kallar på en webservice på url:en. http://www.aaa.com/produktion och när jag gör unittester så kallar den inte på denna URL utan returnerar tillbaka färdiga objekt till mig som jag kan lägga i en databas så jag kan ändra dessa även om jag inte har tillgång till integrationswrappern. Och det styr jag via en parameter i config filen.

Men säg att jag vill göra ett integrationstest på http://www.aaa.com/integrationtest hur får integrationswrappern reda på att det är den URL:en och inte http://www.aaa.com/production som jag skall anropa denna gång? Finns denna länk också i en databas, samt att det är ytterligare en parameter i config-filen som jag måste hålla reda på? Och vad händer om jag har ytterligare en URL som jag måste testa mot http://www.aaa.com/qualtiyassurancetest Hur fungera det då?

Vilka andra funktioner är det du vinner med integrationswrapper som inte rör test? Du har sagt att man får andra fördelar och vinster med integrationswrappern, men inte gett något konkret exempel (förutom F12, då)...

- M

143 ms totalt · 3 externa anrop · v20260731065814-full.b746b907
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
140 ms — hämta tråd, inlägg och bilagor (db)