33 votes

Interfaces Fluent - Chaînage de méthodes

Le chaînage de méthodes est le seul moyen que je connaisse pour construire des interfaces fluides.

Voici un exemple en C #:

 John john = new JohnBuilder()
    .AddSmartCode("c#")
    .WithfluentInterface("Please")
    .ButHow("Dunno");

Assert.IsNotNull(john);

  [Test]
    public void Should_Assign_Due_Date_With_7DayTermsVia_Invoice_Builder()
    {
        DateTime now = DateTime.Now;

        IInvoice invoice = new InvoiceBuilder()
            .IssuedOn(now)
            .WithInvoiceNumber(40)
            .WithPaymentTerms(PaymentTerms.SevenDays)
            .Generate();

        Assert.IsTrue(invoice.DateDue == now.AddDays(7));
    }
 

Alors, comment les autres créent-ils des interfaces fluides? Comment le créez-vous? Quelle langue / plate-forme / technologie est nécessaire?

51voto

Bevan Points 20976

L'idée de base de la construction d'une interface fluide est l'une des raisons de lisibilité - quelqu'un de lire le code doit être en mesure de comprendre ce qui est en train d'être réalisé sans avoir à creuser dans la mise en œuvre de préciser les détails.

Moderne OO langages tels que C#, VB.NET et Java, le chaînage de méthode est une façon que cet objectif est atteint, mais ce n'est pas la seule technique - les deux autres sont classes usine et les paramètres nommés.

Notez également que ces techniques ne sont pas mutuellement exclusives, l'objectif est de maximiser readabilty du code, pas la pureté de l'approche.

Le Chaînage De Méthode

L'idée clé derrière le chaînage de méthode est de ne jamais avoir une méthode qui retourne void, mais toujours revenir à l'objet, ou plus souvent, une interface, qui permet en outre de passer des appels.

Vous n'avez pas besoin de renvoyer nécessairement le même objet sur lequel la méthode a été appelé - qui est, vous n'avez pas toujours besoin de "retour cette;".

Il est utile de conception technique est de créer un intérieur de classe - j'ai toujours suffixe ces avec "Expression" - qui expose l'API fluent, permettant la configuration d'une autre classe.

Cela a deux avantages: il garde l'API fluent dans un endroit isolé de la fonctionnalité principale de la classe, et (parce que c'est un intérieur de classe) on peut bricoler avec les entrailles de la classe principale de moyens que les autres classes ne peuvent pas.

Vous souhaiterez peut-être utiliser une série d'interfaces, de contrôler les méthodes qui sont à la disposition des développeurs à un moment donné dans le temps.

Classes Usine

Parfois, vous voulez construire une série d'objets - les exemples incluent la NHibernate Critères de l'API, de Rhinocéros.On se moque de l'attente des contraintes et NUnit 2.4 nouveau de la syntaxe.

Dans ces deux cas, vous avez des objets réels que vous stockez, mais pour les rendre plus faciles à créer il y a des classes de fabrique de fournir des méthodes statiques pour la fabrication les instances que vous avez besoin.

Par exemple, dans NUnit 2.4 vous pouvez écrire:

Assert.That( result, Is.EqualTo(4));

Le "Est" de la classe est une classe statique complète de l'usine de méthodes qui créent des contraintes pour l'évaluation par NUnit.

En fait, pour permettre des erreurs d'arrondi et d'autres imprécision de nombres en virgule flottante, vous pouvez spécifier une précision pour le test:

Assert.That( result, Is.EqualTo(4.0).Within(0.01));

(L'avance des excuses - ma syntaxe est peut-être éteint.)

Les Paramètres Nommés

Dans les langues qui les prennent en charge (y compris Smalltalk et C# 4.0) paramètres nommés fournir un moyen pour inclure d'autres "syntaxe" dans un appel de méthode, l'amélioration de la lisibilité.

Envisager un hypothétique méthode Save() qui prend un nom de fichier, et d'appliquer les autorisations pour le fichier après l'enregistrement:

myDocument.Save("sampleFile.txt", FilePermissions.ReadOnly);

avec des paramètres nommés, cette méthode pourrait ressembler à ceci:

myDocument.Save(file:"SampleFile.txt", permissions:FilePermissions.ReadOnly);

ou, plus couramment:

myDocument.Save(toFile:"SampleFile.txt", withPermissions:FilePermissions.ReadOnly);

50voto

Chris Pietschmann Points 13397

Vous pouvez créer une interface fluide dans n’importe quelle version de .NET ou dans tout autre langage orienté objet. Tout ce que vous avez à faire est de créer un objet dont les méthodes renvoient toujours l'objet lui-même.

Par exemple en C #:

 public class JohnBuilder
{
    public JohnBuilder AddSmartCode(string s)
    {
        // do something
        return this;
    }

    public JohnBuilder WithfluentInterface(string s)
    {
        // do something
        return this;
    }

    public JohnBuilder ButHow(string s)
    {
        // do something
        return this;
    }
}
 

Usage:

 John = new JohnBuilder()
    .AddSmartCode("c#")
    .WithfluentInterface("Please")
    .ButHow("Dunno");
 

16voto

hangy Points 7722

Autant que je sache, le terme couramment l'interface ne permet pas de spécifier une technologie spécifique ou de cadre, mais plutôt un modèle de conception. Wikipédia possède une vaste exemple de fluent interfaces en C♯.

Dans une simple méthode de définition, vous ne retournez pas l' void mais this. De cette façon, vous pouvez la chaîne de toutes les déclarations sur l'objet qui se comportent comme ça. Voici un exemple rapide basé sur l'original de votre question:

public class JohnBuilder
{
    private IList<string> languages = new List<string>();
    private IList<string> fluentInterfaces = new List<string>();
    private string butHow = string.Empty;

    public JohnBuilder AddSmartCode(string language)
    {
        this.languages.Add(language);
        return this;
    }

    public JohnBuilder WithFluentInterface(string fluentInterface)
    {
        this.fluentInterfaces.Add(fluentInterface);
        return this;
    }

    public JohnBuilder ButHow(string butHow)
    {
        this.butHow = butHow;
        return this;
    }
}

public static class MyProgram
{
    public static void Main(string[] args)
    {
        JohnBuilder johnBuilder = new JohnBuilder().AddSmartCode("c#").WithFluentInterface("Please").ButHow("Dunno");
    }
}

5voto

Andre Vianna Points 759

Il y a quelque temps, j'ai eu les mêmes doutes, vous avez maintenant. J'ai fait quelques recherches et maintenant je suis en train d'écrire une série de billets de blog sur la techinics de la conception d'une interface fluide.

Consultez-le à:

Lignes directrices à parler Couramment la conception de l'Interface en C# partie 1

J'ai une section sur l'enchaînement de X de Nidification, qui peuvent être intéressantes pour vous.

Dans les posts suivants, je vais en parler dans un sens plus profond.

Meilleures salutations,

André Vianna

3voto

Jeff Fritz Points 5002

Interface fluide est réalisé en programmation orientée objet en retournant toujours à partir de vos méthodes de la même interface qui contient la méthode. Par conséquent, vous pouvez obtenir cet effet en java, javascript et vos autres favoris langages orientés objet, quelle que soit la version.

J'ai trouvé cette technique la plus facile à réaliser grâce à l'utilisation d'interfaces:

public interface IFoo
{
	IFoo SetBar(string s);
	IFoo DoStuff();
	IFoo SetColor(Color c);
}

De cette façon, toute classe qui implémente l'interface, obtient la fluidité de la méthode de chaînage des capacités. FWIW.. j'ai écrit le code ci-dessus en C# 1.1

Vous trouverez cette technique parsemé tout au long de l'API jQuery

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X