Dynamic .NET in AutoCAD 2013

Par Serge Camiré, ing.

Cet article commence par une rétrospective des langages avant de mieux aborder le vif du sujet, soit le .Net dynamique dans AutoCAD 2013. Pour les initiés, vous pourriez donc sauter les premiers paragraphes. Si j’ai choisi cet approche, c’est que c’est plus facile de savoir où l’on est rendu lorsqu’on connait l’historique du trajet. Dans son livre « Une brève histoire du temps », Stephen Hawking avait fait remarquer que pour chaque équation qu’il insérerait, il diminuerait ses ventes de moitié et que par conséquent, il n’en avait insérée aucune. Je tenterai de trouver le juste équilibre entre ne pas être trop technique car l’article a déjà le défaut d’être long mais assez pour susciter votre intérêt de creuser davantage certains éléments.

·         L’absence de typage de données avec AutoLISP

·         Langage interprété vs langage compilé

·         L’avènement de DotNet

·         Bref rappel de COM (Component Object Model)

·         Liaison hâtive vs liaison tardive

·         La réflexion dans DotNet

·         Les 3 grands paradigmes de programmation  et le F#

·         AutoCAD et les services Web

·         Quoi de neuf avec Visual Studio 2010

·         Utilisation du type dynamic

·         Plus ça change, plus c’est semblable

L’absence de typage de données avec AutoLISP

La plupart d’entre nous avons commencé à programmer dans AutoCAD avec AutoLISP. Lorsqu’on fait usage d’une variable, elle n’est jamais typé, c’est-à-dire qu’on n’a jamais besoin de déclarer qu’il s’agit d’un nombre, d’une chaine, d’une liste ou de d’autres espèces de donnée. Bien pire (ou bien mieux), la même variable peut changer de type dynamiquement. Dans la même expression, on peut déclarer (setq a 1.0 a "ABC"), ce qui altère le type à l’interne avant même que setq ne la retourne. Pourtant, AutoLISP demeure très performant pour la très grande majorité des projets et ce, même si langage est issu des années 50 (1958 pour être plus exact).

Langage interprété vs langage compilé

Qu’est-ce qu’il y a de différent avec les autres langages? Pour répondre à cette question, il faut revenir à certaines bases, toujours en gardant à l’esprit que les lecteurs de ce forum  sont issus d’un monde Autocadien. Il existe 2 paradigmes : les langages compilés et les langages interprétés.

Commençons par les langages interprétés. Vous avez probablement tous travaillé avec les fichiers LSP au travers de l’interface IDE (Integrated Development Environment) via la commande VLIDE. Peut-être avez-vous aussi travaillé avec des fichiers VBA (fichiers à extension DVB – ceux-ci étant maintenant caducs). Dans les 2 cas, vous utilisez le code sans compilateur. Vous pouvez faire des modifications et c’est toujours le même fichier que vous rechargez. Cette adaptabilité a un coût en performance parce que, pour réduire les risques que le programme ne plante, il doit prévoir le pire à chaque ligne. Lorsqu’il y a une erreur, elle est de type « runtime error » sans distinction qu’elle soit due à une erreur de logique ou à une erreur liée à l’incompatibilité de type et qui aurait pu être évitée par un compilateur.

Le typage des données n’est pas fonction que le langage sont interprété ou compilé. Dans le cas de VBA (ou même VB), les variables n’ont pas à être déclarée en omettant la déclaration Option Explicit ou encore, elles peuvent être déclarées mais non typées explicitement (elles le seront implicitement en Object comme Dim A équivaut à Dim A as Object). Dans le cas d’AutoLISP, toutes les variables ont un type implicite non déclarable mais cela dépasse la portée de cet article (il faut que je pense à mes ventes). Il s’agit d’avoir fait des projets en ObjectARX ou en DotNet pour le savoir.

Un langage compilé implique que la version finale produise un fichier d’exécution différent du code source. Comme le compilateur a pris soin de vérifier certaines compatibilités de type, il prend plus de risque lors de l’exécution et est donc plus rapide. Les erreurs possibles sont alors principalement des erreurs de logique. Dans la même veine, il est possible de compiler des fichiers LSP au format FAS (pour FASt, i.e. rapide) ou VLX (Visual Lisp compiled). La différence entre les 2 formats tient du fait que le premier est la compilation un pour un d’un LSP en un FAS tandis que le second est la compilation d’un ou plusieurs fichiers de types divers en un seul fichier VLX.

Malgré qu’on ait mentionné que VBA ne soit pas compilé mais interprété, il existe depuis longtemps le langage VB qu’il ne faut pas confondre, lequel permet de créer des fichiers exécutables (des EXE ou des DLL.) Mentionnons rapidement que ce type de fichier existait avant l’arrivée de DotNet et était donc forcément de type non géré par un Framework que nous expliquerons plus loin. Le poste de travail qui devait les faire fonctionner devait cependant avoir un module d’exécution préalablement installé (en anglais runtime, soit un ensemble des librairies (DLL) dont ceux-ci pour VB : asycfilt.dll, COMCAT.DLL, msvbvm60.dll, OLEAUT32.DLL, OLEPRO32.DLL, STDOLE2.TLB, Vb6fr.dll ou d’autres pour d’autres langages). La dernière version de VB utilisant ce runtime était la version 6 en 1998. Notons au passage qu’AutoLISP a lui aussi son runtine (vl.arx) et que certains on comprit comment utiliser un équivalent avec AutoCAD LT (mais ceci est un sujet de discussion en soi).

L’avènement de DotNet

En 2002, coup de théâtre, Microsoft dévoile la sortie de la technologie DotNet (alias .Net). Celle-ci s’attaque de façon plus globale aux postes de travail ainsi qu’au monde de l’Internet. En gros, c’est quoi? On a voulu offrir un environnement de programmation qui permette rapidement d’adapter le même code source pour l’un ou l’autre des destinataires précités, avec la contrainte qu’on ne connait pas d’avance quel sera leur système d’exploitation final ni s’il sera utilisé de façon autonome ou via un navigateur de type Internet Explorer. Quand on sait qu’un programme compilé ne doit pas trop se poser de questions lors de son contexte d’exécution, cela demande certaines pirouettes.

Ainsi donc, DotNet repose d’abord sur l’installation d’un Framework (ci-après abrégé FW). Celui-ci comporte entre autre chose le Common Language Runtime (ou CLR) et des très nombreux autres composant.  Il existe une version spécifique de Framework pour chaque système d’exploitation. Vous n’avez pas à vous inquiéter, les mises à jour de Windows (ou autres système d’exploitation) l’ont installé pour vous. C’est peut-être une surprise pour certains d’apprendre ceci mais vos programmes EXE ou DLL que vous écrirez avec Visual Studio 20XX ne sont pas compilés mais d’abord réécrits dans un langage propre à Microsoft (recherchez CIL ou MSIL pour plus de détails si le sujet vous intéresse) puis pris en charge par le CLR une fois distribué sur le poste de vos utilisateurs afin d’être compilés lors de leur première exécution. Pourquoi je le mentionne ? Parce qu’on peut faire de l’ingénierie inverse avec vos fichiers, c’est-à-dire, on peut retrouver le code source. Pour vous protéger, il existe des logiciels d'obfuscation et de compactage (recherchez Dotfuscator Software Services CE pour plus de détails). Une autre implication de ce qui vient d’être dit est que la première exécution de votre programme prend plus de temps puisqu’elle inclut le temps de compilation.

Mentionnons au passage que DotNet est officiellement supporté depuis la version AutoCAD 2005 de façon expérimentale mais n’a été efficace qu’en 2006. Pour chaque version d’AutoCAD existe une version de FrameWork donc une version de Visual Studio (Visual Studio 2008 et suivants permettent de démarrer un projet avec d’anciens Frameworks). Historiquement, Autodesk a respecté le maintien de la même version de FrameWork pour chacune des 3 années que forme une version majeure du logiciel AutoCAD (R17, R18, etc.) sauf qu’entre 2011 et 2012 on est passé du FW 3.5 au FW 4.0. Heureusement, vos applications peuvent migrer vers le haut donc si vous les avez créées avec le FW 3.5 pour AutoCAD 2010 ou 2011, elles fonctionneront toujours avec AutoCAD 2012. Par contre, si vous les avez créées en utilisant le FW 4.0, elles fonctionneront avec AutoCAD 2012 mais pas en 2010 ni en 2011. Aussi, si vos applications partent de loin, soit du FW 2.0 (i.e. pour AutoCAD 2007-2009) vous pourriez devoir faire certains ajustements (recherchez useLegacyV2RuntimeActivationPolicy à ce sujet).

Ce préambule nous a ramené progressivement vers le sujet de cet article soit le .Net dynamique dans AutoCAD 2013. Cette version d’AutoCAD utilise Visual Studio 2010 et le FW 4.0 Comme nous l’avons vu précédemment, AutoCAD 2012 utilisait déjà le FW 4.0 donc l’article aurait pu tout aussi bien faire référence à 2012 si ce n’était du support spécifique de certains objets comme les ObjectID et ceux qui en dérive (les xxxTableId , les xxxDictionaryId et autres) apparu en 2013.

La question est savoir qu’est-ce que ce « Dynamic » apporte ou enlève et dans quel contexte on peut l’utiliser avantageusement. Suite à cet article, peut-être que certains d’entre vous seront découragés de l’utiliser, pas à cause de sa complexité mais de sa pertinence, en tout cas, j’espère que ce ne sera pas parce que je vous ai embrouilléJ. Pour ne pas vous faire perdre votre temps, disons que l’intérêt augmente si vous utilisez AutoCAD WS, le Cloud ou toute technologie Web ou de langage script (Python, Ruby, Perl, VB Script, Java Script, Microsoft Silverlight, etc.). On y reviendra.

Bref rappel de COM (Component Object Model)

Pour comprendre la nouveauté, il faut encore une fois refaire une rétrospective de la technologie visée. Nous allons parler très brièvement de COM et de DotNet et comment ces interfaces communiquent avec d’autres applications.

Nous avons probablement tous entendu parler de COM (Component Object Model)  et d’ActiveX. Au sens large, la famille des technologies COM comprend OLE, COM, COM +, DCOM (Distributed COM) et les contrôles ActiveX et on confond parfois les termes alors que ce sont diverses évolutions. Si vous avez travaillé avec AutoLISP, vous avez sans doute remarqué les fonctions débutant par VLA (le A pour ActiveX) ainsi que la fonction (vl-load-com). Vous avez peut-être aussi travaillé avec des contrôles OCX (OLE (Object Linking and Embedding) Control) Extension) pour afficher la liste des calques en VBA. En gros, COM offre un mécanisme permettant de diffuser des objets dans des environnements inconnus au moment de leur création et du contexte où ils seront utilisés. Une application COM est un serveur de données en ce sens qu’elle va servir des données à son client.

Pour que la communication puisse s’établir avec le client (votre application AutoLISP, VB ou autre), il doit y avoir une interface de communication. Il y en a même souvent 2 : l’une obligatoire et complètement générique (IDispatch) et l’autre facultative et qui est très typée. De l’autre côté, lorsque vous programmez et faites référence à ces objets, vous pouvez soit typer vos variables ou ne pas le faire (c’est-à-dire les typer implicitement en Object). C’est suite à votre déclaration de type que votre compilateur choisira l’interface appropriée. Pour réussir sa tâche, le compilateur se base sur un petit lexique appelé Type Library.  Ces librairies de type sont des fichiers à extension TLB ou TLE. Évidemment, ne pas typer vos variables rend le traitement plus lent.

Rappelons au passage qu’un composant COM a été créé avec l’objectif d’être utilisé dans un environnement inconnu. C’est pourquoi l’échange de données requiert un format neutre soit les Variants, SafeArrays (avec AutoLISP) ainsi que les IDispatch et BSTRs dans d’autres langages. Une fois un variant récupéré, on peut interroger celui-ci afin de lui un type plus précis tel que vlax-vbEmpty, vlax-vbNull, vlax-vbInteger, vlax-vbLong, vlax-vbSingle, vlax-vbDouble, vlax-vbString, vlax-vbObject, vlax-vbBoolean, vlax-vbArray en AutoLISP ou en VT_BOOL, VT_BSTR, VT_CY, VT_DATE, VT_DISPATCH, VT_I2, VT_I4, VT_I8, VT_R4, VT_R8 dans d’autres langages.

Liaison hâtive vs liaison tardive

Lorsque vous omettez de déclarer le type de donnée, on parle de liaison tardive ou late binding. Par opposition, quand vous le faites, on parle de liaison hâtive ou early binding. Dans le premier cas, on parle aussi de façon informelle de duck typing ou de  name binding (recherchez Alex Martelli pour les origines du terme).

Les avantages de déclarer le type de variables sont nombreux : le code s’exécute plus rapidement, le compilateur peut vous assister dans la résolution et la prévention des erreurs; vous disposez de la technologie IntelliSense pour la composition du code et vous profitez de l’aide dynamique. Pour ce qui est de l’IntelliSense, il est encore trop tôt pour me prononcer mais comme je travaille beaucoup avec ObjectARX ces temps-ci, j’ai mis à jour ma licence du logiciel Visual Assist X de Whole Tomato Software. Cet outil réussi à faire des miracles. Peut-être fait-il de l’IntelliSense là ou Visual Studio ne le fait pas. Pour ceux qui font de la programmation sur une base régulière, je vous invite à le découvrir.

Sauf si vous désirez bénéficier des avantages de la liaison tardive expliqués tout de suite après, je vous incite très fortement à déclarer et à typer toutes vos variables quand cela est possible et utile et à utiliser les méthodes de nettoyage et de fermeture appropriées afin de ne pas laisser des objets en mémoire. En plus, cela rend le code plus clair.

Il ne faut pas croire que la liaison tardive n’a que des inconvénients. Le principal avantage d'utiliser la liaison tardive avec COM est qu'il ne requiert pas du compilateur de référencer les bibliothèques qui contiennent l'objet au moment de la compilation. Cela rend le processus de compilation plus résistant à des conflits de version. Il est également idéal pour l’usage de scripts avec des applications telles que l’Internet Explorer ou les programmes de la suite Office, car il jouit d’une interface plus flexibles en n’exigeant pas de connaitre l'API correspondant au moment de la compilation.

La réflexion dans DotNet

Lorsque DotNet est apparu, on a voulu reprendre le concept d’interface utilisé par COM mais en repartant à zéro. Dans sa première version, DotNet avait même omis de supporter COM, ce qui avait soulevé les protestations justifiées de la communauté de développeurs.  Pour découvrir les types de données et d'invoquer leurs membres à l'exécution, DotNet utilise la réflexion. Celle-ci permet d'inspecter dynamiquement le contenu d'assemblages, d'en lire ses types, de créer des instances de ces types durant l'exécution du programme et d'appeler leurs méthodes ou champs dynamiquement. Ce n’est peut-être pas révolutionnaire pour ceux qui sont habitué de faire des programmes pour un poste de travail mais ça l’est pour ceux qui travaillent avec les applications Web.

Traiter de la réflexion dépasse la portée de cet article mais pour ceux que ça intéresse, recherchez les termes manifest, System.Reflection, marshaling, C++ mangling et Dependency Walker. Cela pourrait vous servir car il existe plusieurs méthodes qui ne sont pas exposées via le fichier acdbmgd.dll et qu’il faut les puiser à même le fichier acad.exe.

En principe, COM ne devait pas faire partie de DotNet mais heureusement que ce n’est pas le cas. Il se peut que vous ayez besoin de combiner les 2 technologies. Prenons par exemple la commande NORMES dans AutoCAD qui vérifie la qualité de certaines normes. Puisque cette commande est incomplète (en fait, ce n’est pas un défaut : les normes sont comme les flocons de neige, elles se ressemblent toutes mais en les regardant de près, il n’y en a pas une pareille), vous devez créer des plugins personnalisés. Le même processus s’applique à la gestion des fenêtres nommées Palettes.

La première étape pour la réalisation d’un tel plugin est d’exposer les composants COM du serveur (ici, acad.exe) depuis axdb17enu.tlb  (ou axdb18enu.tlb ou suivants)  et de acstmgr.tlb au Framework via l’outil tlbimp de Visual Studio. Vous obtenez ainsi un assembly PIA (Primary Interop Assembly). Il vous reste ensuite à importer ces références dans votre solution DotNet puis à créer un fichier *.reg pour vos utilisateurs (ou pour vous-même) pour l’enregistrement du composant dans la base de registres (ou encore d’utiliser un Assistant de déploiement comme InstallShield ou InstallAware). Vous devez finalement implémenter toutes les méthodes que le composant COM utilisera pour communiquer avec votre programme. C’est exactement comme lorsque vous définissez la fonction *error* en AutoLISP avec un paramètre obligatoire msg, ou encore la fonction S::STARTUP, ou encore certaines fonctions de rappel (callback function) avec le langage DCL ou les réacteurs que vous définissez mais que vous n’appelez jamais vous-même.

'Exemple de déclaration

Imports System.Runtime.InteropServices

<System.Runtime.InteropServices.ProgId("MonEspaceDeNom.MaClasse"), _ ComClass()> Public Class MaClasse

    Implements AcStMgr.IAcStPlugin2

 

' Déclaration des variables ici.

 

' Déclaration des fonctions d’échange ici.

 

' Initialize -- Initializes the plugin

' This is the only member function in which the interface is

' passed an IAcStManager interface.

   Public Sub Initialize(ByVal pMgr As AcStMgr.AcStManager) _

   Implements AcStMgr.IAcStPlugin2.Initialize

      '   Store pointer to Manager object

      m_pManager = pMgr

      m_pPlugin = Me

   End Sub

 

   'GetObjectFilter -- Plugin populates the provided array

   'with class names of objects that it can check

   'In this case we're only interested in circles

   Public Function GetObjectFilter() As Object _

   Implements AcStMgr.IAcStPlugin2.GetObjectFilter

      Dim sFilterArray(0) As String

      sFilterArray(0) = "AcDbCircle"

      GetObjectFilter = sFilterArray

   End Function

 

   ' La liste des fonctions à définir est beaucoup plus longue.

 

End Class

 

Comme nous l’avons vu, ne pas déclarer de type, c’est-à-dire les déclarer implicitement en Object,  a parfois ses avantages. C’est ainsi que les langages script (ne pas confondre avec les fichiers à extension SCR d’AutoCAD) s’adaptent très facilement aux environnements Web.

Les 3 grands paradigmes de programmation et le F#

Le courant actuel de programmation vante les mérites de l’omission des types de données (duck typing) et ici, on ne parle pas de tirer avantages en liaison tardive tel que nous l’avons montré précédemment. Qu’est-ce qu’il y a de nouveau cette fois? Pour suivre le courant de pensées où l’on a parfois l’impression de revoir le film « Retour vers le futur » (en anglais « Back to the future »), il est bon de présenter comment les choses ont évolués.

En 2005 est apparu le langage F#. La motivation derrière l'apprentissage de F# semble un mystère total. Quel est en effet l'intérêt de F# pour les développeurs, surtout pour ceux qui travaillent avec AutoCAD et qui sont familiers soit avec VB ou C#? Pourtant, on a vu plusieurs blogs de Kean Walmsley à ce sujet. Cela mérite donc qu’on s’y attarde.

Pour répondre, il faut encore une fois revenir à la base. Il existe 3 grands paradigmes de programmation (sur une trentaine possible) : impérative, fonctionnel, et orienté objet.

   La programmation impérative inclut les langages évolués non orientés objet tel que FORTRAN, PASCAL, VB, C, etc. Ces langages de haut niveau comportent essentiellement quatre types d'instructions principales : l'assignation ; le branchement conditionnel ; le branchement sans condition ; le bouclage.

      La programmation fonctionnelle est le plus ancien des trois, en commençant IPL (Information Processing Language) en 1956 puis rendu populaire avec l'apparition de LISP (LISt of parenthesis) en 1958 (l’ancêtre du Common LISP en 1984 et d’AutoLISP en 1986) puis  le langage SQL (Structured Query Language) et XSLT (eXtensible Stylesheet Language Transformation). Le paradigme fonctionnel permet l’emboîtement de fonctions que l'on imbriquer les unesutes refermées (enfin, je crois (il faudrait que je fasse un copier-coller du présent document Word dans l’interface de Visual Lisp pour le vérifier))).

   La programmation orientée objet consiste en la définition et l’assemblage de briques logicielles appelées objets, lesquels contiennent à la fois des données et des méthodes qui peuvent être soit privées, soit publiques ou même soit protégées. Elle permet également de créer des objets plus complexes en les dérivant d’une ou de plusieurs classes de base plus simple.

Pendant des années, le domaine des langages fonctionnels était considéré moins noble pour le développement professionnel. Le manque d'intérêt dans ces langages s'expliquait surtout par le fait qu'ils s'adressaient à des plates-formes peu intéressantes pour les développeurs écrivant des programmes pour Windows ou qu'ils ne prenaient pas en charge des fonctionnalités clés telles que l'accès à des données relationnelles, l'analyse XML et des mécanismes de communication out-of-process (rappel à ce sujet : VBA sur AutoCAD 32 bits faisait des appels in-process jusqu’à ce qu’il soit intégré à une version 64 bits où il est devenu out-of-process).

Cependant, avec le CLR et son approche « plusieurs langages pour une seule plate-forme », l'introduction d'autres langages tel que F#  dans l'univers du développement Windows était inévitable. Il était tout aussi inévitable qu'ils commencent à se faire connaître auprès des programmeurs.

Visual Studio 2008 a commencé à utiliser de façon hybride les paradigmes impératif et fonctionnel dans la technologie LINQ en permettant d’effectuer des requêtes sur à peu près n’importe quel objet.

F# est un nouveau langage qui utilise de façon hybride les 2 paradigmes. En plus, décourage fortement l'utilisation de valeurs nulles et encourage l'utilisation de structures de données immuables ou persistantes, c’est-à-dire que les opérations ne les modifient pas en place  mais renvoient au contraire de nouvelles structures. La structure de données persistante la plus simple est sans doute celle de liste simplement chaînée, où chaque élément contient une référence vers l'élément suivant dans la liste (en AutoLISP, on pale de liste et en DotNet ou ObjectARX, on parle de Result Buffer ou Resbuff). Ceci aide à réduire la fréquence des bogues dans la programmation en réduisant la quantité de code de cas particuliers requise.

Les programmes écrits en F# ont également tendance à être plus concis. Vous tapez et typez moins (ah bon!) : moins de frappes et moins d'endroits où le compilateur doit connaître le type de la variable, des arguments ou du retour. F# est donc un langage ayant un profil de performances similaire à VB ou C#, ce qui est bien supérieur aux langages concis comparables, en particulier les langages dynamiques et de script. C’est la raison pour laquelle il devient un choix plus qu’intéressant lorsque vient le temps de penser à LandXML, AutoCAD WS (Web Service), et les applications résidant sur le Cloud-computing.

Malgré qu’on n’ait pas à le faire explicitement, F# demeure un langage fortement typé utilisant l'inférence de type. Ceci est un mécanisme permettant au compilateur de trouver automatiquement les types le plus général associés à des expressions, sans qu'ils ne soient indiqués explicitement dans le code source. Pour ceux qui ont programmé avec l’ancêtre d’ObjectARX, l’AutoCAD Development System (ADS), ceci s’apparente davantage à la déclaration Union que l’on retrouvait dans les listes chainées de type Resbuff. Avec l’inférence de type, l'expression est évaluée dès qu'elle peut être liée à une variable.

L'inférence de types va de pair avec le polymorphisme, puisque le compilateur génère des types abstraits au besoin d’où sa très grande adaptabilité. Contrairement à la technologie COM ou l’on traitait un cas générique (IDispatch) et un cas typé, le compilateur conserve à l’interne une liste des variables fortement typés.

Les avantages à disposer de ce mécanisme sont multiples : le code source est plus aéré, le développeur n'a pas à se soucier de retenir les noms de types, l'interpréteur fournit un moyen au développeur de vérifier (en partie) le code qu'il a écrit et le programme est peu modifié en cas de changement de structure de données. Les expressions restent les plus générales possibles.

Quoi de neuf avec Visual Studio 2010

Nous voici enfin presque préparé à comprendre un peu mieux ce que voulait dire le « Dynamic » au début de cet article. Auparavant, il nous reste une étape à franchir, celle de faire un résumé des nouveautés de Visual Studio 2010.

Comme nous l’avons vu, lorsque le langage F# est apparu, il offrait un nouveau concept de paradigmes hybrides permettant de définir les traitements algorithmiques sur les données plutôt que de s’acharner à les traiter via de très nombreuses conditions linéaires. Cette légèreté lui conférait une certaine longueur d’avance sur ses compétiteurs. Nous avons vu cependant que Visual Studio 2008 avait commencé à bonifier les langages C# et VB afin qu’ils utilisent LINQ, un concept lui-même hybride ainsi que les types anonymes (comme en F#). Visual Studio 2010 raccourcit davantage l’écart entre ces langages en introduisant de nouveaux concepts de paradigme fonctionnel comme les fonctions Lambda (et oui, on revient à notre bon vieux AutoLISP) ainsi que la covariance et contravariance (échange entre des objets de même parentés mais soit de la classe de base vers une classe dérivée ou l’inverse). Il y a bien d’autres nouveautés mais elles ne sont pas pertinentes pour cet article. Vous pouvez facilement faire des recherches en ligne pour les découvrir.

Nonobstant ce qui a été dit, le langage F# demeure attrayant pour les situations précitées et parce qu’il est très simple de l’utiliser lorsque vient temps de traiter de complexes et grandes banques données grâce à sa verbosité simplifiée.

Utilisation du type dynamic

Il existe 2 techniques de typage de données : statique et dynamique. Le typage statique est une technique utilisée dans certains langages de programmation impératifs que nous avons vu (VB, C#, ++, etc) et qui consiste à déclarer le type à l’avance. Le typage dynamique est une technique utilisée dans certains langages de programmation fonctionnelle comme AutoLISP et est une solution très commode pour le développement rapide de programmes, où le type des objets manipulés n'est pas forcément connu à l'avance.

Visual Studio 2010 introduit maintenant une nouvelle déclaration de type appelé dynamic. Contrairement à ce que son nom laisse présager, il s'agit d'un type statique, donc performant, sauf que pour un objet de type dynamic, l’environnement de développement fait abstraction de la vérification des types et le compilateur fait le travail de typer à votre place selon le meilleur usage. En fait, sans être un objet de type Object, il se comporte dans la plupart des cas comme s'il en était un mais sans sa lenteur. Au moment de la compilation, un élément de ce type est supposé prendre en charge n'importe quelle opération. Par conséquent, tel qu’avec la liaison tardive, vous n'avez pas besoin de savoir si l'objet obtient sa valeur à partir d'une API COM, les API d'automation Office, Visual Studio Tools for Office (VSTO), d'un langage de script tel que Python, Ruby, etc., du modèle d'objet de document (DOM, Document Object Model) HTML, XML ou LandXML, de la réflexion, d’une requête LINQ ou d'une autre partie du programme. Toutefois, si le code n'est pas valide, des erreurs sont détectées au moment de l'exécution (les runtime error).

Il existe une différence fondamentale entre une déclaration statique normale et une dynamique. La première, comme nous l’avons vu fait en sorte que le programme est pris en charge par le Common Language Runtime (CLR). Avec le type dynamique, le programme est pris en charge par le Dynamic Language Runtime (DLR). La CLR ne gère que les langages propres à Microsoft tandis que la DLR de Microsoft a été créée pour prendre en charge d'autres langages.

Comme nous l’avons vu, la programmation fonctionnelle (comme AutoLISP) est orientée dans l’interprétation des données tandis que la programmation impérative (VB et C#) est orientée instructions. On peut voir dans les 3 prochains tableaux comment les 3 langages communs pour AutoCAD commencent drôlement à se ressembler lorsqu’ils utilisent le même paradigme. Dans aucun des cas, on n’a besoin de se soucier des transactions ou du mécanisme d’ouverture et de fermeture des objets.

C#

public static void ChangeLayerNamesDynamically()

{

   dynamic layers =

      HostApplicationServices.WorkingDatabase.LayerTableId;

   foreach (dynamic l in layers)

      if (l.Name != "0")

        Debug.Print("First Floor " + l.Name);

}

 

VB

Public Shared Sub ChangeLayerNamesDynamically()

   Dim layers As dynamic = _

      HostApplicationServices.WorkingDatabase.LayerTableId

 

   For Each l As dynamic In layers

      If l.Name <> "0" Then

         Debug.Print("First Floor " & l.Name)

      End If

   Next

End Sub

 

AutoLISP

(defun c:test (

 / CurrentName layer

   )

   (setq layer (tblnext "layer" t))

   (while layer

      (setq CurrentName (cdr (assoc 2 layer)))

      (if (/= CurrentName "0")

         (princ (strcat "\nFirst Floor " CurrentName))

      )

      (setq layer (tblnext "layer"))

   )

   (princ)

)

 

Au moment d’écrire cet article, il ne me reste qu’une chose à vérifier soit comment le tout se comporte avec la gestion des erreurs (Try Catch Finally) et le ramasse-miettes (garbage collection). Question de performance, il est vrai que très peu de gens se soient plaint de la performance d’AutoLISP jusqu’à maintenant. Il y a encore moins de chance que cela se produise avec le nouveau paradigme. Je crois d’emblée que plusieurs adeptes d’AutoLISP qui n’avait pas encore fait le saut vers DotNet seront tentés de le faire. Par contre, d’expérience je peux vous dire que lorsque quelque chose commence à aller mal, c’est toujours plus facile de résoudre le problème quand on sait ce qui se passe sous le capot.

Plus ça change, plus c’est semblable

Vous croyez revoir le film « Retour vers le futur » ? Dans la même veine, dans les années 80, nous nous sommes réjoui de pouvoir délaisser les ordinateurs centraux au profit des ordinateurs personnels pour revenir à des super-ordinateurs sur la toile ou encore le Cloud-Computing. On a aussi déjà été capable, jusqu’en 1995 et AutoCAD R13 d’installer de nouveaux postes en effectuant une simple copie des fichiers avant d’être obligé d’utiliser un Assistant d’installation puis on nous a annoncé en grande pompe que le DLL Hell était enfin révolu parce qu’on pouvait désormais copier nos DLL de DotNet sans avoir à les installer. Vous me direz que plus ça change et plus c’est pareil. Disons que c’est comme les premiers Européens qui ont franchis l’Atlantique : ils voulaient quitter l’ancien monde mais il ont tout fait pour l’imiter dans le nouveau.