Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 50 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
50
Dung lượng
211,69 KB
Nội dung
total_type IN VARCHAR2 ALL or NET
);
/*
|| For every employee hired more than five years ago,
|| give them a bonus and send them an e-mail notification.
*/
FOR emp_rec IN emp_cur (ADD_MONTHS (SYSDATE, -60))
LOOP
apply_bonus (emp_rec.employee_id);
send_notification (emp_rec.employee_id);
END LOOP;
IF :SYSTEM.FORM_STATUS = 'CHANGED' THEN COMMIT; END IF;
FUNCTION display_user
(user_id IN NUMBER /* Must be valid ID */, user_type
IN VARCHAR2)
The first example uses the single-line comment syntax to include endline descriptions for each
parameter in the procedure specification. The second example uses a multiline comment to explain
the purpose of the FOR loop. The third example uses the double-hyphen to comment out a whole line
of code. The last example embeds a comment in the middle of a line of code using the block
comment syntax.
These two types of comments offer the developer flexibility in how to provide inline documentation.
The rest of this section offers guidelines for writing effective comments in your PL/SQL programs.
3.6.1 Comment As You Code
It is very difficult to make time to document your code after you have finished writing your program.
Psychologically, you want to (and often need to) move on to the next programming challenge after
you get a program working.
You may also have a harder time writing your comments once you have put some distance between
your brain cells and those lines of code. Why exactly did you write the loop that way? Where
precisely is the value of that global variable set? Unless you have total recall, post-development
documentation can be a real challenge.
The last and perhaps most important reason to write your comments as you write your code is that the
resulting code will have fewer bugs and (independent of the comments themselves) be easier to
understand.
When you write a comment you (theoretically) explain what your code is meant to accomplish. If you
find it difficult to come up with that explanation, there is a good chance that you lack a full
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
understanding of what the program does or should do.
The effort that you make to come up with the right comment will certainly improve your
comprehension, and may also result in code correction. In this sense, good inline documentation can
be as beneficial as a review of your code by a peer. In both cases, the explanation will reveal
important information about your program.
3.6.2 Explain the Why Not the How of Your Program
What do you think of the comments in the following Oracle Forms trigger code?
If the total compensation is more than the maximum
IF :employee.total_comp > maximum_salary
THEN
Inform the user of the problem.
MESSAGE ('Total compensation exceeds maximum. Please
re-enter!');
Reset the counter to zero.
:employee.comp_counter := 0;
Raise the exception to stop trigger processing.
RAISE FORM_TRIGGER_FAILURE;
END IF;
None of these comments add anything to the comprehension of the code. Each comment simply
restates the line of code, which in most cases is self-explanatory.
Avoid adding comments simply so that you can say, "Yes, I documented my code!" Rely as much as
possible on the structure and layout of the code itself to express the meaning of the program. Reserve
your comments to explain the Why of your code: What business rule is it meant to implement? Why
did you need to implement a certain requirement in a certain way?
In addition, use comments to translate internal, computer-language terminology into something
meaningful for the application. Suppose you are using Oracle Forms GLOBAL variables to keep
track of a list of names entered. Does the following comment explain the purpose of the code or
simply restate what the code is doing?
/* Set the number of elements to zero. */
:GLOBAL.num_elements := 0;
Once again, the comment adds no value. Does the next comment offer additional information?
/* Empty the list of names. */
:GLOBAL.num_elements := 0;
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
This comment actually explains the purpose of the assignment of the global to zero. By setting the
number of elements to zero, I will have effectively emptied the list. This comment has translated the
"computer lingo" into a description of the effect of the statement. Of course, you would be even
better off hiding the fact that you use this particular global variable to empty a list and instead build a
procedure as follows:
PROCEDURE empty_list IS
BEGIN
:GLOBAL.num_elements := 0;
END;
Then to empty a list you would not need any comment at all. You could simply include the statement:
empty_list;
and the meaning would be perfectly clear.
3.6.3 Make Comments Easy to Enter and Maintain
You shouldn't spend a lot of time formatting your comments. You need to develop a style that is
clean and easy to read, but also easy to maintain. When you have to change a comment, you shouldn't
have to reformat every line in the comment. Lots of fancy formatting is a good indication that you
have a high-maintenance documentation style. The following block comment is a maintenance
nightmare:
/*
===========================================================
| Parameter Description
|
|
|
| company_id The primary key to company
|
| start_date Start date used for date range
|
| end_date End date for date range
|
===========================================================
*/
The right-justified vertical lines and column formatting for the parameters require way too much
effort to enter and maintain. What happens if you add a parameter with a very long name? What if
you need to write a longer description? A simpler and more maintainable version of this comment
might be:
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
/*
===========================================================
| Parameter - Description
|
| company_id - The primary key to company
| start_date - Start date used for date range
| end_date - End date for date range
===========================================================
*/
I like to use the following format for my block comments:
/*
|| I put the slash-asterisk that starts the comment on a
line all by
|| itself. Then I start each line in the comment block
with a double
|| vertical bar to highlight the presence of the comment.
Finally,
|| I place the asterisk-slash on a line all by itself.
*/
On the negative side, the vertical bars have to be erased whenever I reformat the lines, but that isn't
too much of an effort. On the positive side, those vertical bars make it very easy for a programmer
who is scanning the left side of the code to pick out the comments.
I put the comment markers on their own lines to increase the whitespace in my program and set off
the comment. That way I can avoid "heavy" horizontal lines full of delimiters, such as asterisks or
dashes, and avoid having to match the longest line in the comment.
3.6.4 Maintain Indentation
Inline commentary should reinforce the indentation and therefore the logical structure of the program.
For example, it is very easy to find the comments in the make_array procedures shown below. I do
not use any double-hyphens, so the slash-asterisk sequences stand out nicely. In addition, all
comments start in the first column, so I can easily scan down the left-hand side of the program and
pick out the documentation:
PROCEDURE make_array (num_rows_in IN INTEGER)
/* Create an array of specified numbers of rows */
IS
/* Handles to Oracle Forms structures */
col_id GROUPCOLUMN;
rg_id RECORDGROUP;
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
BEGIN
/* Create new record group and column */
rg_id := CREATE_GROUP ('array');
col_id := ADD_GROUP_COLUMN ('col');
/*
|| Use a loop to create the specified number of rows and
|| set the value in each cell.
*/
FOR row_index IN 1 num_rows_in
LOOP
/* Create a row at the end of the group to accept data */
ADD_GROUP_ROW (return_value, END_OF_GROUP);
FOR col_index IN 1 num_columns_in
LOOP
/* Set the initial value in the cell */
SET_GROUP_NUMBER_CELL (col_id, row_index, 0);
END LOOP;
END LOOP;
END;
The problem with these comments is precisely that they do all start in the first column, regardless of
the code they describe. The most glaring example of this formatting "disconnect" comes in the inner
loop, repeated below:
FOR col_index IN 1 num_columns_in
LOOP
/* Set the initial value in the cell */
SET_GROUP_NUMBER_CELL (col_id, row_index, 0);
END LOOP;
Your eye follows the three-space indentation very smoothly into the loop and then you are forced to
move all the way to the left to pick up the comment. This format disrupts your reading of the code
and therefore its readability. The code loses some of its ability to communicate the logical flow "at a
glance," because the physical sense of indentation as logical flow is marred by the comments. Finally,
you may end up writing full-line comments which are much longer than the code they appear next to,
further distorting the code.
Your comments should always be indented at the same level as the code which they describe.
Assuming the comments come before the code itself, those lines of descriptive text will initiate the
indentation at that logical level, which will also reinforce that structure. The make_array procedure,
properly indented, is shown below:
PROCEDURE make_array (num_rows_in IN INTEGER)
/* Create an array of specified numbers of rows */
IS
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
/* Handles to Oracle Forms structures */
col_id GROUPCOLUMN;
rg_id RECORDGROUP;
BEGIN
/* Create new record group and column */
rg_id := CREATE_GROUP ('array');
col_id := ADD_GROUP_COLUMN ('col');
/*
|| Use a loop to create the specified number of rows
and
|| set the value in each cell.
*/
FOR row_index IN 1 num_rows_in
LOOP
/* Create a row at the end of the group to accept
data */
ADD_GROUP_ROW (return_value, END_OF_GROUP);
FOR col_index IN 1 num_columns_in
LOOP
/* Set the initial value in the cell */
SET_GROUP_NUMBER_CELL (col_id, row_index, 0);
END LOOP;
END LOOP;
END;
END LOOP;
END LOOP;
END;
3.6.5 Comment Declaration Statements
I propose the following simple rule for documenting declaration statements:
Provide a comment for each and every declaration.
Does that sound excessive? Well, I must admit that I do not follow this guideline at all times, but I
bet people who read my code wish I had. The declaration of a variable which seems to me to be
perfectly clear may be a source of abiding confusion for others. Like many other people, I still have
difficulty understanding that what is obvious to me is not necessarily obvious to someone else.
Consider the declaration section in the next example. The commenting style is inconsistent. I use
double-hyphens for a two-line comment; then I use the standard block format to provide information
about three variables all at once. I provide comments for some variables, but not for others. It's hard
to make sense of the various declaration statements:
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
DECLARE
Assume a maximum string length of 1000 for a line
of text.
text_line VARCHAR2 (1000);
len_text NUMBER;
/*
|| Variables used to keep track of string scan:
|| atomic_count - running count of atomics scanned.
|| still_scanning - Boolean variable controls WHILE
loop.
*/
atomic_count NUMBER := 1;
still_scanning BOOLEAN;
BEGIN
Let's recast this declaration section using my proposed guideline: a comment for each declaration
statement. In the result shown below, the declaration section is now longer than the first version, but
it uses whitespace more effectively. Each declaration has its own comment, set off by a blank line if a
single-line comment:
DECLARE
/* Assume a maximum string length of 1000 for a line
of text. */
text_line VARCHAR2 (1000);
/* Calculate length of string at time of declaration */
len_string NUMBER;
/* Running count of number of atomics scanned */
atomic_count NUMBER := 1;
/* Boolean variable that controls WHILE loop */
still_scanning BOOLEAN ;
BEGIN
Previous: 3.5 Formatting
Packages
Oracle PL/SQL
Programming, 2nd Edition
Next: 3.7 Documenting the
Entire Package
3.5 Formatting Packages
Book Index
3.7 Documenting the Entire
Package
The Oracle Library
Navigation
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Copyright (c) 2000 O'Reilly & Associates. All rights reserved.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Previous: 3.4 Formatting
PL/SQL Blocks
Chapter 3
Effective Coding Style
Next: 3.6 Using Comments
Effectively
3.5 Formatting Packages
A package is a collection of related objects, including variables, TYPE statements (to define
structures for records, tables, and cursors), exceptions, and modules. We have already covered
structuring all the different objects which make up a package. Now, let's take a look at how to
structure the package itself.
A package has both a specification and a body. The package specification contains the declarations or
definitions of all those objects that are visible outside of the package the public objects. This means
that the objects can be accessed by any account that has been granted EXECUTE authority on the
package. The package body contains the implementation of all cursors and modules defined in the
specification, and the additional declaration and implementation of all other package objects. If an
object, such as a string variable, is declared in the body and not in the package, then any module in
the package can reference that variable, but no program outside of the package can see it. That
variable is invisible or private to the package.
The first point to make about the package structure is that all objects declared in the specification
exist within the context of the package and so should be indented from the PACKAGE statement
itself, as shown below:
PACKAGE rg_select
IS
list_name VARCHAR2(60);
PROCEDURE init_list
(item_name_in IN VARCHAR2,
fill_action_in IN VARCHAR2 := 'IMMEDIATE');
PROCEDURE delete_list;
PROCEDURE clear_list;
END rg_select;
The same is true for the package body. I suggest that you always include a label for the END
statement in a package so that you can easily connect up that END with the end of the package as a
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
whole. I place the IS keyword on a new line to set off the first declaration in the package from the
name of the package. You could always use a blank line. Notice that I use blank lines in rg_select to
segregate different modules which are related by function. I think that logical grouping is always
preferable to an arbitrary grouping such as alphabetical order.
The other important element in formatting a package is the order in which objects are listed in the
package. I generally list objects in the order of complexity of their structure, as follows:
● Scalar variables, such as a VARCHAR2 declaration
● Complex datatypes, such as records and tables
● Database-related declarations, such as cursors
● Named exceptions
● Modules (procedures and functions)
As with simple variable declarations, I sometimes have many different but related objects in my
package. If so, I might group those types of objects together. But within that grouping, I still follow
the above order.
Previous: 3.4 Formatting
PL/SQL Blocks
Oracle PL/SQL
Programming, 2nd Edition
Next: 3.6 Using Comments
Effectively
3.4 Formatting PL/SQL
Blocks
Book Index
3.6 Using Comments
Effectively
The Oracle Library
Navigation
Copyright (c) 2000 O'Reilly & Associates. All rights reserved.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
[...]... Code Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Previous: 2.6 The PRAGMA Keyword 2.6 The PRAGMA Keyword Oracle PL/SQL Programming, 2nd Edition Book Index Next: 3 Effective Coding Style 3 Effective Coding Style The Oracle Library Navigation Copyright (c) 2000 O'Reilly & Associates All rights reserved Please purchase PDF Split-Merge on www.verypdf.com to remove this... purchase PDF Split-Merge on www.verypdf.com to remove this watermark DECLARE no_such_sequence EXCEPTION; PRAGMA EXCEPTION_INIT (no_such_sequence, -2289); BEGIN END; Previous: 2.5 Comments 2.5 Comments Oracle PL/SQL Programming, 2nd Edition Book Index Next: 2.7 Block Structure 2.7 Block Structure The Oracle Library Navigation Copyright (c) 2000 O'Reilly & Associates All rights reserved Please purchase PDF. .. 3.1 Fundamentals of Effective Layout 3.1 Fundamentals of Effective Layout Oracle PL/SQL Programming, 2nd Edition Book Index Next: 3.3 Formatting Control Structures 3.3 Formatting Control Structures The Oracle Library Navigation Copyright (c) 2000 O'Reilly & Associates All rights reserved Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Previous: 2.7 Block Structure Chapter... budgeted, next_year_plan); Previous: 2.7 Block Structure 2.7 Block Structure Oracle PL/SQL Programming, 2nd Edition Book Index Next: 3.2 Formatting SQL Statements 3.2 Formatting SQL Statements The Oracle Library Navigation Copyright (c) 2000 O'Reilly & Associates All rights reserved Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Previous: 2.6 The PRAGMA Keyword Chapter 2... section Previous: 3.3 Formatting Control Structures 3.3 Formatting Control Structures Oracle PL/SQL Programming, 2nd Edition Book Index Next: 3.5 Formatting Packages 3.5 Formatting Packages The Oracle Library Navigation Copyright (c) 2000 O'Reilly & Associates All rights reserved Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Previous: 3.2 Formatting SQL Statements Chapter... first) Previous: 3.2 Formatting SQL Statements 3.2 Formatting SQL Statements Oracle PL/SQL Programming, 2nd Edition Book Index Next: 3.4 Formatting PL/ SQL Blocks 3.4 Formatting PL/SQL Blocks The Oracle Library Navigation Copyright (c) 2000 O'Reilly & Associates All rights reserved Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Previous: 3.1 Fundamentals of Effective Layout... GROUP BY HAVING AND OR ORDER BY Here are some examples of this format in use: SELECT FROM WHERE AND last_name, first_name employee department_id = 15 hire_date < SYSDATE; Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark DELETE DELETE FROM WHERE SELECT FROM GROUP ORDER department_id, SUM (salary) AS total_salary employee BY department_id BY total_salary DESC; INSERT INTO employee... when you are coding that sql from within a pl/ sql block You may not, on the other hand, embed white space in sql statements you are executing from the sql*Plus command line Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Use meaningful abbreviations for table and column aliases It drives me crazy when a query has a six-table join and the tables have been assigned aliases... IF; IF THEN executable_statements; ELSE else_executable_statements; END IF; IF THEN executable_statements ELSE else_executable_statements; END IF; Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark IF 1 THEN executable_statements1; ELSEIF THEN executable_statements2; ELSEIF THEN executable_statementsN; IF 1... dependencies, etc.) without being pulled under I discuss the elements of an effective coding style in the PL/SQL language at this juncture, before we get to any code, for two reasons: Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark q q To drive home the point that if you are going to adopt a coding style which will improve the readability and maintainability of your application, you . */
IS
/* Handles to Oracle Forms structures */
col_id GROUPCOLUMN;
rg_id RECORDGROUP;
Please purchase PDF Split-Merge on www.verypdf.com to remove this. numbers of rows */
IS
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
/* Handles to Oracle Forms structures */
col_id GROUPCOLUMN;