ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Modules vs Called programs

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    Re: Modules vs Called programs

    Here is how I do it... This is a very simple explanation where I leave out certain fringe scenarios that won't break what I list, but certain things that would *automagically* be covered by doing these things that you don't need to worry about at this time.

    1) Create your procedures in your modules. This is what you have already done.
    2) In your Binder Source only use the PGMLVL(*CURRENT) and specify your own signature that will never change SIGNATURE('MYSIG'). Now, in order for this to work you simply have to remember 1 simple rule. ALWAYS ADD NEW EXPORTS TO THE BOTTOM OF THE LIST. If you do that then you can add to your service program over time and you will not have to recompile all the programs that are bound to it because the signature didn't change. And because you put the new exports at the end of the list the ones that were already there are in the same order and will be found with no problems. Any programs that need the new procedures will get recompiled when they need them anyway.
    3) Put your procedure prototypes (PR) in a copy source member. Then you don't have to specify the prototypes in EVERY program you want to use them in. Also, if the parameter list ever changes you won't have to change it in lots of different places. Just change it in the copy member and the module source and then recompile any callers.
    4) You do not need CALLP. I use free form RPG and have NEVER used a CALLP. I simple do this... MyProcedure(Parm1:Parm2:ParmN); If I have a return variable is MyReturnVar = MyProcedure(Parm1:Parm2:ParmN);
    5) When you make a change to your procedures that DOES NOT effect the prototypes you will not have to recompile the service program or any of the bound (or calling) programs. These are the steps...
    1. Recompile Module
    2. Update Service Program

    That is it. If a prototype changed then you'll need to recompile the service program. Then only recompile the programs that actually need to use the effected procedure, which you would need to do anyway since the prototype changed. (I know, there are instances where the prototype can change and you don't need to recompile, that is beyond this scope though).
    Your future President
    Bryce

    ---------------------------------------------
    http://www.bravobryce.com

    Comment


    • #17
      Re: Modules vs Called programs

      For simplicity sake, I only use one module per service program. This allows me to easily locate the soure for any function / subprocedure, and easily include the prototypes.

      ie:

      If I have a function called ITEM_GetQtyOnHand, and I want to include it in my program, then I know that:

      A) The prototypes for the include will be located in a source file called ITEM_P.
      B) The source for the fuction is located in a source file called ITEM_S.
      Michael Catalani
      IS Director, eCommerce & Web Development
      Acceptance Insurance Corporation
      www.AcceptanceInsurance.com
      www.ProvatoSys.com

      Comment


      • #18
        Re: Modules vs Called programs

        Originally posted by bryce4president View Post
        Here is how I do it... This is a very simple explanation where I leave out certain fringe scenarios that won't break what I list, but certain things that would *automagically* be covered by doing these things that you don't need to worry about at this time.

        1) Create your procedures in your modules. This is what you have already done.
        2) In your Binder Source only use the PGMLVL(*CURRENT) and specify your own signature that will never change SIGNATURE('MYSIG'). Now, in order for this to work you simply have to remember 1 simple rule. ALWAYS ADD NEW EXPORTS TO THE BOTTOM OF THE LIST. If you do that then you can add to your service program over time and you will not have to recompile all the programs that are bound to it because the signature didn't change. And because you put the new exports at the end of the list the ones that were already there are in the same order and will be found with no problems. Any programs that need the new procedures will get recompiled when they need them anyway.
        3) Put your procedure prototypes (PR) in a copy source member. Then you don't have to specify the prototypes in EVERY program you want to use them in. Also, if the parameter list ever changes you won't have to change it in lots of different places. Just change it in the copy member and the module source and then recompile any callers.
        4) You do not need CALLP. I use free form RPG and have NEVER used a CALLP. I simple do this... MyProcedure(Parm1:Parm2:ParmN); If I have a return variable is MyReturnVar = MyProcedure(Parm1:Parm2:ParmN);
        5) When you make a change to your procedures that DOES NOT effect the prototypes you will not have to recompile the service program or any of the bound (or calling) programs. These are the steps...
        1. Recompile Module
        2. Update Service Program

        That is it. If a prototype changed then you'll need to recompile the service program. Then only recompile the programs that actually need to use the effected procedure, which you would need to do anyway since the prototype changed. (I know, there are instances where the prototype can change and you don't need to recompile, that is beyond this scope though).
        Thanks @bryce4president. That makes everything crystal clear to me.

        Regards,

        Sriram

        Comment


        • #19
          Re: Modules vs Called programs

          Originally posted by bryce4president View Post
          Here is how I do it... This is a very simple explanation where I leave out certain fringe scenarios that won't break what I list, but certain things that would *automagically* be covered by doing these things that you don't need to worry about at this time.

          1) Create your procedures in your modules. This is what you have already done.
          2) In your Binder Source only use the PGMLVL(*CURRENT) and specify your own signature that will never change SIGNATURE('MYSIG'). Now, in order for this to work you simply have to remember 1 simple rule. ALWAYS ADD NEW EXPORTS TO THE BOTTOM OF THE LIST. If you do that then you can add to your service program over time and you will not have to recompile all the programs that are bound to it because the signature didn't change. And because you put the new exports at the end of the list the ones that were already there are in the same order and will be found with no problems. Any programs that need the new procedures will get recompiled when they need them anyway.
          3) Put your procedure prototypes (PR) in a copy source member. Then you don't have to specify the prototypes in EVERY program you want to use them in. Also, if the parameter list ever changes you won't have to change it in lots of different places. Just change it in the copy member and the module source and then recompile any callers.
          4) You do not need CALLP. I use free form RPG and have NEVER used a CALLP. I simple do this... MyProcedure(Parm1:Parm2:ParmN); If I have a return variable is MyReturnVar = MyProcedure(Parm1:Parm2:ParmN);
          5) When you make a change to your procedures that DOES NOT effect the prototypes you will not have to recompile the service program or any of the bound (or calling) programs. These are the steps...
          1. Recompile Module
          2. Update Service Program

          That is it. If a prototype changed then you'll need to recompile the service program. Then only recompile the programs that actually need to use the effected procedure, which you would need to do anyway since the prototype changed. (I know, there are instances where the prototype can change and you don't need to recompile, that is beyond this scope though).
          Hi,

          I am sorry, I have still not been able to figure out how to go about it. Just to ensure that I do not go astray from the context of this
          thread, I have posted it separately here - http://www.code400.com/forum/showthr...ram-and-binder

          Thanks in advance for any help.

          Best Regards,

          Sriram

          Comment


          • #20
            Hey guys sorry for bumping an old thread. But I felt like a lot of the discussion in this thread ended up being more about the use of Service Programs. I'm totally bought into service programs and think they're awesome.

            But I wanted to ask you guys about this part

            b) What's the difference/benefits if I create a module as opposed to a called program? (none that I see)

            Called program:
            1) I can change that called program and never have to worry about the programs that call it (save and except if I change the parms).

            2) If I use a module, don't I have to recreate/rebind all the mains if I change that module (all that extra work).

            3) in most of the environments I work in, the user nor the performance would see any difference.

            4) same amout of coding wheather it's a module or a subprogram, just extra work binding it all together.

            Please educate me then maybe I can see the benefits.
            I had these exact same thoughts. And wanted to make sure I fully understood the benefits of modules before deciding whether or not to use them outside of service programs.

            Benefits of breaking programs into modules?
            -Programs run faster. As modules are bound/compiled together into one executable and calls to procedures are quicker. (I'm assuming this has something to do with spacial locality of memory and not exposing the program calls to the OS things like scheduler and having to navigate the libraries for the object inode??? do IBM i objects use inodes??).
            -You can bind modules of other ILE languages together to form one *PGM object. Pretty cool.

            Are there any benefits I'm not seeing? I would love to modularize my programs but it seems better to just used called pgms as change management can more clear. Do you guys develop in your shops using modules or called pgms? Furthermore, to those of you who do develop RPG programs using modules outside of service programs how do you approach change management?

            Thanks, again sorry for bumping an old post.

            Comment


            • #21
              Let's start with the difference between a dynamic program call (i.e. a call to a *PGM object) and a bound procedure call (i.e. a call to a procedure in a module - whether that module is in a service program or bound into a *PGM). Those really are the only options. The difference between binding the module into a SRVPGM or a PGM is miniscule in terms of speed of call.

              The two call mechanisms are completely different and the instruction path length likewise is much longer for a PGM call.

              The parameter mechanism is also radical different and probably accounts for much of the performance difference. On a PGM call the calling program hands the parameter pointers to the OS APIs and the called program basically then calls OS APIs to obtain the address of each parameter. On a bound call the parameter pointers (or the actual value in the case of a parameter passed by value) are placed on the stack by the caller and simply pulled off the stack by the called procedure. As you can imagine that is a WAY shorter path.

              That said, these days I would never bother with binding in a module - the maintenance overhead is not worth the performance boost in all but the rarest of cases. But I do make extensive use of Service Programs and all of my programs are built around internal procedures.

              There are exceptions to the "no module binding" rule. For example if a program is A) Subject to frequent changes and therefore smaller pieces would allow multiple programmers to work on it at one time) and B) has large numbers of subprocedures used from all over the place then I _might_ consider binding the module. But then I might just create a service program that is only used by that program.

              As with anything there are always exceptions but ...

              Comment

              Working...
              X