I convertitori da COBOL a Java producono "Jobol"

Perché i convertitori da COBOL a Java producono "Jobol" e come evitarlo

La conversione è stata completata in tre mesi. L'applicazione Java è stata compilata, ha superato i test di base ed è stata dichiarata pronta per la distribuzione. Sei mesi dopo l'avvio della produzione, il team della piattaforma ha notato qualcosa di preoccupante: nessuno del team Java era in grado di gestire il codice. Le revisioni richiedevano il doppio del tempo rispetto alle normali revisioni Java. I report dei bug facevano riferimento a concetti come WORKING-STORAGE, logica PROCEDURE DIVISION e convenzioni per i campi decimali compressi, che gli sviluppatori Java senza esperienza mainframe non riuscivano a comprendere. L'applicazione era stata convertita da COBOL a Java, ma il codice Java risultante pensava, strutturava e si comportava come COBOL. Era Jobol.

Jobol (a volte scritto JOBOL) è la parola composta che indica un codice Java che conserva la semantica procedurale del COBOL senza però adottare le funzionalità orientate agli oggetti di Java. Jason Bloomberg, fondatore della società di analisi Intellyx, lo ha definito in modo diretto: Jobol è un codice Java tecnicamente valido che mantiene l'architettura software originale e preserva la semantica del COBOL, obbligando gli sviluppatori a trattare il codice Java come se fosse COBOL. La conseguenza critica è immediata: un'azienda che converte il COBOL in Jobol non si è liberata dalla necessità di competenze specifiche sul COBOL. Ha semplicemente trasferito tale competenza a un linguaggio che non supporta nativamente i modelli COBOL contenuti nel codice. Ha creato un sistema più difficile da manutenere rispetto al COBOL originale e non offre nessuno dei vantaggi attesi da Java.

Grafico delle dipendenze prima della progettazione del dominio

SMART TS XL mappa ogni dipendenza PERFORM e CALL in modo che il livello di servizio Java rifletta la struttura di accoppiamento effettiva, non la struttura delle classi COBOL.

SCOPRI DI PIÙ…

Che aspetto ha realmente Jobol

Prima di diagnosticare le cause, è necessario rendere visibile lo schema. Ecco la stessa logica aziendale, una verifica del credito del cliente, in tre forme: il COBOL originale, il Jobol prodotto tipicamente dai convertitori automatici e il Java idiomatico prodotto da una modernizzazione eseguita da esperti.

Il COBOL originale:

cobolo

       PERFORM-CREDIT-CHECK.
           MOVE WS-CUST-ID TO DB-CUST-KEY
           READ CUSTOMER-FILE KEY IS DB-CUST-KEY
               INVALID KEY
                   MOVE 'NOT FOUND' TO WS-STATUS
                   PERFORM HANDLE-MISSING-CUSTOMER
           END-READ

           IF CUST-CREDIT-SCORE < 650
               MOVE 'DECLINED' TO WS-CREDIT-RESULT
               MOVE 'Score below threshold' TO WS-DECLINE-REASON
           ELSE IF CUST-OUTSTANDING-BALANCE > CUST-CREDIT-LIMIT
               MOVE 'DECLINED' TO WS-CREDIT-RESULT
               MOVE 'Balance exceeds limit' TO WS-DECLINE-REASON
           ELSE
               MOVE 'APPROVED' TO WS-CREDIT-RESULT
           END-IF.

Il Jobol prodotto da un convertitore riga per riga:

Giava

// Jobol: procedural COBOL logic mapped directly to Java
// No OOP, no encapsulation, static global state, COBOL naming conventions
public class CreditCheckProgram {
    static String WS_CUST_ID;
    static String DB_CUST_KEY;
    static String WS_STATUS;
    static String WS_CREDIT_RESULT;
    static String WS_DECLINE_REASON;
    static int CUST_CREDIT_SCORE;
    static double CUST_OUTSTANDING_BALANCE;
    static double CUST_CREDIT_LIMIT;

    public static void PERFORM_CREDIT_CHECK() {
        DB_CUST_KEY = WS_CUST_ID;
        Customer customer = CustomerFile.read(DB_CUST_KEY);
        if (customer == null) {
            WS_STATUS = "NOT FOUND";
            HANDLE_MISSING_CUSTOMER();
            return;
        }
        CUST_CREDIT_SCORE = customer.getCreditScore();
        CUST_OUTSTANDING_BALANCE = customer.getOutstandingBalance();
        CUST_CREDIT_LIMIT = customer.getCreditLimit();

        if (CUST_CREDIT_SCORE < 650) {
            WS_CREDIT_RESULT = "DECLINED";
            WS_DECLINE_REASON = "Score below threshold";
        } else if (CUST_OUTSTANDING_BALANCE > CUST_CREDIT_LIMIT) {
            WS_CREDIT_RESULT = "DECLINED";
            WS_DECLINE_REASON = "Balance exceeds limit";
        } else {
            WS_CREDIT_RESULT = "APPROVED";
        }
    }
}

Il Java idiomatico prodotto da una modernizzazione qualificata:

Giava

// Idiomatic Java: domain model, encapsulation, value objects, Spring service
@Service
public class CreditCheckService {

    private final CustomerRepository customerRepository;

    public CreditCheckService(CustomerRepository customerRepository) {
        this.customerRepository = customerRepository;
    }

    public CreditDecision check(CustomerId customerId) {
        Customer customer = customerRepository.findById(customerId)
            .orElseThrow(() -> new CustomerNotFoundException(customerId));

        if (customer.creditScore() < CreditThresholds.MINIMUM_SCORE) {
            return CreditDecision.declined("Score below threshold");
        }
        if (customer.outstandingBalance().compareTo(customer.creditLimit()) > 0) {
            return CreditDecision.declined("Balance exceeds limit");
        }
        return CreditDecision.approved();
    }
}

La versione Jobol è composta da 32 righe di stato globale statico, strutturato proceduralmente, con nomi in COBOL e impossibile da testare con unit test senza prima inizializzare lo stato globale della classe. La versione idiomatica è composta da 20 righe, iniettabile, testabile e immediatamente leggibile da qualsiasi sviluppatore Java senza conoscenze di COBOL. Entrambe implementano le stesse regole aziendali. Solo una è gestibile dal team che la modernizzazione avrebbe dovuto supportare.

I sei modelli Jobol e perché i trasformatori li producono

Modello 1: Stato statico globale che sostituisce WORKING-STORAGE

La sezione di lavoro (WORKING-STORAGE SECTION) del COBOL contiene variabili a livello di programma che persistono tra le chiamate PERFORM. Rappresenta lo stato mutabile condiviso del programma: ogni paragrafo legge e scrive le stesse variabili WS. I convertitori automatici mappano questa sezione direttamente ai campi statici Java in una singola classe, preservando la semantica dello stato condiviso ma violando ogni principio di incapsulamento Java.

Perché i convertitori si comportano in questo modo: la mappatura da WORKING-STORAGE a campi statici è una trasformazione meccanica uno a uno. Il convertitore non comprende che il modello di incapsulamento di Java sostituisce lo stato condiviso a livello di programma con variabili di istanza, parametri di metodo e valori di ritorno. Converte ciò che vede senza comprendere il motivo per cui esisteva la struttura originale.

La conseguenza: lo stato statico non è testabile in isolamento, non è thread-safe senza una sincronizzazione esplicita ed è strutturalmente identico al COBOL che ha sostituito. Qualsiasi sviluppatore che abbia bisogno di aggiungere la concorrenza al sistema deve prima districarsi dallo stato statico, un lavoro che è stato rimandato dalla conversione a ogni successivo manutentore.

La soluzione: mappare le variabili WORKING-STORAGE ai campi di istanza, ai parametri di metodo o ai valori di ritorno in base al loro ambito di utilizzo. Le variabili utilizzate solo all'interno di un paragrafo diventano variabili locali. Le variabili passate tra i paragrafi diventano parametri di metodo o valori di ritorno. Le variabili che rappresentano effettivamente lo stato condiviso dell'oggetto diventano campi di istanza in una classe di dominio opportunamente incapsulata.

Modello 2: Eseguire catene che diventano lunghi metodi statici

I programmi COBOL sono organizzati come catene PERFORM, in cui la procedura principale esegue una sequenza di paragrafi denominati, ognuno dei quali può a sua volta eseguire altri PERFORM. I convertitori automatici traducono ogni paragrafo in un metodo statico e ogni PERFORM in una chiamata a un metodo statico. Il risultato è una singola classe con decine di metodi statici che si richiamano a vicenda attraverso un grafo di chiamate che rispecchia la struttura PERFORM di COBOL.

Giava

// Jobol: PERFORM chain mapped to static method calls
public class ProcessOrderProgram {
    public static void main() {
        validateOrder();
        checkInventory();
        calculateTotal();
        applyDiscounts();
        processPayment();
        generateConfirmation();
        updateInventory();
    }

    public static void validateOrder() { /* ... */ }
    public static void checkInventory() { /* ... */ }
    // ... 40 more static methods
}

Perché i convertitori si comportano in questo modo: la mappatura strutturale dal paragrafo COBOL al metodo Java è diretta. Il convertitore identifica correttamente che PERFORM significa "chiama questa unità di codice". Ciò che non coglie è che il modello a oggetti di Java organizza il codice attorno alle entità di dominio, non attorno alle fasi di elaborazione.

La correzione: Identificare i concetti di dominio incorporati nella catena PERFORM. validateOrder, calculateTotale applyDiscounts sono operazioni su un Ordine. processPayment è un'operazione in un contesto di pagamento. checkInventory and updateInventory sono operazioni sull'inventario. Il refactoring distribuisce i metodi statici alle classi di dominio a cui appartengono, sostituendo una lunga catena di chiamate procedurali con un breve metodo di orchestrazione che delega agli oggetti di dominio appropriati.

Schema 3: Tipi numerici senza gestione della precisione

I campi decimali impacchettati (COMP-3) di COBOL hanno un'aritmetica decimale esatta. Convertitori che mappano COMP-3 a Java double or float introducono errori sistematici di arrotondamento in virgola mobile che si accumulano su milioni di transazioni finanziarie.

Giava

// Jobol: COMP-3 mapped to double (wrong)
static double WS_TRANSACTION_AMOUNT;  // Was PIC S9(9)V99 COMP-3
static double WS_RUNNING_TOTAL;

// After 10M additions of 0.1:
// Expected: 1,000,000.00
// Actual:   1,000,000.0000000002 (floating point accumulation)

Giava

// Idiomatic Java: COMP-3 mapped to BigDecimal (correct)
private BigDecimal transactionAmount;  // Preserves decimal precision
private BigDecimal runningTotal;

// After 10M additions of 0.1:
// Result: exactly 1,000,000.00

Perché i convertitori fanno questo: double è il tipo numerico predefinito di Java. Un convertitore che non comprende specificamente la semantica di COMP-3 utilizzerà per impostazione predefinita il tipo numerico Java più comune, che è la scelta sbagliata per l'aritmetica decimale esatta.

La correzione: Ogni campo COMP-3 mappa a BigDecimalOgni calcolo numerico che coinvolge valori COMP-3 utilizza BigDecimal aritmetica. Il scale() di BigDecimal corrisponde alle cifre decimali implicite nella clausola PIC: PIC S9(9)V99 ha 2 cifre decimali implicite, mappate su BigDecimal con scala 2.

Schema 4: Stringhe EBCDIC e reliquie di array di byte

COBOL elabora i dati di tipo carattere come stringhe a lunghezza fissa con spazi di riempimento, utilizzando la codifica EBCDIC. I convertitori spesso producono codice Java che preserva la semantica delle stringhe a lunghezza fissa con spazi di riempimento anche dopo la conversione in UTF-8, risultando in un codice Java che gestisce le stringhe come un programmatore di mainframe degli anni '1970.

Giava

// Jobol: preserves COBOL fixed-length string handling
static char[] WS_CUSTOMER_NAME = new char[40]; // Was PIC X(40)
static char[] WS_CUSTOMER_ADDR = new char[80]; // Was PIC X(80)

// COBOL-style space-padding comparison
if (new String(WS_CUSTOMER_NAME).trim().equals("SMITH")) { ... }

// COBOL-style string concatenation with padding
System.arraycopy(name.toCharArray(), 0, WS_CUSTOMER_NAME, 0,
                 Math.min(name.length(), 40));

Giava

// Idiomatic Java: proper String types and domain objects
private String customerName;  // Trim on read, no padding
private String customerAddress;

// Clean comparison
if ("Smith".equalsIgnoreCase(customer.name())) { ... }

Perché i convertitori fanno questo: la definizione COBOL PIC X(40) ha una lunghezza che il convertitore preserva come dimensione di un array Java. La conversione da EBCDIC a UTF-8 può essere gestita, ma la semantica a lunghezza fissa viene mantenuta inutilmente.

La correzione: Mappa PIC X(n) campi da String oggetti, troncamento in fase di lettura e rimozione dei vincoli di lunghezza fissa. L'unico contesto in cui i vincoli di lunghezza sono rilevanti è ai limiti di persistenza (lunghezza delle colonne del database, posizioni dei formati di file), non nel modello di dominio.

Schema 5: Gestione degli errori tramite codici di stato

COBOL comunica le condizioni di errore tramite codici di stato: FILE STATUS, SQLCODE, RETURN-CODE. I convertitori preservano questo schema in Java, producendo codice che controlla i codici di stato interi dopo ogni operazione, anziché utilizzare il modello di eccezione di Java.

Giava

// Jobol: COBOL status code pattern in Java
static int WS_FILE_STATUS;
static int WS_SQL_CODE;

CustomerFile.read(DB_CUST_KEY);
WS_FILE_STATUS = CustomerFile.getLastStatus();
if (WS_FILE_STATUS == 10) {
    // Not found
} else if (WS_FILE_STATUS == 35) {
    // File not available
} else if (WS_FILE_STATUS != 0) {
    // Unknown error
}

Giava

// Idiomatic Java: exceptions for error conditions
try {
    Customer customer = customerRepository.findById(customerId)
        .orElseThrow(() -> new CustomerNotFoundException(customerId));
    // process customer
} catch (DatabaseUnavailableException e) {
    log.error("Database unavailable during credit check", e);
    throw new CreditCheckServiceException("Service temporarily unavailable", e);
}

Perché i convertitori fanno questo: il controllo del codice di stato è il pattern COBOL; convertirlo in un metodo Java che restituisce o imposta un campo di stato è una trasformazione meccanica. Riconoscere che le eccezioni Java sono l'equivalente idiomatico richiede un giudizio architetturale, non una traduzione meccanica.

La correzione: Mappa le condizioni di errore COBOL alle eccezioni Java. STATO FILE 10 (record non trovato) diventa Optional.empty() o un'eccezione specifica del dominio. Gli errori SQLCODE diventano eccezioni di database tipizzate. La struttura del codice Java riflette l'intento, try/catch per le modalità di errore previste, eccezioni non controllate per quelle impreviste.

Modello 6: Struttura di classe monolitica

I programmi COBOL sono monolitici per definizione: un singolo programma gestisce un'intera funzione aziendale. I convertitori creano una singola classe Java per ogni programma COBOL, producendo classi Java che possono essere lunghe migliaia di righe e gestire molteplici responsabilità che la progettazione orientata agli oggetti distribuirebbe su diverse classi specifiche.

Perché i convertitori fanno questo: un programma COBOL viene mappato a una classe Java, e l'unità di traduzione del convertitore è il programma stesso. La struttura interna del programma (i suoi paragrafi, sezioni, catene PERFORM) diventa la struttura interna della classe senza necessità di scomposizione in classi più piccole.

La soluzione: applicare il principio di responsabilità unica a ciascuna classe convertita. Una classe Jobol di 3,000 righe che convalida l'input, legge da un database, applica regole aziendali, formatta l'output e scrive su un file dovrebbe diventare: un validatore di input, un repository, un servizio di dominio, un formattatore e uno scrittore, ognuno testabile in isolamento e focalizzato su una singola responsabilità.

Il prerequisito per l'analisi strutturale

Ogni pattern Jobol ha un refactoring corrispondente. Tuttavia, il refactoring non può essere applicato dal convertitore, ma richiede la comprensione del funzionamento del programma prima di decidere come ristrutturarlo. Questa comprensione è esattamente ciò che fornisce l'analisi strutturale del codice COBOL sorgente prima dell'esecuzione di qualsiasi strumento di conversione.

Nello specifico, l'analisi strutturale produce gli input necessari per le decisioni di conversione:

Inventario della logica di business. L'enumerazione completa delle condizioni EVALUATE, dei rami IF e delle formule COMPUTE in ogni programma, ovvero cosa decide il programma, non solo come è strutturato. Questo inventario rappresenta la specifica a cui il codice Java sottoposto a refactoring deve corrispondere. Un programma con 847 condizioni EVALUATE richiede una struttura di classe target che possa gestire 847 punti decisionali; l'output del convertitore è la bozza iniziale, non il prodotto finito.

Grafico delle dipendenze. Quali programmi chiamano quali altri programmi. La catena PERFORM che si estende su più programmi COBOL diventa un grafico delle chiamate di servizio in Java. Il grafico delle dipendenze determina quali programmi possono essere rifattorizzati in modo indipendente (poche dipendenze in entrata) e quali devono essere rifattorizzati come gruppi coordinati (molte dipendenze condivise tramite copybook o dati condivisi).

Identificazione del codice morto. I paragrafi e le sezioni che non vengono MAI eseguiti in alcun percorso di esecuzione in produzione sono considerati codice morto e non dovrebbero comparire affatto nel codice Java convertito. I convertitori che includono codice morto aumentano le dimensioni del codice convertito e il conseguente lavoro di refactoring.

Recupero del modello dati. Le voci VSAM FD, le definizioni delle tabelle DB2 e le strutture copybook che definiscono i dati del programma. Ogni struttura dati COBOL corrisponde a uno o più oggetti di dominio Java; la mappatura è determinata dal modello dati, non dai nomi dei campi in WORKING-STORAGE.

Input per l'analisiDecisione di conversione che guida
VALUTA/SE il numero di ramiDecomposizione delle classi di dominio, ovvero quanti casi decisionali gestisce ciascun servizio.
Conteggio delle dipendenze in entrataSequenza di refactoring, prima i programmi con meno dipendenze
Percentuale di codice mortoRiduzione dell'ambito, escludere il codice irraggiungibile dalla conversione
Campi COMP-3BigDecimal mappatura per ogni campo numerico
Lunghezze del campo PIC XMappatura dei tipi di stringa e vincoli del livello di persistenza
ESEGUI la struttura del graficoDecomposizione del livello di servizio, le catene PERFORM diventano chiamate di servizio di dominio
utilizzo dello STATO DEL FILEProgettazione del modello di eccezione: quali codici di stato corrispondono a quali tipi di eccezione.

Cosa dovrebbe invece produrre la conversione

L'alternativa a Jobol è un processo di conversione che utilizza il COBOL come specifica anziché come modello. Il programma COBOL conosce la logica di business, mentre il programma Java deve esprimere tale logica nel linguaggio Java.

Il principio di conversione: Converti l'intento, non la sintassi. Il COBOL IF CUST-CREDIT-SCORE < 650 MOVE 'DECLINED' TO WS-CREDIT-RESULT dice "un cliente con un punteggio di credito inferiore a 650 viene rifiutato". Il codice Java dovrebbe dire la stessa cosa nel linguaggio Java: if (customer.creditScore() < CreditThresholds.MINIMUM_SCORE) return CreditDecision.declined(...). Non if (CUST_CREDIT_SCORE < 650) { WS_CREDIT_RESULT = "DECLINED"; }.

Il flusso di lavoro pratico di conversione che produce codice Java idiomatico:

Fase 1: Analisi strutturale del codice sorgente COBOL, grafo delle dipendenze, inventario della logica di business, recupero del modello dati, identificazione del codice morto. Questa fase produce la specifica. Nulla viene convertito finché questa fase non è completata.

Fase 2: Progettazione del modello di dominio, identificazione delle entità aziendali (Cliente, Account, Transazione, Politica) su cui operano i programmi COBOL. Queste diventano classi di dominio Java. Le variabili WORKING-STORAGE che rappresentano lo stato dell'entità diventano campi di istanza nella classe di dominio appropriata.

Fase 3: Progettazione del livello di servizio, identificazione delle operazioni aziendali (verifica del credito, elaborazione dei pagamenti, calcolo del saldo) implementate dai paragrafi e dalle sezioni COBOL. Queste diventano metodi di servizio Java nella classe di servizio di dominio appropriata. La catena PERFORM che sequenzia i paragrafi diventa la logica di orchestrazione del servizio.

Fase 4: Conversione automatizzata come generatore di bozze. Utilizzare lo strumento di conversione per produrre una bozza Java di partenza per ciascun programma, basata sul modello di dominio progettato nelle fasi 2 e 3. Rivedere la bozza confrontandola con l'inventario della logica aziendale per verificare che ogni ramo decisionale sia rappresentato.

Passo 5: Rifattorizzazione sistematica contro i modelli Jobol, applicare le sei correzioni anti-pattern: sostituire lo stato statico con lo stato dell'istanza, distribuire i metodi statici alle classi di dominio, sostituire i codici di stato con le eccezioni, sostituire double con BigDecimal, sostituire gli array a lunghezza fissa con String, scomporre le classi monolitiche in servizi a responsabilità singola.

Fase 6: Test di equivalenza comportamentale, eseguire il codice Java rifattorizzato sul corpus di test di caratterizzazione generato dall'analisi COBOL. Ogni condizione EVALUATE e ogni ramo IF dovrebbe avere almeno un caso di test che la esegua e verifichi l'equivalenza con l'output COBOL.

Come SMART TS XL Previene Jobol alla fonte

Il prerequisito dell'analisi strutturale per la prevenzione di Jobol, il grafico delle dipendenze, l'inventario della logica aziendale, l'identificazione del codice morto e il ripristino del modello dati, è esattamente ciò che SMART TS XLL'analisi del codice sorgente COBOL viene effettuata prima dell'esecuzione di qualsiasi strumento di conversione.

SMART TS XL'S analisi statica del codice Il codice sorgente COBOL elenca ogni condizione EVALUATE, ogni ramo IF, ogni formula COMPUTE e ogni relazione PERFORM, ovvero l'inventario completo della logica di business che il codice Java sottoposto a refactoring deve rappresentare fedelmente. Quando lo strumento di conversione produce codice Jobol, l'inventario della logica di business costituisce la specifica rispetto alla quale viene validato il refactoring: ogni condizione presente nell'inventario deve comparire nel codice Java, nella classe di dominio appropriata, espressa secondo la terminologia Java.

La mappatura delle dipendenze dell'applicazione produce il grafo PERFORM e il grafo delle chiamate di programma che determinano la struttura del livello di servizio Java. I programmi che si richiamano frequentemente appartengono allo stesso contesto delimitato. I programmi che vengono richiamati da molti altri sono i servizi condivisi che devono essere progettati con cura per supportare tutti i loro utilizzatori nell'architettura Java. Il grafo delle dipendenze è l'input per la fase di progettazione del livello di servizio, convertendo la struttura di accoppiamento implicito di COBOL nella struttura di iniezione di dipendenza esplicita di Java.

L' analisi di modernizzazione del sistema legacy identifica il codice obsoleto, i paragrafi e le sezioni mai raggiunti dai percorsi di esecuzione in produzione, che dovrebbero essere completamente esclusi dall'ambito della conversione. Convertire il codice COBOL obsoleto in codice Jobol obsoleto e poi effettuare il refactoring di quest'ultimo rappresenta uno spreco di risorse che la fase di identificazione del codice obsoleto elimina prima dell'inizio della conversione.

La funzionalità di analisi dell'impatto convalida la sequenza di refactoring: quando l'interfaccia di un programma COBOL cambia durante il refactoring da Jobol a Java idiomatico, l'analisi dell'impatto identifica tutti gli altri programmi il cui equivalente Java deve essere aggiornato per rimanere coerente con l'interfaccia modificata. Il refactoring in ordine di dipendenza, partendo da quelli con meno dipendenze, riduce al minimo il coordinamento richiesto in ogni fase.

I convertitori traducono la sintassi. La modernizzazione trasforma il significato.

I convertitori automatici da COBOL a Java sono più veloci della riscrittura umana. Sono inoltre ottimizzati per un obiettivo diverso: la corrispondenza sintattica piuttosto che l'equivalenza semantica nell'idioma del linguaggio di destinazione. Il "jobol" è ciò che si ottiene dalla corrispondenza sintattica quando il linguaggio sorgente (COBOL) e il linguaggio di destinazione (Java) hanno modelli strutturali fondamentalmente diversi.

Le organizzazioni che evitano Jobol non sono quelle che utilizzano convertitori migliori. Sono quelle che considerano il convertitore come un generatore di bozze piuttosto che come un prodotto finito, investono nell'analisi strutturale prima dell'avvio della conversione, progettano il modello di dominio Java prima dell'esecuzione del convertitore e applicano un refactoring sistematico all'output del convertitore utilizzando l'inventario della logica di business come specifica di validazione.

L'adozione di COBOL è evitabile. Il costo di evitarla è rappresentato dall'analisi strutturale e dalla modellazione del dominio che dovrebbero precedere ogni conversione. Il costo di non evitarla è un sistema Java che richiede competenze COBOL per la manutenzione, il che significa che il vantaggio atteso dalla modernizzazione, ovvero la possibilità di gestire il sistema con sviluppatori Java, non si concretizzerà mai.

Converti l'intento, non la sintassi. La differenza sta nel valore stesso della modernizzazione.