Apr 042016
 

Das Singleton Entwurfsmuster wird in einer Softwarearchitektur verwendet, um sicherzustellen, dass eine Objektinstanz nur einmal erzeugt wird und diese zumeist auch noch global verfügbar ist. Ich verwende es in meinen Entwürfen genau dann, wenn ich dem Anwender die Möglichkeit geben möchte, möglichst einfach auf zentrale Funktionen der zugrundeliegenden Architektur zuzugreifen und diese auch nur einmal vorhanden sein sollen. Es gibt einige Nachteile die man sich dadurch einfängt und eines der Hauptprobleme liegt sicherlich beim Testen. Wie testet man bspw. die Erzeugung des Singletons richtig? Schliesslich wird das Singleton bereits kreiert wenn ich es zum ersten Mal aufrufe und da meine Tests unabhängig voneinander laufen sollen, würden meine nachfolgenden Tests vom bereits kreierten Singleton beeinflusst werden, was ich auf jeden Fall vermeiden möchte.

In unseren Anwendungen verwenden wir immer separate Unittest Assemblies, um die eigentlichen Assemblies mit der Funktionalität zu testen. Die Sichtbarkeit wird über das „InternalsVisibleTo“ Attribut (siehe meinen vorherigen Artikel) für das zu testende Assembly so geändert, dass mit dem „internal“ Modifizierer versehenen Klassen, Methoden, Properties, etc. für das Testassembly sichtbar sind. Im Singleton kann jetzt eine Methode oder ein „set“ eingebaut werden, die das Singleton wieder sauber entfernt.

In der folgenden Klasse habe ich eine „Close()“ Methode implementiert und das „Instance“ Property erweitert. Welche der beiden Wege ihr bevorzugt hängt davon ab, ob weitere Aufräumarbeiten beim Schließen des Singletons notwendig sind (in diesem Fall würde ich eine Methode implementieren) oder ob ein einfaches Setzen des „Instance“ Properties auf „null“ bereits ausreichend ist.

Abschließend sei noch zu erwähnen, dass ich es versuche die Modifikation von Quellcode für anschließende Unittests zu vermeiden, da ich der Meinung bin, dass man damit bereits in die Programmlogik eingreift und Fehler verursachen könnte. Die Modifikation des Singletons halte ich deshalb für eine technische Krücke, die man an dieser Stelle leider nicht vermeiden kann. Wie macht ihr das in eurem Code? Ähnlich oder habt ihr eine elegantere Möglichkeit?

Mrz 022016
 

Wir alle bemühen uns performanten und möglichst effizienten Code zu schreiben und auch gegebenenfalls vorhandenen Legacy Code zu verbessern. Um seinen Code zu optimieren gilt die gute alte Regel – messen, messen und nochmal messen, denn nur so kann man die Engpässe vernünftig identifizieren, um danach gezielt eine Lösung zu suchen. Ich arbeite im Normalfall an dieser Stelle mit der guten alten Stopwatch, die man unter System.Diagnostics im .NET Framework findet.

Scott Hanselman hat in seinem Blog aber eine weitere, sehr elegante Möglichkeit vorgestellt, um Methodenaufrufe und Programmteile zu bewerten. Er verwendet dazu die Open Source Bibliothek BenchmarkDotNet, die man natürlich auch als NuGet Package bekommen kann. Fügt man sie einem Projekt hinzu, so kann man mittels dem Attribut Benchmark Methoden markieren, die man genauer betrachten möchte. Über den BenchmarkRunner kann man dann die Klasse mit den Attributen aufrufen.

Am besten sieht man das an einem kleinen Beispiel, das man so auch auf der GitHub Seite von BenchmarkDotNet findet. Die Idee hinter den Beispiel ist es, die Hashverfahren MD5 und SHA256 miteinander zu vergleichen. Wir erstellen also eine einfache Klasse, die ein Array mit Zufallswerten erzeugt und darauf mit dem Aufruf von zwei Methoden, die mit dem Benchmark Attribut markiert werden, sowohl den MD5 als auch den SHA256 laufen lassen:

In der Main Methode unserer Anwendung (oder in einem anderen Teil der Anwendung) starten wir dann mit

den Benchmark. Die Bibliothek führt jetzt den Benchmark auf den Methoden durch und das kann durchaus etwas dauern. Am Ende erhaltet ihr dann eine Zusammenfassung des Benchmarks, die bspw. so aussehen kann:

Im bin-Verzeichnis findet ihr außerdem noch wesentlich ausführlichere Ergebnisse des Benchmarks, so unter anderem auch Readme Dateien für die gängigsten Webdienste (bspw. GitHub und StackOverflow), aber auch CSV Dateien, die ihr weiter analysieren könnt. Natürlich kann man noch wesentlich mehr mit der Bibliothek testen (bspw. die unterschiedlichen JIT Varianten, Anzahl der Prozessoren, die .NET Runtime, etc.) oder auch die Ergebnisausgabe an eigene Vorgaben anpassen.
Was verwendet ihr denn so für das Benchmarking von Methoden und Programmteilen? Auch Stopwatch? Die BenchmarkDotNet Bibliothek? Etwas anderes? Würde mich über einen Kommentar von euch freuen :-)!

Mai 232015
 

In den letzten Tagen bin ich zum ersten Mal über eine Stelle gestolpert, an der ein „goto“ tatsächlich auch in C# einmal sinnvoll ist. Normalerweise versucht man den Sprung zu irgendwelchen Labeln zu verhindern und in den meisten Fällen braucht man den Befehl auch gar nicht. Allerdings stand ich gerade vor dem Problem, dass ich einen Switch-Case Block so definieren wollte, in dem nach einem Case die darunterliegenden Cases auch ausgeführt werden – also das break nicht notwendig ist. In Java ist das möglich, nicht aber in C#.
Hier ein Beispiel, wie ein solcher Switch-Case Block in Java aussehen könnte:

Das Beispiel ist ganz einfach: Je nach Länge des Arrays wird auf die vorhandenen Elemente irgendeine Operation durchgeführt. In diesem sehr einfachen Beispiel ist das nur eine simple Addition. Lässt man in C# allerdings das break weg, quittiert der Compiler das mit einer Fehlermeldung („Control cannot fall through from one case label (‚case x:‘) to another“). Bleibt also nur Codeduplizierung, oder? Nein, nicht wirklich, denn genau hier kommt das vielgeschmähte goto ins Spiel, da man mit ihm die Labels (inkl. default) innerhalb des Switch-Case Blocks anspringen kann. Damit lässt sich das Beispiel von oben, das in Java funktioniert, ganz einfach auf C# umstellen:

Eine recht einfache Lösung, oder? Bisher kannte ich diese Vorgehensweise noch nicht, aber man lernt ja nie aus :).

Jan 232015
 

Beim Schreiben von Unittests bin ich mal wieder darüber gestolpert, dass jemand speziell für die Unittests Getter und Setter angelegt hat, da er auf die privaten Variablen der Klasse nicht zugreifen konnte. Im Prinzip hat er damit für seinen Unittest die internen Variablen dann über den Zugriffsmodifizierer public dann doch wieder sichtbar gemacht, wenn auch nur indirekt. Das ist so natürlich nicht gewollt, denn sonst hätte man gleich den Zugriff auf die internen Variablen erlauben können. Vielleicht noch kurz zur Erklärung: unsere Unittests sind immer in eigenständige Assemblies ausgelagert, sodass wir von Außen auf die zu testenden Klassen zugreifen müssen. Das macht auch Sinn, da die Unittests in dem Kompilat nicht enthalten sein sollen. Wie kann man das Problem also lösen?

Das .NET Framework bietet dafür das Attribut InternalsVisibleTo aus dem Namespace System.Runtime.CompilerServices an. Um nun die internal Methoden, Variablen und Properties freizugeben, wird das Attribut in die AssemblyInfo.cs des zu testenden Projekts eingefügt.

Danach kann man mit dem im InternalsVisibleTo-Attribut angegeben Assembly seine Unittests auf den Klassen durchführen ohne alles Zugriffsmodifizierer auf public zu setzen.

Solltet ihr eure Assemblies signieren, muss das einzufügende Attribut um den Public Key des zugreifenden Assemblies erweitert werden. Zusätzlich muss außerdem das zugreifende Assembly signiert werden. Der Eintrag in der AssemblyInfo.cs sieht dann so aus:

Das ist natürlich nur eine Herangehensweise, aber – wie ich finde – eine doch recht elegante. Wie macht ihr das in euren Unittests? Habt ihr eine ähnliche Vorgehensweise oder schreibt ihr einfach gar keine ;-)?

Dez 222014
 

Was soll man eigentlich viel über Clean Code schreiben? Es ist ja eigentlich offensichtlich, dass man im Sinne der Wartbarkeit, Einheitlichkeit und Verständlichkeit seinen Quellcode formatieren sollte. Dennoch wird es nicht auf Anhieb gelingen 100%ig sauberen Code zu entwickeln, aber dafür gibt es ja Tools wie bspw. StyleCop, die in den Buildprozess eingebunden werden und den geschriebenen Code analysieren und entsprechend Warnungen oder Fehlermeldungen ausgeben. Ich selbst habe mich bspw. beim Schreiben meines Codes immer an den Klassen des .NET Frameworks gehalten und auch versucht bei unseren Frameworks die angebotenen Methoden daran zu orientieren. Das fällt nicht immer leicht, ist aber notwendig, um den Anwender einen schnellen Einstieg zu ermöglichen. Selbst in privaten Projekten habe ich mittlerweile begonnen, mich an diverse Regeln zu halten, brav Unittests zu schreiben und StyleCop in den Buildprozess zu integrieren. Das kann zwar nervig sein, da man so nicht mal eben schnell ein kleines Tool entwickelt, das man gerade braucht, aber irgendwie habe ich mich daran gewöhnt so zu arbeiten und fühle mich dabei besser. Auf der anderen Seite habe ich mir dadurch aber auch schon einige Zeit gespart, die sonst bei der Fehlersuche verloren gegangen wäre.
Dennoch brandete bei einem Vortrag vor kurzem die Diskussion auf, ob Clean Code überhaupt notwendig sei. Schliesslich komme es nur auf Variablenbenennung und Methodennamen an, den Code kann man dann schon lesen. Tools wie StyleCop würden „Fingerpointing“ betreiben und die Entwickler an den Pranger stellen, wenn die Warnings oder Fehler im Buildprozess auftauchen. Man solle also den Entwicklern lieber ihre Freiheiten lassen.
Ich frage mich, ob es wirklich so ist, dass Entwickler nicht kritikfähig sind und es nicht vertragen, wenn man gewisse Vorgaben und Regeln bei der Implementierung einhalten soll. Das kann ich mir eigentlich gar nicht vorstellen. Sucht man selbst nicht permanent nach Möglichkeiten, den eigenen Code zu verbessern und effizienter zu arbeiten? Ich verstehe, dass man nicht auf einen Schlag den bisher geschriebenen Code Refaktorisieren und auch nur schwer argumentieren kann, dass bereits funktionierender Code noch einmal angepasst werden soll – er funktioniert ja und macht nachher letztendlich das Gleiche. Leider wird es bei dieser Argumentation von gewichtiger Stelle dann aber auch sehr schwierig, diese Methodik einzuführen.
Wie sieht es bei euch aus? Dürft ihr die Clean Code Prinzipien anwenden? Wie konntet ihr Clean Code einführen oder gab es auch Vorbehalte gegen Clean Code?

Durch die weitere Nutzung der Seite stimmst du der Verwendung von Cookies zu. Weitere Informationen

Die Cookie-Einstellungen auf dieser Website sind auf "Cookies zulassen" eingestellt, um das beste Surferlebnis zu ermöglichen. Wenn du diese Website ohne Änderung der Cookie-Einstellungen verwendest oder auf "Akzeptieren" klickst, erklärst du sich damit einverstanden.

Schließen