~ / TIS3 / AL / tps / notification /

Service du noyau fonctionnel : Notification

© 2015 - Renaud Blanch

Le but de ce TP est de mettre en pratique les principes d'architectures vus en cours : la séparation du noyau fonctionnel et de l'interface, l'indépendance du noyau fonctionnel, et le service de notification par le noyau fonctionnel pour permettre l'interaction en respectant les deux premiers principes.

Vous allez partir d'une application minimale fournie qui affiche dans une fenêtre la valeur d'un paramètre qui varie aléatoirement au cours du temps (dans un cas réel, il pourrait s'agir d'une grandeur physique mesurée par un capteur). Cette application ne respecte pas les principes désirés, il va donc s'agir de l'améliorer pas à pas.

Mise en route

Récupérez l'archive des sources de l'application et décompressez-la. Créez un nouveau projet nommé Notifier à partir de ces sources (New Java Project with Existing Sources) en ajoutant le répertoire téléchargé notifier.src à ce projet.

Exécutez ce projet en choisissant comme classe principale notifier.Main et vérifiez que : 1) dans la fenêtre de sortie (output en bas de NetBeans) des valeurs sont affichées ; et 2) une petite fenêtre s'ouvre et affiche ces mêmes valeurs en même temps.

Lisez les trois fichiers sources, Variable.java, Window.java et Main.java et vérifiez que vous comprenez ce qu'ils font.

Questions

Quelles classes font partie du noyau fonctionnel et quelles classes font partie de l'interface utilisateur ? Séparez ces classes en deux paquets, notification.fc (pour functional core) et notification.ui (pour user interface) sans vous soucier des dépendances pour l'instant.

Supprimez maintenant la dépendance du noyau fonctionnel envers l'interface. L'interface connaît le noyau, mais le noyau n'a pas à connaître l'interface (on doit pouvoir modifier l'interface sans affecter le noyau). Mais alors, comment indiquer à l'interface que la valeur gérée par le noyau a changé ?
Ajoutez une boucle sans fin à la méthode main de la classe Main qui va chercher la valeur de la variable pour mettre à jour l'affichage en continu.

Affichez dans la console, à chaque tour de boucle, le nombre de tours de boucle effectués depuis l'execution du programme (pour compter le nombre d'appels à la méthode valueChange).

Essayez de suivre ce nombre en temps réel. Chaque tour de boucle qui s'est effectué trop rapidement pour que vous ayez le temps de le voir est une itération qui surcharge le processeur inutilement. Corrigez ce problème en ajoutant un délais d'une seconde (Thread.sleep(1000)) à chaque tour de boucle.

Constatez maintenant que cette solution affiche les valeurs avec du retard.

On va maintenant ajouter un mécanisme de notification pour garder l'indépendance du noyau fonctionnel tout en permettant une mise à jour instantanée de l'interface. Pour cela, ajoutez au noyau fonctionnel une interface Callback qui contiendra une unique méthode :

public interface Callback {
	public void valueChange(double value);
}
Ajoutez à la classe Variable une liste callbacks d'instance de la classe Callback, une méthode d'abonnement :
public void addCallback(Callback callback) { ... }
et la notification aux abonnés dès que la valeur de la variable est modifiée.

Modifiez enfin la classe Window pour qu'elle implémente l'interface Callback et qu'elle s'abonne à la variable dès qu'elle est crée.

Vérifiez que l'interface est bien mise à jour instantanément et que les principes de séparation et d'indépendance du noyau fonctionnel sont bien respectés (c'est-à-dire, que l'interface connait le noyau mais le noyau ne connaît pas l'interface, le noyau a juste une liste d'abonnés à notifier et ne sait pas qui ils sont ni comment ils gèrent la notification).

Ajoutez une seconde fenêtre à votre programme qui affiche également la variable en temps réel. Par défault, les 2 fenêtres se superposent. Vous pouvez pallier ce problème en appelant la méthode setLocation(int x, int y) héritée de la classe JFrame par la classe Window.

Pour aller plus loin

Java fournit un mécanisme tout fait de fonctions de rappel par le biais des classes PropertyChangeSupport, PropertyChangeListener, et PropertyChangeEvent du paquet java.beans. En vous aidant du tutoriel sur l'utilisation des propriétés, supprimez l'interface ad-hoc Callback et remplacez son utilisation par l'utilisation de l'interface générique PropertyChangeListener. Mettez en commentaire le code des questions précédentes, ne supprimez pas tout !

mise à jour : 9 février 2021