G-7230: Avoid declaring global variables public.
Major
Reliability
Reason
You should always declare package-level data inside the package body. You can then define "get and set" methods (functions and procedures, respectively) in the package specification to provide controlled access to that data. By doing so you can guarantee data integrity, you can change your data structure implementation, and also track access to those data structures.
Data structures (scalar variables, collections, cursors) declared in the package specification (not within any specific program) can be referenced directly by any program running in a session with EXECUTE rights to the package.
Instead, declare all package-level data in the package body and provide "get and set" methods - a function to get the value and a procedure to set the value - in the package specification. Developers then can access the data using these methods - and will automatically follow all rules you set upon data modification.
Example (bad)
CREATE OR REPLACE PACKAGE employee_api AS
co_min_increase CONSTANT types_up.sal_increase_type := 0.01;
co_max_increase CONSTANT types_up.sal_increase_type := 0.5;
g_salary_increase types_up.sal_increase_type := co_min_increase;
PROCEDURE set_salary_increase (in_increase IN types_up.sal_increase_type);
FUNCTION salary_increase RETURN types_up.sal_increase_type;
END employee_api;
/
CREATE OR REPLACE PACKAGE BODY employee_api AS
PROCEDURE set_salary_increase (in_increase IN types_up.sal_increase_type) IS
BEGIN
g_salary_increase := GREATEST(LEAST(in_increase,co_max_increase)
,co_min_increase);
END set_salary_increase;
FUNCTION salary_increase RETURN types_up.sal_increase_type IS
BEGIN
RETURN g_salary_increase;
END salary_increase;
END employee_api;
/
Example (good)
CREATE OR REPLACE PACKAGE employee_api AS
PROCEDURE set_salary_increase (in_increase IN types_up.sal_increase_type);
FUNCTION salary_increase RETURN types_up.sal_increase_type;
END employee_api;
/
CREATE OR REPLACE PACKAGE BODY employee_api AS
g_salary_increase types_up.sal_increase_type(4,2);
PROCEDURE init;
PROCEDURE set_salary_increase (in_increase IN types_up.sal_increase_type) IS
BEGIN
g_salary_increase := GREATEST(LEAST(in_increase
,constants_up.max_salary_increase())
,constants_up.min_salary_increase());
END set_salary_increase;
FUNCTION salary_increase RETURN types_up.sal_increase_type IS
BEGIN
RETURN g_salary_increase;
END salary_increase;
PROCEDURE init
IS
BEGIN
g_salary_increase := constants_up.min_salary_increase();
END init;
BEGIN
init();
END employee_api;
/