Pourquoi Qt est cool ?

J’ai découvert Qt en tant que développeur il y a un peu plus d’un an et je voudrais partager avec vous les meilleurs moments lorsqu’on le découvre, un peu comme si je voulais vous donner envie d’essayer vous aussi…

1. Les signaux et les slots: tisser les appels de méthode dynamiquement à l’exécution

Les objets peuvent émettre des signaux qui ressemblent furieusement à des appels de méthode, mais dont on ne connaît pas le destinataire. Et les objets peuvent également porter des slots qui sont des méthodes particulières qui peuvent être connectées à des signaux. Cette connexion peut se faire soit à la souris dans l’IDE si les objets concernés sont des widgets graphiques, soit programmatiquement avec une méthode qui s’appelle connect. La cardinalité des connexions est bien sûr n-m, c’est-à-dire qu’un même signal peut être connecté un nombre quelconque de slots et qu’un slot peut-être connecté à un nombre quelconque de signaux.

C’est évidemment très pratique en matière d’interface graphique (un bouton émet le signal clicked que l’on peut connecter à ce qu’on veut, etc.) mais c’est au moins aussi pratique pour des tas d’objets non visuels. Par exemple Qt fournit une classe qui s’appelle QNetworkAccessManager et qui permet en quelques lignes de code de faire des requêtes HTTP de façon asynchrone et d’être rappelé par un signal lorsque la requête est finie ou pour donner un pourcentage d’avancement de l’upload ou du download qui s’en suit.

C’est également très agréable pour gérer la communication entre plusieurs threads (un thread émet le signal, mais c’est un autre qui exécute le slot) ou pour simuler un fonctionnement multithread avec le seul thread exécutant la boucle d’événements principale: chaque slot est éxécuté à son tour, car l’appel de slot asynchrone est un événement. C’est de loin le modèle de communication le plus simple que je connaisse qui permette à la fois de faire des appels synchrones, et des communications multithread fonctionnant aussi bien avec des threads préemptifs et non préemptifs.

Pour en savoir plus c’est ici: http://doc.qt.nokia.com/latest/signalsandslots.html et éventuellement là: http://doc.qt.nokia.com/latest/qnetworkaccessmanager.html

2. La réflexivité et le Méta-objet

On vient de parler des signaux et des slots, évidemment ils ne sont pas mus par magie et bien sûr vous vous demandiez en me lisant: comment donc les connexions peuvent-elles être dynamiques à l’exécution alors que C++ est un langage compilé?

Point de sorcellerie. Qt arrive avec un modèle dit de méta-objet qui est proche de la réflexivité Java et stocke sous forme de chaîne de caractères les signatures des méthodes appelables dynamiquement (notamment les slots), pour les objets identifiés comme pouvant porter de telles méthodes (toutes les classes héritant de QObject). Et cette couche basse est directement utilisable: même sans signaux et sans slots il est possible d’appeler une méthode à partir de son nom dans une chaîne de caractère. Pour passer un callback c’est très plaisant. Et bien sûr l’appel peut-être asynchrone (cf. mon exposé précédent sur la communication entre threads).

Pour en savoir plus, le point de départ est ici: http://doc.qt.nokia.com/latest/qmetaobject.html#invokeMethod

3. Une bibliothèque de classes riche et très agréable

Là on est à la limite de l’esthétique, je le reconnais, mais les classes Qt sont extrêmement agréable à utiliser. Beaucoup moins théoriquement belles que les classes Java par exemple mais beaucoup plus pragmatiques. Un seul exemple:

Les collections sont un vrai plaisir à utiliser (notamment grâce à l’implicit sharing, voir point suivant), mais un peu déroutante au début avec par exemple la QList dont le temps d’accès en indexé est constant, juste parce qu’en vrai ce n’est pas une liste chaînée…

Plus ici: http://doc.qt.nokia.com/latest/containers.html#algorithmic-complexity

4. L’implicit sharing ou la copie gratuite d’objets

Un nombre important de classes Qt pratiquent l’implicit sharing, qui n’a rien à voir avec l’adultère ou les parties fines, mais fait que deux copies différentes d’un objet comme une chaîne de caractère (QString) ou une image bitmap (QImage) n’occuperont quasiment qu’une seule fois la place mémoire et se copieront quasi instantanément, tant qu’aucune des deux n’est modifiée. À la première modification en revanche il y a allocation mémoire et copie, c’est une sorte de copy-on-write.

Ça a l’air d’un gadget, mais cela simplifie diablement la gestion des collections et d’une façon générale le dilemme qui existe en C++ entre le passage d’objet par valeur ou par référence: les objets qui pratiquent l’implicit sharing peuvent être passés par valeur pour éviter que l’appelé puisse modifier l’original (comme ce serait le cas s’ils étaient passés par référence) sans avoir à supporter l’essentiel du coût mémoire et CPU de la copie.

Plus d’info ici: http://doc.qt.nokia.com/latest/implicit-sharing.html

5. Qt Creator: un IDE de rêve pour le C++, avec toutes les extensions apportées par Qt

L’environnement de travail de Qt Creator est, avec mes goûts et mes exigences à moi, quasi équivalent à ce qu’est Eclipse au monde Java (je ne parle pas des modules C++ pour Eclipse qui sont très en deçà de leurs pendant Java), en un peu moins lourd (ne nourrissez pas le troll je ne suis presque pas en train de dire que C++ est moins lourd que Java).

Évidemment il gère toutes les spécificités apportées par Qt au C++: complétion automatique des noms de signaux et slots dans les macros Qt, support de l’instruction foreach pour itérer sur les collections, etc.

Plus d’info et une vidéo de démonstration ici: http://qt.nokia.com/products/developer-tools/

6. QGraphicsView: un framework de dessin 2D multi-vues clefs en main

Je ne parlerai qu’un tout petit bout de la bibliothèque de widgets graphiques: le framework de dessin 2D qui tourne autour de la QGraphicsView.

Version courte: on peut mettre n’importe quel objet 2D (un item) dans une scene et visualiser cette scene dans un nombre quelconque de views. On peut avoir plusieurs scenes mais ce sont des mondes séparés sans aucun partage d’items. Les items de base sont des rectangles, ellipses, bitmaps, etc. mais il est très facile de faire son propre item. Le fonctionnement de base de la view permet à l’utilisateur d’interagir en sélectionnant déplaçant, etc. les items sans aucune ligne de code, à tel point que l’un des exemples livrés avec Qt est un Visio-like (ou du moins un Dia-like) de seulement quelques centaines de lignes de code.

Il paraît aussi que le modèle scale à plusieurs dizaines de milliers d’items. Je n’ai pas essayé, mais avec les précautions prises (stocker les items dans un BTree…) et les références commerciales (Walt Disney, industrie aéronautique…) je veux bien le croire. En tout cas pour quelques dizaines d’items c’est le pied.

Plus d’info ici: http://doc.qt.nokia.com/latest/graphicsview.html

7. Les deux évidences: un toolkit GUI riche et une portabilité exemplaire

Je le garde pour la fin car ce sont les deux points forts de Qt, tellement évidents qu’il n’en sont pas amusants: le toolkit graphique de base est très riche (je veux dire en dehors de QGraphicsViews dont je viens de parler mais qui n’est qu’un détail) et la portabilité sur Windows, Linux, MacOSX, et les systèmes embarqués Nokia est exemplaire. Il paraît qu’on peut aussi l’utiliser sur d’autres plateformes (Unix propriétaires, Android, etc.) mais je ne crois pas qu’il soit possible d’acheter du support pour cela, donc c’est un peu l’aventure, et je ne l’ai pas tentée.

8. Installation en deux clics

Sur la page d’accueil de Qt (http://qt.nokia.com/) il y a un gros bouton download, ensuite c’est setup.exe sous Windows et équivalents sous Linux et Mac OS X. Et sinon n’importe quelle distribution Linux décente package Qt Creator et ses dépendances.

Donc vous n’avez aucune excuse pour continuer à lire ce billet plutôt que d’aller installer l’environnement de développement Qt.

9. Les sujets que-je-n-aborderai-pas-faute-de-place-pourtant-j-en-avais-envie

En vrac, si vous n’êtes pas encore convaincus: le système de traduction est nickel pour permettre de séparer le cycle de développement du cycle de traduction; tout est disponible entre triple licence GPL, LGPL ou commerciale; c’est made in Europe; on peut utiliser Qt avec d’autres langage que C++ (il existe des bindings Python et Java, notamment) mais moi j’aime le C++ (au moins avec Qt); il y a des classes de bases très décentes pour gérer facilement des accès aux bases de données SQL et le multithread; le modèle model-view des widgets pour collections (QListView, QTreeView, etc.) est bien pratique une fois qu’on a fait l’effort de le comprendre et les versions simplifiées pour développeur pressés des mêmes widgets évitent le nœud de neurones.

2 réponses à to “Pourquoi Qt est cool ?”

  • Tout d’abord un grand merci à Mr GreG pour sa contribution qui, je l’espère, n’est que la première sur LeMondeDuDev (techniquement, cette phrase est con, mais vous avez compris ce que je voulais dire).

    Ensuite, je crois que ce que je retiens de cet article, c’est : Nokia.

    Plus sérieusement, pour tous ceux qui, comme moi, cherchent constamment à améliorer leur expertise en matière de programmation tout en ne se fatigant pas trop à cela, il semble que Qt facilite pas mal la vie, tout en ne restreignant pas pour autant les possibilités de développement ce qui est, en soi, une réussite.

    Pour les habitués de l’Objective-C, il semble que Qt est une version plus générique est plus extensible que la suite Xcode qui fait un peu tout ce dont cet article parle, mais qui a le mauvais goût (ou pas) de ne le faire que sur Mac et pour Mac.

  • GreG:

    @Bruce: Tout les gens qui m’ont parlé d’Xcode m’on donné (comme toi) envie de regarder et la sensation que ça doit être bien plaisant à utiliser, mais tu l’as deviné, la portabilité limitée est ce qui fait que j’ai préféré me plonger dans Qt.