Utilisation des fonctionnalités de QML : privilégier le code QML/JavaScript
Ou le complémenter avec du code C++/Python ?

Le , par Jiyuu

0PARTAGES

1  0 
Privilégier le code QML/JavaScript ou le complémenter avec du C++/Python ?
Utilisation des fonctionnalités de QML : lorsque cela est possible, faut-il privilégier le code QML/JavaScript ou le complémenter avec du code C++/Python ?

QML est un langage de programmation déclaratif basé sur Qt, pouvant utiliser JavaScript pour les parties impératives et initialement prévu pour faciliter la création d'application mobiles, animées et esthétiques. Avec JavaScript, le développeur a donc accès à un large panel de fonctionnalités, rendant le code QML/JS autonome.

À titre d'exemple, si, dans un projet, une base de données SQLite doit être utilisée, le module LocalStorage permettra de se connecter à ce SGDB et pourrait donc éviter de devoir le faire en C++ ou Python. Cependant, l'interactivité peut aussi utiliser du code C++ (Python avec PyQt, Haskell avec HsQML, etc.), par exemple pour améliorer les performances, tirer parti de ses compétences et habitudes personnelles ou profiter de code existant.

Et vous :
Utilisez-vous Qt Quick et le langage QML pour vos applications ?
Si oui, préférez-vous maximiser le code QML/JS ou bien vous tournez-vous vers d'autres langages comme C++ ou Python pour implémenter la partie logique de votre application ?

Participez au débat, argumentez votre point vue et échangez avec les autres membres de Developpez.com.

Une erreur dans cette actualité ? Signalez-le nous !

Avatar de archqt
Membre confirmé https://www.developpez.com
Le 16/01/2015 à 18:30
Bonsoir,
suivant ce lien : https://www.qtdeveloperdays.com/euro...-judgement-day
il faut éviter de tout mélanger. Personnellement je préfère gérer le modèle en C++ et ensuite utiliser le QML/Javascript pour la vue. Cependant si vous regardez bien certaines démo (ex: module QCamera en C++ ou QML) voire un bête exemple avec un timer vous constatez que le "QML" s’exécute 5 fois plus lent que la version C++.
Par contre ce qui est intéressant est de pouvoir modifier un peu plus rapidement la vue avec le QML. Cependant je suis pour le moment un peu plus à l'aise en C++ pour la partie GUI qu'avec QML. Je trouve que le designer QML est trop en dessous de celui en C++.
Avec QtDesigner (and QtCreator) on gagne beaucoup de temps et cela réduit un peu l'impact gain QML/C++.
Après ce qui manque aussi c'est la réalisation d'une grosse application et son portage en QML. Il y a des exemples certes mais beaucoup de présentations nous laissent sur la faim.
Par contre les animations sons sympas en QML (intérêt pour la vue, et cela évite des héritages en C++).
Bonne soirée
Avatar de Amnell
Rédacteur https://www.developpez.com
Le 16/01/2015 à 20:46
Bonsoir,

Dans ce cas, vous indiquez plutôt une approche Model/View, ce qui correspond plutôt à l'option "Complémenter avec du code C++/Python" si je ne m'abuse.

Note : dans ce post, je parle de C++, mais par rapport au sondage, considérez que les mêmes arguments sont valables pour une utilisation avec Python (même si les performances risquent d'être légèrement moins bonnes que C++).

Pour ma part, j'ai eu l'occasion dans le cadre professionnel de travailler sur des applications Allociné, Dailymotion et Marmiton à l'époque où Intel voulait lancer son app-up pour notebooks Windows 7 et tablettes MeeGo qui n'a semblerait-il d'ailleurs pas fonctionné. C'était à l'époque de Qt Quick 1.0, et les applications ont été développées à 95% en QML/JS, 5% restants étant en C++ pour le viewer et le code spécifique à l'app-up. On se basait sur les webservices des boîtes en question pour récupérer les informations (fiche de film/recette de cuisine/etc.), on parsait ça en JavaScript et intégrait ça dans les modèles QML, ce qui mettait à jour les vues. Et cela fonctionnait bien pour les applications que c'était. La seule partie moche du projet était le player vidéo : on avait fini par y aller salement en passant par un player Flash intégré dans une WebView QML qu'on contrôlait via des appels à evaluateJavaScript(), vu qu'à l'époque, Qt Multimedia n'en était qu'à ses débuts et que ce n'était pas très stable, et qu'on ne pouvait pas utiliser le player de la lib VLC à cause des contraintes de licences, d'autant plus qu'il y avait bien moins de ressources alors au sujet de la communication QML/C++. Toujours est-il qu'on avait des applications qui ne nécessitaient pas de logique C++ et que QML et JavaScript se suffisaient à eux-même, sans aucun problème de fluidité ou quoi que ce soit, et que le développement était très rapide pour des applications esthétiques (design personnalisé en rapport avec le design des applis des boîtes concernées, et ce sans passer mille ans à galérer sur des feuilles de style Qt Widgets) avec de belles animations.

Sur le plan de mes études, dès lors que le langage était libre et qu'il m'était demandé des applications possédant des interfaces graphiques, j'ai toujours choisi d'utiliser QML pour vraiment plonger dedans. Comme gros projet de groupe, on a eu l'occasion de développer une sorte de Skype avec gestion des groupes de conversation (texte, vocal, vidéo et partage d'écran), des contacts, etc. Côté serveur, rien de bien compliqué, du C++ classique avec boost pour faciliter le développement de la partie réseau. Il s'agissait par contre de communication QML/JS/C++ côté client. La partie C++ comportait la socket TCP vers le serveur et les sockets UDP vers les clients, et agissait en tant qu'interface entre le QML/JS et le réseau. À la réception d'un message, le C++ récupère le paquet, l'analyse et en forme une première structure C++ contenant les informations, puis les transforme en JSON et les envoie au QML qui s'en sert pour mettre à jour ses modèles via du JavaScript. À l'inverse, lors d'une action utilisateur (par exemple une demande de connexion), le JavaScript forme un message JSON, transmis au C++ qui l'analyse, le transforme en paquet via les structures C++ et l'envoie sur le réseau. Et cela fonctionnait bien.

À titre personnel, je travaille sur un projet de jeu (un Tactical RPG pour plateformes mobiles où on contrôle des unités tour par tour pour les envoyer affronter d'autres unités) et j'ai fait une erreur : je suis parti de la partie Core pour remonter vers la partie GUI. C'est-à-dire que j'ai codé en C++ des classes Unit, Map, etc., avec toute une API mais qui n'avait aucun moyen de s'intégrer facilement avec du QML que l'on doit plutôt voir de mon point de vue comme étant événementiel. L'intégration avec la partie GUI a été initialement terrible (je partais sur une duplication des données C++ vers les modèles QML par habitude) et, vu la quantité d'informations à stocker, le fait de garder l'interface graphique synchronisée avec la partie Core C++ s'est révélée trop compliquée. J'ai donc tout revisité, changé le code C++ pur en un code plutôt Qt, avec chaque classe dérivant de QObject et possédant des propriétés (comme les propriétés x/y pour les unités, permettant d'avoir leur emplacement sur la carte), permettant une meilleure intégration avec le QML. Moralité de l'histoire ? Et bien ça fait plus de deux ans que je suis sur ce projet (avec des phases de hauts et de bas en terme de temps de travail, laissant des mois pendant lesquels j'avais d'autres préoccupations), et il est loin d'être fini. Cela dit, cela m'aura tout de même permis de constater une chose : coder un projet hybride QML/JS pour la partie graphique/interactions utilisateur et C++ pour la logique nécessite que le C++ soit non pas du code C++ mais du code Qt. De mon point de vue, il y aura toujours besoin au minimum de wrappers pour se placer par-dessus un code C++ pur, parce que ce genre de code non événementiel (n'indiquant pas au minimum par des callbacks lorsqu'une valeur change) est non exploitable avec du QML. Et quitte à partir sur des wrappers longs à développer qui ralentiront le process de développement, je préconise carrément de coder directement du code non générique événementiel (via les signaux/slots/propriétés) axé vers Qt.

Jusque là, j'ai pu présenter plusieurs projets distincts utilisant soit QML/JS seul, soit QML/JS combiné plus ou moins efficacement à C++. Une question en rapport avec le sondage se pose : quel est l'impact des performances sur le code QML/JS/C++ ? À quel point est-ce intéressant de travailler avec une logique en C++ ?

Conceptuellement, l'aspect orienté objet de C++ me semble plus intuitif que l'OO de JavaScript, ce qui fait que je vais préférer coder ma logique en C++ plutôt qu'en JavaScript. Sauf que vu les ennuis, par moment, je me demande s'il ne vaut pas mieux faire ses classes en JavaScript et interfacer ça simplement avec les modèles QML. L'intérêt premier d'avoir le C++ à côté du QML/JS est de se forcer à faire une découpe Model/View propre. Et selon les projets, on peut clairement s'en passer, ce qui engendre en général un réel gain de temps (les applications Qt Quick 1.0 ont été développées relativement rapidement et efficacement et y intègrent bien des animations). Par contre, on ne pourra pas m'enlever de la tête que C++ est indispensable pour étendre QML quand celui-ci s'avère insuffisant. Dans le cadre d'une appli qui ferait toutes les 30ms un affichage de données de caméra, utilisez du C++ pour le timer comme pour le composant d'affichage, n'allez surtout pas utiliser un Canvas et des draws pixel par pixel en JavaScript dessus si vous ne voulez pas que les performances en soient sévèrement dégradées. Mais rien n'empêche d'utiliser C++ pour étendre QML de sorte d'utiliser ces classes C++ dans le QML.

Bref, j'en conclus de mes expériences que QML/JS est viable et sans doute bien plus performant que bien des applications utilisant HTML5/CSS3/JS embarquées dans un WebKit. J'en conclus également que dans nombre de cas où les performances nécessitent d'être minutieux, C++ est à préférer. Et rien n'empêche d'étendre par du C++ QML pour ses propres besoins et de coder la logique en JavaScript derrière pour mêler interactions utilisateur et fonctionnement de l'application elle-même. En gros, c'est très situationnel de mon point de vue, mais pas moins important : une erreur de conception mène a de sales conséquences.

Je suis très intéressé par tous les arguments que vous, lecteurs, pouvez ajouter, étant donné que j'ai beaucoup de mal à trancher et que vous avez peut-être des expériences/tests effectués à partager.

Bonne journée,
Louis
Avatar de Jiyuu
Rédacteur/Modérateur https://www.developpez.com
Le 16/01/2015 à 22:13


Tout d'abord, merci pour vos contributions.

Et bien le coté "performance du code" n'aura pas mis longtemps à venir .

Pour ma part, actuellement codeur amateur autodidacte programmant en Python depuis quelques années, la découverte de QML a été l'occasion de faire de belles GUI, rapidement et offrant beaucoup de possibilités. Un des traits caractéristiques de Python est de pouvoir faire beaucoup de choses (plus ou moins performantes d'un point de vue exécution du code certes) simplement. Selon moi, cela colle pille poil avec la philosophie QML et tant mieux.
Ce qui me plaît beaucoup avec ce langage c'est ça simplicité.
Je rebondis d'ailleurs sur la remarque d'archqt
Je trouve que le designer QML est trop en dessous de celui en C++
C'est pas qu'il est en dessous … c'est juste que c'est une grosse bouse … Heureusement, QML est tellement simple qu'il est plus rapide et plus simple de coder à la main que d'utiliser cette daube.
Franchement, Digia aurait mieux fait de mieux gérer les fichiers Python que de travailler sur ce designer. Mais c'est mon avis, rien que mon avis.

Plus je code en QML, plus je me rends compte que beaucoup de chose peuvent être directement gérées par ce langage, d'autant que je me suis dernièrement intéressé d'un peu plus prêt à JavaScript.

Il faut garder en tête que je suis un 100*% autodidacte et j'ai beaucoup de mal aujourd'hui à m'investir dans C++. Je sais que ce langage est très répandu et que si je souhaite mené à bien mes projets perso-professionnels, il me faudra passer par là.

Cette possibilité de faire un maximum de chose en QML et donc de minimiser le code Python, est pour moi une grande chance.
En effet, en procédant ainsi j'ai la possibilité de travailler sur mes projets, les rendre un maximum fonctionnels et les associés à Python pour les parties indispensables.
En tant qu'autodidacte, cela me laisse alors la possibilité de comparer mon code Python avec ce que j'aurai du faire en C++, mais pas trop non plus. Associé à la lecture d'un ou deux bons tuto sur les bases de C++ et je devrais arriver à m'intéresser à C++

Pour finir, un code QML/JavaScript est peut-être moins rapide que du C++ mais il semblerait être plus rapide que du code Python.

En gros, en maximisant le code QML je peux :
  • faire de belles GUI rapidement et facilement ;
  • gagner probablement en vitesse d'exécution ;
  • favoriser une éventuelle migration d'une appli Python/QML vers C++/QML.


Voilà pour un premier jet
Avatar de Cyborg
Membre du Club https://www.developpez.com
Le 19/01/2015 à 10:01
De mon côté, je travaille (professionnellement) avec 2 types de personnes:
- ceux qui bossent sur de l'embarqué et pour qui chaque Mo de RAM CPU/GPU est important et ne doit pas être gaspillé;
- ceux qui bossent sur le design des graphismes mais qui ne s'y connaissent pas du tout en programmation.

Eh bien je pense que ce sont les 2 extrêmes des solutions techniques à choisir:
- D'un côté, ça pousse pour avoir du C++/QML/JS ... mais en laissant un maximum de choses dans le C++;
- De l'autre, ça pousse pour avoir un maximum de QML/JS pour avoir le loisir de faire ce qu'on veut.

Je tiens à préciser que ces designers sont en train de migrer de Photoshop vers Qt Creator pour la réalisation des graphismes.
Et si j'ai bien suivi, le développement de Qt Creator par Digia va dans ce sens : fournir aux designers un outil de création d'interface graphique permettant ensuite une intégration simplifiée sur des plateformes aussi diverses que variées.

La seule question que je me pose est la performance du JS.
Je sais qu'il ait possible de créer un binaire, si j'ai bien compris, à partir du qml afin d'en optimiser les performances.
Ce que je ne sais pas, c'est si le JS est lu/exécuté à la volée, ou s'il est aussi compilé dans le binaire, permettant ainsi des performances qui devraient être encore plus proche du C++...
Avatar de Amnell
Rédacteur https://www.developpez.com
Le 20/01/2015 à 20:13
Bonsoir,

Par rapport au JavaScript, il est bel et bien exécuté à la volée tout comme le QML, même s'il y a tout un moteur qui travaille autour du QML à l'exécution. L'intérêt d'embarquer les fichiers dans l'exe, de mon point de vue, c'est surtout pour éviter de lire sur le disque dur et de perdre des performances à cause de ça (sur quelques plateformes mobiles, ça peut être significatif).

Cela dit, en terme de performances, j'ai fait des tests et sur du JavaScript simple avec création d'objets et insertion dans des listes, c'est quand même clairement mauvais (autour de dix fois plus lent que le même code exécuté via QtScript directement). Selon la documentation, le JavaScript fourni par QML est optimisé sur la communication avec le QML lui-même, c'est-à-dire la modification de propriétés, de ListModel et autres. S'il est plus lent que ce que fournit QtScript, ce serait principalement parce que QML est typé tandis que JavaScript ne l'est pas et que cela nécessite des allocations de mémoire supplémentaires pour palier à cela, probablement pour faire de l'inférence de type.

Citation Envoyé par Cyborg
Eh bien je pense que ce sont les 2 extrêmes des solutions techniques à choisir:
- D'un côté, ça pousse pour avoir du C++/QML/JS ... mais en laissant un maximum de choses dans le C++;
- De l'autre, ça pousse pour avoir un maximum de QML/JS pour avoir le loisir de faire ce qu'on veut.
Oui, c'est exactement ça ! L'avantage de QML/JS est bien d'avoir le loisir de faire ce qu'on veut, alors que côté C++/QML/JS, on va avoir tendance à se forcer à faire du Model/View, ce qui est compliqué dans pas mal de cas. De là, on va avoir des temps de projet qui vont changer : via du QML/JS simple, on aura un résultat très rapide tandis qu'avec du C++, ça prend de mon point de vue bien plus de temps. Que choisir ? Aucune idée.

Si ça vous intéresse, je peux expliciter mes tests JavaScript vs QtScript avec du code et des chiffres concrets.

Bonne soirée,
Louis
Avatar de Jiyuu
Rédacteur/Modérateur https://www.developpez.com
Le 20/01/2015 à 21:03
Citation Envoyé par Amnell Voir le message
Oui, c'est exactement ça ! L'avantage de QML/JS est bien d'avoir le loisir de faire ce qu'on veut, alors que côté C++/QML/JS, on va avoir tendance à se forcer à faire du Model/View, ce qui est compliqué dans pas mal de cas. De là, on va avoir des temps de projet qui vont changer : via du QML/JS simple, on aura un résultat très rapide tandis qu'avec du C++, ça prend de mon point de vue bien plus de temps. Que choisir ? Aucune idée.
Peut-être qu'alors la bonne réponse à cette question est : cela dépend de la maturité du programme.

Je me souviens d'un sujet concernant l'utilisation de Python dans le monde professionnel (notamment face à C++). Plusieurs personnes avaient indiqué utiliser Python essentiellement dans le but de faire une maquette du programme destinée à être présentée à des clients par exemple, pour ensuite, une fois le projet validé, travailler en C++.
La raison avancée était de passer peu de temps sur cette dite maquette (un programme Python étant plus rapide à faire qu'un C++) pour ensuite pour maximiser les performances du code en repassant en C++.

Inconvénient majeur : on a beau me dire ce que l'on veut : on fait deux fois 100% du boulot (ou presque ... la partie réflexion étant déjà bien avancée).

Pour revenir à notre sujet, l'intérêt pourrait alors être de créer un maximum de chose en QML dans un premier temps afin d'avoir un code fonctionnel rapidement, puis, petit à petit, venir travailler sur la logique en C++ afin d'optimiser les performances du code.
L'avantage est que l'on a pas à retoucher à la partie graphique et à la partie logique qui fonctionne convenablement, on peut ainsi se concentrer un maximum sur les points noirs.

Évidemment, cette logique dépend encore de la performance de chaque langage, d'où :

Citation Envoyé par Amnell Voir le message

Si ça vous intéresse, je peux expliciter mes tests JavaScript vs QtScript avec du code et des chiffres concrets.
Ça c'est pas une mauvaise idée...
Comme je te l'avais dit, j'ai commencé moi aussi quelques tests d'exécution entre du C++, C++/QML, Python, Python/QML, et ceux-ci laissaient apparaître (entre autre) qu'une fonction exécutée en QML était plus rapide qu'une fonction exécutée en Python, ce qui, dans mon cas,n était le point que je voulais mettre en avant ou non. Mais mes tests sont sûrement bien moins pertinents que les tiens.

L'idée pourrait-être de repartir sur ce que tu as fais et de (tenter de) transposer ça en Python et en QML, histoire de s'amuser
Avatar de Amnell
Rédacteur https://www.developpez.com
Le 21/01/2015 à 1:21
Bonsoir,

Je ne sais pas trop si je m'écarte du sujet en postant ça, mais vu que ça reste dans le contexte d'un comparatif code QML/JS vs code QML/JS/C++ (ou Python), j'estime que ça reste pertinent.

Suite à la demande, j'ai remis au propre mes tests (basés sur les sources fournies dans cet article) et je les ai changés pour prendre en compte non pas seulement les appels de méthodes mais aussi le coût des instanciations. Initialement, l'intérêt était de comparer le coût de l'instanciation avec QML de classes JavaScript dont les méthodes sont déclarées via "prototype" ou directement dans la classe. J'y compare donc du côté JavaScript le mode sans "prototype" :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
var ClasseA = function(a, b)
{
    this.a = a;
    this.b = b;

    this.somme = function()
    {
        return this.a + this.b;
    };

    // ...
};
Avec le mode "prototype", supposé être bien plus optimisé :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
var ClasseB = function(a, b)
{
    this.a = a;
    this.b = b;
};

ClasseB.prototype.somme = function()
{
    return this.a + this.b;
};

// ...
Côté C++, j'ai fait une classe qui possède les mêmes méthodes que ses homologues JavaScript. Le test est le suivant :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
for (var i = 0; i < iter_nbr; i++)
{
    var myclass = new ClasseA(3, 2);
    myclass.somme();
    myclass.diff();
    myclass.multiplie();
    myclass.divide();
    myclass.test();
}
Et voici les résultats chez moi pour 2 000 000 itérations, avec Qt 5.4, MinGW 4.9.1 32bits, le tout compilé en release :



En debug, ça fait tout de suite bien plus peur, même si ça ne sert probablement à rien vu que les programmes se diffusent en théorie compilés en release :



Avec une seule instanciation, le coût des appels JavaScript est identique, ce n'est intéressant que sur plusieurs instanciations (pour info, j'ai un résultat de 2040 msecs sur les mêmes tests JS mais avec une unique instance en release). Après, j'imagine qu'il faut en déduire qu'à partir du moment où on n'instancie pas trop ou bien qu'on ne s'amuse pas à faire des millions de calculs comme là, le JavaScript fourni par QML reste tout de même correct.

Les tests peuvent être exécutés sur vos plateformes depuis le zip mis en pièce-jointe.

En théorie, le code est assez simple donc si tu arrives à transposer ça en Python, ça pourrait être sympa de voir le résultat (il faudra sans doute afficher en parallèle les résultats avec un Qt version C++ pour pas fausser les résultats par différence de matériel).

Bonne soirée,
Louis
Avatar de Jiyuu
Rédacteur/Modérateur https://www.developpez.com
Le 22/01/2015 à 0:35


Je viens de taper quelques lignes. Voici ce que cela donne en mode debug pour C++ (moi en release j'ai sensiblement la même chose !!! c'est normal docteur ?)


Pour le test nommé QML, j'ai en fait créé un Item avec les différentes fonctions. Par contre j'ai eu un petit souci pour appeler une fonction d'une fonction.... est-ce que ça peut jouer ? Si ce que j'ai fait est correct, c'est une bonne chose, même si C++ explose réellement tout ... c'est déprimant

Je joins le zip avec ce que j'ai fait.

Demain ou vendredi je compléterai avec un code Cython.

Bonne soirée.

J
Avatar de Amnell
Rédacteur https://www.developpez.com
Le 22/01/2015 à 11:48
Bonjour,

Pour QML, on ne peut pas créer de fonction prenant une lettre majuscule donc on ne peut pas créer de classe, ce qui limite le test à ce que tu as fait. Par contre, pour le test Python, je ne pensais pas que ce ça prendrait autant de temps. Par contre, pour que ça colle avec les classes JavaScript, il faudrait distinguer la classe ClasseC contenant les fonctions sommes/etc. en Python de la classe Testeur pour bien pouvoir instancier la ClasseC dans la boucle de test et voir également le coût des instanciations pour comparer de manière concrète avec JavaScript.

Bonne journée,
Louis
Responsable bénévole de la rubrique Qt : Thibaut Cuvelier -

Partenaire : Hébergement Web