Using ISPF to Refactor and Mass-Update Code: Safe Change Patterns
Refactoring and mass-updating code are common tasks in mainframe development. Whether you're renaming variables, updating dataset names, modernizing code structures, or applying consistent formatting, making these changes safely requires understanding proper techniques and following established patterns. This tutorial covers safe change patterns, verification techniques, and best practices for refactoring and mass-updating code using ISPF editor.
The key to safe refactoring is understanding what will change before making changes, verifying each change is correct, and testing incrementally. ISPF provides powerful tools for finding, changing, and verifying code modifications, but using these tools correctly is essential to avoid introducing errors. This tutorial teaches you how to leverage ISPF features effectively while maintaining code quality and avoiding common pitfalls.
Understanding Refactoring and Mass Updates
Refactoring means restructuring code without changing its functionality, while mass updates involve making the same change across multiple locations. Both require careful planning and execution to avoid breaking working code.
What is Refactoring?
Refactoring is the process of improving code structure, readability, or maintainability without changing what the code does. Common refactoring tasks include:
Renaming: Changing variable names, procedure names, or dataset names to be more descriptive or follow naming conventions
Restructuring: Reorganizing code sections, moving procedures, or reorganizing data structures
Formatting: Applying consistent formatting, indentation, or alignment across code
Simplifying: Breaking complex logic into smaller, more manageable pieces
Modernizing: Updating code to use modern language features or follow current standards
The goal of refactoring is to make code easier to understand, maintain, and extend while preserving its behavior. This means refactoring must be done carefully to avoid introducing bugs.
What are Mass Updates?
Mass updates involve making the same change in multiple places. Common mass update scenarios include:
Dataset Name Changes: Updating dataset names across multiple JCL files when datasets are renamed or moved
Variable Renaming: Renaming a variable or data item that appears in many places
Parameter Updates: Changing parameter values or options across multiple files
Formatting Standardization: Applying consistent formatting rules across multiple source files
Comment Updates: Updating copyright notices, version information, or standard comments
Mass updates can affect many files and many locations within each file. Making these changes safely requires systematic approaches and careful verification.
Why Safety Matters
Unsafe refactoring or mass updates can introduce serious problems:
Breaking Functionality: Incorrect changes can cause programs to fail at compile time or runtime
Partial Updates: Missing some occurrences creates inconsistencies that are hard to find and fix
False Matches: Changing text that looks similar but isn't what you intended can break unrelated code
Context Loss: Changes that are correct in isolation may be wrong in context
Cascading Failures: One incorrect change can cause multiple related failures
Following safe change patterns helps avoid these problems and ensures refactoring improves code quality rather than introducing issues.
Safe Change Pattern: The FIND-FIRST Principle
The most important safe change pattern is the FIND-FIRST principle: always FIND and verify before making changes. This simple rule prevents most refactoring errors.
Step 1: FIND All Occurrences
Before making any change, use FIND to locate all occurrences of what you want to change. This serves multiple purposes:
Discovery: You may find occurrences you didn't know about
Verification: You can see each occurrence in context to verify it should be changed
Planning: You can plan the order of changes and identify any special cases
Counting: You know how many changes you'll make, helping estimate effort
Use FIND with appropriate options. For example, if you're renaming a variable, use FIND with word boundaries or specific patterns to avoid finding the variable name as part of other names. Case sensitivity may matter depending on the language.
Example: To find all occurrences of variable WS-COUNTER in COBOL:
text
1
Command ===> FIND WS-COUNTER
Use FIND NEXT to step through each occurrence, examining the context of each one.
Step 2: Verify Context
For each occurrence found, verify it's actually what you want to change. Consider:
Is it the right item? A variable name might appear as part of a larger name (e.g., WS-COUNTER vs WS-COUNTER-TOTAL)
Is it in the right scope? A local variable and a global variable with the same name are different things
Is it the right type? A data name and a procedure name might have the same spelling but are different
Should it be changed? Some occurrences might be comments, documentation, or should remain unchanged for other reasons
Use split-screen or scroll to see more context around each occurrence. Understanding the context helps ensure changes are correct.
Step 3: Plan the Change
Based on your FIND results, plan how you'll make the changes:
Order of Changes: Some changes may need to be made in a specific order (e.g., define before use)
Grouping: Group related changes together
Special Cases: Identify any occurrences that need special handling
Testing Points: Plan where you'll test after making changes
Document your plan, especially for complex refactoring. This helps ensure nothing is missed and provides a record of what was changed.
Step 4: Make Changes Incrementally
Make changes incrementally rather than all at once:
Small Batches: Change a small number of occurrences, then verify
Test Frequently: Test after each batch to catch problems early
Verify Each Change: Review each change as you make it
Document Progress: Keep track of what's been changed
Incremental changes make it easier to identify problems and allow you to stop and fix issues before they compound.
Safe Pattern: Renaming Variables
Renaming variables is one of the most common refactoring tasks. Following a safe pattern ensures all references are updated correctly.
COBOL Variable Renaming Pattern
To safely rename a COBOL variable:
Step 1: Use FIND to locate all occurrences. In COBOL, variable names can appear in:
Data division definitions (01, 77, or other level numbers)
Procedure division usage (MOVE, ADD, IF statements, etc.)
Comments (which may or may not need updating)
Copybook references (if the variable is defined in a copybook)
Step 2: Verify each occurrence. Check:
Is it the variable you want to rename, or part of another name?
Is it in the correct scope (local vs global)?
Should comments be updated, or left as documentation of the old name?
Step 3: Update the definition first. Change the variable name in its definition (DATA DIVISION), ensuring proper column positioning is maintained.
Step 4: Update all usages. Use CHANGE to update each occurrence in the PROCEDURE DIVISION. Consider using CHANGE with verification (not CHANGE ALL) to review each change.
Step 5: Update copybooks if needed. If the variable is defined in a copybook, update the copybook and verify all programs using that copybook.
Step 6: Compile and test. Compile the program to verify syntax, then test execution to verify behavior is unchanged.
Example: Renaming WS-COUNTER to WS-LOOP-COUNT
Here's a step-by-step example:
text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1. FIND WS-COUNTER
(Verify all occurrences - found in DATA DIVISION and 3 places in PROCEDURE DIVISION)
2. Update definition in DATA DIVISION:
OLD: 01 WS-COUNTER PIC 9(05) VALUE ZERO.
NEW: 01 WS-LOOP-COUNT PIC 9(05) VALUE ZERO.
3. Update each usage in PROCEDURE DIVISION:
OLD: ADD 1 TO WS-COUNTER
NEW: ADD 1 TO WS-LOOP-COUNT
(Repeat for each occurrence, verifying context each time)
4. Compile and test
JCL Dataset Name Renaming Pattern
Renaming dataset names in JCL requires finding all references across potentially many JCL files:
Step 1: Use ISPF Search Utilities (Option 3.14) to find all JCL files containing the dataset name. This searches across multiple files, not just the current one.
Step 2: For each file found, open it and use FIND to locate all occurrences of the dataset name within that file.
Step 3: Verify each occurrence. Ensure you're changing the right dataset name and not part of another name or a comment that should remain.
Step 4: Update each occurrence. Use CHANGE carefully, as dataset names in JCL can appear in DSN= parameters, in comments, or in other contexts.
Step 5: Verify JCL syntax. Use JCL validation or submit a test job to verify the JCL is still valid.
Safe Pattern: Mass Updates with Verification
When making the same change in many places, use verification techniques to ensure correctness.
Using CHANGE with Verification
ISPF's CHANGE command can be used with or without verification:
CHANGE (with verification): Prompts for confirmation before each change. Slower but safer.
CHANGE ... ALL: Changes all occurrences without prompting. Faster but riskier.
For safety, use CHANGE with verification, especially when:
You're not certain all occurrences should be changed
The pattern might match unintended text
You're making changes to production code
The change is complex or context-dependent
Use CHANGE ... ALL only when:
You've verified with FIND that all occurrences should change
The pattern is very specific and unlikely to match unintended text
You're working in a test environment
You have backups and can easily revert
Pattern Matching Best Practices
Use specific patterns to avoid false matches:
Full Names: Use complete variable or dataset names, not partial matches
Word Boundaries: When possible, use patterns that match whole words
Context Patterns: Include surrounding context to make matches more specific
Case Sensitivity: Consider case sensitivity based on the language (COBOL is case-insensitive, but some contexts matter)
Example: To change dataset PROD.DATA to TEST.DATA, use the full dataset name, not just "DATA":
text
1
2
FIND PROD.DATA (Find all occurrences first)
CHANGE PROD.DATA TEST.DATA (Change with verification)
This avoids changing unrelated text containing "DATA".
Safe Pattern: Using Backups and Version Control
Always have a way to revert changes. Backups and version control are essential safety nets.
Creating Backups
Before making refactoring changes:
Copy Files: Create backup copies of files you'll modify
Use Version Control: If available, commit current state before making changes
Document Backups: Note where backups are stored and how to restore them
Test Restore: Verify you can restore from backups if needed
In ISPF, you can create backups by:
Copying members to backup members (e.g., PROG to PROG.BACKUP)
Using dataset utilities to copy entire datasets
Using version control systems if integrated with ISPF
Incremental Saves
Save your work frequently during refactoring:
After Each Batch: Save after completing each group of related changes
Before Testing: Save before compiling or testing
At Checkpoints: Save at logical completion points
Frequent saves ensure you don't lose work and provide points you can return to if needed.
Safe Pattern: Testing and Verification
Testing is crucial for safe refactoring. Verify changes work correctly before considering refactoring complete.
Compile-Time Verification
After making changes, compile the code to verify:
Syntax Correctness: All syntax is valid
Reference Validity: All variable and procedure references are correct
Type Consistency: Data types and structures are consistent
Compiler errors help identify problems early. Fix compilation errors before proceeding to runtime testing.
Runtime Verification
After successful compilation, test execution:
Basic Functionality: Verify the program still performs its basic functions
Edge Cases: Test boundary conditions and error cases
Integration: Verify the program works correctly with other programs and systems
Runtime testing confirms that refactoring preserved functionality, not just syntax.
Comparison Verification
Use ISPF Compare utility to verify changes:
Compare Before/After: Compare original and modified versions to see exactly what changed
Verify Expected Changes: Ensure only intended changes were made
Check for Unexpected Changes: Identify any unintended modifications
Comparison helps verify refactoring correctness and provides documentation of changes.
Common Refactoring Scenarios
Here are safe patterns for common refactoring scenarios:
Scenario 1: Updating Copyright Notices
To update copyright notices across multiple files:
Use ISPF Search Utilities to find all files containing the old copyright text
For each file, use FIND to locate the copyright line
Use CHANGE to update the copyright text
Verify the change maintains proper formatting and column positions
This is relatively safe because copyright notices are typically in comments and changes are straightforward.
Scenario 2: Standardizing Formatting
To apply consistent formatting:
Identify formatting rules to apply (indentation, alignment, spacing)
Use block commands to select sections to format
Apply formatting incrementally, testing after each section
Verify formatting doesn't change code logic (especially important for fixed-format languages)
Be careful with fixed-format languages like COBOL where column positions affect meaning.
Scenario 3: Updating Parameter Values
To update parameter values across multiple files:
Use FIND with specific patterns to locate parameter assignments
Verify each occurrence is the parameter you want to change
Use CHANGE with verification to update values
Test that updated parameters work correctly
Parameter updates can affect program behavior, so testing is especially important.
Explain Like I'm 5: Refactoring Code
Think of refactoring code like organizing your toy box:
Finding Things First is like looking through your whole toy box before deciding what to organize. You need to see everything before you start moving things around, or you might forget where something important is!
Making Backups is like taking a picture of your toy box before you organize it. If you don't like how it looks after organizing, you can put everything back exactly how it was using the picture!
Changing Things Carefully is like moving one toy at a time and checking that it's in the right place. If you move all your toys at once, you might put something in the wrong spot and not remember where it should go!
Testing is like playing with your toys after organizing to make sure you can still find everything you need. If you can't find your favorite toy, you know something went wrong and you need to fix it!
Renaming is like putting new labels on your toy boxes. You need to update all the labels (not just some of them), or you'll get confused about what's in each box!
So refactoring is like organizing your toy box carefully, making sure you know where everything is, and testing that you can still find everything after organizing!
Practice Exercises
Practice safe refactoring with these exercises:
Exercise 1: Safe Variable Renaming
Objective: Practice the FIND-FIRST pattern for variable renaming.
Steps:
Open a COBOL source file with a variable you want to rename
Use FIND to locate all occurrences of the variable name
Verify each occurrence is the variable you want to rename
Update the variable definition first
Update each usage, verifying context
Compile to verify the changes
Exercise 2: Mass Update with Verification
Objective: Practice making mass updates safely.
Steps:
Create a backup of a file you'll modify
Use FIND to locate all occurrences of text you want to change
Verify each occurrence should be changed
Use CHANGE with verification (not CHANGE ALL) to update occurrences
Review each change before accepting
Compare original and modified versions
Exercise 3: Dataset Name Update
Objective: Practice updating dataset names across JCL files.
Steps:
Use ISPF Search Utilities to find JCL files containing a dataset name
For each file, use FIND to locate dataset name occurrences
Verify each occurrence is the dataset you want to change
Update each occurrence carefully
Validate JCL syntax after changes
Test Your Knowledge
1. What should you do before using CHANGE ALL in ISPF?
Nothing, CHANGE ALL is always safe
Use FIND to verify all occurrences first
Only check the first occurrence
Skip verification to save time
2. What is the safest approach for mass updates?
Make all changes at once
Test on a subset first, then apply to all
Make changes without testing
Change everything without verification
3. What ISPF feature helps you compare before and after changes?
FIND
Split-screen
CHANGE
SAVE
4. When renaming a variable, what should you update?
Only the definition
Only the usage
All references (definition and usage)
Only some references
5. What is a key safety practice when refactoring?