When I write a tool for myself — for my own use — I will typically include ISPF assets at the bottom of the code and have software extract them as part of the initialization phase. I rarely load panel text to ISPPLIB or skeletons to ISPSLIB. There are several advantages to keeping your ISPF assets 'local':
- I/O is reduced, sometimes very substantially reduced
- changes made to these assets are reflected immediately without having to be in TEST-mode and certainly without having to leave ISPF and restart it
- there is no doubt about the identity of subsidiary elements
- there is no danger of duplicate member names
- When distributing or installing, there is only one element to distribute or install: the enclosing REXX code
When ISPF is invoked by a non-developer (call it 'standard mode') its habit is to cache any panels, skeletons, or messages that it uses. It keeps them in storage so that if the same element is re-used, ISPF can get it from the cache rather than doing I/O to get a fresh copy. Obviously, if you're modifying that element, saving it to its library won't do a thing for your current session. To get that new panel, you have to exit ISPF to READY-mode and restart ISPF. That takes a lot of I/O because on start-up, ISPF opens and reads ISPPLIB, ISPSLIB, ISPTLIB, ISPMLIB, and ISPLLIB so that it knows all the available membernames and where they're located — in case you ask for one of them.
Developers who work with ISPF services generally invoke ISPF in TEST-mode when developing because in TEST-mode, ISPF caches nothing and always does I/O to handle service requests. If you've just saved a change to a panel and you're in TEST-mode, your next DISPLAY request will retrieve the new version. The penalty you pay for this is that every service request is handled via I/O.
Embedding your ISPF assets gives you the best of both worlds: because ISPF caches elements based on DSN+membername, re-extracting ISPF assets at execution-time creates a new dataset (in VIO) and ISPF recognizes that this member XYZ is not the same XYZ as that in the cache, so it reloads a fresh copy. All other service requests are handled via the cache — because you don't use TEST-mode.
It gets better: When you invoke the enclosing REXX, it all gets read into storage immediately, and that includes your panels and skeletons. Extracting them thus happens at 'core speed' and if they're written to VIO datasets, that happens at 'core speed' as well. No need to read the panel(s) from ISPPLIB or the skeleton(s) from ISPSLIB separately. It's already here.
You no longer have to search through the libraries to ensure you're not using a duplicate membername — because your data is not going to live in any of those libraries. The elements embedded in your application are extracted and loaded to a library which is then LIBDEF'd into a preferential position to all others. If you use a name replicated elsewhere, you will only use your element; the other will be 'masked' by virtue of being too far down the concatenation. Of course, when the application ends, LIBDEF tears down those purpose-built libraries and the environment is restored to its pre-invocation state. Neat.
When you install the application, you install one element. All the other panels and skeletons used by the main REXX routine do not get separately installed — there's no need to formally install them because they will be regenerated dynamically as and when needed.
If anyone out there can find a 'down-side' to any of this, I'd be very interested to hear it. To me, it all looks like 'up-side'.