L’interface fluide : vers un code orienté métier

Introduction

La maintenabilité d'une application dépend fortement de la lisibilité du code source sous-jacent. Cette lisibilité peut être améliorée par : 

  • l'introduction (mesurée) de commentaires dans le code
  • la présence sysématique de Javadoc
  • la vérification automatique à l'aide d'outils comme CheckStyle et PMD (règles de nommage, mesure de complexité...etc)
  • la revue de code effectuée par un développeur tiers

L'objectif de ce billet est de présenter une technique supplémentaire permettant d'améliorer la lisibilité du code : l'interface fluide

Exemple

public class Person {
    
    private String firstName;
    private String lastName;
    private Person father;
    private Person mother;
    public void setFirstName(String firstName){
        this.firstName = firstName
    }
    public void setLastName(String lastName){
        this.lastName = lastName
    }
    public void setFather(Person father){this.father = father}
    public void setMother(Person mother){this.mother = mother}
  
    //Getters volontairement omis pour plus de clarté
    ...
}

Ceci est une classe Person pouvant servir d'entité dans une application d'arbre généalogique. Créons un objet de ce type : 

//La personne
Person person = new Person();
person.setFirstName("Youri");
person.setLastName("Gagarine");
//Le papa
Person father= new Person();
father.setFirstName("Alexeï");
father.setLastName(" Ivanovitch");
//La maman
Person mother = new Person();
mother.setFirstName("Anna");
mother.setLastName("Timofeïevna");
//La famille
person.setFather(father);
person.setMother(mother);

Premier constat : ce code est verbeux. On aimerait qu'il ressemble à : 

//La personne
Person person = new Person().setFirstName("Youri").setLastName("Gagarine");
//Le papa
Person father= new Person().setFirstName("Alexeï").setLastName("Ivanovitch");
//La maman
Person mother = new Person().setFirstName("Anna").setLastName("Timofeïevna");
//La famille
person.setFather(father).setMother(mother);

Notre code est désormais à la fois moins verbeux et beaucoup plus lisible. Même une personne non-technique pourrait lire : 
  • Créer  une première personne dont le prénom et le nom....
  • Créer  une deuxième personne dont le prénom et le nom....
  • Créer  une troisième personne dont le prénom et le nom....
  • Lier la première personne au deux autres à l'aide des liens de paternité et de maternité.
Pour pouvoir bénéficier de cette "expressivité", il suffit de modifier les setters de la classe Person afin que chacun de ces setters renvoie l'objet this

public class Person {
    .....
    public Person setFirstName(String firstName){
        this.firstName = firstName; 
        return this;
    }
    public Person setLastName(String lastName){
        this.lastName = lastName;
        return this;
    }
    public Person setFather(Person father){
        this.father = father ;
        return this;
    }
    public Person setMother(Person mother){
        this.mother = mother ; 
        return this;
    }
    ...
}

Ici, on renvoie l'objet this mais rien n'empêche de renvoyer un objet d'un autre type. L'objectif de cette approche est de concevoir une API centrée sur le métier de l'application que l'on désire développer (Domain Specific Language). A titre d'exemple, L'API Criteria dans JPA 2.0 utilise cette technique pour construire les requêtes.

Conclusion

L'interface fluide aide à concevoir un code concis et orienté métier.

Références

5 commentaires

  1. Fluide interface est une mauvaise bonne idée bien qu’elle s’applique bien aux scripts(jquery).
    Si on ne respecte pas les conventions Java Beans, la perte est à considérer…(introspection, injection, intégration aux frameworks,…)
    Sinon, Scala permet d’atteindre l’objectif DSL.

  2. Abderrazek,

    Pour info , en anglais on dit « Fluent interface » et non « Fluid interface ».

    Pour ce qui est de la spec JavaBeans, cette dernière ne contraint pas du tout le type de retour du setter.

    Pour ce qui est de l’injection idem : aucune contrainte sur le type de retour du setter ( je te laisse faire un test simple avec Spring). Mieux encore, avec l’annotation @Inject (JSR-330), on peut injecter un champ qui ne possède ni getter ni setter (idem, je te laisse faire le test avec Spring)

    Quant à l’introspection, sache que le type de retour n’est pas discriminatoire : tu ne peux pas déclarer dans une classe deux méthodes dont la seule différence est le type de retour. Par conséquent, l’introspection identifie une méthode uniquement par son nom et ses paramètres.

    Pour ce qui est de l’intégration avec les frameworks…as-tu des exemples?

    Scala? ruby, groovy…aussi. Mais qui paye l’apprentissage?

    Et pour terminer, j’ai vu que tu as écrit un billet sur l’utilisation de JMock. Ce dernier fait explicitement la promotion de l’interface fluide.

  3. La capture ci-après apporte une indication. ((/public/ach/setterNOT_STANDART_reflection_echec_JMX.PNG|setterNOT_STANDART_reflection_echec_JMX.PNG))
    Tu peux essayer par toi-même avec le framework displaytag

  4. + Interface fluide testée avec displaytag1.1.1 et displaytag1.2 => Aucun souci

    – Je ne sais pas expliquer ta copie d’écran (je n’ai plus accès aui blog en édition) à moins que tu me fournisse le contexte exact à reproduire.

    :=)

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.