IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Comment migrer vos projets vers VB.NET ?

Cet article explique quelle stratégie de migration adopter et comment migrer vos projets vers VB.NET. ♪

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

Introduction

Avec l'avènement de la plate-forme Microsoft .NET et le nombre important d'applications Web et Windows développées en Visual Basic, la problématique de migration vers VB .Net est d'actualité. Alors quelles sont les motivations pour migrer vers VB .NET (ou C#) ? Faut- il migrer ou non vos projets vers VB .NET ? Visual Basic est-il en fin de vie ?

Ces réponses peuvent varier en fonction de vos projets de développement, de l'expertise de vos équipes de développement, de la taille de votre entreprise, etc. Nous nous efforcerons d'y répondre dans la première partie de notre article.

Enfin cet article ne serait pas complet sans la réalisation d'une migration d'une partie applicative. J'ai choisi de vous montrer un exemple de migration d'une couche d'accès aux données. En termes de complexité c'est une couche intéressante, car transactionnelle s'appuyant sur les services transactionnels COM+ et utilisant les ADO comme composants d'accès aux données.

I. Faut-il migrer vers VB .NET ?

La migration vers VB .Net n'est pas une obligation, et un applicatif qui fonctionne parfaitement aujourd'hui et répond à vos besoins n'a pas de raisons de migrer vers VB .Net. Néanmoins, il se peut qu'une mise à jour ou une nouvelle version de votre projet vous impose de choisir entre Visual Basic et Visual Basic .Net. Ce choix ne peut se faire qu'en considérant plusieurs facteurs et en évaluant leurs avantages et leurs inconvénients. Une fois la décision prise, il faut définir la stratégie à adopter pour réaliser la migration.

I-A. Les avantages

Les nouveautés majeures VB .Net :

  • Visual Basic .Net est un véritable langage orienté objet (l'héritage, le polymorphisme sont une réalité) ;
  • la gestion des erreurs est améliorée via la gestion structurée des exceptions ;
  • la prise en charge d'applications multithreadées est désormais possible.

La plate-forme .NET :

  • une meilleure scalabilité : Les ADO .Net améliorent la scalabilité de votre application en favorisant le mode déconnecté et en réduisant le nombre de connexions et de verrous SGBD. La gestion de la Session ASP a été améliorée et peut être partagée parmi plusieurs serveurs d'une ferme Web ;
  • des performances accrues : L'objet DataReader a été conçu pour sa rapidité d'accès aux données. Les pages ASP .Net sont désormais compilées ;
  • un déploiement facilité : Le déploiement de votre application sera réalisé par un simple XCOPY.

I-B. L'estimation des coûts de la migration

Passer à Visual Basic .NET ne signifie pas simplement changer la syntaxe du langage à utiliser. Le développeur doit monter en compétences sur de nombreux volets : en programmation orientée objet ou connaissance du FrameWork .NET. Cette mise à niveau à un coût non négligeable. Les premiers retours d'expérience sur .NET montrent que les coûts initiaux d'acquisition de la technologie et d'implémentation sont, à terme, compensés par les gains de productivité et de maintenance.

Comme je l'ai précisé plus haut, la notion de coût dépend aussi de votre structure. Si c'est un facteur déterminant pour vous, il faut savoir que d'autres solutions sont possibles. Par exemple, migrer votre application partie par partie permet de réduire les coûts et de s'approprier la technologie progressivement.

I-C. Le type d'application à migrer

Le type d'application est également un facteur important à prendre en compte. L'application est-elle une application Web ? Le code est-il modulaire ? La technologie que j'utilise aujourd'hui est-elle implémentée en Visual Basic .Net ? Autant de questions qui vous orienteront ou non vers une migration.

II. Quelle stratégie adopter pour réaliser la migration ?

Nous entrons enfin dans le vif du sujet. Trois possibilités de migration sont offertes, soit réécrire totalement votre application en Visual Basic .Net, soit la migrer totalement, soit la migrer partiellement.

II-A. La réécriture de votre application

Cette option s'avère intéressante si vous souhaitez :

  • bénéficier de meilleures performances et accroître la scalabilité de votre application (l'utilisation d'ASP .Net et ADO .Net permet de les améliorer) ;
  • migrer votre application, mais que le code existant Visual Basic ne possède pas d'équivalence en Visual Basic .Net ou qu'il est impossible de le migrer.

Cette solution présente les inconvénients suivants :

  • pas de réutilisabilité du code existant ;
  • investissement humain et financier important.

II-B. La migration totale

Avantages :

  • réutilisation d'une partie du code existant ;
  • amélioration des performances et de la scalabilité pour les parties migrées.

Inconvénients :

  • le code migré n'est pas forcément performant et nécessitera des réajustements ;
  • certaines portions migrées (par exemple utilisant les ADO) ne bénéficieront pas des avantages de .NET.

II-C. La migration partielle

Avantages :

  • amélioration des performances et de la scalabilité pour les parties migrées ;
  • préservation de l'investissement en réutilisant du code existant.

Inconvénients :

  • l'utilisation simultanée de Visual Basic et de Visual Basic .Net peut engendrer des problèmes de déploiement et de maintenance ;
  • l'interopérabilité COM+/.NET peut légèrement dégrader les performances de votre application.

Il n'y a pas de solution unique et chacun doit trouver la solution qui s'adapte à ses besoins. En revanche, la solution de migration partielle me semble être un bon compromis. Elle consiste à migrer les éléments de votre application en fonction de vos besoins. Elle permet de préserver l'existant et de réutiliser votre code via l'interopérabilité COM+/.Net. Elle permet d'acquérir progressivement des compétences sur la technologie et d'en tirer des enseignements pour les futurs développements .Net.

III. La migration d'un projet Visual Basic vers VB .Net

Le projet que nous allons étudier est un projet n-tiers respectant l'architecture Windows DNA. Il est constitué d'une couche ASP de présentation, d'une couche d'objets métiers implémentant les règles de gestion et d'une couche de persistance de données utilisant les ADO. Nous migrerons une partie de cette dernière couche.

III-A. Considérations générales

III-A-1. Les fonctionnalités non supportées

Certaines fonctionnalités ne sont plus supportées par VB .NET et ne pourront pas être migrées par l'assistant :

  • le contrôle OLE Container ;
  • Dynamic Data Exchange (DDE) ;
  • le data Binding DAO et RDO ;
  • les contrôles Visual Basic 5 ;
  • les applications DHTML ;
  • les active X Documents ;
  • les property pages.

Les applications utilisant ces fonctionnalités devront soit rester en l'état en Visual Basic 6.0 (Property pages par exemple) soit migrer vers .NET (transformation des ActiveX documents en contrôles utilisateurs).

III-A-2. Les mots clés non supportés

Certains mots clés ont été supprimés du langage.

Mot clé

Description

Def <type>

Il faut explicitement déclarer les variables.

Goto / Gosub

Ces instructions peuvent être remplacées par des If ou des Select Case.

Gosub / Return

Ces instructions peuvent être remplacées par l'utilisation de fonctions ou de procédures.

Option Base 0 | 1

Les tableaux sont indicés à 0.

VarPtr, ObjPtr, StrPtr

Ces fonctions utilisées pour récupérer l'adresse mémoire de certaines variables ne sont plus utilisées.

LSet

Cette fonction permettant l'assignation de type de données n'est plus supportée.

III-B. La stratégie de mise à niveau

Il est recommandé d'installer votre projet sur la machine d'où sera lancée la migration. Cela garantit que le projet VB6 fonctionne et que tous les éléments utilisés par le projet (composants, contrôles …) sont disponibles au moment de la migration.

D'autre part l'assistant de migration accepte seulement des projets Visual Basic 6. Donc si vous disposez de versions antérieures, il est recommandé de les migrer au préalable vers Visual Basic 6.

Image non disponible

La mise à niveau peut être réalisée par étapes en commençant par la partie cliente, puis les objets métiers, et enfin les objets données. Il est possible d'aller au-delà du simple portage et d'intégrer les améliorations du framework .NET. À noter que la migration sera d'autant plus facilitée que votre application a été conçue de façon modulaire et qu'elle respecte certaines bonnes pratiques de programmation. Nous verrons tout ceci en détail par la suite.

III-C. La migration par la pratique à l'aide de l'assistant de migration VS.Net

La migration d'un projet peut être décomposée en plusieurs étapes que nous allons décrire ci-dessous.

  1. Choix des éléments à migrer.
    Il convient de définir quelles parties applicatives vont être migrées en se référant à la stratégie présentée ci-dessus.
  2. Préparation à la migration du projet Visual Basic 6.
    Des corrections peuvent être apportées au code Visual Basic 6 avant le passage de l'assistant de mise à niveau. Il est plus simple de traiter ces corrections directement en Visual Basic et de laisser l'assistant effectuer la mise à jour plutôt que de les effectuer une fois la mise à niveau réalisée.
  3. Migration de l'application via l'assistant de migration de l'VS.Net
  4. Correction des anomalies détectées par l'assistant.
    L'assistant ne corrige qu'une partie des problèmes; charge au développeur de compléter la mise à niveau.
  5. Test de l'application.
    Une fois la mise à niveau achevée, il faut réaliser les tests de non-régression pour s'assurer que l'application présente toujours les comportements attendus.

III-C-1. Choix des éléments à migrer

J'ai choisi de migrer une classe DataAccess d'un composant DataComp représenté physiquement sous la forme d'une DLL. Elle est transactionnelle. Pour les besoins de l'exemple, nous positionnerons ses propriétés transactionnelles à « Transaction Obligatoire » : lorsqu'une de ses méthodes est invoquée, une transaction est initiée.

Nous allons concentrer nos efforts de migration sur une méthode nommée CreerClient donc voici l'interface :

 
Sélectionnez
Function CreerClient(ByVal sSiret As String, _
   ByVal sNomClient As String, _
   ByVal iNumero As Integer, _
   ByVal sRue As String, _
   ByVal sCodePostal As String, _
   ByVal sCommune As String, _
   ByRef vIdentifiant As Variant) As Integer

Cette méthode va créer un client à partir de son siret, de son nom et de son adresse. Elle récupère dès lors l'identifiant du client qui a été généré. Cet identifiant est de type Variant afin de vérifier sa transformation en type Object par l'assistant de migration.

III-C-2. Préparation à la migration du projet Visual Basic 6

Voici les quelques pièges à éviter et à corriger dans votre projet Visual Basic 6 avant la réalisation de la migration :

  • utiliser des liaisons précoces et des conversions explicites de données ;
  • utiliser le type de données Date pour stocker des dates ;
  • utiliser les constantes prédéfinies Visual Basic et non les valeurs sous-jacentes ;
  • éviter la propagation du Null ;
  • utiliser des tableaux indicés à zéros ;
  • éviter des tableaux et des chaînes de taille fixe dans la définition de types utilisateurs ;
  • préciser la portée d'un paramètre explicitement. En Visual Basic les paramètres sont passés par défaut par référence, alors qu'en .NET ils sont passés par valeur.

Cette étape présente un certain nombre de préconisations, mais n'est pas obligatoire. Pour vous aider dans la vérification de votre code, Visual Basic Microsoft propose en téléchargement gratuit l'outil « CodeAdvisor ». Cet outil est disponible à l'adresse suivante : http://msdn.microsoft.com/vbasic/downloads/codeadvisor/default.aspx

III-C-3. La migration de l'application via l'assistant de migration

Pour migrer notre projet Visual Basic nous allons utiliser l'assistant de migration fournit par Microsoft. Pour cela nous ouvrons notre projet .vbp avec l'IDE Visual Studio .NET. L'assistant nous propose dès lors de mettre à niveau notre projet.

Image non disponible

Nous choisissions ensuite le type de projet, en l'occurrence il s'agit d'un ActiveX Server de type DLL.

Image non disponible

Nous sélectionnons l'emplacement où sera stocké le nouveau projet.

Image non disponible

Enfin nous lançons la migration de notre projet.

Image non disponible

Une fois la mise à niveau réalisée, un rapport de mise à jour nous est proposé.

Image non disponible

Ce rapport présente les erreurs et les avertissements détectés par l'outil de mise à jour regroupés par fichier. Pour chaque erreur, une description détaillée indique pourquoi le code présente une anomalie et comment la corriger.

Ce rapport est complété par quatre types de commentaires directement intégrés au code de l'application :

  • UPGRADE_ISSUE : fait référence à des lignes qui empêchent le code de compiler ;
  • UPGRADE_TODO : fait référence à des lignes qui compilent, mais peuvent, à l'exécution, générer des erreurs ;
  • UPGRADE_WARNING : fait référence à des lignes qui compilent et qui peuvent peut-être provoquer des erreurs à l'exécution ;
  • UPGRADE_NOTE : fait référence à du code qui compile pour lequel le passage à VB .Net peut provoquer des effets indésirables.

Étudions maintenant le code généré par l'assistant de mise à niveau VB .NET et regardons les modifications apportées.

  • Génération d'une classe VB .NET qui contient les méthodes de notre précédente classe Visual Basic.
  • Modification des types de données. Le type Integer a été remplacé par du Short. Le Variant par Object.
  • Modification de l'appel à des fonctions qui intègre désormais obligatoirement des parenthèses.
  • Modification de certaines constantes utilisées. Par exemple l'option adCmdStoredProc a été remplacée par ADODB.CommandTypeEnum.adCmdStoredProc.

III-C-4. Correction des anomalies détectées par l'assistant

Malgré les corrections apportées par l'assistant, plusieurs anomalies majeures ont été détectées, mais non corrigées. Nous allons en étudier deux et effectuer les corrections adéquates.

III-C-4-a. La gestion de la chaîne de construction

J'ai pris comme habitude de me servir de la chaîne de construction COM+ afin de définir un chemin d'accès vers un fichier UDL qui détermine la chaîne de connexion à la base de données. À l'activation d'un composant, cette chaîne est récupérée et utilisée dans tous les accès SGBD.

 
Sélectionnez
Implements COMSVCSLib.IObjectConstruct
Private sConstructString As String
                            
Private Sub IObjectConstruct_Construct(ByVal pCtorObj As Object)
                            
    Const NomFonction = "IObjectConstruct_Construct"
                              
    Dim sConstruct As IObjectConstructString
    Set sConstruct = pCtorObj
    sConstructString = sConstruct.ConstructString
                              
End Sub

Pour réaliser la migration de ce code, il faut que ma classe hérite de la classe ServicedComponent de l'espace de noms System.EnterpriseServices. Cette classe permet l'accès aux services COM+. Enfin, il faut surcharger la méthode Construct. Le code migré devient :

 
Sélectionnez
Public Class DataAccess
                        
Inherits System.EnterpriseServices.ServicedComponent
                    
    Private sConstructString As String
                        
    Private Const NomModule As String = "DataClient"
                        
    Protected Overrides Sub Construct(ByVal constructString As String)
        sConstructString = constructString
    End Sub 'Construct
III-C-4-b. L'écriture dans le journal des évènements

En cas d'anomalie une erreur est loguée dans le journal des évènements. La correction consiste à rechercher la méthode permettant d'écrire dans le journal des évènements. La méthode WriteEntry de la classe LogEvent de l'espace de noms System.Diagnostics répond à ce besoin.

 
Sélectionnez
'UPGRADE_ISSUE: La constante vbLogToNT n'a pas été mise à niveau. 
'Cliquez ici : 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="vbup2070"'
'UPGRADE_ISSUE: App méthode App.StartLogging - Mise à niveau non effectuée 
'Cliquez ici : 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="vbup2069"'
App.StartLogging("", vbLogToNT)
                            
'UPGRADE_ISSUE: La constante vbLogEventTypeError n'a pas été mise à niveau. 
'Cliquez ici : 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="vbup2070"'
'UPGRADE_ISSUE: App méthode App.LogEvent - Mise à niveau non effectuée 
'Cliquez ici : 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="vbup2069"'
App.LogEvent(Err.Source & " " & Err.Description, vbLogEventTypeError)

Le code migré manuellement devient alors :

 
Sélectionnez
Imports System.Diagnostics.EventLog
'...
Dim myLog As New EventLog("Application", System.Environment.MachineName, "Classe DataAccess")
myLog.WriteEntry(Err.Source & " " & Err.Description, EventLogEntryType.Error)
III-C-4-c. La gestion des transactions

Notre classe est transactionnelle et nous devons préserver cette propriété. Pour se faire, il s'agit d'utiliser les mécanismes de transactions déclaratives proposés par la classe ServiceComponents de l'espace de noms System.EnterprisesServices.

D'une part nous allons définir en entête de classe l'attribut « TransactionAttribute » afin de définir la propriété transactionnelle de la classe. D'autre part nous allons utiliser l'attribut « AutoComplete » sur chaque méthode pour invoquer automatiquement soit la méthode SetComplete en cas de succès de la transaction soit SetAbort en cas d'erreur.

Voici le code avant et après migration.

 
Sélectionnez
Function CreerClient(…)
Dim ctx As ObjectContext    
'...
    Set ctx = GetObjectContext
    If Not ctx Is Nothing Then
       ctx.SetComplete
       Set ctx = Nothing
    End If
 
Sélectionnez
Imports System.EnterpriseServices
    
<Transaction(TransactionOption.Required)> _
    Public Class DataAccess
    Inherits System.EnterpriseServices.ServicedComponent
                            
    <AutoComplete()> Function CreerClient(ByVal sSiret As String, ByVal sNomClient As String, _
        ByVal iNumero As Short, _
        ByVal sRue As String, _
        ByVal sCodePostal As String, _
        ByVal sCommune As String, _
        ByRef vIdentifiant As Object) As Short
                            '...

La migration est désormais achevée (cf. Comparaison des codes migrés), il ne reste plus qu'à réaliser des tests de non-régression. Nous pourrions poursuivre en intégrant les nouvelles fonctionnalités .NET (remplacement de composants COM en composants .NET, passage de ADO à ADO .Net, modification de la gestion des erreurs …), nous ne traiterons pas ceci dans cet article.

Conclusion

En conclusion, je ne saurais trop vous conseiller de regarder du côté de .NET. Aujourd'hui, il est possible de migrer vos applicatifs progressivement par étapes tout en préservant l'existant via l'interopérabilité COM+. Visual Basic 6 reste supporté par Microsoft. Néanmoins, une migration vers dot net permet au développeur Visual Basic de se former en douceur vers cette technologie et d'étendre à l'avenir ses développements vers d'autres plateformes (Pocket PC, Smartphone, architecture 64 Bits, Linux avec le projet Mono).

Code vb :

 
Sélectionnez
Option Explicit

Private Const NomModule = "DataClient"
            
Function CreerClient(ByVal sSiret As String, _
    ByVal sNomClient As String, _
    ByVal iNumero As Integer, _
    ByVal sRue As String, _
    ByVal sCodePostal As String, _
    ByVal sCommune As String, _
    ByRef vIdentifiant As Variant) As Integer
                
    On Error GoTo GestionErreur
                
    Dim oConnexion As ADODB.Connection
    Dim oRecordset As ADODB.Recordset
    Dim oCommand As ADODB.Command
    Dim ctx As ObjectContext
     
    Dim iCodeRetour As Integer 'contient le code retour de la proc stock
                 
    Set oCommand = New ADODB.Command
                
    With oCommand
        .Parameters.Append .CreateParameter("@Retour", adInteger, _
        adParamReturnValue)
        '...
    End With
                  
    Set oConnexion = New ADODB.Connection
    oConnexion.Open sConstructString
                
    oConnexion.BeginTrans
    With oCommand
         .CommandType = adCmdStoredProc
         .CommandText = "Insert_Client"
         Set .ActiveConnection = oConnexion
    End With
                
    oCommand.Execute , , adExecuteNoRecords
                
    'recuperation du code retour de la procédure stockée
    vIdentifiant = oCommand.Parameters("@Retour").Value
                  
    Set ctx = GetObjectContext
    If Not ctx Is Nothing Then
       ctx.SetComplete
       Set ctx = Nothing
    End If

Code VB.NET

 
Sélectionnez
Option Strict Off
Option Explicit On 
Imports System.Diagnostics.EventLog
Imports System.EnterpriseServices
            
<Transaction(TransactionOption.Required)> _
Public Class DataAccess
Inherits System.EnterpriseServices.ServicedComponent
    Private Const NomModule As String = "DataClient"
            
    <AutoComplete()> _ 
    Function CreerClient(ByVal sSiret As String, ByVal sNomClient As String,  _ 
        ByVal iNumero As Short, ByVal sRue As String, ByVal sCodePostal As String, _
        ByVal sCommune As String, ByRef vIdentifiant As Object) As Short
        On Error GoTo GestionErreur
                        
        Dim oConnexion As ADODB.Connection
        Dim oRecordset As ADODB.Recordset
        Dim oCommand As ADODB.Command
              
        Dim iCodeRetour As Short 
        
        
        oCommand = New ADODB.Command
        
        With oCommand
             .Parameters.Append(.CreateParameter("@Retour",  _ 
                 ADODB.DataTypeEnum.adInteger, _ 
                 ADODB.ParameterDirectionEnum.adParamReturnValue))
                 '...
        End With
            
        oConnexion = New ADODB.Connection
        oConnexion.Open(sConstructString)
        
        With oCommand
             .CommandType = ADODB.CommandTypeEnum.adCmdStoredProc
             .CommandText = "Insert_Client"
             .ActiveConnection = oConnexion
        End With
        
            oCommand.Execute(, , ADODB.ExecuteOptionEnum.adExecuteNoRecords)
            
            vIdentifiant = oCommand.Parameters("@Retour").Value
            
            If (Not oRecordset Is Nothing) Then
               If oRecordset.State = ADODB.ObjectStateEnum.adStateOpen Then _ 
                  oRecordset.Close()
               End If
            
            If (Not oConnexion Is Nothing) Then
               If oConnexion.State = ADODB.ObjectStateEnum.adStateOpen Then  _
                  oConnexion.Close()
               End If
            End If

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Article écrit pour la revue programmez par leduke - Toute reproduction, même partielle doit-être soumise à l'accord de l'auteur.