Base your decisions on heuristics and not on gut feeling

As a developer we tackle very often problems which can be solved in various ways. It is ok not to know how to solve a problem. The real question is: how to decide which way to go 😯

In this situations often I rather have a feeling as a concrete logical reason for my decisions. This gut feelings are in most cases correct – but this fact doesn’t help me if I want to discuss it with others. It is not enough to KNOW something. If you are not a nerd from the 80’s (working alone in a den) it is crucial to be able to formulate and explain and share your thoughts leading to those decisions.

Finally I found a solution for this problem as I saw the session of Mathias Verraes about Design Heuristics held by the KanDDDinsky.

The biggest take away seems to be a no-brainer but it makes a huge difference: formulate and visualize your heuristics so that you can talk about concrete ideas instead of having to memorize everything what was said – or what you think it was said.

Using this methodology …

  • … unfounded opinions like “I think this is good and this is bad” won’t be discussed. The question is, why is something good or bad.
  • … loop backs to the same subjects are avoided (to something already discussed)
  • … the participants can see all criteria at once
  • … the participants can weight the heuristics and so to find the probably best solution

What is necessary for this method? Actually nothing but a whiteboard and/or some stickies. And maybe to take some time beforehand to list your design heuristics. These are mine (for now):

  • Is this a solution for my problem?
  • Do I have to build it or can I buy it?
  • Can it be rolled out without breaking neither my features as everything else out of my control?
  • Breaks any architecture rules, any clean code rules? Do I have a valid reason to break these rules?
  • Can lead to security leaks?
  • Is it over engineered?
  • Is it much to simple, does it feel like a short cut?
  • If it is a short cut, can be corrected in the near future without having to throw away everything? = Is my short cut implemented driving my code in the right direction, but in more shallow way?
  • Does this solution introduce a new stack = a new unknown complexity?
  • Is it fast enough (for now and the near future)?
  • … to be continued 🙂

The video for the talk can be found here. It was a workshop disguised as a talk (thanks again Mathias!!), we could have have continued for another hour if it weren’t for the cold beer waiting 🙂

Wie gesund ist eigentlich mein Code?

 

“software quality metric: A function whose inputs are software data and whose output is a single numerical value that can be interpreted as the degree to which software possesses a given attribute that affects its quality.”

 Definition nach IEEE Standard 1061 – [Quelle: Wikipedia]

Jede Software, deren Code lÀnger als ein paar hundert Zeilen ist, wird irgendwann den Punkt erreichen, dass man den Code auf Anhieb nicht mehr verstehen kann. Die meisten von uns schreiben Code, der Àlter als ein paar Monate ist und noch ganz viele Jahre erhalten bleiben soll. (Alle, die das nicht wollen, können hier aufhören zu lesen).

Das Problem, das man frĂŒher oder spĂ€ter bekommt, ist die KomplexitĂ€t unter Kontrolle zu halten. Jeder neuer Kollege hat das Problem, unbekannten, vorhandenen Code so schnell wie möglich zu verstehen. FĂŒr beide FĂ€lle ist es sehr hilfreich, wenn man Tools zur Hand hat, die zum Beispiel die ZusammenhĂ€nge und AbhĂ€ngigkeiten visualisieren können.

Als ich bei dem Open Space Karlsruhe die Frage gestellt habe, was die .NET-Community zu diesem Zweck nutzt,war die einstimmige Antwort : NDepend.  Code Metriken sind wichtig, sie sind aber nicht allmÀchtig. Wenn man allerdings wissen möchte, wie gesund sein Code ist, was sich verschlechtert hat und welche Baustellen aufgerÀumt wurden, dann ist NDepend das de facto Standardtool, welches benutzt wird.

Was macht das Tool eigentlich?

Um all die Features zu beschreiben, die NDepend hat, wĂŒrde man sehr viel Platz und Zeit benötigen – und zum GlĂŒck ist dies gar nicht nötig: auf deren Webseite findet man alles, was man braucht: Bilder, ErklĂ€rungen, weiterfĂŒhrende Links.

Ich wĂŒrde hier nur zwei wichtige FunktionalitĂ€ten herausheben:

  • Visualisiert

MVC-Runtime Dependency Graph
AbhÀngigkeiten im MVC-Runtime

 

Auf diesem Bild sieht man, dass man gar nichts sieht 😀

Stellt euch mal vor, ihr mĂŒsstet ab sofort an MVC weiterentwickeln. Wo wĂŒrdet ihr anfangen? Ich wĂŒrde hiermit beginnen und immer mehr reinzoomen.

Alle Verwender von DotNetOpenAuth.OpenId

 

  • ErklĂ€rt

Das coolste fĂŒr mich bei NDepend ist eigentlich nicht die Tatsache, dass es mir Statistiken und Grafiken liefert, sondern, dass es sie mir Diese auch  erklĂ€rt!

 

Interne AbhÀngigkeiten von DotNetOpenAuth.OpenId

 

Genau so lĂ€uft es auch mit den Metriken. Ich will nicht wissen, wie diese berechnet werden – eventuell spĂ€ter –  aber ich will wissen, was es bedeutet, wenn ein Wert zu hoch oder zu klein ist. Und das Tool erklĂ€rt dies alles oder leitet mich gezielt dahin weiter, wo es erklĂ€rt wird. Und so, ohne es zu merken, habe ich etwas gelernt, was meine CodequalitĂ€t höchstwahrscheinlich erhöhen wird. Ich kann dadurch ein besserer Programmierer werden.

Es gibt noch sehr viele GrĂŒnde, wofĂŒr man NDepend ausprobieren bzw. nutzen sollte. SpĂ€testens, wenn ein Team sich fĂŒr gemeinsame Regeln einigen möchte, sollte man die Einhaltung durch Tools wie dieses und StyleCop and co. absichern. Dadurch wird irgendwann egal, wie ungesund unserer Code heute ist, morgen wird es ihm auf jedem Fall besser gehen – und uns auch.

Create class from JSON

Ich habe vor einem Jahr bei einer katastrophalen MSFT-Veranstaltung ĂŒber ein super Feature in VS2012 erfahren, das ich – brownfield-bedingt – noch nie ausprobieren konnte. Heute hat es mir allerdings mindestens eine halbe Stunde Arbeit und eine große Menge Frust erspart!

Das Feature ist sehr schnell erklĂ€rt: wenn man ein Objekt, das als JSON oder XML serialisiert vorliegt – also einen string 😉 – in Zwischenspeicher hat, dann kann man das direkt als Klassenmodel abspeichern. Tatata..Fertig 🙂
Edit/Paste Special

Templating mit Razor aber ohne MVC

Ich habe unlĂ€ngst nach einer Möglichkeit gesucht, Seiten schnell und effektiv zu generieren, sowohl fĂŒr Web als auch fĂŒr E-Mails als Background-Jobs. Ein Kollege hat mich auf @razorengine aufmerksam gemacht und diese Templating Engine scheint alles zu bieten, was ich gesucht habe.

A templating engine built upon Microsoft’s Razor parsing technology. The RazorEngine allows you to use Razor syntax to build robust templates. Currently we have integrated the vanilla Html + Code support, but we hope to support other markup languages in future.

Die Installation ist so einfach wie möglich:

//mit NuGet:
Install-Package RazorEngine

Man muss danach nur noch die RazorEngine.dll und System.Web.Razor.dll referenzieren und das war’s.

 

Das Generieren von Seiten kann entweder direkt oder mit vorkompilierten Templates erfolgen:

[Test]
public void PageCanBeParsed()
{
   const string template = "Hello @Model.Name! Welcome to Razor!";
   var result = Razor.Parse(template, new {Name = "World"});

   Assert.That(result, Is.EqualTo("Hello World! Welcome to Razor!"));
}
//unterstĂŒtzt anonyme Klassen
[Test]
public void PageCanBeParsedWithCompiledTemplate()
{
   const string template = "Hello @Model.Name! Welcome to Razor!";
   Razor.CompileWithAnonymous(template, "world");
   var result = Razor.Run(new {Name = "World"}, "world");

   Assert.That(result, Is.EqualTo("Hello World! Welcome to Razor!"));
}
//oder konkrete Typen
[Test]
public void TemplateIsCompiledWithModelType()
{
   const string template = "Hello @Model.Name! Welcome to Razor!";
   var testModel = new TestModel{ Name = "World" };
   Razor.Compile( template, typeof(TestModel), "world2" );
   var result = Razor.Run(testModel, "world2");
   Assert.That(result, Is.EqualTo("Hello World! Welcome to Razor!"));
}

public class TestModel { public string Name; }

Um ehrlich zu sein, ich habe noch keinen Grund gefunden, warum man nicht die vorkompilierte Variante nutzen soll. In diesem Fall wird das Template EIN MAL kompiliert und in Cache abgelegt. Ein Vergleichs- und Stresstest, in dem ich ein halbwegs komplexes Template 500-mal mit Razor.Parse bzw. mit Razor.Compile + Razor.Run aufgerufen habe, hat folgendes geliefert:

   Parse: 03:35.97 min
   Compile+Run: 00:00.63 min

Ich glaube, damit ist alles gesagt. Es sei denn, eine Zeile weniger gilt auch als Argument 🙄

 

RazorEngine unterstĂŒzt fast alles, was Microsoft’s Razor in Views anbietet, wie zum Beispiel Helper-Methoden, Model-Definitionen direkt im Template oder partielle Views:

[Test]
public void EngineSupportsInlineHelper()
{
   const string template = @"@helper MyMethod(string name) {Hello @name}@MyMethod(Model.Name)! Welcome to Razor!";
   var testModel = new TestModel{ Name = "World" };
   var result = Razor.Parse(template, testModel);
   Assert.That(result, Is.EqualTo("Hello World! Welcome to Razor!"));
}

[Test]
public void EngineSupportsInheritsCommand()
{
   const string template = @"@inherits RazorEngine.Templating.TemplateBase
@helper MyMethod(string name) {Hello @name}@MyMethod(Model.Name)! Welcome to Razor!";
   var testModel = new TestModel{ Name = "World" };
   Razor.Compile(template, typeof(TestModel),"testModel");
   var result = Razor.Run(testModel, "testModel");

   Assert.That(result, Is.EqualTo("Hello World! Welcome to Razor!"));
}

[Test]
public void EngineSupportsSubtemplating()
{
    const string masterTemplate = "You are on www.yellow-brick-code.org!";
    Razor.Compile(masterTemplate, typeof(TestModel), "master");

    const string contentView = @"@inherits RazorEngine.Templating.TemplateBase
@helper MyMethod(string name) {Hello @name}@MyMethod(Model.Name)! Welcome to Razor!";
    var testModel = new TestModel{ Name = "World" };

    const string template = contentView + " @Include(\"master\")";

    Razor.Compile(template, typeof(TestModel), "testModelMaster");
    var result = Razor.Run(testModel, "testModelMaster");
    Assert.That(result, Is.EqualTo("Hello World! Welcome to Razor! You are on www.yellow-brick-code.org!"));
}

Und nun sind wir soweit, das Ganze im Web zu testen.

 

Die Engine funktioniert so, dass sie zur Laufzeit aus dem Template eine dll mit einem Zufallsnamen erstellt. Also wenn man die Engine im Web nutzen will, mĂŒssen noch ein paar Dinge getan werden:

  1. RazorEngine.Web.dll referenzieren
  2. Ein VirtualPathProvider in Global.asax.cs registrieren
    public class Global : System.Web.HttpApplication
    {
       protected void Application_Start(object sender, EventArgs e)
       {
          HostingEnvironment.RegisterVirtualPathProvider(new RazorVirtualPathProvider());
       }
    ...
    
  3. In Web.Config muss der BuildProvider registriert werden:
    <configuration>
    <configSections>
    <section name="razorEngine" type="RazorEngine.Configuration.RazorEngineConfigurationSection, RazorEngine" requirePermission="false" />
    </configSections>   <razorEngine factory="RazorEngine.Web.WebCompilerServiceFactory, RazorEngine.Web" /><system.web>
    <compilation debug="true" targetFramework="4.0">
    <buildProviders>
    <add extension=".csrzr" type="RazorEngine.Web.CSharp.CSharpRazorBuildProvider, RazorEngine.Web" />
    </buildProviders>
    </compilation>

So aufgerĂŒstet kann man mit den Models und Templates beginnen. Man kann die Templates als html-Dateien speichern. Allerdings wenn man IntelliSense haben möchte, dann muss MVC3 auf den Rechner installiert und die Datei als cshtml gespeichert werden.

 

Das Beispiel hier ist ĂŒber ein MasterHeader mit dem Anfang der Seite, ein MasterFooter mit dem Ende, beide eingebettet mit " @Include(\"master...\")" in Content. Die ganze Seite bekommt ein Objekt vom Typ Model zum Parsen. Alle Templates werden mit einem ITemplateFinder geladen.

...
ITemplateFinder templateFinder = new TemplateFinder(path);
Razor.Compile(templateFinder.GetTemplate("masterHeader.cshtml"), typeof(Model), "masterHeader");
Razor.Compile(templateFinder.GetTemplate("masterFooter.cshtml"), typeof(Model), "masterFooter");

var model = new Model
{
    PurchaseNo = "011313074142",
    Amount = "270.63",
    Date = "20110121"
};

var template = templateFinder.GetTemplate("Content.cshtml");
Razor.Compile(template, typeof(Model), "content");
var parsedTemplate = Razor.Run(model, "content");
context.Response.ContentType = "text/HTML";
context.Response.Write(parsedTemplate);

Bevor ihr was ĂŒber Namen oder Verantwortlichkeiten was sagt: das Projekt wurde als Spike erstellt, und als solche hat seine Rolle  perfekt erfĂŒllt 🙂 In Produktion wĂŒrde ich das Kompilieren von statischen Templates in Application_Start verschieben und das ITemplateFinder sollte auf  jeden Fall Injected werden.

 

Ich muss mich bei den 2 Jungs, die das Projekt entwickeln, sehr bedanken, es war eine super Idee! Schaut es einfach an, die dll kann noch viel mehr.

Tausende Codezeilen verstehen – aber wie?

Nach 7 Wochen Zwangsurlaub (siehe unten) bin ich wieder back to life: mit einem halbwegs neuen Bein (mit Titaneinlagen und Schlitzschrauben 😉 ), in einer neuen Stadt mit 100%-er Snowcoverage, in einem neuen Job – nach einem Monat VerspĂ€tung.

Das letzte Mal, als ich bei einer Firma den Code verstehen musste, ging es um ASP-Classic. Die AbhĂ€ngigkeiten waren ĂŒberschaubar, das Debugen ging mit Response.Write-Zeilen ;). Aber wie macht man das heute, wie versteht man den bestehende Code, der in vielen Jahren aus den fleißigen Fingern der Programmierern herausgeflossen ist? Und das im Web, in einer unglaublich flexiblen E-Commerce-Anwendung…

Die Lösung war einfach: mit Unit-Tests ! Ich musste nicht erklĂ€rt bekommen haben, WAS der Code tut, nur welche Aufrufe zu welchen Ergebnissen fĂŒhren. Immer, wenn ich ein Szenario verstanden habe, wurden dafĂŒr Tests geschrieben und das Ergebnis besprochen. Der Begriff unit wurde teilweise natĂŒrlich ausgedehnt, aber das hat nichts an der Tatsachen geĂ€ndert, dass am Ende

  1. ich den Code verstanden habe
  2. die meisten analysierten Zeilen durch einen Test abgedeckt wurden
  3. die Diskussionen ĂŒber den Testnamen dazugefĂŒhrt haben, dass manch unnötige Zeilen (lese “Szenarien”) entfernt wurden, also der Code besser geworden ist

Ich wurde getestet … und ganz gut gefunden!

Ich habe zufĂ€llig auf dem Blog von Gordon Breuer eine Webseite entdeckt, wo man seine Kenntnisse teilweise kostenlos testen kann. Ich habe mir den kostenlosen Test “C# 3.0 Fundamentals” ausgewĂ€hlt und jetzt kann ich hier ganz stolz das Ergebnis melden:

C# 3.0 Fundamentals

Scored higher than 64% of all previous test takers.

Demonstrates a clear understanding of many advanced concepts within this topic. Appears capable of mentoring others on most projects in this area.

Das ist aber ein super GefĂŒhl 🙂
Hier die Bewertung der Punkte:

How do I interpret my Brainbench test score?

Scores range from 1-5 with 5 being the highest in the Brainbench
scoring system. Within that range, Brainbench recognizes two levels
of achievement for standard assessments. A score between 2.75
– 3.99 earns the test taker the standard certification while
a score of 4.0 or higher certifies a master level of achievement.

Scores range from 1 to 5 and are divided into the
following proficiency level categories:

Test Overall Score
Range
Proficiency
Level
1.00 – 1.50 Novice
1.51 – 2.50 Basic
2.51 – 3.50 Proficient
3.51 – 4.50 Advanced Master
4.51 – 5.00 Expert

WĂ€hrend ich den Test gemacht habe, musste ich allerdings ziemlich oft wegen Resharper fluchen, weil der ja die ganze Arbeit macht, wenn es um sowas geht a = b ?? 0; aber bei Multiple Choice hat man ja kein Resharper 😆  (hallo RenĂ© …)