There is an old saying in the software development community that you only ever write a program from scratch once - all subsequent programs are simply copies of this original which are then amended as required. This is certainly true with 3rd generation languages such as COBOL which require huge amounts of text just to describe all the various divisions and sections into which you place your code. It is (or was in my day) common practice to have a skeleton source file available that provided this empty shell.
Some people consider that modern 4GLs do not need such a facility as the creation of new components is much speedier than it used to be. However, those of us who write code day after day are in a much better position to judge the accuracy of this statement rather than those armchair warriors. How many times have you come across the following scenario:
That phrase "does exactly the same thing" should trigger in your mind that there is something in common between these two components, and this commonality can be formed into a pattern, a template, something which is repeatable.
After a while you will notice that your entire application can be broken down into groups of components that follow similar patterns, and it is the ability within UNIFACE to produce components (transactions) from pre-defined component templates (transaction patterns) that is the subject of this document.
Before you can build components from templates you must first build a library of templates, but even before this you must identify the patterns that are likely to be repeated. How do you recognise a pattern that could be turned into a template? You can start by categorising a component according to the following:
This identifies the basic layout of entities within a component's structure. Each entity has its own entity frame which may occur once or several times. Any field within an entity frame is assumed to belong to that entity. An entity frame may contain other entity frames within it which are known as "inner" entities. An "inner" entity may also have its own "inner" entities. It is assumed that there will be a relationship between the "outer" and "inner" entities as after each occurrence of the "outer" entity has been read from the database the relationship details will be used to read any matching occurrences from the "inner" entity.
The kind of questions you should be asking are:
Here are some typical structures:
This contains a single occurrence of a single entity. | |
This contains multiple occurrences of a single entity. | |
This contains two entities in a ONE-to-MANY relationship.
There is a single occurrence of the ONE (outer) entity. There are multiple occurrences of the MANY (inner) entity. After reading the OUTER entity it will read the related occurrences of the INNER entity. |
|
This contains two entities in a MANY-to-ONE relationship.
There are multiple occurrences of the MANY (outer) entity. For each MANY (outer) there is a single occurrence of the ONE (inner) entity. After reading each occurrence of the OUTER entity it will read the related occurrence of the INNER entity. |
This identifies how a component behaves when it is used. The kind of questions you should be asking are:
By content I mean the actual data that is contained within a component, specified by particular entity names and field names. The type of widget that is used to display data is largely irrelevant except when it requires complex processing (e.g. a tree widget or a tab page).
In my experience what you should be looking for are cases where structure and behaviour are the same. Content should only be relevant when creating an actual component from a template.
Over the years I have designed and built numerous applications in UNIFACE, and I have managed to acquire a large collection of templates. I started off by defining a standard form layout:
This contains the following areas:
I then started to build individual forms using this standard layout as a starting point, making sure that similar requirements were satisfied in a similar way. Below is a small sample from my collection.
This type of form has the following characteristics:
This type of form has the following characteristics:
This appears to be extremely similar to the LIST2 template, but the absence of the navigation bar has the following impact:
This appears to be extremely similar to the LIST1 template, but the absence of the profile area has the following impact:
This type of form has the following characteristics:
This type of form has the following characteristics:
This type of form has the following characteristics:
This type of form has the following characteristics:
This is just a small sample from my collection of templates, which currently totals over fifty. Copies of my templates, plus example transactions built from them are available for download from my Building Blocks page.
There was no formal method of creating or using templates in version 6, so if developers wished to clone any components it could only be done the hard way:
After creating a form which you subsequently wish to replicate you can either attempt to remember the name of the original form, or you can produce a copy with a meaningful name and a suffix such as 'XX_', 'YY_' or 'ZZ_'. The former method starts to become tricky in a system that has hundreds of forms. At least with the latter method all the template forms are easy to recognise.
The only way to use one of these template forms is to make a duplicate, then go through the copy and replace all the original objects (entities and fields) with the ones that you actually want to use. This means either renaming those objects, or deleting the old ones then inserting the new ones. Renaming is better because (at least with version 7) you have the option of carrying forward any trigger code from the original object. Unfortunately this trigger code will still contain references to the original objects, so it will be necessary to step through every line of code and manually alter all these references. Most omissions will appear when you first compile the component, but it is still possible for mistakes not to become apparent until the component is actually run.
After working on several different systems I decided to keep all my template forms in a separate environment. I actually turned them into a mini example application so I could compile and run them to demonstrate how they worked. This was also a useful place to test enhancements.
One of the improvements with UNIFACE version 7 was the introduction of a new object called a component template. This has its own area in the repository so that components and component templates can be kept separate. Creating a component template is a little more involved, but the investment pays dividends when it comes to using one to create actual components.
As soon as I read about this new facility I went straight to my example application and made a proper component template for each of my example forms. I then rebuilt each form from scratch using the new template just to test that I had got it right. I then recreated my menu and security system using these templates, so in a short space of time I had a fully functioning development environment that was pure version 7. The latest version of this environment, complete with the XAMPLE application, is available for download from my Building Blocks page.
The component template editor can be found on the pulldown menu Editors | Templates | Component, which will give access to a set of screens that are similar to the standard Graphical Form Painter (GFP). However, when creating objects with this editor there are the following differences:
Any proc code that you define in any trigger within the component template will be inherited by a component when it is initially created. In addition the code in a component-level trigger has the ability to be inherited after this point provided that no local modifications to the trigger are made within the component. This means that it is possible to make changes to a component-level trigger within a component template after it has been used to create components and have those changes inherited by all associated components when they are next compiled. This ability to inherit changes is limited to component-level triggers only, and excludes any other triggers or objects.
When you come to create a new component you should see one of the following dialog boxes:
In order to select which component template to use you will then be presented with the Browse Component Template window as follows:.
By confirming to use a component template you will be presented with a screen similar to the following:
The top left-hand area shows the source entities that have been defined in the component template. The top right is the area where you define the target entities required within the component. Note that it is possible to predefine the target entity. As each source entity is selected the bottom left area will show the source fields that have been defined for that entity, with the bottom right used to specify the target fields.
Note that the button can be used to browse through the repository in order to select the model, entity and field names.
Once you have specified targets for all the generic objects you simply press the OK button and the component will be built for you, with all the source objects replaced by their specified targets. The new component will inherit all trigger code defined within the template, plus any defined within the application model for the target objects. All that is left is to resize the objects (if necessary), insert any missing objects, and the finished component is ready for compiling and testing.
When you examine any inherited proc code with the component editor you will still see the unresolved references to generic objects, as in the following example:
params string $params$ : IN endparams clear/e "<MAIN>" getlistitems/occ $params$, "<MAIN>" retrieve/x "<MAIN>" if (!$dbocc(<MAIN>)) putmess "primary key: %%$params$" message $text(M_90007) ; no entry found exit(1) endif reset $formmod display
In order to see code where the generic names have been replaced with target names you should view the compiled listing.
The use of templates need not be restricted to the actual construction of components. It is also possible to extend this concept into other areas of application development:
Every component should have a proper specification before it is given to a developer (well, that's the theory!). Although some organisations do have skeleton specifications these are usually restricted to nothing more than bare paragraph headings, a sort of 'one size fits all' idea. But if a component can be constructed from a template where the basic structure and behaviour have been predefined, then surely it would make sense to have program specifications constructed along similar lines? Instead of having to redefine the standard features for each type of component it would be more efficient to take an appropriate specification template and simply fill in the blanks. To create a specification template all you need do is document the workings of each component template. Thus the specification writer can have a specification template in the same way that a component developer has a component template.
There is no point in having a comprehensive array of component templates at your disposal if the system designers produce designs that do not fit any of the known patterns. The designers need to be educated in what is available so that they choose something that can be built quickly rather than something that requires the re-invention of the wheel. Having looked at a problem they should be able to pick an appropriate solution that is 'off the peg' rather than trying to invent a bizarre solution that is 'off the wall'.
To aid in their education I have created a sample application that contains a working example of virtually every component template in my arsenal. Not only can I use this to demonstrate how a component works in isolation, I can also demonstrate how a group of forms can work together in unison. A practical demonstration is worth much more than a written description. For any given problem the designers should be able to pick the solution from the list of available templates, just like ordering dishes from a chinese menu.
In trying to convince others of the efficacy of component templates several questions have been asked. Here are some of those questions with my answers:
As an example I will take a mini application that I built in 1999. Starting with nothing more than a brief outline specification I designed a system with a database containing 19 tables and 18 relationships, with 50 form components and a few services. I built all the components, performed unit testing, link testing, system testing and created an initial set of online help text.
Fortunately this could be kept small as there was no complex validation and no requirement for user documentation other than the online help text.
In comparison when I built two prototype systems of a similar size in version 6 several years previously they each took 3 months. I think you will agree that a drop from 3 months to 5 weeks is a sizable productivity gain.
Definitely not. My aim is to be able to build every single component within an application from a template with the only customisation being the inclusion of the relevant data fields. It you have to start making changes to the structure or behaviour of a template, including changes to the inherited code, then it is time to think about creating a variation of the template.
I have twice been told by senior people at different organisations 'We don't need 50 templates, we only have 5'
, but after working with the developers my response is always the same: 'You may HAVE only 5 templates, but what you really NEED is 50'
. How can I say this? Simply because the developers found it so cumbersome to start from a primitive template and add in (or take out) the necessary code that they found it easier and quicker to make a copy of an existing component and edit the entity and field names. This means that they are still using the Version 6 method and have yet to learn how to make proper use of component templates in Version 7.
I had the same idea when I first created my templates, but after making the same structural alterations to the same template for several different components I found it much easier in the long run to make the alterations just once in a new template which I could then reuse ad infinitum. Using a template that already contains the modifications is much easier than attempting to replicate the modifications manually. It also avoids the possibility of errors creeping in. If you don't believe me then try this little exercise:
You should see a significant difference in the development time between these two methods. If it is the duty of the IT department to produce results in as short a time as possible, then which of these two methods should you be using?
No. The content of a component (i.e. the data) is irrelevant. It is the combination of structure and behaviour that dictates which template to use. The only reason I paint the first and last fields within an entity in my templates is because of the prompting sequence contained in the <next field> and <previous field> triggers.
Where foreign entities are painted as inner entities and have no impact on either the structure or behaviour of the form then they are there for data purposes only. As such they do not require a variation in the template.
If the behaviour of a component can be altered by setting a value in a component variable then it is a relatively simple process to build this into the template. For example, take the following code in the LIST1 template:
params string $params$ : IN endparams getlistitems/id/component $params$ ; copy to component variables if ($auto_retrieve$) ; is automatic retrieve turned on? call LP_RETRIEVE($params$) ; yes #include STD:FATAL_ERROR endif edit
The component contains a boolean variable $auto_retrieve$
which by default is FALSE. If the value '$auto_retrieve$=Y
' is included in the $params
string then this changes the value to TRUE and causes the local proc LP_RETRIEVE
to be performed before the edit
statement.
This mechanism removes the need for separate templates for minor changes in behaviour, and means that the chosen behaviour can be specified at run time with a passed parameter. In my development environment parameters such as this are stored in the menu database, and thus can be changed at will.
You don't. Once a component has been created from a template there is no way to change the association to a different template. The only way to achieve this is to delete the existing component, then recreate it using the desired template. A good idea is to create a copy of the original component before you delete it, then you will be able to cut and paste any useful stuff instead of having to recreate it from scratch.
If you try to amend the component manually you will probably have to amend some of the inherited trigger code, in which case you will lose all inheritance from the original template. It is not possible to switch inheritance to another template.
This can happen, for example, if you want to resequence the fields on a form and make a different field appear as LAST_FIELD. Let us suppose you have two fields on your form, one called OLD_LAST (currently designated as LAST_FIELD) and NEW_LAST (which you want to become LAST_FIELD). These are the steps you need to go through:
If you examine the bound fields you will see that LAST_FIELD has now been bound to NEW_LAST. Note that you cannot rename a field to a different entity.
Not unless you intend creating several order entry components from this one template, all with the same structure and behaviour. There is usually only one order entry component in a system, and this can/should be created from one of the other standard templates.
The simple answer is that I don't. Even I can't remember them all, and I'm the one who built them! To make life easier for everyone (especially me) I have documented them all in my UNIFACE Development Guidelines - Part 3 (Component Templates) This is a set of HTML files that can be downloaded here.
Creating a useful library of component templates is not a one-step process. In my own case this was a result of many little steps taken over a long period of time, which each new step adding a bit more to the results of the previous step. When the functionality for component templates was introduced in UNIFACE version 7 I already had a set of form templates that I had been using for several years and which I found could easily be converted into the new component templates. The simple steps which I took, and which should be well within the capabilities of any competent programmer, were as follows:
I want something that looks like program X, but dealing with so-and-so data". In other words something that has the same structure and behaviour as program X, but with different content. In this way you can copy the original component, then cut-n-paste to remove all references to the original data objects and replace them with the new data objects. This may be a bit cumbersome, but it is still quicker than building your new component completely from scratch.
So, as you can see it is not possible to create a useful set of component templates overnight. You need to have experience of developing many components so that you can recognise the different patterns that are repeated, and you need the ability to turn those patterns into objects that can be replicated very easily. UNIFACE 7 provides the functionality to create easily-replicatable components in the form of component templates, so if your organisation is not using them effectively then your developers must be lacking in either experience or ability, or perhaps even both.
In my travels I have come across several organisations which do not use component templates at all, for the simple reason that they do not know how to use them, or even what benefits can be obtained by using them. Other organisations have managed to make some use of component templates, but in an extremely limited fashion. When I tell them that my development environment contains 50 templates they laugh and say that they can get by with only 5. Well, I have tried developing with their 5 simple templates, and I can safely say that it requires so much manual intervention before a working component can be created that it is just not worth the effort. In fact, some of their own developers refuse to use their templates because they say it is far easier to copy an existing component and modify it. When I demonstrate to them that I can build applications up to 10 times faster with my 50 templates than they can with their 5 I make them laugh on the other side of their faces.
They try to tell me that my methods are no good because We don't work that way
. All I can possibly say to that is that if any organisation chooses a development methodology that is 10 times less efficient that another methodology then they must have money to burn and time to waste. In these days when RAD (Rapid Application Development) and TTM (Time To Market) are popular buzzwords, which methodology would you choose?
Templates are labour-saving devices in many walks of life, not just software development. The functionality of UNIFACE Component Templates, as introduced in version 7, turns these simple devices into powerful productivity aids. I have come across several organisations whose use of component templates has been either limited or non-existent. This is simply because they just do not know how useful they can be, or don't know how to build them and use them. Although Compuware have provided the basic tools they have not properly demonstrated their use. It is my hope that this document goes some way to help my fellow developers understand just how useful they can be, and to show them how to create their own templates so that they too can experience an increase in productivity.
In 2002 I decided to switch to a different language which was better suited to web applications, and I chose PHP. I rewrote my development framework and found it easy to implement what I felt was missing in UNIFACE - the ability to generate HTML documents from XML using XSL transformations. I also upgraded my implementation of component templates into a series of Transaction Patterns. Each of these uses its own controller script which is in fact totally reusable and can be shared by every transaction that was built from that pattern. Rather than having to create a separate XSL stylesheet for each individual user transaction I managed to create a small set of Reusable XSL Stylesheets which can cover all eventualities.
The end result is that I now have a framework for building web applications which allows me to be far more productive than I could ever be with UNIFACE. I can build database applications for the enterprise in a fraction of the time and therefore a fraction of the cost. As it is written in PHP it can also run on every platform that is supported by PHP. It is also an open source language it is also free, and due to its popularity there will never be a shortage of developers.
Tony Marston
20th December, 2000
mailto:tony@tonymarston.net
mailto:TonyMarston@hotmail.com
http://www.tonymarston.net
27th Oct 2016 | Added Postscript. |
1st Mar 2003 | Added Section 8 - Summary. |
31st Jan 2002 | Changed section 7j to point to an HTML version of my documentation on component templates. |