Technology overflow

by DotNetNerd 21. January 2009 19:24

Nye frameworks, tools og principper

Starten på det nye år, som samtig har været starten på nyt job for mig, har betydet at det var tid til at lære nogle frameworks at kende som jeg ikke tidligere har brugt professionelt. Det har været rigtigt spændende, men har også fået mit hoved til at eksplodere i forhold til tanken om at skulle blogge om det. Jeg vil derfor skrive lidt om hvad jeg har set på, fordi det nok er en del af de ting bloggen kommer til at omhandle fremadrettet.

Vi er en shop der gør alvor af at arbejde efter agile pricipper så jeg har haft tid til at kigge på ORM, Unit testing, mocking, Dependency Injection, Continuous Integration og Migrations. Dertil kommer Office Interop og ASP.NET MVC, som jeg endelig får mulighed for at bruge professionelt, hvor det ellers har været på todo-listen hjemme siden jeg fik leget med de helt tidlige bits. Og sidste men ikke mindst har jeg kigget op tools til synkronisering og deling af data.

Object relationel mappers

Mere præcist har jeg i forbindelse med ORM's kigget på NHibernate, Fluent NHibernate og LINQ to NHibernate, samtidig med at jeg har en bog på vej om LINQ to entities. Jeg håber LINQ to Entities udvikler sig til et reelt alternativ til NHibernate, som jeg lige knap synes det er idag. Hovedanklagen idag er at det ikke giver persistence ignorence, hvilket er et stort minus i forhold til at få et pænt løst koblet design. Det er dog et issue Microsoft er klar over, og noget de arbejder på til vNext. Et andet issue der arbejdes på som er væsentligt er iøvrigt model drevet design, hvor LINQ to Entities idag er meget datadriven.

Continuous Integration

Opsætning af et continuous integration miljø, som skal baseres på Team Foundation Server er en anden ting jeg er ved at se på. Umiddelbart virker det nemt at komme igang med, men udarbejdning af build scrips skal nok blive interessant at se på. En overvejelse er blandt andet om man skal holde sig til at bruge MS Build Server eller om NAnt viser sig at være den rigtige vej at gå?

Migrations

Migrator.NET har været rimeligt nemt at komme igang med, bortset fra at dokumentationen er rimeligt tynd, så selve konfigurationen skulle det lige pilles lidt ved for at få det til at spille.

Data synkronisering og deling af data

Idet jeg er begyndt at pendle er synkronisering af data imellem min desk- og laptop også blevet et super relevant emne, hvilket fik mig til at afprøve synctoy, live sync, mesh, skydrive samt servicen delicious. Mesh har jeg forelsket mig lidt i, selvom jeg må erkende at stabiliteten ikke er god nok endnu i beta versionen, samtidig med at de 5 GB plads man får idag er lidt tyndt når man på et skydrive får 25 GB.

Test driven development – my two cents.

by DotNetNerd 11. May 2008 13:07

Test driven development – my two cents.

Unit testing er en metode til at teste at en individuel enhed kildekode fungerer korrekt.  Egentlig har unit testing været brugt i flere årtier, men begrebet har den seneste tid udviklet sig til lige at være et buzzword der er oppe i tiden – især som metodik i form af Test Driven Development. TDD bliver der blogget enormt meget om for tiden – og netop derfor vil jeg ikke kaste mig ud i at forklare hvad det er, men lader det være en forudsætning for at læse videre.

Udbredelsen af TDD/unit testing er en stor del af grundlaget for at Microsoft har kastet sig over at lave MVC frameworket, som et alternativ til den klassiske måde at udvikle ASP.NET applikationer på.

Rob Conery der står bag SubSonic, og nu er ansat hos Microsoft er for tiden i gang med en serie på sin blog som han kalder MVC storefront, hvor han går efter at blive klogere på både MVC og TDD. En sjov detalje han har bemærket er at alle i miljøet snakker om ”at hvis man nu er purist skulle man gøre sådan og sådan”, men han har umiddelbart ikke kunne finde nogen der direkte er purister inden for TDD.

Personligt kan jeg godt se anvendeligheden i TDD, men jeg mener helt klart at der er alt for meget hype om det, og at det bestemt ikke er alting det er velegnet til. Min holdning skyldes helt enkelt to ting; for det første at man ofte ikke har en god nok beskrivelse af hvad man skal udvikle til at man kan skrive en rigtigt god unit test, og for det andet at det ikke altid er noget godt kvalitetsmål. Med det mener jeg at det ikke er alting man kan teste ved hjælp af unit tests, både fordi eksempelvis usability slet ikke er noget mål for en unit test, men også fordi omkostningerne ved at skrive og vedligeholde tests kan være større end gevinsten. Dette er i nogen grad en pointe ”Joel on software” også har fremført, blandt andet ved en tale på Yale.

Jeg laver selv en del applikationer, hvor beskrivelserne er sparsomme, og udviklingen derfor ikke kan undgå at blive ”trial and error” baseret. Ikke forstået som i at der er masser af ”fejl” som sådan i koden (selvfølgelig er der også det), men fordi kundens ønsker ændrer sig markant i løbet af processen. Teoretikeren vil nok sige at så er analysen af projektet ikke god nok, en pointe der ikke går helt tabt på mig, men der er mange kunder hvor det simpelthen ikke er muligt i praksis. Let the religious battle between theory and pragma begin!

Min anden pointe med at det ikke er alting der lader sig unit teste, er selvfølgelig også et spørgsmål om vilje. Brugerflader og sprocs er vanskelige at teste, og selvom man gør sig en masse anstrengelser for at lave unit tests af disse ting er værdien mindre - i forhold til at kunne teste ”rene funktioner”, med kendt input og output. En sidste observation jeg har gjort mig, er at fejl oftere skyldes integrationsproblemer end direkte logiske fejl – og i systemer hvor det er tilfældet er integrationstests i virkeligheden mere formålstjenlige.

Selvom jeg måske nu lyder meget skeptisk, synes jeg at unit tests og TDD er rigtigt godt, til de ting det rent faktisk er opfundet til. Min indsigelse er blot imod den megen hype der er, da heller ikke det er nogen Silver bullet, og jeg føler at anvendeligheden af unit tests har det med at blive overdrevet.

Frameworks og tools – de små måske vigtige forskelle.

De fleste jeg har snakket med der har arbejdet med unit testing kender NUnit frameworket, som nok er det mest udbredte framework til unit testing i .NET. Frameworket er oprindelig portet fra JUnit og har efterhånden en del år på bagen.

Der findes imidlertid også to andre udbredte open source  alternativer som er MbUnit og XUnit – forskellene imellem de tre frameworks er relativt små, men som man siger ”god is in the details”.

MbUnit omtales som NUnit på crack, og er et framework der er udviklet til at være mere udvidelsesvenligt end NUnit er. Det er i dag nok det mest advancerede unit testing framework og giver blandt andet mulighed for at man via attributter beskriver data der skal passes til en testmetode, og derved kan den samme metode kaldes flere gange hvor forskellige grænseværdier testes.

[RowTest]
[Row("Christian", "123")]
[Row("Christian", "", ExpectedException = typeof(InvalidUserException))]
[Row("", "123", ExpectedException = typeof(InvalidUserException))]
[Row("Christian", "qwerty", ExpectedException = typeof(InvalidUserException))] 
public void CheckUserLogins(string name, string password)

Det har desuden også en feature til at rulle database ændringer tilbage ved hjælp af attributterne SqlRestoreInfoAttribute, RollBack og RestoreDatabaseFirst.

XUnit findes på codeplex, og det er udviklet med henblik på at skulle passe bedre ind i .NET miljøet, samtidig med der er ryddet op i attributter og assertions med henblik på at få pænere testkode. Jeg kan personligt virkelig godt lide at det gør brug af generics, og at det giver mulighed for at lave en slags aspect oriented programming.

Generics bruges blandt andet til fixture setup, sådan at man ved at bruge IUseFixture<T> kan passe klasser til ens testmetoder, som man så kan arbejde med.

public class MyTests : IUseFixture<MyFixture>, IDisposable
{    
    public void SetFixture(MyFixture data)    
    {                
        data.SomeMethod();    
    }
}

Aspect oriented programming fungerer ved at man laver ens egne attributter ved f.eks. at extende BeforeAfterTestAttribute, som blot er at overskrive et par metoder.

public class PrepreDatabaseAttribute : BeforeAfterTestAttribute
{    
    public override void Before(MethodInfo methodUnderTest)    
    {        
        // Do your pre-test stuff    
    }    
    public override void After(MethodInfo methodUnderTest)    
    {        
        // Do your post-test stuff    
    }
}

Udover et decideret testframework skal man også bruge et tool til at udføre ens tests og give overblik over hvad der går godt og hvad der fejler – de berømte grønne lamper man nyder at se lyse når man benytter TDD. NUnit har den fordel at der følger et lille separat tool med der kan lige præcis det, og som virker ganske fint til de flestes behov. Til XUnit er der et lignende tool under udvikling, men det er stadig eksperimentalt og virker ikke just som et færdigt tool endnu.

Alle 3 frameworks kan imidlertid også bruges sammen med TestDriven.NET og ReSharper , som begge er bedre bud hvis man vil have en ordentlig brugsoplevelse.

 TestDriven.NET er et add-in til Visual Studio, som giver mulighed for afvikling af unit tests, og er det tool flertallet bruger. Jeg må dog erkende at jeg synes TestDriven.NET er relativt dyrt, taget i betragtning af at det startede som et gratis værktøj og i bund og grund stadig er et simpelt add-in.

Resharper er også et Visual Studio add-in som man kan skaffe til rundt regnet samme pris som TestDriven.NET, men man får bare meget mere med i pakken, da det blandt andet også tilbyder hjælp til refactoring, formattering og kode analyse. Som det fremgår er jeg selv faldet lidt for ReSharper, selvom jeg var lidt skuffet over at det endnu ikke er klar i en .NET 3.5 udgave, så kodeanalysen fejler hårdt på LINQ queries o.lign. En ny version målrettet .NET 3.5 skulle dog være på trapperne, så jeg må bare leve med at slå kodeanalyse fra indtil da.

Test af sprocs – der hvor det bliver mere vanskeligt.

Når jeg nu tidligere har nævnt at jeg mener sprocs er vanskelige at teste, skylder jeg også at beskrive hvordan man kan gøre det - og uddybe hvad jeg mener med at værdien i mine øjne er mindre end ved test af mere isolerede funktioner.

Jeg læste i går en ganske god artikel i MSDN magazine omkring brugen af LINQ to SQL til test af sprocs. Der var egentlig ikke et perspektiv der i første gang havde slået mig, men det er egentlig klart at LINQ to SQL er godt til at teste sprocs på meget lettere vis end det var muligt i tiden pre-LINQ. Helt enkelt består sproc tests af.

·         Klargøring af database, så den er i en velkendt tilstand.

·         Afvikling af sproc.

·         Test af databasens tilstand er som ønsket.

De tre trin lyder simple nok, man har naturligvis en række komplikationer i forhold til det her med databasens tilstand. Det letteste er sandsynligvis at arbejde med en tom kopi af databasen, som gerne er separat fra ens anden test/udviklings database der typisk indeholder en røvfuld ”real world” data. Ved hjælp af LINQ kan man så faktisk med meget få linjer kode slette alle data i en tabel, og indsætte de data man ønsker som grundlag for testen.

Ligeledes kan man i LINQ afvikle den sproc der skal testes, og så er der egentlig ”bare” tilbage at teste databasens tilstand efterfølgende. Et godt tip fra artiklen er at hente alt data i en tabel, hashe det ved hjælp af eksempelvis en MD5 hash. Resultatet kan så meget enkelt sammenlignes med en hash som man udregner ved udformning af testen – noget der kan være en kende besværligt, da det at tage hashen første gang man afvikler koden kun beviser at resultatet er det samme ved efterfølgende afvikling og ikke nødvendigvis om det er korrekt.

Få overblik med Unit testing af sprocs

En anden måde at bruge unit tests på i forbindelse med sprocs, som jeg selv har været med til at implementere er at skrive en parser der undersøger hvilke sprocs man kalder fra sin kode og sammenligne med de sprocs der rent faktisk findes i databasen. Selvom det ikke er nogen test af funktionaliteten som sådan, kan det på store projekter bruges til at teste om de sprocs man kalder findes og omvendt om man har sprocs der ikke længere bliver brugt.

Lidt i samme boldgade kan man skrive en unit test der læser ens sprocs ud, og gemmer dem i databasen igen - giver dette en exception er det en god indikation af at sproc’en er knækket. Igen er det ikke nogen gylden løsning da man ikke finder logiske fejl og ikke engang alle slags fejl på den måde. Det er imidlertid et simpelt værktøj, som har sin berettigelse i at det kan give overblik og finde alvorlige problemer med meget simple midler.

Tags: ,

Model-View-Controller - seperation of concerns

by DotNetNerd 2. November 2007 16:19

Model-View-Controller Framework

Frameworks der bygger på et Model-View-Controller pattern er blevet meget populære indenfor webudvikling, især Ruby on Rails vil mange kunne nikke genkendende til.

En af de store fordele ved MVC frameworks er at de giver "seperation of concerns" hvilket vil sige at man får adskilt datamodellen og brugergrænsefladerne. ASP.NET har været kritiseret for at netop det at opnå en klar adskillelse kan være meget svært idet en url mapper direkte til en aspx, som indeholder både markup og codebehind.

En anden force ved MVC frameworks er at de gør det muligt - og ligefrem naturligt - at basere sin udvikling på unittests. Dette er vigtigt ved udviklingen af større systemer, da man derved kan refaktorere uden at være nervøs for ikke at kunne overskue konsekvenserne.

Som alternativ til den almindelige aspx model er Microsoft derfor gået igang med at udvikle deres eget MVC framerwork, som skal passes direkte ind i .NET frameworket og understøtte både CLR og DLR sprog. MVC frameworket designes udfra at det skal være "extensible and pluggable", hvilket vil sige at der skal være muligt for udviklere at skifte ALLE enkeltdele af modellen ud hvis de ønsker at lave deres egen implementation. Derudover bliver der gjort meget ud af at frameworket skal performe godt og være "mockable" - altså det skal være muligt at lave unittesting baseret på mockups.

Routing regler 101

Routing er et kernebegreb i MVC frameworks, som går ud på at mappe en url til en given controller der skal håndtere det aktuelle request. Som standard vil MVC frameworket understøtte to former for mapning:

<Controller>/<Action>/<Param>
<SomeName>/<Action>/<Param> => <Controller>

Eksempelvis kunne man dermed lave en struktur der tillader redigering af produkter, hvor de følgende vil mappes til "rediger produkt med Id 4".

ProductsController/Edit/4
Products/Edit/4 => ProductsController

Udover at mappe til Controllers er det også muligt at mappe til ControllerFactories, som giver et abstraktionslag der kan dirigere videre til forskellige controllere alt efter hvad der skal udføres.

Routing kan f.eks sættes op i ApplicationStart eventet på Global.asax, og i de eksempler der har været vist indtil videre gør man sådan her:

Router.Routes.Add(
new Route("Products", "/Products/[action]/[id]", typeof(ProductController));


Controllers - systemets knudepunkt

Som tidligere nævnt er målet at designet skal være "extensible" og ud fra den devise er der flere mulige klasser der kan extendes, når man skal implementer sin egen controller.

Hvis man vil lave sin helt egen kan man tage udgangspunkt i interfacet IController, som har én metode kaldet Execute der modtager en IHttpContext og RouteData. RouteData er en dictionary af tokens fra url'en der udgør de parametre siden kaldes med.

public void Execute(IHttpContext context, RouteData routeData)
{
   
}

Alternativt kan man bygge videre på klasserne ControllerBase, Controller, Controller<T> eller IControllerFactory.
Det mest oplagte er at arbejde med Controller<T>, som er en typestærk standard implementation af IController.

Hver metode mapper her til en action, og parametre til de efterfølgende tokens i urlen. ControllerAction attributten fortæller at der er tale om en action, og ved at sætte DefaultAction=true indikerer man at denne metode skal kaldes hvis ingen action er givet af url'en. Udover denne attribut kan man tilføje andre til f.eks at håndtere caching.

class Products : Controller<ProductData>
[ControllerAction(DefaultAction=true)]
[OutputCache(Duration=10)]
public void List(int? number)
{
    ViewData["number"] = number;
    ProductData viewData = new ProductData();
    viewData.Number = number;
    RenderView("ProductView", ViewData); 
}

public class ProductData
{
    public int Number { get; set; }
}

ViewData bruges til at holde de data der skal passes til viewet. Der er som udgangspunkt en Dictionary til dette, med ved at bruge Controller<T> kan man angive en type man selv definerer.

Metoden RenderView bruges til at kalde et specifikt view og passe data til viewet.

Komplekse objekter kommer også til at kunne bruges som parametre ved hjælp af Type Descriptors som kan plugges ind.

Views - brugerflader rensede for logik

Views kan være aspx eller ascx filer med alt hvad de normalt kan, inclusiv brug af masterpages, bortset fra postbacks ikke er mulige og dermed undgår man at bruge viewstate.

Dette skyldes at views skal tilgås igennem en Controller, hvilket man ville bryde med ved at tillade postbacks.

Til at understøtte links ud kommer der blandt andet en hjælpeklasse der hedder html samt nogle extention methods. Skal man generere et link kan man f.eks. gøre følgende.

string link = Html.Link("Products", new {Action="Edit", param="4"});
string link = Html.Link<Products>(controller => controller.Edit(4));

På samme vis findes der en .Url metode der udelukkende returnerer url'en.

I den lidt mere fikse afdeling findes der også en metode til at lave links til paging som en pæn xhtml ul/li liste. Dette kræver at den liste man arbejder på implementerer IPagedList, som indeholder properties der beskriver det samlede antal elementer og index.

string paginationLinks = Html.PaginationLinks(viewData, "Products", "List", "10");

Af andre smarte metoder jeg lige vil nævne kort er der RedirectToAction til at håndtere redirects, og en UpdateFrom extention method, til at tage data fra Request.Form, et dataset eller andet og udfore en update.

RedirectToAction<Products>(c => c.List(0))

product.UpdateFrom(Request.Form)
Data kan fra views tilgås som tidligere antydet igennem ViewData, som kan være en type man selv definerer ellers igennem en Dictionary. Det er muligt på views det implementerer ViewPage<T> at tilgå data både via indexer og ved at tilgå properties direkte.

public class ProductView : ViewPage<ProductData>
{
    int i;
    i = ViewData["Number"];
    i = ViewData.Number
}

Ønsker man at benytte ajax vil der blive lavet sådan at man kan lave et kald og indsætte det returnerede html i en ny type panel.

Who am I?

My name is Christian Holm Diget, and I work as an independent consultant, in Denmark, where I write code, give advice on architecture and help with training. On the side I get to do a bit of speaking and help with miscellaneous community events.

Some of my primary focus areas are code quality, programming languages and using new technologies to provide value.

Microsoft Certified Professional Developer

Microsoft Most Valuable Professional

Month List