Episode 8: Mathias découvre COM

Bonjour tout le monde, et merci de votre patience…
Ça fait presque 5 mois que je n’ai pas blogué, et que j’ai interrompu ma série « Mathias découvre… »
Comme j’en découvre tous les jours, j’ajouterai bien d’autres épisodes avant la conclusion finale, mais j’ai peur que ça dure une éternité 🙂
En réalité, je voulais « jouer la montre » avec ces blogs, afin de stabiliser mon projet et lui trouver un nom sympathique. Mais je n’ai pas vraiment trouvé le temps d’y travailler, alors je vais « pousser l’oisillon hors du nid », et j’ajusterai plus tard s’il ne vole pas très bien ;D

Je change de sujet par rapport aux précédents postes, et je m’attaque à un autre sujet épineux: la communication inter-processus.

Au début de ma vie professionnel, je n’ai pas commencé à travailler en .Net, mais en Delphi.

J’avoue que Delphi était séduisant. Avant .Net, c’était la manière la plus efficace de réaliser des applications Windows lourde avec un Designer d’interface unique. Et puis, n’oublions pas que l’inventeur du langage Delphi n’est autre que Anders Hejlsberg, qui fut embauché par Microsoft pour inventer C# !

Quand .Net prenait de plus en plus d’ampleur,  j’ai alors réussi à convaincre tout le monde de s’y mettre.
Mais comme la migration devait se faire petit à petit, il fallait intégrer Delphi avec .Net.

Pour cela, j’ai découvert COM.
COM est une technologie 100% Microsoft, mais qui se base sur les mêmes principes que Corba.
COM permet de communiquer entre les applications, peu importe le langage. La communication se faisait en activant des services, à l’aide d’un contrat qui se rédigeait dans un langage indépendant du langage de compilation : IDL (Interface Definition Language).

C’était magique : on pouvait inclure un UserControl .Net dans une application Delphi existante ! On pouvait aussi appeler des services .Net depuis Delphi, et vis vers ça !

Les services étaient d’ailleurs enregistrés auprès de Windows, dans la base de registre. Donc, quand un programme Delphi demande un service qui répond à une interface, Windows se charge de le localiser (DLL ou EXE) de l’héberger dans un conteneur (dans le cas de l’EXE, il lance ce dernier, dans le cas de la DLL, il l’host dans DLLHOST.exe) et d’instancier le service pour qu’il puisse être utilisé.

Et ce n’est pas tout ! Il y avait aussi DCOM qui est la version distribué de COM. Cela veut dire que si la DLL n’est pas sur la machine actuelle, Windows se charge d’interroger les autres serveurs DCOM pour qu’ils instancient le service à distance ! Tout cela avec une couche de sécurité ultra complexe !

De plus, le langage IDL supporte les méthodes, les propriétés, les événements, les paramètres de type « out », l’héritage d’interfaces, la gestion des versions, etc.…

Si vous souhaiter exposer des services sous Windows, cette technologie semble la plus appropriée.

Dans le monde des serveurs J2EE, ce fût Corba, concurrent direct à COM, qui remplissait ce rôle.

Mais voila : COM est 100% Windows, 100% Natif (non managé) ce qui rend le pont COM-.Net peu performant.

Concernant CORBA, il existe bien des connecteurs pour .Net, mais pas de serveur CORBA 100% managé.
De plus, CORBA est abandonné dans certains domaines à cause de sa lourdeur : les distributions Linux ont migré de CORBA à DBUS pour avoir aussi leur « équivalent à COM ». A noter que DBus existent en 100% .Net: http://www.ndesk.org/DBusSharp

Microsoft abandonne d’ailleurs COM pour sa technologie de communication phare : WCF.
Avant WCF, Microsoft avait introduit une autre solution 100% .Net: .Net Remoting. Mais ce dernier était trop simple et a fini par être abandonné, même si c’est toujours la technologie par défaut pour communiquer inter-AppDomain.

Alors, que choisir comme technologie de communication et d’activation de service ? Point à Point ou par un intermédiaire (Bus/Broker)? Quel format de message/marshalling doit-on utiliser?

Pour ma part: COM n’est pas multi-plateforme, je ne suis pas convaincu par l’usine à gaz WCF, DBusSharp est trop bugué, .Net remoting est trop simple/limité… je reste un sur ma fin.

Mais entre temps, j’ai découvert le « Messaging » et la communication asynchrone, qui est parfaite pour un environnement distribué. On ne peut pas remplacer le RPC par le Messaging dans tous les cas, mais il a falloir que j’exploite cette voie.

DBus avec .Net

Pour ceux qui ne le savent pas, je travail sur un serveur d’application .Net indépendant de la plateforme Windows: DotNetServer.

Après une version bonne pour une démo, j’ai voulu refactoriser le tout pour avoir quelque chose de viable.
Dans mon dernier billet, j’explique mon périple à la recherche d’un protocole de communication Inter-Processus, et j’ai choisi NDesk.DBus: l’implémentation full .Net de D-Bus.

La solution était sexy:

  • Déclaration des services par interface, ne pouvant exposer QUE des types simples ou Struct. Cela force à réaliser qu’en matière de communication, une instance d’objet ne veut rien dire et qu’on communique que par DTO.
  • Support des méthodes, propriétés et événements
  • Channel par Socket/TCP ou par Pipe
  • Communication optimisé binaire (pas d’XML ou de SOAP….)
  • Exposition des services sur le Bus avec un contrat au format XML (comme un WSDL en quelque sorte)
  • Cross-platform: provient du monde Linux mais existe sous Windows
  • Un standard de communication Inter-Processus, de plus en plus utilisé sous Linux, remplaçant CORBA (avec Bonobo)

Mais voila, tout n’est pas rose, et DBus me donne du fil à retorde.
L’implémentation .Net n’est pas très propre:

  • API pas très utilisable car quasiment tout est Internal
  • Pas de doc?
  • Ça manque de convention, le source n’est pas très lisible, j’ai envie de passer un coup de Resharper dessus 🙂
  • Beaucoup, beaucoup de commentaire du genre « //temporary hack » ou « //TODO« … beaucoup de code commenté qui prouve que la personne a voulu faire bien mais n’a pas eu le temps
  • Quand j’exécute DBusExplorer pour scanner mes services, cela plante 1 fois sur 2 mon client
  • Je n’arrive pas à faire marcher un service ou un client dans un Thread!!! Cela me bloque totalement

Je me demande si je ne vais pas revenir à une solution .Net Remoting:

  • implémentation .Net et Mono
  • channel IPC (par Pipe)
  • supporte les événements
  • DBus est vraiment orienté « Desktop » comme le D l’indique. J’en fait donc une utilisation détournée.

Mais une autre solution peut aussi faire l’affaire: ProtoBuf, un protocole performant inventé par Google.

Je vais tacher de vous tenir plus au courant, histoire aussi de recueillir des opinions concernant mes choix.

DotNetServer

Comme je tarde à sortir mes posts sur les Techdays (et d’autres sujets, haha, surprise!), je vais en sortir un « tout petit ».

Pas de conteneur d’application en .Net… ou presque

En fait, c’est suite à une frustration absolue datant du premier jour ou j’ai découvert .Net (car je faisais du Java, avant, dans mon temps libre…).
Après avoir lourdement digéré J2EE, les EJB, RMI/IIOP, j’ai été déçu de ne rien voir de tel en .Net.
Certains dirait que ce n’est pas une grosse perte 😉 En effet, J2EE n’a rien de simple, mais c’est quand même parfois puissant.

Je trouve stressant qu’une application .Net « d’entreprise » doit forcement dépendre des services Windows, des tâches schédulées, ou d’IIS. Déployer une application Java sur Tomcat est d’une simplicité déconcertante, et Microsoft propose un équivalent seulement dans le future Windows Server 2008 R2 avec Windows AppFabric.
Et encore, pour avoir vu la présentation aux Techdays, je suis plutôt déçu.

Lire la suite