|
(combining several helpful replies below) Scott writes: >A simple wrapper usually doesn't significantly improve >the interface of the API any more than just >prototyping it would. This makes perfect sense. But my thinking is not to simply mimic the API interface, but to simplify it. For instance, create a user space wants a qualified user space name, extended attribute, initial size, initial value, public authority, text, replace flag and error feedback. If I use an interface that requires only a name and text, I could have the wrapper supply defaults. So the create would go from C callp CrtUsrSpc('MBRDATA QTEMP':'USRSPC': C 1:x'00':'*ALL':'List of Members in File' c '*YES': dsEC) to eval rc=crtusrspc('PGMLIST': 'QTEMP': 'List of programs') The defaults could get filled in for the other parms. But your next sentence makes me want to think twice about that: >I've found that in order to support all of the functions of >any given API, my parameters end up being very nearly >the same as the ones IBM provides. That's presuming that you don't want to superset the API. I could do something like crtUsrSpcSmall crtUsrSpcMed crtUsrSpcLarge (with appropriate defaults) all of which call crtUsrSpc which is a private function that mimics the full function of QUSCRTUS. This is a little contrived, but my idea is not to make the raw interface public; only the custom ones - the ones I (hopefully!) make easier to use. Would that lead to a proliferation of functions? It hasn't so far, but that's why I'm asking for advice - if I knew all the answers I wouldn't have to work for a living! <grin> >I think that when you have specific details that you >want to get from an API, and you do it the same way >frequently, it's easier to have a procedure in a service >program with a very simple interface. That's where I'm heading (I hope!) Nathan writes: >... a higher level interface that incorporates calls to more >than one system API can also apply to many applications. Said much better than I could have. Here's what I'm doing. We're doing a major overhaul of our product, and want to verify that the object code at the customer sites matches the code we have here on the development box. It's possible that source was shipped to the customer and changes made onsite. The approach we decided on was to compare the source member change date/time. That's easy for OPM programs: DSPOBJD *SERVICE to an outfile and a simple query to find the differences. ILE programs don't fit that pattern. I need to write a routine that uses QBNLPGMI to get that information for all the modules in the ILE program. That, in turn, requires a user space: QUSCRTUS, RTV (or PTR) and DLT functions. Instead of writing all those functions in a quick boilerplate I figured "why not do it the Right Way?" Hence, my post. Is it unrealistic of me to think that I can incrementally grow useful service programs this way? Lisa writes: >Also if you need to change the parameters on a >function with or without binding language, it would >seem you would be rebinding many more objects. >This would hold especially true for APIs that may >add functionality requiring different parameters. I probably didn't give a clear picture of what I'm trying to do - sorry! I never bind by reference - if it is a one-use procedure, it goes in the same source member as the mainline, if not it goes in a service program. I use binder language faithfully, so I'm pretty much shielded from having to re-bind my existing service programs. I use a common naming convention for members, putting each "piece" into a separate source file: members named SOCKETSVC; prototypes in QPROTOSRC (for /COPY or #include), code in QRPGLESRC/QCSRC, binder language in QSRVSRC. That makes it fairly easy to find all the parts. As far as a catalogue goes, there aren't that many service programs now, but I will probably try to make something like Javadoc to pass over the prototypes and create something in QTXTSRC. (back on track) If an API I use gets a significant function that I need a new interface for, I'll probably write a new function with a new name and deprecate the "old" one with comments in the prototype and code source. That way, when I'm looking to use a function I'll direct myself to the new one instead of the old one. Nelson writes: >We also put all the prototypes in a single source member and >use the "IF Defined" compiler directive so that only requested >prototypes are copied into the actual programs that >need to use them. The prototypes source member itself, >then becomes the universal list of all publicly-available >procedures. That's an interesting thought. Where do you set the /DEFINE? In the mainline? How do you know what to /DEFINE? Look it up in the prototype source member? Buck
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.