Dans le dé­ve­lop­pe­ment de logiciels et de sites Internet, la struc­tu­ra­tion des données joue un rôle important. En effet, si les données d’un projet sont bien struc­tu­rées, il pourra être lu par d’autres logiciels de façon efficace et précise. Sur le Web, ceci est tout par­ti­cu­liè­re­ment essentiel pour les moteurs de recherche basés sur du texte tels que Google, Bing ou Yahoo qui peuvent en­re­gis­trer le contenu d’un site internet de façon optimale grâce à des balises struc­tu­rées cor­res­pon­dantes.

Dans le dé­ve­lop­pe­ment logiciel, l’uti­li­sa­tion des données struc­tu­rées – que ce soit pour des ap­pli­ca­tions Web ou de bureau – se révèle gé­né­ra­le­ment avan­ta­geuse partout où les pro­grammes et les services doivent échanger des données via des in­ter­faces et où une vitesse de trai­te­ment des données élevée est désirée. Dans cet article, vous dé­cou­vri­rez quel rôle peut jouer le format de sé­ria­li­sa­tion Protocol Buffers (Protobuf) dans ce cadre et en quoi cette méthode de struc­tu­ra­tion se démarque de sa célèbre al­ter­na­tive JSONP.

Qu’est-ce que Protobuf (Protocol Buffers) ?

Avec Protocol Buffers, abrégé en Protobuf, Google met à dis­po­si­tion du grand public depuis 2008 un format d’échange de données ini­tia­le­ment développé pour une uti­li­sa­tion interne sous forme de projet open source (pour partie sous licence Apache-2.0). Le format binaire permet aux ap­pli­ca­tions d’en­re­gis­trer et d’échanger en toute sim­pli­cité des données struc­tu­rées et ces pro­grammes peuvent même être codés dans dif­fé­rents langages de pro­gram­ma­tion. Les langages suivants font notamment partie des langages supportés :

  • C#
  • C++
  • Go
  • Objective-C
  • Java
  • Python
  • Ruby

Protobuf est notamment utilisé en as­so­cia­tion avec HTTP et RPC (Remote Pro­ce­du­rel Calls) pour la com­mu­ni­ca­tion client-serveur locale et à distance – en par­ti­cu­lier pour décrire les in­ter­faces né­ces­saires dans ce cadre. La com­po­si­tion du protocole est également connue sous l’ap­pel­la­tion gRPC.

72mPlAfHIjs.jpg Pour afficher cette vidéo, des cookies de tiers sont nécessaires. Vous pouvez consulter et modifier vos paramètres de cookies ici.

Quels sont les avantages de Protocol Buffers de Google ?

Lors du dé­ve­lop­pe­ment de Protobuf, Google a fait tout par­ti­cu­liè­re­ment attention à deux facteurs : la sim­pli­cité et la per­for­mance. Au moment de son dé­ve­lop­pe­ment – qui, comme nous l’avons déjà indiqué plus haut, s’est déroulé en interne dans un premier temps –, ce format avait pour vocation de remplacer le format XML de nature similaire. Il fait aujourd’hui con­cur­rence à d’autres solutions telles que JSON(P) ou Flat­Buf­fers. Une analyse des ca­rac­té­ris­tiques et des points forts de cette méthode de struc­tu­ra­tion montre pourquoi Protocol Buffers constitue toutefois la solution idéale pour de nombreux projets.

Des schémas clairs et in­te­rap­pli­ca­tions

Un système de base de données bien organisé constitue la base de toute ap­pli­ca­tion de qualité. L’or­ga­ni­sa­tion de ce système et des données qu’il contient se voit souvent accorder une priorité élevée, mais lorsque les données doivent être trans­mises à un service tiers, les struc­tures sous-jacentes sont alors perdues. Un codage unique des données dans le schéma Protocol Buffers vous permet de veiller à ce que votre projet trans­mette les données struc­tu­rées de la façon souhaitée, sans perdre les struc­tures en question.

Com­pa­ti­bi­lité des­cen­dante et as­cen­dante

L’im­plé­men­ta­tion de Protobuf rend superflue la réa­li­sa­tion la­bo­rieuse des contrôles de version qui se tra­dui­sent gé­né­ra­le­ment par du code « moche » (en anglais « ugly code »). Afin de pouvoir maintenir la com­pa­ti­bi­lité des­cen­dante avec d’anciennes versions ou la com­pa­ti­bi­lité as­cen­dante avec de nouvelles versions, Protocol Buffers utilise des champs numérotés servant de points de référence aux services procédant à l’accès. Pour publier de nouvelles fonc­tion­na­li­tés, il n’est donc pas toujours né­ces­saire d’adapter la totalité du code.

Confort et flexi­bi­lité

Le codage de Protobuf utilise au­to­ma­ti­que­ment des mo­di­fi­ca­teurs (au choix : optional, required ou repeated) per­met­tant de sim­pli­fier con­si­dé­ra­ble­ment la pro­gram­ma­tion. Cette méthode de struc­tu­ra­tion permet ainsi de dé­ter­mi­ner la forme de la structure de données au niveau du schéma après quoi les détails de l’im­plé­men­ta­tion des classes utilisées sont au­to­ma­ti­que­ment pa­ra­mé­trés pour les dif­fé­rents langages de pro­gram­ma­tion. D’autre part, vous pouvez modifier à tout moment le statut pour passer par exemple de « required » à « optional ». Le transport des struc­tures de données peut également être réglé à l’aide de Protocol Buffers : un codage des struc­tures de requête et de réponse gé­né­riques permet de garantir en toute sim­pli­cité un transfert des données plus flexible et plus sûr entre les dif­fé­rents services.

Moins de code boi­ler­plate

L’im­por­tance du code boi­ler­plate (parfois appelé sim­ple­ment boi­ler­plate) dans la pro­gram­ma­tion est fonction du type de projet et de sa com­plexité. En termes simples, il s’agit d’éléments de code réu­ti­li­sables né­ces­saires en de nombreux endroits d’un logiciel et, gé­né­ra­le­ment, peu per­son­na­li­sables. Un tel code sert par exemple souvent à préparer l’uti­li­sa­tion des fonc­tion­na­li­tés issues des bi­blio­thèques. Les boi­ler­plates sont notamment répandus dans les langages web Ja­vaS­cript, PHP, HTML et CSS même s’ils ne sont pas idéals pour la per­for­mance de l’ap­pli­ca­tion web. Un schéma Procotol Buffers adapté contribue à diminuer le code boi­ler­plate et ainsi à améliorer la per­for­mance du­ra­ble­ment.

Une in­te­ro­pé­ra­bi­lité lin­guis­tique simple

À l’heure actuelle, les ap­pli­ca­tions standard ne sont plus uni­que­ment codées dans un seul langage et combinent des éléments et des modules de pro­grammes de dif­fé­rents types de langages. Protobuf facilite con­si­dé­ra­ble­ment l’in­te­rac­tion des dif­fé­rents éléments de code : si de nouveaux com­po­sants avec un langage différent du langage actuel du projet sont ajoutés, il vous suffira de faire traduire le schéma Protocol Buffers dans le langage cible cor­res­pon­dant à l’aide du gé­né­ra­teur de code adéquat ce qui permet de réduire les efforts né­ces­saires à un minimum. Pour ce faire, il est bien entendu né­ces­saire que les langages utilisés soient supportés par Protobuf (soit par défaut s’ils figurent dans les langages listés plus haut soit en ajoutant des plug-ins de four­nis­seurs tiers.

Protobuf vs. JSON : com­pa­ra­tif de ces deux formats

Google a tout d’abord développé Protocol Buffers comme une al­ter­na­tive au XML (Ex­ten­sible Markup Language) et a surpassé ce langage de balisage sur de nombreux aspects. La struc­tu­ra­tion des données avec Protobuf a non seulement tendance à être plus simple, mais per­met­trait également – d’après le géant du numérique – une structure de données de trois à dix fois plus petite et de 20 à 100 fois plus rapide qu’une structure XML com­pa­rable.

Protocol Buffers est également souvent comparé avec le langage de balisage de Ja­vaS­cript JSON (JavaScript Object Notation), mais il convient de noter que les deux tech­no­lo­gies ont été conçues avec des objectifs dif­fé­rents : JSON est un format de messages découlant du Ja­vaS­cript, échan­geant les messages au format texte et supporté par la quasi-totalité des langages de pro­gram­ma­tion courants. La palette de fonc­tion­na­li­tés de Protobuf comprend plus d’un format de messages puisque la tech­no­lo­gie de Google offre également des règles et des outils divers per­met­tant de définir et d’échanger des messages. En principe, Protobuf supplante aussi JSON en matière de per­for­mance si l’on considère l’envoi de messages de façon générale, mais le tableau suivant « Protobuf vs. JSON » montre que les deux tech­no­lo­gies de struc­tu­ra­tion pré­sen­tent des avantages et des in­con­vé­nients :

Protobuf JSON
Dé­ve­lop­peur Google Douglas Crockford
Fonction Langage de balisage pour les données struc­tu­rées (en­re­gis­tre­ment et trans­mis­sion) et les bi­blio­thèques Langage de balisage pour les données struc­tu­rées (en­re­gis­tre­ment et trans­mis­sion)
Format binaire oui non
Stan­dar­di­sa­tion non oui
Lisible par l’homme par­tiel­le­ment oui
Com­mu­nauté/do­cu­men­ta­tion petite com­mu­nauté, manuels en ligne pour ap­pro­fon­dir immense com­mu­nauté, do­cu­men­ta­tion of­fi­cielle de qualité et divers tutoriels en ligne, etc.

Par con­sé­quent, si vous souhaitez un format de sé­ria­li­sa­tion bien documenté, en­re­gis­trant et trans­met­tant les données struc­tu­rées dans un format lisible par l’homme, vous devriez opter pour JSON plutôt que pour Protocol Buffers. C’est d’autant plus vrai si la partie serveur de l’ap­pli­ca­tion est écrite en Ja­vaS­cript et si la majeure partie des données est traitée di­rec­te­ment par les na­vi­ga­teurs par défaut. En revanche, si la flexi­bi­lité et la per­for­mance de la structure des données jouent pour vous un rôle essentiel, Protocol Buffers est ha­bi­tuel­le­ment la solution la plus efficace.

Tutoriel : in­tro­duc­tion pratique à Protobuf avec l’exemple de Java

Protocol Buffers peut faire la dif­fé­rence dans de nombreux projets logiciels, mais comme souvent, il sera né­ces­saire dans un premier temps de connaître les par­ti­cu­la­ri­tés et les astuces syn­taxiques de cette tech­no­lo­gie de sé­ria­li­sa­tion et d’apprendre à les utiliser. Afin de vous donner un aperçu de la syntaxe et de l’échange de messages de Protobuf, le tutoriel suivant vous présente les premiers pas avec cette tech­no­lo­gie – de la dé­fi­ni­tion du format per­son­na­lisé dans un fichier .proto à la com­pi­la­tion des struc­tures de Protocol Buffers. Pour l’exemple, nous avons pris comme base de code une simple ap­pli­ca­tion de carnet d’adresses Java qui permet de lire les données des contacts à partir d’un fichier et de les écrire dans un autre fichier. Chaque entrée du carnet d’adresses est dotée des pa­ra­mètres « nom », « n° d’id. », « adresse e-mail » et « numéro de téléphone ».

Définir le format de données per­son­na­lisé dans le fichier .proto

Les struc­tures de données que vous souhaitez réaliser avec Protocol Buffers doivent tout d’abord être décrites dans le fichier .proto. Il s’agit du fichier de con­fi­gu­ra­tion par défaut de ce format de sé­ria­li­sa­tion. Vous devez ajouter un message pour chaque structure que vous souhaitez sé­ria­li­ser dans ce fichier (c’est-à-dire présenter sous la forme d’une suite d’in­for­ma­tions). Spécifiez ensuite les noms et les types de chaque champ de ce message et ajoutez le/les mo­di­fi­ca­teur(s) souhaité(s). Chaque champ doit comporter un mo­di­fi­ca­teur.

Pour le carnet d’adresses Java, les struc­tures de données du fichier .proto peuvent res­sem­bler à ce qui suit :

syntax = "proto3";
package tutorial;
option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";
message Person {
    required string name = 1;
    required int32 id = 2;
    optional string email = 3;
    enum PhoneType {
        MOBILE = 0;
        HOME = 1;
        WORK = 2;
    }
    message PhoneNumber {
        required string number = 1;
        optional PhoneType type = 2 [default = HOME];
    }
    repeated PhoneNumber phones = 4;
}
message AddressBook {
    repeated Person people = 1;
}

La syntaxe de Protocol Buffers rappelle fortement celle de C++ ou de Java. La version de Protobuf est toujours signalée en première position, ici proto3, et est suivie par la des­crip­tion du pack logiciel dont vous souhaitez struc­tu­rer les données. Cette des­crip­tion inclut notamment un nom unique (« tutorial ») et dans cet exemple de code, les deux options spé­ci­fiques à Java « java_package » (paquet Java dans lequel sont en­re­gis­trées les classes générées) et « java_outer_classname » (qui définit les noms des classes).

Elle est suivie par les messages Protobuf qui peuvent comporter un nombre illimité de champs, sachant que les types de données typiques comme « bool », « int32 », « float », « double » ou « string » sont dis­po­nibles. Ces derniers sont pour partie utilisés dans l’exemple. Comme indiqué plus haut, chaque champ d’un message doit comporter au moins un mo­di­fi­ca­teur parmi :

  • required : ce champ impose une valeur. En l’absence de valeur, le message restera « uni­ni­tia­li­zed », c’est-à-dire non ini­tia­lisé ou non envoyé.
  • optional : un champ « optional » peut contenir une valeur, mais ce n’est pas impératif. En l’absence de valeur, une valeur standard est utilisée. Dans le code ci-dessus, on trouve par exemple la valeur standard « HOME » (numéro fixe du domicile) pour le type de numéro de téléphone.
  • repeated : les champs avec le mo­di­fi­ca­teur « repeated » peuvent être répétés à volonté (ou être absents, c’est-à-dire répétés zéro fois).

Vous trouverez un guide détaillé con­cer­nant la dé­fi­ni­tion du format de données per­son­na­lisé avec Protocol Buffers sur le forum des dé­ve­lop­peurs de Google.

Compiler le schéma Protocol Buffers per­son­na­lisé

Une fois les struc­tures de données per­son­na­li­sées définies de la façon désirée dans le fichier .proto, générez les classes né­ces­saires à la lecture et à l’écriture des messages Protobuf. Pour ce faire, utilisez le com­pi­la­teur Protocol Buffers (protoc) sur le fichier de con­fi­gu­ra­tion. Si vous ne l’avez pas encore installé, té­lé­char­gez sim­ple­ment la dernière version dans le ré­per­toire GitHub officiel. Dé­com­pres­sez le fichier ZIP à l’em­pla­ce­ment désiré et lancez le com­pi­la­teur avec un double-clic (il se situe dans le dossier « bin »).

Note

Veillez à bien té­lé­char­ger la bonne version du com­pi­la­teur Protobuf : Protoc est dis­po­nible pour les ar­chi­tec­tures 32 ou 64 bits (Windows, Linux ou macOS).

Spécifiez ensuite :

  • le ré­per­toire source dans lequel se trouve le code de votre programme (ici la balise « SRC_DIR »),
  • le ré­per­toire cible dans lequel le code généré devra être en­re­gis­tré (ici la balise « DST_DIR »)
  • et le chemin vers le fichier .proto.

Comme vous souhaitez aussi générer des classes Java, utilisez également l’option --java_out (il existe des options si­mi­laires pour les autres langages supportés). La commande complète pour la com­pi­la­tion est donc la suivante :

protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/addressbook.proto
Conseil

Google propose un tutoriel Java Protobuf détaillé dans lequel est notamment expliquée la trans­mis­sion des messages via Protocol Buffers (lecture/écriture) dans la section « De­ve­lo­pers », l’espace de projet pour les dé­ve­lop­peurs du géant du numérique. Vous y trouverez également des notices pour les dif­fé­rents langages supportés tels que C++, Go ou Python.

Aller au menu principal