Implementing the interaction layer in a layered application framework

Introduction

 In the previous article I made a global description of implementing a layered application framework for SQL. In the article the following layers are identified:

 Domain layer (static domain objects)
User layer (view of various user groups on domain objects)
Interaction layer (Human Computer and Computer Computer Interaction)
 In this article I will present an implementation in Visual  Object classes how the Human Computer Interaction can be implemented in a generic way. In my daily work I am mainly involved in modelling application logic using a CASE tool. One of the deliverables of the CASE tool is a Visual Objects implementation (and instantiation) of this model as layered objects. 

Arrays as carriers

One of the great aspects of Clipper is completely implemented in Visual Objects: the array technology. And of course with reason: arrays are so powerful in VO. For example the possibility to dynamically add elements to the array and the fact that you can store any kind of entities like objects in an array. In the previous article I described the aspect of array carriers briefly. The name–value combination arrays are a way to let layers communicate with each other in a structured way. For communication between the interaction layer and the user interface this technique is also used. However in this situation an array of objects is used.

In the previous article I described the object that implements a servicelayer for communication for interaction. This object has the following method: 

METHOD GetListControls(strName) CLASS ServicesObject
LOCAL arrRes :={} AS ARRAY

DO CASE
 CASE Upper(strName)=="DETAIL_CONTACT"
    AAdd(arrRes,SELF:GetControlItem("CONTACT ","CONTACT_DATE "))
    AAdd(arrRes,SELF:GetControlItem("CONTACT ","CONTACT_ID "))
    AAdd(arrRes,SELF:GetControlItem("CONTACT ","DESCRIPTION "))
....
ENDCASE
RETURN arrRes

 

The code shows how an array is dynamically populated with controlitem objects (see next paragraph). The number of elements depends on the servicename passed as argument of the method. The interaction objects can use this carrier array for further processing, like drawing windows and controls. In the figure below the argument passing is explained.

 
ControlItem 

 In Visual Obects in datawindows and -servers instances of fieldspec classes are used to implement characteristics of fields. This is the basic idea behind the ControlItem class: it implements the static aspect and some dynamics of an attribute in the domain layer in the sense of a carrier. When the serviceobject is instantiated the init method calles the loadcontrols method. This method again fills an array with controlitem elements. In the code below a number of examples are given: 

AAdd(aRet, { "CONTACT", "CONTACTTYPE_ID ",;
ControlItem{ "Contacttype_id", "Contacttype", "I", "Lookup_Contacttype", "1", "", 0} })

AAdd(aRet, { "CONTACT", "CONTACTTYPE_ID ",;
ControlItem{ "Contacttype_id", "Contacttype", "I", "Lookup_Contacttype", "1", "", 0} })
AAdd(aRet, { "CONTACT", "CONTACT_DATE ",;
ControlItem{ "Contact_date", "Contact date", "D", "", "1", "", 10} })
AAdd(aRet, { "CUSTOMER", "CUSTOMER_TYPE ",;
ControlItem{ "Customer_type", "Customer type", "V",;
{ "Business client", "Personal client" } , "0", "", 50} })

The controlitems are representations of attributes of the domain layer. Therefore the items are identified by the name of the object type and the property. A controlitem stores information that a control on a window can use to display the data in a correct manner. For example the second element is the caption used for the control it gives the control a for the user logical name instead of the name of the property. Other items are the datatype , a domain of values (the name of a datasupply service or an array of static elements) the cardinality of the element and the initial value of the control.

The controlitem class has a little more functionality that is mainly used to make transformations between interaction controls and database implementation easier. For example the source code below transforms a dateformat in a control when possible to the format of a date in the database. 

METHOD DateFormatter() CLASS ControlItem
LOCAL blnOk:= TRUE AS LOGIC
IF SELF:strTypeContent="D" .and. !Empty(SELF:usuValue)
  IF !Instr("-", SELF:usuValue) .AND.;
   !Instr("/", SELF:usuValue)
    blnOk := FALSE
    SELF:usuValue := ""
  ELSE
    SELF:UsuValue := [] + SubStr(SELF:usuValue,7,4)+"-"+;
    SubStr(SELF:usuValue,4,2)+"-"+;SubStr(SELF:usuValue,1,2)
  ENDIF 
ENDIF   
RETURN blnOk
   


Interaction implementation


In the application framework a number of default interaction classes are defined. These classes are instantiated with the meta data for this specific application and a basic application is available. Most of the time this is an application with sufficient logic. In a small number of application extra user interactions like reports and specific datawindows with a richer interaction. In the figure you can see the default framework windows with on the left hand side a treeview to navigate through the elements and on the righthand side the details of the selected treeview element. In this article I wil only describe the detail window, in a later article I will describe the treeview implementation.
The datawindow is generated based on the carrier array with control items. To make this possible the autolayout method of the datawindow class is implemented in a derived class from the datawindow. A summary of the source code of this method is given below: 

FOR liField:=1 UPTO ALen(aVelden)
  oField := aVelden[liField]
  cType := oField:strTypeContent
  …
  DO CASE
    CASE cType="M"
      oPoint:Y   := oPoint:Y - (1.5 * editGap)
      liHoogte -= (1.5 * editGap)
      newControl := CaptionMultilineEdit{SELF, 200+liField,;
      oPoint,;
      Dimension{(60*TextMetric.tmAveCharWidth)+liCaption,;
      editGap*2.5 - 6},; _Or(…) }
    CASE …
    OTHERWISE
      IF ALen(aVelden[liField]:arrValues) > 0
        aTemp := aVelden[liField]:arrValues
      ELSE
   aTemp:=SELF:objService:GetFieldDomain(;
   aVelden[liField]:strValues)
      ENDIF  
      DO CASE
        CASE ALen(aTemp)>0
          newControl := CaptionComboBox{SELF,;
          200+liField,;
          oPoint,;
          Dimension{ CalculateComboSize(aTemp,;
          SELF)+liCaption, editHeight}}
         nX:=NewControl:Origin:X
         nY:=NewControl:Origin:Y - 60             
         …
          NewControl:FillUsing(aTemp)
      ENDCASE
    ENDCASE
    newControl:LinkControl(aVelden[liField])
    newcontrol:Value:=aVelden[liField]:strInitValue
    newControl:Show()
  ENDIF
NEXT

In the summary code you can see how in a for next loop the carrier array is processed. For each element based on a number of conditions the right control is created. Special care is taken to handle the domain of the control correctly. If the domain retrieved by  the method GetFieldDomain() is processed. When it is an array it is a static domain when it is a string it is the name of a data supply service.

At the end of the source code you can see how the control is linked to the controlitem class. This takes care of further controlitem handling in the derived control class.

Connecting the servicelayer with the interactionlayer


In the above paragraph a description is given how the interaction layer generates generic datawindows based on the information supplied by the servicelayer in carrier arrays. This is one aspect of the communication between the servicelayer and the various classes in the interactionlayer. For example a datawindow with modified controls have to send these changes to the domainlayer and from there to the database. Or a report has to display data from the domainlayer.

As explained there are two kinds of services datasupply and datamodify services. The first one retrieves data from the domainlayer the second kind modifies the domain objects. This is very easy to implement now. On the datawindow the following code is added to retrieve information from the domainlayer by calling a window generate method datasupply service:

METHOD GenerateForm(strEvent, strDataService, aPara) CLASS ServiceLayer
LOCAL oWnd AS DLADataWindow
oWnd:= DLADataWindow{oMainWindow, SELF, strDataService}
oWnd:SetEvent(strEvent)

oWnd:FillControls(SELF:ExecuteSupplyService(;
strDataService, aPara))
…   
oWnd:Show()


 

The method calls the supplyservice and instantiates an wrapper class over the sql statement. This is passed to the window to set the values of the controls with the values of the select statement.

 Summary

In this article a description is given of how to implement the interaction layer of a Visual Objects application. This application uses a three layer architecture with services to interact between the layers and the user interaction.

By using generic software it is easy to implement default user presentations that communicate with the servicelayer to retrieve information and modify the state of domain objects in a SQL database. This generic implementations are stored in class libraries and the specific application behaviour is generated by a CASE tool. Applying this work process opens opportunities to develop software very fast and in a cyclus with iterations.

 

About the author

 Bert is software developer for more than 15 years now. In his early programming days he started with Foxbase and Clipper. Later Visual Objects, Microsoft Office and ASP webapplications were included. He is interested in model (data) driven solutions and object oriented methodologies. Bert is an independent software developer. He can be reached by email at bert@dla-architect.nl. His website is: www.dla-architect.nl   
 

Commentaar van anderen:
ChristianLouboutin op 14-8-2010 om 11:23
Christian Louboutin Shoes, Christian Louboutin, Christian Louboutin Shoes, Wedding Shoes, Christian Louboutin Copyright 2010, Chemicals Chemistry via VerticalNews. Christian Louboutin Shoes, Wedding Shoes Pattinson great actorly virtue is that he wears clothes well, so it too bad he slackered-out in cargo pants here. Christian Louboutin, Christian Louboutin Shoes, Wedding Shoes, Discount Christian Louboutin, Manolo Blahnik Shoes Tyler is less revealed than telegraphed through accessories a dead brother depth, a pack-a-day habit angst, a bookstore job smart, Discount Christian Louboutin, Louboutin, Christian Louboutin Sale, Louboutin Shoes, Sale Christian Louboutin Rodita zip sandals New style Black 14 a rich, aloof, and permanently disappointed daddy Pierce Brosnan. Louboutin Sale, Herve Leger Bandage Dress, Herve Leger Dress, Herve Leger V Neck Dress, Herve Leger Bandage Dress Falling for You Love, angst, and something else is in the air in Remember Me Remember Me Herve Leger Dress, Chanel Shoes, Yves Saint Laurent Shoes, Manolo Blahnik Shoes Platform Cage Sandal 13 by Allen Coulter Summit Entertainment Opens March 12 Putatively a new romance starring Robert Pattinson, Remember Me begins like a vigilante movie Alexander Wang Shoes, Louboutin Shoes, Louboutin Sale, Louboutin, Christian Louboutin Sale, Buy Christian Louboutin A Brooklyn subway platform, a racially charged stickup girl watches her mother get shot. Christian, Christian Louboutin Discount, Christian Dior Shoes, Christian Louboutin Pumps Pattinson great actorly virtue is that he wears clothes well, so it too bad he slackered-out in cargo pants here.
Geef feedback:

CAPTCHA image
Vul de bovenstaande code hieronder in
Verzend Commentaar