--> erka
Jag tror du missförstår mig. Jag förstår skillnaden mellan integrations- och enhetstester. Det jag vill åt är att i de fall syftet är att undvika integrationstester så förespråkar jag användningen av en integrationswrapper istället för användning av DI. Detta för att erhålla en renare och utvecklarvänligare arkitektur. Jag vill alltså att testimplementeringen är så nära integrationen som möjligt. Vi antar att du har en OrderRepository som implementerar ett interface med syftet att man ska kunna tex mocka objekt. Jag skulle hellre använda mig av en integrationswrapper och skipa interface:t. På detta sätt kan jag mocka objekt på inparameterar samt testa min OrderRepository djupare än om jag skulle använt mig av ett interface. Jag kan till och med validera tex sql-sats som är mappad till det mockade objektet, dvs att tex kolumnnamn är mappade korrekt utan att exekuera frågan.
Nja, automatiserade tester är inte en grundprincip i agil. Eller fungerande mjukvara är inte detsamma som automatiserade tester. Men automatiserade tester är en väg för att uppnå fungerande mjukvara. Det är dock viktigt att beakta att agil bygger på många andra värderingar och principer än enbart fungerande mjukvara. En viktig bit är fokus på affärsnytta.
Jag tycker att affärsnyttan och kunders behov ska styra hur pass väl fungerande mjukvara vi ska utveckla. Du kan säkerligen erhålla fullständig perfektion i fungerande mjukvara med hjälp av bla automatiserade tester men till vilket pris? Har kunden behov av perfektion? Är kunden beredd att betala priset för vad perfektion är? De erfarenheter jag har är att kunden inte har dessa pengar och därför gäller det att försöka hitta en good enough nivå.
Så det handlar inte om Cowboy-programmering utan om att hitta en vettig nivå på testning och löskoppling, samt att undvika att överproducera eller underproducera.
Nedan följer ett grovt exempel på hur en integrationswrapper skulle kunna göras. Om vi tex skapar en basklass till XMLDocumentReader. Det finns andra sätt att lösa detta men nu tog jag bara en av dessa:
public class XMLDocumentReader : XMLDocumentReaderBase
{
private XMLParser Parser { get; set; }
public XMLDocumentReader()
{
Parser = new XMLParser();
}
public XMLDocument ParseFile(string fileName)
{
return //Anrop till basklassen som hanterar integrationen och om XMLdocumentet ska hämtas från filarkivet eller om det ska returnera ett dynamiskt hårdkodat objekt.
}
}
Samma princip implementerat på Gladhs olika exempel (det kvittar om det är anrop till stordator eller WCF)
public class OrderRepository : RepositoryBase //I detta fall skapar vi en RepositoryBase
{
public Order GetById(int id)
{
//Anrop till basklassen som hanterar integrationen och om ordern ska hämtas från databasen (stordatorn/wcf) eller om det ska returnera ett dynamiskt hårdkodat objekt.
}
}
>erka: Ett system blir enklare, och renare med DI, om sedan utvecklarna har svårt att hänga med i hur en bra uppbyggt klass fungerar är att annat problem, skaffa bättre utvecklare eller kanske gör det som är att föredra, utbilda dem i varför.
Det handlar inte om att det är svårt att hänga med utan frågan är om det är nödvändigt det man implementerar samt vilket värde det ger. Jag tror det finns alltför mycket överdesign i vår branch. Sen tycker jag i och för sig att kompetens i IT-branchen är relativt låg men det är en annan fråga.
>Gladh: Som jag ser det så verkar du (lukaspojken) hänga upp dig på DI är till för testbarhet. Och det är ju en sak du kan använda det till. Men själva idén med att ge ett objekt de objekt som det behöver för att klara av sitt arbete, istället för att detta objekt själv skall skapa de objekt de behöver är ju möjligheten att få löstkopplade system.
Men varför vill du uppnå ett löstkopplat system? Bara för att man kan uppnå hög flexibilitet så innebär det inte att man ska köra på det. Vi antar att syftet är att löskoppla vår koppling till databasen men hur ofta byter man databas? Att implementera en sådan lös koppling med syftet att om vi någon dag skulle behöva byta databas så kan vi göra det lätt är överdesign och slöseri med kundens pengar.
>Nickemannen: ...att det blir mer kod tror jag inte heller.
Om du tex skapar ett interface till en entitet eller till ett repository hur gör du då för att det inte skulle bli mer kod än om du skulle skipa köra med interface? Vi säger att du har ett repository inteface som tex kräver att GetById, PersistAll m.m. är med. Genom att du bara skapar interfacet så har du mer kod, eller?
>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å.