Dans un billet précédent, je vous faisait part d'une grande découverte que nous avions fait lors du développement de nos applis WPF : Vos développeurs vont devoir oublier une bonne partie de ce qu'ils savent sur l'écriture d'une application ! Eh bien, pour que cela soit un peu plus parlant, voici un exemple.
NB : tous les codes fournis dans cet article ne sont pas à utiliser dans l'état, et présentent juste une façon naïve et simplifiée à outrance des concepts que je souhaite démontrer. A vous de compléter tout cela par les habituelles optimisations, gestion d'erreurs etc.
Imaginons que vous ayez à afficher dans un écran une liste de clients, en Windows Forms, cela devrait ressembler plus ou moins à cela :
// ...
public void Search(/* ... */)
{
List<Client> clients = MonObjetMetier.Search(/* ... */);
listView1.Items.Clear();
foreach (Client c in clients)
{
ListViewItem it = listView1.Items.Add(c.Nom);
it.SubItems.Add(c.CodePostal);
it.Tag = c;
}
}
// ...
Une méthode Search(), qui raffraichit une liste- bon, évidemment, dans la vraie vie vous auriez fait quelque chose de plus complexe pour utiliser le multi-threading ainsi que pour éviter le listview1.Items.Clear() - et cela roule. Maintenant, imaginez que vous ayez la même chose à faire en WPF... bien sûr, la même technique est parfaitement utilisable, mais vous n'allez pas vous faire aimer de votre designer : il aura besoin de vous ne serait-ce que pour échanger l'ordre des colonnes !
La première chose à faire, c'est de ne plus réflechir en terme de "texte affiché" mais en terme "d'objet affiché" : ce n'est pas à vous, en tant que développeur, de décider ni où, ni comment seront affichés (si ils le sont) les codes postaux ! Contentez-vous de vous dire que l'écran affiche des clients, et laissez quelqu'un d'autre se charger de la présentation.
// ...
public void Search(/* ... */)
{
List<Client> clients = MonObjetMetier.Search(/* ... */);
listView1.Items.Clear();
foreach (Client c in clients)
{
listView1.Items.Add(c);
}
}
// ...
Si vous utilisez cette méthode, le designer pourra assez facilement modifier la façon dont seront affichées chacune des lignes de la liste (avec un DataTemplate) et/ou l'apparence globale de celle-ci (par un ControlTemplate ou un ItemsPanelTemplate). En vous arrêtant là, vous aurez déjà fait un gros progrès par rapport à WinForms, mais il est possible d'aller beaucoup plus loin : dans l'extrait de code ci-dessus, c'est encore le developpeur qui decide de mettre les données dans la listview. Et si le designer voulait utiliser autre chose qu'une listview ? ?
La deuxieme partie de l'équation est donc d'arrêter, aussi, de réaliser des écrans qui affichent quelque chose : encore une fois "ce n'est pas à vous, en tant que développeur, de décider ni où, ni comment seront affiché[e]s (si [elles] le sont)" les données. Contentez vous de fournir des données (sous la forme de collections, par exemple, à vous d'optimiser la façon dont ses données sont chargées/mise à disposition).
// ...
public ObservableCollection<Client> LesClients = ...
public void Search(/* ... */)
{
List<Client> clients = MonObjetMetier.Search(/* ... */);
LesClients.Clear();
foreach (Client c in clients)
{
LesClients.Add(c);
}
}
// ...
En écrivant vos programmes de cette manière, vous devriez voir une grande simplification du workflow développeur<>designer, chacun pouvant alors s'occuper de ce qu'il connait le mieux : la gestion des règles métiers et de l'aspect technique ou la représentation des informations et leur manipulation.