Attribute für die Konfiguration von Verhalten

Weit jenseits von spektakulär oder elegant, aber denoch nützlich ist das Verwenden von Attributen für die Konfiguration von Verhalten. Hier ein Beispiel für die Konfiguration von Testfällen:

[TestFixture] 
[RestartIocContainer(true)] [TruncateAllTables(true)]
public class CatalogDuplicationTest : TestBase
{
    [Test]
    public void SomeTest()
    {
        //
    }
}

Der Testfall kümmert sich beim Ausführen des SetUps um die Auswertung der Attribute. Hier der konkrete Code aus der Basisklasse:

...
 
[SetUp]
public virtual void SetUp()
{
    if (IsOnMethodSetupTruncateAll())
        _nHibernateHelper.TruncateAll();
 
    ...
}
 
private bool IsOnMethodSetupTruncateAll()
{
    foreach (Attribute attribute in GetType().GetCustomAttributes(true))
        if (attribute.GetType() == typeof(TruncateAllTablesAttribute))
            _onMethodSetupTruncateAll = ((TruncateAllTablesAttribute)attribute).Value;
 
    return _onMethodSetupTruncateAll;
}
 
...

Der Vollständigkeit halber hier noch der Code für ein Attribut, wobei die MSDN das Thema Attribute hervorragend abdeckt

public class TruncateAllTablesAttribute : Attribute
{
    public bool Value = true;
 
    public TruncateAllTablesAttribute(bool value)
    {
        Value = value;
    }
}

Clean Code Developer MindMap

Erstellt von Daniel Rothmaler und sehr besuchenswert, vor allen Dingen da die Knoten direkt auf die entsprechenden Absätze der Clean-Code-Developer-Seite zeigen:

Clean-Code-Developer-MindMap 


"NHibernate.MappingException: Association references unmapped class" die Zweite

Ich bin heute auf ebendiese Exception gestossen als ich folgende zeilen zu einem Mapping-File in CO hinzufuegte: 

<set name="NHibernateFiles">
<key column="EntityId"/>
<one-to-many class="SpeakFriend.Utilities.StoredFile, SpeakFriend.Utilities"/>
</set>

Per Google-Suche landete ich direkt auf unserem Blog und fand Olivers Beitrag. Ich dachte schon, das Problem waere erledigt. Einfach das Mapping-File auf "Embedded Ressource" setzen und fertig. Aber Pustekuchen, das war ja schon alles richtig eingestellt. Ich konnte auch StoredFile von CO aus persistieren . Ein Blick in die App.config half mit auch nicht weiter:

<mapping assembly="SpeakFriend.Utilities" />
<mapping assembly="ConceptOffice.Core" />
<mapping assembly="ConceptOffice.Core.Client" />

Alles war fein referenziert. Und es klappte ja auch alles. Nur beim parsen des Mapping-Files hatte er ein Problem.

Nun die Aufloesung: Ein Durchwuehlen des Stack-Traces fuehrte mich auf folgende Stelle: 

protected NHibernateHelper _nhibernateHelperSqlLite =
new NHibernateHelper(new Configuration().Configure("lite-nhibernate.cfg.xml")
.BuildSessionFactory().OpenSession());

Beim Blick in lite-nhibernate.cfg.xml fiel es mir dann wie Schuppen von den Augen. Die fettgedruckte Zeile fehlte: 

<mapping assembly="SpeakFriend.Utilities" />
<mapping assembly="ConceptOffice.Core" />
<mapping assembly="ConceptOffice.Core.Client" />

Fazit: Nur nicht aufgeben, man findet den Fehler immer irgendwann.


BUG-Centric Development

Vorweg, der folgende Post soll primär zeigen wie gut wir mit Bugs umgehen, nicht das Gegenteil.  Ich denke auch, dass wir einen hochwertigen Entwicklungsprozess haben, den wir immer weiter verbessern, dieser Post soll dabei helfen.

Das folgende Diagramm zeigt die Entwicklung der aktiven Bugs seit dem 13 November 08 für www.camping.info.

Bugs-Active 

Wie läst sich hohe Anzahl der Fehler erklären?

Nach Sichtung der offenen Fehler, lassen sich folgenden Gründe finden:

1:) Verbesserungen werden als Bug erfasst. Oft sind die Grenzen zwischen Bug und UserStory verwaschen. Ob die nicht vorhandene Benutzernachricht ein Fehler oder ein Verbesserungswunsch ist, ist oft eine Grenzfrage. Der Vorteil eine Verbesserung als Bug zu erfassen liegt vermeidlich darin, dass der Verbesserungswunsch/Bedarf, nicht in der Vielzahl von UserStories untergeht.

2) Alte Bugs werden nicht reviewed und geschlossen. Ein Fehler der nicht der aktuellen Iteration zugeordnet ist geht gerne unter, auch wenn er schon lange nicht mehr besteht. Denn das Reviewen und Schließen kostet in jedem Fall Zeit und unser Kunde brauch neue Features!

3:) Fehler die reported wurden, aber nicht zuzuordnen sind. Beispielsweise wurde mehrfach beobachtet, dass das CSS der Seite im Firefox nicht geladen wurde. Auch wenn sich im entsprechenden Bug die Lösungsansätze sammeln, konnte der Fehler konnte noch nicht nachvollzogen werden. In dieser Kategorie haben wir einige Fehler die wir vermutlich auch nicht so schnell lösen werden und sollten, mit Blick auf die richtige Prioritisierung.

Bug: Als Entwicklungsfeedback

Das folgende Diagramm zeigt die geschlossenen Bugs seit dem 13 November:

Bugs-Closed

Hier ist es möglich, das eine Prozess-Problem dokumentiert wird. Entwicklungen werden umgesetzt und geclosed. Mark unser Tester deployed auf den Stage-Server und findet Fehler die als Bug-reported werden. Ein Verbesserung könnte erreicht werden, in dem wir konsequenter UserStories auf “zu Testen” setzen und Probleme in weiteren Aufgaben, Fragen und Testfällen dokumentieren.

Insgesamt würde ich mir wünschen, das wir weg kommen vom Ansatz Bugs als Kommunikationsmittel zu verwenden, hin zu eine Arbeitsweise in der Bugs als Qualtitätsmetrik nützlich sind.

In wieweit eine solche Perspektive Projekten wirklich hilft, scheint mir schwer zu sagen, wobei ich ein bisschen hoffe, dass sich Prozesse durch Formalisierung und Analyse verbessern und optimieren lassen.


Projekt Versionierung und Buildmanagement

Für unsere Projekte verwenden wir eine Versionierungsstrategie, in der es darum geht die Versionskontrolsystem-Revision (in unserem Fall SVN) zuzuordnen:

Beispiel www.camping.info:

Camping-Info-Revision

Interessant für uns, ist nur der hintere Teil: 2013.214.

Die Version wird vor jedem deployment in die Assembly.Info.cs geschrieben, noch händisch, und so wieder ausgelesen:

Assembly assembly = Assembly.GetExecutingAssembly();
ltVersion.Text = assembly.GetName().Version.ToString();

 

Für das Build-Mangement verwenden wir Target-Process, wobei der Buildname auch die Revision beinhaltet:

Build-Übersicht

Hier lässt sich sehen, dass die aktuelle Camping.Info Version (x.x.2013.214) am 30 Juil deployed wurde und zur Iteration 4.7 gehört.

Noch mehr Informationen finden sich den Build-Details:

Build-Details

Die Build-Details beinhalten alle in der Version durchgeführten Änderungen. Diese Informationen können als Info an den Kunden direkt weitergegeben werden. Mit Erwin Oberascher von www.camping.Info haben wir jedoch den Ideal-Fall, in dem der Kunde Zugriff und Interesse an solchen Projekt-Artefakten hat.