450 likes | 600 Views
CS278 Chapter7. Where to Put the Code in Forms?. CS278 Chapter7. disable_all_buttons.txt Sample of generic coding used to loop through a block and disable all buttons. Disable_all_buttons.fmb. Standards for code Placement. Do you use packages or stand-alone program units?
E N D
CS278 Chapter7 Where to Put the Code in Forms?
CS278 Chapter7 disable_all_buttons.txt Sample of generic coding used to loop through a block and disable all buttons. Disable_all_buttons.fmb
Standards for code Placement Do you use packages or stand-alone program units? Which is better, database code or Forms code? How do you handle Forms functions such as EXIT_FORM? Do you write the code in a trigger or in a program unit? Does form-side code belong in the form or in a library? Which library do you write the code into?
Standards for code Placement • If you use object library code, should you copy or subclass it • Do you write the trigger on the form, block, or item level?
Packages or Stand-Alone Benefits of Packages • Organization of code • Object orientation • Publicly available objects • Publicly restricted source
Packages or Stand-Alone Benefits of Packages Since you place all documentation about the intent and usage of the package code in the specification, developers using the packages only need to know the name of the package. The header comments can guide developers on which part of the package to use. • Increase performance
Drawbacks of Packages • Extra development steps • Less access granularity • Additional object to handle Using packages requires that you create and follow standards for another type of object (packages) in addition to functions and procedures. This means your developers will need to think about which package is the appropriate location for their new procedure or function. • Additional development overhead
Database Server or Form? • If you decide to write database code, the database server will execute the code.
Database Server or Form? • If you decide to write the code on the Form side, there are two possibilities for where the code will be executed. • In the Web environment, forms will be located on the application server • The Forms code will execute there, not in the client browser
Database Server or Form? • If you are deploying forms in a client/server environment • The forms will be located on the client side • All Forms code will execute on the client machine
Database Server or Form? • Placing code on the database server will cause it to do extra processing. Server hardware can be pretty efficient.
Database Server or Form? • Network bandwidth ( the amount of data that the network can handle simultaneously) is a key issue with networks. • The commodity is usually at a premium, and upgrading a net work may be more difficult or costly than upgrading the server hardware. • Therefore, a key determinant in placing your Forms code will be how you can use as little of the network as possible.
How to split the Forms Code • Here is an example of code you might write in the PRE-INSERT trigger of an EMP block in the form • There is nothing wrong with this code, but Forms would send the cursor declaration and all statements to the database for each row
How to split the Forms Code DECLARE v_found BOOLEAN; CURSOR c_empseq /*(parameters)*/ IS SELECT empno_seq.nextval FROM dual; BEGIN OPEN c_empseq /*(parameters)*/; FETCH c_empseq INTO :emp.empno; v_found := c_empseq%FOUND; CLOSE c_empseq; END;
How to split the Forms Code Better strategy is to write a code as part of the SPMTS_EMP package in the database FUNCTION next_empno RETURN NUMBER IS v_found BOOLEAN; v_empno NUMBER; CURSOR c_empseq /*(parameters)*/ IS SELECT empno_seq.nextval FROM dual; BEGIN OPEN c_empseq FETCH c_empseq INTO v_empno; v_found := c_empseq%FOUND; CLOSE c_empseq; RETURN (v_empno); END;
How to split the Forms Code The PRE_INSERT trigger code would consist of only the following: :emp.empno := spmts_emp.next_empno;
How to split the Forms Code • Other Database Code Sources • Data Triggers • Blocks Based on Views • Blocks Based on procedure
Handling Forms Functions • How to handle Forms Functions • The Forms Functions standard • You want to ensure that the same code you write to call a Forms function will be activated from the corresponding menu item, canvas button, or key press. There are a few steps involved with this: 1. Write a form-level key-trigger for the Forms function that calls procedure in the F_TOOLBAR library package.
Handling Forms Functions 2.Write menu item code if there is a corresponding menu item that issues a DO_KEY call with the function name as the parameter, for example, ‘DO_KEY (‘COMMIT_FORM’);”. If you define that the menu item also displays as a menu toolbar button, the button will use the same code as the menu item. 3.Write WHEN-BUTTON-PRESSED code on the canvas button (if one exists) with the same text as the menu item code.
Form-Level triggers • Component Effect • Key press (CTRL-Q on the PC) Fires the KEY-EXIT trigger, which calls the generic library package procedure, F_TOOLBAR.EXITFORM • Menu item and associated menu The code is “DO_KEY Toolbar button (File-Exit) EXIT_FORM’);”. This fires the KEY_EXIT trigger • Canvas Button The same code as the menu item. • F_TOOLBAR.EXIT_FORM This procedure does everything you need to do before exiting (checks uncommitted records, automatically commits, asks the user for confirmation on the exit, and so on). It then exits the form.
The Trigger standard • This means that if you decide to use the program node in the Object Navigator to store the code you call in triggers, you will have two places to look for the code. One is the trigger, to see the actual code.
Form or Library • The Library standard • Assume that all code you write is useful in other forms. After you write the code, step back and think if it is truly specific to the form you are working on. If you can’t make a good case for not generalizing it, make it generic, test the generic version, and move it to a library.
Generic Library Code Example • The following shows a generic procedure you would write to disable all items in a block. The procedure would be located in the F_BLOCK package of the library PROCEDURE disable_all_buttons( P-block-name in VARCHAR2) IS V-curr-item VARCHAR (30); V_block-item VARCAHR (61);
Generic Library Code Example BEGIN --validate the block name passed in IF id_null (find_block(p_block_name)) THEN f_alert.ok (Error: The block name passed in (‘ || p_block-name||’) is not valid. Contact the ‘ || ‘administrator.’, f_alert.g_fail); ELSE v_curr_item:=get_block_property (p_block_name, FIRST_ITEM); -- -- loop through all items in the block WHILE v_curr_item is NOT NULL
PROCEDURE disable_all_buttons(continue) LOOP V_block_item := p_block_name || ‘.’ || v_curr_item; --turn off the enabled property for the buttons IF get_item_ property (v_block_item, ITEM_TYPE) =‘BUTTON’ THEN set_item_property (v-block-item, ENABLED, PROPERTY_FALSE ); END IF; v_curr_item := get_item_property (v_block_item, NEXTITEM); END LOOP; END IF; END;
Which library • A generic library As you create more and more Forms applications, you will create a toolbox of code that helps with normal chores. Appendix A describes an example of this type of library. The package in this library are written to support specific objects, but are written totally generically so that they can be used for any project in the future. For example, the F_MENU package contains procedures to hide, show, enable, and disable a menu item.
NoteThe Specific Library Standard • Place the code in the generic library if it is truly nonspecific for any database. • Use the application library if it contains references to database code in a specific application. • Place the code in the form-specific library if it only be used by one form.
NoteThe specific Library Standard • You can divide the generic library into two files: • one library file for nondatabase actions and • The nondatabase library would contain code to manipulate Forms objects (such as items, blocks, canvases and windows). • one library file for database actions. • The database library would contain code to handle generic routines that were non-application specific (such as security, queries to a standard lookup table, generic routines to load a sequence value, and so on).
Which library • An application-specific library • This library contains code that calls database packages for a particular application, For example, a packaged function that you might include in this library would be one that performs lookups on a particular reference table to derive a description from an ID. This function would call a database function that would query the table based on an ID and return the value of the description from the PROJECT table if it were passed the project ID. The Forms library would call this function and manipulate the results in some way.
Which library • A form-specific library • There may be code that is just too specific to make it generic to serve many forms and applications. You might want to include this code in a form-specific library and attach it to the single form.
Subclass or Copy from the Object Library? • As mentioned earlier, the first step when writing code is to determine if there is already code that can do at least part of the work. Someone may have already written a function to translate an ID to a name, for example, and you might be able to sue this as is or incorporate it into your new code. Code reuse is an important goal in very project. The keys to finding an existing routine are naming conventions and documentation.
Subclass or Copy from the Object Library • Note The object Library standard • Avoid storing program units in the object library. If you need form-level triggers that exits in an object library, subclass the triggers.
Subclass or Copy from the Object Library • Subclassing Code from Object Libraries While it is a simple matter to create that trigger in each form, it is even easier to subclass the trigger from the object library. In this way, the triggers will all have the same code, and if you do not change the code in any particular form, changing the object library will cause all forms to change the next time they are recompiled.
Subclassing Code from Object Libraries • Subclassing also maintains a link between the form and its source, in this case, an object library. The link establishes a commonality between all forms that use the same source.
Subclassing Code from Object Libraries • Subclassing also allows changes. You can override the code in a subclassed program unit. If you do that, the Property Palette will show a broken inheritance symbol ( an “x” instead of an arrow symbol) by the Trigger Text property to indicate that the text is overridden , as Figure 7-1 shows(see page 202).
Which Level of trigger You also need to decide at what level to place the trigger- form, block, or item. Figure 7-2(see the page 203) shows the location of these triggers in the Object Navigator. • Note The Trigger-Level Standard Write block-level triggers for item and block events. This will greatly reduce the number of places you need to look for Forms code.
Which Level of Trigger For example, the following is a procedure contained in the F_TOOLBAR package. It is called by the WHEN-BUTTON-PRESSED trigger written on the block level. The buttons in the block are named with DO_KEY functions. For example, the Exit, save, and New Record buttons are called EXIT-FORM, COMMIT_FORM, and CREATE_RECORD, respectively.
Execution Hierarchy • You can define a trigger at a higher level and then code the same trigger on a lower level- for example, on an item WHEN-BUTTON-PRESSED when there is already one on the block level. The lower-level code takes precedence unless you set the Execution Hierarchy property on the lower trigger’s properties to “Before” or “After”.
Execution Hierarchy • As another example of a high-level trigger, you can create a single WHEN-VALIDATE-ITEM trigger for all items in the form that calls a single packaged procedure. This procedure checks the :SYSTEM.TRIGGER_ITEM and performs a validation based on that.
The options • Form level For example, if your form included blocks for EMP and DEPT, the logic in a form-level WHEN-VALIDATE-ITEM trigger could check the: SYSTEM.TRIGGER_BLOCK to see if it was EMP or DEPT and call a separate procedure for each to perform the validation on items in the block.
The options • Block level Write triggers on the block level to handle specific block and items actions. Use a single call to a packaged procedure in the trigger text. The procedure checks which item fired the trigger (using :SYSTEM.TRIGGER_ITEM) and calls other procedures to perform the action (like checking the item contents is a WHEN-NEW-ITEM-INSTANCE trigger). Forms events such as WHEN-NEW-FORM-INSTANCE would still be written on the form level.
The options • Item level Write triggers at the lowest level possible. If you need to validate an item, use the WHEN-VALIDATE-ITEM trigger on the item level. If you need to add a value to an INSERT statement, write a PRE-INSERT trigger on the block level. If you need to check which window the user closed, code a WHEN-WINDOW-CLOSED trigger on the form level. As in other standards, you use a single call to packaged procedure as the trigger text.
The Development Process • The normal path for placing code is to write the code (database or form based) in the form trigger or package without worrying about where you will eventually place it. See the page 29 • Genericizing Code for the Library • If you decide that a package you have developed belongs in a library, you just need to drag and drop it into the library in the Object Navigator.
The Development Process • Copy (‘100’, ‘imp.empno’); • To use the value of :emp.EMPNO in an expression, follow this syntax: • IF name_in (‘EMP.EMPNO’)=‘100’ • Both COPY and NAME_IN work only on character values. If your items are number or date data types, you must convert the value using the TO-CHAR, TO_DATE, or TO_number FUNCTION. For example:
The Development Process • For example: DECLARE v_today DATE := SYSDATE; BEGIN copy (to_char (v_today), :emp.hire_date); IF TO_NUMBER (name_in ( ‘EMP.SALARY’)) > 1000 THEN …