#Handwerk: Clean vs. pragmatisch?

3. Mai 2010 - 11:31 Uhr

Am Beispiel von Thomas’ Blogbeitrag “Null Verständnis” kann man wunderschön zwei Dinge erkennen: Erstens, wie schnell man aus einem praktischen Problem in eine Grundsatzdiskussion abgleiten kann und zweitens, dass es offensichtlich einen Unterschied zwischen möglichst sauberen Vorgehensweisen und pragmatischen Ansätzen geben kann. Oder ist dem nicht so?

Zunächst zum Thema “Grundsatzdiskussion”: Ich persönlich bin kein großer Freund dieser Form von Diskussionen, werden sie doch gerne anhand von vereinfachten Beispielen geführt und nähern sich schnell einem recht grundlegendem Level an, da ab einem gewissen Punkt das Selbstverständnis eines Teils der Diskussionspartner berührt werden könnte. Das beiseite gelassen, eignen sie sich jedoch wundervoll, um unterschiedliche Grundideen auszuarbeiten, wie es in diesem Fall geschehen ist: Auf der einen Seite die Fraktion, die gerne auf null als Rückgabewert von GetXXX-Funktionalitäten verzichten möchte, wenn diese als Parameter einen ID-Wert übergeben bekommen und der Datensatz nicht existiert (Begründung: ID kennzeichnet nun mal einen eindeutig identifizierten Datensatz, gibt es diesen nicht, ist irgendwas faul im Staate Dänemark – das Ganze kann dann wahlweise über ein Null-Objekt oder eine Exception abgebildet werden), auf der anderen Seite die Fraktion, die in diesem Fall eben null zurück gibt und das im Code abfragen und abfangen möchte.

Unabhängig davon, dass ich die Meinungen beider Fraktionen nachvollziehen kann (und dennoch gerne Null-Objekte einsetze, da sie die weitere Verarbeitung stark erleichtern können und oftmals der Wartbarkeit zuträglich sind), haben wir es hier mit einem eher grundsätzlicheren Problem zu tun: Clean Code vs. pragmatische Entwicklung, um es mal zugespitzt zu umschreiben. Dieser Widerspruch ist jedoch bei näherer Betrachtung keiner, jedenfalls soweit es mich betrifft, denn in Wahrheit haben wir es an dieser Stelle eher mit zwei verschiedenen Anforderungsmodellen zu tun:

Beiden Fraktionen geht es um einen möglichst sauberen, wiederverwendbaren und auch für andere Entwickler leicht verständlichen Code. Da sind sich beide einig, der Unterschied liegt darin, ob und wie mit Annahmen außerhalb des DataLayers umgegangen wird:

  • Die “Clean Coder” wollen, dass der Code vertrauenswürdig ist, d.h. er soll sich in jedem Fall eindeutig verhalten und außerhalb des Kontextes etwa eines DataLayers keinerlei Annahmen über dessen Struktur und Funktionsweise erfordern. Ich folge diesem Ansatz in der Regel. Das bedeutet für: Null-Objekte, da wo es sinnvoll ist (Benutzer gehören für mich in aller Regel dazu), null bei nicht relevanten Geschichten oder Dingen, die schon ganz eindeutig aussagen, dass es eventuell auch KEIN Ergebnis geben kann (FindXXX-Methoden wäre klassische Kandidaten dafür).
  • Die “Pragmatiker” haben einen anderen Schwerpunkt: Sie legen weniger Wert auf die oben angesprochene Vertrauenswürdigkeit von Code, denn die erarbeiteten Lösungen werden entweder meist allein verwendet, oder stellen Lösungen dar, die von einem Endkunden in aller Regel nicht selbstständig weiterentwickelt werden. Hier heißt es: Null statt eines Null-Objekts, denn hier ist außen bekannt, wie das Repository sich verhält und die Anwendungsfälle für etwa Null-Objekte halten sich meist in Grenzen.

Beide Fraktionen haben somit unterschiedliche Anforderungen an Code, der scheinbare Widerspruch zwischen pragmatischem und sauberen Programmieren ist also keiner – wir haben es schlicht mit unterschiedlichen Verwendungsszenarien zu tun.

Ob, und in welchem Umfang man nun die Meinung der einen oder der anderen Fraktion teilen mag, ist eine andere Frage. Ich persönlich tendiere zur Clean Code-Ansicht, denn ich habe für mich die Sinnhaftigkeit von Null-Objekten schon seit geraumer Zeit erkannt. Dementsprechend definiere ich meine Entitäten und meine Schichten auch und kann mich so darauf verlassen, stets eine funktionsfähige Objektinstanz zu besitzen und entsprechend meinen Code einfacher strukturieren. Das Ergebnis: Wartbarkeit und Sicherheit steigen, meine Applikation verhält sich vorhersagbarer, ich kann mindestens ebenso gut testen, wie beim eher “pragmatischen” Ansatz.

Insofern erscheint mir hier der Clean Code-Ansatz im Endeffekt sogar pragmatischer zu sein.

4 Kommentare » | Allgemeines, Handwerk, Meinung

#WP7S: Fakten-Roundup (III) von der #MIX10

18. März 2010 - 04:05 Uhr

Inzwischen ist die MIX-Konferenz bereits wieder Geschichte, aus meiner Sicht jedoch sehr interessante Geschichte. Ich habe enorm viel gelernt und den einen oder anderen sehr interessanten Menschen kennen gelernt.

Hier nun die letzten Fakten zu Windows Phone 7 Series, die ich – wie die letzten Male auch – direkt wieder aus meiner Twitter-Timeline klaue:

  • Performance beginnt schon beim Designer. Nicht erst beim Entwickler.
  • Fixed Width / Fixed Height bei Listen ist derzeit optimal. Data Virtualization (lade nur das, was Du brauchst).
  • 30 Frames / Sekunde für Animationen / Video / etc.
  • Application.Current.Host.Settings.EnableFrameRateCounter – kann genutzt werden, um Performance zu messen.
  • Application.Current.Host.Settings.EnableRedrawRegions – Feststellen, was wann wie wo neu gezeichnet werden muss.
  • BitmapCache einschalten steigert Performance.
  • Gerade die Animationen können extrem performancehungrig werden. Sollte man sich tatsächlich mal in Ruhe irgendwo anschauen.
  • CacheModes sollten nicht gemischt werden – CacheMode="None" innerhalb von CacheMode="BitmapCache"-Elementen ist extrem unperformant.
  • Media mit geringstmöglicher Framerate codieren – sehr aufwändig zu rendern.
  • Auch bei MediaElement: CacheMode="BitmapCache" setzen.
  • Media-Decoding + PNG-Handling stets hardwarebasiert, JPG-Handling KANN hardwarebasiert stattfinden.
  • Hardware-Beschleunigung nur für Elemente bis max 2.048×2.048 Pixeln. Alles, was größer ist, muss per Software "beschleunigt" werden.
  • Wichtig: Applikationen laufen nur mit gültiger License
  • Code ist signiert
  • Applikationen können nur Ressourcen ansprechen, für die sie freigegeben sind, wird zur Laufzeit überprüft.
  • Klare Aussage: "Echte Programme" (C++) wird es nicht auf der Plattform geben.
  • Push-Notification-Tokens bleiben auch beim Pausieren gültig. App muss sich also noch dem Pausieren nicht neu registrieren.
  • Keine DLLs übers Netz nachladbar. Nur signierter Code wird ausgeführt. Signierter Code kommt nur über den Marketplace.
  • Find & Wipe-Remote-Service existiert.
  • MyPhone-Service setzt Find & Wipe-Remote-Service um
  • Updates für das Gerät werden von MS bereitgestellt, es wird aber keine Patch-Tuesdays geben. Also eher analog zu #iPhone.
  • Marketplace kann mehr, als bisher bekannt – es wird wohl Szenarios rund um geschlossene Benutzergruppen o.ä. geben.
  • Featured-App kontrolliert den Hintergrund des Marketplaces. :-)
  • Suche funktioniert natürlich auch im Marketplace.
  • Apps in der Regel innerhalb von 5 Tagen verfügbar, klare Aussagen über Timelines, Dokus ab Mai für Windows Phone aktualisiert.
  • Applikation wird von Microsoft auf benötigte Schnittstellen geprüft und mit einem Manifest versehen.
  • Applikationen / Käufe sind an die Live-ID gebunden, bis zu fünf Geräte parallel mit einer ID einsetzbar.
  • Kein Nexus von Microsoft geplant. MS verkauft weiterhin keine Entwickler-Phones. :-)
  • Kein Buy once – Play everywhere (XBox-Spiel kaufen und auf WP7S spielen) derzeit, vielleicht zukünftig.
  • XNA ist C#-only, Managed Code only.
  • Silverlight: Wenn Vektorgrafiken, XNA: Wenn 3D-Grafiken. Mal ganz pauschal gesagt. :-)
  • Konfigurierbare Standardeffekte, keine Custom Shaders. #XNA
  • Zugriff auf Audio, Video und Photos via #XNA-Framework. Nicht nur Chooser notwendig, wenn ich das richtig verstanden habe.
  • Zwei Profile bei #XNA: Reach (möglichst kompatibel für alle Plattformen) oder HiDef (spezifisch nur für eine Plattform).
  • Derzeit nur Entwicklung mit C#. VB kommt (vielleicht) später nach. #MIX10
  • Allgemein: class statt struct, struct nur für Dinge, die kleiner 16 Bytes sind
  • GC ist teuer. Zwei Strategien: Seltener laufen lassen (Objekte < 1MB). Oder: Schnell fertig werden lassen (ValueTypes verwenden).
  • GC: Weniger Referenzen. Nur Objekte, wo notwendig. Weniger Listen, mehr Arrays.
  • GC manuell aufrufen: GC.Collect() – bitte nicht so oft. Teuer. Idealerweise nur nach dem Load oder in Pausen.
  • Boxing vermeiden. StringBuilder statt String. GC per WeakReference-Klasse überprüfen. CLR-Profiler verwenden (#XNA). .NET Reflektor.
  • foreach-Statement ist okay, darauf achten, dass der Enumerator ein primitiver Typ ist.
  • yield-Statement verwenden – wird zu einem Zustandsautomaten kompiliert.
  • Best practices für mobiles Web: Weniger Farben und Schriften, weniger JS, keine Backgrounds, Content an Screengröße anpassen. Kleine Bilder.
  • Best practices für mobiles Web (II): So wenig als möglich Input, sinnvolle Vorgaben, Cookies für Eingaben verwenden.
  • Entwicklung für mobiles Web: Standards verwenden (XHTML, HTML 4.01, XHTML-MP), CSS 2.1, DOM 1, ECMAScript3. DOCTYPE setzen.
  • Entwicklung für mobiles Web: Standard-Medientypen (JPEG, GIF, PNG, 3GP, AVI, WMV, MP4) verwenden. Keine Frames!
  • Entwicklung für mobiles Web: Keine Table-Layouts, keine nested Tables, keine Image-Maps, kein Flash.
  • Entwicklung für mobiles Web: Mobile-META-Tags verwenden: HandheldFriendly, MobileOptimized, Viewport.
  • Standard-Viewport für #WP7S: 1024px.
  • Entwicklung für mobiles Web: JS im Client für Fähigkeiten verwenden, UserAgent auf dem Server nutzen
  • Entwicklung für mobiles Web: Bei Codeplex mal nach #MBDF schauen – UserAgents und deren Fähigkeiten auswerten. BrowsCap 2.0?
  • IE7 + Features: getElementsByClassName, .querySelector, .querySelectorAll, Viewport, XHTML-Handling.
  • Viewport-Settings: width, height, user-scalable implementiert, minimum-scale, maximum-scale und initial-scale nicht implementiert.
  • CSS-Props: -ms-text-size-adjust, -webkit-text-size-adjust implementiert. Fixed positioning: Hängt am Dok., nicht am Window.

So, das waren dann alle Informationen, die ich auf der MIX gesammelt und für bloggenswert befunden habe.

Kommentieren » | WP7S, Windows Phone 7 Series

#WP7S: Das Mißverständnis – oder: Windows Phone ist nicht Windows Mobile

17. März 2010 - 19:58 Uhr

Auf der #MIX10 hat Microsoft virtuell die Hosen runtergelassen und viele, viele Details zu Windows Phone 7 Series veröffentlicht. Dabei waren Dinge, die für viele Entwickler, die bisher für Windows Mobile entwickelt haben, unverständlich sind und echte Showstopper darstellen, etwa der Verzicht auf C++, das Nicht-Vorhandensein einer Datenbank, die Einschränkungen hinsichtlich Ressourcen-Zugriff.

Allgemein gibt es im Moment ein gewaltiges Aufheulen in der Community, erste Petitionen werden gestartet, das große Jammern setzt ein. Dabei wird gerne übersehen, dass es zwei ganz gewaltige Unterschiede zwischen Windows Phone und Windows Mobile gibt:

  1. Windows Phone ist ein kompletter Neustart. Neu, neu, neu – alte Zöpfe wurden abgeschnitten, neue Ansätze ausgelotet. Das System ist darüber hinaus ein klassisches 1er Release, d.h. derzeit fehlende APIs und Funktionalitäten werden ziemlich sicher zukünftig nachgereicht.
  2. Die Zielgruppe ist eine komplett andere: Bisher waren es Geschäftskunden in verschiedenen Ausprägungen (klingt irgendwie… krank), jetzt sind es Privatleute. Menschen, die ganz andere Dinge, als beim bisherigen System erwarten. Und damit ändern sich auch die zur Verfügung gestellten Funktionalitäten und die Schwerpunkte der Plattform.

Beide Dinge sollte man verstehen, bevor man anfängt, sich über die Plattform aufzuregen.

Kommentieren » | Mobile, WP7S, Windows Phone 7 Series

#WP7S: Fakten-Roundup (II) von der #MIX10

17. März 2010 - 01:23 Uhr

Nächste Session zum Thema “Development für WindowsPhone 7 Series” ist vorbei. Hier wieder die wichtigsten Informationen:

  • Applikationen sind Page-basiert. #WP7S Struktur: Application -> Frame -> Page(s).
  • Navigation zwischen Pages: HyperlinkButtons
  • Daten übertragen: QueryString-Parameter im HyperlinkButton
  • Zugriff auf die QueryString-Parameter: NavigationContext.QueryString.TryGetValue(<Schlüssel>, out <Variable>);
  • In aufgerufener Page: OnNavigatedTo()-Methode überschreiben, um entsprechende Initialisierung vorzunehmen.
  • Navigation zurück: NavigationService.GoBack();
  • Orientation: SupportedOrientation-Property: Landscape, Portrait, PortraitOrLandscape.
  • OnOrientationChanged-Methode für entsprechendes Event überschreibbar.
  • App-Bar: Buttons und MenuItems. #WP7S Wichtig: Bilder für Buttons müsen als “Content” kompiliert werden.
  • Buttons werden in App-Bar direkt angezeigt, MenuItems sind halt das untergeordnete Menü
  • SplashScreen: SplashScreenImage.jpg, muss als “Content” kompiliert werden, wird automatisch angezeigt.
  • Standard-Controls beherrschen automatisch Theming und Skinning.
  • Push notifications: Vom Server initiiert. Großer Vorteil: Applikation muss nicht wirklich multitasken, wird per Push aktiviert.
  • Push Notifications: 3 Typen: Tile-Update, Toast-Notification (kleine Notification-Bar), App-Notification für laufende Applikationen.
  • Push-Notification: App sendet URI an eigenen Server, Server pushed an gegebene Applikation, Service benachrichtigt Device.
  • Push: Keine spezielle Software nötig, alles HTTP-Requests (POST).
  • Channel-URI wird von MS bereitgestellt..
  • HttpNotificationChannel-Klasse: HttpNotificationChannel channel = new HttpNotificationChannel(“<APP-Name>”);
  • EventHandler für ChannelUriUpdated -> In EventHandler wird die URI entgegen genommen.
  • Das Push-Zeug sieht wirklich einfach und angenehm benutzbar aus.
  • Location-Services derzeit im Emulator nicht aktiviert.
  • Location-APIs sind die gleichen, wie bei Windows 7.
  • Location auf drei Wegen: Satellit, WIFI und Triangulation per Basis-Stationen.
  • Es gibt einen Location-Service (frei) von Microsoft, so dass man oft auf GPS verzichten könnte.
  • Location-Service kann Adresse auflösen.
  • Klasse für Geo-Koordinaten: GeoCoordinateWatcher.
  • Auflösen von Adressen: CivicAddressResolver-Klasse.
  • Location-Handling sieht sehr cool aus.
  • BackKey-Abfangen: OnBackKeyPress-Methode überschreiben.
  • Obscured / Unobscured-Events für Störungen bzw.. das Weggehen der Störungen. Noch nicht in den MIX-Bits.
  • Paused / Unpaused – Applikation wird suspended. Wenn der Benutzer wiederkommt: Resume.
  • Wenn Pause, dann alles wegspeichern, App könnte (wird) gekillt werden.
  • Resume kann genutzt werden, um den Status wieder herzustellen.

So. Die nächste Session handelt von Performance-Optimierungen / –Überlegungen für Windows Phone 7 Series.

Kommentieren » | WP7S, Windows Phone 7 Series

#WP7S: Fakten-Roundup (#MIX10)

16. März 2010 - 23:48 Uhr

So, eine weitere interessante Session ist rum, hier wieder ein paar neue Fakten zu Windows Phone 7 Series aus Entwicklersicht:

  • Kein Zugriff auf die gesamte Kontaktliste, Einzel-Auswahl nur über Chooser
  • Keine Bluetooth-API derzeit
  • SD-Karten werden für den Programmierer nicht direkt unterstützt – Isolated Storage wird aber entsprechend dynamisch erweitert.
  • Kein(!) Cut, Copy & Paste-Support derzeit
  • Webbrowser-Control kann konfiguriert werden, so dass es JS ausführt: <Instanz>.EnableScript = true;
  • Webbrowser kann zu String navigieren (das, was bei #WM6 nicht funktionierte): <Instanz>.NavigateToString(<HTML>);
  • Kommunikation App <-> Webbrowser analog zu Windows: <Browser>.invokeScript(); Von Seite zu App: window.external.<Methode>().
  • Eingebautes Webbrowser-Control ist stets die selbe Version, wie der Browser
  • Derzeit nur ein MediaElement pro Page.
  • Vibrationen auslösen: VibrateController vc = VibrateController.Default; vs.Start(TimeSpan.FromSeconds(60)); :-)
  • MIC-Input: RAW-WAF-Daten abgreifen. Latenz etwa 10ms
  • Accelerometer ansprechen: AccelerometerSensor acc = AccelerometerSensor.Default; Reaktion per ReadingChanged-Event.
  • Devicespezifische Assemblies im System.Devices-Namensraum (und entsprechenden Assemblies).
  • Accelerometer: X, Y, Z-Richtungen (X ist horizontal, Y ist vertikal, Z ist Entfernung).
  • InputScopes in #WP7S geben an, welche Art von Eingabe (Nummern, Email-Adressen, etc.) eingegeben werden kölnnen.
  • Basis ist Silverlight 3, zusätzliche Assemblies

Mehr nach der nächsten Session.

Kommentieren » | WP7S, Windows Phone 7 Series

#MIX10: MIX-PIX

16. März 2010 - 17:59 Uhr

Hier einige Bilder von der MIX-Konferenz, relativ unmotiviert geschossen und nicht sortiert:

Inhaltlich ist die Konferenz definitiv spannender als die Bilder. :-)

Kommentieren » | Allgemeines

#WP7S: Die neuen Fakten

16. März 2010 - 00:30 Uhr

Auf der #MIX10 hat Microsoft den Vorhang von der Entwicklung für Windows Phone 7 Series gezogen. Wichtigste Nachricht vorweg: Die Entwicklertools werden kostenfrei zur Verfügung stehen. Weitere sehr wichtige Informationen: Keine Datenbank derzeit auf dem Phone und kein Multitasking für eigene Applikationen, dafür ein Push-Mechanismus.

Das sind die Fakten, die ich gerade einmal aus meiner Twitter-Timeline ziehe:

  • VS2010 als primäres Tool für Entwickler
  • Der Emulator ist x86-kompiliert, dürfte also um Klassen schneller als der 6.5er-Emulator laufen
  • Unterstützung für Push-Notifications, keine Background-Tasks
  • LINQ to Objects, LINQ to XML sind verfügbar
  • Oberfläche mit Silverlight 3+
  • Ganz klar: Kein Migrationspfad von 6.5 nach 7
  • Einfachste API, um die Trial-Funktionalität im Marketplace umzusetzen
  • Marketplace unterstützt Kreditkarten und Abrechnung durch Netzbetreiber
  • Phone als Developer-Phone freischalten funktioniert über Webseite bei MS, Phone wird remote unlocked
  • Dateiformat ist XAP
  • Ausschließlich .NET-Code, vom System gemanagete Sandbox
  • Silverlight für Applikationen, XNA für Spiele, Plattformen sollen zusammenwachsen
  • Silverlight soll zukünftig auch auf dei XBox kommen.

Das waren erst einmal die schnellen Fakten. More to come.

Kommentieren » | WP7S, Windows Phone 7 Series

Webbrowser-Control: ObjectForScripting

20. Februar 2010 - 23:48 Uhr

Man wird alt, wie ein Sack, man baut gefühlte siebenhundert Applikationen, die das Webbrowser-Control verwenden – und dann stellt man fest, das man bisher viel zu viel Arbeit in dämliche Workarounds gesteckt hatte, nur weil man die Doku nie komplett gelesen hat.

So ging es mir heute, als ich über die ObjectForScripting-Eigenschaft des .NET-Webbrowser-Controls gestolpert bin, die es erlaubt, eine Klasse zu definieren, deren Methoden vom Webbrowser-Control bzw. darin enthaltenem JavaScript-Code per window.external.<Methodenname> angesprochen werden kann. Einzige Bedingung: Die Klasse muss COM-sichtbar sein, also das ComVisible-Attribut muss mit dem Wert true gesetzt sein.

Tja, hätte man mal vorher in der Doku nachgeschaut…

Kommentieren » | .NET

#SQLCLR: Rückgabenlänge von Userdefined Functions

19. Dezember 2009 - 10:17 Uhr

Wer mit der im SQL Server 2005 / 2008 integrierten .NET-Unterstützung arbeitet, will diese Funktionalitäten recht schnell nicht mehr missen – wird aber über kurz oder lang auch darüber stolpern, dass etwa die Rückgabelänge von Zeichenketten auf 8 KByte beschränkt ist. Das mag zwar nach viel klingen, aber wenn man ein XML-Fragment zurückgeben möchte, stößt man recht zuverlässig an diese Grenze und fängt sich eine TruncationException ein.

Eine gewöhnliche Userdefined Function in C# sieht etwa so aus:

[SqlFunction]
public static SqlString Foo(String input) { ... }

Sowohl Rückgabe, als auch der Übergabeparameter input sind hier auf eine Größe von maximal 8 KByte beschränkt. Wem das nicht ausreicht, der muss das SqlFacet-Attribut verwenden, das sich sowohl oberhalb der Funktion, als auch vor dem Übergabeparameter notieren lässt:

[SqlFunction]
[return: SqlFacet(MaxSize = -1)]
public static SqlString Foo([SqlFacet(MaxSize = -1)] String input) { ... }

Problem gelöst: Die MaxSize-Angabe definiert, dass es keine maximale Größe für den Parameter oder die Rückgabe mehr geben soll. Nach dem erneuten Bereitstellen der Assembly im SQL Server sollte es keine TruncationException mehr geben.

Kommentieren » | .NET, SQL Server, Tipp

#Java: Kein Java 1.4 und Java 5 für Snow Leopard

7. Oktober 2009 - 18:03 Uhr

Wem es noch nicht aufgefallen sein sollte: Java 1.4 und Java 5 sind EOL, End of lifecycle. Das ist für sich nicht weiter schlimm, im Archiv von Sun kann man sich die älteren JREs und SDKs problemlos herunter laden, aber wenn man Snow Leopard besitzt, schaut man ganz schön in die Röhre, denn Sun liefert(e) Java für den Mac noch nie direkt aus, und Apple stellt die EOL-Versionen für Snow Leopard schlicht nicht zur Verfügung.

Die JREs kann man dennoch installieren, im Wiki von OneSwarm ist das anschaulich beschrieben und erklärt. Ohne Chance ist man (laut meinem derzeitigen Wissensstand) jedoch, wenn es um die SDKs geht, es sei denn, irgendjemand hätte noch eine gezippte Version davon auf der Platte.

Kommentieren » | Java

« Ältere Einträge