Samedi 24 Avril 2010
Modèles d'application
Tiens, le topic de Folco sur les façons de coder m'a rapellé un des nombreux posts que j'avais l'intention d'écrire, alors je vais le faire tant que j'y pense.
En observant la façon dont sont conçues les applications, on observe souvent deux façons de faire.
Une application en console avec un parsing intégral des paramètres de texte, et par dessus, une interface graphique qui s'interface avec le mode texte de l'application.
Je l'apellerai le « modèle Linux », vous comprendrez pourquoi.
Une application graphique, monobloc, contenant tout le code, logique et l'interface.
Je l'apellerai le « modèle Windows », bien que cela soit également applicable aux applications OSX.
Le modèle Linux est dérivé d'une habitude à toujours vouloir des utilitaires en ligne de commande, utilisables dans des scripts, mais s'adapte mal ailleurs. Les interfaces construites par dessus le mode texte souffrent d'une rupture brutale avec le modèle de données de l'application, rendant l'interfaçage et la synchronisation entre les deux mondes (texte et graphique), très difficile. Parfois, la partie graphique va devoir réimplémenter des traitements déjà faits par l'application en mode texte, car elle n'a aucun accès direct au code de celle-ci… Celà conduit souvent à des interfaces de piètre qualité, qui marchent pour un oui ou pour un non, mais ne savent pas toujours vous remonter la raison exacte des erreurs.
Le modèle Windows a été fait pour un monde graphique, où la ligne de commande joue un rôle très marginal. Dans ce cas, pas la peine de concevoir un quelconque mode texte, et la conception d'interfaces graphiques est d'autant plus aisée.
Si chacun de ces deux modèles peuvent sembler avoir leurs avantages, soyons honnêtes… Moi je les trouves tous les deux complètement nuls.
Il existe une autre façon de faire…
Découpler le code de l'application du code de l'interface, par exemple en plaçant le code de l'application dans une librairie séparée. De cette manière, il est possible de créer plusieurs interfaces indépendamment des fonctionnalités de l'application. Le code ainsi produit est réutilisable, et facilement modifiable. L'interface graphique et l'interface texte bénéficieront du même ensemble de fonctionnalités, directement accessibles.
Bien évidemment, cela implique de développer deux interfaces différentes, mais pas nécéssairement simultanément…
Une application bien codée devrait toujours suivre ce modèle (même si elle est au final, et par souci de simplicité, compilée en un seul fichier) ou un modèle dérivé. Ne serait-ce parce que cela implique aussi une façon propre de structurer le modèle de données.
Allons un peu plus loin maintenant. Et répondons à la question: Pourquoi je vous parle de tout ça ?
Et bien d'abord parce que je me suis rendu compte, après avoir codé pas mal de trucs, que mon code propre tendait très fortement vers ce modèle, et que c'est vraiment aisé d'en dériver deux interfaces (texte/graphique) sans avoir trop de code à écrire.
Ensuite, parce que cela permet de concevoir des applications multi-plateformes décentes, offrant une interface native à chaque couple système d'exploitation + interface (graphique ou texte…). Cela pourrait aussi être un jeu, avec une interface DirectX pour Windows, OpenGL pour tout le monde, DirectFB pour Linux, etc… Vous voyez le dessin ?
En gros, ce que je suggère, c'est de coder l'application en tant que bibliothèque (.so, .dll, .dylib, ce que vous voulez…), et séparément, de coder une (ou plusieurs) interfaces en tant qu'éxécutables (.exe, a.out, ce que vous voulez…).
Ce n'est pas un concept de back-end (l'application va utiliser son interface comme un plug-in) ou de front-end (le « modèle Linux » ), mais bel et bien quelque chose de différent que je propose.
Peut-être cela a-t-il déjà un nom d'ailleurs, mais ça, je n'en sais fichtrement rien.
En observant la façon dont sont conçues les applications, on observe souvent deux façons de faire.
Je l'apellerai le « modèle Linux », vous comprendrez pourquoi.
Je l'apellerai le « modèle Windows », bien que cela soit également applicable aux applications OSX.
Le modèle Linux est dérivé d'une habitude à toujours vouloir des utilitaires en ligne de commande, utilisables dans des scripts, mais s'adapte mal ailleurs. Les interfaces construites par dessus le mode texte souffrent d'une rupture brutale avec le modèle de données de l'application, rendant l'interfaçage et la synchronisation entre les deux mondes (texte et graphique), très difficile. Parfois, la partie graphique va devoir réimplémenter des traitements déjà faits par l'application en mode texte, car elle n'a aucun accès direct au code de celle-ci… Celà conduit souvent à des interfaces de piètre qualité, qui marchent pour un oui ou pour un non, mais ne savent pas toujours vous remonter la raison exacte des erreurs.
Le modèle Windows a été fait pour un monde graphique, où la ligne de commande joue un rôle très marginal. Dans ce cas, pas la peine de concevoir un quelconque mode texte, et la conception d'interfaces graphiques est d'autant plus aisée.
Si chacun de ces deux modèles peuvent sembler avoir leurs avantages, soyons honnêtes… Moi je les trouves tous les deux complètement nuls.
Il existe une autre façon de faire…
Bien évidemment, cela implique de développer deux interfaces différentes, mais pas nécéssairement simultanément…
Une application bien codée devrait toujours suivre ce modèle (même si elle est au final, et par souci de simplicité, compilée en un seul fichier) ou un modèle dérivé. Ne serait-ce parce que cela implique aussi une façon propre de structurer le modèle de données.
Allons un peu plus loin maintenant. Et répondons à la question: Pourquoi je vous parle de tout ça ?
Et bien d'abord parce que je me suis rendu compte, après avoir codé pas mal de trucs, que mon code propre tendait très fortement vers ce modèle, et que c'est vraiment aisé d'en dériver deux interfaces (texte/graphique) sans avoir trop de code à écrire.
Ensuite, parce que cela permet de concevoir des applications multi-plateformes décentes, offrant une interface native à chaque couple système d'exploitation + interface (graphique ou texte…). Cela pourrait aussi être un jeu, avec une interface DirectX pour Windows, OpenGL pour tout le monde, DirectFB pour Linux, etc… Vous voyez le dessin ?

En gros, ce que je suggère, c'est de coder l'application en tant que bibliothèque (.so, .dll, .dylib, ce que vous voulez…), et séparément, de coder une (ou plusieurs) interfaces en tant qu'éxécutables (.exe, a.out, ce que vous voulez…).
Ce n'est pas un concept de back-end (l'application va utiliser son interface comme un plug-in) ou de front-end (le « modèle Linux » ), mais bel et bien quelque chose de différent que je propose.
Peut-être cela a-t-il déjà un nom d'ailleurs, mais ça, je n'en sais fichtrement rien.

Par contre découper en plusieurs processus je suis pas sur de voir où tu veux en venir. (Oui, on peut, mais pour quoi faire ?)
./5> Bah en tout cas pas ce qui touche aux services vitaux du système. (Genre les outils wifi & co…)
On préfère faire 50 utilitaires en mode console qui s'attaquent aux API bas niveau du noyau de manière brutale plutôt qu'élaborer une API propre et _unique_ que tout le monde puisse utiliser. C'est ce qui désavantage linux comparativement aux systèmes propriétaires des tréfonds de l'enfer (ça c'est pour faire plaisir à Kevin).
./3 > Ouais, si seulement !
Enfin pour les jeux de TI faut pas abuser, ces machines n'ont pas la même puissance que nos PC
./2 > Bah j'attend de voir le « beaucoup de gens », parce qu'au niveau de ce qu'on a accès dans le grand public, c'est pas encore ça. Y'a guère que Office (& dérivés genre Visual Studio) qui me vienne a l'esprit dans le genre modulaire et réutilisable, mais en dehors de ça…
D'ailleurs, SA/RT est très adaptée pour construire ce genre de programme de façon intelligente
Note en plus que non content de découper ton application en modules d'un point de vue architecture, tu peux en plus la découper en plusieurs processus en suivant ce même découpage.
- qu'on sort pour le dev en cours d'architecture logicielle
- qu'on enseigne pour les fameuses 7 couches du réseau (en précisant toujours qu'une fois implémentées il n'en reste que 3 ou 4)
- qu'on présente sur la répartition client/serveur (du mainframe au client lours)
- qu'on assène avec les modèles/normes CUA, MDI, SDI, MVSDI...
Avec en permanence le même problème, outre le fait que d'une part (comme tu le dis) les frameworks permettant de resepecter ces "normes" sont quasi-inexistants, on a toujours un choix cornellien sur le mode "d'optimisation" des développements : rapide, performant, petit, maintenable, portable (deux choix possibles).
Après, si des frameworks rendaient cette séparation plus instinctive et facilement réutilisable, ça pourrait être intéressant.