Mein Stundensatz

Der Stundensatz eines externen Mitarbeiters und was darunter zu verstehen ist.

Häufiger bin ich als Informatiker/Softwareentwickler als Experte, Entwickler oder Berater bei Firmen unterwegs. Da in der Softwareentwicklung immer mit unerwareten Problemen zu rechnen ist, diese aber in den Risikobereich des Auftraggebers fallen, wird in der Regel mit Stundensätzen abgerechnet. Pauschale gesamtkostenschätzungen sind einfach unseriös…

Doch wann beginnt die Uhr zu ticken, und was gehört dazu. Hier wiedergegeben ist meine Meinung zu Das Ganze. Vielleicht einen Tacken großzügiger als man meint, aber ich begründe es:

  • Anfahrt nicht dabei – Die Anreise, wie auch die Abreise ist Teil der Spesen. Entweder man vereinbart, dass Fahrten extra berechnet werden, oder man macht einen „inklusiven Stundensatz“, der Spesen enthält, und rechnet sich das intern hin.
  • Zeit beginnt ab Ankunft am PC – auch wenn es dann vielleicht erst einmal einen Kaffee gibt, denn Kaffeetrinken ist auch dabei.
  • PC startklar machen/Updates, die kommen – Teil der berechneten Zeit. Dass ein Rechner hochfährt oder aus sonstigen Gründen (unsägliche Updates) nicht sofort benutzbar ist, das gehört zu den unabwendbaren Tatsachen. Zwar ist es auch nicht die Schuld des Projektgebers, aber der Berater kann es eigentlich auch nicht ausbaden – Freizeit ist es jedenfalls nicht. Wo soll man in 5min auch hin? Nebenbei lässt es sich mit einem „Produktiven Kaffee“ überbrücken.
  • Kaffee/Wasser besorgen und mit Kollegen trinken – ist essentieller Teil der Arbeit. Damit berechnete Zeit. Auf diesem sog. Flurfunk wird neben Tratsch auch häufig die nächste hilfreiche/essentielle Information verteilt. Es wäre schade für beide Seiten, das zu verpassen. Der Deal zwischen Quatsch und Prduktivität ist zugunsten letzterer. Daher als sog. „Produktiver Kaffee“ bezahlte Zeit. Ein weiterer Aspekt ist, dass Kaffee und Getränk auch für den Körper essentiell sind. Ein Entwickler mit gelöschtem Durst oder mit wohligem Gefühl ist ein besserer Entwickler. Da diese Zeiten sich mehrheitlich wieder auszahlen für den Projektgeber ist es in seinem Interesse, dass Experten sich gut versorgen können. Es muss nicht gratis sein, wäre aber bei Kosten/Nutzenrechnung im Vorteil.
  • Mittagspause – eindeutig nicht dabei. Hier geht der Experte in seine Freizeit. Die er zwar zum Essen verwendet aber es ist einfach eine Pause und die Arbeitszeit wird unterbrochen.
  • Web-Browse-Pause am Rechner – ist bezalte Zeit. Warum? Als Entwickler muss man sich stark konzentrieren, um die bestellte Leistung zu erbringen. Das geht nicht 8h am Stück. Da ist es naturlich klar, dass zu jedem Konzentrationsboost eine Zerstreuungspause gehört. Und wenn Web-Browsen der Zerstreuung dient, dann ist es produktiv. Denn nur wer sich kurz zerstreut hat, kann wieder Leistung bringen. Möglicherweise kommt man ja genau dabei auf die Lösung eines Problems. Daher sind 1/4 der Zeit als derartige Pausen als normal und produktiv einzustufen.
  • Herumlaufen/Herumstarren – ist bezahlte Zeit. Hier gilt dasselbe wie bei Web-Browse-Pause. Wenn das herumstarren der Zerstreuung oder dem Denkvorgang dient und 1/4 der Zeit nicht überschreitet, dann ist es produktive Zeit.
  • Eine Runde Kickerspielen – fraglich. Hier kann man durchaus mal die Zeit anhalten. Vor allem, wenn es länger dauert. Indes ist es auch Zerstreuung und in diesem Fall dann produktive Zeit. Kommt auf die Länge an. 1/4-Regel.
  • Klopause – überraschend, aber auch das ist bezahlte Zeit. Gut, man kann argumentieren, dies solle zu Hause gemacht werden. Andererseits kommt das Bedürfnis wie höhere Macht aus dem Nichts und irgendwen trifft es halt. Aber halt: Die besten Ideen kommen doch oft, wenn man auf dem Örtchen sitzt… und Zerstreuung ist es auch. Daher: Wenn es wieder unter die 1/4 der Zeit-Regel passt, ist auch die Sitzung bezahlte Zeit.
  • Konferenz (sog. Meeting) – das hat natürlich der Projektgeber zu verantworten und wenn er der Meinung ist, dass man bei irgend einer Konferenz oder Lehrgang dabei sein sollte, dann ist das mit dem vollen Stundensatz zu bezahlen.
  • Privates Telefonat – kommt drauf an. Auch hier gilt wieder dasselbe wie bei Zerstreuung. 1/4 der Zeit darf es sein. Wird es länger oder ist das Gespräch eher aufregend, dann gehört es aus den Berechneten Stunden heraus.
  • Ende – wenn der Rechner verlassen wird und die letzte Taste gedrückt wurde. Dann endet die verbuchte Zeit.

Zusammenfassend kann man sagen, dass ein Arbeitstag nie 100% hochkonzentriert durchgehalten werden kann. Geht gar nicht. Es muss Zerstreuung und Entspannung dazu. Diese beiden Teile sind aber zeitlich verflochten und quasi untrennbar miteinander verbunden. Wer mich 1h engangiert, muss mir 15min „unproduktive“ Zeit zugestehen. Nur so bekommt er 45min volle Leistung. Was man als Entwickler in diesem ca. 1/4 der Zeit macht, ist egal. Gut wäre, dass man sich dabei zerstreut und im Unterbewusstsein weiterdenkt. So haben alle was davon. Und weil man nicht mitten am Tag 15min Freizeit machen kann, gehört diesr Teil genauso zum engagement dazu und wird berechnet.

Unit-Tests über fremdem Code mit „Microsoft Fakes“

Ja sowas geiles. Testen von statischen Methoden, Interfaces und sammeln von Ergebnissen (Aufrufen). Das alles geht mit dem ehemaligen MS-Research-Tool „Moles“, welches heute in „Microsoft Fakes“ aufgegangen ist und seit VS2012 mitgeliefert wird. Da allerdings schon jemand einen tollen Artikel darüber geschrieben hat, verweise ich einfach darauf:

Unit-Tests mit MS-Fakes…. Links:

Böser Dispatcher

An dieser Stelle eines der vielen Gotchas bei .Net-Entwicklung.

Es gibt manchmal Klassen (oft ViewModel), die haben prim​är mal keine GUI-Referenz, werden aber manchmal wecheslweise in einem Worker-Thread ausgeführt. Problematisch wird dann eine eventuell daran gebundene GUI. Oder man muss einfach nur unterscheiden, ob man im Worker-Thread oder im GUI-Thread lebt.

Der Dispatcher ist mehr oder weniger das unterscheidbare Merkmal, an dem ein GUI-Thread von anderen unterschieden werden kann:

Gleicher Thread wie der Dispatcher… Gut, möchte man meinen. Doch diese Prüfung hat einen bösen Fehler.CurrentDispatcher hat Seiteneffekte: Existiert kein Dispatcher zum aktuellen Thread, wird ein neuer erzeugt. Dispatcher sind nämlich keineswegs GUI-Spezifisch, sondern ein allgmeiner Dispatch-Mechanismus. Der Name ist irreführend.

Korrekt ist dagegen die Prüfung mit diesem Idiom:

Doch leider zu kurz gedacht. Im Prinzip ist das Richtig. Doch nur so lange, als keiner das erstere Idiom mit Dispatcher.CurrentDispatcher verwendet hat und uns somit einen parasitären Dispatcher auf den Worker-Thread gesetzt hat. Irgendwann hat dann jeder Worker-Thread einen Dispatcher.

Also was tun? Gleich auf Application zugreifen … tja leider. Denn Applicaiton ist der einzig gute Ankerpunkt in diesem Fall.

Dabei soll aber nicht unerwähnt bleiben, dass es in einer GUI-Applikation durchaus mehrere UI-Threads geben kann. Typischerweise dann in mehreren Fenstern. Es ist unwahrscheinlich, aber es geht und dann wäre auch dieser Code hier wahrscheinlich inkorrekt.

Bei WinXP-Fotoanzeige Diashow-Intervall einstellen

Womit man auf seine alten Tage noch so zu tun bekommt. Windows XP glaubte ich ja eigentlich schon hinter mich gebracht zu haben. Doch da gibt es Leute, die es tatsächlich noch einsetzen. Es war ja auch nicht so schlecht… nur ein wenig unsicher sonst aber…

Und wer es einsetzt um damit Urlaubsfotos durchzublättern kommt auf die Diashow der Fotoanzeige. Da die Zeitintervalle zwischen den Bildern mit 3 sek nicht allen Leuten taugen, kommen dann Fragen, wie man dieses Intervall wohl ändert. Da es keine Oberfläche dafür gibt, bleibt nur die Registrierung zu bearbeiten. Konkret muss man unter HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionExplorerShellImageView gehen und dort den DWORD-Wert Timeout erstellen. Hinein kommt die Zeit in Millisekunden, die die Fotoanzeige zwischen zwei Bildern warten soll.

Aus gegebenem Anlass habe ich für diese einfache Aufgabe ein Programm geschrieben. Verwendet habe ich dazu WinForms und C#. Man wird also das .Net Framework 2.0 benötigen. Das Programm bietet eine simple Oberfläche um genau diese Eine Aufgabe zu erledigen. Gut für Leute, die häufiger mal die Zeitabstände ändern müssen, mit der Registrierung aber nix am Hut haben.

Download Programmdatei

Download Quellcode

Anmerkung: Das Programm ist nach dem QnD-Prinzip entstanden. Daher nur schnell zackzack entstanden… einfach so.

WPF Dependency Properties von innen Setzen

Entwicklung eines WPF-Composite-Controls mit Dependency Properties (aka. Abhängkgeitseigenschaften)

Ab und zu muss man bei der Etnwicklung von WPF-Oberflächen neue Controls erstellen. Nun gibt es verschiedene Arten von Controls. Man unterscheided sog. Lookless Controls und Composite Controls. Erstere sind quasi rein nur eine von UIElement abgeleitete Datenstruktur. Das gesamte Verhalten, das Aussehen und die modifikation der Datenfelder (die Dependency Properties) geschieht über Styles und dort wiederum mit Triggern und Binungen. Darum soll es hier aber nicht gehen. Hier geht es um die andere Art von Control: Um Kompositum-Kontrollelemente bzw. User-Controls. Also in Etwa ein Panel oder ein Window. Mehrere Controls sind in einem neuen Control zusammengepfärcht und interagieren intern miteinander, während sie nach außen hin wie ein einziges auftreten. Dies lässt sich mit und ohne View-Model machen. Man hat also die Wahl zwischen MVVM und code behind. Je nach komplexität des Kontrollements ist es entweder sinnvoll oder einfach Overhead, ein View-Model dazu zu bauen. Hier soll es jetzt um ein einfaches Control gehen und daher greifen wir auf code behind zurück.

Das Control

Entwickelt wird ein Datei-Auswahl-Control. Es besteht aus einem Label und einem Button. Klickt man den Button, so erscheint ein Datei-Öffnen-Dialog und die fürderhin ausgewählte Datei wird angezeigt. Gleichzeitig hat auch die extern sichtbare Eigenschaft „FileName“ ihren Wert geändert und alle Bindungen  darauf ändern sich mit. Die Wahl fällt auf ein Control mit Code-Behind. Somit können wir einfach auf das Click-Ereignis des Buttons reagieren. Dort muss dan aktiv der Wert der Eigenschaft geändert werden. Tatsächlich ist hier par Bindung das Control sein eigenes View-Model.
Bestandteile:

Vorgehen

Zunächst benötigen wir ein Control.
Daher legen wir eine XAML-Datei an und passend dazu eine Code-Behind-Datei. Wir erben von System.Windows.Control.

 

und

 

Controlaufbau

Das Control besteht aus zwei weiteren Controls: Button und Label. Wir fügen beide ein und Binden das Label an die noch zu erstellende Eigenschaft FileName. Damit das nacher funktioniert, muss die Source noch korrekt sein. Wir erreichen das recht einfach, indem wir dem Conttol(!) den DataContext setzen und auf sich selbs verweisen lassen. Das Control ist
so gesehen sein eigenes View-Model.

 

Abhängigkeitseigenschaften

Zur erfolgreichen Bindung benötigt das Control noch eine Dependency Property FileName:

mah beachte, wie per FrameworPropertyMetadata ein Standardwert mitgegeben wurde und die Bindungsoptionen standardmäßgig auf TwoWay definiert wurden. Dies hat im Folgenden den Vorteil, dass man von Extern (bei Verwendung) nicht bei Binungen Mode=TwoWay angeben muss.

Events

Wir wollten es einfacher mit dem Button. Nun fehlt noch der Eventhandler:

Man beachte hier die beiden Aufrufe der von DependencyObject stammenden Methodena: SetCurrenValue und ClearValue. Damit wird der Wert bzw. die Bindung hinter einem Dependency-Property geänder bzw. auf den Std.-Wert (aus den Metadaten) zurückgesetztgesetzt. Verwendet man vergleichsweise dazu GetValue/SetValue wie in der Implementierung des CLR-Properties, zerstört man die Bindung. Das wäre fatal, da dann die Funktionalität zusammenbricht. An dieser Stelle sein noch kurz auf die Doku verwiesen… Demnach seien CLR-Getter/Setter nur so zu implementieren, wie hier gezeigt. Nur Aufrufe von GetValue/SetValue und keine weiteren Aktionen nebenher. Denn WPF ruft gerne selbst GetValue/SetValue mit passenden Parametern auf und umgeht dabei die CLR-Properties. Zusatzaktionen
muss man daher in passenden PropertyChanged– bzw. CoerceValue– oder ValidateValue-Callbacks machen. Auf selbige wurde hier verzichtet.

Eingebaut

Nun sehen wir uns noch an, wie dieses Control zu verwenden ist. Dazu wurde ein WPF-Fenster gestaltet, dass dieses Control verwendet und gleichzeitig einen Textblock an unsere neue Dependency-Property bindet:

 

… es ist kein Code-Behind nötig….
Man beachte, wie zunächst der text „aus window“ im Control steht, und später der Wert aus dem Eventhandler des Controls (siehe im Code: cancel oder OK-Zweig).

Programmiersprachen und Metadaten

Schaut man sich heute mal so den Quelltext eines mittleren Programms an, welches in C, C++ oder ähnlich geschrieben ist, wird man feststellen, dass es von Metadaten und Stringlisten nur so wimmelt. Der Grund ist klar die komplexität des Programms. Verursacht durch die Anforderungen die nach Flexibilität verlangen. Vereinfacht gesagt reicht eine Enumeration als Typ nicht mehr aus – stattdessen wird zusätzlich oder ersatzweise eine Liste oder ein Feld mit Zeichenketten und oder Konstanten angelegt. Oder es werden zusätzliche Elementvariablen in Klassen oder Strukturen eingeführt, die Metadaten zu ihren Objekten halten oder oder oder.

Sieht man sich dagegen ein Programm in einer verwalteten Sprache an wie Java oder .Net, stellt man ähnliches fest aber weit weniger. Meist sind die Programme komplexer geworden, weil nun mehr Freiheiten bestehen. Aber eigentlich benötigen sie derartiger Hilfskonstruktionen weniger. Stattdessen wird Reflexion häufiger eingesetzt. Typen (z.B. eine Enumeration) werden einfach definiert und verwendet (klassisch, Lehrbuch) und wenn die Anforderungen komplexer werden, werden diese Typen reflektiert. Man verlässt sich auf die von der Laufzeitumgebung bereitgestellten Metadaten und inspiziert sie / verwendet sie passend.

Das Resumé aus dem Ganzen ist nun: Früher, in den kompilierten Sprachen gab es wenig bis keine Metadaten. Ergo führen viele Programme im Quelltext welche ein (die aber nur eher schlecht mit den eigentlichen Daten (Kode) integrieren). Man stellte also fest, dass quasi jedes etwas komplexere Programm solche Metadaten benötigt. In der Folge berücksichtigte man das bei der Entwicklung von verwalteten Sprachen und sagte sich: Lass uns gleich für alle Typen zwangsweise Metadaten einführen und mitschleppen. So ist es bei Java, C# und .Net also möglich, Reflexion zu verwenden und Daten über Typen zu ermitteln. Überdies erlauben beide Sprachen das Anfügen von zusätzlichen Metadaten in Form von Attributen bzw. Annotationen. Das hat letztlich zu einem neuen Stil in der Entwicklung geführt. Man verlässt sich nun mehr auf Metadaten im Typsystem und legt Dinge generischer aus. Zwar werden Programme dadurch langsamer aber auch flexibler, stabiler und besser wartbar.

Über die Möglichkeit, die das Generieren neuer Typen zur Laufzeit angeht, lasse ich mich ein andermal aus.