Passer au contenu principal

Elle est peu connue, et pourtant il s’agit probablement d’un des meilleurs trucs qui existent dans le langage, j’ai nommé : la visibilité package private en Java.

Quelques rappels sur les niveaux de visibilités

Nous avons deux types de niveaux de visibilité en Java pour les classes, attributs et méthodes :

– Ceux qui font partie de votre API
– Ceux qui n’en font pas partie.
Seuls les niveaux de visibilité faisant partie de votre API pourront être utilisés par des développeurs de projets tiers. Bon pour le pervers du fond, il est vrai que tant que vous ne marquez pas vos JAR comme Sealed il est possible de contourner cette restriction. On peut aussi utiliser la réflexivité à moins d’avoir mis en place un SecurityManager.

Les niveaux de visibilité faisant partie de l’API

Commençons par la visibilité public. Dans ce mode, votre méthode/attribut/classe sera visible à la fois des classes héritées de toutes les autres classes, aussi bien à l’intérieur qu’à l’extérieur du package de votre classe. On la déclare comme suit :


public void foo();

Ensuite, on a la visibilité protected. Dans ce mode, votre méthode/attribut/classe sera visible des classes qui héritent de la vôtre, ainsi que des classes qui sont dans le même package que la vôtre. Autrement dit si une classe d’un package différent hérite de la vôtre, elle aura accès à l’élément protected. Par contre si cette même classe n’en hérite pas, elle ne pourra pas l’utiliser.


protected void foo();

A noter qu’une classe qui ne fait pas partie d’une classe parente ne peut être déclarée protected.

Les niveaux de visibilité ne faisant pas partie de votre API

Les niveaux ci-dessous ne seront normalement pas utilisables par des tiers, pour peu qu’ils codent un minimum proprement.

Le niveau de visibilité package private est le moins connu et pour cause : c’est le seul qui n’a pas de mot-clef dédié. Un attribut/méthode/classe ayant cette visibilité pourra être utilisé uniquement depuis d’autres classes appartenant au même package. La déclaration est comme suit :


void foo();

Enfin le niveau de visibilité private est le plus restrictif. Un attribut/méthode/classe ayant cette visibilité pourra être utilisé uniquement depuis l’intérieur de cette classe. A noter que les classes private doivent obligatoirement appartenir à une classe parente qui ne soit pas private. La déclaration est pour ces classes/attributs/méthodes est comme suit :


private void foo();

Et alors, à quoi cette visibilité sert ?

En fait cette visibilité va servir à deux choses :

– Mieux découper votre code.
– Simplifier les tests unitaires.
Voyons ça de plus près.

Mieux découper votre code

On trouve fréquemment dans la vraie vie des classes contenant de très nombreuses méthodes, la majorité étant private. L’explication est que le développeur ne souhaite pas que ces méthodes fassent partie de son API. Le souci est qu’en procédant ainsi, les classes atteignent rapidement plusieurs milliers de lignes de code.

Une solution existe pourtant pour faire face à ce problème : il suffit de créer une ou plusieurs classes ayant la visibilité package private, autrement dit sans le mot clef public devant class, dans laquelle vous déportez certaines de vos méthodes. L’idée est de regrouper ces méthodes par thématiques plus simplement qu’en ajoutant de gros commentaires indiquant que vous passez de méthodes en rapport avec telle ou telle fonctionnalité à d’autres. D’ailleurs si vous devez faire appel à de tels commentaires, c’est qu’il est urgent de penser à découper votre code…

Simplifier les tests unitaires

Pour préserver la maintenabilité des tests unitaires, on fait fréquemment appel à des frameworks de mocking, le plus connu étant probablement Mockito dans le monde Java. Ceux-ci permettent de simuler le comportement d’objets tiers sans que vous ayez à vous préoccuper de leur implémentation réelle, c’est d’ailleurs une jolie application de la programmation orientée objet non ? 😉

Il se trouve qu’il est impossible sans sévèrement tricher de faire un mock sur une méthode privée, étant donné qu’on ne peut mocker les méthodes d’une classe sous test. (En fait si c’est possible avec des outils comme Powermock mais vaut mieux éviter pour plein de raisons.) Or un test unitaire doit idéalement tester seulement un petit fragment de code et pas tout un système. Dès lors si vous devez appeler d’autres méthodes il sera souvent utile de les mocker.

Et c’est précisément là que la visibilité package private rentre en jeu : en déplaçant vos méthodes dans une classe package private du même package vous pouvez tester simplement séparément les méthodes de la classe package private, puis celles de votre classe qui fait partie de votre API. Et comme ça il est simple de monter à 80% minimum de couverture de code. En prime vous découpez mieux votre code.

Cet article vous a plu ? Vous aimerez sûrement aussi :

Julien
Moi c’est Julien, ingénieur en informatique avec quelques années d’expérience. Je suis tombé dans la marmite étant petit, mon père avait acheté un Apple – avant même ma naissance (oui ça date !). Et maintenant je me passionne essentiellement pour tout ce qui est du monde Java et du système, les OS open source en particulier.

Au quotidien, je suis devops, bref je fais du dév, je discute avec les opérationnels, et je fais du conseil auprès des clients.

Son Twitter Son LinkedIn

Rejoignez la discussion Un commentaire

  • Il y a confusion ici entre private et internal. En .net, si on veut qu’une classe soit public à l’intérieur du package (qu’on appelle un assembly) et privée en dehors, il faut utiliser le mot clé Internal.

    un Assembly peut exposer ces classes internal à un projet en tests via l’attribut [internalsvisibleto(…)]

Laisser un commentaire