TechTalk/Hands-on Lab "Silverlight 2 Beta"

April 22nd, 2008

Letzte Woche hatte ich das Vergnügen, am MSDN TechTalk und Hands-on Lab zu Silverlight 2 dabei zu sein. Mit dem Lab wollte es leider aus technischen Gründen nicht klappen, die Speeches waren jedoch äusserst interessant. Die Präsentationen von Ronny Saurenmann und Sascha Corti stehen auf der Microsoft-Webseite bereit. Die "Hands-on Lab"-Unterlagen hat Sascha Corti in seinem Blog-Post "Silverlight 2 Beta 1 - End-to-End Hands-On Lab" veröffentlicht.

Die Speeches gaben einen Überblick über Silverlight und hoben einige Features hervor. Hier sind einige Elemente lose zusammengetragen. Interessant waren für mich besonders die Möglichkeiten bei der Arbeit mit Daten. An der Modifikation des Aussehens von Steuerelementen habe ich (persönlich) eher weniger Interesse.

  • Cool fand ich das Silverlight Data Grid. Zumindest die Demonstration der Möglichkeiten war beeindruckend und ich habe ähnliche Möglichkeiten wie in der Windows-Entwicklung (kein Paging- und Postback-Käse wie im "normalen" Web). Besonders das "Inline-Editing" ist praktisch.
  • Fehlen tut in der aktuellen Version (Beta 1) noch die Drop Down Box. Im Manual zum Lab ist eine Anleitung enthalten, selbst eine zu bauen, jedoch lässt sich meiner Meinung nach nicht in Minuten aus einer Text- und einer List-Box eine vollwertige Drop Down Box bauen. Das Steuerelement verhält sich, obwohl subtil, total anders als das Original. Man gehe jedoch davon aus, dass in der finalen Version eine Drop Down Box dabei sein.
  • Silverlight bietet keine DataSet-Unterstützung. Der empfohlene Weg sei, eine List<T> (bzw. "Custom Objects") zu verwenden, mit dem LINQ-Helper alle geänderten Werte zu suchen und zurück an die Datenquelle (in der Regel wohl an einen Web Service) zu senden.
  • Silverlight unterstützt nur asynchrone Datenabfragen (Web Service, etc.). Dies ist logisch, schliesslich würde andernfalls der Browser des Benutzers stillstehen.
  • Data Binding ist weitgehend unterstützt, die Anwendung gleich wie bei der Windows Presentation Foundation (WPF). Wichtig in diesem Zusammenhang: "DataContext"- und "ItemsSource"-Properties.

Bei diesen Präsentationen sah ich auch des öfteren LINQ in Anwendung. Dies war sehr interessant, da ich noch nie damit gearbeitet habe, gehört jedoch in einen anderen Topf.

Für einen .NET-Programmierer ist Silverlight bestimmt eine schöne Sache, um "interaktive Web-Applikationen" zu entwickeln. Das Plug-In ist für den Internet Explorer, Mozilla Firefox und Safari verfügbar und unter Linux als "Moonlight" bekannt. Ich wage nicht, über die potentielle Verbreitung ein Urteil zu fällen respektive zu urteilen, ob die Unterstützung dieser Plattformen in den meisten Fällen ausreicht.

Da bleibt noch eine Frage: Warum, wieso muss das GUI von Blend so schaurig unpassend schwarz sein? Bsst, ganze Strasse dunkel, warum?

Zum Schluss noch einige Zitate zur Auflockerung:

  • "In Silverlight 1 you didn't even have a text box!"
  • "In this case I'd already said it's the system but I'm sure it's me who did something wrong." (der Internet Explorer verabschiedete sich abrupt)
  • "There is coffee, we know how important this is for you."
  • "Well, a demo application without an animation is no demo application."

Data Source Independent DAL

März 11th, 2008

Another short piece of personal learning. Ich markiere für einmal den grossen Architekten. :)

Die Idee eines Data Access Layers ist gemeinhin, Datenzugriffe datenbank- oder sogar datenquellenneutral (neben relationalen Datenbanken allein können ja auch Textdateien oder ein Web Service als Datenquelle dienen) zu halten. In der Praxis ist dies nach meinen Erfahrungen nicht immer genau so der Fall, wie dies die Theorie anpreist.

Die Theorie sagt: Der Presentation Layer präsentiert Daten und enthält keine Logik (höchstens formelle Prüfung oder Plausibilisierung von Eingaben), der Business Layer hantiert mit den Business-Objekten und implementiert die Logik, der Data-Access Layer liest und speichert die Daten und abstrahiert die Zugriffe auf die Datenquelle auf allgemeinem Level.

Ich wollte nun einen Business Layer, der weder von der Datenquelle abhängt noch hunderte Zeilen Code enthält, um die netten Rückgabewerte und Ausgabeparameter wieder in Objekte umzubauen. Ich wollte im DAL auch keine Strukturen definieren, dessen Felder denjenigen im Business-Objekt entsprechen. Ein Objekt (Business Entity!) soll "as it is" ohne weitere Bearbeitung zur Speicherung gereicht werden und auch fixfertig wieder aus dem DAL kommen.

Dafür habe ich nun ein separates Assembly gebaut mit abstrakten Basisklassen für die Business-Objekte. Business Layer und DAL haben beide eine Referenz darauf, sodass beide die Grundstruktur der Objekte kennen. Hier eine schnelle PowerPoint-Skizze:

Architekturskizze

Der Business Layer kann nun dem DAL beliebige Instanzen von Klassen übergeben, welche von den (abstrakten) Basisklassen im DAL abgeleitet sind. Im Business Layer kann ich meine Business-Entitäten erstellen, die von den Basisklassen erben, meine Methoden erstellen und zusätzliche Interfaces implementieren, beispielsweise für bequemes .NET Windows Forms Data Binding.

Zur Implementierung habe ich vorerst nur die gekapselten Felder und das IEquatable Generic Interface in der Basisklasse implementiert: Die Entität soll grundsätzlich sofort einsetzbar sein (für Business-Layer und DAL!), aber keine besonderen Businessfunktionalitäten bereitstellen. Die braucht der DAL nämlich nicht, und hat sie auch nicht zu brauchen.

Nein, allzu neu ist die Idee nicht. Bei simple talk ist die Idee im Artikel ".NET Application Architecture: the Data Access Layer" (der Artikel ist sehr empfehlenswerte Lektüre!) beispielsweise aufgegriffen, diskutiert und Alternativen gegenübergestellt. Sie beschreibt diesen Approach als akademisch:

From an academic standpoint, this approach is probably the truest form of a data abstraction for a DAL because you can make the shared classes completely data-source independent and not just database independent.

Diesen Eindruck macht er auch auf mich. Ich bin mir nicht sicher, inwiefern er bei grossen Projekten mit aberhunderten von Entitäten wirklich bequem durchführbar ist. Aber er ist bestimmt nicht schlecht; ich werde damit experimentieren.

Stored Procedures

Februar 26th, 2008

Die Diskussion in der Schulklasse um Stored Procedures ist erneut aufgekommen: Im Rahmen unserer so-richtig-Vier-Tier-Hangman-Applikation, die wir für die Schule entwickeln müssen, wurde deren Notwendigkeit in Frage gestellt und diskutiert. Ich bin bekanntlich immernoch ein Verfechter von Stored Procedures für jeden kleinen SQL-Befehl, der gegen die Datenbank abgesetzt wird.

Grund 1: Stored Procedures sind eine definierte Schnittstelle

Stored Procedures definieren zwischen Datenbank und jeder Applikation eine klare Schnittstelle. Mit anderen Worten:

Stored procedures are a contract. (...) The header of the stored procedure defines the parameters that the developer must supply, and the body is where the DBA puts all of their voodoo magic to get the data you requested.

Die treffende Beschreibung stammt aus dem Post Service Oriented Databases auf PaulStovell.NET.

Durch die Stored Procedure wird es leichter, die Datenbank zu erweitern, die Daten weiter zu normalisieren, total anders abzulegen oder Felder umzubenennen. Ausserdem können Optimierungen in der Abfrage vorgenommen werden, ohne an der Applikation selbst zu schrauben.

Trotzdem ist es natürlich gefährlich, beliebige Änderungen beispielsweise an Feldnamen vorzunehmen und dann durch die Stored Procedure unter dem alten Namen anzuzeigen, wenn dadurch die Einheitlichkeit der Namen (und somit der Überblick über das Gebilde) verloren geht.

Grund 2: Stored Procedures sind vorkompiliert

Stored Procedures sind vorkompiliert. Somit wird die Abfrage nicht bei jeder Verwendung neu interpretiert weil wieder von der Applikation versandt (zumindest beim Microsoft SQL Server - ich kenne nicht jede DB). Dazu sei ein Artikel SQL Server Stored Procedures von About Databases Guide Site zitiert:

Precompiled execution. SQL Server compiles each stored procedure once and then reutilizes the execution plan. This results in tremendous performance boosts when stored procedures are called repeatedly.

Natürlich macht sich das erst ab einer bestimmten Nutzungsfrequenz und/oder Query-Komplexität bezahlt, aber es schadet auch sicher nicht. :)

Grund 3: Netzwerk-Traffic

Je länger das Query, desto mehr Netzwerkverkehr verursacht die Übermittlung. Ein Stored Procedure Aufruf ist je nach länge wesentlich (oder auch unwesentlich) kürzer.

Grund 4: Mehr Sicherheit durch restriktivere Permissions

Werden Stored Procedures konsequent verwendet, braucht erhält ein Web- oder Service-User, respektive der Benutzer selbst, keine direkten Zugriffsrechte auf Tabellen. Ihm wird lediglich eingeräumt, die Stored Procedures auszuführen, die er benötigt. Der Entwickler oder DBA legt auf diese Weise genau die Queries fest, welche der Benutzer auszuführen hat. Alles andere geht nicht.

Nachtrag: Heute, am 5. Mai, bin ich zu diesem Thema auf simple-talk über "Bad Database Security" von Tony Davis gestossen.

Grund 5: Änderungen an Queries (bei Client-Applikationen)

Bei Applikationen, die auf dem Client laufen und nicht auf dem Server, werden hart codierte Queries mit auf den Client kopiert. In einer neuen Version ändert sich eine Abfrage und ein Benutzer holt sich die neue Version nicht. Es gibt zwei blöde Szenarien:

  1. Blöd: Das Query in der alten Version funktioniert nicht mehr und der Benutzer kann nicht arbeiten. Dies geht in Grund 1 hinein, aber kann natürlich auch mit Stored Procedures passieren, falls sich eine Schnittstelle ändern muss.
  2. Blöder: Das Query liefert Daten, die es nicht liefern sollte. Nehmen wir an, in die Datenbank wird ein neues Feld "IsUserVisible" (Bit) eingefügt. Neu werden den Benutzern nur noch die Einträge angezeigt, welche "IsUserVisible" auf 1/true gesetzt haben. Krasser Häcker Hans-Detlev startet die alte Version und sieht Informationen, die er vielleicht besser nicht sehen sollte.

Was kein Grund ist...

Kein Grund ist meiner Meinung nach das SQL-Injection-Problem. Zwar kann die Tragweite dank eingeschränkten Rechten kleiner sein, aber folgendes kann der geneigte Bastler immer noch machen:

string sql = "EXEC MyStoredProc @Filter = \'" + filter + "\'"

Umgekehrt geht auch folgendes:

string sql = "SELECT * FROM Hubschrauber WHERE HubschrauberId = %1";
// ... und hier mit einem DbCommand-Objekt und Parametern arbeiten

Hm...

Was gibt es dazu für andere Meinungen, Alternativen? Oder wie sieht das auf den verschiedenen DBs aus?

InfoPath, Expressions and 256 Characters

Februar 12th, 2008

For once I'm writing in English, because I am translating English developer slang to German very badly (even worse that I write in English :P) and I'm sure there are more English-speaking developers. Maybe I will write a German version later on.

InfoPath behaves pretty strange when I use expressions that are longer than 256 characters. This morning I worked with rules and conditions on click of a button on an InfoPath form. In my opinion the following is a bug, but it might be a feature too of course:

InfoPath Button Properties Window

If you replace "(long expression here)" with any kind of expression which is longer than 256 characters, everything will go well when you press OK. Now open the properties window again. The expression will be cut to 265 characters. You can paste it again and it will be well again.

The problem is, e.g. you change a condition for a rule that applies on click. Everything will look well, but Apply or OK will not work. As soon as you close the dialog, the changes will be wasted. As a workaround (in German: "Würgaround"), change the expression to "asdf" (or anything that is shorter than the magic 256 characters), make your changes, apply the changes, reopen the window and paste the expression again.

The Tumble Dryer

Januar 10th, 2008

Ich ziele nicht auf die Lyrics von "Retirement", Kaiser Chiefs, nein.

"Ich selber habe die Erfahrung gemacht, daß normale Shirts, Hosen, usw., die nicht gerade besondere Applikation und Sonderstoffe beinhalten, auch getrocknet werden können." (Tobias Haase in de.etc.haushalt)

Dies las ich die in de.etc.haushalt, gefunden über Google. Die Erfahrung kann ich bestätigen, übernehme aber selbstverständlich keinerlei Haftung. ;)

Mein Problem ist, dass der Trockenraum des Wohnblocks schlecht ist. In zweierleit Hinsicht:

  • Die Raumluft wird weder geheizt noch getrocknet und die Wäsche trocknet entsprechend langsam.
  • Es stinkt zwischendurch ein wenig faulig (oder so ähnlich, woher auch immer das kommt) oder nach Zigarettenrauch aus dem Treppenhaus oder dem Lift. Wenn ich die Wäsche nun drei Tage hängen lassen muss, nimmt sie eine Mischung aus sämtlichen Gerüchen auf.

Nun habe ich Gebrauch vom Tumbler gemacht, obwohl die meiste Wäsche dafür nicht offiziell geeignet gewesen wäre. Quer durch, von Shorts bis Pullover, alles in eine Ladung und auf dem Schonprogramm durch. Kein Problem, lediglich nicht ganz "schranktrocken". Aber diese Restfeuchtigkeit liess sich gut in einigen Stunden in der Wohnung wegtrocknen.

Warum ich das schreibe? Ich habe lange gegoogelt, um eine Empfehlung bezüglich Tumlerbenutzung bei normalen Textilien zu finden. Massenhaft Werbung für Geräte habe ich gefunden, und in der Wikipedia historische Fakten. Kurz vor der Kapitulation stiess ich auf den oben genannten Beitrag. Und selbstverständlich beweist man ja auch Hausmännlichkeit.

Operation “Bohrhammer” (Heimwerkerkönig)

Dezember 31st, 2007

Ein grosses Jahrhundertprojekt seit dem Einzug in die neue Wohnung war (!) das Aufhängen der neuen Lampe. Tatataaa:

Aufgehängte Lampe im Wohnzimmer

Zwischen Weihnachten und Neujahr habe ich endlich die Zeit gefunden, mich mit dem Bohrhammer an die Bohrlöcher zu machen, die ich schon lange vor mir her schob: Die Garderobe (für einen Euro in Deutschland gefunden), die Lampe sowie einen Wand-Zeitschriftenhalter. Mit dem Bohrhammer ging das ganz leicht, anders als mit der Schlagbohrmaschine. Damals habe ich damit die Lampe aufhängen wollen, nach der Farbe auf der Decke aber aufgegeben.

Wand-Zeitschriftenhalter

Den Wand-Zeitschriftenhalter und die Asterix-Bände habe ich zu Weihnachten bekommen, und das bewährt sich wirklich. WLAN habe ich noch keines, somit ist ein Stoss Hefte in der Nähe des Topfes super.

Die Garderobe hängt zwar ein wenig schief (das Foto lassen wir diskret weg), aber sonst ging das auch als Informatiker ganz gut. Es ist nur ganz wichtig, sich vorher zu erkundigen, wo Gas-, Wasser-, und Stromleitungen verlaufen. Ich habe da einiges gegoogelt und viel gefunden (u.a. "Wenn Bohrer oder Nagel eine Leitung treffen"), jedoch hat mir das den Gang zum Hausmeister nicht erspart.

Ach ja: Die Nachbarn waren gerade beide nicht zu Hause. ... und nun bleibt mir nur noch, einen guten Rutsch zu wünschen.

cede.ch: Pretty quick 2 weeks…

Dezember 14th, 2007

Mit meinen Bestellungen wollte es in der letzten Zeit nicht immer hinhauen. Zum Auftakt in der neuen Wohnung hatte ich zwei Wochen kein Internet und exakt heute vor drei Monaten habe ich mir für meinen Bürostuhl Teppichrollen gekauft, die ich in den nächsten Tagen erhalten sollte.

Um so mehr hat mich heute erfreut und erstaunt, dass ich bereits eine Lieferung von cede.ch im Briefkasten hatte. Gestern, etwa um drei Uhr, habe ich online Mach 6 und You Could Have It So Much Better bestellt. Lieferzeiten zwei Wochen, respektive drei bis vier Tage. Heute lag die Lieferung beider Scheiben im Briefkasten.

Super Sache!

Nachtrag: Beim Transport wurde die eine Hülle beschädigt. Ohne dass dies nötig gewesen wäre, wurden mir noch zwei Hüllen nachgeschickt, die nach zwei weiteren Tagen bei mir waren. Eine war wieder beschädigt, wohl ebenfalls ein Transportschaden. Der prompte Service freut mich sehr, obwohl die Hülle wohl bis zum nächsten Schaden im Schrank liegen wird.

.NET Windows Forms Data Binding

November 12th, 2007

In den nächsten Monaten steht mir Training in .NET bevor, um in näherer Zukunft die Prüfung zum Microsoft Certified Professional im Bereich .NET-Entwicklung (MCP 70-536) ablegen zu können. Gestern habe ich mich anhand von zwei Screencasts von Paul Stovell genauer mit DataBinding auseinandergesetzt. Der Post hat ein wenig TSchoenerNotizblock-Charakter und darf nicht als fertiger Artikel gesehen werden, das ist wichtig.

Implementierung von Business Objects

Für mein Beispiel, zugegebenermassen ein "gspürsch-mi?"-Beispiel, habe ich mir die Business-Entität "Person" ausgesucht, mit den Eigenschaften "FirstName", "LastName" und "EMail" (exposed in gleichnamigen Properties). Zusätzlich habe steht ein Flag "IsDirty" bereit, das jedoch für mein Beispiel nicht von Bedeutung ist.

Ziel ist es, nach alter OO-Weisheit, das Objekt aus der echten Welt abzubilden. Diese Person allein könnte nun in .NET bereits als Datenquelle verwendet werden, jedoch habe ich einige weitere Implementationen vorgenommen, um die DataBinding-Features auszureizen.

IEditableObject, INotifyPropertyChanged, IDataErrorInfo

Meine Person-Klasse implementiert nun explizit (!) die .NET-DataBinding-Interfaces IEditableObject, INotifyPropertyChanged und IDataErrorInfo aus dem System.ComponentModel-Namespace. Die explizite Implementierung ist nicht zwingend, es funktioniert auch so. Ich habe den Ansatz gewählt, um das fachliche Element (die Entität "Person") vom technischen Teil (DataBinding) der Klasse sauber zu trennen.

Ein Wort zur expliziten Interface-Implementierung: Implementiere ich ein Interface explizit, stehen die entsprechenden Properties nur zur Verfügung, wenn ich meine Objektinstanz in ein Feld vom Typ des Interfaces, in unserem Falle IEditableObject, INotifyPropertyChanged oder IDataErrorInfo speichere oder in ein solches caste. Habe ich ein Feld vom Typ Person, steht die Eigenschaft nicht zur Verfügung:

// Das Error-Property ist von IDataErrorInfo gegeben und
// implementiert.
Person p = new Person();
IDataErrorInfo d = new Person();
String s = p.Error(); // funktioniert nicht
String t = ((IDataErrorInfo)p).Error; // funktioniert
String u = d.Error; // funktioniert auch

Da nun .NET Windows Forms Data Binding intern mit den Interfaces arbeitet, kann es die Methoden und Eigenschaften, die wir bereitstellen, wunderbar verwenden. Arbeite ich jedoch selbst mit einer Objektinstanz, interessieren mich die DataBinding-Elemente nicht und ich sehe sie auch nicht. Wunderbar.

Die Implementierungen und deren Zweck rolle ich an dieser Stelle nicht aus. Gerne verweise ich auf die entsprechenden MSDN-Artikel oder den Screencast von Paul Stovell in seinem Blog-Post Binding Patterns 0×0002 - Binding to Objects (englisch) mit dem geilen Kamel. Das Video habe ich mir an einem gemütlichen Sonntag Morgen bei einem Käffchen und einer Schale Corn Flakes reingezogen und in vierzig gemütlichen Minuten viel gelernt (und mich gefragt, warum ich jahrelang von Hand Text-Boxen abgefüllt habe...).

Architektur

Diese Implentierung hält die Architektur der Programms sauber. Beispielsweise sind sämtliche Validierungsroutinen dank dem IDataErrorInfo-Interface innerhalb des Business-Objekts angesiedelt und wandern nicht in den Anzeige-Layer. Und weil .NET Windows Forms Data Binding diese Interfaces out-of-the-box unterstützt, ist auch die Fehleranzeige durch einfaches Einfügen eines ErrorProviders auf der Form, der an die BindingSource gehängt wird, getan.

Der Anzeige-Layer ist dank DataBinding wirklich nur ein Anzeige-Layer und beinhaltet keinen weiteren Code. Fehlerbehandlung, Editieren mit Abbrechen und Bestätigen sowie die Aktualisierung aller Fehler läuft automatisch.

localhost

September 26th, 2007

Nach weiteren stressigen Wochen in der neuen Wohnung, an der Arbeit und in der Schule nun ein kleiner erneuter Gruss aus der Wohnung:

Fussmatte

Die Fussmatte stammt aus dem Shop von getdigital.de und macht sich ganz gut im Flur. Weiter habe ich dort ein T-Shirt mit einem aufgedruckten Koffeinmolekül gekauft. Dies ist jedoch kaum für jemanden von Bedeutung, eigentlich brüste ich mich in diesem Post nur mit meiner krassen Fussmatte. ;-)

Flatlife – Ein Erfahrungsbericht

Juli 14th, 2007

Der Umzug ist überstanden, der Kühlschrank voll, das erste Bier gezischt und die Wohnung langsam eingerichtet. Heute kommen noch die letzten Kisten aus dem Flur in den Keller. Wer selbst umzieht und Informatiker (bzw. einfach nur ein Mann) ist, soll sich folgendes merken: Ein Dosenöffner wird vor dem Umzug gekauft, das ist wichtig!

Meine Liste von Überlebenswerkzeugen für die Wohnung sah wiefolgt aus, und bisher bin ich mit dieser Auswahl ganz gut gefahren. Jedoch hatte ich einige Sachen beim Einzug noch nicht (beispielsweise den genannten Dosenöffner oder den Duschvorgang): WC-Bürste, Gläser, Karaffe, Topfuntersetzer, Küchenutensilien, Kochgeschirr, Schüssel, Bratpfanne, Geschirr-Startbox, WC-Papier, Tür-Dichtungsband, Filzgleiter (bei Parkettboden), Duschvorgang (M-Budget), Schnur, Besen und Schaufel, Sparschäler, Küchenmesser, Brotmesser, Schwämme (Multipack!), Lappen, Küchentücher.

Wohnzimmer meiner Wohnung

Zum Einzug habe ich nur einen einzigen Tipp: Wer sich auf ricardo.ch mit Möbeln eindecken will, soll diese bitte nicht am Umzugstag auch noch abholen gehen wollen. Das gibt Stress. Es bleibt mir noch, allen Helfern zu danken, die mir mit Ihren Autos, Oberarmen und Werkzeugkisten geholfen haben, mich bei der Einrichtung unterstützt oder während der Werkerei die Küche geschmissen haben.

In meinen ersten Tagen in der Wohnung habe ich festgestellt, dass sich ein Kühlschrank anscheinend auch unter der Woche nicht von selbst füllt, dass der Ernährungsplan reichlich karg aus Nudeln und Tomatensauce besteht (ich konnte ja ohne Dosenöffner nicht einmal die Rösti-Dose schlachten!) und dass Staatsbetriebe reichlich dürftige Öffnungszeiten haben. Ferner finde ich es angenehm, in der ganzen Wohnung oben-ohne herumzulaufen, ohne dass sich jemand gestört fühlt und stehe später auf, wenn nicht um Punkt halb sieben das Haus zu rumoren beginnt, weil Mitbewohner aufstehen.

And the winner is: Internet im Haus ist nicht selbstverständlich!