La solution consiste donc à être pragmatique, et pour ce faire, rien ne vaut le développement piloté par les tests, aka TDD, puisqu'il permet de mettre en situation le code de la classe et ainsi choisir le niveau d'encapsulation ad hoc pour chacun des composants de la classe en cours de conception.

Cependant, l'expérience m'a appris que cela n'est pas toujours suffisant, et en conséquence, j'applique lors de mes développement une philosophie complémentaire, basée sur le succès, ou plus précisément sur ce qui fait le succès des formats ouverts.

En effet, un format ouvert, du fait même qu'il soit ouvert et donc manipulable, échangeable ou manipulable facilement, a une espérance de vie beaucoup plus longue qu'un format fermé.

Il favorise de plus l'interopérabilité entre les systèmes et il est également beaucoup plus évolutif, puisque ces spécifications sont connus de tous et que tout à chacun peut donc le modifier pour l'adapter à ses besoins sans la moindre restriction.

Le principe des formats ouverts est d'ailleurs tellement puissant que des sociétés telle que la fondation Mozilla ont pour but, entre autre, de les promouvoir afin d'assurer l'interopérabilité au sein d'Internet.

Or, une classe, en POO, a pour but d'interagir avec d'autres classes, et se doit d'être évolutive afin de pouvoir être adapté aux besoins des utilisateurs, via, entre autre, le mécanisme d'héritage.

Il est donc possible de faire un parallèle entre un format ouvert et une classe, et logiquement, il n'y a aucune raison que ce qui fait le succès de l'un ne fasse pas le succès de l'autre.

Le secret d'une classe réussie est donc dans l'ouverture maximale vers l'extérieur, et donc le recours le plus systématique possible au mot-clef public, et cela aussi bien pour les propriétés que pour les méthodes.

En conséquence, lorsque je développe, tous les composants de ma classe sont publiques par défaut.

Ce n'est qu'une fois que le TDD m'a permis de définir l'intégralité de l'interface de ma classe, aussi bien au niveau des propriétés que des méthodes, ainsi que son implémentation, que je réduis au besoin le niveau de visibilité des éléments de ma classe.

Arrivé à ce point, vous allez me dire que le développeur se retrouve dans la même situation qu'au départ.

En effet, à première vue, il ne dispose d'aucune règle qui lui permette de choisir son niveau d'encapsulation, mais en y regardant de plus prés, ce n'est pas exact.

Du fait de l'utilisation du TDD, le développeur dispose d'une implémentation, d'un code concret, qu'il peut analyser à loisir afin de définir les éléments critiques, c'est à dire ceux qui ne doivent absolument pas être altéré par l'extérieur sous peine de briser l'intégrité de l'objet ou de corrompre son fonctionnement.

Mais là encore, suivant le principe des formats ouverts, il est nécessaire de limiter au maximum le niveau d'encapsulation, en privilégiant l'utilisation de protected et en n'appliquant le mot-clef private que sur les éléments les plus spécifiques, et qui sont donc à ce titre intégralement extrêmement dépendant de l'implémentation de la classe.

De plus, toujours suivant le même principe, il ne faut pas perdre de vue qu'il est toujours possible de définir des accesseurs et des modificateurs pour les propriétés protégées ou privées afin de permettre leur modification sans corrompre l'objet.

C'est ainsi que par exemple, en PHP, il est de bon ton de définir comme étant protégée une propriété qui doit être d'un certain type, et de définir la méthode permettant de l'initialiser comme étant publique, cette dernière étant chargée de s'assurer que la propriété sera toujours du bon type, de la manière suivante :

<?php

class foo {
protected $adapter = null; // doit être une instance de \adapter.

public function setAdapter(\adapter $adapter)
{
$this->adapter = $adapter;
return $this;
}
}

?>

Cependant, l'utilisation du TDD permet de faire apparaître ces méthodes spécifiques au cours du processus de développement si elles sont nécessaires, et en conséquence, il n'y a pas besoin de s'en soucier outre mesure dans ce contexte.

Et il y a un autre point capital à ne pas oublier.

Le succès des formats ouverts vient du fait que leurs spécifications sont connues, et dans la grande majorité des cas, elles sont connues car rédigées sous la forme d'une documentation.

En conséquence, il est nécessaire de documenter les classes et surtout leur implémentation précisément, soit à l'aide des tests unitaires, soit à l'aide d'une documentation plus explicite.

Ce dernier point est notamment primordial pour tout ce qui a le niveau de visibilité protected, pour deux raisons.

Tout d'abord, ce n'est pas forcément testables, et ensuite, une mauvaise utilisation d'un élément protégé par une classe fille peut potentiellement très facilement corrompre l'intégrité de l'objet, puisqu'un élément protégé est nécessaire à son bon fonctionnement, sans pour autant être spécifique à l'implémentation.

Et comme la bonne utilisation de ces éléments est de la responsabilité du programmeur et que le plus gros problème en informatique est situé entre la chaise et le clavier, il est absolument nécessaire de borner les choses au maximum afin de limiter au maximum le risque d'erreur.

Évidemment, tout cela tient plus de la recette de cuisine que d'autre chose, puisque c'est le fruit de mon expérience, que ce soit en tant que développeur C++ ou en tant que développeur PHP.

Dans l'ensemble, cela donne de bons résultats, mais je n'ai absolument aucun argument scientifique pouvant étayer mon propos.

Mais, après tout, le bon sens a-t-il besoin d'être validé par la Science ?