COBOL BY CONTENT Clause
Master parameter passing and data transfer with the BY CONTENT clause. Learn how to safely pass data to subprograms, protect original values, and implement robust modular programming techniques in your COBOL applications.
Overview
The BY CONTENT clause in COBOL specifies that parameters should be passed by value rather than by reference when calling subprograms. This means that a copy of the data is created and passed to the called program, ensuring that any modifications made within the subprogram do not affect the original data in the calling program.
BY CONTENT provides an important data protection mechanism in modular programming. It allows you to pass data to subprograms for processing or validation without risking unintended modifications to the original values. This is particularly valuable when working with critical data, implementing validation routines, or when you need to preserve the original state of data items.
Understanding BY CONTENT is essential for creating robust, maintainable COBOL applications with clear data flow and minimal side effects. It enables safer programming practices and helps prevent subtle bugs that can occur when subprograms unintentionally modify calling program data.
Basic Syntax and Usage
Simple BY CONTENT Call
The basic syntax for using BY CONTENT involves specifying it in the USING clause of a CALL statement. Here's the fundamental structure:
123456CALL 'VALIDATE' USING BY CONTENT WS-INPUT-DATA BY CONTENT WS-VALIDATION-RULES. CALL 'CALCULATE' USING BY CONTENT WS-AMOUNT BY CONTENT WS-TAX-RATE BY REFERENCE WS-RESULT.
In the first example, both parameters are passed BY CONTENT, meaning the validation subprogram receives copies and cannot modify the original data. The second example shows a mixed approach where input values are protected BY CONTENT while the result is passed BY REFERENCE for modification.
Passing Literals BY CONTENT
One unique advantage of BY CONTENT is the ability to pass literal values directly in the CALL statement:
1234567CALL 'LOGGER' USING BY CONTENT 'ERROR' BY CONTENT 'Invalid customer ID' BY CONTENT WS-CUSTOMER-ID. CALL 'FORMATTER' USING BY CONTENT 'CURRENCY' BY CONTENT 2 BY CONTENT WS-AMOUNT.
This capability allows you to pass configuration values, format specifications, or constant parameters directly without creating intermediate data items. This makes your code more concise and readable while maintaining the safety benefits of BY CONTENT.
Subprogram Parameter Declaration
In the called subprogram, parameters passed BY CONTENT are declared in the LINKAGE SECTION and accessed normally:
12345678LINKAGE SECTION. 01 LK-INPUT-VALUE PIC 9(6)V99. 01 LK-PROCESSING-FLAG PIC X(1). 01 LK-RESULT-CODE PIC 9(4). PROCEDURE DIVISION USING LK-INPUT-VALUE LK-PROCESSING-FLAG LK-RESULT-CODE.
From the subprogram's perspective, BY CONTENT parameters appear as regular data items in the LINKAGE SECTION. The subprogram can read and modify these values, but changes won't affect the original data in the calling program.
Advanced Parameter Passing Techniques
Mixed Parameter Passing Strategies
Effective modular programming often requires mixing BY CONTENT and BY REFERENCE based on the purpose of each parameter:
123456CALL 'PROCESS-ORDER' USING BY CONTENT WS-CUSTOMER-ID BY CONTENT WS-ORDER-DATE BY CONTENT WS-ORDER-ITEMS BY REFERENCE WS-ORDER-TOTAL BY REFERENCE WS-STATUS-CODE BY REFERENCE WS-ERROR-MESSAGE.
This example demonstrates a common pattern: input parameters (customer ID, order date, items) are passed BY CONTENT for protection, while output parameters (total, status, error message) are passed BY REFERENCE so the subprogram can return results to the caller.
Complex Data Structure Passing
BY CONTENT can be used with complex data structures, though this requires careful consideration of memory usage:
12345678910111201 WS-CUSTOMER-RECORD. 05 WS-CUST-ID PIC 9(8). 05 WS-CUST-NAME PIC X(50). 05 WS-CUST-ADDRESS. 10 WS-STREET PIC X(30). 10 WS-CITY PIC X(25). 10 WS-STATE PIC X(2). 10 WS-ZIP PIC 9(5). 05 WS-CREDIT-LIMIT PIC 9(7)V99. CALL 'VALIDATE-CUSTOMER' USING BY CONTENT WS-CUSTOMER-RECORD BY REFERENCE WS-VALIDATION-RESULT.
When passing large structures BY CONTENT, the entire structure is copied, which uses additional memory but provides complete protection of the original data. This is ideal for validation routines that need to examine all fields without risk of modification.
Table and Array Passing
Tables and arrays can be passed BY CONTENT, though this should be done judiciously due to memory considerations:
1234567801 WS-SALES-ARRAY. 05 WS-MONTHLY-SALES OCCURS 12 TIMES. 10 WS-MONTH PIC 9(2). 10 WS-AMOUNT PIC 9(7)V99. 10 WS-UNITS PIC 9(5). CALL 'ANALYZE-TRENDS' USING BY CONTENT WS-SALES-ARRAY BY REFERENCE WS-TREND-REPORT.
This approach allows the analysis subprogram to work with a complete copy of the sales data without any risk of accidentally modifying the original figures. The trend analysis can perform any calculations or transformations needed without affecting the source data.
Tutorial: Building a Secure Data Processing System
Let's create a comprehensive data processing system that demonstrates the effective use of BY CONTENT for data protection and secure processing. This tutorial will show you how to build a system that maintains data integrity while enabling flexible processing capabilities.
Step 1: Define the Main Data Structures
First, we'll establish the main data structures that will be processed by various subprograms:
12345678910111213WORKING-STORAGE SECTION. 01 WS-EMPLOYEE-RECORD. 05 WS-EMP-ID PIC 9(6). 05 WS-EMP-NAME PIC X(30). 05 WS-EMP-SALARY PIC 9(6)V99. 05 WS-EMP-DEPARTMENT PIC X(10). 05 WS-EMP-HIRE-DATE PIC 9(8). 01 WS-PROCESSING-RESULTS. 05 WS-VALIDATION-STATUS PIC X(1). 05 WS-TAX-AMOUNT PIC 9(6)V99. 05 WS-NET-SALARY PIC 9(6)V99. 05 WS-ERROR-COUNT PIC 9(3).
These structures represent the core data that needs protection (employee record) and the results that will be modified by processing (results). The employee record will be passed BY CONTENT to ensure it remains unchanged throughout processing.
Step 2: Implement Data Validation
Next, we'll create a validation routine that uses BY CONTENT to examine data without modifying it:
123456789101112MAIN-PROCESSING. PERFORM LOAD-EMPLOYEE-DATA CALL 'VALIDATE-EMP' USING BY CONTENT WS-EMPLOYEE-RECORD BY REFERENCE WS-VALIDATION-STATUS BY REFERENCE WS-ERROR-COUNT IF WS-VALIDATION-STATUS = 'Y' PERFORM PROCESS-PAYROLL ELSE PERFORM HANDLE-VALIDATION-ERRORS END-IF.
The validation call passes the employee record BY CONTENT, ensuring that any validation logic cannot accidentally corrupt the original data. The validation results are passed BY REFERENCE so the subprogram can return status information to the main program.
Step 3: Create the Validation Subprogram
Now we'll implement the validation subprogram that receives the protected data:
1234567891011121314151617IDENTIFICATION DIVISION. PROGRAM-ID. VALIDATE-EMP. DATA DIVISION. LINKAGE SECTION. 01 LK-EMPLOYEE-RECORD. 05 LK-EMP-ID PIC 9(6). 05 LK-EMP-NAME PIC X(30). 05 LK-EMP-SALARY PIC 9(6)V99. 05 LK-EMP-DEPARTMENT PIC X(10). 05 LK-EMP-HIRE-DATE PIC 9(8). 01 LK-VALIDATION-STATUS PIC X(1). 01 LK-ERROR-COUNT PIC 9(3). PROCEDURE DIVISION USING LK-EMPLOYEE-RECORD LK-VALIDATION-STATUS LK-ERROR-COUNT.
The validation subprogram receives a copy of the employee record and can perform any necessary checks without affecting the original data. It can modify the validation status and error count to communicate results back to the calling program.
Step 4: Implement Calculation Logic
Let's create calculation routines that use BY CONTENT for input protection:
123456789PROCESS-PAYROLL. CALL 'CALC-TAX' USING BY CONTENT WS-EMP-SALARY BY CONTENT WS-EMP-DEPARTMENT BY CONTENT 'FEDERAL' BY REFERENCE WS-TAX-AMOUNT CALL 'CALC-NET' USING BY CONTENT WS-EMP-SALARY BY CONTENT WS-TAX-AMOUNT BY REFERENCE WS-NET-SALARY.
These calculation calls protect the input values (salary, department, tax type) by passing them BY CONTENT. The calculations can use these values freely without risk of modifying the source data, while results are returned through BY REFERENCE parameters.
Step 5: Implement Audit and Logging
Finally, we'll create audit logging that uses BY CONTENT to safely record processing activities:
12345678910AUDIT-PROCESSING. CALL 'LOG-TRANSACTION' USING BY CONTENT 'PAYROLL' BY CONTENT WS-EMP-ID BY CONTENT WS-EMP-SALARY BY CONTENT WS-NET-SALARY BY CONTENT FUNCTION CURRENT-DATE CALL 'UPDATE-STATS' USING BY CONTENT WS-EMP-DEPARTMENT BY CONTENT WS-NET-SALARY BY CONTENT 1.
The audit logging passes all data BY CONTENT to ensure complete protection of the original values. This guarantees that logging activities cannot accidentally modify business data, maintaining data integrity throughout the audit process.
Performance and Memory Considerations
Memory Usage Optimization
While BY CONTENT provides data protection, it uses additional memory by creating copies of the passed data. Here are strategies for optimization:
1234567* For large structures, consider passing key fields only CALL 'VALIDATE-KEY' USING BY CONTENT WS-EMP-ID BY CONTENT WS-EMP-DEPARTMENT BY REFERENCE WS-VALIDATION-RESULT * Instead of passing the entire record * CALL 'VALIDATE-KEY' USING BY CONTENT WS-EMPLOYEE-RECORD
By passing only the necessary fields BY CONTENT, you can achieve data protection while minimizing memory usage. This approach is particularly effective for validation routines that only need to examine specific fields.
Performance Impact Analysis
The performance impact of BY CONTENT depends on the size and frequency of data copying:
123456789* Low impact - small data items CALL 'UTILITY' USING BY CONTENT WS-COUNTER BY CONTENT WS-FLAG * Medium impact - moderate structures CALL 'PROCESS' USING BY CONTENT WS-CUSTOMER-RECORD * High impact - large tables (use judiciously) CALL 'ANALYZE' USING BY CONTENT WS-LARGE-TABLE
Consider the trade-off between data protection and performance. For frequently called subprograms with large data structures, you might choose BY REFERENCE with careful programming practices to avoid unintended modifications.
Hybrid Approaches
You can implement hybrid approaches that balance protection and performance:
123456789* Pass read-only data BY CONTENT, working data BY REFERENCE CALL 'COMPLEX-CALC' USING BY CONTENT WS-CONFIGURATION BY CONTENT WS-INPUT-VALUES BY REFERENCE WS-WORK-AREA BY REFERENCE WS-RESULTS * Use local copies for protection when needed MOVE WS-CRITICAL-DATA TO WS-WORK-COPY CALL 'RISKY-PROCESS' USING BY REFERENCE WS-WORK-COPY
These hybrid approaches allow you to protect critical data while maintaining performance for working data that can be safely modified. Manual copying gives you complete control over what data is protected and when.
Practical Exercises
Exercise 1: Banking Transaction System
Create a banking system that uses BY CONTENT to protect account data:
123456* Design subprograms for: * - Account validation (protect account data) * - Interest calculation (protect principal) * - Transaction logging (protect all transaction data) * - Balance inquiry (protect account information) * Use BY CONTENT appropriately for data protection
Solution Approach: Pass account numbers, balances, and transaction amounts BY CONTENT to validation and calculation routines. Use BY REFERENCE only for output parameters like status codes and results. Implement comprehensive error handling for all subprogram calls.
Exercise 2: Inventory Pricing System
Build an inventory system with complex pricing rules using protected data:
123456* Create subprograms for: * - Product validation (protect product data) * - Price calculation (protect base prices) * - Discount application (protect customer data) * - Tax calculation (protect all input values) * Mix BY CONTENT and BY REFERENCE appropriately
Solution Approach: Use BY CONTENT for all input data that should remain unchanged (product info, customer data, pricing rules). Pass calculation results BY REFERENCE. Implement a clear separation between input protection and output generation.
Exercise 3: Report Generation Framework
Design a flexible reporting system that protects source data:
123456* Implement subprograms for: * - Data formatting (protect raw data) * - Summary calculations (protect detail records) * - Report layout (protect formatting templates) * - Output generation (protect all source information) * Optimize for both protection and performance
Solution Approach: Pass report data BY CONTENT to formatting routines to ensure source data integrity. Use BY REFERENCE for generated output and status information. Consider memory usage for large datasets and implement efficient data handling strategies.
Best Practices and Guidelines
When to Use BY CONTENT
- When passing data that should not be modified by the subprogram
- For validation routines that examine but don't change data
- When passing constants or configuration values
- For calculation inputs that must remain unchanged
- When calling external or third-party subprograms
- For audit and logging functions that record data
Design Patterns
- Use BY CONTENT for inputs, BY REFERENCE for outputs
- Pass literals BY CONTENT for configuration parameters
- Group related read-only parameters for BY CONTENT passing
- Consider the size vs. protection trade-off for large structures
- Document parameter passing intentions clearly
- Implement consistent patterns across your application
Error Handling and Debugging
- Test subprograms with both BY CONTENT and BY REFERENCE parameters
- Verify that BY CONTENT parameters provide expected protection
- Monitor memory usage when passing large structures BY CONTENT
- Document any performance implications of parameter passing choices
- Use consistent error handling patterns for all subprogram calls
- Test boundary conditions and error scenarios thoroughly
Maintenance and Evolution
As your application evolves, regularly review parameter passing strategies. Consider whether data that was initially passed BY CONTENT still requires protection, and whether performance considerations have changed. Document the rationale for parameter passing choices to help future maintainers understand the design decisions.
Maintain consistency in parameter passing patterns across your application. Establish coding standards that specify when to use BY CONTENT versus BY REFERENCE, and ensure all team members understand the implications of each approach.
Interactive Quiz
Test Your BY CONTENT Knowledge
Question 1:
What happens when a parameter is passed BY CONTENT to a subprogram?
Question 2:
Which type of values can be passed using BY CONTENT but not BY REFERENCE?
Question 3:
What is the main advantage of using BY CONTENT for parameter passing?