Les mots ont leur importance

/img/post/pouvoir-des-mots.jpg

Il y a plusieurs années de ça, dans le cadre d’un projet de restructuration d’un programme, initialement conçu selon une approche procédurale multi-couches encore en vigueur dans les années 2000, vers une conception plus orientée objet, un des développeurs a lancé, sur le renommage des DAO en Repository, que ce ne sont que des mots qui désignent la même chose. Récemment, dans un tout autre contexte, j’ai reçu une reflexion similaire sur la dénomination de classes d’objet dont les noms étaient soit techniques, soit généralistes (du genre FooService ou FooManager).

Les mots ont pourtant leur importance. Ils véhiculent des idées, des concepts et c’est par eux que nous communiquons et comprenons ce que nos interlocuteurs veulent nous dire. C’est aussi par eux que nous construisons nos peceptions et donc nos propres mythes. Ils forgent même, par leur sémantique propre, et leur composition, ceux-ci. Choisir tel mot au lieu d’un autre n’est pas anodin et peut dénoter la structure de nos pensées et celle de nos croyances. Un exemple simple peut être donné avec la sémantique différente que véhicule chacune des expressions «à cause de» et «grâce à» et l’utilisation de l’un plutôt que l’autre.

Ainsi, dénaturer les mots ou utiliser l’un en lieu et place d’un autre, et vous modifiez la compréhension, voir pire, le raisonnement, votre vision, conduisant ainsi, potentiellement, à des incompréhensions, voir des déviances. C’est pourquoi des politiciens, des entrepreneurs ou managers s’évertuent à user et parfois abuser de paralogismes le plus souvent pour cacher la vacuité de leurs propos et de leur vision même, et nous donner à entendre ce que l’on veut bien y trouver (ou ce qu’ils veulent, parfois aussi, s’autopersuader). Joseph Goebbels n’a t’il pas écrit :

A force de répétitions et à l’aide d’une bonne connaissance du psychisme des personnes concernées, il devrait être tout à fait possible de prouver qu’un carré et en fait un cercle. Car après tout, que sont «cercle» et «carré» ? De simples mots. Et les mots peuvent être façonnés jusqu’à rendre méconnaissables les idées qu’ils véhiculent.

Malgré la résonnance de ces propos avec l’actualité, nous ne sommes toutefois pas ici pour débattre de celle-ci, pas plus de la post-vérité qui sévit dans la sphère politico-médiatique et celle des réseau-sociaux. Par contre, le poids des mots en politique et en société l’est, aussi, tout autant dans notre métier. Après tout, qu’est ce que tente d’apporter selon vous Eric Evans avec son Domain Driven Design (DDD), si ce n’est un moyen, par le biais d’un ubiquitous language et de modèles d’analyse, de conscientiser des concepts métiers et leurs relations de manière compréhensible aussi bien par les gens du métier que par les développeurs. Oui, les mots ont leur importance, voir même ils sont le socle même de nos compréhensions d’une problématique, de sa solution ainsi que de nos échanges.

Aussi, lorsqu’un développeur me dit que DAO ou Repository «osef», c’est joué avec les mots, je ne peut m’empêcher de lever les yeux et de laisser échapper un profond et long soupir. Pourquoi ? Après tout, l’un et l’autre ne sont qu’un moyen d’accéder aux données des objets métiers persistées dans une source de données, quelqu’elle soit (noSQL ou SQL). Une DAO (Data Access Object), toutefois, comme son nom l’indique, a une forte connotation technique et, d’ailleurs, il est courant que son interface transpire de détails techniques propre à la source de données sous-jacente. Comme l’illustre l’exemple en Java ci-dessous (dans ce qui suit, j’ommet explicitement le code des méthodes, le sujet étant le nommage) :

public class VoucherDetailsDao {

    public VoucherDetails getByPrimaryKey(VoucherPK voucherKey) {
        // SQL request by using either JDBC or a Data Mapper library
    }

    public List<VoucherDetails> getAllByCustomerForeignKey(PrimaryKey customerKey) {
        // SQL request by using either JDBC or a Data Mapper library
    }

    ...
}

(Il m’est arrivé de rencontrer en guise de DAO, en lieu et place de classes instanciables, des classes statiques !)

La classe implémente directement les accès à la base de données SQL ici. C’est assez courant parce que dans la vie d’une application il est extrêmement rare de changer le type de source de données. Toutefois, ceci peut poser problème lorsque l’on change de système de base de données et que l’implémentation contient des détails techniques non génériques propres à celui jusqu’alors utilisé. Ou encore que l’on change d’outil de requêtage à la base de données (en passant par exemple de JDBC à un cadriciel de Data Mapping comme MyBatis par exemple). C’est pourquoi il est moins coûteux et plus aisé de découper l’interface de l’implémentation au début du projet :

public class VoucherDetailsDaoImpl implements IVoucherDetailsDao {

    @Override
    public VoucherDetails getByPrimaryKey(VoucherPK voucherKey) {
        // SQL request by using either JDBC or a Data Mapper library
    }

    @Override
    public List<VoucherDetails> getAllByCustomerForeignKey(PrimaryKey customerKey) {
        // SQL request by using either JDBC or a Data Mapper library
    }

    ...
}

Le nommage illustré par le code ci-dessus est celui que je rencontre le plus souvent ; le I préfixant le nom de l’interface est pour indiquer que c’est une interface et le Impl postfixant la classe que c’est une implementation. Nous pouvons remarquer les noms très techniques de l’interface, de la classe et des méthodes. J’ai souvent constaté, à ce titre, que le nommage technique des classes d’objets amenaient souvent le programmeur a avoir une démarche de pensée toute aussi technique et par conséquent à doter la classe d’une interface elle aussi teintée de détails techniques qui, selon l’approche orientée objet, auraient dû être encapsulés. Les mots conditionnent la pensée. Toutefois, il est possible de cacher ces détails par une interface moins teintée technique :

public class VoucherJdbcDao implements VoucherDao {

    @Override
    public Voucher getById(Id voucherId) {
        // SQL request by using JDBC
    }

    @Override
    public List<Voucher> getAllByCustomer(Id custommerId) {
        // SQL request by using JDBC
    }

    ...
}

Ici, je précise, par l’usage du terme JDBC, que l’implémentation utilise directement l’API JDBC de Java pour accéder à la base de données relationnelle. Si JPA est utilisée comme abstraction d’infrastructure de persistance, l’implementation peut être écrite comme suit :

public class VoucherJPADao implements VoucherDao {

    @Override
    public Voucher getById(Id voucherId) {
        // requesting by using JPA
    }

    @Override
    public List<Voucher> getAllByCustomer(Id custommerId) {
        // requesting by using JPA
    }

    ...
}

(L’accès aux objets persistés se faisant par l’intermédiaire de l’interface VoucherDao, l’implémentation utilisée est encapsulée par le moteur d’injection des dépendances ou par une Factory.)

Par conséquent, quelle différence y a t’il entre le code ci-dessus et celui ci-après ?

public class VoucherJPARepository implements VoucherRepository {

    @Override
    public Voucher getVoucher(Id voucherId) {
        // requesting by using JPA
    }

    @Override
    public List<Voucher> getAllCustomerVouchers(Customer custommer) {
        // requesting by using JPA
    }

    ...
}

Nonobstant le nommage, nous devrions avoir ici le même code. Ce qui est le cas. Pourtant, il y a une nette différence par le nom même des classes et des méthodes. Les mots ont leur importance, ne l’oubliez pas, parce qu’ils véhiculent la sémantique et donc la manière perçue des choses et des concepts.

Dans le premier cas, nous avons un objet techique et par son aspect technique, nous aurons tendance à penser technique et donc à oublier le métier derrière auquel s’inscrit cet objet. C’est pourquoi les DAO sont très souvent codés comme je l’ai illustré ici (et encore dans le meilleur des cas). Alors, certes, oui, le rôle d’un DAO est d’ordre technique ; il fait partie de l’infrastructure selon la dénomination en vigueur en DDD. Mais, selon l’approche orientée objet, sa technicité se doit d’être cachée par son interface. Autrement dit, son interface doit adhérer au modèle métier et tous les aspects techniques, que ce soit d’implémentation ou de responsabilité, se doivent être encapsulés.

Ainsi donc, si un DAO est un objet qui accède aux données persistées, donc un objet de convénience (comme les classes utilitaires par exemple), le Repository est, quant à lui, un objet qui représente un dépôt d’objets métier du domaine, ici dans notre exemple, les Vouchers. La sémantique, ici, a son importance. Le Repository est par conséquent lui aussi un objet métier, mais d’infrastructure, qui encaspule les détails techniques d’accès à la source de données. Aussi, le programmeur qui manipule ou code l’interface du Repository conserve une démarche mentale, et par conséquent une approche de programmation, avant tout orientée métier et non plus technique. La technique viendra seulement quand il s’agira de coder le corps des méthodes ; nous pouvons dire ici que l’étape, le processus, de codage technique est tout aussi encapsulé que l’implémentation.

Avec un exemple très simple, j’espère avoir mis en exergue, même dans la réalisation d’un logiciel, l’importance des mots et des expressions dans le code. Les noms véhiculent la sémantique de chaque unité logicielle (classe, méthode, …) dans une programme. Par conséquent, les noms permettent non seulement de comprendre en un seul coup d’oeil le rôle et la représentation de l’unité logicielle dans le métier, mais ils participent aussi à ce que les développeurs gardent, sans rupture, une vision et une démarche mentale axée sur ce même métier.


comments powered by Disqus