Regions or no regions – this is the question

Die dnc12 ist gerade vorbei und wir k├Ânnten uns schon wieder zusammensetzen ­čÖé
Heute gab es auf Twitter eine kurz angerissene Diskussion, die das Zeug dazu hatte, die Gem├╝ter aufzuheizen: soll man oder soll man nicht #regions nutzen?

 

Nach dem kurzen Tweet-Austausch wurde es klar, dass es viele Entwickler gibt, die Regions gerne nutzen. Ich habe zwar den ganzen Abend nachgedacht, habe allerdings keine Gr├╝nde gefunden, sie selbst verwenden zu wollen.

 

Ich meine, warum sollte man Code NICHT sehen wollen?

  • Geht es vielleicht um eine oder mehrere Methoden, die man ausblenden will? Das w├╝rde aber entweder bedeuten, dass man
    – die Funktionalit├Ąt der ganzen Klasse ausblendet, aber dann wozu, man ├Âffnet einfach die Klasse nicht ­čśë
    – nur ein Teil der Funktionen ausblendet, und dann stellt sich die Frage, warum manche Funktionen viel ├Âfter angeschaut werden als andere? Das hat f├╝r mich irgendwie ein CodeSmell
  • Geht es vielleicht um ein Teil einer einzigen Methode, und zwar einer ganz gro├čen, sonst w├╝rde man sie nicht teilweise ausblenden wollen? Zusammengeklappt w├╝rde man dann eine Art Kommentar sehen, was mich sofort an Martin Fowlers Hinweis bez├╝glich Kommentare erinnert hat: Kommentare sind ideale Namensgeber. Wenn man im Code einen Kommentar braucht, dann ist das meistens ein Smell f├╝r ein Extract Method (genauso wie die Tatsache, dass die Methode wahrscheinlich zu lang ist)

    You have a code fragment that can be grouped together.

    Turn the fragment into a method whose name explains the purpose of the method.

  • Geht es vielleicht um Regionen um Methoden, Events, Fields, Properties, also nach Sichtbarkeit und Rolle? Daf├╝r k├Ânnte ich einen einzigen Grund vorstellen, und zwar den, dass man auf Anhieb die ├Âffentliche Methoden und Eigenschaften sehen will. Das w├Ąre allerdings die Aufgabe eines Interfaces, oder? Dazu kommt auch noch meine – pers├Ânliche – Vorliebe, Code wie ein Buch zu lesen, von oben nach unten, also von einer ├Âffentlichen Methode weiter in die Details, also zu den privaten Methoden (ganz nach CCD – Single Level of Abstraction (SLA))

    Hilfreich als Analogie ist der Blick auf Artikel in der Tageszeitung: dort steht zu oberst das Allerwichtigste, die ├ťberschrift. Aus ihr sollte in groben Z├╝gen hervorgehen, wovon der Artikel handelt. Im ersten Satz des Artikels wird dies auf einem hohen Abstraktionsniveau beschrieben. Je weiter man im Artikel fortschreitet, desto mehr Details tauchen auf. So k├Ânnen wir auch unseren Code strukturieren. Der Name der Klasse ist die ├ťberschrift. Dann folgen die ├Âffentlichen Methoden auf hohem Abstraktionsniveau. Diese rufen m├Âglicherweise Methoden auf niedrigerem Niveau auf, bis zuletzt die “Bitpfriemelmethoden” ├╝brig bleiben. Durch diese Einteilung kann ich als Leser der Klasse entscheiden, welchen Detaillierungsgrad ich mir ansehen m├Âchte. Interessiert mich nur grob, wie die Klasse arbeitet, brauche ich mir nur die ├Âffentlichen Methoden anzuschauen. In ihnen wird die Funktionalit├Ąt auf einem hohen Abstraktionsniveau gel├Âst. Interessieren mich weitere Details, kann ich tiefer einsteigen und mir die privaten Methoden ansehen.

Was meint ihr, ├╝bersehe ich da was? (Notiz an mich: bei #nossued das Gespr├Ąch fortsetzen!)

Sind Unit Tests wirtschaftlich untragbar?

Immer wieder h├Âre ich die Aussagen “Unit Tests sind sch├Ân und gut, wir haben nur keine Zeit daf├╝r.” Oder “Klar, man kann Tests machen, hauptsache, es nimmt nicht zu viel Zeit von der Arbeit weg” ??!!

 

Nur um Missverst├Ąndnisse zu vermeiden: Tests macht man nicht zum Spa├č oder aus Langeweile, die Tests stellen die Essenz, die abstraktester Form der L├Âsung dar!

 

Ich habe bis heute Schwierigkeiten damit, meinem Gegen├╝ber zu erkl├Ąren, dass er sich irrt. Ich WEI├č es einfach aus Erfahrung, dass dies eine Milchm├Ądchenrechnung ist. Keine ernsthafte Argumente gegen Tests w├╝rden bei einer tieferen ├ťberpr├╝fung standhalten. Die Pros ├╝bertreffen klar die Kontras. Aber wie soll ich etwas – f├╝r mich – Offensichtliches in Worte fassen? Wie soll ich etwas in ein paar S├Ątzen erkl├Ąren, was ich in einem andauernden Prozess durch jeden NICHT (oder nicht richtig) geschriebenen Test gelernt habe? Oder durch jeden Aha-Effekt oder durch jeden stressfreien Release (kein Stress entsteht, wo kein Platz f├╝r Bugs existiert ­čśë )

 

Unit Tests sind f├╝r den Open Mind “selbsterkl├Ąrend”: wenn der Bug in einem ungetesteten Code steckt, dann wird das zu einer “blinden” Fehlersuche f├╝hren, die Tage dauern kann und auf jedem Fall Geld und Ruf kostet. Wie lange dauert es, den Fehler in einem getesteten Codebasis zu finden, wo die Eingrenzung innerhalb von Sekunden erfolgt? Wie oft kommt es ├╝berhaupt vor, dass dieses Problem entsteht? F├╝r mich schaut die Rechnung so aus:

 
Zeit_f├╝r_fehlersuche = Unproduktive_Zeit;
f(Unproduktive_Zeit) = Verschwendetes_Geld;
 
0->Zeit_f├╝r_fehlersuche(getesteter_Code)----------------------->Zeit_f├╝r_fehlersuche(ungetesteter_Code)---.....oo
 

Ok, ich glaube, ihr kennt jetzt meinen Standpunkt ­čśë Aber ich bin ja nicht die ultimative Ma├čstab daf├╝r, wie man arbeiten sollte. Deshalb habe ich ein paar Artikel und Statistiken von kl├╝geren Leuten zusammengesucht, bitte liest die auch.

 

Diese Infos habe ich bei stackoverflow gefunden:

Realizing quality improvement through test driven development: results and experiences of four industrial teams und hier eine Diskussion dar├╝ber.

The study and its results were published in a paper entitled Realizing quality improvement through test driven development: results and experiences of four industrial teams, by Nagappan and research colleagues E. Michael Maximilien of the IBM Almaden Research Center; Thirumalesh Bhat, principal software-development lead at Microsoft; and Laurie Williams of North Carolina State University. What the research team found was that the TDD teams produced code that was 60 to 90 percent better in terms of defect density than non-TDD teams. They also discovered that TDD teams took longer to complete their projectsÔÇö15 to 35 percent longer.

ÔÇťOver a development cycle of 12 months, 35 percent is another four months, which is huge,ÔÇŁ Nagappan says. ÔÇťHowever, the tradeoff is that you reduce post-release maintenance costs significantly, since code quality is so much better. Again, these are decisions that managers have to makeÔÇöwhere should they take the hit? But now, they actually have quantified data for making those decisions.ÔÇŁ

Es gab auch kleinere Experimente dazu wie z.B. Code Lab – TDD vs. Non-TDD

Over 3 iterations, average time taken to complete the kata without TDD was 28m 40s. Average time with TDD was 25m 27s. Without TDD, on average I made 5.7 passes (delivering into acceptance testing). With TDD, on average I made 1.3 passes (in two attempts, they passed first time, in one it took 2 passes.)

Now, this was a baby experiment, of course. And not exactly laboratory conditions. But I note a couple of interesting things, all the same.

Und weil ein Bild mehr als tausend Worte spricht: Die Kostenverteilung bei getesteten Code schaut ungef├Ąhr so aus
Testing Benefits

Tests schreiben ist einfach, der Ertrag ist riesig. Warum soll man also keine Tests schreiben? Sind wir wirklich unfehlbar, schreiben wir immer den perfekten Code? Seien wir mal ehrlich…Ich bin es sicher nicht und ihr auch nicht.

 

Und hier noch die obligatorische Buchempfehlung: The Art Of Unit Testing Das Buch ist wunderbar verst├Ąndlich geschrieben mit echten Beispielen und guten Argumenten, warum und wie man testen soll.

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.

NOS S├╝d – ein etabliertes Konzept

Man nehme 50 bis 80 engagierte Menschen, ein gemeinsames Thema (Softwareentwicklung rund um .NET), 4 oder 5 R├Ąume mit vielen St├╝hlen und ein paar Steckdosen und Flipcharts oder Beamer, gebe ausreichend Kaffee und ein Versprechen auf ein sp├Ąteres Bier dazu. Man gebe ihnen alle Freiheiten der Kreativit├Ąt – und eventuell ein Paar Gadgets, da es vorwiegend um M├Ąnner geht ­čśë – und lasse sie machen. Fertig ist das OpenSpace-Gericht, mit Erfolgsgarantie.

 

Nach ca. 60 Stunden werden alle NOS-S├╝d 2011 mit einem gef├╝llten “mentalen” Rucksack verlassen! Manche werden konkrete technische Fragen gekl├Ąrt bekommen haben, manche werden in ihrem Vorgehensweisen best├Ątigt und manchen werde eine ganz neue Richtung aufgezeigt. Manche lernen endlich die kennen, dessen (deren) Blogs sie seit langem lesen und manche werden aus der Anonymit├Ąt “des einsamen Softwareentwicklers” herauskommen und sich als “Nerds” outen. Es werden Freundschaften gegr├╝ndet und sicherlich auch k├╝nftige Gesch├Ąftsbeziehungen.

 

Und alle gehen m├╝de und voll mit Tatendrang nach Hause, sich in der Community weiter zu engagieren und n├Ąchstes Jahr wieder zu kommen.

 

Das alles ist Open Space und gilt speziell f├╝r den .NET Open Space S├╝d, der an diesem Wochenende abgehalten wurde. Erstens war er schon f├╝r das zweite Mal in Karlsruhe, wo es bekannterma├čen immer sch├Ânes Wetter ist ­čśë Zweitens waren da gerade so viele Menschen, dass keine Person und/oder Frage untergehen konnte. Aber das besondere “Salz” lieferten die Organisatoren dazu: Frank, Alex, Ralf und Aydin und all ihren gro├čartigen Helfer. Es ist f├╝r mich immer wieder erstaunlich, wo sie die Zeit und Energie finden, das alles “so nebenbei” zu organisieren. Manchanderer findet nicht mal genug Zeit, zu einem User Group-Treffen hin zu gehen und die Jungs opfern ihre Freizeit daf├╝r, uns diese j├Ąhrliche Treffen zu organisieren. Nochmal DANKE daf├╝r!

 

Ja, und nur zur Info: ich habe mir ein Twitteraccount eingerichtet ­čÖé

dotnet-cologne: veni-vidi-vici!

Am letzten Freitag fand die dotnet Cologne zum 3. Mal statt. Ich habe die ersten 2 Male nicht teilgenommen, aber wie ein Freund meinte, diesmal hatte ich “Heimvorteil” ­čÖé Nach der langen Pause, bedingt durch Beinbr├╝che, Umz├╝ge und ├Ąhnliche Erfahrungen, hatte ich regelrechte Entzugserscheinungen: Entzug von der Community.

Principles, patterns, and practices are important, but it’s the people who make them work. – Robert C. Martin aka Uncle Bob

Es war super! ├ťber 300 Leute, darunter sehr-sehr viele bekannte Gesichter, riesen Freude sie wieder zu sehen. Der erste Vortrag, den ich besucht habe, hie├č “Agile Architekturen” und wurde von Ilker abgehalten. Er hat zwei konkrete Beispiele – die Hexagonale Architektur von Alistair Cockburn und Data Context Interaction, der “neue MVC” – vorgestellt, samt Fallbeschreibung und Code f├╝r jeweils ein User Case. Wir d├╝rften/sollten uns dann eine Meinung ├╝ber die L├Âsungen bilden und diese Meinung auch kundtun. Es wurde schnell klar, dass jede Variante ihre Vor- und Nachteile hat, und dass die allgemein g├╝ltige “agile Architektur” nicht wirklich existiert.

 

Nach der Pause ging es dann f├╝r mich mit Daniel “REST Wars: WCF WebHTTP vs. ASP.NET MVC” weiter. Es war eine sehr interessante und kompetente Pr├Ąsentation. Am Ende hatte ich eine ganz genaue Vorstellung dar├╝ber, WOZU man REST verwenden soll und welche technologische M├Âglichkeiten man hat. Notiz an mich: WCF WebAPI bei Codeplex anschauen.

 

Als Lunch-Session wollte ich unbedingt von Sergey ├╝ber psake h├Âren, aber die Zeit ist bei den Gespr├Ąchen mit den Jungs von User Group Karlsruhe irgendwie verflogen. Daf├╝r habe ich stattdessen Kay Giza kennengelernt ­čÖé Endlich kann ich ein Gesicht zu jener Person zuordnen, die mir seit Jahren regelm├Ą├čig Tipps und Empfehlungen schickt. Er hatte selbst eine Session ├╝ber MSDN vorbereitet und ich h├Ątte ihn sehr gern geh├Ârt, aber er war parallel mit der Azure-Session und an dieser musste ich auf jedem Fall teilnehmen. Also hat Kay meine Fragen zum MSDN zwischen a flying coke ( ­čśë you know what I mean) und einen Kaffee im Foyer beantwortet. Danke sch├Ân ­čÖé

 

Der “├ťberflieger” des Tages war eindeutig Bart de Smet – der Mann, der in seiner Freizeit u.a. Sudoku mit c# (Stichwort Microsoft Solver Foundation) l├Âst.
Ich konnte leider nur den ersten von 2 Vortr├Ągen besuchen, ├╝ber “LINQ to Everything” – und das hat er wirklich wortw├Ârtlich gemeint. (Stichwort IQbservable, IScheduler)

 

Der vorletzte Vortrag war der bereits erw├Ąhnte “Azure: Portierung einer Anwendung”. Wir haben einen kleinen ├ťberblick von der Zusammensetzung von “the Cloud” bekommen, und die “Do’s and Dont’s” dazu. Und mir wurden diese zwei Tatsachen klar: in der Cloud alles kostet Geld und ohne Clean-Code (insbesondere ohne Dependency Injection) braucht man dar├╝ber gar nicht nachzudenken. Wenn aber die Vorbedingungen erf├╝llt sind, dann geht das Portieren super schnell und einfach.

 

Last but not least habe ich mir eine Session ├╝ber “Rich-Internet Apps & Mobile Anwendungen mit HTML5…” geg├Ânnt, ein Thema, mit dem ich mich zur Zeit nicht direkt besch├Ąftigen muss – zur Entspannung so zusagen ­čśë Also dies war eine super Entscheidung, Tim Fischer ist ein gro├čartiger Vortragender! Als Nebeneffekt habe ich erfahren, wie man JavaScript-Code ohne es zu schreiben generiert (Stichtwort Sencha) und was hinter dem Begriff HTML5 steckt.

 

Damit war f├╝r mich das Pflichtprogramm zu Ende, aber nat├╝rlich nicht der Tag.
Jeder, der bei solchen Community-Events schon teilgenommen hat, wei├č, dass die besten Gespr├Ąche rund um Entwickler-Sein bei dem/den abschlie├čenden Bier/en danach gef├╝hrt werden. So hatte ich die Ehre, endlich codemurai kennen zu lernen und die Meinungen der anderen ├╝ber Themen wie “warum ist Softwareentwicklung einer M├Ąnnerdomaine” oder “Absatzmarkt China” oder “das Geheimniss hinter dem Erfolg von osteurop├Ąischen Softwareunternehmen” zu h├Âren.

 

Es war sch├Ân, es war anstrengend und es war sehr lehrreich.
Genauso, wie eine Konferenz sein soll.

 

Tausend Dank an das Orga-Team und an die Sprecher f├╝r ihre gro├čartige Arbeit und f├╝r ihre M├╝he, diese Community zu st├Ąrken und zu pflegen.
“Individuals and Interactions over Processes and Tools” – wie das Agile Manifest es so sch├Ân definiert – weil wo w├Ąren wir, wenn das nicht war w├Ąre?!

 

Das n├Ąchste Event – NOS S├╝d 2011 – wartet schon…

Design copy-paste

www.codekicker.de
Irgendwann Anfang Februar habe ich von Marco Parrillo (Neue Mediengesellschaft Ulm mbH) eine Empfehlung f├╝r: “codekicker.de – Die deutschsprachige Entwickler-Community | Machen Sie mit!” bekommen. Ich finde so was immer super und habe die E-Mail sofort an meinen Kollegen weitergeleitet (die Empfehlung kam ja von einer seri├Âsen Gesellschaft).

Ich hatte in der Arbeit keine Zeit, also habe ich die Seite erst am Abend ge├Âffnet :
www.stackoverflow.com

Oh, dachte ich, super: eine deutsche Tochter von stackoverflow!

Auf den ersten Blick konnte man das nirgendwo sehen, also habe ich alles durchsucht: Impressum, Kontakte, sonstige Infoseiten, aber gar nichts… Danach habe ich einfach die Suchfunktion benutzt, aber das einzige Ergebnis eine Frage zu einem Stackoverflow-Exception war.

Durch googeln bin ich f├╝ndig geworden: die Seite ist gar keine Tochterseite von stackoverflow, sie wurde einfach nur kopiert! Auf die Suchbegriffe stackoverflow + codekicker habe ich folgende Diskussion bei stackoverflow gefunden:

In germany a Stackoverflow-like site was created, that is very, very similar to Stackoverflow in the mechanics of reputation and badges etc. That is so similar, that I think they could use the same software. Did you sell it to them? Or are they using a very similar clone-software? The Community I have in mind is Codekicker.

Das war ern├╝chternd (und gleichzeitig komisch, da es offensichtlich eine Diskussion auf codekicker ├╝ber das Thema gibt, aber irgendwie doch nicht gefunden wird).
Als ich dann die Antworten der Betreiber der Seite gelesen habe, wurde ich richtig entt├Ąuscht:

Vielen Dank f├╝r deine Anteilnahme an unserem Projekt ­čśë Du darfst uns gerne auf unserer Feedbackseite gr├╝ndlich deine Meinung sagen. Per Mail oder Telefon bin ich heute den ganzen Tag zu erreichen.

Gru├č,
Marvin

Irre ich mich, oder waren die 2 Studenten sogar stolz auf ihre copy-paste F├Ąhigkeiten? Und kann es wirklich sein, dass alle das ok finden und keine daran was auszusetzen hat? Ich meine, sogar die Logos sind ganz ├Ąhnlich. Und auch, wenn stackoverflow den Code nicht patentiert hat, jemand hat sich ja richtig viel M├╝he gemacht, das Design auszudenken, angefangen mit den Farben bis zum Gesamtbild.

Die Antworten variierten zwischen “das macht ja nichts, Hauptsache ist es auf Deutsch” und “wenn es dir nicht passt, dann nutze es nicht!” – was f├╝r mich erst Recht keine Antwort ist.

Ich ├╝berlege nun seit ein paar Wochen, ob ich das hier ansprechen soll, aber ich m├Âchte eure Meinung wissen:

  1. Bin ich wirklich die einzige, die diese Tatsachen st├Âren? W├Ąre es wirklich zu viel gewesen, irgendwo auf der Seite ein Dankesch├Ân an stackoverflow auszugeben?
  2. Auch wenn das von 2 Studenten OK w├Ąre, ist es auch in Ordnung, dass nun mehrere renommierte Zeitungen ihren guten Namen dazu geben?
  3. Ist es dann auch in Ordnung, dass diese Zeitungen mit einer kopierten Seite Geld machen wollen – da sie ja kr├Ąftig Werbung daf├╝r machen? Und diesen Satz habe ich gar nicht verstanden: “mit codekicker.de ist am 1. Februar 2011 die neue deutschsprachige Community-Plattform f├╝r Entwickler gestartet”? Die Seite gibt es ja schon seit Juli 2009.

Eins ist sicher: ich empfinde gro├čen Respekt gegen├╝ber Jeff und Joel und die anderen von stackoverflow und ich finde, sie leisten gro├čartige Arbeit (auch, wenn sie dies sicher nicht umsonst tun). Genauso einen Respekt habe hatte ich auch vor den Redakteuren dieser Zeitungen. Durch sie aber – da ich ihre Empfehlung weitergeleitet habe – habe ich nun auch eine Sache unterst├╝tzt, deren Betreiber es meiner Meinung nach nicht verdient haben. Mein Fehler, wird so bald sicher nicht wieder passieren.

File provided for Reference Use Only By Microsoft Corporation (c) 2007

Seit ein paar Wochen, wenn ich mit Resharper zu der Implementierung von manchen Microsoft-Funktionen navigieren will, bekomme ich die ganze dll heruntergeladen und danach den ganzen Code zu sehen:

// ==++==
//   Copyright (c)  Microsoft Corporation.  All rights reserved.
// ==--==
namespace System.Globalization {
    using System.Security.Permissions; 
    using System.Runtime.Serialization; 
    using System.Text;
    using System; 
    //
    // Property             Default Description
    // PositiveSign           '+'   Character used to indicate positive values.
    // NegativeSign           '-'   Character used to indicate negative values. 
    // NumberDecimalSeparator '.'   The character used as the decimal separator.
    // NumberGroupSeparator   ','   The character used to separate groups of 
    //                              digits to the left of the decimal point. 
    // NumberDecimalDigits    2     The default number of decimal places.
    // NumberGroupSizes       3     The number of digits in each group to the 
    //                              left of the decimal point.
    // NaNSymbol             "NaN"  The string used to represent NaN values.
    // PositiveInfinitySymbol"Infinity" The string used to represent positive
    //                              infinities. 
    // NegativeInfinitySymbol"-Infinity" The string used to represent negative
    //                              infinities. 
    // Property                  Default  Description
    // CurrencyDecimalSeparator  '.'      The character used as the decimal
    //                                    separator.
    // CurrencyGroupSeparator    ','      The character used to separate groups 
    //                                    of digits to the left of the decimal
    //                                    point. 
    // CurrencyDecimalDigits     2        The default number of decimal places. 
    // CurrencyGroupSizes        3        The number of digits in each group to
    //                                    the left of the decimal point. 
    // CurrencyPositivePattern   0        The format of positive values.
    // CurrencyNegativePattern   0        The format of negative values.
    // CurrencySymbol            "$"      String used as local monetary symbol.
    // 

    [Serializable] 
    [System.Runtime.InteropServices.ComVisible(true)] 
    sealed public class NumberFormatInfo : ICloneable, IFormatProvider
    { 

        // invariantInfo is constant irrespective of your current culture.

        private static NumberFormatInfo invariantInfo;
...

Das ist wunderbar, es ist gro├čartig zu sehen, wie die Klassen Random or DateTime aufgebaut sind. Obwohl ich keine Ahnung habe, warum das passiert… Ich hoffe allerdings, dass es kein Bug ist, und ich weiterhin den Code statt irgendeine Dokumentation sehen werde, auch wenn komischerweise am Ende der meisten Klassen der Titel dieses Artikels steht: File provided for Reference Use Only By Microsoft Corporation (c) 2007 ­čśë

Das alles ist cool, aber noch nicht wirklich ein Grund f├╝r einen Blogeintrag. Den folgenden Kommentar wollte ich euch aber nicht vorenthalten:

        // READTHIS READTHIS READTHIS 

        // This class has an exact mapping onto a native structure defined in COMNumber.cpp

        // DO NOT UPDATE THIS WITHOUT UPDATING THAT STRUCTURE. IF YOU ADD BOOL, ADD THEM AT THE END. 

        // ALSO MAKE SURE TO UPDATE mscorlib.h in the VM directory to check field offsets. 

        // READTHIS READTHIS READTHIS

        internal int[]  numberGroupSizes = new int[] {3};
...
        internal bool m_useUserOverride=false;    // NEVER USED, DO NOT USE THIS! (Serialized in Everett)
...

­čść

Recht auf benutzerfreundliche Software

Bei den letzten DNUGK├Âln-Treffen habe ich einen verbl├╝ffenden Satz geh├Ârt:

Jeder B├╝rger hat ein streitbares Recht auf benutzerfrendliche Software.

Die Grundlage wird durch die Bildschirmarbeitsverordnung (BildschirmarbV, Dezember 1996) geliefert. Die Liste der Anforderungen an den Bildschirmarbeitspl├Ątzen beinhaltet folegende Punkte:

21.
Bei Entwicklung, Auswahl, Erwerb und ├änderung von Software sowie bei der Gestaltung der T├Ątigkeit an Bildschirmger├Ąten hat der Arbeitgeber den folgenden Grunds├Ątzen insbesondere im Hinblick auf die Benutzerfreundlichkeit Rechnung zu tragen:
21.1
Die Software mu├č an die auszuf├╝hrende Aufgabe angepa├čt sein.
21.2
Die Systeme m├╝ssen den Benutzern Angaben ├╝ber die jeweiligen Dialogabl├Ąufe unmittelbar oder auf Verlangen machen.
21.3
Die Systeme m├╝ssen den Benutzern die Beeinflussung der jeweiligen Dialogabl├Ąufe erm├Âglichen sowie eventuelle Fehler bei der Handhabung beschreiben und deren Beseitigung mit begrenztem Arbeitsaufwand erlauben.
21.4
Die Software mu├č entsprechend den Kenntnissen und Erfahrungen der Benutzer im Hinblick auf die auszuf├╝hrende Aufgabe angepa├čt werden k├Ânnen.

Das erste, was mir – und ich bin sicher, nicht nur mir – in Sinn gekommen ist, war: wie zum Teufel konnte Windows dieser Verordnung entsprechen?? Ich denke dabei vor allem an Punkt 21.3 …

Am Ende des vorher erw├Ąhnten Satzes, gab es allerdings noch eine Bemerkung: “es wei├čt nur keiner“.

Also jetzt schon.

Off Topic: In dieser Liste gibt es noch einen letzten Punkt:

22.
Ohne Wissen der Benutzer darf keine Vorrichtung zur qualitativen oder quantitativen Kontrolle verwendet werden.

Und jetzt frage ich mich, ob all die Konzerne (Deutsche Bahn, Telekom und wie die alle hei├čen), die ihren Mitarbeiter ausgespitzelt haben, wirklich dieser Anforderung entsprechen…

40 Jahre – 1600 Kilometer

public static void Main(Events e)
{
    Wenn( e == als Steinbock-M├Ądchen in einer ungarischen Familie in Rum├Ąnien geboren)
    {
       Gl├╝cklich aufwachsen
       Ein gl├╝cklicher/in einer Diktatur dem Establishment trotzender Teenager sein 
//ohne Diktatur kann man ja nicht so gut trotzen

       /*
       Testlauf f├╝r eine Partnerschaft, Akzeptanzkriterien nicht erf├╝llt, Feature verworfen
       */

       Wenn( e == bei der einzig blutigem Umsturz in Europa in der vordersten Reihe stehen)
       {
            Sch├Ątzen lernen, was man hat und was man erk├Ąmpft hat.
            Die ersten "Communities" mitgr├╝nden
       }
       Wenn(e == !( Flie├čbandarbeiter von 7 bis 15 Uhr sein wollen ) )
       {
            Eine Uni f├╝r Maschinenbau - Fahrichtung Schienenfahrzeuge besuchen
            Coole Sachen erleben // Z├╝ge selbst fahren, z.B.
       }
       sonst
       {
           // else gibt es nicht!
       }

       Wenn(e == das beste Model "Ehemann" gefunden && Typeof(e) == Typeof(Ehemann) && e.Land == "Deutschland")
       {
           Alles neu Anfangen // Sprache, Land, Stadt ... Leben
           Wenn(Recht f├╝r ein neue Ausbildung durch Zeitarbeit erarbeitet)
           {
                Sich in die Anwendungsentwicklung-Umschulung st├╝rzen, alles lernen, was nur geht.
                Wenn( fertiggelernt )
                      9/11 => IT-Markt absturz // wie auch sonst alle Arbeitsm├Ąrkte

               Weitere Sachen lernen // wie. z.B. Lotus Notes
                Wenn(e == Job finden)
                {
                      Noch mehr lernen.
                      Job als Hobby und Hobby als Job definieren.
                      Community beitreten!
                      Noch VIEL mehr lernen.
                }
           }
           Wenn(e == es reicht, den Ehemann nur 3 Tage die Woche zu sehen, da er Consultant || TimeSpan > 6 Jahre)
           {
                 Neuen Job in K├Âln suchen //Stadt durch zweite Parameter vorgegeben
                 Sleep(7 Wochen) //Wegen ungeplanntem Beinbruch
                 super Job + super Kollegen + tolle Freunde + wunderbare Stadt + geniale Wohnung 
//Wetter k├Ânnte besser sein ...

                 Do
                 {
                      continue;

                 } while ( true );
           }
     }
}

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