ההמרה הושלמה תוך שלושה חודשים. יישום הג'אווה עבר קומפילציה, עבר מבחני עשן בסיסיים והוכרז כמוכן לפריסה. שישה חודשים לאחר תחילת הייצור, צוות הפלטפורמה שם לב למשהו מטריד: אף אחד בצוות ג'אווה לא הצליח לתחזק את הקוד. הסקירות ארכה פי שניים מסקירות ג'אווה רגילות. דוחות הבאגים התייחסו למושגים, WORKING-STORAGE, לוגיקת PROCEDURE DIVISION, מוסכמות של שדות עשרוניים עמוסים, שמפתחי ג'אווה ללא ניסיון במחשבים מרכזיים לא יכלו לעקוב אחריהם. היישום הומר מ-COBOL לג'אווה, אך ג'אווה שנוצרה חשבה, בנתה והתנהגה כמו COBOL. זה היה ג'אבול.
ג'בול (לפעמים מכונה JOBOL) הוא שם משפחה לקוד ג'אווה ששומר על הסמנטיקה הפרוצדורלית של COBOL מבלי לאמץ את יכולות ה-"מונחיות העצמים" של ג'אווה. ג'ייסון בלומברג, מייסד חברת האנליסטים Intellyx, הגדיר זאת ישירות: ג'בול הוא קוד ג'אווה תקף מבחינה טכנית שמשאיר את ארכיטקטורת התוכנה המקורית במקומה ושומר על סמנטיקה של COBOL, מה שמחייב את המפתחים להתייחס לג'אווה כאילו הייתה COBOL. התוצאה הקריטית מגיעה מיד: ארגון שממיר COBOL ל-Jobol לא שחרר את עצמו מהצורך במומחיות COBOL. הוא פשוט העביר את דרישת המומחיות הזו לשפה שאינה תומכת באופן טבעי בתבניות COBOL שהקוד מכיל. הוא יצר מערכת שקשה יותר לתחזוקה מאשר COBOL המקורי ואינה מספקת אף אחת מהיתרונות הצפויים של ג'אווה.
גרף תלות לפני עיצוב דומיין
SMART TS XL ממפה כל תלות של PERFORM ו-CALL כך ששכבת השירות של Java משקפת את מבנה הצימוד בפועל, ולא את מבנה המחלקה COBOL.
גלו עוד…איך ג'ובול נראה באמת
לפני אבחון הגורמים, יש צורך שהדפוס יהיה גלוי. הנה אותה היגיון עסקי, בדיקת אשראי של לקוח, בשלוש צורות: COBOL המקורי, Jobol שממירים אוטומטיים מייצרים בדרך כלל, וג'אווה אידיומטית שמייצרת מודרניזציה מיומנת.
ה-COBOL המקורי:
קובול
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: 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";
}
}
}
ג'אווה האידיומטית, מודרניזציה מיומנת מייצרת:
תאווה
// 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();
}
}
גרסת Jobol היא בעלת 32 שורות של מצב גלובלי סטטי, בנוי באופן פרוצדורלי, בעל שם COBOL, ואי אפשר לבצע בדיקת יחידה מבלי לאתחל תחילה את מצב המחלקה הגלובלי. הגרסה האידיומטית היא בעלת 20 שורות, ניתנת להזרקה, ניתנת לבדיקה וקריאה מיידית על ידי כל מפתח Java ללא רקע ב-COBOL. שתיהן מיישמות את אותם כללי עסקים. רק אחד מהם ניתן לתחזוקה על ידי הצוות שהמודרניזציה הייתה אמורה לאפשר.
ששת דפוסי הג'ובול ומדוע ממירים מייצרים אותם
תבנית 1: מצב סטטי גלובלי המחליף WORKING-STORAGE
מקטע WORKING-STORAGE של COBOL מכיל משתנים ברמת התוכנית שנשארים לאורך קריאות PERFORM. זהו המצב המשותף הניתן לשינוי של התוכנית, כל פסקה קוראת וכותבת את אותם משתני WS. ממירים אוטומטיים ממפים זאת ישירות לשדות סטטיים של Java במחלקה אחת, תוך שמירה על הסמנטיקה של המצב המשותף תוך הפרה של כל עקרון אנקפסולציה של Java.
מדוע ממירים עושים זאת: מיפוי שדות מ-WORKING-STORAGE למיפוי שדות סטטי הוא טרנספורמציה מכנית של אחד לאחד. הממיר אינו מבין שמודל האנקפסולציה של ג'אווה מחליף מצב משותף ברמת התוכנית במשתני מופע, פרמטרי מתודה וערכי החזרה. הוא ממיר את מה שהוא רואה מבלי להבין מדוע המבנה המקורי היה קיים.
התוצאה: מצב סטטי אינו ניתן לבדיקה בבידוד, אינו בטוח עבור הליכי משנה ללא סנכרון מפורש, וזהה מבחינה מבנית ל-COBOL אותו החליף. כל מפתח שצריך להוסיף מקביליות למערכת חייב תחילה לפרק את המצב הסטטי, עבודה שנדחתה מההמרה לכל מתחזק עוקב.
התיקון: מיפוי משתני WORKING-STORAGE לשדות מופע, פרמטרי מתודה או ערכי החזרה בהתבסס על היקף השימוש שלהם. משתנים המשמשים רק בתוך פסקה אחת הופכים למשתנים מקומיים. משתנים המועברים בין פסקאות הופכים לפרמטרי מתודה או ערכי החזרה. משתנים המייצגים באמת את מצב האובייקט המשותף הופכים לשדות מופע במחלקת תחום עטופה כראוי.
תבנית 2: ביצוע שרשראות הופכות לשיטות סטטיות ארוכות
תוכניות COBOL מאורגנות כשרשראות PERFORM, כאשר הפרוצדורה העיקרית PERFORM מבצעת רצף של פסקאות בעלות שם, שכל אחת מהן עשויה לבצע PERFORM אחרות. ממירים אוטומטיים מתרגמים כל פסקה לשיטה סטטית וכל PERFORM לקריאה לשיטה סטטית. התוצאה היא מחלקה אחת עם עשרות מתודות סטטיות הקוראות זו לזו באמצעות גרף קריאה המשקף את מבנה PERFORM של COBOL.
תאווה
// 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
}
מדוע ממירים עושים זאת: המיפוי המבני מפסקת COBOL לשיטת Java הוא ישיר. הממיר מזהה נכון ש-PERFORM פירושו "קרא ליחידת קוד זו". מה שהוא מפספס הוא שמודל האובייקטים של Java מארגן את הקוד סביב ישויות תחום, ולא סביב שלבי עיבוד.
התיקון: זהה את מושגי התחום המוטמעים בשרשרת PERFORM. validateOrder, calculateTotal, ו applyDiscounts הן פעולות על הזמנה. processPayment היא פעולה בהקשר של תשלום. checkInventory ו updateInventory הן פעולות על Inventory. ה-refactoring מחלק את המתודות הסטטיות למחלקות התחום אליהן הן שייכות, ומחליף שרשרת קריאה פרוצדורלית ארוכה בשיטת תזמור קצרה שמאצילה סמכויות לאובייקטים מתאימים בתחום.
תבנית 3: סוגים מספריים ללא טיפול מדויק
לשדות עשרוניים ארוזים (COMP-3) של COBOL יש חשבון עשרוני מדויק. ממירים שממפים COMP-3 ל-Java double or float להציג שגיאות עיגול שיטתיות של נקודה צפה המצטברות על פני מיליוני עסקאות פיננסיות.
תאווה
// 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)
תאווה
// 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
למה ממירים עושים זאת: double הוא סוג המספרי המוגדר כברירת מחדל של ג'אווה. ממיר שאינו מבין באופן ספציפי את הסמנטיקה של COMP-3 יבחר כברירת מחדל את סוג המספרי הנפוץ ביותר בג'אווה, שהוא הבחירה הלא נכונה עבור חשבון עשרוני מדויק.
התיקון: כל שדה COMP-3 ממפה ל BigDecimalכל חישוב מספרי הכולל ערכי COMP-3 משתמש BigDecimal חשבון. ה scale() של BigDecimal תואם את המקומות העשרוניים המשתמעים בפסקת PIC: PIC S9(9)V99 יש 2 ספרות אחרי הנקודה, מיפוי ל BigDecimal עם קנה מידה 2.
תבנית 4: מחרוזות EBCDIC ושרידי מערך בייט
COBOL מעבד נתוני תווים כמחרוזות מרופדות באורך קבוע בקידוד EBCDIC. ממירים מייצרים לעתים קרובות קוד Java ששומר על סמנטיקה של מחרוזות מרופדות באורך קבוע גם לאחר המרה ל-UTF-8, וכתוצאה מכך Java מטפלת במחרוזות כמו מתכנת מיינפריים משנות ה-1970.
תאווה
// 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));
תאווה
// 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())) { ... }
מדוע ממירים עושים זאת: להגדרת COBOL PIC X(40) יש אורך שהממיר שומר כגודל מערך של Java. ייתכן שההמרה מ-EBCDIC ל-UTF-8 תטופל, אך הסמנטיקה באורך קבוע מועברת ללא צורך.
התיקון: מַפָּה PIC X(n) שדות ל String אובייקטים, חיתוך בעת קריאה והסרת אילוצים באורך קבוע. ההקשר היחיד שבו אילוצי אורך חשובים הוא בגבולות ההתמדה (אורך עמודות מסד נתונים, מיקומי פורמט קובץ), לא במודל הדומיין.
תבנית 5: טיפול בשגיאות באמצעות קודי סטטוס
COBOL מתקשר מצבי שגיאה באמצעות קודי סטטוס: FILE STATUS, SQLCODE, RETURN-CODE. ממירים משמרים דפוס זה ב-Java, ומייצרים קוד שבודק קודי סטטוס שלמים לאחר כל פעולה במקום להשתמש במודל החריגים של Java.
תאווה
// 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
}
תאווה
// 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);
}
מדוע ממירים עושים זאת: בדיקת קוד סטטוס היא תבנית COBOL; המרתו לשיטת Java שמחזירה או מגדירה שדה סטטוס היא טרנספורמציה מכנית. ההכרה בכך שחריגים ב-Java הם המקבילה האידיומטית דורשת שיקול דעת ארכיטקטוני, לא תרגום מכני.
התיקון: מיפוי תנאי שגיאה של COBOL לחריגים ב-Java. סטטוס קובץ 10 (רשומה לא נמצאה) הופך ל- Optional.empty() או חריג ספציפי לתחום. שגיאות SQLCODE הופכות לחריגי מסד נתונים מסוג Typed. מבנה קוד Java משקף כוונה, try/catch עבור מצבי כשל צפויים, וחריגים לא מסומנים עבור מצבי כשל בלתי צפויים.
תבנית 6: מבנה מעמדי מונוליטי
תוכניות COBOL הן מונוליטיות מטבען, תוכנית אחת מטפלת בפונקציה עסקית שלמה. ממירים יוצרים מחלקת Java אחת לכל תוכנית COBOL, ומייצרים מחלקות Java שאולי יהיו באורך של אלפי שורות ומטפלות במספר תחומי אחריות שתכנון מונחה עצמים היה מחלק על פני מספר מחלקות ממוקדות.
מדוע ממירים עושים זאת: תוכנית COBOL אחת ממפה למחלקת Java אחת, יחידת התרגום של הממיר היא התוכנית. המבנה הפנימי של התוכנית (פסקאות, מקטעים, שרשראות PERFORM) הופך למבנה הפנימי של המחלקה ללא פירוק למחלקות קטנות יותר.
התיקון: יש להחיל את עקרון האחריות היחידה על כל מחלקה שהומרה. מחלקת Jobol בת 3,000 שורות שמאמתת קלט, קוראת ממסד נתונים, מיישמת כללי עסקיים, מעצבת פלט וכותבת לקובץ צריכה להפוך ל: מאמת קלט, מאגר, שירות תחום, מעצב וכותב, כל אחד ניתן לבדיקה בנפרד, כל אחד מתמקד באחריות אחת.
תנאי מוקדם לניתוח מבני
לכל תבנית Jobol יש שיפוץ מקביל. אבל השיפוץ לא יכול להיות מיושם על ידי הממיר, הוא דורש הבנה של מה שהתוכנית עושה לפני שמחליטים כיצד לבנות אותה מחדש. הבנה זו היא בדיוק מה שניתוח מבני של COBOL המקור מספק לפני הפעלת כל כלי המרה.
באופן ספציפי, ניתוח מבני מייצר את התשומות הנדרשות להחלטות המרה:
מלאי לוגיקה עסקית. הפירוט המלא של תנאי EVALUATE, ענפי IF ונוסחאות COMPUTE בכל תוכנית, מה שהתוכנית מחליטה, לא רק איך היא בנויה. מלאי זה הוא המפרט שה-Java שעבר שיפוץ חייב להתאים לו. תוכנית עם 847 תנאי EVALUATE דורשת מבנה מחלקה יעד שמכיל 847 נקודות החלטה; הפלט של הממיר הוא טיוטת ההתחלה, לא המוצר המוגמר.
גרף תלות. אילו תוכניות קוראות לאילו תוכניות אחרות. שרשרת PERFORM המשתרעת על פני מספר תוכניות COBOL הופכת לגרף קריאה לשירות ב-Java. גרף התלות קובע אילו תוכניות ניתן לעבד מחדש באופן עצמאי (מעט תלויות נכנסות) ואילו יש לעבד מחדש כקבוצות מתואמות (תלויות משותפות רבות באמצעות ספרי עותקים או נתונים משותפים).
זיהוי קוד מת. פסקאות וקטעים שמעולם לא מבוצעים מכל נתיב ביצוע ייצור הם קוד מת, הם לא אמורים להופיע כלל ב-Java המומר. ממירים הכוללים קוד מת מנפחים את בסיס הקוד המומר ואת מאמצי העיבוד מחדש שלאחר מכן.
שחזור מודל נתונים. ערכי VSAM FD, הגדרות טבלאות DB2 ומבני ספר עותקים המגדירים את נתוני התוכנית. כל מבנה נתונים של COBOL ממופה לאובייקט תחום אחד או יותר של Java; המיפוי נקבע על ידי מודל הנתונים, לא על ידי שמות השדות ב-WORKING-STORAGE.
| קלט ניתוח | החלטת המרה שהיא מניעה |
|---|---|
| ספירת ענפי EVALUATE/IF | פירוק מחלקות דומיין, כמה מקרי החלטה כל שירות מטפל בהם |
| ספירת תלות נכנסות | רצף עיבוד מחדש, מספר התלויות הקטן ביותר תחילה |
| אחוז קוד מת | צמצום היקף, אי הכללת קוד שאינו נגיש מההמרה |
| שדות COMP-3 | BigDecimal מיפוי עבור כל שדה מספרי |
| אורכי שדה PIC X | מיפוי סוגי מחרוזות ואילוצי שכבת התמדה |
| מבנה גרף PERFORM | פירוק שכבת השירות, שרשראות PERFORM הופכות לקריאות שירות של תחום |
| שימוש במצב קובץ | עיצוב מודל חריגים, אילו קודי סטטוס ממפים לאילו סוגי חריגים |
מה שההמרה צריכה לייצר במקום זאת
האלטרנטיבה ל-Jobol היא תהליך המרה המשתמש ב-COBOL כמפרט ולא כתבנית. תוכנית COBOL יודעת מהי הלוגיקה העסקית, ותוכנית Java צריכה לבטא את הלוגיקה הזו בניב הקוד של Java.
עקרון ההמרה: המר את הכוונה, לא את התחביר. ה-COBOL
IF CUST-CREDIT-SCORE < 650 MOVE 'DECLINED' TO WS-CREDIT-RESULTאומר "לקוח עם דירוג אשראי מתחת ל-650 נדחה". שפת הג'אווה אמורה לומר את אותו הדבר בשפת ג'אווה:if (customer.creditScore() < CreditThresholds.MINIMUM_SCORE) return CreditDecision.declined(...). לֹאif (CUST_CREDIT_SCORE < 650) { WS_CREDIT_RESULT = "DECLINED"; }.
תהליך העבודה המעשי של ההמרה שמייצר ג'אווה אידיומטית:
שלב 1: ניתוח מבני של מקור COBOL, גרף תלות, מלאי לוגיקה עסקית, שחזור מודל נתונים, זיהוי קוד מת. שלב זה מייצר את המפרט. שום דבר לא מומר עד להשלמת שלב זה.
שלב 2: תכנון מודל דומיין, זיהוי ישויות העסקיות (לקוח, חשבון, עסקה, מדיניות) שעליהן פועלות תוכניות COBOL. אלו הופכות למחלקות דומיין של Java. משתני WORKING-STORAGE המייצגים את מצב הישות הופכים לשדות מופע במחלקת הדומיין המתאימה.
שלב 3: תכנון שכבת השירות, זיהוי פעולות העסק (בדיקת אשראי, עיבוד תשלומים, חישוב יתרה) שפסקאות וסעיפים של COBOL מיישמים. אלה הופכות למתודות שירות Java במחלקת השירות המתאימה בתחום. שרשרת PERFORM שמסדרת פסקאות הופכת ללוגיקת התזמור של השירות.
שלב 4: המרה אוטומטית כמחולל טיוטות, השתמש בכלי ההמרה כדי לייצר טיוטת Java התחלתית עבור כל תוכנית, בהתבסס על מודל התחום שתוכנן בשלבים 2 ו-3. סקור את הטיוטה מול מלאי הלוגיקה העסקית כדי לוודא שכל ענף החלטות מיוצג.
שלב 5: שחזור שיטתי כנגד תבניות Jobol, יישום ששת תיקוני האנטי-תבניות: החלפת מצב סטטי במצב מופע, הפצת מתודות סטטיות למחלקות דומיין, החלפת קודי סטטוס בחריגים, החלפה double עם BigDecimal, החלף מערכים באורך קבוע ב- String, לפרק מחלקות מונוליטיות לשירותים בעלי אחריות יחידה.
שלב 6: בדיקת שקילות התנהגותית, הפעלת קוד Java שעבר רפקטורציה כנגד קורפוס בדיקות האפיון שנוצר מניתוח COBOL. לכל תנאי EVALUATE וענף IF צריך להיות לפחות מקרה בדיקה אחד שמפעיל אותו ומאמת שקילות עם פלט COBOL.
איך SMART TS XL מונע ג'ובול במקור
הניתוח המבני הנדרש למניעת ג'ובול, גרף התלות, מלאי לוגיקה עסקית, זיהוי קוד מת ושחזור מודל נתונים, הוא בדיוק מה SMART TS XLהניתוח של מקור COBOL מספק לפני הפעלת כל כלי המרה.
SMART TS XL"S ניתוח קוד סטטי מונה כל תנאי EVALUATE, כל ענף IF, כל נוסחת COMPUTE וכל קשר PERFORM במקור COBOL, מלאי הלוגיקה העסקית המלא ש-Java שעבר שיפוץ חייב לייצג נאמנה. כאשר כלי ההמרה מייצר Jobol, מלאי הלוגיקה העסקית הוא המפרט שלפיו השיפוץ מאושר: כל תנאי במלאי חייב להופיע ב-Java, במחלקת התחום המתאימה, כפי שמבוטא בניב של Java.
מיפוי תלות היישומים מייצר את גרף PERFORM ואת גרף קריאת התוכנית הקובעים את מבנה שכבת השירות של Java. תוכניות הקוראות זו לזו שייכות לעתים קרובות לאותו הקשר מוגבל. תוכניות הנקראות על ידי רבות אחרות הן השירותים המשותפים שיש לתכנן בקפידה כדי לתמוך בכל הצרכנים שלהן בארכיטקטורת Java. גרף התלות הוא הקלט לשלב תכנון שכבת השירות, וממיר את מבנה הצימוד המרומז של COBOL למבנה הזרקת התלות המפורשת של Java.
ניתוח המודרניזציה של קוד מדור קודם מזהה קוד מת, פסקאות וקטעים שמעולם לא הגיעו אליהם מנתיבי ביצוע הייצור, שיש להוציאם לחלוטין מתחום ההמרה. המרת COBOL מת ל-Jobol מת ולאחר מכן עיבוד מחדש של Jobol מת מבזבזת מאמץ ששלב זיהוי הקוד המת מבטל לפני תחילת ההמרה.
יכולת ניתוח ההשפעה מאמתת את רצף העיבוד מחדש: כאשר ממשק תוכנית COBOL משתנה במהלך העיבוד מחדש מ-Jobol ל-Java אידיומטי, ניתוח ההשפעה מזהה כל תוכנית אחרת שגם המקבילה שלה ב-Java חייבת להתעדכן כדי להישאר עקבית עם הממשק שהשתנה. עיבוד מחדש לפי סדר תלויות, כאשר מספר התלויים הנמוך ביותר קודם, ממזער את התיאום הנדרש בכל שלב.
ממירים מתרגמים תחביר. מודרניזציה משנה משמעות.
ממירים אוטומטיים של COBOL ל-Java מהירים יותר מכתיבה מחדש אנושית. הם גם מותאמים למטרה שונה: התאמה תחבירית ולא שקילות סמנטית בשפת היעד. Jobol הוא מה שהתאמה תחבירית מייצרת כאשר לשפת המקור (COBOL) ולשפת היעד (Java) יש מודלים מבניים שונים באופן מהותי.
הארגונים שנמנעים מ-Jobol אינם אלה שמשתמשים בממירים טובים יותר. הם אלה שמתייחסים לממיר כאל מחולל טיוטות ולא כמוצר מוגמר, משקיעים בניתוח מבני לפני תחילת ההמרה, מתכננים את מודל הדומיין של Java לפני שהממיר פועל, ומיישמים שיפוץ שיטתי על פלט הממיר כאשר מלאי הלוגיקה העסקית הוא מפרט האימות.
ניתן להימנע מ-Jobol. העלות של הימנעות ממנו היא עבודת הניתוח המבני ומידול הדומיינים שצריכות להקדים כל המרה. העלות של אי הימנעות ממנו היא מערכת Java הדורשת מומחיות ב-COBOL כדי לתחזק, מה שאומר שהתועלת הצפויה של המודרניזציה, היכולת לתחזק את המערכת עם מפתחי Java, לעולם לא תתממש.
המר את הכוונה. לא את התחביר. ההבדל הוא הערך המלא של המודרניזציה.


