Konwersja zakończyła się w trzy miesiące. Aplikacja Java została skompilowana, przeszła podstawowe testy dymowe i została uznana za gotową do wdrożenia. Sześć miesięcy po rozpoczęciu produkcji zespół platformy zauważył coś niepokojącego: nikt z zespołu Java nie był w stanie utrzymać kodu. Przeglądy trwały dwa razy dłużej niż standardowe przeglądy Javy. Zgłoszenia błędów odwoływały się do pojęć, takich jak WORKING-STORAGE, logika DZIELENIA PROCEDUR, konwencje dotyczące upakowanych pól dziesiętnych, których programiści Javy bez doświadczenia w pracy z komputerami mainframe nie byli w stanie zrozumieć. Aplikacja została przekonwertowana z COBOLA na Javę, ale powstała Java myślała, była strukturowana i zachowywała się jak COBOL. To był Jobol.
Jobol (czasami nazywany JOBOL) to zlepek kodu Javy, który zachowuje semantykę proceduralną COBOL-a bez wykorzystywania możliwości obiektowych Javy. Jason Bloomberg, założyciel firmy analitycznej Intellyx, zdefiniował to wprost: Jobol to technicznie poprawny kod Javy, który zachowuje oryginalną architekturę oprogramowania i semantykę COBOL-a, wymagając od programistów traktowania Javy tak, jakby była COBOL-em. Krytyczna konsekwencja jest natychmiastowa: przedsiębiorstwo, które konwertuje COBOL na Jobol, nie uwalnia się od potrzeby posiadania specjalistycznej wiedzy w zakresie COBOL-a. Po prostu przeniosło to wymaganie do języka, który natywnie nie obsługuje wzorców COBOL-a zawartych w kodzie. Stworzyło system trudniejszy w utrzymaniu niż oryginalny COBOL i nie zapewnia żadnych oczekiwanych korzyści Javy.
Wykres zależności przed projektowaniem domeny
SMART TS XL mapuje każdą zależność PERFORM i CALL, dzięki czemu warstwa usług Java odzwierciedla rzeczywistą strukturę sprzężenia, a nie strukturę klas COBOL.
DOWIEDZ SIĘ WIĘCEJ…Jak naprawdę wygląda Jobol
Zanim zdiagnozujemy przyczyny, musimy dostrzec wzorzec. Oto ta sama logika biznesowa – weryfikacja zdolności kredytowej klienta – w trzech formach: oryginalnej wersji COBOL, wersji Jobol, którą zazwyczaj generują zautomatyzowane konwertery, oraz idiomatycznej wersji Java, którą generuje profesjonalna modernizacja.
Oryginalny COBOL:
kobol
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.
Jobol wygenerowany przez konwerter linia po linii:
Jawa
// 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";
}
}
}
Idiomatyczna Java to wykwalifikowana modernizacja, która produkuje:
Jawa
// 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();
}
}
Wersja Jobol składa się z 32 linii statycznego stanu globalnego, o strukturze proceduralnej, nazwach COBOL i niemożliwych do przetestowania jednostkowego bez uprzedniej inicjalizacji stanu klasy globalnej. Wersja idiomatyczna składa się z 20 linii, jest wstrzykiwalna, testowalna i natychmiast czytelna dla każdego programisty Javy bez doświadczenia w COBOL-u. Obie implementują te same reguły biznesowe. Tylko jedna jest możliwa do utrzymania przez zespół, któremu modernizacja miała umożliwić.
Sześć wzorców Jobola i dlaczego konwertery je produkują
Wzorzec 1: Globalny stan statyczny zastępujący PAMIĘĆ ROBOCZĄ
Sekcja WORKING-STORAGE języka COBOL przechowuje zmienne na poziomie programu, które są zachowywane po wywołaniach funkcji PERFORM. Jest to współdzielony, zmienny stan programu, każdy akapit odczytuje i zapisuje te same zmienne WS. Automatyczne konwertery mapują je bezpośrednio na pola statyczne Javy w jednej klasie, zachowując semantykę współdzielonego stanu, jednocześnie naruszając wszystkie zasady enkapsulacji Javy.
Dlaczego konwertery to robią: Mapowanie WORKING-STORAGE na pole statyczne to mechaniczna transformacja jeden do jednego. Konwerter nie rozumie, że model enkapsulacji Javy zastępuje współdzielony stan na poziomie programu zmiennymi instancji, parametrami metod i wartościami zwracanymi. Konwertuje to, co widzi, nie rozumiejąc, dlaczego pierwotna struktura istniała.
Konsekwencja: Stan statyczny jest nietestowalny w izolacji, wątkowo niebezpieczny bez jawnej synchronizacji i strukturalnie identyczny z językiem COBOL, który zastąpił. Każdy programista, który musi dodać współbieżność do systemu, musi najpierw rozplątać stan statyczny – zadanie, które zostało odroczone z konwersji do każdego kolejnego administratora.
Rozwiązanie: Mapowanie zmiennych WORKING-STORAGE na pola instancji, parametry metod lub wartości zwracane w oparciu o ich zakres użycia. Zmienne używane tylko w jednym akapicie stają się zmiennymi lokalnymi. Zmienne przekazywane między akapitami stają się parametrami metod lub wartościami zwracanymi. Zmienne, które rzeczywiście reprezentują stan obiektu współdzielonego, stają się polami instancji w prawidłowo hermetyzowanej klasie domeny.
Wzorzec 2: Łańcuchy PERFORM stają się długimi metodami statycznymi
Programy COBOL są zorganizowane jako łańcuchy instrukcji PERFORM. Główna procedura PERFORM wykonuje sekwencję nazwanych akapitów, z których każdy może wykonywać inne. Automatyczne konwertery tłumaczą każdy akapit na metodę statyczną, a każde polecenie PERFORM na wywołanie metody statycznej. Rezultatem jest pojedyncza klasa z dziesiątkami metod statycznych wywołujących się nawzajem za pośrednictwem grafu wywołań, który odzwierciedla strukturę instrukcji PERFORM w COBOL.
Jawa
// 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
}
Dlaczego konwertery to robią: Mapowanie strukturalne z akapitu COBOL na metodę Javy jest bezpośrednie. Konwerter poprawnie identyfikuje, że PERFORM oznacza „wywołaj tę jednostkę kodu”. Nie bierze pod uwagę faktu, że model obiektowy Javy organizuje kod wokół encji domeny, a nie wokół kroków przetwarzania.
Poprawka: Zidentyfikuj koncepcje domenowe osadzone w łańcuchu PERFORM. validateOrder, calculateTotal, applyDiscounts są operacjami na zamówieniu. processPayment jest operacją w kontekście płatności. checkInventory oraz updateInventory Są to operacje na Inventory. Refaktoryzacja dystrybuuje metody statyczne do klas domeny, do których należą, zastępując długi łańcuch wywołań proceduralnych krótką metodą orkiestracji, która deleguje zadania do odpowiednich obiektów domeny.
Wzorzec 3: Typy numeryczne bez precyzyjnej obsługi
Pola dziesiętne spakowane (COMP-3) w COBOL-u mają dokładną arytmetykę dziesiętną. Konwertery mapujące COMP-3 na Javę double or float wprowadzają systematyczne błędy zaokrągleń zmiennoprzecinkowych, które kumulują się w milionach transakcji finansowych.
Jawa
// 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)
Jawa
// 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
Dlaczego konwertery to robią: double jest domyślnym typem liczbowym Javy. Konwerter, który nie rozumie semantyki COMP-3, domyślnie użyje najpopularniejszego typu liczbowego Javy, co jest niewłaściwym wyborem w przypadku dokładnej arytmetyki dziesiętnej.
Poprawka: Każde pole COMP-3 jest mapowane na BigDecimal. Każde obliczenie numeryczne obejmujące wartości COMP-3 wykorzystuje BigDecimal arytmetyka. scale() ukończenia BigDecimal dopasowuje domniemane miejsca dziesiętne w klauzuli PIC: PIC S9(9)V99 ma 2 domniemane miejsca dziesiętne, mapując na BigDecimal ze skalą 2.
Wzorzec 4: ciągi EBCDIC i relikty tablic bajtów
COBOL przetwarza dane znakowe jako ciągi znaków o stałej długości, uzupełnione spacjami, w kodowaniu EBCDIC. Konwertery często generują kod Java, który zachowuje semantykę ciągów znaków o stałej długości, uzupełnionych spacjami, nawet po konwersji do UTF-8. W rezultacie Java obsługuje ciągi znaków jak programista komputerów mainframe z lat 1970. XX wieku.
Jawa
// 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));
Jawa
// 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())) { ... }
Dlaczego konwertery to robią: Definicja COBOL PIC X(40) ma długość, którą konwerter zachowuje jako rozmiar tablicy Java. Konwersja z EBCDIC do UTF-8 może być obsługiwana, ale semantyka o stałej długości jest niepotrzebnie przenoszona.
Poprawka: Mapa PIC X(n) pola do String obiektów, przycinanie przy odczycie i usuwanie ograniczeń o stałej długości. Jedynym kontekstem, w którym ograniczenia długości mają znaczenie, są granice trwałości (długości kolumn w bazie danych, pozycje w formatach plików), a nie model domeny.
Wzorzec 5: Obsługa błędów za pomocą kodów stanu
COBOL komunikuje warunki błędów za pomocą kodów statusu: FILE STATUS, SQLCODE, RETURN-CODE. Konwertery zachowują ten wzorzec w Javie, generując kod, który sprawdza całkowite kody statusu po każdej operacji, zamiast korzystać z modelu wyjątków Javy.
Jawa
// 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
}
Jawa
// 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);
}
Dlaczego konwertery to robią: Sprawdzanie kodu statusu to wzorzec języka COBOL; konwersja na metodę Javy, która zwraca lub ustawia pole statusu, to transformacja mechaniczna. Rozpoznanie, że wyjątki Javy są idiomatycznym odpowiednikiem, wymaga oceny architektonicznej, a nie mechanicznej translacji.
Poprawka: Zamapuj warunki błędów COBOL na wyjątki Java. STATUS PLIKU 10 (rekord nie znaleziony) staje się Optional.empty() lub wyjątek specyficzny dla domeny. Błędy SQLCODE stają się wyjątkami typu bazy danych. Struktura kodu Java odzwierciedla intencję, try/catch dla oczekiwanych trybów awarii, niesprawdzone wyjątki dla nieoczekiwanych.
Wzorzec 6: Monolityczna struktura klas
Programy COBOL są z założenia monolityczne – pojedynczy program obsługuje całą funkcję biznesową. Konwertery tworzą jedną klasę Java dla każdego programu COBOL, generując klasy Java, które mogą liczyć tysiące wierszy i obsługiwać wiele zadań, które w projektowaniu obiektowym rozdzieliłyby się na kilka wyspecjalizowanych klas.
Dlaczego konwertery to robią: Jeden program COBOL mapuje się na jedną klasę Java, a jednostką translacji konwertera jest program. Wewnętrzna struktura programu (jego akapity, sekcje, łańcuchy PERFORM) staje się wewnętrzną strukturą klasy bez jej rozpadu na mniejsze klasy.
Rozwiązanie: Zastosuj zasadę pojedynczej odpowiedzialności do każdej konwertowanej klasy. Klasa Jobol o 3,000 wierszach, która waliduje dane wejściowe, odczytuje je z bazy danych, stosuje reguły biznesowe, formatuje dane wyjściowe i zapisuje je do pliku, powinna stać się: walidatorem danych wejściowych, repozytorium, usługą domenową, formaterem i modułem zapisu, z których każdy można testować w izolacji, a każdy koncentruje się na jednym zadaniu.
Wymagania wstępne analizy strukturalnej
Każdy wzorzec Jobol ma odpowiadającą mu refaktoryzację. Jednak refaktoryzacja nie może być zastosowana przez konwerter, wymaga zrozumienia działania programu przed podjęciem decyzji o jego restrukturyzacji. Właśnie takie zrozumienie zapewnia analiza strukturalna kodu źródłowego w języku COBOL przed uruchomieniem jakiegokolwiek narzędzia konwersji.
Konkretnie rzecz biorąc, analiza strukturalna dostarcza danych wejściowych, które są niezbędne do podjęcia decyzji o konwersji:
Inwentaryzacja logiki biznesowej. Pełne wyliczenie warunków EVALUATE, rozgałęzień IF i formuł COMPUTE w każdym programie, czyli to, co program decyduje, a nie tylko jak jest skonstruowany. Ta inwentaryzacja to specyfikacja, którą musi spełniać zrefaktoryzowana wersja Java. Program z 847 warunkami EVALUATE wymaga struktury klasy docelowej, która uwzględnia 847 punktów decyzyjnych; wyjściem konwertera jest wersja robocza, a nie gotowy produkt.
Graf zależności. Które programy wywołują które inne programy. Łańcuch PERFORM obejmujący wiele programów COBOL staje się grafem wywołań usługi w Javie. Graf zależności określa, które programy można refaktoryzować niezależnie (niewiele zależności przychodzących), a które należy refaktoryzować jako skoordynowane grupy (wiele współdzielonych zależności poprzez kopie lub współdzielone dane).
Identyfikacja martwego kodu. Akapity i sekcje, które nigdy nie są WYKONYWANE z żadnej ścieżki produkcyjnej, to martwy kod i w ogóle nie powinny pojawiać się w przekonwertowanej Javie. Konwertery zawierające martwy kod zawyżają wartość przekonwertowanej bazy kodu i utrudniają późniejszą refaktoryzację.
Odzyskiwanie modelu danych. Wpisy VSAM FD, definicje tabel DB2 i struktury copybook definiujące dane programu. Każda struktura danych COBOL jest mapowana na jeden lub więcej obiektów domeny Java; mapowanie jest określane przez model danych, a nie przez nazwy pól w WORKING-STORAGE.
| Dane wejściowe analizy | Decyzja o konwersji, którą napędza |
|---|---|
| OCEŃ/JEŻELI liczba oddziałów | Rozkład klasy domeny, ile przypadków decyzyjnych obsługuje każda usługa |
| Liczba zależności przychodzących | Kolejność refaktoryzacji, najpierw programy o najmniejszej liczbie zależności |
| Procent martwego kodu | Zmniejszenie zakresu, wykluczenie nieosiągalnego kodu z konwersji |
| Pola COMP-3 | BigDecimal mapowanie dla każdego pola numerycznego |
| Długości pól PIC X | Mapowanie typów ciągów i ograniczenia warstwy trwałości |
| Struktura grafu PERFORM | Rozkład warstwy usług, łańcuchy PERFORM stają się wywołaniami usług domenowych |
| Użycie STATUSU PLIKU | Projekt modelu wyjątków, które kody statusu są mapowane na które typy wyjątków |
Co zamiast tego powinna wytworzyć konwersja
Alternatywą dla Jobol jest proces konwersji, który wykorzystuje COBOL jako specyfikację, a nie szablon. Program COBOL zna logikę biznesową, a program Java powinien wyrazić tę logikę w języku Java.
Zasada konwersji: Konwertuj intencję, a nie składnię. COBOL
IF CUST-CREDIT-SCORE < 650 MOVE 'DECLINED' TO WS-CREDIT-RESULTmówi: „klient z scoringiem kredytowym poniżej 650 zostaje odrzucony”. Java powinna powiedzieć to samo w języku Java:if (customer.creditScore() < CreditThresholds.MINIMUM_SCORE) return CreditDecision.declined(...). Nieif (CUST_CREDIT_SCORE < 650) { WS_CREDIT_RESULT = "DECLINED"; }.
Praktyczny przepływ pracy konwersji, który generuje idiomatyczne dane w języku Java:
Krok 1: Analiza strukturalna źródła COBOL, graf zależności, inwentaryzacja logiki biznesowej, odzyskiwanie modelu danych, identyfikacja martwego kodu. Ten krok generuje specyfikację. Dopóki ten krok się nie zakończy, nic nie jest konwertowane.
Krok 2: Projekt modelu domeny, identyfikacja jednostek biznesowych (Klient, Konto, Transakcja, Polityka), na których operują programy COBOL. Stają się one klasami domeny Java. Zmienne WORKING-STORAGE, które reprezentują stan jednostki, stają się polami instancji w odpowiedniej klasie domeny.
Krok 3: Projekt warstwy usług, identyfikacja operacji biznesowych (sprawdzanie zdolności kredytowej, przetwarzanie płatności, obliczanie salda) implementowanych przez akapity i sekcje COBOL. Stają się one metodami usług Java w odpowiedniej klasie usług domenowych. Łańcuch PERFORM, który sekwencjonuje akapity, staje się logiką orkiestracji usługi.
Krok 4: Automatyczna konwersja jako generator projektu. Użyj narzędzia konwersji, aby wygenerować początkowy projekt Java dla każdego programu, korzystając z modelu domeny opracowanego w krokach 2 i 3. Przejrzyj projekt pod kątem inwentaryzacji logiki biznesowej, aby upewnić się, że każda gałąź decyzyjna jest reprezentowana.
Krok 5: Systematyczna refaktoryzacja w oparciu o wzorce Jobola, zastosowanie sześciu poprawek antywzorcowych: zastąpienie stanu statycznego stanem instancji, dystrybucja metod statycznych do klas domeny, zastąpienie kodów stanu wyjątkami, zastąpienie double w BigDecimal, zastąp tablice o stałej długości tablicami String, rozkłada klasy monolityczne na usługi o pojedynczej odpowiedzialności.
Krok 6: Testowanie równoważności behawioralnej – uruchom zrefaktoryzowaną wersję Javy na korpusie testów charakterystyki wygenerowanym z analizy COBOL. Każdy warunek EVALUATE i gałąź IF powinny mieć co najmniej jeden przypadek testowy, który go sprawdza i weryfikuje równoważność z wynikami COBOL.
W jaki sposób SMART TS XL Zapobiega Jobolowi u źródła
Warunkiem wstępnym analizy strukturalnej w celu zapobiegania błędom Jobola, grafu zależności, inwentaryzacji logiki biznesowej, identyfikacji martwego kodu i odzyskiwania modelu danych jest dokładnie to, czego potrzebujesz SMART TS XLAnaliza kodu źródłowego COBOL jest przeprowadzana przed uruchomieniem jakiegokolwiek narzędzia konwersji.
SMART TS XL'S statyczna analiza kodu Wylicza każdy warunek EVALUATE, każdą gałąź IF, każdą formułę COMPUTE i każdą relację PERFORM w kodzie źródłowym COBOL, czyli kompletny inwentarz logiki biznesowej, który zrefaktoryzowana Java musi wiernie odzwierciedlać. Gdy narzędzie konwersji generuje Jobol, inwentarz logiki biznesowej stanowi specyfikację, względem której weryfikowane jest refaktoryzacja: każdy warunek w inwentarzu musi występować w Javie, w odpowiedniej klasie domenowej, wyrażonej w języku Java.
Mapowanie zależności aplikacji generuje graf PERFORM i graf wywołań programu, które określają strukturę warstwy usług Java. Programy, które wywołują się nawzajem, często należą do tego samego ograniczonego kontekstu. Programy wywoływane przez wiele innych to usługi współdzielone, które muszą być starannie zaprojektowane, aby obsługiwać wszystkich swoich odbiorców w architekturze Java. Graf zależności stanowi dane wejściowe do etapu projektowania warstwy usług, konwertując niejawną strukturę sprzężeń COBOL-a na jawną strukturę wstrzykiwania zależności Javy.
Analiza modernizacji legacy identyfikuje martwy kod, akapity i sekcje, do których nie udało się dotrzeć ze ścieżek wykonania produkcyjnego, a które powinny zostać całkowicie wyłączone z zakresu konwersji. Konwersja martwego kodu COBOL na martwy kod Jobola, a następnie refaktoryzacja martwego kodu Jobola, marnuje nakład pracy, który jest eliminowany przez etap identyfikacji martwego kodu przed rozpoczęciem konwersji.
Funkcja analizy wpływu weryfikuje kolejność refaktoryzacji: gdy interfejs programu COBOL zmienia się podczas refaktoryzacji z Jobol do idiomatycznej Javy, analiza wpływu identyfikuje każdy inny program, którego odpowiednik w Javie również musi zostać zaktualizowany, aby zachować spójność ze zmienionym interfejsem. Refaktoryzacja w kolejności zależności, z najmniejszą liczbą elementów zależnych na początku, minimalizuje koordynację wymaganą na każdym etapie.
Konwertery tłumaczą składnię. Modernizacja zmienia znaczenie.
Automatyczne konwertery z COBOL-a do Javy są szybsze niż przepisywanie kodu przez człowieka. Są one również zoptymalizowane pod kątem innego celu: zgodności składniowej, a nie ekwiwalencji semantycznej w idiomie języka docelowego. Jobol to efekt zgodności składniowej, który powstaje, gdy język źródłowy (COBOL) i język docelowy (Java) mają zasadniczo różne modele strukturalne.
Organizacje, które unikają Jobol, to nie te, które używają lepszych konwerterów. To te, które traktują konwerter jako generator szkiców, a nie gotowy produkt, inwestują w analizę strukturalną przed rozpoczęciem konwersji, projektują model domeny Java przed uruchomieniem konwertera i stosują systematyczną refaktoryzację wyników konwertera, wykorzystując inwentaryzację logiki biznesowej jako specyfikację walidacyjną.
Można uniknąć Jobol. Kosztem uniknięcia jest analiza strukturalna i modelowanie domeny, które powinny poprzedzać każdą konwersję. Kosztem nieuniknięcia jest system Java, którego utrzymanie wymaga znajomości języka COBOL, co oznacza, że oczekiwane korzyści z modernizacji, czyli możliwość utrzymania systemu przez programistów Java, nigdy nie zostaną zrealizowane.
Zmień intencję. Nie składnię. Różnica tkwi w całej wartości modernizacji.


