Vous êtes sur la page 1sur 66

Universit de Technologie de Compigne HI CORPORATION

Dpartement Gnie Informatique Shinjuku, Tokyo, Japon

Rapport de stage de n dtude TN10


Fvrier 2017 - Juillet 2017

Conception et Dveloppement dun outil daide au


dbug dune application graphique embarque

Mohammed Aladin TALEB


GI05 Systme Temps Rel et Informatique Enfouie

Suiveur UTC Suiveur HI CORPORATION


Stphane BONNET Guillaume GEORGE
2

1 Remerciements
Ce stage au Japon naurait pu tre possible sans lintervention de certaines personnes que
je souhaiterais citer ici. Un grand merci Stphane Bonnet et Anne Gunand, mes suiveurs de
stage respectivement en ingnieurie informatique et en design dexprience utilisateur, ainsi qu
ladministration de lUTC pour leur attention porte ainsi que leurs conseils donns avant, pendant
et aprs le stage. Je remercie galement les managers et employs de HI Corporation, notamment
Maemoto-san, Maruyama-San et Terada-san, qui ont eu confiance en mes comptences et qui mont
accueilli au sein de leur quipe.
Je tiens remercier de manire trs particulire Guillaume George qui, en plus davoir t mon
tuteur de stage, fut un excellent partenaire de travail, un indispensable interprte et un trs bon
guide. Il nest pas simple de vivre, travailler et voluer au sein un pays dont on ne comprend pas la
culture et encore moins la langue ; et cette exprience aurait probablement pris une tournure plus
ngative sans son support constant.
En outre, ces six mois au Japon ne peuvent tre rsums cette seule exprience professionnelle.
Chaque moment fut en effet loccasion de dcouvrir cette culture et den apprendre plus sur mes
rapports avec celle-ci. Je transmets toute ma gratitude mes nouveaux amis - Thai Tam, Hitomi,
Marie, ... - qui mont permis dentrevoir les subtilits de la vie japonaise.
Ces remerciements ne seraient pas complets si je ne citais pas mes parents, mon petit frre
ainsi que mes amis proches qui mont soutenu au quotidien et qui ont su trouver les mots pour me
redonner le sourire dans les moments o jen avais le plus besoin.
2 Objectifs du stage et de ce rapport
Tous les tudiants en cycle dingnieur de lUniversit de Technologie de Compigne (UTC)
doivent rejoindre une entreprise ou un laboratoire pendant leur dernier semestre afin dy effectuer
leur stage de fin dtude dune dure denviron cinq mois et demi. Cette exprience, qui se doit
dtre en concordance avec son choix de cursus, donne loccasion au futur ingnieur de contribuer
un projet soulevant de vritables enjeux et constitue en ce sens une ultime passerelle vers le milieu
professionnel.
Etudiant en ingnieurie informatique, jai plus particulirement intgr la filire Systme
Temps-Rel et Informatique Enfouie afin de me spcialiser dans le domaine des systmes physiques
que les utilisateurs peuvent manipuler de manire plus fine et motionnelle que le simple combo
clavier/souris. En outre, je crois en une informatique altruiste qui peut profondment amliorer et
simplifier la vie de ses utilisateurs, quils soient dveloppeurs ou simples tres vivants, du moment
quon prenne suffisamment le temps de les considrer tout au long dun projet. Cest la raison pour
laquelle je suis en parallle lUTC un master en design dexprience utilisateur (abrg UXD).
Ce cursus ma permis de comprendre certains des tenants et des aboutissants des mthodes de
design centres utilisateur et je suis convaincu quune application de celles-ci au sein dun projet
informatique permet daboutir des concepts innovants et rpondant pertinamment aux besoins
exprims ou non de lutilisateur final.
Ce stage tait galement loccasion de valider mon projet de fin dtude de ce master et se devait
donc de comporter une phase danalyse et de design non-ngligeable. Il nest malheureusement pas
simple de trouver une entreprise comprenant lintrt de lUX, la faute une discipline encore trop
jeune, trs souvent simplifie et confondue avec dautres pans du monde du design, et ncessitant
une organisation de projet adquate. Les grandes entreprises ou les socits traditionnelles ont ainsi
pour habitude dignorer compltement ce domaine ou alors de sparer les quipes de design de
celles de dveloppement. Jai heureusement trouv une entreprise qui a bien souhait maccueillir
afin que je puisse appliquer mes comptences dans le domaine du design et de lingnieurie
informatique au sein dun mme projet.
Ce rapport commencera par prsenter cette entreprise ainsi que les grandes lignes du projet
sur lequel jai travaill pendant toute la dure de mon stage, de fvrier 2017 mi-juillet 2017..
Il rentrera ensuite dans les dtails de conception et dimplmentation de celui-ci. Un deuxime
rapport ddi au jury du master se concentrera quant lui sur les phases danalyse et de design du
concept. Bien que lentreprise a accept que je dvoile la plupart de mon travail, elle a souhait
garder confidentielle le code source crit, jai toutefois fait de mon mieux pour illustrer mes propos
avec quelques lignes de code assez gnriques.
La langue principale de mon stage fut langlais, cependant ce rapport a t crit en franais
afin de respecter les consignes de lUTC. Il nhsitera cependant pas utiliser les terminologies
anglaises pour dsigner certains concepts cls - ne vous attendez donc pas lire le terme "cadriciel".
Je vous souhaite une bonne lecture.
Table des matires

1 Remerciements 2
2 Objectifs du stage et de ce rapport 3

1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1 Prsentation de lentreprise HI Corporation 7
1.1 Historique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2 Organisation de lentreprise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2 Prsentation du produit UI Conductor 11
2.1 Problmatique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2 Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3 Quelques exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.4 Concurrence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3 Prsentation du projet Debugger 14

2 Prparation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

3 Communication entre deux machines . . . . . . . . . . . . . . . . . . . . . . . . . 19


1 Objectifs 19
1.1 Contraintes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2 Recherches 20
2.1 Choix de la technologie de communication . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.2 Choix du protocole de transmission . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.3 Analyse de lAPI Socket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.4 Architecture rseau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3 Architecture 25
3.1 Refonte de lAPI Socket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.2 Pipeline denvoie et de reception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.3 Fonctionnement des Workers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4 Dveloppement 26
4.1 Choix du langage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
4.2 Programmation Orient Object en C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.3 API Publique vs. Prive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.4 Abstraction de lOS et de la cible . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5 Implmentation de lAPI Socket 31
5.1 Vrification des erreurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
6 Conclusion 33

4 Intgration au sein de UIC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35


1 Objectifs 35
2 Recherches 35
3 Architecture 36
4 Dveloppement 38
4.1 Programmation gnrique en C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5 Preuve de concept 40
6 Conclusion 41

5 Analyse des usages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

6 Premier prototype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1 Introduction 45
2 Choix des technologies 45
2.1 Contraintes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
2.2 Recherches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
3 Dveloppement 50
4 Tests Utilisateurs 50

7 Second prototype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
1 Introduction 51
2 Librairie dAnalyse 51
2.1 Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
2.2 Proposition dimplmentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
2.3 Electron et DLL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3 Gestionnaire derreur 55
3.1 Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.2 Dveloppement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
4 Interface Graphique 57
4.1 Dveloppement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.2 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

8 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Introduction

1 Prsentation de lentreprise HI Corporation


HI Corporation, souvent dsigne par le diminutif HI Corp, est une entreprise japonaise
fonde le 17 avril 1989 qui compte 57 employs au mois davril 2017. Depuis prs de 40 ans, HI
Corporation a comme principal corps de mtier la conception, le dveloppement et la vente de
solutions de dveloppement pour ordinateurs embarqus.

http://www.hicorp.co.jp (Japonais/Anglais)

Un ordinateur embarqu est une machine spcialement conue pour sinscrire au sein dun
systme lectronique et mcanique afin que la machine puisse interragir avec le milieu exterieur
laide de capteurs et dactionneurs. Les applications excutes sur ce type dordinateur ont pour
particularit de fonctionner sous diffrentes contraintes :
Des contraintes de performancs : les ordinateurs embarqus tant dans beaucoup de cas des
systmes informatiques dont le matriel est spcialis pour un certain type de tche, leurs
capacits en termes de puissance de calcul et de mmoire sont gnralement limites ;
Des contraintes de sret : selon le degr de criticit du domaine, les applications et ordina-
teurs embarqus peuvent tre amens inclure un certain nombre de mcanismes minimisant
les risques de bloquage lors de leur excution.
Le systme informatique pilotant une imprimante, celui contrlant le flux de carburant dans un
moteur de voiture, ou encore dans une moindre mesure, lordinateur inclus dans un smartphone,
8 Chapitre 1. Introduction

sont tous des appareils embarqus dont les applications excutes doivent respecter les contraintes
cites.

1.1 Historique
Lentreprise sest notamment fait connatre en 2001 pour le projet MascotCapsule, lun des
premiers moteurs de rendu 3D temps-rel pour appareils mobiles, quelle concevait depuis les
annes 90. En 2010, plus de 600 millions dappareils dans le monde utilisaient cette solution pour
afficher du contenu 3D.

Capture dcran du jeu Resident Evil 4 dvelopp pour plateformes iOS en 2009 laide
du moteur MascotCapsule eruption de HI Corporation.
http://www.hicorp.co.jp/products_v3/ (Japonais)

Cependant en 2007, face larrive imminente des gants Apple et Google sur le march du
mobile, lentreprise dcide de se retirer de ce secteur pour se concentrer sur dautres portions du
march des outils de dveloppement pour appareils embarqus. Cest ainsi quen 2009, HI Corp.
sort la premire version de Higlyph, son moteur de rendu de police de charactre, notamment
exploit par la console PS VITA de Sony. En 2016, on estime que 40 millions dappareils exploitent
ce produit.

Quelques unes des fonctionnalits permises par le moteur Higlyph.


http://www.hicorp.co.jp/en/products_higlyph/

Lanne 2012 marque la cration de lentit ArtSpark pour regrouper HI Corporation ainsi que
Celsys, une entreprise fonde en 2011 spcialise dans les logiciels de dessin. La mme anne
dbute le devloppement de UI Conductor, moteur dinterface graphique sur lequel sest port mon
sujet de stage. La section suivante est spcifiquement ddie sa prsentation.
1 Prsentation de lentreprise HI Corporation 9

Lentreprise dfend depuis maintenant quelques annes lide que la voiture devrait tre une
entit motionnelle avec qui le conducteur peut communiquer - selon les termes de HI Corp., la
voiture devrait tre un "pote". Des designers graphique et dexprience de lentreprise travaillent sur
linterface de la voiture de demain en utilisant notamment UI Conductor comme moyen de donner
vie leurs ides. Pour renforcer cette volont de simposer sur le march des solutions dinterface
graphique pour lautomobile, HI Corporation a rejoint en 2016 le projet Automotive Grade Linux
aux cts de Mercedez-Bend, Toyota ou encore Nissan. Ce projet open-source et collaboratif vise
crer le principal systme dexploitation pour applications automobiles dinfotainment.

https://www.automotivelinux.org

HI Corporation dveloppe actuellement principalement le moteur Higlyph, la solution UI


Conductor mais galement les produits Affinity et VI Transfer conus pour monitorer les capteurs
de la voiture afin de proposer des interfaces graphiques et des services contextuels.
En 2016, les 1 429 millions de Yen (environ 10 millions deuros) net encaisss par lentreprise
proviennent dun modle bas sur de la vente de service ainsi que sur des royalties. Les clients
payent tout dabord les logiciels puis doivent verser lentreprise un montant fixe par appareil
produit contenant une des solutions fournies par HI Corporation.

1.2 Organisation de lentreprise


Bien que HI Corporation ne compte quune soixantaine demploys, lorganisation y est plutt
pyramidale limage dautres entreprises traditionnelles japonaises, ce qui frle par moment le
ridicule. Cette partie tentera de dresser un portrait simplifi de cette organisation.
Lentreprise dont le sige social est bas Shinjuku (Tokyo) est compose de 9 dpartements,
chacun dirig par un chef de dpartement ainsi quun manager ou un chef de section, ceux-ci
assurent le bon fonctionnement conomique et administratif de leur division respective. Au dessus
deux se trouvent le PDG ainsi que les membres du conseil dadministration chargs de la stratgie
de lentreprise.
Les 9 dpartements sont les suivants :
Dpartement de la stratgie commerciale donnant une ligne directrice toute lentreprise ;
Dpartement commercial dont les employs ont pour charge de dmarcher de nouveaux
clients au Japon et linternationnal ;
Dpartement CX/IP qui dveloppe principalement des projets portant sur le "vhicule dans le
cloud" ;
Dpartement OEM/IP dont les projets sont faits en collaboration avec des fournisseurs de
matriel pour lautomobile ;
10 Chapitre 1. Introduction

Dpartement Interface Homme-Machine (HMI) qui dveloppe les projets lis de prs ou de
loin aux interfaces graphiques, principaux produits de HI Corporation ;
Dpartement des futurs projets qui soccupe de dvelopper des prototypes pour les potentiels
prochains produits de lentreprise ;
Dpartement du support qui rpondent aux problmes des clients. ;
Dpartement du design charg de crer les diffrentes ressources graphiques pour lquipe
commerciale et les quipes de dveloppement ;
Dpartement de la qualit qui sassure du bon fonctionnement des produits ou mises jour
qui sont amens tre mis sur le march.
La plupart des quipes sont composes des employs permanents bass Tokyo ou dans les
seconds locaux situs Sapporo, dans le nord du Japon. Cependant, des employs de Celsys ou
dautres entreprises partenaires, mais galement des interims viennent ponctuellement renforcer les
rangs. Notez que, bien que les japonais comprennent lintrt des stages, le Japon ne reconnait pas
officiellement le statut de stagiaire et il est assez rare que des tudiants viennent renforcer les rangs
des entreprises. Cest ainsi que jai t administrativement considr comme une sorte dinterimaire
durant mes 6 mois de stage.
Jai t accueilli par le dpartement HMI qui contient la plus grosse quipe : 13 ingnieurs
informatique et dveloppeurs - une femme pour douze hommes. Parmi eux, six ont le poste de
manager technique, ce qui leur donne la possibilit de grer un projet si loccasion se prsente
(mais galement de prtendre un meilleur salaire). Ce dpartement est lui-mme plus ou moins
divis en trois quipes : la principale soccupe du moteur dinterface graphique UI Conductor,
une autre sadonne au dveloppement du moteur Higlyph, tandis que la dernire est charge de
dvelopper des projets de dmonstration avec les technologies de lentreprise pour les prsentations
commandites par le dpartement commercial ou celui du support.
2 Prsentation du produit UI Conductor 11

2 Prsentation du produit UI Conductor


2.1 Problmatique
exbeans UI Conductor, aprs rduit par lacronyme UIC, est un environnement de dveloppe-
ment dinterface graphique pour systme embarqu.
Cette solution rpond une problmatique trs frquemment souleve par le processus de
dveloppement dapplications embarques. En effet, il existe de plus en plus dappareils embarqus
conus pour afficher une interface graphique afin dtre en interaction directe avec un utilisateur
quelconque. On peut citer ce titre le milieu de lautomobile : le module de navigation, le systme
multimdia ainsi que les diffrents voyants et compteurs sont autant dapplications embarques
amenes arborer des interfaces graphiques de plus en plus complexes.

Prototype dun tabeau de bord dvelopp par HI Corporation laide de UIC prsent lors
du salon Automotive World 2017.
http://www.hicorp.co.jp/event_automotiveworld2017/ (Japonais)

Cependant, les contraintes que doivent respecter les applications embarques rendent difficiles
leur conception ainsi que leur dveloppement. Cest la raison pour laquelle les designers et dve-
loppeurs dinterface graphique ne peuvent gnralement pas contribuer au dveloppement de ce
type dapplication.
Le workflow habituel est donc constitu dallers-retours entre lquipe de design qui soccupe
de concevoir linterface graphique et lquipe de dveloppement, compose dingnieurs ayant
conscience des limitations des appareils embarqus, qui limplmente. Cette organisation du travail
en ping-pong est assez contraignante. Non seulement les designers et les ingnieurs ont souvent du
mal communiquer, mais cette organisation oblige les designers et les managers attendre que les
dveloppeurs finissent la phase de dveloppement pour entamer des tests dusabilit et itrer sur
linterface graphique.
En outre, une application embarque est toujours adapte et optimise pour un ordinateur
embarqu prcis, quon appellera par la suite une cible ou une plateforme, afin de mieux pouser
ses limitations. Bien que les systmes dexploitation proposent une abstraction du matriel, il est
gnralement ncessaire de fixer larchitecture matrielle et logicielle de la cible avant de commen-
cer le moindre dveloppement. Cest ainsi que la conception et le dveloppement dapplications
embarques traditionnelles se retrouvent extrmement dpendants de la machine ce qui rigidifie,
squentialise et complexifie toute la cration du produit.

2.2 Solution
UIC tente de simplifier et paralleliser ce workflow en proposant un certain nombre doutils
permettant aux diffrents acteurs de contribuer au projet indpendamment les uns des autres. Ceci
se matrialise principalement par une application graphique appele Tact, qui reprend certains
12 Chapitre 1. Introduction

concepts de lenvironnement de dveloppement Unity. Tact est conu pour que les designers
puissent construire linterface sans crire une seule ligne de code. Ce logiciel contient galement
un module de test pour pouvoir simuler le rendu de linterface graphique.

Application cre laide de Tact.

La mme application teste laide du simulateur.

Une fois le projet prt tre test sur un appareil embarqu, Tact gnre un ensemble de
fichiers binaires reprsentant les ressources ainsi que le comportement de lapplication. Une librairie
compile pour une cible donne permet ensuite dimporter et dafficher linterface gnre par loutil.
Cette librairie contient notamment une API haut-niveau cre pour que les dveloppeurs front-end
(appels designers techniques par lentreprise) puissent programmer la logique de lapplication sans
se soucier des contraintes de lappareil embarqu ; ainsi quune API bas-niveau qui elle donne la
possibilit aux dveloppeurs embarqus dadapter et doptimiser lapplication pour quelle puisse
fonctionner au mieux sur la plateforme. Lentreprise a galement dvelopp un plugin sintgrant
au logiciel Adobe Photoshop qui simplifie limportation des ressources graphiques au sein de loutil
Tact.
UIC est capable dafficher simultanment plusieurs crans composs dobjets 2D et 3D. Il
simplifie en outre le dveloppement des interactions, des animations, des transitions entre crans ou
encore des patterns dinterface frquemment utiliss comme les listes dfilantes. Nanmoins, UIC
2 Prsentation du produit UI Conductor 13

nest pas conu pour grer la logique de lapplication, les dveloppeurs ont ainsi tout le loisir de
choisir comment implmenter le comportement de linterface.

Une application embarque compose de trois interfaces diffrentes fonctionnant de


manire conjointe. Chaque interface est gre par un appareil diffrent, UIC se chargeant
de synchroniser leur comportement.

Mon projet de stage nayant pas port spcifiquement sur le moteur dinterface, ce rapport ne
rentrera dans les dtails techniques de ce produit que de manire ponctuelle et contextuelle.

2.3 Quelques exemples

La solution UIC supporte dj lexcution de linterface graphique de produits grand public


disponibles principalement sur le territoire nippon. On peut citer pour loccasion certaines impri-
mantes de la marque EPSON mais galement des tableaux de bord de vhicules personnels et
professionnels dveloppes pour le march japonais.

Imprimante EPSON Colorio EP-879 dont linterface fonctionne grce UIC.

2.4 Concurrence

Bien entendu, UIC nest pas la seule solution disponible sur le march ; lentreprise doit jouer
des coudes avec plus dune dizaine de concurrents au Japon ainsi qua linternational. Parmi eux,
nous pouvons citer Qt dont le clbre framework a t declin pour le monde de lembarque mais
egalement Rightware Kanzi equipant les voitures Audi dont linterface graphique a t trs reconnue
par certains prix de design.
14 Chapitre 1. Introduction

Tableau de bord virtuel de lAudi TT 2015, cre grce la solution Kanzi.

Les diffrences entre toutes ses solutions sont plutt techniques et assez subtiles. Elles sont
tous capables dafficher des interfaces graphiques complexes mais certaines se sont focalises sur
les fonctionnalits de rendu graphique tandis que dautres permettent entre autres dimplmenter la
logique de linterface graphique.
Bien entendu, la license associe loutil ainsi que lenvironnement de dveloppement propos
jouent un rle important dans le choix dune solution plutt quune autre.

Interface graphique de Kanzi.


http://www.rightware.com/kanzi/

3 Prsentation du projet Debugger


Bien que UIC soit un projet relativement mature, lentreprise continue dajouter de nouvelles
fonctionnalits afin dtre en concordance avec les tendances technologiques et les attentes des
clients, mais galement de faire face une concurrence internationale toujours plus rude.
En loccurrence, un nombre non-negligeable de clients, de dveloppeurs internes ou externes
lentreprise, ainsi que dutilisateurs potentiels ont manifest leur mcontentement face lab-
sence doutils chargs de faciliter la recherche de bugs ou de problmes de performance ; ces
outils, communemment appels Debugger ou Profiler, faisant gnralement partie de larsenal du
dveloppeur.
Cette problmatique ma t annonce ds mon arrive et les managers mont laiss le choix
entre entamer la conception et le dveloppement du Debugger, ou contribuer au dveloppement de
UIC. Je dois avouer que le challenge tant en termes techniques que de design propos par ce projet
ma rapidement convaincu de le slectionner afin de gagner en exprience dans les domaines du
dveloppement informatique et du design centr utilisateur.
3 Prsentation du projet Debugger 15

Lentreprise ma alors laiss carte blanche pour que je dfinisse dans les grandes lignes les
spcifications de ce projet et que je dveloppe un premier prototype pendant ces quelques mois de
stage, et ce selon lorganisation et la mthodologie qui me semblait les plus adaptes. Jallais tre
suivi et paul par Guillaume George, diplm de lUTC en Gnie Informatique filire STRIE qui
a rejoint HI Corporation en 2013 ds son projet de fin dtude.
Prparation

Ma premire semaine de stage a t marque par la traditionnelle configuration du poste de


travail ainsi que la prise en main du produit. Jai donc pris connaissance de la documentation de
lapplication Tact ainsi que de la librairie UIC. Jai t notamment amen mettre en place une
chaine de compilation croise afin de pouvoir compiler et tester mes prototypes sur une machine
embarque de test.

Mon espace de travail trs complet : un Windows pour dvelopper le debugger, une
machine virtuelle sous Linux pour assurer la compilation croise et un Mac pour les outils
de design.
18 Chapitre 2. Prparation

La cible en question tait une M3 de la marque Renesas. Ce System-on-Chip bas sur un


processeur ARM 64bit est commercialis depuis 2016. Il a t conu comme une plateforme
complte de prototypage pour application embarque de vhicule pouvant facilement sinterfacer
avec les capteurs, actionneurs et moniteurs disponibles dans lhabitacle. Ce SoC etait configur
avec le systme dexploitation Automotive Grade Linux et le gestionnaire de fentre Wayland.

La Renesas M3
https://www.renesas.com/en-us/solutions/automotive/products/rcar-m3.html

Aprs que lon mait fourni le package Ubuntu contenant les programmes de compilation
croise de la cible, jai d adapt la chaine de compilation croise gnrique, mise en place par
lentreprise, pour quelle puisse fonctionner sur cette plateforme. Ceci a pu tre effectu laide de
CMake, un gnrateur de makefile multiplateforme que je navais jamais eu loccasion dutiliser
jusqu prsent.

Linterface de CMake qui ma suivi pendant toute la dure du stage.


Communication entre deux machines

1 Objectifs
Lors de notre premire runion pour dfinir les grandes lignes du projet, Guillaume ma nonc
certaines fonctionnalits demandes par les dvelopeurs de lentreprise. Parmi elles figuraient le
suivi des donnes du moteur dinterface graphique ainsi que le contrle de lapplication, le tout
en temps rel et " distance", dans le sens "depuis une application excute sur un ordinateur
de bureau". Il nous est donc naturellement venu lide de considrer la conception de deux
programmes distincts amens communiquer ensemble pour assurer lchange dinformation et
dinstructions :
Dun ct, une librairie se greffant sur UIC responsable de lenvoie de donnes provenant du
moteur dinterface graphique, et qui se comporte comme une interface pour que des appareils
externes puissent contrler lapplication.
De lautre, une application graphique, excute sur un ordinateur de bureau, charge de
rcuprer ces informations et de les afficher lutilisateur.
Cette librairie allait tre divise en deux parties. Une premire assez gnrique assurant seule-
ment la transmission de donnes entre deux ordinateurs quelconques, en loccurence une machine
embarque et un ordinateur de bureau ; la deuxime faisant la passerelle entre UIC et ce module de
communication.

1.1 Contraintes
Avant mme de commencer la conception de cette librairie, jai pris connaissance des diffrentes
contraintes que le module devait respecter.
Il tait important que la librairie soit, au mme titre que UIC, multi-plateforme. Il fallait donc
sassurer quelle fonctionne sur un maximum de cibles ainsi que sur les deux principaux systmes
dexploitation embarqus : Linux et Windows. Bien entendu, les diffrentes API devaient tre
abstraites pour simplifier le travail du dveloppeur qui exploitera ce module de communication.
Dans un second temps, la librairie devait galement faire la distinction entre APIs publiques
et APIs prives. En effet, HI Corporation ne donne accs qu une partie du moteur dinterface
20 Chapitre 3. Communication entre deux machines

graphique sous la forme dun sous-ensemble de fonctions et structures, la totalit du code source
tant dj compil, et ce afin de se protger dun ventuel plagiat de leurs technologies.
A ce titre, je devais minimiser les changements dAPIs et de structures publiques pour rester
compatible avec la version actuelle. Si possible, il fallait que je massure que mes contributions
naltrent en rien le comportement des structures dj mises en place.
Enfin, pour tre en accord avec les contraintes du milieu de lembarqu, lentreprise doit
sassurer que les fonctions quelle fournit sxcutent correctement, lune des rgles fondamentale
fixe par HI Corp tant que lappel une fonction publique ne doit pas interrompre lexcution. Je
devais donc accorder une attention toute particulire la gestion des erreurs ainsi qu celle de la
mmoire afin que mes contributions puissent tre inclues dans le produit final.

2 Recherches
2.1 Choix de la technologie de communication
Bien que nous comptions abstraire la technologie assurant la communication entre les deux
appareils, il nous a fallu trs rapidement faire un choix dimplmentation pour pouvoir dvelopper
un premier prototype. Il existe ce titre plusieurs manires dinteragir avec le logiciel et le matriel
dune machine embarque. Une premire mthode consiste sonder directement le processeur
laide doutils lctroniques prvus cette effet, comme une sonde JTAG. Une seconde mthode
consiste quant elle exploiter les ports I/O de la cible, comme les ports GPIO ou dautres plus
communs comme le port USB, le port srie, le port RJ45, etc.
Il tait important de choisir la technologie la plus adapte nos besoins en matire de transfert de
donnes, mais galement la plus communment disponible sur ce type dappareil et celle permettant
de simplifier au maximum le dveloppement dune preuve de concept. Nous avons alors dcid
de baser notre module de communication sur les couches rseau du modle OSI, assurant une
abstraction logicielle et donc une simplicit de dveloppement, le tout transport via une connexion
Ethernet. En effet, il se trouve que la plupart des appareils embarqus de prototypage disposent
dun port Gigabit Ethernet RJ45 permettant ainsi un dbit thorique (de 1Gb/s donc) suffisament
lev pour les messages que nous souhaitions priori transmettre.
Les sockets sont les concepts logiciels grce auxquels un dveloppeur peut mettre facilement
en place une communication temps-rel entre plusieurs machines connectes un mme rseau.
Nayant jamais exploit ce concept auparavant, ctait la parfaite occasion dtudier comment
utiliser efficacement cet outil au sein dune application embarque.

2.2 Choix du protocole de transmission


Concrtement, une socket et une interface logicielle vers un protocole de communication
particuler - issue de la couche transport du modle OSI - choisir gnralement entre TCP/IP et
UDP. Ces protocoles fonctionnent de manire trs diffrente et proposent ainsi chacun des avantages
et des inconvnients. Il conviendra alors de choisir le plus adapt notre projet.
En loccurrence, le protocole UDP (appel galement Datagram Mode) a t conu pour
permettre un envoi simple de donnes dune entit vers une autre. Avec cette mthode, lexpditeur
peut envoyer un message nimporte quel autre appareil du rseau connaissant son adresse IP et
son port. Le protocole UDP nassure ni la bonne rception du message ni le bon ordonnancement
des messages. En outre, il ne permet pas non plus lenvoi de messages plus gros quenviron 64ko
octets thorique sur le protocole IPv4 (en pratique, ce nombre est rduit environ 570 octets) ; le
dveloppeur est alors responsable du dcoupage/recollage des donnes sil a besoin de transmettre
de plus grosses quantits de donnes.
Bien que limit, ce protocole lger sduit par sa simplicit ainsi que sa vitesse de transmission.
2 Recherches 21

Il est trs utilis dans les applications de communication en temps-rel o la perte de messages
nest pas critique comme les jeux vido ou le streaming en direct de mdias.
Au contraire, le protocole TCP (appel galement Stream Mode) garantit lacheminement du
message ainsi que leur ordre de rception. Il est de plus capable de diviser si ncessaire un message
en paquets qui seront transmis sparemment puis rassambls chez le destinataire.
Ce protocole est trs intressant pour les applications o chaque message doit absolument
tre reu en ltat. Cependant, cette garantie se paye au prix dune procdure de handshake
ncessaire pour dbuter la transmission, dun plus grand nombre de donnes transmises pour
assurer lacquittement de chaque message, et dune taille de message plus importante pour pouvoir
contenir les informations ncessaires au routage.
A ce moment de nos recherches, nous ne savions pas encore quel type de donnes allait tre
chang entre les appareils. Nous avons donc opt pour le protocole TCP afin de ne pas avoir
nous soucier de la bonne reception des donnes ; tout en abstrayant suffisamment notre architecture
pour nous donner la possibilit de passer au protocole UDP en cas de problmes de performance.

2.3 Analyse de lAPI Socket


Il tait prsent important dtudier la structure de lAPI propose par les systmes dexploita-
tion afin de comprendre les diffrentes tapes de configuration et dexploitation dune socket.
Les systmes dexploitation Unix utilisent lAPI dites de Berkeley normalise au dbut des
annes 80 par luniversit du mme nom. Cet ensemble dune vingtaine de fonctions assure la mise
en place de la connexion ainsi que la transmission et la reception de messages ([1], [2]).
Une fois nest pas coutume : sur Unix, tout est fichier. La fonction socket cre alors un
descripteur de fichier via lequel le dveloppeur peut crire ou lire en utilisant les traditionnelles
fonctions read et write ; ou encore les fonctions send, recv, sendto et recvfrom pour disposer
de plus de prcision sur lenvoie et la reception des donnes. Cest au moment de la cration de la
socket que le dveloppeur peut choisir le protocole de transmission.
LAPI fait notamment la distinction entre serveur et client. Cette distinction est par contre
diffrente des applications webs o le serveur ne fait que rpondre aux requtes des clients. Dans le
cas des sockets, le serveur est lentit qui coute les nouvelles connexions venant des clients et qui
autorise ou non la mise en place de la connexion. Une fois celle-ci tablie, les deux entits peuvent
communiquer lune avec lautre en temps-rel sans distinction particulire.
Le serveur a pour cela accs aux fonctions bind, listen et accept respectivement pour
associer le serveur un port local, pour commencer lcoute de nouvelles connexions et pour
autoriser la demande de connexion dun client. Le client quant lui na qu appeler la fonction
connect avec ladresse IP et le port du serveur pour lancer la procdure de handshake dans le
cadre du protocole TCP.
Microsoft a quant lui dvelopp dans le dbut des annes 90 la librairie WinSock dans le but
de standardiser les connexions rseaux sous Windows. Celle-ci est inspire des sockets Berkeley et
propose ainsi une API trs similaire ([3], [4]). A part quelques petites subtilits, le portage dune
application rseau de Linux Windows et vice-versa peut se faire assez rapidement.
Cette API assez vieille a t notamment critique par D. Shmidt qui lui reproche un manque
de cohrence dans sa structure [5]. En effet, lenchainement des fonctions nest pas simple
apprhender, lAPI tant structure de manire linaire plutt que de manire hierarchique. Il ny
a par exemple pas de distinction de type entre les sockets dcoute et les sockets dcriture, ou
encore entre les sockets TCP et les sockets UDP, donc aucune vrification possible au moment de
la compilation pour sassurer de la cohrence des structures manipules.
Il regrette tout de mme un lger manque de portabilit entre les diffrents systmes dexploita-
22 Chapitre 3. Communication entre deux machines

tion. Par exemple, les fonctions sur systme POSIX attendent des descripteurs de fichiers (des int)
en argument tandis que Windows manipule des pointeurs.
Tous ces problmes rendent assez prilleuse la manipulation des sockets par des dveloppeurs
peu expriments. Il faut donc autant que faire se peut simplifier cette API pour rendre lutilisation
des fonctionnalits rseaux plus abordable et plus sre. Shmidt propose ce titre un wrapper de
cette API crite en C++ au sein de la librairie ACE exploitant les spcificits du langage pour
vrifier un maximum derreurs de logique au moment de la compilation ([6], [7]).

2.4 Architecture rseau


Les performances et la maintenabilit dune librairie de rseau dpendent normment de
larchitecture et des designs patterns utiliss. Depuis la naissance dinternet, les dveloppeurs
mettent au point diffrentes organisations logicielles et fonctions systmes pour optimiser le
fonctionnement de ce type dapplication. Cette tendance sest accentue depuis la diffusion dans
les annes 90 du problme C10K [8]. Celui-ci soulve le fait que les serveurs sont techniquement
capables de grer plus de 10 000 connexions et requtes simultanes mais labsence de fonctions
optimises les en empche. Notre plateforme est certes bien diffrente des serveurs considrs par
ce problme mais les problmatiques doptimisation restent similaires.
Les cours et articles de Schmidt [5] qui dtaillent diffrents design patterns applicables dans le
cas dun projet rseau, et dont la plupart sont utiliss au sein de la librairie ACE, ont t une norme
source dinspiration pour la conception et le dveloppement de ce module de communication. La
suite de cette partie expliquera certains des points abords par lauteur.

Design patterns prsents par Shmidt.

Tout dabord, il faut savoir que toutes les fonctions de lAPI socket sont par dfaut bloquantes :
elles bloquent le thread courant tant que lopration de rseau en cours dexcution nest pas
acheve. Cette subtilit pose un gros problme pour les serveurs qui doivent accepter le handshake
(avec la fonction accept) et recevoir les messages entrants (avec recv ou une de ses drive). En
effet, chacune de ces deux fonctions tant bloquante, il nest pas possible dcouter les connexions
entrantes en mme temps que les messages reus.
Par exemple, le code suivant ne fonctionne que pour une seule connexion :
1 // Attente d une premiere connexion
2 accept (...) ;
2 Recherches 23

3
4 while ( true )
5 {
6 // Attente d un nouveau message
7 recv (...) ;
8 }

Mais il nest pas possible dutiliser le code suivant pour couter la fois les connexions entrantes
et les messages reus :
1 while (1)
2 {
3 // Attente d une nouvelle connexion
4 accept (...) ;
5
6 // Attente d un nouveau message
7 // ( Un message par connexion ...)
8 recv (...) ;
9 }

Si les fonctions sont non-bloquantes, il est possible dutiliser le dernier listing pour atteindre
nos objectifs. Mais cette boucle infinie extrmement energivore nest pas du tout optimise pour les
systmes embarqus. Bien heureusement, de nombreuses primitives disponibles dans diffrents
systmes dexploitation permettent dcouter ltat des sockets et davertir le programme lorsquune
est prte excuter une nouvelle fonction rseau.
On pourrait alors diviser ces primitives en deux catgories, celles comme les traditionnelles
select et poll qui bloquent tout de mme lexcution en attendant quun vnement dune des
sockets est reu (on les appelle synchronous event demultiplexer) ; et celles qui ne bloquent pas
lexcution mais qui avertit le programme dun changement dtat dune socket laide de signaux
ou de fonctions de callbacks. On retrouve galement dans la littrature la distinction entre level-
based et edge-based [8] : le premier avertit lapplication continuellement tant que lvnement na
pas t trait tandis que la deuxime navertit lapplication quau moment dun vnement.
De nombreuses primitives sont disponibles sur la plupart des systmes. Celles-ci trouvent prin-
cipalement leur diffrence dans les limitations de limplmentation systme, certaines permettant
de mieux grer de grandes quantits dvnements que dautres.
Les fonctions prcdentes permettent dcouter les vnements du rseau, il faut prsent
dterminer une manire efficace de les traiter. Il est tout fait possible de les traiter sur le mme
thread dcoute, auquel cas il peut tre intressant de considrer le design pattern Reactor [9] (aussi
appel Dispatcher ou Notifier) pour dcoupler la gestion des vnements de lcoute en elle-mme.
Cette mthode a nanmoins linconvnient de bloquer lensemble du systme si le traitement dun
seul vnement se trouve tre chronophage.
A lautre extrme, le design pattern Active Object [10] propose de traiter chaque vnement au
sein dun thread disctinct puis de renvoyer la balle au thread principal laide dun mcanisme de
callback. A priori intressante, la surcharge associe lutilisation dun fil dexcution ne permet
malheureusement pas dutiliser ce type dorganisation pour une trop grosse quantit dvnements
reus de manire simultane.
Un compromis serait dutiliser un nombre limit et rduit de threads se partageant les vne-
ments traiter, auquel cas il est ncessaire de garder dune quelconque manire en mmoire les
vnements en attente de traitement. Ceci peut tre simplement implment laide dune simple
file ou par des structures plus complexes sil est ncessaire de prendre en compte dautres variables,
24 Chapitre 3. Communication entre deux machines

comme la priorit, pour lordonnancement des vnements. La plupart des autres design patterns
proposs par Schmidt, comme le Half-Sync/Half-Async [11] ou le Leader/Followers [12], sont
autant de manires de simplifier et/ou doptimiser la synchronisation de lensemble des threads
ainsi que la gestion de la structure contenant les vnements en attente.
3 Architecture 25

3 Architecture
Ces recherches mont permis dacqurir suffisamment de connaissances pour pouvoir crire
les grandes lignes de larchitecture du module de communication. Les diagrammes de classes
et de squences ont t dune importante capitale pour mettre plat lorganisation ainsi que le
fonctionnement de cette premire librairie.

3.1 Refonte de lAPI Socket


Comme expliqu prcdemment, lAPI utilise par dfaut dans Linux et Windows pour exploiter
les sockets est une source commune derreurs quil faut simplifier et clarifier pour viter une
mauvaise utilisation. Ceci passe notamment par la distinction entre socket serveur capable daccepter
de nouvelles connections et socket client conue pour se connecter un serveur. Ces deux types de
sockets se voient affecter une API diffrente, ainsi, une socket serveur peut rpondre aux fonctions
suivantes :
Une fonction dinitialisation sur un port ;
Une fonction denvoie de message une socket client spcifie ;
Une fonction dcoute de message et de nouvelles connexions. Pour simplifier le dvelop-
pement, nous avons opt pour une mthode qui bloque le thread courant tant quun nouvel
vnement na pas t reu ;
Une fonction de dconnexion.
Une socket client peut rpondre quant elle aux fonctions suivantes :
Une fonction de connexion une entit du rseau, dtermine par son adresse et son port ;
Une fonction denvoie de message son socket server associe ;
Une fonction dcoute de message entrant ;
Une fonction de dconnexion.
Limplmentation de ces fonctions tant dpendante de la cible, elle est la charge des dvelop-
peurs qui auront tout le loisir dexploiter les appels systmes les plus adquats.
Cette nouvelle API pure a t ensuite abstraite, encapsule et tendue pour crer des structures
plus complexes assurant les principales fonctionnalits ncessaires pour notre projet.

3.2 Pipeline denvoie et de reception


Dans son niveau le plus gnral, la librairie de communication dfinit une instance de rseau
(une instance de client et une de serveur) capable de communiquer par le biais de deux pipelines :
lun denvoie et lautre de reception, ces deux pipelines fonctionnant de manire symtrique. Ils
sont chacun chargs de respectivement encoder/dcoder les messages et de les stocker dans une
file en attendant leur transmission/traitement. Lencodage et le dcodage des donnes ainsi que
la file de messages sont des fonctionnalits abstraites afin de donner suffisamment de libert
dimplmentation.
Des workers sont quant eux chargs de traiter les donnes arrivant dans la file de messages.
En loccurrence, le worker denvoie rcupre les messages transmettre, les encode si ncessaire,
puis les envoie via lAPI socket ddie. Celui de reception rcupre les messages reus, les dcode
si ncessaire, puis appelle une fonction de callback ddie au traitement du message. Ces workers
sont galement abstraits pour simplifier leur changement de comportement.

3.3 Fonctionnement des Workers


Un worker se doit de sxcuter indpendamment du flux dxcution principal. En effet, il na
besoin de neffectuer sa tche que lorsquun nouveau message est ajout dans la file sans oublier que
le traitement dun message ne doit pas bloquer le flux dexcution. Il est alors intressant dxcuter
26 Chapitre 3. Communication entre deux machines

les workers dans des threads indpendants qui seront synchroniss avec la file de messages laide
de smaphores.
La question qui vient immdiatement ensuite est : combien de threads sont ncessaires pour ce
projet ? Jai mentionn dans la partie prcdente un certain nombre dapproches diffrentes : un
unique thread par worker, un thread par message traiter ou encore plusieurs threads se partageant
les messages.
Dans un premier temps, nous souhaitons conserver lordre denvoie et de reception de messages.
En effet, si lutilisateur envoie deux instructions UIC, il sattend vraissemblablement ce que les
instructions soient traites dans cet ordre. Lapproche du "un seul thread par worker" assure cet
ordonnancement.
En outre, la librairie sera vraisemblablement utilise dans le cadre dune communication en un
pour un. Nous pensons autoriser la communication avec une poigne dautres machines mais ce
nombre ne nous semble pas suffisamment pour envisager lutilisation dun thread par client.
La premire approche semble ainsi tre la plus adapte pour nos besoins, mais galement la
plus simple implmenter pour un premier prototype.
En outre, il existe des cas o le worker de reception doit appeler une fonction asynchrone
pour traiter le nouveau message reu. Pour illustrer ceci, imaginons que le worker reoivent une
instruction lui demandant de changer lcran de linterface graphique. UIC xcute le changement
dcran de manire asynchrone : la fonction setScreen retourne immdiatement true si lcran
peut tre chang, et une fonction de callback avertit le thread principal lorsque lcran courant
a bien t modifi. Cette fonction de callback peut tre appele parfois plusieurs secondes aprs
la fonction initiant le changement dcran. Dans ce cas, nous souhaitons que le worker ne traite
linstruction suivante quune fois le changement dcran compltement finalis.
Le design pattern appel Asynchronous Completion Token [13] rsout justement ce problme.
Ce pattern propose dutiliser un token associ au message actuellement trait, ce token contient en
fait un smaphore sur lequel le thread du worker attend. Ce token est ensuite pass au dveloppeur
qui peut dbloquer le thread et donc entammer le traitement du message suivant en librant le
smaphore quand il le souhaite.

4 Dveloppement
Une fois larchitecture dcrite et valide par mes collgues, je me suis attel son implmenta-
tion, en prenant en compte les contraintes cites en dbut de partie.

4.1 Choix du langage


Avant de commencer dvelopper, il nous fallait dterminer le langage de programmation avec
lequel cette librairie allait tre crite. Celui-ci devait tre notamment suffisamment mature pour
proposer des compilateurs sur la plupart des plateformes embarques.
Nous avions alors le choix entre C89, aussi appel C90 ou ANSI C, la premire spcification de
ce langage conu pour tre facilement compilable, et C++03, la seconde spcification de ce langage
orient-object. Bien que mon architecture tait initialement pense pour un langage orient object,
nous tions conscients quil tait relativement simple de le faire fonctionner sur un langage moins
complet. Deux raisons nous ont finalement convaincu dopter pour le C89 :
Certains clients nutilisent que des plateformes embarques assez vieilles ou personnalises,
celles-ci ne disposant que de simples compilateurs C89. Utiliser ce langage nous assurait de
couvrir un plus grand nombre de cibles ;
La quasi totalit de la librairie embarque du moteur dinterface graphique est dveloppe
avec cette spcification, sans que a nait pos de problmes de dveloppement particulier.
4 Dveloppement 27

Dans un soucis de cohrence, il tait ainsi plus intressant dcrire le code source de cette
librairie de communication avec la mme norme.

4.2 Programmation Orient Object en C


Le fait que le moteur dinterface graphique soit crit en C ne lempche pas pour autant
dexploiter une approche issue de la programmation orient objet pour organiser ses diffrents
composants. Au contraire, une grande partie des fonctionnalits offertes par le C++ sont en fait
accessibles en C89, moyennant suffisamment defforts [14].
Le moteur dinterface graphique exploite deux organisations du code diffrentes pour sappro-
cher de larchitecture des langages orients objets. La premire consiste utiliser des structures
struct pour y inclure les proprits des objets puis de proposer les mthodes comme un ensemble
de fonctions dclares lextrieur de la structure. Ces fonctions prendront en premier paramtre
un pointeur vers lobjet appelant, similaire au this implicite du C++.
1 typedef struct {
2 int variableA ;
3 /* autre variables */
4 } MaClasse ;
5
6 MaClasse * MaClasse_new ( /* ... */ ) ; // Constructeur
7 void M a Cl asse_ setVar iable A ( MaClasse * this , int variableA ) ;
8 int M a C lasse _getV ariabl eA ( const MaClasse * this ) ;
9 void MaClasse_delete ( MaClasse * this ) ; // Destucteur

La syntaxe dutilisation des objets est toutefois un peu diffrente du C++ :


1 MaClasse * obj = MaClasse_new () ;
2 M a C l a s s e_ setVar iable A ( obj , 5) ;
3 MaClass_delete ( obj ) ;

La deuxime consiste intgrer des pointeurs de fonction au sein de de la structure. Cependant,


comme vous pouvez le voir dans le listing suivant, cette approche ncessite un peu plus de travail.
1 typedef struct MaClasse MaClasse ; // Forward Declaration
2
3 void (* func_Delete ) ( MaClasse * this ) ;
4 void (* func_SetVariableA ) ( MaClasse * this , int variableA ) ;
5 int (* func_GetVariableA ) ( const MaClasse * this ) ;
6 /* autres definitions de types de fonction */
7
8 typedef struct {
9 int variableA ;
10 /* autre variables */
11
12 func_Delete delete ;
13 func _SetVariableA setVariableA ;
14 func _GetVariableA getVariableA ;
15 /* autres fonctions */
16 } MaClasse ;
17
18
19 MaClasse * MaClasse_new ( /* ... */ ) ; // Il faut tout de meme une fonction qui
va remplir les pointeurs de fonctions
28 Chapitre 3. Communication entre deux machines

La syntaxe dutilisation des objets est la suivante :


1 MaClasse * obj = MaClasse_new () ;
2 obj - > setVariableA ( obj , 5) ;
3 obj - > delete ( obj ) ;

Bien quelle se rapproche du C++, il faut tout de mme passer explicitement this en argument
de toutes les fonctions, ce qui rend le code trs redondant. A cause de cette rptition de code,
potentielle source derreur, on prferera la premire approche pour dvelopper nos classes.
Cette mthode a toutefois le mrite de faciliter le dcouplage qui plus est dynamique de la
dclaration et la dfinition dune fonction. Il est ainsi possible de changer la vole la dfinition
dune fonction en assignant simplement le pointeur de fonction vers une autre. On utilisera alors
cette organisation du code pour les fonctionnalits dpendantes de cette spcificit ainsi que pour
les fonctions qui nont pas besoin daccder this (on se rapproche alors des fonctions statiques
de classes en C++).
Dans les deux cas, lhritage peut se faire simplement en utilisant une approche par la classe
mre ou par la classe fille. Lapproche par la classe mre consiste ne manipuler quun pointeur
vers la structure parente, celle-ci contenant un pointeur gnrique vers une structure enfant que le
dveloppeur devra rinterprter via un cast.
1 enum Mere_Fille_Type {
2 FILLE_1 ,
3 FILLE_2
4 }
5
6 struct Mere {
7 int varMere ;
8
9 Mere_Fille_Type typeFille ;
10 void * fille ; // Pointeur generique vers la fille . Si la mere est une
classe abstraite , ce pointeur ne peut etre nul .
11 };
12
13 struct Fille1 {
14 int varFille1 ;
15 }
16
17 struct Fille2 {
18 int varFille2 ;
19 }
20
21 Mere * Mere_new ( /* ... */ ) ; // Cette fonction n existe que si la mere n est
pas une classe abstraite .
22 Mere * Fille1_new ( /* ... */ ) ;
23 Mere * Fille2_new ( /* ... */ ) ;
24
25 void Mere_setVarMere ( Mere * this ) ;
26 // Les fonctions suivantes sont responsables du cast de void * vers Fille1 *
ou Fille2 *
27 void F i lle1_setVarFille1 ( Mere * this , int varFille1 ) ;
28 void F i lle2_setVarFille2 ( Mere * this , int varFille2 ) ;

Cette mthode a nanmoins le dsavantage de devoir constamment manipuler, de manire


assez contre-intuitive, un pointeur vers la classe mre. Rien nempche donc le programme suivant
4 Dveloppement 29

de compiler, de sxcuter et de voir son excution interrompue par un potentiel Segmentation


Fault :
1 Mere * fille1 = Fille1_new () ;
2 F il l e2 _ setVarFille2 ( fille1 ) ; // Acces a un membre qui n existe pas

Lapproche par la fille consiste quant elle manipuler des pointeurs vers la classe fille, comme
on le ferait en C++. La classe fille peut contenir lobjet mre ou alors un pointeur vers celui-ci.
1 struct Mere {
2 int varMere ;
3 };
4
5 struct Fille1 {
6 Mere mere ; // Premiere variante : Fille1 contient " mere "
7 int varFille1 ;
8 }
9
10 struct Fille2 {
11 Mere * mere ; // Deuxieme variante : Fille2 pointe vers " mere "
12 int varFille2 ;
13 }
14
15 Mere * Mere_new ( /* ... */ ) ; // Cette fonction n existe que si la mere n est
pas une classe abstraite .
16 Fille1 * Fille1_new ( /* ... */ ) ;
17 Fille2 * Fille2_new ( /* ... */ ) ;

Si la structure fille contient la structure mre au dbut de sa dfinition mmoire (premire


variante), il est alors possible de passer de lune lautre avec un simple cast :
1 Fille1 * fille1 = Fille1_new () ;
2 Mere * mere1 = ( Mere *) fille1 ; // Correct car les sizeof ( Mere ) premiers bits
de Fille1 representent bien une Mere
3 mere1 = & fille1 - > mere ; // Correct
4
5 Fille2 * fille2 = Fille2_new () ;
6 Mere * mere2 = ( Mere *) fille2 ; // Incorrect
7 mere2 = fille2 - > mere ; // Correct

La deuxime variante (par pointeur) est intressante si la mre doit tre dcouple de la fille,
que ce soit pour des raisons de fonctionnalit ou de fragmentation de la mmoire. Nanmoins,
limpossibilit de pouvoir facilement passer du type fille au type mre rend le code trs verbeux.
De part ses avantages sur lapproche par classe mre, nous avons opt pour un hritage par
classe fille. Il faut nanmoins faire trs attention aux fonctions et classes manipules car cette
approche ne permet pas en ltat dassurer le polymorphisme de manire automatique.

4.3 API Publique vs. Prive


UIC tablit une nette distinction entre les API publiques, accessibles et visibles par les dvelop-
peurs externes lentreprise, et les API prives rserves au dveloppement en interne, ceci afin de
ne pas rvler certaines parties sensibles de larchitecture de la librairie qui pourraient tre plagies
ou tout simplement mal exploites.
30 Chapitre 3. Communication entre deux machines

Bien heureusement, les mthodes de compilation et ddition des liens dun programme crit
en C permettent de cacher les structures de donne et les les fonctions. Voici un exemple :
1 /* Fichier main_public . h ( fourni aux developpeurs ) */
2
3 // Structure publique : le developpeur a acces a son contenu
4 typedef struct {
5 /* ... */
6 } StructPublic ;
7
8 // Structure cachee : le developpeur n a pas acces a son contenu mais tout
de meme l utiliser
9 // StructHidden est remplacee par sa veritable organisation memoire au
moment d edition des liens
10 typedef struct StructHidden StructHidden ;
11
12 // Fonction publique manipulant une structure publique
13 StructPublic * StructPublic_new ( /* ... */ ) ;
14
15 // Fonction publique manipulant une structure cachee
16 StructHidden * StructHidden_new ( /* ... */ ) ;

1 /* Fichier main_private . h ( non fourni aux developpeurs ) */


2
3 # include " main_public . h "
4
5 // Definition de la structure cachee que le developpeur peut exploiter
6 typedef struct {
7 /* ... */
8 } StructHidden ;
9
10 // Structure privee : le developpeur n y a pas acces et ne peut pas l
utiliser
11 typedef struct {
12 /* ... */
13 } StructPrivate ;
14
15 // Fonction privee manipulant une structure publique
16 StructPublic * _StructPublic_new ( /* ... */ ) ;
17
18 // Fonction privee manipulant une structure cachee
19 StructHidden * _StructHidden_new ( /* ... */ ) ;
20
21 // Fonction privee manipulant une structure privee
22 StructPrivate * _StructPrivate_new ( /* ... */ ) ;

1 /* Fichier main_library . c ( fichier , cree par l entreprise , compile dans la


librairie ) */
2 # include " main_private . h " // Ce fichier a acces a toutes les structures et
fonctions
3
4 /* ... */

1 /* Fichier myFile . c ( fichier cree par le developpeur ) */


5 Implmentation de lAPI Socket 31

2 # include " main_public . h " // Ce fichier a acces a toutes les structures et


fonctions publiques
3
4 /* ... */

Le code source de la librairie de UIC utilise cette technique pour organiser les diffrentes
fonctions et structures. Mes contributions allaient donc vraisemblablement devoir sinspirer de cette
approche.

4.4 Abstraction de lOS et de la cible


Comme expliqu dans les contraintes, il est primordial dabstraire un maximum de fonctions
de base, ceci afin de donner la possibilit aux ingnieurs dadapter et doptimiser au mieux leur
programme pour une cible donne. Cest dailleurs une bonne pratique suivie par un grand nombre
de librairies embarques.
UIC inclut dj ce mcanisme par le biais de linterface IPlatform qui propose une impl-
mentation dun certain nombre de fonctions dpendantes de la cible mais indispensables au bon
fonctionnement du programme. Cest lune des seules structures de UIC dfinies laide de la
mthode des pointeurs de fonction. Cette interface, passe tous les objets qui en auront besoin,
est gnre par une librairie charge de proposer une implmentation pour la cible courante. Il y a
donc au minimum : une IPlatform pour Linux et une pour Windows, mais chaque dveloppeur
est libre de proposer des variantes.
Les fonctions proposes par cette structure sont :
Les fonctions de gestion de mmoire malloc, realloc et free.
Les fonctions de lecture de fichier ;
Les fonctions de gestion de thread ;
Les fonctions de mutex ;
Les fonctions de log
Jai t libre dinclure les fonctions que je jugeais pertinentes au sein de cette interface. A ce titre,
jy ai ajout toutes les procdures relatives la nouvelle API de socket ainsi quaux smaphores,
puis propos une implmentation de ces procdures pour Linux et Windows en exploitant les API
disponibles sur le systme dexploitation respectif.

5 Implmentation de lAPI Socket


Limplmentation de la nouvelle API sest faite relativement sans accroc, les appels systmes
tant relativement similaires sur Windows et Linux. Nayant jamais eu loccasion de travailler aussi
prs du protocole TCP/IP, javoue tre tomb dans lerreur de dbutant consistant considrer que
les messages reus laide dun driv de recv taient complets et quun send tait ncessairement
li un unique recv.
Ce nest cependant pas le cas. Comme le protocole TCP/IP dcoupe automatiquement le
message en paquets pour accommoder le rseau, paquets qui seront ensuite recolls chez le
destinataire, on ne peut pas savoir combien de paquets ont t envoy par send et donc combien
ont t reus et rarrangs au moment dun appel recv. Il nest donc pas impossible que le
destinataire ne reoive quune partie dun message ou alors plusieurs messages dun coup, charge
au dveloppeur dindiquer si le destinataire doit attendre la fin du message ou dcomposer les
messages reus.
Pour cela, il est ncessaire de fixer une mthode de sparation des messages. La plus simple,
celle que nous avons implmente, tant de prfixer chaque message par sa taille ; lalternative un
peu plus subtile tant de suffixer chaque message par un indicateur de fin.
32 Chapitre 3. Communication entre deux machines

5.1 Vrification des erreurs


Comme expliqu dans les contraintes, les fonctions composant lAPI publique ne doivent pas,
dans la mesure du possible, interrompre lexcution de lapplication graphique. Les procdures
de cette librairie doivent donc inclure des mcanismes de vrification des arguments ainsi que de
lexcution des sous-routines et retourner un code derreur prenant la forme dun enum indiquant si
ncessaire la cause du problme.
Laspect le plus complexe de cette tape de vrification est le rtablissement de ltat initial si
la fonction appele ne sexcute pas correctement. En effet, une fonction publique peut appeler
tout un ensemble de procdures qui vont altrer ltat interne du systme en manipulant notamment
diffrentes portions de la mmoire. Il est alors ncessaire dannuler toutes ces modifications pour
viter les tats incohrents, les fuites de mmoire, les lments de synchronisation de threads qui
demeurent reservs, les processus zombies ou encore les threads qui sexcutent inutilement.
Les deux listings suivants dcrivent une trame possible pour une fonction publique :
1 ErrorCode fonctionPrincipale ( /* arguments */ )
2 {
3 /* verification des arguments */
4 /* retour si necessaire */
5
6 ErrorCode res ;
7
8 res = fonction1 (...) ;
9 if ( res )
10 {
11 res = fonction2 (...) ;
12 if ( res )
13 {
14 /* ... */
15 }
16 else
17 {
18 a nnulationFonction1 (...) ;
19 a nnulationFonction2 (...) ;
20 return res ;
21 }
22 }
23 else
24 {
25 a nn ulationFonction1 (...) ;
26 return res ;
27 }
28 }

1 ErrorCode fonctionPrincipale ( /* arguments */ )


2 {
3 /* verification des arguments */
4 /* retour si necessaire */
5
6 ErrorCode res ;
7
8 res = fonction1 (...) ;
9 if (! res )
10 {
11 a nn ulationFonction1 (...) ;
12 return res ;
13 }
6 Conclusion 33

14
15 res = fonction2 (...) ;
16 if (! res )
17 {
18 a nn ulationFonction1 (...) ;
19 a nn ulationFonction2 (...) ;
20 return res ;
21 }
22
23 /* ... */
24 }

Ces mthodes, qui respectent les principes de programmation enseigns lUTC, sont malheu-
reusement trs redondantes et ont tendance rendre le code trs verbeux et difficilement maintenable.
Lutilisation de goto, bien que proscrite par certains professeurs !, a t ici trs pertinente pour
simplifier lcriture du code source :
1 ErrorCode fonctionPrincipale ( /* arguments */ )
2 {
3 /* verification des arguments */
4 /* retour si necessaire */
5
6 ErrorCode res ;
7
8 res = fonction1 (...) ;
9 if (! res )
10 goto err1 ;
11
12 res = fonction2 (...) ;
13 if (! res )
14 goto err2 ;
15
16 /* ... */
17
18 err2 :
19 an nulatonFonction2 (...) ;
20
21 err1 :
22 a nn ulationFonction1 (...) ;
23
24 return res ;
25 }

6 Conclusion
Cette premire phase, qui sest tendue sur moins dun mois, a t loccasion dtudier et dex-
ploiter diffrents concepts fondamentaux du dveloppement de fonctionnalits de communication
entre appareils embarqus. Elle a abouti la cration dune librairie respectant les contraintes de
lentreprise qui donne la possibilit deux machines connectes au mme rseau de se transmettre
des messages en temps rel. Il faudrait toutefois la tester dans des cas rels dutilisation pour
sassurer que tous les choix techniques correspondent bien la ralit du terrain.
Intgration au sein de UIC

1 Objectifs
La premire phase a permis de concevoir les fondations de tout notre systme de communication.
La librairie cre est certes gnrique, mais lAPI propose est encore trop complexe pour nos
besoins et il est pour linstant difficile de linterfacer avec UIC. Cest ainsi que durant cette seconde
phase, nous avons tendu cette librairie pour pouvoir plus simplement rpondre aux cas dutilisation
suivants :
Lordinateur envoie une requte la machine embarque, cette dernire est ensuite charge
de retourner une rponse. On se rapproche ici de larchitecture client/serveur exploite par
les serveurs webs.
La machine embarque envoie spontanment une information lordinateur ;
Les contraintes nonces et dcrites en phase prcdente taient toujours applicables pour le
dveloppement de cette intgration.

2 Recherches
Notre premier cas dutilisation sapparentait au Remote Procedure Call (RPC) : un client appelle
une fonction dfinie sur un serveur qui lui renvoie le rsultat ; la diffrence tant que dans le cas du
RPC, le client ne sait pas que la fonction est excute sur une autre machine.
Il tait alors possible de sinspirer des spcifications rseaux qui autorisent ce type de fonc-
tionnalits. Au fil de nos recherches, nous avons dcouvert JSON RPC, une norme trs simple
qui exploite le format JSON pour remplir peu de chose prs les deux cas dutlisation dcrits
prcdemment.
JSON RPC 2.0 dfinit deux structures : les requtes et les rponses [15]. Les requtes sont
envoyes par le client au serveur et contiennent :
Un champ method indiquant lidentificateur de la fonction excuter ;
Une structure params dcrivant les paramtres de la fonction excute ;
Un champ id contenant lidentificateur de la requte, ceci est trs utile pour associer une
36 Chapitre 4. Intgration au sein de UIC

rponse la requte initiale. Si ce champ est nul ou non spcifi, la requte est considre
comme une notification et le client ne sattend pas une rponse.
Les rponses sont elles envoyes du serveur vers le client. Elles sont composes de :
Lun des deux champs result ou error contenant respectivement le rsultat de la procdure
ou la description de lerreur si la fonction na pas pu tre correctement excute ;
Un champ id contenant lidentificateur de la requte laquelle cette rponse fait rfrence.
Chaque requte et rponse envoye contient galement le champ jsonrpc dcrivant la version
de la norme pour assurer lintercompatibilit entre les versions.
Cette spcification a pos les grandes lignes de notre protocole mais il nous a fallu la modifier
lgrement pour quelle puisse mieux correspondre nos cas dutilisation.
Tout dabord, JSON RPC ne permet pas au serveur denvoyer spontanment un message au(x)
client(s). Pour permettre cette fonctionnalit, nous autorisons le champ id de lobject rponse dtre
nul, auquel cas la rponse est considre comme tant une notification du serveur vers le client.
Lautre problme est inhrent au JSON. Bien que trs pratique, et relativement simple srialiser
ou dsrialiser, cet encodage ne permet pas de dcrire des fichiers binaires sans conversion au
pralable, vers du base64 par exemple. Dautres part, nutilisant que des chaines de caractres, ce
format peut savrer lourd lors denvoie de simples valeurs numriques. Nous avons donc cherch
une alternative ce format pour encoder les requtes et rponses, alternative qui se devait tre tout
aussi simple manipuler.
Parmi les diffrentes spcifications de JSON binaires tudies, nous avons t sduits par
lencodage MessagePack [16], et ce pour les raisons suivantes :
il a une structure uniquement binaire, ce qui lui permet dtre plus lger que JSON ;
il peut encoder les principaux types de donnes : null, bool, int, float, fichiers binaires,
tableaux et dictionnaire. Il est galement possible de crer de nouveaux types de donnes ;
il peut encoder et dcoder le message sous la forme dun flux. Il nest donc pas ncessaire de
parser toutes les donnes avant de pouvoir lexploiter, ce qui permet dconomiser lespace
mmoire relativement limit sur plateforme embarque ;
il est disponible sur 50 langages de programmation diffrents. Il existe notamment quatre
implmentations pour C, et deux pour C++11. Certaines dentre elles tant adaptes pour
lembarqu, comme cmp [17] qui donne la possibilit au dveloppeur de redfinir les fichiers
de lecture et dcriture dans le flux.

3 Architecture
Ces recherches prliminaires nous ont bien aid pour dterminer larchitecture de notre solution
de requte/rponse. Une question restait cependant en suspens : comment intgrer cette librairie
au sein de UIC ? Pour rpondre celle-ci, il mtait ncessaire de tout dabord comprendre
larchitecture globale de la solution de HI Corporation.
Larchitecture de UIC est base principalement sur des contextes dinterface UIContext
contenant toute la logique de chargement des fichiers, de mise jour des donnes ainsi que
de laffichage sur un cran. Il est en effet possible pour une application embarque davoir diffrents
contexte, chacun contrlant un cran diffrent. Il est donc important de considrer les UIContext
comme des entits indpendantes et ainsi donner la possibilit au client de selectionner le contexte
vers lequel il souhaite envoyer sa requte. Nous avons donc ajout un champ la structure de
requte reprsentant le contexte en question.
A ce moment, le module de communication avait thoriquement accs au contexte. Comment
maintenant donner la possibilit ce dernier denvoyer des notifications vers les clients connects ?
3 Architecture 37

Comme indiqu dans les premires contraintes, mon intgration se devait de minimiser les
modifications des structures internes. Il ne mtait donc pas permis de passer le serveur au contexte
et aux autres structures pour quils puissent transmettre des messages vers les clients connects ;
et au vue de la quantit de structures diffrentes manipuler, modifier chacune dentre elle aurait
ncessit un travail titanesque et inutile.
En tudiant ces diffrentes structures, je me suis rendu compte quelles partagaient toutes
un pointeur vers linterface IPlatform qui contient toutes les fonctions dpendantes de la cible.
Elment intressant de cette structure : elle contient un champ void *pUserData pass toutes
les fonctions donnant la possibilit au dveloppeur dy mettre ce que bon lui semble.
Si le champ void* pUserData est une structure IPlatform, il est alors possible de chainer
plusieurs IPlatform au moment de lappel dune fonction dpendante de la cible. Ceci permet
notamment dintercepter et de sonder les appels aux fonctions spcifiques la plateforme. Si la
structure IPlatform de sonde contient en plus un pointeur vers le serveur (encore une fois, via
le champ pUserData), celle-ci est alors capable de transmettre une notification sur le rseau ds
quune fonction de plateforme est appele.
Pour donner la possibilit au UIContext ainsi quaux autres structures denvoyer spontanment
des notifications via le server, il suffit alors de :
1. Gnrer la structure IPlatform originale de la cible ;
1 IPlatform * pPlatform = getIPlatform () ;

2. Crer et initialiser le serveur en utilisant la plateforme originale de la cible afin que celui-ci
puisse accder lAPI Socket ;
1 Server * pServer = creerServeur ( pPlatform ) ;

3. Gnrer une structure IPlatform de sonde qui a accs au serveur et qui est donc capable
denvoyer une notification quand lune des fonctions de plateforme est appele, puis dappeler
la fonction de plateforme originale ;
1 IPlatform * pProbedPlatform = g ene re rPl at efo rme So nde ( pServer ) ;

4. Crer et initialiser le context avec la plateforme de sonde. Le contexte peut ainsi transmettre
des donnes ds sa cration ;
1 UIContext * pContext = creerUIContext ( pProbedPlatform ) ;

5. A ce moment l nanmoins, le serveur na pas encore connaissance du contexte, et ne peut


donc pas lui transmettre les requtes si ncessaires. Il faut donc indiquer au serveur quun
contexte a t ajout.
1 l i erContextAuServeur ( pServer , pContext ) ;

Avec cette organisation temporelle, puisque le UIContext est cr aprs la plateforme de sonde,
il est possible de monitorer son fonctionnement ds son allocation sans quil ne soit ncessaire de
modifier son comportement.
38 Chapitre 4. Intgration au sein de UIC

4 Dveloppement
Ayant suivi les mmes contraintes que la phase prcdente, le dveloppement de cette partie
a t sensiblement semblable celle de la librairie de communication quelques dtails prs qui
seront discuts ici.

4.1 Programmation gnrique en C


Lun des cas dutilisation de ce seconde module se rapproche dune organisation client/serveur
que lon trouve dans le milieu du web : le client envoie une requte avec des arguments quelconques
au serveur qui doit ensuite la traiter pour renvoyer une rponse si ncessaire. Le systme de
srialisation des messages (ici MessagePack) tant abstrait pour les deux parties, il est ncessaire
de proposer un ensemble de fonctions charges de, ct client, construire la requte partir
darguments mais galement de, ct serveur, rcuprer les paramtres de cette requte.
Le problme rside dans le fait que ces arguments peuvent tre de diffrents types, ce qui,
puisque le C est un langage de programmation typage fort, impose lcriture de multiples fonctions
au droulement similaire mais linterface diffrente.
1 Requete * creerRequete () ;
2
3 /* Les fonctions suivantes s executent de maniere similaire */
4 void ajouterArgument ( Requete * pThis , String nom , int valeur ) ;
5 void ajouterArgument ( Requete * pThis , String nom , unsigned int valeur ) ;
6 void ajouterArgument ( Requete * pThis , String nom , float valeur ) ;
7 void ajouterArgument ( Requete * pThis , String nom , double valeur ) ;
8 void ajouterArgument ( Requete * pThis , String nom , MaStructure valeur ) ;
9 /* ... */
10
11 /* Les fonctions suivantes s executent de maniere similaire */
12 int recupererArgument ( Requete * pThis , String nom ) ;
13 unsigned int recupererArgument ( Requete * pThis , String nom ) ;
14 float recupererArgument ( Requete * pThis , String nom ) ;
15 double recupererArgument ( Requete * pThis , String nom ) ;
16 MaStructure recupererArgument ( Requete * pThis , String nom ) ;
17 /* ... */

Il est tout fait possible de simplifier lextrme cette interface en exploitant les pointeurs
gnriques :
1 Requete * creerRequete () ;
2
3 void ajouterArgument ( Requete * pThis , String nom ,
4 void * valeur , size_t taille ) ;
5 void recupererArgument ( Requete * pThis , String nom ,
6 void ** valeur , size_t * taille ) ;

Cette dernire mthode a nanmoins deux inconvnients. Tout dabord, la perte du type empche
de vrifier la logique dajout et de rcupration au moment de la compilation et durant lexcution.
Ensuite, lutilisation de pointeurs gnriques limitent ces fonctionnalits aux lvalue.
Ce problme serait relativement rapidement rsolu en C++ laide de la programmation
gnrique :
1 class Requete
2 {
3 public :
4 Dveloppement 39

4
5 /* Une seule implementation est necessaire pour ces fonctions . Le
compilateur s occupe du reste . */
6 template < typename T >
7 void ajouterArgument ( String nom , T valeur ) ;
8
9 template < typename T >
10 T r ecupererArgument ( String nom ) ;
11 };

Il est en fait possible de sapprocher de ce comportement en C laide des macros du mcanisme


de preprocessing sexcutant avant la compilation du code source.
1 # define Macro1 ( arg ) fonction ( arg )
2 # define Macro2 ( arg ) fonction_ ## arg () // Operateur de concatenation
3
4 /* La premiere ligne est remplacee par la deuxieme */
5 Macro1 ( maVariable ) ;
6 fonction ( maVariable )
7
8 /* La premiere ligne est remplacee par la deuxieme */
9 Macro2 ( maVariable ) ;
10 f on c ti o n_maVariable ()

Cet outil de gnration de code se trouve tre suffisamment puissant et versatile pour assurer
quelques principes de programmation gnrique, voici quelques exemples :
1 /* En C ++ */
2 template < typename T >
3 struct Argument
4 {
5 String requete ;
6 T valeur ;
7 void setValeur ( T v ) { valeur = v ; }
8 };

1 /* En C */
2 # define DefinirMaStructure ( type ) typedef struct { \
3 String requete ; \
4 type valeur ; \
5 } MaStructure_ ## type
6
7 typedef unsigned int uint ;
8
9 /* Ces lignes generent le code necessaire pour definir toutes les variantes
de structures */
10 De fi ni rMaStructure ( int ) ;
11 De fi ni rMaStructure ( uint ) ;
12 De fi ni rMaStructure ( float ) ;
13 De fi ni rMaStructure ( bool ) ;
14 /* ... */
15
16 # define DeclarerSetValeur ( type ) void setValeur_ ## type ( MaStructure_ ## type *
pThis , type v )
17 # define DefinirSetValeur ( type ) DeclarerSetValeur ( type ) { pThis - > valeur = v ;
}
40 Chapitre 4. Intgration au sein de UIC

18
19 /* Ces lignes generent le code necessaire pour declarer et definir toutes
les variantes de la fonction setValeur */
20 Decl arerSetValeur ( int )
21 DefinirSetValeur ( int ) ;
22
23 Decl arerSetValeur ( uint ) ;
24 DefinirSetValeur ( uint ) ;
25 /* ... */
26
27 /* Cette macro est utilisee pour appeler la variante de setValeur
correspondant au type */
28 # define SetValeur ( type , pThis , valeur ) void setValeur_ ## type ( pThis , valeur )

Les fonctionnalits gnriques se payent toutefois au prix dune quantit importante de macro
crire, celles-ci pouvant tre trs difficiles implmenter et debugger car la plupart des
environnement de dveloppement ainsi que des debuggers pas--pas ne supportent pas lexpansion
des macros.

5 Preuve de concept
Une fois la phase de dveloppement acheve, jai dvelopp une petite application pour
prsenter ce que la librairie de communication et de sonde pouvait faire une fois interface avec
UIC. Cette application, dveloppe en C++ en utilisant le framework Qt, permettait notamment
de simuler des inputs ainsi que de rcuprer les logs que les UIContext envoyaient par le biais
dappels aux fonctions de linterface IPlatform.
Jai souhait all plus loin en rcuprant le contenu de la pile dappel (la stacktrace ou
backtrace) au moment de lenvoie du log. Deux approches ne ncessitant pas de modifier lappli-
cation existent.
La premire consite envoyer une notification chaque entre et chaque sortie de fonctions.
Sachant que les messages sont reus de manire ordonne, il est possible de suivre en temps rel
ltat de la pile dexcution. Le compilateur gcc autorise ce type de comportement laide du
paramtre de compilation -finstrument-functions [18]. Lorsque ce paramtre est activ, gcc
va insrer du code pour excuter les deux procdures suivantes, respectivement chaque entre de
fonction et chaque sortie de fonction.
1 void _ _ c y g_ p r of i l e_ f u nc _ e nt e r ( void * this_fn , void * call_site ) ; // Fonction
d entree
2 void _ _ c y g_ pr o fi le _f u nc _e xi t ( void * this_fn , void * call_site ) ; // Fonction
de sortie

Sous Windows, il est possible de passer au compiliateur msvc des paramtres /Gh [19] et /GH
pour quil puisse appeller une fonction particulire respectivement chaque entre et sortie de
fonction. Il est toutefois ncessaire dcrire un peu dassembleur pour exploiter au mieux ces deux
fonctions.
1 void __declspec ( naked ) _cdecl _penter ( void ) ; // Fonction d entree (
parametre / Gh )
2 void __declspec ( naked ) _cdecl _pexit ( void ) ; // Fonction de sortie (
parametre / GH )
6 Conclusion 41

La seconde consiste quant elle remonter la pile dexcution seulement lorsque ncessaire,
en loccurrence au moment de lenvoie du log. Cette procdure est nanmoins dpendante du
compilateur qui aura le loisir dorganiser la pile dexcution comme il le souhaite. Des fonctions
sont toutefois disponibles sur les principaux systmes dexploitation : Backtrace de libc sous
Unix [20] et les fonctions StackWalk de la librairie DbgHelp sous Windows [21].
Dans un premier temps, jai opt pour la deuxime approche afin de limiter les transmissions
de messages. Il restait cependant traduire les adresses des fonctions et des lignes en des valeurs
comprhensibles par le dveloppeur. Il se trouve que la librairie DbgHelp de Windows en est
capable au moment du parcours de la pile en se rferrant aux fichiers de debug. Sous Linux, cest
plus compliqu, et il faut notamment utiliser lexcutable addr2line pour effectuer la traduction.

6 Conclusion
Cette seconde phase qui a dur moins de trois semaines a abouti sur une premire intgration
de la librairie de communication au sein de UIC. Il tait alors possible de transmettre des requtes
la cible et dcouter les notifications envoyes spontanment par les diffrentes structures de la
librairie. Il ne restait plus qu dcrire le contenu de ces requtes ainsi que celui de ces notifications
afin de rpondre aux besoins des utilisateurs.
Analyse des usages

Les deux phases prcdentes ont permis de prparer le terrain pour tout un tas dapplications
diffrentes et notamment du prototypage. Il tait maintenant temps de dterminer quelles fonction-
nalits notre outil devait proposer et jai pour cela dcid de suivre les mthodologies tudies et
appliques dans le cadre du Master UXD. Celles-ci consistent aller au contact des utilisateurs
pour comprendre comment ils exploitent le produit afin de mettre en valeur les problmes quils
rencontrent, de sen inspirer pour dvelopper de nouveaux concepts, puis de se rferer ces mmes
utilisateurs ds quil est ncessaire de valider une hypothse.
A premire vue, ce projet semblait titanesque et bien trop difficile finaliser par une personne
en lespace de quelques mois. Lobjectif tant daboutir une premire preuve de concept plutt
qu un rapport danalyse complet, jai prfr adopter une approche verticale et spcifique par
itrations plutt quhorizontale et exhaustive.
Ainsi, une premire phase de recherche qui a dur un bon mois a permis de dfricher le terrain
de manire gnrale. Aprs avoir choisi le concept le plus pertinent et celui pouvant apporter les
meilleurs rsultats en un minimum de temps, une deuxime phase danalyse et didation sest
concentre sur ce concept pour pouvoir clarifier les zones dombre avant de dboucher sur un
prototype fonctionnel. Cette priode de mon stage a ainsi vu senchainer des phases de recherche,
didation et de prototypage sur des concepts de plus en plus prcis ; le tout ponctu de tests
utilisateurs pour sassurer que le projet allait dans la bonne direction.
Je vous invite consulter le second rapport pour comprendre comment jai appliqu cette
mthodologie ce projet.
Premier prototype

1 Introduction

Une fois les premires ides mises plat, la mthodologie UX impose la cration de prototypes
qui seront ensuite tests par les utilisateurs finaux, ceci afin de vrifier les hypothses de comporte-
ment. Aprs avoir ralis quelques prototypes statiques avec le combo papier/crayon, je me suis
attel au dveloppement dun premier prototype interactif que lutilisateur pourra parcourir durant
les tests.

2 Choix des technologies

2.1 Contraintes
Avant de foncer tte baisse dans lcriture du code source, il tait ncessaire de choisir les
technologies qui allaient nous accompagner pendant les prochaines phases de dveloppement.
Les premiers lments graphiques raliss pendant la phase didation decrivaient des com-
posants dinterface complexes dots de nombreuses interactions comme des graphiques et des
diagrammes. Les technologies selectionnes devaient permettre de facilement implmenter ce type
dlments.
46 Chapitre 6. Premier prototype

Quelques composants graphiques prvus pour loutil prototyp.

Ces technologies devaient tre galement suffisamment simples daccs pour dune part, me
permettre de rapidement implmenter mes ides et, dautre part, donner la possibilit dautres
dveloppeurs de contribuer au projet. Enfin, il tait galement primordial de dvelopper cette
application avec des technologies multi-plateforme afin de toucher un maximum dutilisateurs.

2.2 Recherches
Les dveloppeurs de lentreprise travaillent principalement sur le framework Qt, plateforme
que javais dj eue loccasion dexploiter lors de diffrents projets personnels et professionnels.
Au cours de ces projets, je me suis toutefois rendu compte de la difficult implmenter des
interfaces graphiques la fois fine et complexes, la faute un manque dAPI ddie et labsence
de communaut partageant ses widgets.
Au contraire, la communaut issue du dveloppement web est extrmement dynamique et
nhsite pas diffuser ses crations. A ce titre, prs dun demi-million de modules front-end et
back-end sont proposs sur npm [22], le principal gestionnaire de paquet de nodejs. De la mme
manire, de nombreux framerworks graphiques aux licenses permissives comme Angular sont
disponibles gratuitement. De plus, les dernires moutures du HTML, du CSS et du JavaScript
ont dj fait leur preuve dans le domaine des interface graphiques dynamiques, il semblait donc
intressant de se pencher sur ces technologies.
La principale limitation de ces langages est quils ncessitent un navigateur web charg dinter-
prter lapplication. Or, le but nest pas de faire un site web, mais une application autonome qui
nhsitera pas saccorder avec les bonnes pratiques de chacun des systmes dexploitation en
matire de look n feel.
Mes recherches ont alors mis en valeur deux technologies conues pour crer des applications
multi-plateformes laide de langages web : Electron, maintenu par GitHub, et NW.js. Ces deux
solutions fonctionnent de manire analogue : lapplication est compose dun navigateur web
complet, en loccurrence Chromium, qui affiche un site web crit en HTML/CSS/JS, dune API qui
fait le pont entre front-end et le back-end dvelopp au dessus de node.js, et dune API systme qui
2 Choix des technologies 47

permet linterface dappeler des fonctions du systme dexploitation.


Electron et NW.js ne permettent pas dcrire linterface graphique, le dveloppeur est ici
compltement libre dans son choix de technologie. Il est toujours possible dcrire toute linterface
en HTML/CSS/JS mais ce serait passer ct de nombreux frameworks dinterface chargs de
structurer toute lapplication afin quelle soit facile maintenir. Les parties suivantes illustrent
certaines des technologies adoptes pour ce projet.
Les diffrences entre ces solutions sont toutefois assez subtiles, trop subtiles mme pour pouvoir
ce stade proposer un choix objectif [23]. Cependant, Electron semblait tre port par une bien
meilleure communaut, compose notamment de Microsoft qui a dvelopp Visual Studio Code
avec cette technologie.

Node.js
On ne prsente plus cet environnement qui depuis 2009 permet aux dveloppeurs dexploiter le
langage JavaScript pour implmenter leur back-end. node.js est bas sur le moteur dexcution V8,
conu initialement pour Google Chrome, qui assure des performances intressantes en compilant le
code JavaScript plutt quen linterprtant.

Electron
Une application Electron est compose de deux types de processus [24]. Lunique processus
principal a accs lenvironnement nodejs et aux API systmes fournies par Electron, celui-ci
est execut ds le lancement de lapplication. Ce processus peut invoquer autant de processus de
rendus que necessaire, chacun tant une application web affiche par une fentre Chromium dedie.
Tous ces processus peuvent communiquer entre eux au travers dune API IPC.
La principale limitation de cette solution est la ncessit de fournir le navigateur Chromium,
le moteur de JavaScript V8 ainsi que nodejs avec lapplication web, raison pour laquelle les
excutables peuvent facilement atteindre plusieurs centaines de mga-octets, sans compter les
diverses ressources.

React
React est une librairie (ou framework selon les developpeurs...) JavaScript dinterface gra-
phique dont lobjectif est de simplifier la cration et la maintenance de larges applications webs
dynamiques [25]. Cette solution est spcifique au dveloppement de linterface, la composante Vue
du paradigme Modle-Vue-Controlleur, et mme sil est techniquement possible de dvelopper
toute une application avec React, il est plus intressant de le coupler avec dautres technologies.
Une application developpe avec React est constitue de composants graphiques indpendants
et autonomes. Chacun de ces modules est en fait un objet ou une fonction JavaScript charge de
gnrer le code HTML/CSS spcifique son fonctionnement. Ces lments graphiques peuvent
tre eux-mmes constitus dautres composants React, ce qui permet de dsolidariser les diffrents
modules.
Ces composants peuvent tre crits en JavaScript pure ou en JSX, une extension de ce dernier
supportant la syntaxe du HTML afin de simplifier lcriture de page web. Voici un court exemple
en JavaScript (norme ES6) et JSX :
1 import React from " react " ;
2
3 class Bouton extends React . Component {
4 render () {
5 return < button > Mon Boutton </ button >
6 }
7 }
8
9 /* Page contient un Bouton */
48 Chapitre 6. Premier prototype

10 class Page extends React . Component {


11 render () {
12 return (
13 <div >
14 Voici un boutton :
15 < Bouton / >
16 </ div >
17 )
18 }
19 }

Contrairement dautres librairies dinterface comme jQuery ou Angular, les composants


React ne manipulent pas directement le DOM de la page, ainsi, le code HTML/CSS rendu par le
composant nest pas ncessairement inclus au sein de la page web. Au lieu de cela, React manipule
un DOM virtuel beaucoup plus performant qui va calculer les diffrences entre le DOM courant
et les modifications apportes par les composants afin de cibler et minimiser les modifications du
vrai DOM. Ainsi, le dveloppeur na pas se soucier de lordre de mise jour des componsants :
ds quun lment interne est modifi, tout larbre des composants est recr et React se dbrouille
ensuite pour seulement mettre jour les lments ncessaires de la page. A premire vue, cette
opration peut sembler extrmement coteuse, mais cette librairie a plus dun tour dans son sac
pour gagner en performance, comme nous le verrons plus tard.
La maintenabilit de lapplication est quant a elle assure en partie par un flux de donnes et
dvnements unidirectionnel. Au moment du rendu dun composant, celui-ci passe des parametres
(appels props) a ses enfants : cest le seul moment ou un composant pre peut modifier un
composant fils. Ces paramtre peuvent prendre diffrentes formes : valeurs numriques, objets,
classes ou encore fonctions de callback que lenfant peut appeler pour notifier un de ses anctres.
La transmission de donnes nest donc possible que de parent enfant tandis que les vnements
suivent un chemin allant de lenfant vers un anctre. En plus de cette spcificit, chaque composant
peut manipuler un objet state reprsentant son tat interne. Cet objet nest accessible que par son
propritaire qui peut alors le modifier pour enclencher le rendu de la totalit des composants et
donc la modification de la page.
Ce paradigme de dveloppement volontairement limitant peut rebuter certains. React donne
bien entendu la possibilit de passer outre cette organisation mais ce serait prendre le risque de voir
son application transforme en plat de spaghettis.
Redux
Comme dcrit prcdemment, chaque composant a la possibilit de stocker et modifier un tat
interne. Dans un sens, cette fonctionnalit est trs intressante car elle rend indpendant chaque
composant. Mais gare aux abus, rien nempche en effet le dveloppeur dy inclure tout et nimporte
quoi. En loccurrence, o devraient tre entreposes les donnes spcifiques lapplication qui
doivent tre partages avec de multiples composants ? Les inclure dans les composants serait
contraire au principe de dcouplage entre modle et vue et nest pas directement compatible avec le
flux unidirectionnel. Cest cette volont de dcoupler logique et donne qui incite les utilisateurs de
React a dnicher des solutions de gestion de modle fonctionnant de paire avec cette librairie.
Parmi ces solutions, on retrouve le populaire Flux galement maintenu par Facebook [26].
Flux nest pas une librairie proprement parler, mais plutt un concept dcrivant une organisation
possible du systme de gestion de modle dune application graphique. Tout comme React, Flux
est bas sur un flux unidirectionnel dvnements. Linterface ainsi que dautres entites peuvent
envoyer des actions un dispatcher charg de diffuser cet vnements plusieurs stores. Chaque
store est une entit contenant une partie des modles manipuls par lapplication. Les stores notifient
ensuite linterface dun changement dans son tat interne, lincitant ainsi se mettre jour.
2 Choix des technologies 49

Redux [27] est une implementation de Flux, gnralement choisie pour sa documentation
claire et sa facilit dinterface avec React. Cette solution exploite donc les concepts dactions, de
dispatcher et de store, et en ajoute trois nouveaux quil est ncessaire dassimiler.
La modification dun store en rponse une action ne peut se faire quau moyen de fonctions
appeles reducer. Ces fonctions, implementes par le dveloppeur, doivent tre "pures", cest
dire quelles ne sont censes modifier ltat du store qu partir de laction fournie en argument et
rien dautre, ceci afin de rendre indpendant le store de tout effet de bord et donc de simplifier sa
maintenance et son test.
Lorganisation interne des stores doit tre de plus compltement abstraite pour la vue, encore
une fois pour dcoupler leur fonctionnement. Les selectors sont les fonctions chargs de proposer a
la vue une interface simple pour accder aux donnes du store. Si le store est une base de donne,
alors un selector est une requte SELECT.
Enfin, les middlewares, placs entre le dispatcher et le reducer, peuvent intercepter, modifier et
crer des actions. Tous les effets de bord, comme les appels dAPI externes, doivent tre excuts
au sein de ces entits.
Lintegration au sein de React peut se faire tres simplement laide de fonctions prvues cet
effet. Cette API permet notamment de faire la distinction entre les containers et les composants de
presentation : les premiers ont leur tat intgr au store et en sont donc dpendants, les seconds ne
dpendant que des props et de leur tat interne.
La principale limitation de React et Redux rside malheureusement dans le nombre de concepts
comprendre et matriser pour entamer avec srnit le dveloppement dune application graphique.

d3
d3js [28] est lune des librairies open-source daffichage de donnes les plus populaires. Elle
permet de trs facilement lier des donnes des lments du DOM pour raliser des graphiques
et organigrammes dynamiques, anims et interactifs et ce laide dune API dclarative. On la
retrouve le plus souvant de paire avec le format dimage vectoriel SVG, qui peut faire partie du
DOM dune page web.
De nombreux modules dvelopps par la communaut sont joints a d3js pour simplifier la
cration de graphes temporels, la gestion de la physique et les interactions complexes.

WebPack
La principale force de la communaut JavaScript, savoir lutilisation et le partage abondants
de petits modules qui sassemblent pour former des logiciels plus complexes la manire de la
philosophie Unix, peut devenir une grosse faiblesse au moment du passage en production [29].
Tout dabord, charge au dveloppeur de lister lensemble des modules utiliss - parfois plusieurs
centaines - dans lordre des dpendances, et ce sous la forme de balises script intgres au sein
de la page HTML. En outre, les variables globales tant partages entre tous les modules, il faut
galement sassurer que ces dpendances ne se marchent pas sur les pieds en manipulant les mmes
variables. Enfin, le chargement successif de tous ces modules ncessite plusieurs appels HTTP qui,
mme si effectus en local, se rvlent tre trs chronophages.
WebPack [30] propose un solution tous ces problmes. Il navigue le code source de lapplica-
tion de manire statique afin dtablir un graphe de dpendance de tous les modules. Ce graphe
est ensuite parcouru et chaque fichier, que ce soit du code source ou des donnes multimdia, se
voit trait par un plugin. Les plugins conus pour les fichiers JavaScript peuvent notamment les
minimifier pour rduire la taille du code source ainsi que rendre la rtro-ingnieurie plus complexe,
ou encore les encapsuler dans un conteneur indpendant afin dviter les partages de variables
globales. Le plugin exporte ensuite une chaine de caractre qui sera incluse au sein dun unique
fichier source final contenant alors la totalit de lapplication. Une seule requte HTTP est ainsi
50 Chapitre 6. Premier prototype

suffisante pour inclure tous les modules de lapplication.

3 Dveloppement
Aprs avoir tudi et selectionn les principales technologies, je me suis attel au dveloppement
de linterface en suivant les premires spcifications graphiques dfinies durant la prcdente
phase de design. Ce fut notamment loccasion de me familiariser avec toutes ces librairies au
fonctionnement tres diffrent et de massurer quelles taient aussi simples prendre en main
quelles le prtendent. Cela ma pris plusieurs semaines pour comprendre une partie des subtilits
de chacune dentre elles, en voici un rapide resum.
Une fois maitris, le combo React/Redux permet une organisation trs fine et dcouple de
larchitecture logicielle. Le paradigme de dveloppement par composant simplifie grandement
leur conception ainsi que leur partage, et le flux unidirectionnel permet de clairement suivre les
changes de donnes et les modifications dtat. Cependant, limplmentation des fonctionnalits
peut rapidement devenir verbeux : il ne faut certes que quelques lignes pour faire un composant
basique mais il est ncessaire dcrire plusieurs fonctions rparties sur diffrents fichiers pour
respecter le flux unidirectionnel. Cest dautant plus le cas lorsque lon souhaite programmer des
animations, lments pourtant rcurrents des interfaces qui se transforment en vritable cauchemard.
D3js ncessite egalement un temps dadaptation mais, une fois cette priode passe, la reali-
sation de graphiques sen voit tres simplifie. Cependant, lintgration au sein de React relve du
dfi [31]. En effet, React se veut seul matre du DOM alors que d3js ne fonctionne quen accdant
directement au DOM. Deux approches sont disponibles pour faire coexister ces deux librairies. La
premire consiste gentillement demander React de laisser certaines manipulations locales du
DOM la charge de d3js. La deuxime propose de nutiliser que les modules de calcul de d3js et
dexploiter React pour afficher du SVG en modifiant le DOM.
La premire a lavantage dtre tres simple mettre en place et de pouvoir facilement partager
ses graphiques avec la communaut d3js mais son decouplage avec React rend son intgration
difficile sur le long terme. La deuxime quant elle respecte larchitecture et les principes de React
mais ncessite de rcrire la quasi-totalit des fonctionnalits graphiques de d3js en exploitant le
principe des composants. Bien heureusement, de nombreux developpers ont rencontr ce problme
auparavant et ont dj partag des composants React bass sur cette deuxime approche.

4 Tests Utilisateurs
Une fois ce premier prototype finalis laide de fausses donnes et dlments dinterface
factices, ce qui a ncessit un bon mois de travail, il tait important de faire tester son interface
des utilisateurs pour vrifier les hypotheses de design qui ont abouti aux premieres specifications
graphiques. Le droulement et les conclusions de ce test sont disponibles dans le second rapport.
Second prototype

1 Introduction
Bien que le prototype prcdent ait t test laide de fausses donnes, il a permis de mettre
en valeur des sources potentielles derreurs et dincomprhensions dans linterface. Cependant, afin
de vrifier de manire plus fidle nos intuitions, il tait maintenant ncessaire de dvelopper un
nouveau prototype manipulant des donnes relles. Voici un rsum des fonctionnalits attendues.
Ce prototype devait tre capable de se connecter la cible pour pouvoir rcuprer un certain
nombre de donnes relatives au fonctionnement de lapplication comme les logs, la frquence
daffichage, lutilisation de la mmoire ou le temps pass dans les fonctions essentielles. Loutil
devait galement tre en mesure de reconstruire ltat un instant t des principaux objets manipuls
par UIC. Enfin, il tait important quil comporte les prmices de fonctionnalits danalyse du
comportement de lapplication, de contrle dinterface et de chargement/sauvegarde des sessions
de debug.
Son interface graphique exploitait les mmes technologies que le prototype prcdent mais
nous avons fait le choix de sparer au maximum les fonctions de communication et danalyse des
donnes proprement parler et ce pour dcoupler ces deux lments afin de pouvoir changer de
technologie dinterface si ncessaire.

2 Librairie dAnalyse
Lun des plus gros morceaux de ce projet fut le back-end de linterface graphique charg, dans
le cadre de ce prototype, de rcuprer et dentreposer toutes les donnes transmises par la cible afin
de les traiter et les analyser ds que linterface graphique en avait besoin.

2.1 Architecture
Pour marquer une nette sparation entre le front-end et le back-end, nous avons encapsul
ce dernier au sein dune librairie, sobrement appelle "Analysis", charge dynamiquement par
linterface graphique. Linterface pourra communiquer avec le back-end par le biais de deux APIs :
une premire compose de fonctions de requte que linterface peut appeler tout moment et
52 Chapitre 7. Second prototype

une seconde forme de fonctions de callback permettant au back-end denvoyer des donnes vers
linterface de manire asynchrone.

La base de donnes reprsentant lvolution de ltat de lapplication embarque constitue le


coeur de cette librairie. Pour limiter les envoies de donnes depuis la cible, nous avons opt pour un
systme de diffrence : ds quun objet de UIC change dtat, un message indiquant seulement la
modification est transmis. Ce dernier dcrit linstant t de la modification, lidentificateur de lobjet
modifi, lidentificateur de la proprit modifie et la nouvelle valeur de cette proprit. Tous ces
messages sont alors entreposs dans un ensemble de structures de donnes dont lorganisation
dpendra de limplmentation souhaite.
Lorsque linterface souhaite reconstruire ltat du systme un instant t, la librairie na qu
parcourir lensemble des proprits des objets puis rcuprer la valeur indique par le dernier
message de modification reu avant linstant t. Cet algorithme assez simple ne fonctionne toutefois
que sous certaines conditions. Il est dabord ncessaire quau moment de la reconstrution toutes les
modifications envoyes avant linstant t ait t reues par lapplication. Puisque notre prototype est
bas sur le protocole TCP/IP qui assure la bonne rception des messages et prserve leur ordre, si
lapplication a receptionn un message estampill dun instant t 0 t, alors toutes les modifications
avant t ont bien t reus, et la construction sera cohrente.
Ensuite, les messages de modification dun couple objet/proprit doivent avoir des instants
t distincts pour viter les ambiguits au moment de la reconstruction. Une horloge fournissant
une valeur la microseconde prs devrait tre suffisante pour assurer cette distinction mais, si ce
nest pas possible, le protocole TCP/IP assure ici encore le bon ordre de reception messages. Si
toutefois les prochains dveloppeurs souhaitent saffranchir de la garantie de prservation de lordre
de reception, un simple identificateur unique de message, incrment chaque envoi de la cible,
permettrait de rsoudre lambiguit.
Enfin, ce mcanisme ne connait que les paramtres, les objets et les valeurs dont il a dj reu
un message de modification. Ainsi, si un paramtre na jamais t modifi, lalgorithme naura pas
connaissance de sa valeur par dfaut, auquel cas la reconstruction sera incomplte. Un systme
effectuant un snapshot au moment de la connexion de linterface la cible permettrait dindiquer
lensemble des paramtres et objets ainsi que leur valeur au dbut de la session de test. Il faut
toutefois sassurer que le snapshot est bien cohrent et ce en interdisant toute modification des
objets pendant la ralisation et lenvoi du snapshot.

En outre, voici quelques prcisions sur les diffrents champs du message dcrivant une modifi-
cation. Les horloges de la cible et de la librairie excute sur lordinateur de bureau nont pas besoin
dtre synchronises pour que lapplication fonctionne. Ainsi, linstant t peut tre dtermin sur la
cible partir de nimporte quel rfrentiel et il est important de donner la libert dimplmentation
au dveloppeur du moment quil sassure que les t sont bien strictement croissants tout au long de
la session de test.
De plus, le couple compos de lidentificateur de lobjet modifi et de celui de la proprit
modifie doit constituer une cl primaire en ce sens quil doit permettre de dterminer sans
ambiguit la liste des messages de modification pour assurer la reconstruction. Les proprits sont
ici reprsentes par une simple chaine de caractres, la manire dun identificateur de variable,
cependant les objets de UIC nont malheureusement pas tous des identificateurs distincts et en
inclure ncessiterait une importante charge de travail. Pour ce premier prototype, nous avons dcid
quun objet UIC serait identifi par son pointeur ce qui assure son unicit du moment que tous les
objets appartiennent au mme espace dadressage virtuel. Ce choix ne fonctionne toutefois pas si
lobjet est dplac en mmoire que ce soit par simple copie ou par dstruction puis reconstruction
de lobjet mais, heureusement pour nous, UIC interdit ce type dopration.
2 Librairie dAnalyse 53

2.2 Proposition dimplmentation


Bien que le choix des structures de donnes peut tre libre, il est important de les slectionner
en prenant en compte leurs avantages et leurs limitations. En effet, les applications embarques les
plus complexes peuvent contenir un nombre de couples distincts de lordre de la centaine de millier
et jusqu une soixante de modification par seconde pour chacun. Compte-tenu de ces quantits,
trois oprations sont notamment susceptibles de considrablement ralentir la reconstruction.
La premire est la rcupration de la liste des messages de modification associe un couple
objet/proprit. Une manire doptimiser ce type dopration est de tenir un dictionnaire associant
un couple sa liste de messages, lutilisation de ce type de structure assurerait une complexit
temporelle moyenne constante. En C++, cela donnerait :
1 std :: unordered_map < std :: pair < ObjectKey , ParamKey > , Messages >

La seconde est lie la structure assez verticale des objets de UIC : un UIContext contient
plusieurs Screens qui compose des Objects forms de Plugins dont certains peuvent tre lis
dautres Plugins. Ces liens peuvent tre dtermins laide de cls trangres prenant la forme
dune proprit dun des objets, par exemple un Screen peut avoir une proprit parent pointant
vers le UIContext qui le contient. Dans ce cas, la base de donne est normalise et sa structure suit
un modle horizontal. Au moment de la reconstruction par contre, il est ncessaire de rapidement
reformer la hierarchie, ce qui ncessite lobtention dun objet partir de son identificateur. L
encore, un dictionnaire associant une cl dobjet son objet assurerait une complexit constante.
En C++, cela donnerait :
1 std :: unordered_map < ObjectKey , Object >

Enfin, la troisime opration est lobtention du message de modification contenant la valeur que
la proprit avait linstant t. Ceci peut tre effectu en temps logarithmique si la structure utilise
est par exemple un tableau tri (recherche dichotomique) ou encore un arbre binaire quilibr.
Cette librairie tant excute sur un ordinateur standard, nous ntions plus limits par un
quelconque langage de programmation. Nous avons donc opt pour du C++11 afin de profiter des
spcificits de ce langage ainsi que de la librairie std.

2.3 Electron et DLL


Limplmentation de cette architecture sest droule sans encombre particulier. Cependant,
lintgration au sein de lapplication graphique a t lgrement chaotique.
Il existe trois manires dappeler des fonctions externes depuis une application base sur nodejs
[32]. La premire, la plus gnrale, consiste encapsuler ces fonctions au sein dun excutable
qui sera lanc dans un processus spar ; une interface base sur un mcanisme de communication
interprocessus, comme un pipe, permettant dappeler ces fonctions. Elle a lavantage de pouvoir
fonctionner dans de multiples contextes, notamment lorsque la technologie utilise ne permet pas
dappeller des DLL, mais elle ncessite de mettre en place tout un protocole de communication et
de synchronisation entre linterface graphique et le processus externe.
La seconde propose dutiliser une DLL classique qui sera lue par un paquet node prvu cette
effet, comme le module node-ffi. Cette mthode sduit par le fait que la DLL na pas besoin
dtre adapte pour lapplication mais elle souffre de la surcharge associe au module de lecture de
la DLL ce qui peut rendre in fine cette mthode peu performante.
Enfin, la troisime mthode, la plus spcifique nodejs, consiste crer une DLL compile
spcifiquement pour le moteur JavaScript V8 que nodejs peut directement lire. Contrairement la
54 Chapitre 7. Second prototype

mthode prcdente, la DLL est ici lue sans passer par un quelconque intermdiaire et elle a de
plus accs lAPI du moteur V8 ce qui lui vaut dtre en thorie lapproche la plus performante et
la plus adapte des trois. Ce gain de performance se paye par contre au prix dune modification de
la chaine de compilation de la librairie ainsi que de son API.
Comme nous tions toujours en tape de prototypage, nous avons encore une fois opt pour
la mthode permettant limplmentation la plus rapide. En loccurrence, la seconde ne ncessitait
pas de modifier dune quelconque manire la libriarie en elle-mme et il suffisait seulement de
saccotumer lAPI de node-ffi [33] pour povoir rapidement accder aux fonctionnalits offertes
par la librairie. Cest la raison pour laquelle nous avons finalement implment cette approche.
Cest malheureusement ce moment que le dveloppement a connu plus de bas que de
hauts. Lappel de fonctions incluses dans DLL depuis un excutable qui nutilise pas les mmes
technologies est gnralement assez prilleux. Il faut en effet apporter une attention trs fine aux
pointeurs et structures de donnes manipules au sein des deux parties sans quoi un Segmentation
Fault ou une incohrence de donne peut trs vite arriver. Si ce cas arrive, et il arrivera trs
probablement si les structures contiennent de nombreuses indirections par pointeur comme dans ce
projet, il est trs difficile de debugguer linterface en elle-mme.
A ce titre, un problme relatif la gestion des structures entre les langages C et C++ nous a
souvent donn du fil retordre. Il faut savoir que linterface dune librairie ne peut qutre constitue
de fonctions crites en C ; le C++ est ensuite capable de caster la structure vers un objet C++ si
ncessaire. Ainsi, node-ffi considre que les pointeurs redirigent vers des structures C tandis que
la librairie interpte ces mmes pointeurs comme des structures C++. Il faut alors sassurer que ces
structures ont bien la mme organisation au sein de la mmoire.
Prenons lexemple suivant :
1 /* C ++ */
2 struct cplusplus
3 {
4 cplusplus ( int a ) ;
5 ~ cplusplus () ;
6 int a ;
7 };
8
9 /* C */
10 typedef struct
11 {
12 int a ;
13 } c;

Les structures cplusplus et c sont (normalement) organises de la mme manire en mmoire,


malgr le fait que la version C++ dfinit galement des fonctions. Les adresses de ces fonctions ne
sont en fait pas incluses au sein de la structure mmoire.
Prenons prsent lexemple suivant :
1 /* C ++ */
2 struct cplusplus
3 {
4 cplusplus ( int a ) ;
5 ~ cplusplus () ;
6 virtual void func () ;
7 int a ;
8 };
9
10 struct cplusplus_2 : public cplusplus
11 {
3 Gestionnaire derreur 55

12 cplusplus_2 ( int a ) ;
13 ~ cplusplus_2 () ;
14 void func () override ;
15 })
16
17 /* C */
18 typedef struct
19 {
20 int a ;
21 } c;

Lorsque la structure cplusplus appelle func(), le programme doit dterminer dynamiquement


si la fonction appeler est celle de cplusplus ou celle de cplusplus_2. Le langage C++ utilise
pour cela une virtual method table : le compilateur alloue un espace au sein de la structure de
lobjet pour conserver le pointeur de la fonction appeler.
Ainsi, lorsquun objet cplusplus_2 est instanti, deux espaces mmoire sont reservs : lun
pour stocker la variable int a et lautre pour entreposer le pointeur vers la fonction cplusplus_2::func.
La mme approche est effectue pour instantier un object cplusplus.
Les structures cplusplus_2 et c nont alors plus du tout la mme structure mmoire et il
devient beaucoup plus difficile de les faire transiter aux travers dune interface DLL. Il fallait faire
extrmement attention ce comportement pour viter de facheux bugs.

3 Gestionnaire derreur
Lors de la phase danalyse, les dveloppeurs ont remont de multiples problmes relatifs
la gestion des erreurs. En effet, toutes les fonctions formant lAPI publique de UIC retournent
un enum indiquant si la procdure sest excute avec succs ou un code dcrivant lerreur le cas
chant. Bien que trs simple mettre en place, lutilisation dun simple enum porte de nombreux
dfauts [34] : il ne permet pas de vhiculer avec prcision, nuance et contexte la cause de lerreur et
il ne peut indiquer, dans le cas commun dun enchainement de fonctions, laquelle a bloqu le bon
fonctionnement des procdures.

3.1 Architecture
Pour proposer une premire solution ces problmes, je me suis inspir de deux solutions qui
ont dj fait leur preuve. La premire, incluse dans la totalit des librairies dApple, exploite un objet
plutt quun simple integer pour reprsenter lerreur. Comme indiqu dans leur documentation
[35], un objet a lavantage de pouvoir encapsuler de nombreuses donnes htrognes supportant
la comprhension du problme comme des messages derreur ou encore la ligne qui a bloqu
lexcution de la fonction. Ses fonctionnalits peuvent galement tre tendues laide de mthodes
ddies par exemple laffichage de lerreur.
Cependant, les diffrentes API dApple sont conues pour prendre en compte ce systme de
gestion des erreurs, cest ainsi que les fonctions critiques peuvent remplir un objet derreur pass
en argument si ncessaire. Il ntait par contre pas envisageable de modifier la totalit des fonctions
publiques de UIC pour prendre en compte ce nouveau systme. Cest alors quintervient la seconde
source dinspiration.
OpenSSL [36] est une librairie open-source de chiffrement dveloppe en C utilise au sein de
nombreux projets de grande ampleur. Ses dveloppeurs ont bien compris quil nest pas possible de
reprsenter une cascade derreurs au travers dune seule donne et ont ainsi conu un gestionnaire
derreur exploitant une queue dobjets, chacun reprsentant une unique erreur.
56 Chapitre 7. Second prototype

Pour ne pas surcharger lAPI, cette queue nest pas passe en argument de chaque fonction.
Au lieu de cela, elle est propose sous la forme dun singleton permettant chaque portion de
lapplication dy avoir accs, tandis quun simple boolen retourn par les fonctions critiques
tmoigne de leur bonne excution. Pour fonctionner dans un environnement multi-thread, il est
ncessaire de prendre en compte les diffrentes piles dexcution et donc de sparer lenchainement
des codes derreur. Ceci implique lutilisation de plusieurs queues derreur (une par thread) et dun
mcanisme permettant dobtenir la queue relative au thread courrant. Chaque thread possedant sa
propre pile, il est tout fait possible de stocker cette queue dans sa mmoire ddie. Dun point
de vue de limplmentation cependant, chaque file dexcution aurait manipuler une variable
distincte pour spcifier sa propre queue.
Le mcanisme de Thread-Local Storage (TLS) [37] permet quant lui de rfrencer des
variables locales au thread comme si elles taient globales. Le dveloppeur a donc limpression de
manipuler une unique variable globale alors que chaque thread possde sa propre copie distincte.
OpenSSL exploite cette mthode pour simplifier sa gestion des queues derreur, des API systmes
tant disponibles sur plateformes Windows et POSIX.

3.2 Dveloppement
Le gestionnaire derreur dvelopp implmente un systme de singleton local chaque thread,
chaque singleton tant charg dorganiser sa queue derreur. Ceci a pu tre ralis laide des
mmes fonctions de TLS que pour OpenSSL, le tout bien entendu abstrait au sein de linterface
IPlatform. Une API a ensuite t conue pour simplifier lajout derreur au sein de la queue ainsi
que son parcours.
Il reste prsent intgrer cette nouvelle organisation des erreurs au sein des fonctions de UIC
dj existante, ce qui ncessitera trs certainement un trs long et laborieux travail.
4 Interface Graphique 57

4 Interface Graphique
Linterface graphique a t developpe en parallle des modules dcrits prcdemment, lint-
gration de la DLL au sein de la paire React/Redux sest dailleurs faite assez rapidement. Cependant,
cette phase de developpement a t trs souvent ralentie par dimportants problmes de perfor-
mance rendant la page web excessivement lente et donc inutilisable. La page "Timeline" accueillant
plusieurs graphiques dynamiques a notamment t le thtre du plus grand nombre de modifications
darchitecture et doptimisations.

Page "Timeline" du second prototype contenant de multiples composants graphiques


complexes.

4.1 Dveloppement
La premire version de cette page a t developpe laide de la librairie react-timeseries
[38] qui exploite d3js et React pour afficher et mettre jour des graphes temporels en SVG.
Cependant, cette premire itration avait comme defaut dtre beaucoup trop lente pour tre
utilisable efficacement lorsque beaucoup dlments taient affichs. A ce stade, il tait assez
difficile de dterminer les vritables causes de ces ralentissements : taient-ils ds mes algorithmes
daffichage ? la librairie react-timeseries ? React ? ou encore au JavaScript ?
Le navigateur Chromium comporte un profiler affichant la dure de toutes les fonctions appeles
pendant une periode fixe. Cet outil, qui ma accompagn pendant toute la dure du dveloppement
de linterface, ma permis de mieux cibler la cause des problmes et de comparer limpact de mes
diffrentes optimisations.
58 Chapitre 7. Second prototype

Profiler de Chromium.

React propose quant lui un ensemble de fonctions permettant de mesurer lefficacit du rendu
de larbre. Pour rappel, chaque modification de ltat dun composant, React relance par dfaut
une procedure de rendu de la totalit des composants. Cependant, les composants qui nont pas subi
de modifications de state ou de props ne sont pas rendus nouveau. Cette spcificit constitue le
principal moyen doptimiser une application React : il faut sassurer que les composants qui nont
pas t modifis ne soient pas rendus pour rien, et ces fonctions permettent justement de dtecter
les rendus inutiles.

Profiler de React. On voit que 15ms ont t gches en mettant inutilement jour le
composant App situ la racine de larbre de rendu.

Appliqu la page en question, cet outil a mis en valeur un grand nombre de rendus inutiles.
En tudiant de plus prs la raison de ces rendus, jai pu me rendre compte que React vrifiait les
modifications des state et props en effectuant une comparaison par rfrence et non par valeur.
Par exemple, dans le listing suivant, la variable style est recre chaque rendu du composant.
React considre donc que cette variable est diffrente chaque rendu et quil faut reconstruire le
composant, inutilement.
1 function render ()
2 {
3 /* Variable Locale */
4 let style = { backgroundColor : " blue " };
5
6 /* Ce div est rendu a chaque fois */
7 return < div style ={ style } / >
8 }

Au contraire, dans le listing suivant, la variable style ne change pas de rfrence donc le
composant ne sera rendu quune seule fois.
1 /* Variable Globale */
4 Interface Graphique 59

2 let style = { backgroundColor : " blue " };


3
4 function render ()
5 {
6 /* Ce div est n est rendu qu une seule fois */
7 return < div style ={ style } / >
8 }

Ce cas simple, mais tout de mme frquent, peut tre facilement rsolu en faisant attention au
cycle de vie de chaque objet pass aux composants React sous la forme de props.
Il est en fait possible dimposer une vrification par valeur mais celle par rfrence a lavantage
dtre extrmement rapide. Le store par exemple entrepose une assez grosse quantit de donnes - il
peut notamment contenir tout ce quil sest pass au sein de la cible pendant totalit de la session de
test ! Celui-ci tant consult chaque rendu de composant, une vrification par valeur ncessiterait
de parcourir la totali du store pour dterminer si le composant doit tre mis jour ou non. Au
contraire, une vrification par rfrence est immdiate.
Linconvnient apparait bien entendu au moment de la mise jour du store. En effet, modifier
un objet ne change pas sa rfrence, le seul moyen donc dindiquer aux composants que le store a
bien t altr, cest en lassociant une nouvelle rfrence ce qui ncessite malheureusement de
cloner la totalit du store. En pratique, il y a moins de mises jour de store que de mises jour
des composants et, dans le pire des cas, cloner un objet est plus rapide queffectuer des oprations
de vrification dgalit, ce qui justifie tout fait la copie du store chaque modification pour
lassocier une nouvelle rfrence. Certaines parties du store de ce projet ont toutefois souffert de
cet inconvnient, il a alors t ncessaire de rflechir une approche hybride entre vrification par
rfrence et par valeur selon la partie du store.
Autre dtail de fonctionnement important, une modification du store enclenche directement la
procdure de rendu par le biais dune fonction de notification. Ceci est problmatique lorsquil est
ncessaire de mettre jour le store chaque fois que la librairie danalyse reoit un message de
la cible, soit plusieurs centaines de fois par seconde. Dans ce cas la, React se retrouvent devoir
regnrer constamment larbre et ne peut pas tenir la cadence. Il est heureusement possible, laide
de librairies ddies, de contrler et de limiter les notifications du store afin que React neffectue
pas son rendu plus dune fois par frame.
Cependant, malgr de nombreuses optimisations apportes ici et l pour minimiser le travail
de React et de ses composants lors des rendus, la page peinait toujours se montrer de manire
fluide ds lors quun grand nombre dlments taient affichs a lcran en mme temps. Dapres le
profiler de Chromium, ces ralentissements semblaient venir du fait que les manipulations du DOM,
et donc a fortiori du format SVG reprsentant le graphe, sont extrmement coteuses. Il fallait donc
rapidement sabstraire du SVG au profit dautres technologies daffichage.
Une alternative au SVG est le canvas fourni par HTML5 fonctionnant de manire analogue
aux librairies graphiques 2D/3D : le developpeur a accs tout un ensemble de fonctions servant
dessiner sur ce canvas. Le canvas est beaucoup plus performant que le SVG car il na pas besoin de
sencombrer dun DOM, mais galement car les navigateurs les plus performants peuvent affecter
le processeur graphique la manipulation du canvas. Linconvnient tant justement labsence
de DOM, le rendant difficile debugger et intgrer au sein dune application React. De plus,
les developpeurs ny pensent pas souvent mais les outils daide la lecture de page web pour
aveugles ou les solutions dassistance aux personnes mobilit rduite se basent sur une analyse du
DOM. Utiliser un canvas rendrait lapplication trs difficilement accessible pour cette population.
Nanmoins, les performances avec SVG taient tellement mdiocres quil fallait absolument passer
au canvas, et ce malgr toutes les limitations cites.
60 Chapitre 7. Second prototype

Pour ne pas partir de zero, je me suis bas sur Konva.js [39], une librairie permettant de
simplifier le dessin sur le canvas. Contrairement au canvas qui ne propose que des primitives simples
de dessin, Konva.js permet la manipulation dobjets haut-niveaux comme des rectangles, des images
ou du texte, et soccupe lui meme de laffichage sur le canvas. La librairie react-konva donne
quant elle la possibilit de manipuler ces objets comme des componsants React, assurant ainsi
une cohrence dans le code source. Le mme comportement sapplique donc sur ces composants
Konva : ils sont rendus quen cas de ncessit et sont gaement pris en compte par lalgorithme de
reconciliation.
Cette nouvelle technologie a donn, comme prvu, des resultats bien plus intressants que
le SVG. Cependant, partir dun certain nombre dobjets affichs lecran, encore trop faible
pour nos besoins, la page souffrait nouveau de lourds ralentissement, et ce malgr toutes les
optimisations apportes, certaines brisant mme certains principes fondamentaux de React.
Le profiler indiquait que lalgorithme de reconcialiation prenait trop de temps pour garantir un
framerate intressant. Une seule solution subsistait alors : sabstraire de React pour le dveloppe-
ment des composants graphiques exploitant le canvas. Bien que trs simple a utiliser, Konva avait
galement ses propres limitations de performance. Jai donc opt pour le dveloppement dune
librairie spcifiquement conue pour directement dessiner dans le canvas en mettant de ct tout
intermdiaire coteux en performance.
La premire version de cette solution a permis datteindre un framerate trs acceptable dans les
cas dutilisation o les prcdentes crachaient leurs poumons. Neanmoins, lorganisation des objets
au sein du canvas saverait assez complexe et il fallait inclure la totalit de la logique daffichage au
sein dun unique object JavaScript. Adieu donc la programmation par composants.
Que nenni ! Lorganisation par composant a eu normment doccasions de faire ses preuves
tout au long du dveloppement de linterface graphique, si bien quil me semblait impensable de
sen abstraire completement. Cest ainsi que la deuxime version de cette solution a t conue pour
fonctionner de manire similaire React. En loccurrence, chaque composant a la possibilite de
dessiner sur le canvas au cours du rendu. A la fin de cette fonction, le composant peut retourner un
ensemble de composants fils qui auront galement loccasion de dessiner sur ce canvas. Un simple
algorithme de reconciliation a d cependant tre intgr pour assurer lintgrit des composants au
cours de leur dure de vie.
La principale diffrence avec React est labandon de la reconciliation locale. En effet, chaque
mise jour, React parcourt deux fois son arbre, la premire fois pour demander chaque composant
de se mettre a jour et la deuxime pour appliquer lalgorithme de reconciliation et modifier le
DOM si ncessaire. Cette architecture fait sens pour deux raisons principales. Dune part, il faut
tout prix minimiser les modifications coteuses du DOM et dautre part, il est tout fait possible
de manipuler localement le DOM. Le canvas fonctionne de manire oppose : il est tres simple
de dessiner sur le canvas mais il est dans la plupart des cas impossible de modifier localement le
canvas au changement dun composant. Il est donc dans tous les trs ncessaire de reconstruire tout
le canvas chaque fois, raison pour laquelle il est plus intressant de saffranchir de cette mise
jour en deux temps impose par les spcifications du DOM. Cest ainsi que les performances
de cette nouvelle librairie sont principalement assures par un unique parcourt de larbre et une
modification directe du canvas.
Cette solution atteint nanmoins elle aussi ses limites lorsquil est ncesaire dafficher plusieurs
milliers dlments. Pour tenter de les contourner, je me suis inspir de quelques techniques
doptimisations de React afin de limiter et cibler autant que possible les rendus dans le canvas. A la
fin de mon stage, il restait cependant encore beaucoup doptimisations tester mais dans lensemble
les performances ont t dmultiplies depuis la version SVG. En outre, il semble prsent difficile
datteindre de meilleurs rsultats avec les technologies Electron et JavaScript.
4 Interface Graphique 61

4.2 Conclusion
Aprs plusieurs mois de dveloppement avec React, celui-ci a finalement montr ses limites.
Son principe en composant reste toujours apprciable, mais ses performances laissent desirer
lorsquil faut assurer une frquence daffichage acceptable sur des pages contenant une grande
quantit dobjets. Jai malheureusement pris beaucoup trop de temps men rendre compte. En
effet, ntant pas expriment en technologies du web et souhaitant respecter la fnantise des
dveloppeurs, jai essay au maximum de ne pas rinventer la roue et jai donc pass la plupart du
temps chercher LA librairie graphique qui me permettrait dafficher exactement ce que je veux
de manire simple et performante. Avec le recul, il savre que jaurais d ds le debut crer ma
propre solution adapte mes besoins plutt que de persister detourner dautres librairies de leurs
zones de confiance.
De la mme manire, javoue avoir t sduit par la paire Redux/React mme si elle ncessite
de se pencher sur de nombreux petits details en apparence anodins pour optimiser les performances
de lapplication dans des cas critiques.
Pour conclure sur lutilisation de ces librairies, je regrette principalement leur courbe dap-
prentissage assez pentue. Il nest pas simple de rentrer compltement dans leur paradigme : il
faut dabord prendre le temps de shabituer aux nouveaux concepts quils proposent ainsi qu
lorganisation quils imposent. Une fois cette premire prise en main passe, la difficult se ressent
par accoups successifs. En effet, au cours du dveloppement de lapplication, le dveloppeur fera
face de multiples problmes de performance ou la quasi-impossibilit dimplmenter facilement
une fonctionnalit requise, ce qui le fera questionner sur la vritable puissance et versatilit de ces
solutions. Aprs un temps de recherche, il comprendra les raisons de ces limitations, la plupart
tant en fait des "fonctionnalits" quil faut apprendre a dompter plutt que de vritables problmes,
et cherchera alors un moyen de les contourner. La communaut active, les documentations claires
ainsi que les milliers de modules dj disponibles laideront passer cette tape et repartir de plus
belle. Cependant, aprs un certain nombre ditrations et doptimisations, la comprhension du
code source ncessitera un apprentissage pointue et une bonne matrise de la totalit des concepts
qui se sont ajouts au fur et mesure. Ce qui au debut netait que quelques ides cles comprendre
en surface devient un enchevtrement de techniques fines trs difficilement abordables pour les
dbutans qui devront passer par le mme processus dinitiation pour vraiment saisir les tenants et
aboutissants de chaque itration.
Conclusion

Au terme de ces 26 semaines de stage, le projet Debugger prit finalement forme. Nous sommes
passs durant cette priode de quelques plaintes et dune poigne de fonctionnalits demandes
une comprhension fine du domaine ainsi qu des prototypes fonctionnels rpondant de manire
priori pertinente aux problmes des utilisateurs.
Quatre grosses parties ont t conues et dveloppes savoir : une librairie de communication,
une intgration au sein de la solution UI Conductor, une librairie danalyse du fonctionnement
de lapplication cible et une interface graphique. Les fonctionnalits de ces modules ont suivi les
conclusions des analyses issues de la mthodologie centre utilisateur qui a notamment consist
aller la rencontre des dveloppeurs pour mettre en valeur les points noirs la solution actuelle.
Il reste bien entendu normment de parties dvelopper et de points noirs claircir avant
que ce projet ne puisse prtendre au titre de produit. Pour rappel, le stage sachve pendant le
dveloppement du deuxime prototype qui eut pour objectif dtre le support de tests utilisateur
censs vrifier ou invalider les hypothses de design qui ont men la cration de concepts cls.
Bien que mes choix de design ont sduit mes managers, on ne peut se prononcer sur la vritable
pertinence de ces choix temps que le prototype na pas t test rigoureusement. Ainsi, il faudrait
court terme continuer dvelopper ce prototype, et donc de baser chaque prise de dcisions sur le
fait que celui-ci doit tre rapidement finalis. A moyen terme par contre, il faudrait repasser sur
les diffrents choix techniques et effectuer des tests et des benchmarks prcis afin de vrifier que
chaque dcision est toujours pertinente et valable dans le cadre dun produit qui se veut stable et
mature.
En outre, les phases danalyse ont mis en valeur de nombreux domaines dans lesquels il serait
intressant de faire ressortir des concepts prototyper pour nouveau effectuer des tests utilisateurs.
Il serait envisageable densuite itrer sur ceux-ci afin de se rapprocher dun cosystme complet de
concepts rsolvant idalement la totalit des problmes.
Ces 6 mois ont t particulirement denses et ont t pour moi loccasion de minvestir
dans de nombreux pans du monde de linformatique. Jai eu ce titre loccasion dappliquer les
connaissances et comptences acquises grces certaines UV suivies lUTC, notamment :
SR02 et SR05 pour la programmation parallle ;
64 Chapitre 8. Conclusion

MI11 pour la mise en place dune chaine de compilation croise et pour le dveloppement
sous contrainte embarqu ;
LO21 et NF17 pour la conception darchitectures logicielles ;
NF16 grce laquelle japporte maintenant une attention particulire aux avantages et
inconvnients de chaque structure de donne et algorithme.
Ce quoi je dois ajouter lexprience acquise grce mon prcdent stage et mes projets
personnels dans des domaines tels que Git, SVN, Visual Studio ou le dveloppement de DLL.
Mais jai galement eu la chance de pouvoir apprendre, la plupart du temps par moi-mme, de
nombreuses technologies et mthodologies comme :
Les sockets et la programmation rseau en gnral ;
Lutilisation de C89 pour dvelopper une librairie destine une cible embarque ;
CMake pour la gnration de makefile et de chaine de compilation croise ;
Le dveloppement dapplication graphique en HTML/CSS/JS avec des librairies telles que
nodejs, Electron React, Redux et d3.
En dehors des comptences techniques, ce stage fut galement le thtre du dveloppement de
comptences humaines. Ce semestre durant lequel jai travaill principalement seul au sein dun
environnement trs diffrent de ma culture natale a t trs formateur. Jai ainsi appris morganiser
dans mon travail et adapter mes interventions en fonction de la culture de mon interlocuteur.
Je regrette cependant le manque de considration que lentreprise a eu lgard de mon stage.
Je nai eu que trs peu de contact humain, la faute principalement une barrire de la langue
beaucoup trop prononce, et jai trs souvent eu limpression dtre dans un bac sable o je
pouvais exprimenter ce que je voulais pour avoir mes diplmes. Mes runions de suivi avec mes
"managers" se comptent litrallement sur les doigts dune seule main, ce qui explique que jai
souvent eu limpression davoir t jet dans le vide et de ne travailler pour rien.
Outre les petites baisses de morale que cela peut causer, ce manque de communication se
conclut malheureusement par un manque de partage et donc une relative difficult prendre du
recul sur mon projet et finalement sur mes comptences.
Je reste toutefois suffisamment positif pour transformer ces points noirs en exprience excep-
tionnelle qui mont permis den apprendre beaucoup plus sur moi-mme, notamment sur ma faon
de travailler et sur ce quoi jaspire. Il est maintenant grand temps de prendre du recul sur ce qui
sest pass pendant ce stage de fin dtude afin de se prparer au mieux pour le grand saut dans la
vie active.
Bibliographie

[1] Beejs guide to network programming. http://beej.us/guide/bgnet/output/html/multipage/


index.html.
[2] Introduction to sockets programming in c using tcp/ip. http://www.csd.uoc.gr/~hy556/
material/tutorials/cs556-3rd-tutorial.pdf.
[3] Winsock official documentation. https://msdn.microsoft.com/en-us/library/ms741416(v=
VS.85).aspx.
[4] Winsock programmers fac. http://tangentsoft.net/wskfaq/.
[5] D. C. Shmidt, Pattern-oriented software architecture course. https://github.com/ppizarro/
coursera/tree/master/POSA/Slides.
[6] D. C. Shmidt, Systems programming with c++ wrappers, http://www.dre.vanderbilt.edu/
~schmidt/PDF/C++-wrappers.pdf.
[7] The adaptative communication environment (ace) website. http://www.cs.wustl.edu/
~schmidt/ACE.html.
[8] The c10k problem. http://www.kegel.com/c10k.html.
[9] D. C. Shmidt, Reactor. www.dre.vanderbilt.edu/~schm6idt/PDF/Reactor.pdf.
[10] D. C. Shmidt, Active Object. www.dre.vanderbilt.edu/~schmi8dt/PDF/Active-Objects.pdf.
[11] D. C. Shmidt, Half Sync / Half Async. http://www.dre.vanderbilt.edu/~schmidt/PDF/HS-HA.
pdf.
[12] D. C. Shmidt, Leader/Followers. http://www.dre.vanderbilt.edu/~schmidt/PDF/LF.pdf.
[13] D. C. Shmidt, Asynchronous Completion Token. http://www.cs.wustl.edu/~schmidt/PDF/ACT.
pdf.
[14] A.-T. Shreiner, Object-oriented Programming in ANSI-C. https://www.cs.rit.edu/~ats/books/
ooc.pdf.
[15] Json-rpc 2.0 specification. http://www.jsonrpc.org/specification.
[16] Messagepack website. http://msgpack.org.
66 BIBLIOGRAPHIE

[17] cmps repository. https://github.com/camgunz/cmp.


[18] Trace and profile function calls with gcc. https://balau82.wordpress.com/2010/10/06/
trace-and-profile-function-calls-with-gcc/.
[19] "GH" documentation et exemple. https://msdn.microsoft.com/en-us/library/c63a9b7h.aspx.
[20] Gnu backtrace documentation. https://www.gnu.org/software/libc/manual/html_node/
Backtraces.html.
[21] Dbghelp documentation. https://www.gnu.org/software/libc/manual/html_node/Backtraces.
html.
[22] npm.js website. https://www.npmjs.com.
[23] Nw.js and electron compared (2016 edition). http://tangiblejs.com/posts/
nw-js-and-electron-compared-2016-edition.
[24] Documentation delectron. https://electron.atom.io/docs/.
[25] Documentation de react. https://facebook.github.io/react/docs/hello-world.html.
[26] Documentation de flux. https://github.com/facebook/flux/tree/master/examples.
[27] Documentation de redux. http://redux.js.org.
[28] Documentation de d3. https://github.com/d3/d3/wiki.
[29] Webpack : When to use and why. http://blog.andrewray.me/
webpack-when-to-use-and-why/.
[30] Documentation de Webpack. https://webpack.js.org.
[31] Using D3.js with animations in React. http://blog.krawaller.se/posts/
using-d3-js-with-animations-in-react/.
[32] Calling native c++ dlls from a node.js web app. https://nodeaddons.com/
calling-native-c-dlls-from-a-node-js-web-app/.
[33] Documentation de node-ffi. https://github.com/node-ffi/node-ffi.
[34] Error handling in c. http://rlc.vlinder.ca/blog/2010/01/error-handling-in-c/.
[35] Apples introduction to error handling programming guide for cocoa. https://developer.apple.
com/library/content/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorHandling/
ErrorHandling.html.
[36] Documentation de OpenSSL. https://www.openssl.org/docs/.
[37] Thread local storage. https://en.wikipedia.org/wiki/Thread-local_storage.
[38] Documentation de react-timeseries. http://software.es.net/react-timeseries-charts/.
[39] Documentation de Konvajs. https://konvajs.github.io.