Hydorah


Wer findet, dass die Spiele früher einfach besser waren, der sollte sich unbedingt mal Hydorah ansehen. Das ist wirklich ein Game der alten Schule. In alter horizontal shooter Manier muss man sich durch sehr schön designte Level kämpfen. Eigentlich habe ich ja bisher nur den ersten erleben ( noch nicht überleben ) dürfen, aber ich bin sicher die folgenden sind auch alle gut.

Enumerations als bit fields verwenden


Als ich letztens einen Unittest schrieb, fiel mir auf, dass ich in vielen Tests immer wieder die selbe Methode des Testees aufrief. Alles was sich änderte waren die Stubs und die Mock Objekte. Das Ganze sah ziemlich schlecht aus. Es musste sich doch irgendwie vereinfachen lassen. Ich versuchte also den Code in eine neue Methode auszulagern. Diese könnte ich dann von meinen Tests aus aufrufen. Aber wie konnte ich die Parameter so gestalten, dass die Signatur übersichtlich blieb? Da fiel mir ein, dass ich schon mal irgendwo gesehen hatte wie man enumerations als bit fields verwenden kann:

Ausgangspunkt soll folgendes enum sein:

public enum Colors
{
    None,
    Red,
    Green,
    Blue
}

Da enumerations eine Art name/value pair collection sind, kann man jeden Eintrag auf eine Zahl mappen. Die folgende Schleife tut dies für die Werte 0 bis 7 und gibt den Namen aus:

for (int i = 0; i < 8; i++)
{
    Console.WriteLine("{0,3} - {1}", i, ((Colors)i).ToString());
}

Das enum von oben liefert folgendes Ergebnis:

0 – None
1 – Red
2 – Green
3 – Blue
4 – 4
5 – 5
6 – 6
7 – 7

Das ist recht unspektakulär. Der C# Compiler hat einfach für jeden Eintrag im enum einen Zahlenwert vergeben. Von 0 beginnend, bis 3. Wenn man die Enumeration um das Flags Attribut ergänzt, ändert sich die Ausgabe noch nicht wirklich. Eigentlich traurig, weil man das enum dann immer noch nicht als Bitfeld verwenden kann.

Bei einem binären wert von 0011 ist nicht klar ob hier Rot und Grün oder nur Blau gemein ist. Deshalb müssen wir das enum noch ein wenig ändern:

[Flags]
private enum Colors
{
    None = 0,
    Red = 1,
    Green = 2,
    Blue = 4
}

Hier wurden jetzt neben dem Flags Attribut noch die Nummern von Hand vergeben. Damit kann man verhindern, das Bau anstelle der 3 die 4 bekommt. Binär sieht das dann so aus:

0000 – None
0001 – Red
0010 – Green
0100 – Blue

Wenn nun wieder die Schleife von weiter oben ausgeführt wird, sieht das Ergebnis ganz anders aus:

0 – None
1 – Red
2 – Green
3 – Red, Green
4 – Blue
5 – Red, Blue
6 – Green, Blue
7 – Red, Green, Blue

Das liegt daran, dass zum Beispiel die 7 binär eine 111 ist. Es ist also das bit für Rot, Grün und Blau gesetzt.

Nun könnte man sich eine Methode mit folgender Signatur bauen:

public void SetColors( Colors color )

Das schöne ist jetzt das man nicht nur eine sondern mehrere Farben vergeben kann. Zum Beispiel Rot und Grün:

SetColors( Colors.Red | Colors.Green  )

Rot und Grün wird mit einem binären ODER verknüpft das ergibt dann den Wert: 0011. Dieser wird an die Methode übergeben.

Innerhalb von SetColors kann man dann mit folgendem Code prüfen, welche Farben aktiv sind:

public static void SetColors(Colors colors)
{
    if (IsColorSet(colors, Colors.Red))
    {
        //Do something
    }

     // ...
}

private bool IsColorSet(Colors colors, Colors colorToCheckFor)
{
    return (colors & colorToCheckFor) == colorToCheckFor;
}

Der kombinierte Wert wird also mit einem logischen UND mit dem zu prüfenden Wert verknüpft. Dadurch werden alle Bits gekippt, die nicht im zu prüfendem Wert 1 sind.
Bei Rot und Grün haben wir zum Beispiel 0011. Nur Rot ist die 0001. Und aus 0011 & 0001 wird 0001. Also wieder Rot.

Enumerations sind zusammen mit dem Flag Attribut also sehr gut geeignet um Optionen weiterzugeben, bei den auch verschieden Kombinationen möglich sind.

Die drei Platt’schen Regeln


In der aktuellen Ausgabe des .NET Magazins beschreibt David Platt seine drei Platt’schen Regeln über Software.  Im Wesentlichen lauten sie wie folgt:

  1. Software an sich hat keinen Wert. Der Wert ergibt sich aus der gesteigerten Zufriedenheit seiner Nutzer.
  2. Dies kann erreicht werden durch die Unterstützung  bei einer Aufgabe. Oder wenn sie es schafft den Benutzer in einen vergnüglichen Zustand zu versetzen.
  3. Dabei darf der Benutzer nichts von der Anwendung merken. Sie darf ihn nicht behindern oder unterbrechen.

Das Programm müsste also den Benutzer kennen lernen anstatt der Benutzer das Programm.  Da das Programm aber nicht so recht lernen kann, muss diese Aufgabe vom Entwickler übernommen werden. Das klingt nach einer schwierigen Aufgabe.

Hier gehts zum MSDN Artikel

Bücher: “Von Bienen und Leitwölfen”


Ich habe es wieder mal geschafft ein Buch zu lesen. Und zwar handelt es sich dabei um “Von Bienen und Leitwölfen” von Matthias Nöllke. Viele Regeln aus der Natur gelten nämlich genauso fürs Business. Zum Beispiel, dass man immer mit Maß vor gehen sollte. Steckt man zum Beispiel, ein paar Piranhas in ein Becken mit vielen Goldfischen, werden diese nicht sofort alle vernascht. Die Piranhas essen sich nur satt. Sie überfressen sich nicht. Die übrigen Goldfische werden am Leben gelassen. Es werden ihnen lediglich die Flossen abgebissen, damit sie auch schön dableiben. Versuchen sie das doch mal mit Ihren Kunden.

Debugger sehr sehr sehr langsam


Nach einem ClearCase update wurde mein Rechner beim Debuggen fruchtbar langsam. Jeder Schritt beim Debuggen dauerte über 5 Sekunden. Aber nur mit Projekten, die auf einem ClearCase View liegen. Eine kleines Testprojekt auf der lokalen Platte lief ohne Probleme.
Fast einen ganzen Tag habe ich nach Lösungen im Internet gesucht, aber nichts hat geholfen. Dann kam ich auf die Idee meine Einstellungen zu reseten und siehe da, es geht wieder! Was jetzt wirklich das Problem war weiß ich aber leider nicht.

SQL Server Compact Edition


Vor kurzem habe ich die Compact Edition des SQL Servers ausprobiert. Diese gibt es ja schon länger, aber ich dachte immer sie währe nur für mobile Geräte nützlich. Doch weit gefehlt. Wenn man dem Nutzer seiner Anwendung das installieren eines SQL Servers ersparen will, kann man einfach die dll’s der CE Version mit deployen. Mehr ist nämlich nicht nötig und so muss nicht immer eine SQL Server Instance im Hintergrund laufen.

Wenn man eine Anwendung mit der CE Edition entwickeln möchte, muss man sich diese zuerst installieren. Dabei wird, wie gesagt, aber keine Instance angelegt. Es werden lediglich dll’s auf die Platte kopiert. Die Datenbank erstellt man am besten mit dem SQL Server Management Studio. Dazu bei Server type einfach SQL Server Compact Edition angeben und bei Database file „new Database“ wählen. Danach noch den Anweisungen folgen. Das Ganze funktioniert leider nur mit der 2008er Version des Management Studios. Was man, soweit ich weiß, nicht einzeln herunterladen kann.

Wenn man seine Datenbank erstellt hat, bedient man sie am besten mit Linq to SQL. Seinen Mapper Code kann man sich von sqlmetal erstellen lassen, dass beim Visual Studio und im .NET SDK dabei ist:

sqlmetal e:\TimeProofer.sdf /namespa ce:MyNamespace /password:mypass /code:TimeProofer.cs

Das erstellte Codefile kann man dann in sein Projekt einfügen und zum Beispiel so verwenden:

TimeProofer tp = new TimeProofer("Data Source=E:\\TimeProofer.sdf;Password=mypass");
Project project = new Project();
project.Proj_name = "My new Project";
project.Proj_description = "With this description";

tp.Project.InsertOnSubmit(project);
tp.SubmitChanges();

foreach (var projects in from p in tp.Project select p)
{
    Console.WriteLine(project.Proj_name);
}

Zuerst wir eine neue Instance der TimeProofer Klasse angelegt. Als Parameter wird ein ConnectionString verwendet. Nun kann ein neues Projekt angelegt werden. Project ist übrigens eine Tabelle in meiner Datenbank.  Das neue Projekt wird dann der Projekttabelle hinzugefügt und submitted. Abfragen kann man seine Tabelle mit der Linq typischen Syntax.

Alles in allem kommt man so ziemlich schnell zu einer einfachen Datenbankschicht, die für kleine Anwendungen vollkommen ausreichen ist.

Hier noch ein Link zu SQL Server CE:

http://www.microsoft.com/sqlserver/2005/en/us/compact.aspx

Neue Sprachfeatures in C# 3.0


Mit dem .NET Framework 3.5 kommt auch eine neue Version von C#, welche viele Neuerungen für uns bereit hält. Zum einen kann der Quellcode wesentlich verkürzt werden ohne dabei unleserlich zu werden,und zum anderen werden völlig neue Möglichkeiten eröffnet. Dieser Artikel soll einen kurzen Überblick über diese Features geben. Ich hoffe sie sind ebenso begeistert wie ich.

Automatically Implemented Properties

Ich habe es schon immer etwas störend empfunden, wenn man zu vielen Variablen immer die Properties per Hand eingeben musste. Später war mir da der ReSharper eine große Hilfe. Doch jetzt wird die Sache, auch ohne, deutlich einfacher. So sah ein privates Feld mit zugehörigem Property bis jetzt aus:

private string _Message;

public string Message

{

get { return _Message; }

set { _Message = value; }

}

Zuerst muss man seine Variable anlegen und dann muss das Property dafür geschrieben werden. Dies kann jetzt wie folgt vereinfacht werden:

public string Message { get; set; }

Natürlich könnte man jetzt sagen, dass man dafür auch einfach ein öffentliches Feld nehmen könnte. Aber man kann den Zugriff natürlich einschränken:

public string Message { get; private set; }

So kann auf die Variable nur innerhalb der Klasse schreibend zugegriffen werden. Zu beachten ist hierbei, dass immer ein get und set angegeben werden muss.Eine Variable, die auch innerhalb der Klasse nur gelesen oder geschrieben werden kann macht ja auch nicht viel Sinn. Dafür gibt es ja zum Beispiel Konstanten.

Object und Collection initializers

Diverse Properties einer Klasse können nun direkt bei ihrer Initialisierung mit Werten gefüllt werden.

Das ganze sieht dann so aus:

Email mail = new Email(“hans@xyz.de”) { Message = “Hello World”, From = “john@doe.de” }

Bei einem parameterlosen Konstruktor, kann man sogar die runden Klammern weg lassen.

Email mail = new Email() { From = “john@doe.de”, recipient = “hans@xy.de” }

Zu beachten ist hierbei, dass nicht alle Felder gefüllt werden müssen. Diese erhalten dann ihren normalen Wert, der ihnen in der Klasse zugewiesen wird.

Jede Klasse die System.Collections.Generic.IEnumerable<T> implementiert kann von Collection initializers profitieren. Dabei können die Collections gleich bei ihrer Erzeugung mit Werten gefüllt werden.Dieses Feature kann man wie folgt verwenden:

List<Email> myEmail = new List<Email>

{

new Email(“1@zwei.de”),

new Email(“2@zwei.de”),

new Email(“3@zwei.de”),

new Email(“4@zwei.de”)

};

Bei der Ausführung wird dann zuerst die Liste initialisiert und dann werden per Add(…) die Elemente hinzugefügt. Dafür muss die Add Methode natürlich public sein.

Implicitly typed local Variables

In C# 3.0 kann der Datentyp einer Variablen vom Compiler implizit festgelegt werden. Dazu dient das Schlüsselwort var, welches bereits aus diversen Scriptsprachen bekannt sein dürfte. Doch anders als bei diesen, kann der Datentyp einer mit var deklarierten Variablen sich nicht während der Laufzeit des Programms ändern. Ihr wird der Typ bei ihrer initialisierung vom Compiler zugewiesen. Deshalb ist es auch notwendig die Variable bei ihrer Deklaration zu initialisieren. Dies sieht dann so aus:

var number = 27;// number ist vom Typ int

var message = „Hallo“// message ist vom Typ string

Wenn sie diese Zeilen im Visual Studio in einer Klasse schreiben, können sie mit der Maus über eine Variable gehen und werden im Quickinfo den entsprechenden Typ sehen. Wenn sie ein Array mit var deklarieren wollen, müssen sie zusätzlich new[] verwenden.

var numbers = new[] { 1, 2, 3};

Wozu soll das nun gut sein? Mit Hilfe von var lässt sich wesentlich generischer Code schreiben. Egal was die Methode GetSomeData() im folgenden Beispiel liefert, in der foreach Schleife kann immer ihr Inhalt ausgegeben werden.

var dataList = GetSomeData();

foreach( var data in dataList)

Console.WriteLine(data);

Außerdem kommt var bei LINQ exzessiv zur Verwendung. Doch dazu später mehr.

Extension Methods

Extension Methods sind meiner Meinung nach, eine der ganz besonders praktischen Neuerungen in C# 3.0. Mit ihnen lassen sich Klassen um Methoden erweitern, ohne dass man die Klasse selbst ändern muss. Man muss also nicht einmal Zugriff auf den Quellcode der Klasse habe oder diese neu übersetzen. Konkret bedeutet das, dass man auch Klassen irgendeines Frameworks erweitern kann. Die Extension Method muss dazu in einer statischen Klasse als statische Methode deklariert werden. Außerdem muss der erste Parameter vom Typ der zu erweiternden Klasse sein und dem Schlüsselwort this folgen.

public static class ExtensionMethods

{

publicstatic bool IsSpam( this Email mail, List<string> blackList)

{

return blacklist.Contains(mail.Sender);

}

}

An einer anderen Stelle, kann dann diese Methode auf den Typ Email aufgerufen werden.

public static void Main(string[] args)

{

List<string> blackList = GetBlackList();

Email mail = GetNewMail();

If (mail.IsSpam(blackList))

mail.Delete();

}

Wichtig ist noch, dass die Extension Method nur zur Verfügung steht, wenn ihr Namespace inkludiert wurde.

Lambda Expressions

In C# 2.0 wurden anonyme Methoden eingeführt, die es erlauben Delegates, gleich bei ihrer Initialisierung mit einem Funktionsrumpf zu versehen. Das war und ist sehr praktisch, wenn man, zum Beispiel, in einer Liste nach einem bestimmten Element sucht.Lambda Expressions bieten nun eine wesentlich einfachere Syntax. Stellen sie sich zum Beispiel vor, sie suchen alle Emails von Hans@Maulswurf.de aus einer Liste von Emails.

var mail = mailList.FindAll(m => m.Sender == „Hans@Maulswurf.de“)

Eine Lambda Expression besteht aus einer Parameterliste, dem Zeichen => und einem Ausdruck. Dabei können die Typen der Parameterliste explizit oder implizit angegeben werden. Zur Suche der Emails hätten wir also auch folgendes schreiben können.

var mail = mailList.FindAll( (Email m) => m.Sender == „Hans@Maulswurf.de“)

Lamda Expressions werden sehr häufig bei der Verwendung von LINQ eingesetzt. Dazu soll aber noch ein extra Artikel folgen.

Tolles Buch


My Job Went To India (And All I Got Was This Lousy Book)

Dieses Buch richtet sich an alle ambitionierten Softwareentwickler, die sich auf Dauer ihren Job, oder besser gesagt, einen Job sichern und darin immer besser werden wollen. Dabei wird quer durch das Buch immer wieder die indische Kultur angerissen. Dabei führt der Autor einem vor Augen, dass das Ziel der Inder keineswegs ist, uns unsere Jobs wegzunehmen, sondern schlicht und einfach sich und ihre Familien zu ernähren. Es ist ganz klar, dass immer mehr Teilprojekte in Billiglohnländern entwickelt werden und dadurch hier Arbeitsplätze wegfallen. Doch man kann etwas dagegen tun. Dieses Buch wirkt beim Lesen sehr motivierend und wehr den Pragmatischen Programmierer mochte wird dieses Buch lieben. Selbst wenn sie sich sicher in ihren Job fühlen, können sie lernen wie sie ein besserer Entwickler werden können und für die Zukunft gewappnet sind.

Falscher Debugger


Mit unter soll es vorkommen, dass sich in einer Anwendung ein Fehler eingeschlichen hat. Zumindest in denen, die man nicht selbst Programmiert hat. Stößt das Framework auf einen solchen Fehler erscheint, sofern das SDK installiert ist und Debug Symbols vorhanden sind, ein Fenster, in welchem man einen Debugger starten kann. Bei mir war nun das Problem das ich bei einer .NET 2.0 Anwendung nur die Debugger für das 1.1er Framework wählen konnte, die dann mit dem Prozess natürlich ganz und gar nicht zurecht kamen. Die Lösung des Problems lag in der Registry. Dort fand ich unter [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework] folgende zwei Schlüssel:

"DbgManagedDebugger"="\"C:\Programme\Gemeinsame Dateien\Microsoft Shared\VS7Debug\vs7jit.exe\" PID %d APPDOM %d EXTEXT \"%s\" EVTHDL %d"

"DbgJITDebugLaunchSetting"=dword:00000002

Wie man sieht, ist dort der Debugger von VS 7, sprich .NET 1.1, angegeben. Also kann das ja nicht gehen. Ändert man die Wete der beiden Schlüssel auf:

"DbgManagedDebugger"="\"C:\WINDOWS\system32\vsjitdebugger.exe\" PID %d APPDOM %d EXTEXT \"%s\" EVTHDL %d""DbgJITDebugLaunchSetting"=dword:00000010

sieht das Ganze schon besser aus. Offenbar lag der Fehler daran, dass ich VS 2005 vor der 2003er Version installiert habe. Wie auch immer. Jetzt funktioniert es wieder super. Wichtig war mir das Ganze um einen selbst geschriebenen Windows Service zu Debuggen. Das geht ja von Haus aus ziemlich schlecht. Schreibt man aber System.Diagnostics.Debugger.Launch(); wird in dieser Zeile der Debugger gestartet. Das kann sehr hilfreich sein.