• Aucun résultat trouvé

PKG-04: Implement flexible, user-adjustable functionality using package state toggles and

Dans le document Preface Oracle PL/SQL Best Practices (Page 159-163)

related techniques.

As you rely more and more on packages to offer functionality to programmers on your team or in your company, you want to design those packages to be flexible and responsive to varying user needs.

You certainly don't want programmers going into the package bodies and changing implementations. You also don't want them making copies of your code and then producing their own variations.

Instead, add programs to the package specification that allow developers to modify (within certain accepted pathways) the behavior of your package to fit their varying requirements. These programs might turn on/off certain features ("toggles") or might set internal package values.

The most important feature of these programs is that they allow the package to change its behavior without having to change the source code.

Example

I have decided to build a check-out package that allows librarians to check books out of their collection. The default rule is that a person can have a maximum of 10 books checked out at any time. I can write my package to hard-code that rule as follows:

CREATE OR REPLACE PACKAGE BODY checkout_pkg IS

c_max_allowed CONSTANT PLS_INTEGER := 10;

FUNCTION can_check_out (

borrower_id IN borrower.id%TYPE,

RETURN (l_checked_out < c_max_allowed AND l_book_is_available);

END can_check_out;

...

But this approach doesn't let a librarian override this rule, which he might need to do with a professional researcher, for example. A much better approach is to offer, in the specification, a way to change the checkout limits, within reasonable boundaries.

Here's a modified package specification:

CREATE OR REPLACE PACKAGE BODY checkout_pkg IS

PROCEDURE set_checkout_limit (count_in IN PLS_INTEGER);

FUNCTION checkout_limit RETURN PLS_INTEGER;

FUNCTION can_check_out (

borrower_id IN borrower.id%TYPE, isbn_in IN book.isn%TYPE)

RETURN BOOLEAN;

The implementation of this override is simple: change the constant to a variable and modify it from within set_checkout_limit:

CREATE OR REPLACE PACKAGE BODY checkout_pkg IS

g_max_allowed PLS_INTEGER := 10;

PROCEDURE set_checkout_limit ( count_in IN PLS_INTEGER) IS BEGIN

g_max_allowed :=

LEAST (GREATEST (count_in, 1), 20);

END set_checkout_limit;

FUNCTION checkout_limit RETURN PLS_INTEGER IS

BEGIN

RETURN g_max_allowed;

END checkout_limit;

Another example of this technique is the on/off switch you build to implement a

"window" in a package (see [PKG-05: Build trace "windows" into your packages using standardized programs.]).

Benefits

The increased flexibility makes it more likely that the package is used and reused.

Code reuse generally improves the quality of your application and reduces the resources needed to test and maintain the code base.

You can often layer toggles and other setting programs on top of an existing package;

it doesn't all have to be figured out in advance.

Challenges

From a design standpoint, you can implement this flexibility either as a package-level setting or by adding another parameter to your programs. Choose the package-level approach if the setting or switch is a preference the user will want to apply to the overall package behavior, and not just a single program. You can even build a small GUI applet that allows a developer to easily change these settings.

Resources

watch.pkg : This package, used to trace program execution, offers the ability to switch output between the screen and database pipes.

PKG-05: Build trace "windows" into your packages using standardized programs.

On the one hand, it's very helpful to use packages to hide complexity. On the other hand, it's often the case that users can be greatly aided by being able to look inside packages and watch what's happening.

You can easily build a "read-only" window into a package. Users can open the window when and if he wants to, watch what the package is doing (or at least what the author of the package claims the package is doing), and then shut the window when that information isn't needed.

To build a window, you will need to:

• Add tracing code inside the package body.

• Supply an on-off switch in the specification so that users can open and close the window.

Example

My overdue fines package allows a user to set the daily fine rate, as shown by this partial package body:

CREATE OR REPLACE PACKAGE BODY overdue_pkg IS

g_daily_fine NUMBER := .10;

PROCEDURE set_daily_fine (fine_in IN NUMBER) IS BEGIN

g_daily_fine :=

GREATEST (LEAST (fine_in, .25), .05);

END set_daily_fine;

...

I now want to add a trace to this package so that a user of overdue_pkg can see what the daily fine is being set to when her application runs. First, I add an on-off switch to the package specification and body:

CREATE OR REPLACE PACKAGE overdue_pkg IS

... other elements in package

PROCEDURE trc;

PROCEDURE notrc;

FUNCTION tracing RETURN BOOLEAN;

END overdue_pkg;

Then, I add my trace to the set_daily_ fine procedure:

PROCEDURE set_daily_fine (fine_in IN NUMBER) IS

BEGIN

IF tracing THEN

watch.action ('set_daily_fine', fine_in);

END IF;

g_daily_fine :=

GREATEST (LEAST (fine_in, .25), .05);

END set_daily_fine;

Rather than call DBMS_OUTPUT.PUT_LINE or even my enhanced pl procedure, notice that I call watch.action. The watch package is a more robust tracing mechanism.

Among other features, it allows you to direct output to a database pipe, bypassing the buffer limitations of DBMS_OUTPUT.

Now, when I want to watch what is happening inside my overdue package, I simply turn on trace for my session before I run my application code:

SQL> exec overdue_pkg.trc SQL> exec library_test

Benefits

This "read-only" window into a package can help you ensure that you're using the package properly or allow you to confirm that the data you're passing into the package is correct. Such windows increase your confidence in the package and allow you to use it more effectively. The on-off switch for the window is based on the "get and set" technique discussed in [DAT-15: Expose package globals using "get and set"

modules.].

Windows are easy to add to your package after you have written the base code. Just add an on-off switch and put an IF statement inside the appropriate module.

Challenges

If you add trace calls, add them comprehensively, taking into account the

perspective and needs of the user. Looking through a smoky window may be more confusing than not being able to see at all.

It's worth coming up with a plan for where and when you will insert trace calls in your code. Take into account possible impact on performance and readability. You may also find yourself adding trace logic iteratively as you work on different sections of code, in order to watch several computations or logic paths.

Dans le document Preface Oracle PL/SQL Best Practices (Page 159-163)

Documents relatifs