Mrz 182017
 

Vor ein paar Tage bin ich an der Arbeit auf ein interessantes Phänomen gestossen, dass mir so bisher noch nicht bewusst war. Wenn man die Math.Round() Methode von .NET verwendet, dann heisst das nicht automatisch, dass bei 1.5 auf 2 und bei 2.5 auf 3 aufgerundet wird. Ein kleines Beispielprogramm zeigt das Verhalten der Math.Round() Methode des .NET Frameworks:

Und das Ergebnis:

Komisch, irgendwie haben wir das in der Schule doch mal anders gelernt… Die Antwort ist aber ganz einfach, denn in der MSDN Dokumentation steht unter Math.Round(double):

Rundet einen Gleitkommawert mit doppelter Genauigkeit auf den nächsten ganzzahligen Wert.

Im englischen heisst dieses Verfahren „Bankers Rounding“ und hat den Vorteil, dass bei einer Verteilung von Werten das arithmetische Mittel der gerundeten Zahlen gleich dem arithmetischen Mittel der nicht gerundeten Zahlen ist. Um dennoch das von uns gewüschte Verhalten zu erhalten, ist Math.Round() überladen und man kann zusätzlich noch das MidpointRounding mit angeben. Im folgenden Beispiel sieht man dann das umgestellte Programm:

Ergebnis:

Das Problem ist jetzt nicht riesig, aber dennoch ist es ein Verhalten, dem man sich bewusst sein sollte, wenn man mathematische Berechnungen durchführt. In unseren Anwendungen hat es in wenigen Fällen zu abweichenden Ergebnissen geführt und die Math.Round() Methode hatte dabei niemand auf dem Schirm.

Jan 182017
 

Vor einiger Zeit stand ich vor dem Problem, dass ich in einer Assembly feststellen musste, wo ich denn jetzt eigentlich laufe, um davon dann meine Weiterverarbeitung innerhalb der Assembly abhängig zu machen. Das hört sich erst einmal komisch an, lag aber daran, dass ich hier eine komplett autarke Komponente nicht wieder von anderen Assemblies abhängig machen wollte. In diesem Fall gab es dann auch gleich mehrere Möglichkeiten:

  • innerhalb einer von mir geschriebenen Anwendung
  • innerhalb einer von einem mir unbekannten Entwickler geschriebenen Anwendung (z.B. Konsole oder Desktop)
  • innerhalb des Unittest Runners

Die von mir geschriebene Anwendung besitzt natürlich einen Strong Name und zwar genau wie meine unabhängige Assembly. D.h. also, dass ich einfach den Public Key des aufrufenden Prozesses (eigene Anwendung, unbekannte Anwendung, Unittest Runner) mit dem Public Key meiner Assembly vergleichen kann und damit ganz einfach dieses Problem lösen konnte. Über Reflection kommt man auch relativ einfach an die entsprechenden Informationen, die man dafür braucht, heran.
Die folgende Methode ist dabei entstanden und liefert true zurück, wenn der Code der Assembly innerhalb einer von mir signierten Anwendung (Prozess) läuft. In allen anderen Fällen wird ein false zurückgeliefert.

Ist eigentlich ganz einfach und funktioniert bei mir ohne Probleme. Den entsprechenden Unittest erspare ich euch hier an dieser Stelle aber einfach einmal. Solltet ihr dennoch daran Interesse haben, dann einfach einen Kommentar hinterlassen und ich trage ihn noch schnell nach :-).

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 :).

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