fredag, juli 25, 2008

Tillbaka från semester

Semestern är slut och jag har jobbat en vecka nu. Inte skulle det vara fel med lite mer ledighet men men… Jag är annars tillbaka på samma projekt som innan semestern vilket så klart är skönt (att ha något att komma tillbaka till). Veckan i projektet har bjudit på en hel del arkitekturförändringar då vi har lärt oss en del om komplexiteten i applikationen på sista tiden. Jag skrev lite om projektet som jag jobbar med i ett tidigare blogginlägg men den fina portaltanken har vi nu lämnat bakom oss. Det blev för mycket strul med kommunikation och svårare att dela state mellan applikationer. För mycket legacy kod och för lite tid helt enkelt.

Det som har varit glädjande under den här veckan är:

  • Vi har kommit igång med Scrum på allvar igen i projektet. Vi är nu mitt inne i en två veckors sprint och vår burn-down ser okej ut. Vet dock av erfarenhet att vi borde ha hunnit lite längre för jag tror att en del av uppgifterna är lite tunt estimerade.

  • Alla våra projekt är konverterade till Visual Studio 2008 och .NET Framework 3.5!

  • Jag har nyss checkat in mina första rader med LINQ-kod i ett produktionssystem!!! (mer om det i nästa inlägg)

  • Jag har skrivit mina första enhetstester på produktionskod i Visual Studio 2008.



Den här veckan har också upptäckt att jag är väldigt ifrågasättande vilket inte alltid är så positivt. Det finns en tendens hos mig att ställa frågan Varför? och kanske gör jag det lite för mycket ibland. Jag menar, bara för att jag inte skulle implementera en lösning på samma sätt så betyder det inte att det är en sämre lösning, antagligen snarare tvärt om!

Veckan som kommer bjuder på upplopp i sprinten samt förberedelse inför Agile2008 i Toronto!

Var för övrigt och såg The Dark Knight igår och jag säger bara oj oj oj! Ser fram emot att se den på IMAX i Toronto nästa helg!

torsdag, juni 12, 2008

Snippet för Singleton

Många gånger har jag tänkt att jag ska göra en snippet för att skapa en singleton men det har aldrig blivit av men idag, efter en lyckad release hos kund, så tycket jag att jag kunde ta mig fem minuter för att knåpa ihop en sådan som sedan kommer att spara in de fem minuterna om och om igen. Och om jag sedan också kan spara fem minuter åt någon annan så är väl det toppen!

Min singleton är baserad på DoFactorys Singleton med .NET optimized code men jag har bytt ut deras accessor, som är en metod, till en property pga jag tycker att det då blir snyggare att accessa den från annan kod då. Man slipper parenteserna i anropet.

Skapa en ny fil i Visual Studio av typen XML File,döp den till singleton.snippet, spara den i \My Documents\Visual Studio 2008\Code Snippets\Visual C#\My Code Snippets\ och klistra in följande kod:


<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">


  <CodeSnippet Format="1.0.0">


    <Header>


      <Title>singleton</Title>


      <Shortcut>singleton</Shortcut>


      <Description>Code snippet for singleton class</Description>


      <Author>Björn Eriksen - Connecta</Author>


      <SnippetTypes>


        <SnippetType>Expansion</SnippetType>


      </SnippetTypes>


    </Header>


    <Snippet>


      <Declarations>


        <Literal>


          <ID>className</ID>


          <ToolTip>The name of the class</ToolTip>


          <Default>SingletonClassName</Default>


        </Literal>


        <Literal>


          <ID>methodName</ID>


          <ToolTip>A method in the singleton class</ToolTip>


          <Default>MethodName</Default>


        </Literal>


      </Declarations>


      <Code Language="CSharp">


        <![CDATA[


          public sealed class $className$


              {


                  //This is the instance that will hold the instance


                  private static readonly $className$ instance =


                    new $className$();


 


                  //Private constructor


                  private $className$()


                  {


                  }


 


                  //The property used to return the singleton instance


                  public static $className$ UniqueInstance


                  {


                      get


                      {


                          return instance;


                      }


                  }


 


                  //Add methods


                  public void $methodName$()


                  {


 


                  }


              }


        ]]>


      </Code>


    </Snippet>


  </CodeSnippet>


</CodeSnippets>


onsdag, juni 11, 2008

Lazy Load och Eager Load med LINQ to SQL

Lazy Load

LINQ to SQL implementerar i grunden ett pattern som heter Lazy Load. Lazy Load innebär att man, som i fallet med LINQ to SQL har att göra med en databas, bara hämtar de rader som man behöver när man faktiskt behöver dem. Inom LINQ kallar man det för Deferred Query Execution vilket betyder att man kan definiera en fråga i ett läge men att kopplingen mot databasen sker först när man börjar iterera resultatet.

När man deklarerar en fråga för att t ex hämta alla kunder som finns i en stad som börjar på bokstaven M:

            var customers = from c in db.Customers

                            where c.City.StartsWith("M")

                            select c;


så kommer det att skapas en representation av frågan i form av ett Query Expression Tree. Om man då sätter break point och debuggar kan man se vilken SQL som kommer att exekveras. Men det är först när man använder någon information från resultatet:

            foreach (var customer in customers)

            {

                Console.WriteLine(customer.ContactName);

            }


som raderna faktiskt hämtas. Så frågan ovan genererar en server-round trip som returnerar 13 rader (om man använder sig av Northwinds databas).

Om man sedan går vidare på varje kund och skriver ut dess ordrar enligt följande:

            foreach (var customer in customers)

            {

                Console.WriteLine(customer.ContactName);

                foreach (var order in customer.Orders)

                {

                    Console.WriteLine(" - " + order.OrderDate.ToString());

                }

            }


så kommer man att för varje kund-objekt generera en ny SQL och hämta just den kundens ordrar. Det innebär att iterationen över kundernas ordrar kommer att generera 14 server-round trips.

Det här kan vara väldigt bra i vissa lägen men mindre bra i andra lägen. Tänk att man har ett presenteras en trädvy där alla kund-objekt visas och sedan väljer användaren att bara expandera en av dessa kunder för att visa kundens alla ordrar. Ja då kanske det är bättre att i bara hämta just den kundens ordrar istället för att skicka över alla kunders ordrar.

Eager Load

Men om man nu har en sådan situation där man vet att man vill ladda alla kunder och alla dess ordrar, dvs man vill använda sig av Eager Load istället för Lazy Load, ja då finns det förstås en lösning och det är DataLoadOptions.

För att lyckas med Eager Load i LINQ så skapar man ett objekt av typen DataLoadOptions och anropar en metod som heter LoadWith. I LoadWith anger man vilka objekt man ska ladda samtidigt som det huvudobjekt man hämtar. Detta gör man med hjälp av ett lambdauttryck. DataLoadOptions-objektet lägger man sedan till i DataContext-objektet. Här nedan har jag använt mig av en object initializer för att sätta propertyn samtidigt som jag skapar objektet.

            var dlo = new DataLoadOptions();

            dlo.LoadWith<Customer>(p => p.Orders);

            var db = new NorthwindDataContext() { LoadOptions = dlo };


Den frågan som jag ställde i början av det här inlägget gällde att hämta alla kunder som bor i en stad som börjar på bokstaven M. När man då skapar ett DataLoadOptions-objekt så är det ett objekt av typen Customer som man anger som typ till den generiska metoden LoadWith och det här objektet är det som kallas grundobjektet. I lambdauttrycket anger man sedan vilket typ av objekt som man vill ladda samtidigt som det grundobjekt man planerar att hämta. Detta innebär att man med en server-round trip kommer att hämta kund-objekten samt dessa kunders alla ordrar.

DataLoadOptions-objektet kan man sedan fylla på med flera relaterade objekt av andra typer som man vill ladda samtidigt som huvudobjektet.

            var dlo = new DataLoadOptions();

            dlo.LoadWith<Customer>(p => p.Orders);

            dlo.LoadWith<Order>(o => o.Order_Details);


Lazy Load är ett fantastiskt pattern men det är väldigt viktigt att man känner till vilka implikationer det kan få att använda det. Lazy Load innebär alltid ett mer chatty interface vilket som sagt kan vara bra ibland men helt förödande i andra lägen.

onsdag, maj 14, 2008

reSharper 3.1 med C# 3.0...

Igår installerade jag reSharper 3.1 på min Visual Studio 2008. Bättre intellisense, bättre refactoring-stöd och en allmänt trevligare utvecklingsmiljö var det som lockade. Tyckte också att det skulle bli kul att se vilket extra stöd man fick till de nya features i C# 3.0 så utan att läsa på allt för mycket installerade jag den senaste versionen, 3.1. Hoppade direkt in och skapa en ny console application i mitt favorit direcotry d:\junk\ och började skriva min favorit LINQ-fråga:

var procs = from p in Process.GetProcesses()

          select p;

 

Men istället för p så poppade en skum intellisense upp och ville ha en typ av nått slag... skrev om skrev om och skrev om men jag fick inte till frågan. Började tro att jag hade hamnat i akut LINQ-koma! Men det visade sig så klart att reSharper 3.1 inte har stöd för C# 3.0 utan då måste man vänta till version 4.0.

 

Det alternativ man har är att ladda ner den senaste nightly builden från reSharper 4.0 men det känns lite väl hard core just nu med tanke på att vissa av byggena är taggade som Not Recommended.

 

 

Så, dags för avinstallation. In på add/remove programs och plocka bort den - gick mycket smärtfritt och sedan tillbaka in till Visual Studio igen men...

 

Ingen intellisense!

 

Det visade sig dock att det bara var en checkbox under Tools/Options/Text Editor/C#. Av någon anledning återställer inte avinstallationen av reSharper "Auto list members" - Puh!

 

Men visst är det så att man är lite sugen på att ladda ner senaste bygget och testa 4.0...

fredag, maj 02, 2008

Plugin-pattern på webben

Martin Fowler har i sin bok Patterns of Enterprise Application Architecture beskrivit ett plugin patter som man kan använda för att länka ihop applikationer genom konfiguration istället för vid kompilering. Min tanke var att bygga en webbapplikation, typ en portal, som sedan blir medveten om att andra applikationer existerar bara genom en konfigurering istället för att man måste känna till den vid utveckling. Min vision var att kunna utveckla och uppgradera portalen för sig och sedan utveckla och uppgradera applikationer för sig.

Jag började med att definiera ett interface som varje applikation måste implementera. Det interfacet ska kunna leverera information om applikationen i fråga:

    public interface IApplicationInfo

    {

        string ApplicationName { get; set; }

    }

 

Sedan la jag till en PluginFactory med en statisk metod getPlugin. Den metodens uppgift var att läsa in assemblyt (snyggt ord) från disk och skapa en instans av den klass som implementerar IApplicationInfo och returnera denna...

public static IApplicationInfo getPlugin(string assemblyName)

{

var assembly = Assembly.LoadFrom(assemblyName);

var assemblyTypes = from a in assembly.GetTypes()

                    select a;

 

foreach (var t in assemblyTypes)

{

    var o = Activator.CreateInstance(t);

    if (o is IApplicationInfo)

        return o as IApplicationInfo;

}

return null;

}

 

Först placerade jag min PluginFactory i samma Visual Studio 2008 projekt som Portalen men det gjorde att mina enhetstester mot getPlugin blev otroligt sega att köra eftersom att den måste starta igång webservern först. Det blev dock betydligt bättre när jag flyttade ut den till ett eget class-library. Ett härligt bevis på hur test-driven utveckling gör att man fattar beslut tidigt som gör att ens arkitektur blir mer testbar!

Nästa steg var att lägga till en AppSetting i min web.config för varje applikation som jag vill att portalen ska känna till och använde mig av en LINQ-fråga för att hämta ut dessa:

var applications = from a in ConfigurationManager.AppSettings.AllKeys

                   where a.StartsWith("PortalApplication")

                   select new { AssemblyName = ConfigurationManager.AppSettings[a] };

 

Grymt coolt! Refelction, LINQ, plugin-patterns och allt möjligt coolt men sen då? Vad har jag vunnit med det här jämfört med att bara lägga in den här informationen i web.config eller i en databas. Hur ska jag nu få mina applikationer att agera i portalen som om de var en del av portalen från första början?

Ju mer jag funderar på det hela desto mer ser det ut som att det är Facebook jag vill bygga (fast utan den sociala delen)... För det är ju precis det Facebook är, en portal med viss gemensam funktionalitet och ett antal tjänster som sedan applikationsutvecklare kan nyttja för att bygga egna applikationer som jackas in i portalen. Så hur har Facebook löst interaktionen mellan en applikation och portalen? Kör varje applikation i en IFrame eller? Är det någon som vet??

tisdag, april 22, 2008

Fråga via Messenger på min blog

Det är fantastiskt kul när någon kontaktar mig på Messenger genom min blog. Då känns det verkligen att det finns någon där på andra sidan som läser det man skriver då och då. Idag hände det för andra gången men den här gången var jag på lunch och kunde inte svara :-(

Frågan handlade om hur man estimerar uppgifter i en sprintplanering i Scrum och om man bör dela upp estimaten för en uppgift i implementation respektive i test.

På Sprint Definition Meeting (som man har innan Sprint Planning Meeting) kommer teamet överens med produktägaren vilka product backlog items man ska implementera under den kommande sprinten. Dessa bryter sedan teamet ner till uppgifter under sprintplanneringen och varje uppgift estimeras. Dessa uppgifter ska estimeras utifrån ett sedan tidigare definierat klart-begrepp där det i min värld absolut ingår test!

Så säg att "Klart" för ett specifikt team betyder "Kodat, Verifierat, Granskat, Incheckat", ja då ska estimatet på 5 story points innebära att det är just kodat, verifierat, granskat och incheckat. Om klart-begreppet istället är "Kodat & Incheckat" (vilket det är för många utvecklare) så har man aktivt valt att lägga test utanför sprinten.

Det kan så klart också vara helt okej att lägga test utanför sprinten. Om man tex har en testavdelning och en testprocess som är implementerad och fungerar bra så tycker jag inte att man ska riva den och flytta in testresurserna i teamen. I alla fall inte initialt, utan då tycker jag att man ska anpassa sig till det man har och se till att man ökar kvaliteten på sina leveranser till testavdelningen tex genom testdriven utveckling.

John, hoppas att det här var svar på frågan du ställde på messenger och om inte är det bara att du hör av dig igen!

onsdag, april 16, 2008

Bug vid konvertering till 2008?

Idag fick jag en fråga från en tidigare uppdragskollega om att konvertera en web-applikation jag jobbat med till Visual Studio 2008. Han hade försökt men lyckades inte och fick det härliga och informativa System.Runtime.InteropServices.COMException. Inget i event loggen, ingen info i konverteringsloggen, ingenting... Man tackar!

Det projektet använder sig av EPiServer och Web Application Project (WAP). WAP var ju först en separat download till 2005, ingick sedan i SP1 och är nu en del av VS2008 så jag trodde att felet var där men icke. Felet ligger istället i hur de olika versionerna av Visual Studio hanterar om IIS finns installerat på utvecklarmaskinen eller inte.

Det finns en inställning under project properties där man kan välja om man ska använda den inbyggda web servern eller om man ska använda IIS. I VS2005 kan man välja det senare alternativet även om man inte har IIS installerat men det kan man inte i VS2008 utan får ”The IIS Web Server is not installed on this computer”.

Det trevliga COMException får man om man först skapar ett Web Application Project i 2005’an, sätter att den ska använda IIS utan att ha IIS installerat och sedan öppnar det i 2008’an.

Så lösningen är antingen att se till att IIS är installerat innan konverteringen till 2008 eller så går man in i projektfilen och ändrar True till False.

[Update 2008-04-22]
Buggen är verifierad sedan länge av produktteamet och kommer att rättas i nästa release (SP1).

tisdag, april 15, 2008

.NET 3.5 Enhancements Training Kit

Som jag har skrivit i ett tidigare inlägg på min blog så finns det ett VS2008 & .NET 3.5 Training Kit. Det här paketet har varit källan till en hel del när det gäller de seminarier jag har hållit tillsammans med Addskills om nyheterna i VS2008 och .NET Framework 3.5. Demos, slides och exempelkod har nyttjats.

Nu är det släppt ett liknande training kit för .NET 3.5 Enhancments som berör följande, kommande, tekniker:
- ADO.NET Data Services
- ASP.NET MVC
- ASP.NET Dynamic Data
- ADO.NET Entity Framework
- ASP.NET Ajax History
- ASP.NET Silverlight Controls

Med tanke på vilken källa till kunskap det förra training kittet har varit så kändes det här som en något perfekt att sätta tänderna i! Men... Det saknas en hel del.

"Presentations will be added in a future release of the training kit."
"Demos will be added in a future release of the training kit."
"Screencasts will be added in a future release of the training kit."
"Resources will be added in a future release of the training kit."

Det enda som finns med är ett par Hands-on labbar. Lite besviken blev jag men precis som de skriver så kommer det att komma i kommande releaser av training kitet.

.NET 3.5 Enhancements Training Kit

Dags för beta-cert!

Idag släpptes tre nya cert från Microsoft i det som kallas .NET 3.5 exams:

70-502: Windows Presentation Foundation
70-503: Windows Communication Foundation
70-504: Windows Workflow Foundation

Dom betatestades under början av året så om det var någon som skrev den under beta-tiden så börjar resultaten att trilla ner nu. Det tar alltså ett par månader från det att man skriver tills man får reda på om man klarade eller inte. Under tiden så utvärderas frågor och feedback, frågor stryks och ändras och sedan sätts en nivå som blir den som gäller för att klara beta-certet. Logga in på MCP-siten - där ser man resutlatet snabbast.

Det är också två andra cert som just nu beta-testas:

70-561: Microsoft .NET Framework 3.5, ADO.NET Application Development
70-562: Microsoft .NET Framework 3.5, ASP.NET Application Development

Betaperioden pågår fram till den 4 maj och det är gratis att skriva. Observera att tiden för certet är fyra timmar och att det är betydligt mycket fler frågor än på ett vanligt cert.

När man ska anmäla sig till beta-cert behöver man en kod och certen börjar med nummer 71 istället för 70.

71-561 – beta code = 561B1
71-562 – beta code = 562B1

Själv ska jag skriva den 29 och 30 april.

onsdag, mars 12, 2008

Cert som pensioneras under 2009

Om ett år, 2009, så kommer ett antal Microsoft-cert som leder fram till MCAD, MCSD och MCDBA att pensioneras. Detta innebär dock inte att man kommer att förlora titeln från sitt transcript. Däremot innebär det att man inte längre kommer att kunna använda något av följande cert i sin examensplan:

Exam 70-300: Analyzing Requirements and Defining Microsoft .NET Solution Architectures
Exam 70-301: Managing, Organizing, and Delivering IT Projects by Using Microsoft Solutions Framework 3.0
Exam 70-305: Developing and Implementing Web Applications with Microsoft Visual Basic .NET and Microsoft Visual Studio .NET
Exam 70-306: Developing and Implementing Windows-based Applications with Microsoft Visual Basic .NET and Microsoft Visual Studio .NET
Exam 70-310: Developing XML Web Services and Server Components with Microsoft Visual Basic .NET and the Microsoft .NET Framework
Exam 70-315: Developing and Implementing Web Applications with Microsoft Visual C# .NET and Microsoft Visual Studio .NET
Exam 70-316: Developing and Implementing Windows-based Applications with Microsoft Visual C# .NET and Microsoft Visual Studio .NET
Exam 70-320: Developing XML Web Services and Server Components with Microsoft Visual C# and the Microsoft .NET Framework
Exam 70-330: Implementing Security for Applications with Microsoft Visual Basic .NET
Exam 70-340: Implementing Security for Applications with Microsoft Visual C# .NET
Exam 70-228: Installing, Configuring, and Administering Microsoft SQL Server 2000 Enterprise Edition
Exam 70-229: Designing and Implementing Databases with Microsoft SQL Server 2000 Enterprise Edition