ExpressionBuilder

Original: http://martinfowler.com/bliki/ExpressionBuilder.html

 

 

 

Martin Fowler

8 Août 2013

L’un des problèmes avec un FluentInterface est qu’il conduit à des méthodes qui cherchent impairs. Considérons cet exemple:

 

customer.newOrder()
  .with(6, "TAL")
  .with(5, "HPK").skippable()
  .with(3, "LGV")
  .priorityRush();


Méthodes comme avec, à sauter, et priorityRush ne siègent pas bien sur la classe de commande. La nomination fonctionne bien dans le contexte de la petite DomainSpecificLanguage que l’interface fournit couramment, mais nous nous attendons généralement API sous la forme de ce que je appelle une API de commande Query. Dans un API de commande requête chaque méthode est logique individuellement dans ne importe quel contexte. Il peut également honorer des principes tels que CommandQuerySeparation qui en Java signifie que les méthodes qui modifient la ObservableState d’un objet ne devraient pas avoir une valeur de retour. Mélange méthodes couramment de style avec des méthodes de commande requêtes peuvent prêter à confusion parce que les méthodes couramment peuvent violer les attentes de ce que la plupart des API devraient ressembler.

Un générateur d’expression est une solution à ce problème. Un constructeur d’expression est un objet distinct sur lequel nous définissons l’interface fluide qui se traduit alors les appels fluides aux appels API réguliers sous-jacents. Ainsi, un constructeur d’expression pour le cas de la commande ressemblerait à quelque chose comme ça.

 

public class OrderBuilder {
  private Order subject = new Order();
  private OrderLine currentLine;

  public OrderBuilder with(int quantity, String productCode) {
    currentLine = new OrderLine(quantity, Product.find(productCode));
    subject.addLine(currentLine);
    return this;
  }

  public OrderBuilder skippable() {
    currentLine.setSkippable(true);
    return this;
  }

  public OrderBuilder priorityRush() {
    subject.setRush(true);
    return this;
  }

  public Order getSubject() {
    return subject;
  }
}


Dans ce cas, je ai une seule classe expression constructeur, mais vous pouvez également avoir une petite structure de constructeurs, quelque chose comme un constructeur à la clientèle, afin constructeur, et la ligne constructeur. L’utilisation d’un objet unique signifie que vous besoin d’une variable de garder une trace de ce que la ligne que vous travaillez sur la méthode à sauter. En utilisant une structure peut éviter cela, mais ce est un peu plus compliqué et vous devez vous assurer constructeurs de niveau inférieur peut gérer méthodes qui sont destinés à la hausse des constructeurs d’ordre. Dans ce cas, une OrderLineBuilder aurait besoin de disposer de méthodes de délégation pour toutes les méthodes de la OrderBuilder.

Lectures complémentaires

Je parle plus en détail sur les constructeurs d’expression dans mon livre sur Domain-Specific Languages

Un bon exemple ouverte de l’utilisation d’un constructeur d’expression est dans la bibliothèque JMock. Je ai trouvé le papier OOPSLA décrivant l’évolution du DSL de JMock manipulation très utile.

Historique des révisions

Première publié le 4 Janvier 2007. Révisé le 8 Août 2013.