The CALL statement represents one of the most sophisticated and powerful features in COBOL, enabling comprehensive program linkage, modular programming architecture, and inter-program communication that forms the backbone of enterprise application design. Far more than just a simple program invocation mechanism, the CALL statement facilitates the creation of complex, maintainable software systems by allowing programs to be broken down into specialized, reusable components that can be developed, tested, and maintained independently while working together as cohesive application suites. This capability is fundamental to modern COBOL development practices and is essential for building scalable, enterprise-grade applications that can adapt to changing business requirements while maintaining reliability and performance.
Understanding the CALL statement goes beyond basic syntax to encompass advanced concepts such as dynamic program loading, sophisticated parameter passing mechanisms, error handling strategies, memory management, and integration patterns that enable COBOL applications to interface seamlessly with contemporary technology stacks. The CALL statement serves as the foundation for creating service-oriented architectures, implementing business logic separation, and establishing communication protocols between different application components, making it an indispensable tool for enterprise software architects and developers.
The CALL statement implements a sophisticated program linkage mechanism that enables one COBOL program (the calling program) to transfer control to another program (the called program or subprogram) while maintaining the ability to pass data between them and return control to the original program upon completion. This mechanism goes far beyond simple program execution to provide a comprehensive framework for building modular applications where complex business logic can be decomposed into manageable, specialized components that work together to accomplish larger objectives.
At its core, the CALL statement manages program context switching, parameter marshaling, memory allocation, and execution environment setup in a way that preserves data integrity and program state across program boundaries. This involves sophisticated runtime operations including stack management, register preservation, memory mapping, and execution context switching that occur transparently to the application programmer but are crucial for reliable program operation.
The architectural implications of the CALL statement extend throughout the entire application design process. It enables the implementation of layered architectures where presentation logic, business logic, and data access logic can be separated into distinct programs. It facilitates the creation of utility libraries that can be shared across multiple applications. It supports the development of plugin architectures where functionality can be added or modified without changing core application code. These capabilities make the CALL statement essential for creating maintainable, scalable enterprise applications.
The CALL statement is fundamental to implementing modular programming principles in COBOL applications. Modular programming involves breaking down complex applications into smaller, focused programs that each handle specific aspects of the overall functionality. This approach provides numerous benefits including improved maintainability, easier testing, better code reusability, clearer separation of concerns, and enhanced team productivity through parallel development of different modules.
In enterprise environments, modular programming enabled by CALL statements allows organizations to create standardized libraries of business logic that can be shared across multiple applications. Common functions such as date calculations, validation routines, data formatting, error handling, and business rule processing can be centralized in called programs, ensuring consistency across the organization and reducing duplication of code and effort.
The modular approach also supports agile development practices by enabling teams to work on different components simultaneously without interfering with each other. Changes to specific business logic can be isolated to individual programs, reducing the risk of unintended side effects and making application maintenance more predictable and manageable.
The performance characteristics of CALL statements are crucial considerations in enterprise application design. While CALL statements provide tremendous flexibility and architectural benefits, they do introduce overhead related to program loading, context switching, parameter marshaling, and stack management. Understanding these performance implications enables developers to make informed decisions about when to use CALL statements versus alternative approaches such as PERFORM statements or inline processing.
Static CALL statements (where the program name is specified as a literal) generally provide better performance than dynamic CALL statements (where the program name is determined at runtime) because the called program can be loaded and linked at compile time. However, dynamic CALL statements offer greater flexibility for building configurable applications where program behavior can be modified without recompiling the calling program.
Optimization strategies for CALL statement performance include minimizing the frequency of calls in tight loops, using appropriate parameter passing methods to avoid unnecessary data copying, caching frequently called programs in memory, and structuring program hierarchies to minimize call depth and complexity. These optimizations can significantly impact application performance in high-volume processing scenarios.
In modern enterprise environments, CALL statements serve as building blocks for service-oriented architectures and integration patterns that connect COBOL applications with contemporary technology stacks. Called programs can act as service interfaces, data transformation engines, protocol adapters, and integration points that enable COBOL applications to participate in distributed computing environments while maintaining their core business logic and data processing capabilities.
The CALL mechanism facilitates the implementation of adapter patterns where legacy COBOL business logic can be wrapped in modern interfaces, enabling integration with web services, message queuing systems, database APIs, and cloud computing platforms. This capability is essential for organizations that need to modernize their technology infrastructure while preserving investments in proven business logic and maintaining operational continuity.
Additionally, CALL statements enable the creation of plugin architectures where functionality can be extended through the addition of new called programs without modifying existing application code. This extensibility is crucial for applications that need to adapt to changing business requirements, integrate with new systems, or support customization for different organizational units or customer requirements.
The parameter passing capabilities of CALL statements represent one of the most sophisticated aspects of COBOL's inter-program communication model. The three primary parameter passing methods (BY REFERENCE, BY CONTENT, BY VALUE) each serve specific purposes in data sharing and protection strategies, enabling developers to implement precise control over how data flows between programs and what modifications are permitted.
BY REFERENCE parameter passing enables efficient sharing of large data structures without the overhead of copying data, while also allowing called programs to modify the original data in the calling program. BY CONTENT provides protection against unintended modifications by passing copies of data, ensuring that the original data remains unchanged. BY VALUE is optimized for passing simple values and literals, providing the best performance for scalar data types.
Understanding these parameter passing mechanisms is crucial for implementing effective data flow architectures, ensuring data integrity across program boundaries, and optimizing application performance. The choice of parameter passing method can significantly impact both the functionality and performance characteristics of inter-program communication, making it an important design consideration in enterprise application development.
The CALL statement allows:
1234567CALL { "program-name" | identifier-1 } [USING { { [BY REFERENCE] } { identifier-2 | file-name-1 } | { BY CONTENT } { identifier-3 | literal-1 } | { BY VALUE } { identifier-4 | literal-2 } }...] [ON EXCEPTION imperative-statement-1] [NOT ON EXCEPTION imperative-statement-2] [END-CALL]
1234567891011121314151617181920212223242526272829303132333435363738394041IDENTIFICATION DIVISION. PROGRAM-ID. MAIN-PROGRAM. DATA DIVISION. WORKING-STORAGE SECTION. 01 CUSTOMER-ID PIC 9(8) VALUE 12345678. 01 CUSTOMER-NAME PIC X(30). 01 ACCOUNT-BALANCE PIC S9(8)V99. 01 RETURN-CODE PIC 9(2). PROCEDURE DIVISION. MAIN-PARA. DISPLAY "Main program starting...". *> Simple call without parameters CALL "INITIALIZE" ON EXCEPTION DISPLAY "Failed to call INITIALIZE program" STOP RUN END-CALL. *> Call with parameters CALL "GET-CUSTOMER" USING CUSTOMER-ID CUSTOMER-NAME ACCOUNT-BALANCE ON EXCEPTION DISPLAY "Failed to call GET-CUSTOMER" MOVE 99 TO RETURN-CODE NOT ON EXCEPTION DISPLAY "Customer retrieved successfully" PERFORM DISPLAY-CUSTOMER-INFO END-CALL. DISPLAY "Main program ending...". STOP RUN. DISPLAY-CUSTOMER-INFO. DISPLAY "Customer Information:". DISPLAY "ID: " CUSTOMER-ID. DISPLAY "Name: " CUSTOMER-NAME. DISPLAY "Balance: $" ACCOUNT-BALANCE.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960IDENTIFICATION DIVISION. PROGRAM-ID. GET-CUSTOMER. DATA DIVISION. LINKAGE SECTION. 01 LK-CUSTOMER-ID PIC 9(8). 01 LK-CUSTOMER-NAME PIC X(30). 01 LK-ACCOUNT-BALANCE PIC S9(8)V99. WORKING-STORAGE SECTION. 01 CUSTOMER-TABLE. 05 CUSTOMER-ENTRY OCCURS 5 TIMES. 10 CUST-ID PIC 9(8). 10 CUST-NAME PIC X(30). 10 CUST-BAL PIC S9(8)V99. 01 INDEX-VAR PIC 9(2). 01 FOUND-FLAG PIC X VALUE 'N'. PROCEDURE DIVISION USING LK-CUSTOMER-ID LK-CUSTOMER-NAME LK-ACCOUNT-BALANCE. MAIN-PARA. PERFORM INITIALIZE-CUSTOMER-DATA. PERFORM SEARCH-CUSTOMER. IF FOUND-FLAG = 'Y' DISPLAY "Customer found in subprogram" ELSE DISPLAY "Customer not found" MOVE "UNKNOWN CUSTOMER" TO LK-CUSTOMER-NAME MOVE ZERO TO LK-ACCOUNT-BALANCE END-IF. GOBACK. INITIALIZE-CUSTOMER-DATA. *> Initialize sample customer data MOVE 12345678 TO CUST-ID(1). MOVE "John Smith" TO CUST-NAME(1). MOVE 1500.75 TO CUST-BAL(1). MOVE 23456789 TO CUST-ID(2). MOVE "Jane Johnson" TO CUST-NAME(2). MOVE 2750.50 TO CUST-BAL(2). MOVE 34567890 TO CUST-ID(3). MOVE "Bob Wilson" TO CUST-NAME(3). MOVE -150.25 TO CUST-BAL(3). SEARCH-CUSTOMER. PERFORM VARYING INDEX-VAR FROM 1 BY 1 UNTIL INDEX-VAR > 5 IF CUST-ID(INDEX-VAR) = LK-CUSTOMER-ID MOVE CUST-NAME(INDEX-VAR) TO LK-CUSTOMER-NAME MOVE CUST-BAL(INDEX-VAR) TO LK-ACCOUNT-BALANCE MOVE 'Y' TO FOUND-FLAG EXIT PERFORM END-IF END-PERFORM.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051IDENTIFICATION DIVISION. PROGRAM-ID. REFERENCE-DEMO. DATA DIVISION. WORKING-STORAGE SECTION. 01 INPUT-NUMBER PIC 9(5) VALUE 100. 01 OUTPUT-NUMBER PIC 9(5). 01 COUNTER PIC 9(3) VALUE 0. PROCEDURE DIVISION. MAIN-PARA. DISPLAY "Before CALL - Input: " INPUT-NUMBER. DISPLAY "Before CALL - Counter: " COUNTER. *> BY REFERENCE allows the called program to modify values CALL "MODIFY-VALUES" USING BY REFERENCE INPUT-NUMBER BY REFERENCE COUNTER BY REFERENCE OUTPUT-NUMBER. DISPLAY "After CALL - Input: " INPUT-NUMBER. DISPLAY "After CALL - Counter: " COUNTER. DISPLAY "After CALL - Output: " OUTPUT-NUMBER. STOP RUN. *> Called subprogram IDENTIFICATION DIVISION. PROGRAM-ID. MODIFY-VALUES. DATA DIVISION. LINKAGE SECTION. 01 LK-INPUT PIC 9(5). 01 LK-COUNTER PIC 9(3). 01 LK-OUTPUT PIC 9(5). PROCEDURE DIVISION USING LK-INPUT LK-COUNTER LK-OUTPUT. MAIN-PARA. *> Modify input parameter MULTIPLY LK-INPUT BY 2 GIVING LK-INPUT. *> Increment counter ADD 1 TO LK-COUNTER. *> Set output value COMPUTE LK-OUTPUT = LK-INPUT + LK-COUNTER. DISPLAY "In subprogram - Modified input: " LK-INPUT. DISPLAY "In subprogram - Counter: " LK-COUNTER. DISPLAY "In subprogram - Output: " LK-OUTPUT. GOBACK.
123456789101112131415161718192021222324252627282930313233343536373839404142IDENTIFICATION DIVISION. PROGRAM-ID. CONTENT-DEMO. DATA DIVISION. WORKING-STORAGE SECTION. 01 ORIGINAL-VALUE PIC 9(5) VALUE 500. 01 CALCULATION-RESULT PIC 9(8). PROCEDURE DIVISION. MAIN-PARA. DISPLAY "Before CALL - Original: " ORIGINAL-VALUE. *> BY CONTENT passes a copy - original cannot be modified CALL "CALCULATE" USING BY CONTENT ORIGINAL-VALUE BY REFERENCE CALCULATION-RESULT. DISPLAY "After CALL - Original: " ORIGINAL-VALUE. DISPLAY "After CALL - Result: " CALCULATION-RESULT. STOP RUN. *> Called subprogram IDENTIFICATION DIVISION. PROGRAM-ID. CALCULATE. DATA DIVISION. LINKAGE SECTION. 01 LK-INPUT-VALUE PIC 9(5). 01 LK-RESULT PIC 9(8). PROCEDURE DIVISION USING LK-INPUT-VALUE LK-RESULT. MAIN-PARA. DISPLAY "In subprogram - Received: " LK-INPUT-VALUE. *> Try to modify input (won't affect original) MULTIPLY LK-INPUT-VALUE BY 10 GIVING LK-INPUT-VALUE. DISPLAY "In subprogram - Modified: " LK-INPUT-VALUE. *> Calculate result COMPUTE LK-RESULT = LK-INPUT-VALUE * LK-INPUT-VALUE. GOBACK.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364IDENTIFICATION DIVISION. PROGRAM-ID. VALUE-DEMO. DATA DIVISION. WORKING-STORAGE SECTION. 01 CALCULATION-TYPE PIC 9 VALUE 1. 01 BASE-VALUE PIC 9(5) VALUE 100. 01 RESULT PIC 9(8). PROCEDURE DIVISION. MAIN-PARA. *> BY VALUE for passing literals and simple values CALL "MATHEMATICAL-OPERATION" USING BY VALUE CALCULATION-TYPE BY VALUE 25 BY VALUE BASE-VALUE BY REFERENCE RESULT. DISPLAY "Result of operation: " RESULT. *> Call with different literal values CALL "MATHEMATICAL-OPERATION" USING BY VALUE 2 BY VALUE 50 BY VALUE BASE-VALUE BY REFERENCE RESULT. DISPLAY "Result of second operation: " RESULT. STOP RUN. *> Called subprogram IDENTIFICATION DIVISION. PROGRAM-ID. MATHEMATICAL-OPERATION. DATA DIVISION. LINKAGE SECTION. 01 LK-OPERATION-TYPE PIC 9. 01 LK-MULTIPLIER PIC 9(3). 01 LK-BASE PIC 9(5). 01 LK-RESULT PIC 9(8). PROCEDURE DIVISION USING LK-OPERATION-TYPE LK-MULTIPLIER LK-BASE LK-RESULT. MAIN-PARA. DISPLAY "Operation: " LK-OPERATION-TYPE. DISPLAY "Multiplier: " LK-MULTIPLIER. DISPLAY "Base: " LK-BASE. EVALUATE LK-OPERATION-TYPE WHEN 1 MULTIPLY LK-BASE BY LK-MULTIPLIER GIVING LK-RESULT WHEN 2 COMPUTE LK-RESULT = LK-BASE + LK-MULTIPLIER WHEN 3 COMPUTE LK-RESULT = LK-BASE - LK-MULTIPLIER WHEN OTHER MOVE ZERO TO LK-RESULT END-EVALUATE. GOBACK.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960IDENTIFICATION DIVISION. PROGRAM-ID. DYNAMIC-CALL-DEMO. DATA DIVISION. WORKING-STORAGE SECTION. 01 PROGRAM-NAME PIC X(20). 01 USER-CHOICE PIC 9. 01 INPUT-DATA PIC X(50). 01 OUTPUT-DATA PIC X(100). 01 RETURN-CODE PIC 9(2). PROCEDURE DIVISION. MAIN-PARA. PERFORM DISPLAY-MENU. PERFORM GET-USER-CHOICE. PERFORM CALL-SELECTED-PROGRAM. STOP RUN. DISPLAY-MENU. DISPLAY "Dynamic Program Menu:". DISPLAY "1. Data Validation". DISPLAY "2. Data Formatting". DISPLAY "3. Data Calculation". DISPLAY "4. Data Reporting". DISPLAY "Enter choice (1-4): " WITH NO ADVANCING. GET-USER-CHOICE. ACCEPT USER-CHOICE. EVALUATE USER-CHOICE WHEN 1 MOVE "VALIDATE-DATA" TO PROGRAM-NAME WHEN 2 MOVE "FORMAT-DATA" TO PROGRAM-NAME WHEN 3 MOVE "CALC-DATA" TO PROGRAM-NAME WHEN 4 MOVE "REPORT-DATA" TO PROGRAM-NAME WHEN OTHER DISPLAY "Invalid choice" STOP RUN END-EVALUATE. CALL-SELECTED-PROGRAM. MOVE "Sample input data" TO INPUT-DATA. DISPLAY "Calling program: " PROGRAM-NAME. CALL PROGRAM-NAME USING INPUT-DATA OUTPUT-DATA ON EXCEPTION DISPLAY "Error: Program " PROGRAM-NAME " not found" DISPLAY "or failed to load" MOVE 99 TO RETURN-CODE NOT ON EXCEPTION DISPLAY "Program executed successfully" DISPLAY "Output: " OUTPUT-DATA MOVE 0 TO RETURN-CODE END-CALL. DISPLAY "Return code: " RETURN-CODE.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061IDENTIFICATION DIVISION. PROGRAM-ID. CALL-ERROR-HANDLING. DATA DIVISION. WORKING-STORAGE SECTION. 01 PROGRAM-LIST. 05 PROG-ENTRY OCCURS 5 TIMES. 10 PROG-NAME PIC X(15). 10 PROG-STATUS PIC X(10). 01 INDEX-VAR PIC 9(2). 01 SUCCESS-COUNT PIC 9(2) VALUE 0. 01 FAILURE-COUNT PIC 9(2) VALUE 0. 01 TEST-DATA PIC X(20) VALUE "TEST DATA". 01 RESULT-DATA PIC X(50). PROCEDURE DIVISION. MAIN-PARA. PERFORM INITIALIZE-PROGRAM-LIST. PERFORM TEST-ALL-PROGRAMS. PERFORM DISPLAY-RESULTS. STOP RUN. INITIALIZE-PROGRAM-LIST. MOVE "UTILITY1" TO PROG-NAME(1). MOVE "UTILITY2" TO PROG-NAME(2). MOVE "UTILITY3" TO PROG-NAME(3). MOVE "NONEXISTENT" TO PROG-NAME(4). MOVE "UTILITY5" TO PROG-NAME(5). TEST-ALL-PROGRAMS. PERFORM VARYING INDEX-VAR FROM 1 BY 1 UNTIL INDEX-VAR > 5 PERFORM TEST-SINGLE-PROGRAM END-PERFORM. TEST-SINGLE-PROGRAM. DISPLAY "Testing program: " PROG-NAME(INDEX-VAR). CALL PROG-NAME(INDEX-VAR) USING TEST-DATA RESULT-DATA ON EXCEPTION MOVE "FAILED" TO PROG-STATUS(INDEX-VAR) ADD 1 TO FAILURE-COUNT DISPLAY " Status: FAILED - Program not found or error" NOT ON EXCEPTION MOVE "SUCCESS" TO PROG-STATUS(INDEX-VAR) ADD 1 TO SUCCESS-COUNT DISPLAY " Status: SUCCESS - " RESULT-DATA END-CALL. DISPLAY-RESULTS. DISPLAY " ". DISPLAY "Program Test Summary:". DISPLAY "====================". DISPLAY "Successful calls: " SUCCESS-COUNT. DISPLAY "Failed calls: " FAILURE-COUNT. DISPLAY " ". DISPLAY "Detailed Results:". PERFORM VARYING INDEX-VAR FROM 1 BY 1 UNTIL INDEX-VAR > 5 DISPLAY PROG-NAME(INDEX-VAR) " - " PROG-STATUS(INDEX-VAR) END-PERFORM.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475IDENTIFICATION DIVISION. PROGRAM-ID. NESTED-CALLS-DEMO. DATA DIVISION. WORKING-STORAGE SECTION. 01 LEVEL-INDICATOR PIC 9 VALUE 1. 01 PROCESSING-DATA PIC X(100). 01 FINAL-RESULT PIC X(200). PROCEDURE DIVISION. MAIN-PARA. MOVE "Initial data for processing" TO PROCESSING-DATA. DISPLAY "Level " LEVEL-INDICATOR " - Main program starting". CALL "LEVEL-TWO" USING LEVEL-INDICATOR PROCESSING-DATA FINAL-RESULT. DISPLAY "Level " LEVEL-INDICATOR " - Main program ending". DISPLAY "Final result: " FINAL-RESULT. STOP RUN. *> Second level program IDENTIFICATION DIVISION. PROGRAM-ID. LEVEL-TWO. DATA DIVISION. LINKAGE SECTION. 01 LK-LEVEL PIC 9. 01 LK-DATA PIC X(100). 01 LK-RESULT PIC X(200). WORKING-STORAGE SECTION. 01 NEXT-LEVEL PIC 9. 01 INTERMEDIATE-RESULT PIC X(150). PROCEDURE DIVISION USING LK-LEVEL LK-DATA LK-RESULT. MAIN-PARA. ADD 1 TO LK-LEVEL GIVING NEXT-LEVEL. DISPLAY "Level " LK-LEVEL " - Processing data: " LK-DATA. STRING "Level-2 processed: " LK-DATA DELIMITED BY SIZE INTO INTERMEDIATE-RESULT. CALL "LEVEL-THREE" USING NEXT-LEVEL INTERMEDIATE-RESULT LK-RESULT. DISPLAY "Level " LK-LEVEL " - Returning to caller". GOBACK. *> Third level program IDENTIFICATION DIVISION. PROGRAM-ID. LEVEL-THREE. DATA DIVISION. LINKAGE SECTION. 01 LK-LEVEL PIC 9. 01 LK-DATA PIC X(150). 01 LK-RESULT PIC X(200). PROCEDURE DIVISION USING LK-LEVEL LK-DATA LK-RESULT. MAIN-PARA. DISPLAY "Level " LK-LEVEL " - Final processing: " LK-DATA. STRING "Level-3 final: " LK-DATA DELIMITED BY SIZE INTO LK-RESULT. DISPLAY "Level " LK-LEVEL " - Processing complete". GOBACK.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051IDENTIFICATION DIVISION. PROGRAM-ID. RECURSIVE-DEMO. DATA DIVISION. WORKING-STORAGE SECTION. 01 INPUT-NUMBER PIC 9(2) VALUE 5. 01 FACTORIAL-RESULT PIC 9(10). PROCEDURE DIVISION. MAIN-PARA. DISPLAY "Calculating factorial of " INPUT-NUMBER. CALL "FACTORIAL" USING INPUT-NUMBER FACTORIAL-RESULT. DISPLAY "Factorial of " INPUT-NUMBER " is " FACTORIAL-RESULT. STOP RUN. *> Recursive factorial program IDENTIFICATION DIVISION. PROGRAM-ID. FACTORIAL. OPTIONS. RECURSIVE. DATA DIVISION. LINKAGE SECTION. 01 LK-NUMBER PIC 9(2). 01 LK-RESULT PIC 9(10). WORKING-STORAGE SECTION. 01 TEMP-NUMBER PIC 9(2). 01 TEMP-RESULT PIC 9(10). PROCEDURE DIVISION USING LK-NUMBER LK-RESULT. MAIN-PARA. DISPLAY "Calculating factorial for: " LK-NUMBER. IF LK-NUMBER <= 1 MOVE 1 TO LK-RESULT DISPLAY "Base case reached: " LK-RESULT ELSE SUBTRACT 1 FROM LK-NUMBER GIVING TEMP-NUMBER CALL "FACTORIAL" USING TEMP-NUMBER TEMP-RESULT MULTIPLY LK-NUMBER BY TEMP-RESULT GIVING LK-RESULT DISPLAY "Calculated: " LK-NUMBER " * " TEMP-RESULT " = " LK-RESULT END-IF. GOBACK.
Passing Method | Data Transfer | Modification | Use Case |
---|---|---|---|
BY REFERENCE | Address passed | Original can be modified | Input/Output parameters |
BY CONTENT | Copy of data | Original protected | Input-only parameters |
BY VALUE | Value copied | Cannot be modified | Literals and constants |
12345678910111213141516*> Use CALL for: *> 1. Separate compiled programs *> 2. Reusable utility functions *> 3. Modular architecture *> 4. Dynamic loading *> 5. Different programming languages CALL "UTILITY-PROGRAM" USING PARAMETER-LIST. *> Use PERFORM for: *> 1. Internal paragraphs/sections *> 2. Same program structure *> 3. Better performance *> 4. Simple code organization PERFORM CALCULATE-TOTALS.