Pendlerscrumagileliv

by DotNetNerd 7. April 2009 16:59

Hvis Jokerens liv er et Junkiegøglercirkusliv må jeg betegne mit nye liv som et pendlerscrumagileliv. (Be warned: det her er en af de lidt bløde artikler om mig selv, og mine erfaringer - sorry).

Fra årsskiftet begyndte jeg at arbejde hos Vertica i Århus, men er stadig bosiddende i Odense. Det at skulle pendle var jeg spændt på da jeg tog imod jobbet, men det har vist sig ikke at være så hårdt som jeg kunne have frygtet. Jeg er som de fleste andre ikke voldsomt imponeret over DSB's planlægningsevner, og oplever dermed fra tid til anden lidt frustrationer. Alt i alt har det alligevel været rimeligt problemfrit at skulle pendle. Det skal siges at jeg ikke pendler hver dag, og arbejder i toget når jeg gør - hvilket naturligtvis også hjælper en del.

Udover at skulle tilpasse mig livet som pendler var det også et skifte til en virksomhed der i langt højere grad arbejder med scrum og agile principper. Det har betydet en noget anden arbejdsgang end jeg var vant til, og jeg må helt klart tilskrive mig den voksende skare af folk der tilslutter sig disse principper.

Scrum har været med til at gøre det lettere at fokusere på det der er jobbet - at skrive software - samtidig med at det giver en dejlig ærlig tilgang til tingene. De gevinster føler jeg allerede i hverdagen, selvom vi ikke selv mener at vi er færdige med at indføre scrum - og bliver man egentlig nogensinde bliver det? Jeg har været til JAOO days om agile udvikling i København, og vores projektledere har er blevet certificerede scrum mastere. Så det er et område vi har fokus på, og det er derfor rart at mærke at investeringen giver afkast - i modsætning til de fleste andre investeringer, som verden ser ud for tiden.

Til den mere tekniske side har jeg haft mere fokus på TDD, DDD og CI - som man ikke kommer udenom som moderne agile udvikler. Uden at være modstander  har jeg altid været lidt skeptisk overfor TDD, men jeg må erkende at jeg er begyndt at mærke gevinsten i form af bedre design, og følelsen af frihed til at refaktorere. Vi holdt codecamp i ANUG regi i starten af marts ved min kollega Daniel Gonzáles Garcia, og det virker til at være et emne der har rimelig stor interesse i communitiet. Forhåbentligt lokker det flere til at begynde at arbejde med frameworks som ASP.NET MVC - som jeg selv er igang med :)

DDD tankegangen har altid været det der faldt mig naturligt, kontra databasetænkning som har en tendens til at bide en i røven når et system bliver tilstrækkeligt omfattende - og dermed uoverskueligt. At vi direkte har fokus på principperne giver en god fælles terminologi, og kombineret med brugen af et ORM gør det livet som udvikler en del sjovere.

CI er for mig noget nyt at skulle bruge i praksis, og én umiddelbar erfaring har været at det fjerner en hel del af smerten ved at skulle udgive webløsninger. Det meste der skrives om CI handler om at få afprøvet den samlede kodebase, og få afviklet sine unittests. Dette er naturligt også et hovedfokus - men det at gøre udgivelse til en mere naturlig del af processen skal bestemt ikke overses som en vigtig gevinst.

 

Tags: , , , ,

Gmail som spamfilter

by DotNetNerd 5. April 2009 14:51

Forleden nåede jeg punktet hvor jeg var ved at være for træt af mit mailsetup. Jeg havde kun et elendigt webinterface til at checke min private mail fra, samtidig med at spamfighter efterhånden ikke var godt nok på grund af mængden af spammails. Problemet er at jeg stadig skulle vente på at hive mails ned, idet de først bliver filtreret fra lokalt.

På kombineret anbefaling fra henholdsvis Søren Spelling Lund og Martin Strøm gjorde jeg derfor det at jeg satte min gmail konto til at trække mine mails ind fra mailserveren. På den måde kan jeg udnytte gmails spamfilter, og samtidig checke mails via gmails webinterface. Derudover satte jeg IMAP op på min gmail konto, så jeg stadig kan læse mine mails fra outlook og andre e-mail klienter. Det er super simpelt at gøre, og det hele kan administreres ved at logge ind på gmail og gå ind under "Settings" -> "Accounts" og "Forwarding and POP/IMAP".

Det er helt klart en anbefaling jeg vil give videre, da det fungerer rigtigt godt, ved at man får det bedste fra gmail uden at give afkald på fordelene ved at have sin egen mailserver med en mail adresse i eget domæne.

Tags:

SQL management studio og den dummeste feature ever

by DotNetNerd 25. March 2009 08:53

Jeg løb for nylig ind i at SQL Server 2008 management studio smed en exception da jeg prøvede at ændre et tabel design "Saving changes is not permitted. The changes require the following tables to be dropped and recreated..."

Først troede jeg det var NHibernate der havde låst tabellen, da den var genereret af NHibernate, men efter lidt søgning fandt jeg ud af at det var Microsoft der går hårdt efter titlen "dumbest feature of the year". Af en eller anden grund synes de som standard at det ikke skal være muligt at lave designændringer der kræver at tabellen droppes i 2008 udgaven af SQL manager.

 Idag løb en kollega så ind i samme problem, og dermed slog det mig at det nok var værd lige kort at skrive om her på bloggen, hvordan man slår det fra. Det er så enkelt som at gå ind under tools -> options og slå et flueben fra under punktet designers som det kan ses her:

 

Tags:

ViewData, reflectionbaseret typemapping og performance implikationer

by DotNetNerd 22. March 2009 13:17

Et sted jeg ofte oplever friktion imellem practices og frameworks er imellem godt objektorienteret design og webudviklings frameworks. Veldesignede objekter er sjældent specielt velegnede til f.eks databinding og serialisering. Eksempelvis kaster serialiseringsprocessen i MVC frameworket en exception, hvis man forsøger at serialisere et objekt der er del af en mange til mange relation (hvor to klasser har collections indeholdende instancer af hinandens typer). Det giver fint mening at det forholder sig sådan i en serialiseringskontekst, men omvendt kan man ikke i sit design undvære mange-til-mange relationer. I forhold til databinding kan det være et issue at man gerne vil databinde et objekt hvor nogle properties er komplekse typer, hvorfra der skal noget logik til at afgøre hvilken værdi der skal representere objektet i brugerfladen.

Løsningen på den slags udfordringer er ofte at lave en ViewData klasse der som udgangspunkt er et subset af den oprindelige klasse. Properties som er mere komplekse kan så fjernes eller ændres, og udregnede eller relaterede data kan tilføjes viewet. Som bekendt er der ingen designbeslutninger uden konsekvenser, og her er den tydelige konsekvens at man nu skal skrive kode til at mappe imellem entiteter og viewdata. I mange tilfælde er det virkelig trivielt, da properties navngives ens, så for at undgå at skulle gøre dette manuelt skrev jeg en MapToView metode.

public static ViewType MapToView<EntityType, ViewType>(EntityType entity) where ViewType : new()
{
    var view = new ViewType();

    var entityType = entity.GetType();
    var viewType = view.GetType();

    foreach(var property in entityType.GetProperties())
    {
        var viewProp = viewType.GetProperty(property.Name);
        if(viewProp != null && viewProp.PropertyType == property.PropertyType)
        {
            viewProp.SetValue(view, property.GetValue(entity, null), null);
        }
    }

    return view;
}

Den er naturligvis reflection baseret, og så siger ens barnelærdom jo at man skal passe på hvad det betyder for performance. En helt kort test hvor jeg har to klasser med 10 string properties som jeg mapper 1000 gange viste over 5 observationer at det tager ca. 53 gange så lang tid med MapToView frem for med manuel mapning. Det skal dog ses i det lys at vi snakker omkring 145 millisekunder på en 3,2 GHz Pentium 4 for de 1000 mapninger - så med mindre der virkelig er skarpe designkrav omkring performance vil det næppe være et issue.

Tags:

getJSON æøå gotcha

by DotNetNerd 19. March 2009 15:42

Idag løb jeg ind i en lille gotcha forbindelse med brug af JQuerys getJSON til at sende brugerinput til en MVC controller action. Problemet var at karaktererne æøå blev encoded i forbndelse med kaldet.

Efter uden held at have roddet med at ændre hvilken encoding JQuery bruger fik jeg et tip fra min kollega Morten Bock om at det kunne være fordi det (naturligvis) sendes via http get og dermed skulle urlencodes. Doh! Derfra tog det så ikke lang tid at finde ud af at der i javascript findes en escape funktion der gør netop det - og så var det blot at decode ved hjælp af Server.UrlDecode på serveren. 

Anyhow, håber hermed min erfaring kan være til nytte for andre der løber ind i samme problem.

Tags:

JQuery Ajax debugging

by DotNetNerd 9. March 2009 20:36

Jeg løb fornylig ind i at jeg ville lave et ajax kald ved hjælp af JQuery og $.getJSON, men min action blev aldrig ramt og der blev ikke kastet nogen exceptions. Det viser sig at skyldes at getJSON forsøger at lave kaldet, men hvis det fejler ignorerer den det blot. Løsningen er at for at kunne debugge skal man istedet bruge $.ajax, som gør det muligt at registrere en errorhandler. Herfra kan man så tilgå det response der returneres, og hvis man udskriver det til siden får man en overraskende god fejlside, der gør det nemt at debugge.

Det var ikke et trick jeg fandt beskrevet nogen steder, så jeg synes det var værd at dele - og så er det ellers en af den slags posts jeg tror jeg selv bliver glad for næste gang jeg skal bruge den her lille snippet :-)

$.ajax(
{
    type: "GET",
    url: "/Controller/Action",
    data: { registrationTypeId: selectedValue },
    dataType: "json",
    error: function(xhr, status, error) {
        document.write(xhr.responseText);
    }, success: function(json) {
        alert("Data Returned: " + json);
    }
});

Tags: ,

xVal - fin løsning på klassisk problemstilling

by DotNetNerd 3. March 2009 17:11

Noget så basalt som validering der på overfladen virker som en simpel ting har alligvel en tendens til at ende med at ende med at blive uskønt i webløsninger. Der er to problemer jeg tit har set når jeg har kigget både mine egne og andres projekter igennem.

  1. Man bør implementere sin validering både client- og serverside. Dette fører til at man bryder DRY princippet, og laver valideringen dobbelt i henholdsvis javascript og ens eget CLR language of choise.
  2. Om noget er validt er i høj grad afhængig af kontekst  - se who knew domain validation was so hard .

Især punkt 1 er tit en tjørn i øjet på webudviklere, da de færreste synes det er sjovt at lave validering. Ligefrem at skulle gøre det samme to gange kan derfor være en pain - især når det så senere skal vedligeholdes.

Her kommer xVal til undsætning hvis man arbejder med ASP.NET MVC, da det gør det muligt at udtrykke sin validering ved hjælp af attributter man angiver på properties på sine entiteter. Samtidig gør det at man får flyttet sin validering ned i modellen, hvor man gerne vil have den.  Jeg vil undlade at komme med eksempler, da Steve Sanderson allerede har lavet nogle gode eksempler på sin blog. En stor bonus ved frameworket der fortjener at blive nævnt er at det er meget fleksibelt, både i forhold til valg af framework til clientside validering, og når man ønsker at implementere sine egne custom valideringer.

I forhold til punkt 2 bryder xVal umiddelbart med princippet om ikke at ligge valideringen på sine entiteter. Jeg vil imidlertid spille gråzone kortet, idet selve det at foretage valideringen er noget man styrer server- og clientside. Det er dermed helt muligt at lave andre typer af validering også, og anvende xVal specifikt til at validere brugerinput fra formularer.

 

Tags:

AOP - PostSharp vs Windsor

by DotNetNerd 27. February 2009 20:56

På mit seneste projekt har jeg kigget nærmere på at lave AOP ved hjælp af henholdsvis PostSharp og Castle Windsors IInterceptor. De to fremgangsmåder har hver sine fordele og ulemper, men begge har også nogle shortcomings.

Castle Windsors bud på AOP virker ved at man implementerer en IInterceptor, hvilket kræver at man skriver en Intercept metode der tager et IInvocation objekt som argument, hvorpå man kan kalde Proceed der hvor metoden skal indkapsles. Interceptoren registreres så for en klasse, hvilket bevirker at alle metoder på klassen indkapsles.
En typisk implementation ser sådan her ud:

public class LoggingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        // Entry logic
        invocation.Proceed();
        // Exit logic
    }
}

Postsharp, som et et lille framework til at lave AOP i .NET, virker ved at man implementerer en attribut der extender en af frameworkets aspects - eksempelvis OnExceptionAspect, OnMethodInvocationAspect eller OnMethodBoundaryAspect. I og med det er en attribut man implementerer påføres denne blot de metoder man ønsker skal indkapsles.
To helt typiske eksempler kunne være:

public class LoggingAttribute : OnMethodBoundaryAspect   
{       
    public override void OnEntry(MethodExecutionEventArgs eventArgs) { //Entry logic }        
    public override void OnExit(MethodExecutionEventArgs eventArgs) { //Exit logic }   
}

public class LoggingAttribute : OnMethodInvocationAspect   
{
    public override void OnInvocation(MethodInvocationEventArgs eventArgs)       
    {           
        //Entry logic
        eventArgs.Delegate.DynamicInvoke(eventArgs.GetArguments());           
        //Exit logic
    }
}

PostSharp er dermed mere finkornet i forhold til at man kan vælge hvilke metoder der indkapsles, og ved at man implementerer et passende aspect - omvendt er det i scenarier hvor alle metoder skal påvirkes og det virker dejligt ligetil med IInterceptor når amn alligevel bruger castle windsor.

Et punkt hvor castle windsor udmærker sig er at argumenter kan tilgås via IInvocation objektet ud fra navn frem for at de udelukkende kan tilgås via index - som desværre det eneste PostSharp tilbyder. Det er efter min mening en rimelig stor mangel i PostSharp, da det betyder at man ikke kan gøre koden robust i forhold til scenarier hvor et parameters navn er mere pålidelige end index - noget der er typisk i f.eks MVC løsninger.

I et scenarie jeg sad med fornylig var det actions på en controller, der bliver kaldt via reflection af MVC frameworket, som jeg ønskede at indkapsle, således at jeg via AOP kunne styre authorization. Her viste sig nogle uhensigtsmæssighed i begge måder at lave AOP. Det var for det første mere besværligt at finde ud af hvilken action der var kaldt, på grund af begge frameworks egentlig indkapsler de metoder der kalder min action via reflection. Derudover var det svært at lave koden solid i forhold til ændringer i navngivning af controllers og actions - da mine regler for authorization nødvendigvis må bindes op  på hvilken controller/action de gælder for.

Løsningen blev at lave unittests der via reflection verificerer at de authorization regler der er sat op rent faktisk matcher en controller og action. For at sikre at man ikke glemmer at sætte regler op for en given action indførte jeg desuden "secure by default" ved at nægte adgang til actions der ikke er konfigureret authorization for.

 

Tags:

Authorization i MVC

by DotNetNerd 9. February 2009 15:46

Ud af boksen er MVC frameworket udstyret med en AuthorizeAttribute, således at man kan angive på sine actions at det kun er brugere i bestemte roller der har lov at tilgå den.

[Authorize(Roles="Employee")]

Det i sig selv virker smart nok, men hvor tit har du lavet en løsning hvor authentization ikke er mere komplekst end det?

På mit nuværende projekt løb jeg hurtigt på det problem at en bruger godt må tilgå en action, hvis det id metoden tager som parameter er id’et på hans egen bruger. Altså med andre ord, han/hun må godt se egne data.

Jeg ville stadig helst undgå at skulle skrive kode i starten af mine actions til at undersøge den slags, da det er en af de ting der er oplagt at lave ved hjælp af AOP. Da attributter kun kan tage statiske værdier, var det udelukket at løse det ved at lave min egen FilterAttribute. Efter at have været lidt i tænkeboks fandt jeg frem til at bruge Castle Windsors IInterceptor til at lave validering af actions.

public class AuthorizationInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        if (invocation.Arguments != null && invocation.Arguments.Length > 0 && invocation.Arguments[0] != null)
        {
            if (invocation.Arguments[0].GetType() == typeof(RequestContext))
            {
                var context = (RequestContext)invocation.Arguments[0];
                var values = context.RouteData.Values;
                var auth = new AuthorizationManager();

                if (!auth.Authorize((string)values["controller"] + "/" + (string) values["action"], (string) values["id"]))
                {
                    throw new UnauthorizedAccessException("You are not authorized for this action");
                }
            }
        }

        invocation.Proceed();
    }
}

Selve det at lave authorization kan nu implementeres i en separat AuthorizationManager klasse, der også kan bruges i forbindelse med f.eks at generere en menu med de punkter, en bruger har ret til at se.

Efter blandt andet at have ladet mig inspirere af authorization via en config-fil fandt jeg frem til at jeg gerne ville samle konfigurationen, men at jeg dog ville undgå en xml-fil, og istedet have mulighed for at lave mere advanceret authentization. Det førte til nedenstående løsning, som jeg er blevet rimeligt godt tilfreds med, da det giver mig en stor grad af fleksibilitet.

public bool Authorize(string controllerAction, string id)
{
    IPrincipal user = HttpContext.Current.User;
    Employee empl = _repo.GetByUserName(user.Identity.Name);
    var employeeId = 0;
    int.TryParse(id, out employeeId);
    var dic = new Dictionary<string, Predicate<Employee>>
                  {
                      {
                          "Employee/Edit", employee => user.IsInRole(Config.Admin) ||
                                                       (user.IsInRole(Config.Employee) &&
                                                       employee.Id == employeeId)
                          },
                  };

    Predicate<Employee> pred;
    return !dic.TryGetValue(controllerAction, out pred) || pred.Invoke(empl);
}

Tags:

TFSBuild og NUnit tests

by DotNetNerd 27. January 2009 17:30

Forleden sad jeg og bankede hovedet imod en mur i form af et build der skulle konfigureres til at afvikle NUnit tests. Jeg fandt en række forskellige eksempler, men det gav mig alligevel lidt bøvl. Løsningen viste sig imidlertid at være simpel nok, men det er det jo tit når det først virker.

  1. Hent og installer MSBuild Community tasks
  2. Konfigurer TFSBuild.proj, som findes igennem Team Explorer, under build definitions, hvor der skal tilføjes:

<Target Name="AfterCompile">
    <CreateItem Include="$(OutDir)..\**\*Test.dll">
      <Output TaskParameter="Include" ItemName="TestAssembly" />
    </CreateItem>
    <NUnit
      Assemblies="@(TestAssembly)"
      OutputXmlFile="$(OutDir)UnitTests.xml"
      ContinueOnError="false"
      ToolPath="C:\Program Files (x86)\NUnit 2.5\bin\net-2.0" />   
  </Target>

CreateItem bruges til at skabe en liste over assemblies der som konvention hedder noget med Test.dll til sidst, og denne liste fodres så til NUnit tasken, der desuden skal peges hen til hvor NUnit er installeret.

Efter at konfigurationen var på plads prøvede jeg Build Notification Tool som er en del af TFS powertools – det kan klart anbefales frem for blot at få tilsendt en stribe e-mails når builds er kørt.

Tags: ,

Who am I?

My name is Christian Holm Nielsen, 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.

Month List