Valid violation of encapsulation?

Stefan

Well-Known Member
The past few days there has been quite some discussion on encapsulation (on the peg). The following is an excerpt from our documentation on how to talk to our business logic (running on its own AppServer). The business logic temp-tables are exposed to the outside world in a prodataset and therefore violate the encapsulation 'rule'.

To me our interface seems very efficient and clear. What would an alternative interface look like? A temp-table filled with name / value pairs seems kludgy to me?


Introduction


All Exact Financials Enterprise business logic can be invoked on the AppServer. This document describes how to invoke the business logic from a Progress OpenEdge client with a connection to the AppServer.

The following steps are involved:
  1. connect
  2. request dataset
  3. fill temp-tables
  4. pass dataset
  5. disconnect
The following variables are used to illustrate how to create an item:

Code:
DEFINE VARIABLE happserver AS HANDLE NO-UNDO.
DEFINE VARIABLE cuser_object AS CHARACTER NO-UNDO.
DEFINE VARIABLE dsinput AS HANDLE NO-UNDO.
DEFINE VARIABLE dsoutput AS HANDLE NO-UNDO.
DEFINE VARIABLE hbllitem AS HANDLE NO-UNDO.
DEFINE VARIABLE lok AS LOGICAL NO-UNDO.

1. connect

When connecting to the AppServer the user id and password must be passed:

Code:
CREATE SERVER happserver.
hAppServer:CONNECT(
   "-URL appserver://server:nameserverport/appservername":U,
   "user":U,
   "password":U
).

If the connection is succesful a user object is returned as RETURN-VALUE - this must be stored and used for every subsequent call to the AppServer.

Code:
cuser_object = RETURN-VALUE.

If a connection is created to a state-free AppServer, the AppServer connect procedure is not executed upon connecting to the AppServer so an additional call is required to authenticate the user and get the user object

Code:
RUN system/start/appcon.p ON happserver ( "user":U, "password":U, ? ).
cuser_object = RETURN-VALUE.

2. request dataset


The AppServer procedure ifall/bl/initialize.p returns a dataset based on the table passed:

Code:
RUN ifall/bl/initialize.p ON happserver (
   cuser_object,
   "llitem":U,
   OUTPUT DATASET-HANDLE dsinput
).

The definitions of the dataset can be easily viewed using write-xml:

Code:
dsinput:WRITE-XML(
   "FILE":U, SUBSTITUTE( "&1&2.xml":U , SESSION:TEMP-DIRECTORY, dsinput:NAME ),
   TRUE, ?, ?, TRUE
).

3. fill temp-tables


Find the temp-table buffers in the dataset using:

Code:
hbllitem = dsinput:GET-BUFFER-HANDLE( "tmp-llitem":U ).
hbllitem:BUFFER-CREATE().
ASSIGN
   hbllitem::adm_nr = 621
   hbllitem::item_code = "new item":U
   .

4. pass dataset


The next step is to pass the dataset back to the AppServer, calling the remote procedure that contains the action you want to perform. The following business logic actions are supported:
  • create
  • find
  • update
  • delete
  • search
  • assign
Code:
RUN ifall/bl/create.p ON happserver (
   cuser_object, ?, ?,
   DATASET-HANDLE dsinput,
   OUTPUT DATASET-HANDLE dsoutput,
   OUTPUT lok
).

In the above example 'create' can be replaced with 'find', 'update', 'delete', 'search' or 'assign'. If the action failed, lok is set to false and the error temp-table tterrors contains the errors that occurred.

5. disconnect


Code:
DELETE OBJECT dsinput.
DELETE OBJECT dsoutput.
happserverISCONNECT().
DELETE OBJECT happserver.

That's all.
 
When i did web project with flex and webservices i used this same method.
On state-free model even without connect and disconnect statements.

Incoming data mapped to flex object and classes.
Fieldname and value pair already exists in xml. You dont need to change it.
 

Marian EDU

Member
Stefan, I wouldn't consider this as a violation of encapsulation... as we can't pass objects between appserver and client you can look at it as a form of object serialization :)

Probably the only case where temp-table/dataset encapsulation is questionable is on the client-side where the 'View'/'Presenter' need to become data-bound to the data structure in the 'Model'... and this is mostly true for a data-grid where we will prefer to work on the same temp-table (by-reference) that is owned by the Model instead of getting a copy of it to work with, therefore we might end-up having some method in the Model that will expose the temp-table/dataset by returning the handle to it and this can be seen as a violation of encapsulation.
 
Top