Fluent Interfaces: Sinnvoll?

Ich hatte Fluent Interfaces mal in einem Blog gelesen und hatte es seit dem auf meinem Zettel stehen, das mal genauer anzusehen.

Was ist das eigentlich? Wikipedia weiß es natürlich.

Sucht man bei Google danach findet man Blogs mit Einträgen von 2006/2007…sind Fluent Interfaces schon tot? Vielleicht!

Einige Beispiele:

IConfigurationFluent config =
      new ConfigurationFluent().SetColor("blue")
                               .SetHeight(1)
                               .SetLength(2)
                               .SetDepth(3);

Das schreit einfach nach dem Object Initializer von C#! In etwa so:

IConfiguration config =
      new Configuration {Color = “blue”, Height=1, Length=2, Depth=3};

Dann spart mach sich das zusätzliche “return this” in der Implementierung.

Ok, dann hat Troy Demonbreun folgendes Beispiel:

order
    .AddFreeShipping()
    .IncludeItem(15)
    .SuppressTax();

Das sieht an sich ja ganz nett aus, allerdings hat seine Implementierung den “Fehler”, dass IncludeItem() den Kontext von Order auf OrderItem ändert. Nach meinem Verständnis von Fluent Interfaces müsste aber folgendes möglich sein (geht bei ihm nicht):

order
    .AddFreeShipping()
    .IncludeItem(15).SuppressTax()
    .IncludeItem(4)
    .IncludeItem(77)
    .PrepareAsGift();

Und als drittes Beispiel hab ich folgendes, leicht komplexes Konstrukt gefunden:

EventComponent planningMeeting =
   Plan.Event("Project planning meeting").
      RelatedTo(planningTask).
      WithPriority(1).
      At("Head office").
      OrganizedBy("jane@megacorp.com", "Jane Doe").
      StartingAt("12:00").Lasting(45).Minutes.
      Attendants(
         "peter@megacorp.com",
         "paul@megacorp.com",
         "mary@contractor.com").AreRequired.
      Attendant("john@megacorp.com").IsOptional.
      Resource("Projector").IsRequired.
      ClassifyAs("Public").
      CategorizeAs("Businees", "Development").
      Recurring.Until(2008).EverySingle.Week.On(Day.Thursday).
      Except.Each.Year.In(Month.July | Month.August);
planningMeeting.SendInvitations();

…hier kann ich schon etwas verstehen, warum Fluent Interfaces (=FIs) sexy sein könnten. Aber zuerst muss ich hier auch sofort wieder an Object Initializer und Collection Initializer denken (Nein, ich bau das jetzt nicht um :-P ) und dann hab ich da noch einen letzten Punkt zu: Man kann FIs nur einsetzen, wenn man zu einem Zeitpunkt bereits alles weiß zu dem Objekt, was man erstellen will. Das ist an sich ja nicht schlecht, aber wie kommt denn die Liste der Attendants da rein? Doch meistens mit foreach und das geht nicht in dieser Kette von Aufrufen.

Ach und noch ein allerletzter Punkt: In diesem Ansatz muss ich viel Schmalz darauf verbraten, wann eine Methode Sinn macht:

…Attendants( … ).Except.Minutes.WithPriority(1); //?!

Fazit:
[x] Ich hab mir Fluent Interfaces angesehen
[x] Ich weiß keinen guten Fall, wann das Ganze wirklich Sinn macht

This entry was posted in C#, coding. Bookmark the permalink.

5 Responses to Fluent Interfaces: Sinnvoll?

  1. Hi,

    ich habe mich im Zuge meiner Bachelorarbeit mit dem Thema beschäftigt. Der Wikipedia-Artikel am Anfang von deinem Beitrag ist zum Beispiel von mir ;)
    Klar sind Fluent Interfaces kein Allheilmittel aber sie machen vor allen Dingen da Sinn wo man eine API anbieten will die sich so gut wie von allein erklärt und den Benutzer davor bewahrt sie falsch zu benutzen. Und wie du schon geschrieben hast, dass Erstellen eines Fluent Interface ist nicht unbedingt trivial. Und genau hier setzt meine Bachelorarbeit an. Ich habe versucht das Erstellen von Fluent Interfaces so weit wie möglich zu erleichtern. Mit Hilfe eines Modellers ist es nun möglich Fluent Interfaces in Diagrammen zu modellieren aus denen dann direkt der Code generiert werden kann.

    Schau mal einfach unter: http://www.fluent-interfaces.com

    Grüße
    Philipp

  2. Fabse says:

    Moin!

    ich hab mir direkt auch mal deine videos angeguckt. im hintergrund liefern diese methoden nicht “this” zurück, sondern immer wieder andere klassen, die erst im zusammenspiel das fluent interface darstellen. das finde ich gut, denn man kann dadurch keine falschen sachen zusammenbauen. Aber man sieht auch, wie du für die einfachsten dinge schon viel aufwand hast und ich möchte nicht wissen, wie lange du an dem metamodel gesessen hast…hatte mal einen kommilitonen, der sich auch mit generierung beschäftigt hat und ich glaube, das lohnt sich erst, wenn du fluent interfaces am band produzierst bzw. man selbst das metamodel nur einkauft… und ich glaube die “generierung von sql” durch eine fluent api kannste so gut wie vergessen. gibt in der .net welt linq2sql, was das so ziemlich darstellt und da haben sicherlich ne gute menge ms-entwickler dran geschraubt und nun das ganze trotzdem über board geworfen, weils einfach zu komplex ist. Aber trotzdem gute Arbeit, was haste für deine BA bekommen? Ich hoffe doch ne 1?!

  3. Hallo nochmal,

    nun die Modellgetriebene Softwareentwicklung ist eigentlich nur zu Beginn etwas aufwendig. Hat man erstmal ein Metamodel (und das ging in diesem Fall ziemlich schnell) und eine Generierungsebene kann man sehr schnell Änderungen vornehmen. Die Generierung von SQL selbst sollte auch nur ein Beispiel sein. Kann aber für die einfachsten Fälle oder sagen wir mal angepasst auf ein jeweiliges Projekt sehr sinnvoll sein. Es muss ja nicht der gesamt Sprachumfang umgesetzt werden nur vielleicht das was man immer wieder auf dieser Ebene braucht. Der Vorteil ist folgender. Verwendet man solche Sprachen ohne IDE-Unterstützung dann fallen Fehler meist erst zur Laufzeit auf. Bildest du aber einen Teil der Grammatik mit einem Fluent Interface ab hast du gleich vorab eine Code-Validierung durch den Compiler. Hinzukommt, dass man Einsteigern den Umgang mit neuen Technologien in einem Projekt so enorm erleichtern kann. Aber natürlich sind Fluent Interfaces kein Allheilmittel. Sicher der Aufwand für ein komplexes Fluent Interface ist nicht zu unterschätzen aber genau dafür habe ich ja diesen Fluent Interface Modeller entwickelt :) Sonst musste man das alles per Hand schreiben. In einem größen Beispielprojekt konnte ich so von knapp 4000 Zeilen Code 95% automatisch aus meinem Modell generieren lassen. Die restlichen 200 Zeilen war sehr schnell hinzugefügt.

  4. jo says:

    Der Fehler tritt meines erachtens nur während des debuggens auf.
    // Internal static method that returns a read-only, non-user override accounted, CultureInfo object
    internal static CultureInfo CreateReadOnlyCultureInfo(string name) {
    if (!_cultureCache.Contains(name)) {
    // To be threadsafe, get the lock before creating
    lock (_cultureCache) {
    if (_cultureCache[name] == null) {
    _cultureCache[name] = CultureInfo.ReadOnly(new CultureInfo(name));
    }
    }
    }
    return (CultureInfo)_cultureCache[name];
    }

  5. Fabse says:

    Sorry, aber ich sehe den Zusammenhang zum Beitrag und/oder den anderen Kommentaren nicht?!

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

*

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>