Progress Programming Tips

By Rod Gaither (rdg@worldinfo.com)


PPT-8  Hooking up with a persistent procedure at run time

Tip:

In our efforts to extend the ADM and provide a fuller set of
standard features we have implemented a "Services" provider
program.  The program is run persistently at application
startup and then each program that needs access to services
goes out and connects up upon instantiation.  The trick to this
is to put some unique identifier in the persistent procedure's
PRIVATE-DATA attribute.

Every program uses the following code to make that connection.

---- Code insert begins ----

PROCEDURE wis-get-services :
/*--------------------------------------------------------------------
----------
  Purpose:     Lookup and set the services handles
  Parameters:  
  Notes:       
----------------------------------------------------------------------
--------*/
  DEFINE VARIABLE h-first  AS HANDLE        NO-UNDO.  
  DEFINE VARIABLE h-tmp    AS HANDLE        NO-UNDO.
  DEFINE VARIABLE t-key    AS CHARACTER     NO-UNDO.
  DEFINE VARIABLE t-list   AS CHARACTER     NO-UNDO.


  ASSIGN 
    h-first = SESSION:FIRST-PROCEDURE
    h-tmp   = SESSION:FIRST-PROCEDURE
    t-key   = (IF h-first:PRIVATE-DATA <> ? THEN h-first:PRIVATE-DATA
    ELSE "").

  /***[ Loop until proper procedure found ]***/  
  DO WHILE (NOT t-key BEGINS "Services") AND VALID-HANDLE(h-tmp):

    ASSIGN h-tmp = h-tmp:NEXT-SIBLING.
    IF VALID-HANDLE(h-tmp)
    THEN DO:
      ASSIGN
        h-first = h-tmp
        t-key   = (IF h-first:PRIVATE-DATA <> ? THEN
        h-first:PRIVATE-DATA ELSE "").      
    END.

  END.

  IF VALID-HANDLE(h-first) AND t-key BEGINS "Services"
  THEN DO:
    ASSIGN h-serv = h-first.

    RUN get-handles IN h-serv 
      ( INPUT
      "err,lib,help,val,status,object,tab,menu,tb,backgrnd,main",
      OUTPUT t-list).

    ASSIGN
      h-err       = WIDGET-HANDLE(ENTRY(1,t-list))
      h-lib       = WIDGET-HANDLE(ENTRY(2,t-list))
      h-help      = WIDGET-HANDLE(ENTRY(3,t-list))
      h-val       = WIDGET-HANDLE(ENTRY(4,t-list))
      h-status    = WIDGET-HANDLE(ENTRY(5,t-list))
      h-obj       = WIDGET-HANDLE(ENTRY(6,t-list))
      h-tab       = WIDGET-HANDLE(ENTRY(7,t-list))
      h-menu      = WIDGET-HANDLE(ENTRY(8,t-list))
      h-tb        = WIDGET-HANDLE(ENTRY(9,t-list))
      h-backgrnd  = WIDGET-HANDLE(ENTRY(10,t-list))
      h-main      = WIDGET-HANDLE(ENTRY(11,t-list)) NO-ERROR.

  END.

END PROCEDURE.

---- Code insert ends ----

Some advantages of this technique are the separation of the
services program from the application as a whole.  It is found by its
key rather than a specific program name, making it easy to modify at a
later date.  Along the same lines it is the services procedure's job
to initialize each individual service properly and manage their
instances.  The "User" programs just ask for the handle by purpose for
their use.

The downside is that the interface to using those handles is
still fairly tightly bound.  Changing parameter lists or
procedure names will still cause problems for the "User"
programs.

The same technique could be used though to provide application
specific services as well.  Any effort to isolate the functions
by purpose for an application helps to provide encapsulation
that make modifications and replacement of such services easier.

Wisdom:

Don't get in a hurry, it is a big waste of time.


Rod Gaither                  | rdg@worldinfo.com
World Information Systems    | (910) 333-2580  Voice
Greensboro, NC               | (910) 333-2584  Fax