- Tác giả

- Name
- Nguyễn Đức Xinh
- Ngày xuất bản
- Ngày xuất bản
Cấu trúc điều kiện trong COBOL – IF, EVALUATE và best practice cho backend dev
Vì sao phải hiểu rõ điều kiện trong COBOL?
Trong mọi ngôn ngữ lập trình, rẽ nhánh điều kiện (conditional) là trung tâm của business logic. Với COBOL – đặc biệt trong hệ thống banking/enterprise – điều kiện lại càng quan trọng hơn vì:
- Business rule thường dài, nhiều nhánh, dễ sai nếu code IF lồng nhau quá phức tạp
- Cần đọc/maintain chương trình cũ hàng chục ngàn dòng, sử dụng cả
IFvàEVALUATE - Error handling, logging, mapping status → message đều dùng condition
Ở bài 004, bạn đã nắm toán tử và biểu thức, bài này tập trung vào:
- Cú pháp và cách dùng
IF ... ELSE ... END-IF.trong COBOL EVALUATE– tương đươngswitch-casetrong ngôn ngữ hiện đại- Kết hợp điều kiện với
AND,OR,NOT - Best practice để code điều kiện đọc được, tránh "IF hell"
- Liên hệ trực tiếp với code enterprise trong
[course/cobol/sections/code-example/RZZBSQLN1.PCO](course/cobol/sections/code-example/RZZBSQLN1.PCO)
IF, ELSE, END-IF trong COBOL
Cú pháp cơ bản
IF condition
statement-1
END-IF.
Với ELSE:
IF condition
statement-1
ELSE
statement-2
END-IF.
So với Java/Python:
IF~ifELSE~elseEND-IF.~ dấu{}đóng block
Ví dụ đơn giản: kiểm tra tuổi
01 WS-AGE PIC 99.
PROCEDURE DIVISION.
MOVE 20 TO WS-AGE.
IF WS-AGE >= 18
DISPLAY "Adult"
ELSE
DISPLAY "Minor"
END-IF.
STOP RUN.
Ví dụ trong enterprise: check file status
Trong RZZBSQLN1.PCO có đoạn:
INP1-OPEN-RTN.
MOVE "INP1-OPEN-RTN" TO DSP_PROC.
OPEN INPUT INP1FILE.
IF F_STS NOT = "00"
MOVE "FILE :" TO DSP_MSG
MOVE INP1_FILE TO DSP_MSGNAIYO
MOVE "No.004" TO DSP_MSGCD
...
PERFORM IO-ERROR THRU IO-ERROR-EXT
GO TO STOP-PGM
END-IF.
INP1-OPEN-EXT.
EXIT.
Giải nghĩa theo mindset backend dev:
open INP1FILE
if (fSts != "00") {
// fill error message
ioError()
goto stopPgm
}
Pattern này lặp lại trong nhiều routine:
- Check file open/close/read
- Nếu error → set message →
PERFORM IO-ERROR→GO TO STOP-PGM
Kết hợp điều kiện với AND, OR, NOT
COBOL dùng:
AND– cả hai điều kiện đều đúngOR– một trong hai điều kiện đúngNOT– phủ định
Ví dụ: kiểm tra nhiều điều kiện
IF WS-AGE >= 18 AND WS-COUNTRY = "VN"
DISPLAY "Adult in Vietnam"
END-IF.
IF NOT (F_STS = "00") OR ERR1_ERRCNT > 0
DISPLAY "Has error"
END-IF.
Trong RZZBSQLN1.PCO có pattern:
IF BCMO-1 = ZERO OR
BCMO-2 = SPACE
GO TO CMD-GET-ERR
END-IF.
Mapping sang pseudo-code:
if (bcmo1 == 0 || bcmo2 == " ") {
goto cmdGetErr
}
Best practice:
- Khi AND/OR nhiều điều kiện, nên xuống dòng thẳng cột để dễ đọc
- Nếu logic phức tạp, có thể tách thành biến flag trung gian (ví dụ
WS-HAS-ERROR-FLAG)
Nested IF – Khi nào nên tránh?
IF lồng nhau quá sâu sẽ làm code khó đọc, đặc biệt trong COBOL, nơi block được kết thúc bằng END-IF. chứ không có {}.
Ví dụ xấu (minh họa):
IF A = 1
IF B = 2
IF C = 3
...
END-IF
END-IF
END-IF.
Cải thiện bằng cách:
- Dùng
AND:IF A = 1 AND B = 2 AND C = 3(nếu phù hợp) - Hoặc dùng
EVALUATE(switch-case) cho một số tình huống
Trong enterprise COBOL, thường thấy pattern early exit:
IF condition-error
... handle error ...
GO TO STOP-PGM
END-IF.
* logic ok nằm phía dưới, không bị IF bao quanh
Đây là cách mà RZZBSQLN1 xử lý lỗi file và lỗi SQL.
EVALUATE – switch-case trong COBOL
EVALUATE là cấu trúc rẽ nhánh mạnh mẽ, tương đương switch-case trong Java/C:
EVALUATE expression
WHEN value-1
statements-1
WHEN value-2
statements-2
WHEN OTHER
statements-default
END-EVALUATE.
Ví dụ cơ bản: phân loại điểm
01 WS-SCORE PIC 9(3).
PROCEDURE DIVISION.
MOVE 85 TO WS-SCORE.
EVALUATE TRUE
WHEN WS-SCORE >= 90
DISPLAY "A"
WHEN WS-SCORE >= 80
DISPLAY "B"
WHEN WS-SCORE >= 70
DISPLAY "C"
WHEN OTHER
DISPLAY "D"
END-EVALUATE.
STOP RUN.
Ở đây, trick hay là dùng EVALUATE TRUE để tạo ra cảm giác giống chuỗi if/else if/else.
Ví dụ thực tế trong RZZBSQLN1: đánh giá COMPLETION-CODE
Trong đoạn ENDDSP-RTN:
EVALUATE COMPLETION-CODE
WHEN 0
MOVE NC"�����͐���I�����܂����B" TO END_MSG41
WHEN 254
MOVE NC"�����͌x���I�����܂����B" TO END_MSG41
WHEN OTHER
MOVE NC"�����ُ͈�I�����܂����B" TO END_MSG41
END-EVALUATE.
Dịch nghĩa theo logic:
switch (completionCode) {
case 0:
message = "Kết thúc bình thường";
break;
case 254:
message = "Kết thúc với cảnh báo";
break;
default:
message = "Kết thúc bất thường";
}
Pattern này rất phổ biến trong batch:
- Mapping completion code → message hiển thị cuối job
- Mapping error code → text mô tả
EVALUATE nhiều expression (nâng cao)
COBOL còn cho phép EVALUATE nhiều expression một lúc:
EVALUATE A ALSO B
WHEN 1 ALSO 1
...
WHEN 1 ALSO 2
...
WHEN OTHER
...
END-EVALUATE.
Tuy nhiên trong thực tế enterprise, rất nhiều code chỉ dùng EVALUATE một biểu thức hoặc EVALUATE TRUE.
So sánh IF vs EVALUATE – dùng khi nào?
| Tình huống | Nên dùng | Lý do |
|---|---|---|
| Điều kiện đơn, 1–2 nhánh | IF |
Ngắn gọn, dễ đọc |
| Chuỗi nhiều nhánh trên cùng 1 biến | EVALUATE |
Giống switch-case, dễ maintain |
| Nhiều range (>=, <=) chồng nhau | EVALUATE TRUE |
Thay cho nhiều IF/ELSE IF |
| Check error trước rồi exit | IF (early exit) |
Rõ ràng, pattern phổ biến trong batch |
Trong RZZBSQLN1:
- Dùng IF cho các check đơn:
- Check
F_STSsau OPEN/READ/CLOSE - Check
INP1_INPCNT > 0trước khi EXEC SQL
- Check
- Dùng EVALUATE để map
COMPLETION-CODE→ message
Ví dụ tổng hợp: luồng xử lý đơn giản với IF + EVALUATE
Giả sử ta viết một batch COBOL nhỏ:
- Đọc tổng số record và số lỗi
- Tính
COMPLETION-CODE:- 0 nếu
ERR-COUNT = 0 - 254 nếu
ERR-COUNT > 0nhưng< 10 - 255 nếu
ERR-COUNT >= 10
- 0 nếu
- In message cuối job dựa vào
COMPLETION-CODE
IDENTIFICATION DIVISION.
PROGRAM-ID. JOB-END-DEMO.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-REC-COUNT PIC 9(6) VALUE ZERO.
01 WS-ERR-COUNT PIC 9(6) VALUE ZERO.
01 COMPLETION-CODE PIC 9(3) VALUE 0.
01 WS-END-MESSAGE PIC X(50).
PROCEDURE DIVISION.
* Giả lập kết quả xử lý
MOVE 100 TO WS-REC-COUNT.
MOVE 3 TO WS-ERR-COUNT.
* Xác định COMPLETION-CODE
IF WS-ERR-COUNT = 0
MOVE 0 TO COMPLETION-CODE
ELSE
IF WS-ERR-COUNT < 10
MOVE 254 TO COMPLETION-CODE
ELSE
MOVE 255 TO COMPLETION-CODE
END-IF
END-IF.
* Map COMPLETION-CODE -> message
EVALUATE COMPLETION-CODE
WHEN 0
MOVE "JOB END NORMAL" TO WS-END-MESSAGE
WHEN 254
MOVE "JOB END WITH WARN" TO WS-END-MESSAGE
WHEN OTHER
MOVE "JOB END ABEND" TO WS-END-MESSAGE
END-EVALUATE.
DISPLAY "REC= " WS-REC-COUNT.
DISPLAY "ERR= " WS-ERR-COUNT.
DISPLAY WS-END-MESSAGE.
STOP RUN.
Đây chính là pattern mà RZZBSQLN1 áp dụng ở quy mô lớn hơn.
Bài tập thực hành
Bài 1 – Phân loại khách hàng theo số dư
Yêu cầu:
- Khai báo:
BALANCE PIC S9(7)V99,RANK PIC X(10) - Logic:
- Nếu
BALANCE < 0→RANK = "DEBT" - Nếu
BALANCE >= 0và< 1000→RANK = "NORMAL" - Nếu
BALANCE >= 1000→RANK = "VIP"
- Nếu
- Viết bằng:
- Version 1: chuỗi
IF/ELSE IF - Version 2: dùng
EVALUATE TRUE
- Version 1: chuỗi
Bài 2 – Map file status sang message
Giả sử có:
F-STS PIC X(02)
Quy ước:
"00"– OK"10"– EOF (end of file)"90"– Lỗi khác
Yêu cầu:
- Viết
EVALUATE F-STSđể:- Hiển thị
"OK"nếu"00" - Hiển thị
"EOF"nếu"10" - Hiển thị
"FILE ERROR"cho giá trị khác
- Hiển thị
Bài 3 – Early exit pattern cho batch
Viết đoạn code mô phỏng pattern trong RZZBSQLN1:
- Sau khi
OPEN INPUT FILE, nếuF-STS NOT = "00"thì:- Gán
COMPLETION-CODE = 255 - Hiển thị message lỗi
GO TO STOP-PGM
- Gán
- Ở label
STOP-PGM., hiển thị"JOB END"cùngCOMPLETION-CODEvàSTOP RUN.
Bài 4 – Refactor IF lồng nhau sang EVALUATE TRUE
Cho code (giả sử):
IF SCORE >= 90
MOVE "A" TO GRADE
ELSE
IF SCORE >= 80
MOVE "B" TO GRADE
ELSE
IF SCORE >= 70
MOVE "C" TO GRADE
ELSE
MOVE "D" TO GRADE
END-IF
END-IF
END-IF.
Hãy viết lại bằng EVALUATE TRUE cho dễ đọc hơn.
Kết luận
Trong bài này, bạn đã:
- Hiểu rõ cách dùng
IF/ELSE/END-IFtrong COBOL - Nắm được
AND,OR,NOTđể kết hợp điều kiện - Thấy sức mạnh của
EVALUATEtrong việc thay thế chuỗiif/else ifdài - Nhìn được pattern điều kiện trong chương trình enterprise như
RZZBSQLN1.PCO– từ check file status đến map completion code → message
Kết hợp với bài 004 (toán tử & biểu thức), bạn đã đủ khả năng đọc hầu hết logic rẽ nhánh và tính toán trong một chương trình COBOL thực tế.
Ở các bài tiếp theo, chúng ta sẽ đi sâu vào:
- Vòng lặp & PERFORM (Loop & Control Flow) – cách tổ chức
MAIN-RTN,INIT-RTN,FINISH-RTNgiống batch program thật - FILE SECTION & FILE-CONTROL – chi tiết về đọc/ghi file text, pattern xử lý file trong enterprise mainframe.
