Matter AI | Code Reviewer Documentation home pagelight logodark logo
  • Contact
  • Github
  • Sign in
  • Sign in
  • Documentation
  • Blog
  • Discord
  • Github
  • Introduction
    • What is Matter AI?
    Getting Started
    • QuickStart
    Product
    • Security Analysis
    • Code Quality
    • Agentic Chat
    • RuleSets
    • Memories
    • Analytics
    • Command List
    • Configurations
    Patterns
    • Languages
      • Supported Languages
      • Python
      • Java
      • JavaScript
      • TypeScript
      • Node.js
      • React
      • Fastify
      • Next.js
      • Terraform
      • C#
      • C++
      • C
      • Go
      • Rust
      • Swift
      • React Native
      • Spring Boot
      • Kotlin
      • Flutter
      • Ruby
      • PHP
      • Scala
      • Perl
      • R
      • Dart
      • Elixir
      • Erlang
      • Haskell
      • Lua
      • Julia
      • Clojure
      • Groovy
      • Fortran
      • COBOL
      • Pascal
      • Assembly
      • Bash
      • PowerShell
      • SQL
      • PL/SQL
      • T-SQL
      • MATLAB
      • Objective-C
      • VBA
      • ABAP
      • Apex
      • Apache Camel
      • Crystal
      • D
      • Delphi
      • Elm
      • F#
      • Hack
      • Lisp
      • OCaml
      • Prolog
      • Racket
      • Scheme
      • Solidity
      • Verilog
      • VHDL
      • Zig
      • MongoDB
      • ClickHouse
      • MySQL
      • GraphQL
      • Redis
      • Cassandra
      • Elasticsearch
    • Security
    • Performance
    Integrations
    • Code Repositories
    • Team Messengers
    • Ticketing
    Enterprise
    • Enterprise Deployment Overview
    • Enterprise Configurations
    • Observability and Fallbacks
    • Create Your Own GitHub App
    • Self-Hosting Options
    • RBAC
    Patterns
    Languages

    COBOL

    COBOL (Common Business-Oriented Language) is a compiled English-like computer programming language designed for business use. It is an imperative, procedural language that was designed in 1959.

    COBOL, despite its longevity and importance in business applications, has several common anti-patterns that can lead to maintainability problems and bugs. Here are the most important anti-patterns to avoid when writing COBOL code.

    * Anti-pattern: Excessive use of GO TO
    PROCEDURE DIVISION.
       PERFORM INITIALIZE-ROUTINE.
       GO TO PROCESS-DATA.
    
    INITIALIZE-ROUTINE.
       MOVE ZEROS TO TOTAL-AMOUNT.
       MOVE SPACES TO ERROR-MESSAGE.
    
    PROCESS-DATA.
       READ INPUT-FILE
          AT END GO TO END-OF-FILE
       END-READ.
       
       IF AMOUNT-FIELD > 1000
          GO TO LARGE-AMOUNT-ROUTINE
       ELSE
          GO TO SMALL-AMOUNT-ROUTINE
       END-IF.
    
    LARGE-AMOUNT-ROUTINE.
       ADD AMOUNT-FIELD TO LARGE-TOTAL.
       GO TO PROCESS-DATA.
    
    SMALL-AMOUNT-ROUTINE.
       ADD AMOUNT-FIELD TO SMALL-TOTAL.
       GO TO PROCESS-DATA.
    
    END-OF-FILE.
       DISPLAY "Processing complete".
       STOP RUN.
    
    * Better approach: Structured programming
    PROCEDURE DIVISION.
       PERFORM INITIALIZE-ROUTINE.
       PERFORM PROCESS-DATA UNTIL END-OF-FILE.
       DISPLAY "Processing complete".
       STOP RUN.
    
    INITIALIZE-ROUTINE.
       MOVE ZEROS TO TOTAL-AMOUNT.
       MOVE SPACES TO ERROR-MESSAGE.
    
    PROCESS-DATA.
       READ INPUT-FILE
          AT END SET END-OF-FILE TO TRUE
          NOT AT END PERFORM PROCESS-RECORD
       END-READ.
    
    PROCESS-RECORD.
       IF AMOUNT-FIELD > 1000
          PERFORM LARGE-AMOUNT-ROUTINE
       ELSE
          PERFORM SMALL-AMOUNT-ROUTINE
       END-IF.
    
    LARGE-AMOUNT-ROUTINE.
       ADD AMOUNT-FIELD TO LARGE-TOTAL.
    
    SMALL-AMOUNT-ROUTINE.
       ADD AMOUNT-FIELD TO SMALL-TOTAL.

    Avoid excessive use of GO TO statements, which create spaghetti code that is difficult to understand and maintain. Use structured programming constructs like PERFORM, IF-ELSE, and EVALUATE instead.

    * Anti-pattern: Using magic numbers
    IF CUSTOMER-TYPE = 1
       COMPUTE DISCOUNT = TOTAL-AMOUNT * 0.10
    ELSE IF CUSTOMER-TYPE = 2
       COMPUTE DISCOUNT = TOTAL-AMOUNT * 0.15
    ELSE IF CUSTOMER-TYPE = 3
       COMPUTE DISCOUNT = TOTAL-AMOUNT * 0.20
    END-IF.
    
    * Better approach: Use named constants
    01 DISCOUNT-RATES.
       05 REGULAR-CUSTOMER-RATE     PIC 9V99 VALUE 0.10.
       05 PREFERRED-CUSTOMER-RATE   PIC 9V99 VALUE 0.15.
       05 PREMIUM-CUSTOMER-RATE     PIC 9V99 VALUE 0.20.
    
    01 CUSTOMER-TYPES.
       05 REGULAR-CUSTOMER          PIC 9 VALUE 1.
       05 PREFERRED-CUSTOMER        PIC 9 VALUE 2.
       05 PREMIUM-CUSTOMER          PIC 9 VALUE 3.
    
    * In PROCEDURE DIVISION
    IF CUSTOMER-TYPE = REGULAR-CUSTOMER
       COMPUTE DISCOUNT = TOTAL-AMOUNT * REGULAR-CUSTOMER-RATE
    ELSE IF CUSTOMER-TYPE = PREFERRED-CUSTOMER
       COMPUTE DISCOUNT = TOTAL-AMOUNT * PREFERRED-CUSTOMER-RATE
    ELSE IF CUSTOMER-TYPE = PREMIUM-CUSTOMER
       COMPUTE DISCOUNT = TOTAL-AMOUNT * PREMIUM-CUSTOMER-RATE
    END-IF.

    Avoid using magic numbers (hardcoded numeric literals) in your code. Use named constants to make your code more readable and maintainable.

    * Anti-pattern: Flat data structures
    01 CUSTOMER-RECORD.
       05 CUSTOMER-ID           PIC X(10).
       05 CUSTOMER-NAME         PIC X(30).
       05 CUSTOMER-ADDRESS-1    PIC X(30).
       05 CUSTOMER-ADDRESS-2    PIC X(30).
       05 CUSTOMER-CITY         PIC X(20).
       05 CUSTOMER-STATE        PIC X(2).
       05 CUSTOMER-ZIP          PIC X(10).
       05 CUSTOMER-PHONE        PIC X(15).
       05 CUSTOMER-EMAIL        PIC X(50).
    
    * Better approach: Use hierarchical data structures
    01 CUSTOMER-RECORD.
       05 CUSTOMER-ID           PIC X(10).
       05 CUSTOMER-NAME         PIC X(30).
       05 CUSTOMER-ADDRESS.
          10 STREET-ADDRESS-1   PIC X(30).
          10 STREET-ADDRESS-2   PIC X(30).
          10 CITY               PIC X(20).
          10 STATE              PIC X(2).
          10 ZIP-CODE           PIC X(10).
       05 CUSTOMER-CONTACT.
          10 PHONE-NUMBER       PIC X(15).
          10 EMAIL-ADDRESS      PIC X(50).

    Use hierarchical data structures to organize related data fields. This makes your code more readable and easier to maintain, especially when passing data between program modules.

    * Anti-pattern: Hardcoded file names
    SELECT CUSTOMER-FILE
       ASSIGN TO "C:\DATA\CUSTOMER.DAT"
       ORGANIZATION IS INDEXED
       ACCESS MODE IS DYNAMIC
       RECORD KEY IS CUSTOMER-ID.
    
    * Better approach: Use configuration files or environment variables
    SELECT CUSTOMER-FILE
       ASSIGN TO CUSTOMER-FILE-PATH
       ORGANIZATION IS INDEXED
       ACCESS MODE IS DYNAMIC
       RECORD KEY IS CUSTOMER-ID.
    
    * In WORKING-STORAGE SECTION
    01 CONFIGURATION-VARIABLES.
       05 CUSTOMER-FILE-PATH     PIC X(100).
    
    * In PROCEDURE DIVISION
    ACCEPT CUSTOMER-FILE-PATH FROM ENVIRONMENT "CUSTOMER_FILE_PATH".
    IF CUSTOMER-FILE-PATH = SPACES
       MOVE "C:\DATA\CUSTOMER.DAT" TO CUSTOMER-FILE-PATH
    END-IF.

    Avoid hardcoding file paths and names in your programs. Use configuration files or environment variables instead, which makes your code more flexible and portable across different environments.

    * Anti-pattern: Not validating input
    ACCEPT CUSTOMER-ID.
    READ CUSTOMER-FILE
       INVALID KEY DISPLAY "Customer not found"
    END-READ.
    
    * Better approach: Validate input data
    ACCEPT CUSTOMER-ID.
    
    * Validate input format
    IF CUSTOMER-ID IS NOT NUMERIC
       DISPLAY "Error: Customer ID must be numeric"
       EXIT PARAGRAPH
    END-IF.
    
    IF CUSTOMER-ID = ZEROS
       DISPLAY "Error: Customer ID cannot be zero"
       EXIT PARAGRAPH
    END-IF.
    
    * Proceed with valid input
    READ CUSTOMER-FILE
       INVALID KEY DISPLAY "Customer not found"
    END-READ.

    Always validate input data before processing it. This helps prevent runtime errors, data corruption, and potential security issues.

    * Anti-pattern: Using PERFORM THRU
    PROCEDURE DIVISION.
       PERFORM INITIALIZE-ROUTINE THRU INITIALIZE-EXIT.
       PERFORM PROCESS-DATA THRU PROCESS-EXIT.
       STOP RUN.
    
    INITIALIZE-ROUTINE.
       MOVE ZEROS TO TOTAL-AMOUNT.
       MOVE SPACES TO ERROR-MESSAGE.
    INITIALIZE-EXIT.
       EXIT.
    
    PROCESS-DATA.
       READ INPUT-FILE
          AT END GO TO PROCESS-EXIT
       END-READ.
       ADD AMOUNT-FIELD TO TOTAL-AMOUNT.
       GO TO PROCESS-DATA.
    PROCESS-EXIT.
       EXIT.
    
    * Better approach: Use structured PERFORM statements
    PROCEDURE DIVISION.
       PERFORM INITIALIZE-ROUTINE.
       PERFORM PROCESS-DATA UNTIL END-OF-FILE.
       STOP RUN.
    
    INITIALIZE-ROUTINE.
       MOVE ZEROS TO TOTAL-AMOUNT.
       MOVE SPACES TO ERROR-MESSAGE.
    
    PROCESS-DATA.
       READ INPUT-FILE
          AT END SET END-OF-FILE TO TRUE
          NOT AT END ADD AMOUNT-FIELD TO TOTAL-AMOUNT
       END-READ.

    Avoid using PERFORM THRU statements, which can lead to maintenance issues if paragraphs are reordered or renamed. Use structured PERFORM statements with well-defined paragraph boundaries instead.

    * Anti-pattern: Duplicating data definitions
    * In Program A
    01 CUSTOMER-RECORD.
       05 CUSTOMER-ID           PIC X(10).
       05 CUSTOMER-NAME         PIC X(30).
       05 CUSTOMER-ADDRESS.
          10 STREET-ADDRESS-1   PIC X(30).
          10 STREET-ADDRESS-2   PIC X(30).
          10 CITY               PIC X(20).
          10 STATE              PIC X(2).
          10 ZIP-CODE           PIC X(10).
    
    * In Program B (duplicated definition)
    01 CUSTOMER-RECORD.
       05 CUSTOMER-ID           PIC X(10).
       05 CUSTOMER-NAME         PIC X(30).
       05 CUSTOMER-ADDRESS.
          10 STREET-ADDRESS-1   PIC X(30).
          10 STREET-ADDRESS-2   PIC X(30).
          10 CITY               PIC X(20).
          10 STATE              PIC X(2).
          10 ZIP-CODE           PIC X(10).
    
    * Better approach: Use COPY books
    * In CUSTOMER.CPY file
    01 CUSTOMER-RECORD.
       05 CUSTOMER-ID           PIC X(10).
       05 CUSTOMER-NAME         PIC X(30).
       05 CUSTOMER-ADDRESS.
          10 STREET-ADDRESS-1   PIC X(30).
          10 STREET-ADDRESS-2   PIC X(30).
          10 CITY               PIC X(20).
          10 STATE              PIC X(2).
          10 ZIP-CODE           PIC X(10).
    
    * In Program A and Program B
    COPY CUSTOMER.

    Use COPY books to share common data definitions and code across multiple programs. This reduces duplication and ensures consistency.

    * Anti-pattern: Cryptic variable names
    01 X1              PIC 9(5)V99.
    01 X2              PIC 9(5)V99.
    01 X3              PIC 9(5)V99.
    
    COMPUTE X3 = X1 * X2.
    
    * Better approach: Descriptive variable names
    01 ITEM-PRICE      PIC 9(5)V99.
    01 QUANTITY        PIC 9(5)V99.
    01 TOTAL-COST      PIC 9(5)V99.
    
    COMPUTE TOTAL-COST = ITEM-PRICE * QUANTITY.

    Use meaningful and descriptive names for variables, paragraphs, and sections. This makes your code more readable and easier to understand and maintain.

    * Anti-pattern: Minimal error handling
    READ CUSTOMER-FILE
       INVALID KEY DISPLAY "Error reading file"
    END-READ.
    
    * Better approach: Comprehensive error handling
    READ CUSTOMER-FILE
       INVALID KEY
          MOVE "Y" TO ERROR-FOUND
          MOVE "Customer record not found" TO ERROR-MESSAGE
          PERFORM LOG-ERROR
          PERFORM DISPLAY-ERROR-TO-USER
    END-READ.
    
    IF ERROR-FOUND = "Y"
       PERFORM ERROR-RECOVERY-ROUTINE
    END-IF.

    Implement proper error handling with detailed error messages, logging, and recovery procedures. This helps diagnose and resolve issues more quickly.

    * Anti-pattern: Inappropriate use of REDEFINES
    01 MULTI-PURPOSE-FIELD.
       05 NUMERIC-VALUE         PIC 9(10).
       05 TEXT-VALUE REDEFINES NUMERIC-VALUE PIC X(10).
       05 DATE-VALUE REDEFINES NUMERIC-VALUE.
          10 YEAR               PIC 9(4).
          10 MONTH              PIC 9(2).
          10 DAY                PIC 9(2).
          10 FILLER             PIC 9(2).
    
    * Better approach: Use separate fields for different purposes
    01 CUSTOMER-DATA.
       05 CUSTOMER-ID           PIC 9(10).
       05 CUSTOMER-NAME         PIC X(30).
       05 REGISTRATION-DATE.
          10 REG-YEAR           PIC 9(4).
          10 REG-MONTH          PIC 9(2).
          10 REG-DAY            PIC 9(2).

    Avoid using REDEFINES to repurpose the same memory location for different data types. This can lead to data corruption and maintenance issues. Use separate fields for different purposes instead.

    * Anti-pattern: Unstructured code
    PROCEDURE DIVISION.
    MAIN-LOGIC.
       OPEN INPUT CUSTOMER-FILE.
       OPEN OUTPUT REPORT-FILE.
       READ CUSTOMER-FILE
          AT END MOVE "Y" TO END-OF-FILE-FLAG
       END-READ.
       PERFORM UNTIL END-OF-FILE-FLAG = "Y"
          MOVE CUSTOMER-NAME TO REPORT-NAME
          MOVE CUSTOMER-BALANCE TO REPORT-BALANCE
          WRITE REPORT-RECORD
          READ CUSTOMER-FILE
             AT END MOVE "Y" TO END-OF-FILE-FLAG
          END-READ
       END-PERFORM.
       CLOSE CUSTOMER-FILE.
       CLOSE REPORT-FILE.
       STOP RUN.
    
    * Better approach: Structured code with modular design
    PROCEDURE DIVISION.
    MAIN-LOGIC.
       PERFORM INITIALIZATION.
       PERFORM PROCESS-RECORDS UNTIL END-OF-FILE.
       PERFORM TERMINATION.
       STOP RUN.
    
    INITIALIZATION.
       OPEN INPUT CUSTOMER-FILE.
       OPEN OUTPUT REPORT-FILE.
       PERFORM READ-CUSTOMER-RECORD.
    
    PROCESS-RECORDS.
       PERFORM WRITE-REPORT-RECORD.
       PERFORM READ-CUSTOMER-RECORD.
    
    WRITE-REPORT-RECORD.
       MOVE CUSTOMER-NAME TO REPORT-NAME.
       MOVE CUSTOMER-BALANCE TO REPORT-BALANCE.
       WRITE REPORT-RECORD.
    
    READ-CUSTOMER-RECORD.
       READ CUSTOMER-FILE
          AT END MOVE "Y" TO END-OF-FILE-FLAG
       END-READ.
    
    TERMINATION.
       CLOSE CUSTOMER-FILE.
       CLOSE REPORT-FILE.

    Use structured programming principles with modular design. Break down your program into logical, self-contained modules with clear responsibilities.

    * Anti-pattern: Nested IF statements
    IF TRANSACTION-TYPE = "S"
       IF CUSTOMER-TYPE = "R"
          IF AMOUNT > 1000
             COMPUTE DISCOUNT = AMOUNT * 0.10
          ELSE
             COMPUTE DISCOUNT = AMOUNT * 0.05
          END-IF
       ELSE IF CUSTOMER-TYPE = "P"
          IF AMOUNT > 1000
             COMPUTE DISCOUNT = AMOUNT * 0.15
          ELSE
             COMPUTE DISCOUNT = AMOUNT * 0.10
          END-IF
       END-IF
    END-IF.
    
    * Better approach: Use EVALUATE
    EVALUATE TRUE
       WHEN TRANSACTION-TYPE = "S" AND CUSTOMER-TYPE = "R" AND AMOUNT > 1000
          COMPUTE DISCOUNT = AMOUNT * 0.10
       WHEN TRANSACTION-TYPE = "S" AND CUSTOMER-TYPE = "R"
          COMPUTE DISCOUNT = AMOUNT * 0.05
       WHEN TRANSACTION-TYPE = "S" AND CUSTOMER-TYPE = "P" AND AMOUNT > 1000
          COMPUTE DISCOUNT = AMOUNT * 0.15
       WHEN TRANSACTION-TYPE = "S" AND CUSTOMER-TYPE = "P"
          COMPUTE DISCOUNT = AMOUNT * 0.10
       WHEN OTHER
          MOVE ZEROS TO DISCOUNT
    END-EVALUATE.

    Use the EVALUATE statement for complex conditional logic instead of deeply nested IF statements. This makes your code more readable and easier to maintain.

    FortranPascal
    websitexgithublinkedin
    Powered by Mintlify
    Assistant
    Responses are generated using AI and may contain mistakes.