Modernizzare software obsoleto: Delphi, VB6 e MFC verso .NET passo dopo passo

Laborarbeitsplatz mit Pipette, Proben und Messsoftware auf dem Laptop

Architettura software e UML

Il software funziona da vent'anni, i clienti fanno affidamento su di esso – e l'unico che conosce davvero il codice Delphi l'anno prossimo andrà in pensione. Riscrivere tutto da capo? Ci vogliono anni e i benefici arrivano solo alla fine. Esiste una via migliore: pezzo dopo pezzo, senza fermare l'operatività.

Perché adesso – e perché non tutto in una volta

Per Visual Basic 6 la situazione è chiara. Microsoft non supporta più l'ambiente di sviluppo dall'8 aprile 2008. Secondo Microsoft il runtime funziona anche con Windows 11, ma è supportato solo in caso di gravi regressioni e falle di sicurezza critiche. Microsoft raccomanda espressamente di sostituire le applicazioni VB6. Delphi e MFC invece continuano a essere mantenuti. Lì la pressione arriva da un'altra parte: meno sviluppatori che capiscono il codice, un'interfaccia superata, test mancanti, librerie senza aggiornamenti.

Nessuno demolisce un ponte su cui passa traffico ogni giorno per costruirne uno nuovo. Lo si costruisce accanto e si sposta una corsia dopo l'altra. Martin Fowler dà a questo schema il nome del fico strangolatore, che avvolge lentamente un albero: il codice nuovo cresce attorno a quello vecchio finché quello vecchio può essere spento. Ogni passo entra in esercizio e porta subito benefici.

Cinque passi

  1. Inventario: rilevare moduli, database, interfacce e maschere. Quali parti cambiano spesso, quali causano più errori?
  2. Fissare il comportamento: far girare il vecchio software con input reali e registrare i risultati. Questi «golden master» sono il metro di misura per ogni nuova riga.
  3. Costruire un ponte: vecchio e nuovo devono dialogare tra loro finché esistono entrambi.
  4. Trasferire modulo per modulo: cominciare dalla parte che cambia più spesso o che fa più male. Rilasciare ogni passo.
  5. Spegnere: solo quando più nulla richiama la parte vecchia, questa viene eliminata.

Ponti tra vecchio e nuovo

  • Delphi: il vecchio nucleo di calcolo viene reso accessibile come DLL con export stdcall, e .NET lo richiama tramite P/Invoke. In alternativa si comunica tramite COM.
  • VB6: le nuove parti nascono in .NET e vengono messe a disposizione come server COM. Con EnableComHosting l'SDK genera una .comhost.dll, che viene registrata con regsvr32. Due insidie: VB6 è a 32 bit, ma l'involucro COM è per impostazione predefinita a 64 bit. E .NET non genera più una libreria dei tipi. Per l'early binding in VB6 la scrive da sé tramite IDL oppure usa il late binding tramite CreateObject.
  • MFC: C++/CLI collega codice nativo e .NET nello stesso processo. Le nuove finestre di dialogo nascono in WPF o WinForms e vengono incorporate nelle finestre MFC.

Ecco come appare in piccolo il ponte Delphi. Il vecchio nucleo:

library Messkern;



// Vecchio nucleo di calcolo, esposto all'esterno come DLL con stdcall

function Mittelwert(Werte: PDouble; Anzahl: Integer): Double; stdcall;

var

  I: Integer;

  Summe: Double;

begin

  Summe := 0;

  for I := 0 to Anzahl - 1 do

  begin

    Summe := Summe + Werte^;

    Inc(Werte);

  end;

  if Anzahl > 0 then

    Result := Summe / Anzahl

  else

    Result := 0;

end;



exports

  Mittelwert;



begin

end.

E la chiamata da C#, subito con il confronto con la nuova implementazione:

using System;

using System.Linq;

using System.Runtime.InteropServices;



double[] messreihe = { 10.2, 10.4, 10.1, 10.3 };

double alt = Messkern.Mittelwert(messreihe, messreihe.Length);

double neu = messreihe.Average();

// Golden master: il nuovo codice deve fornire ciò che forniva il vecchio

Console.WriteLine(Math.Abs(alt - neu) < 1e-9 ? "gleich" : $"Abweichung: {alt} / {neu}");



internal static class Messkern

{

    // Se la DLL è a 32 bit, anche il processo .NET deve girare come x86

    [DllImport("Messkern.dll", CallingConvention = CallingConvention.StdCall)]

    internal static extern double Mittelwert(double[] werte, int anzahl);

}

Insidie con i tipi di dati

  • Virgola mobile: l'Extended di Delphi in Win32 occupa dieci byte, un double .NET otto. I risultati differiscono quindi nelle ultime cifre. Confronti con una tolleranza.
  • Data: il TDateTime di Delphi e il Date di VB6 contano i giorni dal 30/12/1899 come numero in virgola mobile. DateTime.FromOADate li converte.
  • Valuta: Currency è in entrambi i linguaggi un intero a 64 bit con quattro cifre decimali fisse. In .NET diventa decimal, non double.
  • Testi: una string di Delphi non deve mai attraversare il confine di una DLL. Usi PWideChar o WideString. Le versioni più vecchie di Delphi lavorano con testi ANSI, per lo più nella codepage 1252.

Dalla pratica

Un produttore di strumenti di misura utilizzava da decenni un software Delphi sviluppato internamente. All'inizio ci sono state consulenza e pianificazione: abbiamo messo a confronto obiettivi e possibilità delle nuove tecnologie, e dei prototipi hanno mostrato come potrebbero presentarsi le soluzioni. Poi abbiamo formato in sede l'intero team del cliente. Un team di progetto di dieci persone porta il software in modo agile su C# e WPF, con MariaDB ed Entity Framework. Il nuovo software è già in uso internamente e convince sia i tecnici di misura sia le vendite. Per un applicativo verticale per l'ingegneria civile in C++, MFC e ObjectARX, un'analisi di convenienza economica ha mostrato in anticipo da quando il porting si ripaga.

Errori tipici

  • Tutto nuovo, tutto in una volta: per anni nessun beneficio, e alla fine manca la metà.
  • Riscrivere a memoria invece che in base al comportamento misurato.
  • Correggere tacitamente vecchi errori su cui fanno affidamento gli utenti o i sistemi a valle.
  • Mescolare 32 e 64 bit. Una DLL a 32 bit in un processo a 64 bit finisce in una BadImageFormatException.
  • Passare testi oltre il confine senza una regola chiara. Il risultato sono crash o caratteri accentati corrotti.
  • Ricostruire l'interfaccia pixel per pixel invece di migliorare i processi.
  • Non coinvolgere il proprio team. Chi non capisce il nuovo codice presto si ritroverà a mantenere di nuovo software obsoleto.

Come La aiutiamo

Fonti: Microsoft, «Support Statement for Visual Basic 6.0 on Windows»; Microsoft Learn, «Exposing .NET Core components to COM»; Martin Fowler, «Strangler Fig Application»; Embarcadero DocWiki, «System.Extended»; casi di studio «Modernizzazione di un software per strumenti di misura: da Delphi a C#» e «Modernizzazione di un applicativo AutoCAD per l'ingegneria civile», Casi di studio Cadida.

CONTACT

Seleziona la tua lingua

Primo colloquiofissare oraPrimo colloquiofissare ora