Traduit le 30 janvier 2021 depuis RemObjects.com sur une base fournie par DeepL.com (version gratuite)
Certains développeurs et fournisseurs d'outils, principalement ceux liés à des langages non gérés tels que C++ ou Delphi, définissent le développement natif comme la compilation directe vers le code-octet attendu par le processeur physique. C'est certainement une façon de voir les choses, mais nous pensons que c'est imprécis et que cela ne tient pas compte de la complexité des systèmes logiciels actuels. Prenons l'exemple suivant : si vous compilez une application pour x86, puis l'exécutez sur un processeur x64, est-ce vraiment « natif » ? On peut dire que non.
Le code non géré, natif du CPU, est de moins en moins pertinent de nos jours, et nous pensons que la véritable nativité du code, des applications et – surtout – de l'expérience du développeur se définit par d'autres critères.
Chez RemObjects, nous sommes fiers de fournir des solutions de développement logiciel véritablement natives pour une variété de plateformes. Nous considérons deux niveaux différents et séparés pour déterminer ce que nous considérons comme un développement « natif » : une expérience utilisateur native, et une expérience développeur native.
1. Une expérience utilisateur native
Qu'est-ce qui fait une expérience utilisateur native ? Pendant longtemps, il n'y a eu qu'une seule plateforme pour le développement grand public : Windows. Cela a changé et, dans l'ensemble, les utilisateurs choisissent leur environnement de travail par préférence. Même en évitant de se lancer dans la « guerre des systèmes d'exploitation », on ne peut ignorer que chaque plateforme actuelle a ses propres paradigmes d'utilisation distincts, et que les clients choisissent généralement leur plateforme informatique avec soin et souhaitent que leurs applications fonctionnent et se comportent bien sur ce système particulier, en adhérant aux paradigmes de leur plateforme.
Les utilisateurs de Windows s'attendent à ce que les applications se comportent « à la manière de Windows », et les utilisateurs de Mac veulent qu'elles fonctionnent « à la manière de Mac ». De même, les utilisateurs d'iOS veulent des applications pour leurs iPhones et iPads qui correspondent à la philosophie de conception de cette plateforme, et les applications pour téléphones Windows doivent une fois de plus adhérer à des paradigmes d'interface utilisateur complètement différents de ceux que les utilisateurs d'Android attendent de la plateforme qu'ils ont choisie.
Il est évident que le degré d'intégration des applications dans la plateforme qui les entoure varie : la plupart des jeux, par exemple, ont généralement une interface utilisateur plus ésotérique et indépendante de la plateforme (après tout, ils visent à vous sortir de votre routine quotidienne et à vous immerger dans une expérience de divertissement), tandis que les applications professionnelles et de productivité doivent généralement adhérer à la plateforme de la manière la plus stricte.
Le caractère natif n'est pas non plus uniquement dû à l'utilisation de contrôles et de thèmes d'IU de base exactement comme cela est prescrit. Par exemple, de nombreuses applications iPhone parmi les plus célèbres et les plus respectées ajoutent des textures ou des nuances subtiles aux contrôles fournis par le système d'exploitation. Mais elles continuent à se sentir « natives », car elles s'en tiennent aux paradigmes de base de l'IU, et les contrôles – tout en ayant l'air visuellement raffinés – ont un aspect, une sensation et, surtout, un comportement conformes aux attentes de l'utilisateur.
Pour ce faire, on utilise généralement ce qu'on appelle souvent les « ensembles de widgets natifs » des plates-formes. Qu'il s'agisse d'un bouton Win32 standard ou d'un bouton NSB natif du Mac, chaque ensemble de widgets offre un aspect et une convivialité uniques, qu'il s'agisse de l'espacement du texte dans les limites du rectangle environnant, de la taille des polices, des styles, de la force et de la direction des dégradés ou des détails complexes de la réaction et de l'animation du bouton lorsqu'on clique ou qu'on le touche. Ces détails subtils sont ancrés dans l'esprit de l'utilisateur ; celui-ci a des attentes subconscientes quant à la façon dont le contrôle sera ressenti lorsqu'il sera utilisé, souvent jusqu'au paramétrage du temps des animations. Ce qui peut sembler être une attention inutile aux détails devient crucial pour l'expérience de l'utilisateur, et celui-ci ressentira un effet de « vallée de l'étrange » si ses attentes ne sont pas satisfaites.
Mais le caractère natif va au-delà des simples contrôles offerts à l'utilisateur. La plupart des systèmes d'exploitation fournissent une infrastructure générale que les utilisateurs sont habitués à voir et avec laquelle ils travaillent – depuis les dialogues standardisés Ouvrir/Fermer ou Imprimer sur les ordinateurs de bureau jusqu'aux modèles de message électronique ou de tweet fournis par le système d'exploitation sur les téléphones.
Nous pensons que pour créer une expérience utilisateur véritablement native avec votre application, vos outils de développement doivent vous permettre de travailler avec les widgets et l'infrastructure natifs de la plateforme. Quel que soit l'effort déployé pour créer des bibliothèques “taille unique”, aucun bouton multiplateforme ne ressemblera vraiment à un bouton Windows standard, à un bouton Mac standard, à un bouton iOS standard. Afin de proposer à vos clients une application véritablement native, vous devez choisir une chaîne d'outils de développement qui vous permette de travailler avec la plateforme native.
Actuellement, ces chaînes d'outils comprennent .NET/WPF, Metro/WinRT, Delphi/VCL (pour Windows), Objective-C/Cocoa (pour Mac et iOS), MonoMac et MonoTouch (pour Mac et iOS, respectivement), Java (pour Android) ou MonoDroid (également pour Android).
Il va sans dire que chez RemObjects, nous essayons d'aider les développeurs à faire tous ces choix dans la chaîne d'outils. Que ce soit avec nos compilateurs (Oxygene, RemObjects C# et Swift) ou avec notre suite de produits Data Abstract, nous vous proposons une couverture complète de chacune des combinaisons énumérées ci-dessus.
Mais : nous pensons qu'une expérience utilisateur native, bien qu'essentielle, n'est qu'une partie d'un processus réussi de développement d'application.
2. Une expérience de développement native
À l'époque où Win32 était la référence en matière d'API pour les systèmes d'exploitation (et avant), les outils de développement devaient fournir de solides couches d'abstraction sur lesquelles les développeurs pouvaient travailler – parce que les API des systèmes d'exploitation étaient si basiques que travailler directement sur celles-ci revenait à travailler en langage assembleur (ou, en fait, à travailler en assembleur).
Lorsque des outils comme les plus récents Turbo Pascal, Visual Basic ou Delphi ont fait leur apparition, le développement avec les API DOS ou Win16/Win32 était une corvée. Les développeurs ont donc accueilli favorablement les couches d'abstraction qui facilitaient le codage, des bibliothèques de classes de base aux couches d'abstraction de l'interface utilisateur comme TurboVision, OWL, la VCL ou MFC.
Mais les plateformes ont évolué, et avec les produits Microsoft .NET et WinRT, Apple Cocoa (et Cocoa Touch) ou Android Dalvik basé sur Java, les API ont depuis longtemps atteint un niveau convivial pour les développeurs, un niveau sur lequel on peut et on devrait coder directement.
Les abstractions supplémentaires qui s'ajoutent à ces API sont une distraction, et non une aide, pour le développeur, car elles ajoutent une couche supplémentaire de surcharge inutile à l'application et à l'expérience de développement. Et ces abstractions se sont avérées être des échecs à plusieurs reprises, comme lorsque VCL.NET a essayé de reconstruire la bibliothèque de classes bien appréciée de Delphi sur le framework .NET (déjà beaucoup plus évolué et sophistiqué, mais orthogonal et donc incompatible, qui était alors dans sa version précoce 1.1).
Les abstractions inutiles d'API déjà bonnes (ou excellentes) ne servent à rien pour les développeurs qui les utilisent. Au contraire, elles séparent les développeurs de la plateforme, et les uns des autres. Pour chaque article, échantillon ou billet de blog fourni par, disons, Apple ou la communauté Cocoa qui montre comment utiliser une fonctionnalité d'iOS, il doit y avoir l'équivalent “et voici comment vous le faites dans MonoTouch”, “et voici comment vous le faites dans FireMonkey”, “et voici comment vous le faites dans ...”. L'abstraction empêche les développeurs de pouvoir (ré)utiliser la documentation ou les échantillons du fournisseur de la plateforme. Pire encore, elle fragmente la communauté des développeurs sur la même plateforme, empêchant les programmeurs d'interagir et de partager du code – chaque contrôle Cocoa écrit dans MonoTouch est un contrôle Cocoa qui ne peut pas être facilement réutilisé par un développeur utilisant la chaîne d'outils native Xcode/Objective-C (ni par un développeur utilisant FireMonkey, ou Titanium, ou toute autre couche d'abstraction).
Les abstractions empêchent également les développeurs d'adopter rapidement et facilement les nouvelles fonctionnalités de la plateforme. Lorsque les derniers SDK du fournisseur de la plateforme sortent, les développeurs qui utilisent les chaînes d'outils natives peuvent généralement commencer à travailler avec les nouvelles technologies dès le premier jour (ou même plus tôt). Dès qu'un nouveau SDK Android est disponible, les développeurs Java natifs peuvent utiliser les nouvelles API. Le jour même où une nouvelle version d'iOS est disponible, les développeurs Cocoa peuvent commencer à se salir les mains avec les nouveautés. Pendant ce temps, les développeurs coincés derrière une couche d'abstraction non native doivent attendre que leur fournisseur d'outils fasse l'abstraction des nouvelles API pour eux.
Sans parler du fait que les outils de développement non natifs vous enfermeront souvent et vous forceront à vous en tenir à la couche d'abstraction.
Le principal argument de vente et l'attrait d'une chaîne d'outils non native est généralement la “familiarité”, c'est-à-dire l'idée que la couche d'abstraction vous permettra d'accéder à une nouvelle plateforme sans la courbe d'apprentissage abrupte que représente, en fait, l'apprentissage d'une nouvelle plateforme.
Mais cela est trompeur et s'avère souvent ne pas être le cas. La principale courbe d'apprentissage sur une nouvelle plateforme n'est généralement pas le langage de développement, ni même le système de classes – il s'agit d'apprendre à connaître la plateforme elle-même et à écrire d'excellentes applications pour cette plateforme (ce qui nous ramène à notre premier critère : l'expérience utilisateur native).
Travailler avec une couche d'abstraction s'avère en fait avoir l'effet inverse de celui escompté, en rendant plus difficile la compréhension de la documentation du fournisseur de la plateforme (qui est entièrement adaptée aux outils natifs de la plateforme, bien sûr) et en rendant plus difficile la réutilisation des exemples de code existants trouvés en ligne.
Pour revenir au cas d'iOS : avoir à regarder et à comprendre la documentation ou les exemples écrits pour les API Objective-C de Cocoa peut sembler difficile si l'on n'est pas encore familier avec les paradigmes de l'Objective-C. Mais ce qui est en fait plus difficile, c'est d'avoir à regarder cette même documentation ou cet exemple, puis de comprendre comment il se traduit dans votre couche d'abstraction, disons, basée sur le C#.
Et aucune couche d'abstraction n'est jamais parfaite. La plateforme sous-jacente et ses API finiront par échapper au contrôle du développeur et il faudra s'en occuper. Tout effort visant à éviter de connaître et de comprendre la plateforme avant de développer sur celle-ci est malavisé et ne fait que retarder l'inévitable. Au bout du compte, il manque une fonctionnalité à l'abstraction et le développeur doit creuser jusqu'aux API de base et la mettre en œuvre lui-même. Ou alors, un bogue se produit qui nécessite un débogage plus important que ce que la couche d'abstraction prend en charge.
Comme pour l'expérience utilisateur native, ici à RemObjects Software nous nous sommes donné pour mission de soutenir (et d'encourager) les développeurs à utiliser des outils de développement natifs de la plateforme ; vous remarquerez que nous encourageons les développeurs à opter pour la chaîne d'outils plus native même dans les cas où recommander une solution moins native signifierait une vente supplémentaire pour nous.
En ce qui concerne le compilateur, une fois de plus, Oxygene, C# et Swift prennent en charge le développement natif sur les plateformes classiques Windows, Metro (Windows 8 et 10), Windows Phone, Android, Mac, iOS, watchOS et tvOS. Nos compilateurs sont également un excellent choix pour la construction de serveurs multiplateformes basés sur Mono ou Java.
Avec la suite Data Abstract, nous prenons en charge le développement natif pour toutes les grandes plateformes actuelles : Windows classique (via .NET et Delphi), Metro/WinRT, Windows Phone, Mac et iOS, ainsi qu'Android et d'autres plateformes basées sur Java.
Autres préoccupations, telles que la réutilisation des codes
Nous sommes bien sûr conscients que d'autres facteurs entrent en jeu dans la décision concernant la chaîne d'outils de développement. Des considérations telles que la réutilisation du code peuvent figurer plus haut sur la liste des priorités qu'une expérience de développement natif, et c'est normal.
Notre philosophie est que, toutes choses étant égales par ailleurs, les développeurs devraient viser une chaîne d'outils qui soit native sur les deux plans : l'expérience de l'utilisateur et l'expérience du développeur. Si nécessaire, un compromis dans l'expérience du développeur peut être fait – c'est après tout un compromis qui n'affecte que le développeur, s'il est poursuivi correctement. D'après notre expérience, aucun compromis ne devrait jamais être fait en ce qui concerne la fourniture d'une expérience utilisateur véritablement native.
En matière de réutilisation du code entre plateformes, nous, chez RemObjects Software, avons pour objectif d'aider, à la fois au niveau du langage (en fournissant aussi bien Oxygene que RemObjects C# et Silver comme langage natif du développeur pour toutes les principales plateformes, ainsi que leur bibliothèque Sugar) et au niveau de la base de données en arrière-plan, en maintenant la compatibilité avec le câble Data Abstract et en vous permettant de partager une infrastructure de serveur commune pour toutes vos applications clientes natives.
Pour en savoir plus
Vous pouvez en savoir plus sur nos produits à la fois multiplateformes et natifs Elements (Oxygene, C# et Swift) et Data Abstract, respectivement sur les sites remobjects.com/elements et remobjects.com/da.
Vous pouvez également trouver une matrice générale de la manière dont nos produits s'intègrent dans les différentes chaînes de développement natives (ainsi que semi-natives et non natives, si vous devez passer par là), à l'adresse remobjects.com/products/toolchains.
Ce sujet a été publié pour la première fois sur nos blogs.
…