G-7230: Avoid declaring global variables public.
Reason
You should always declare package-level data (non-constants) 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.
For package-level constants, consider whether the constant should be public and usable from other code, or if only relevant for code within the package. If the latter, declare the constant in the package body. If the former, it is typically good practice to place the constants in a package specification that only holds constants.
Example (bad)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | 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; -- NOSONAR: non-deterministic
end employee_api;
/
create or replace package body employee_api as
procedure set_salary_increase(in_increase in types_up.sal_increase_type) is
co_increase constant types_up.sal_increase_type := in_increase;
begin
g_salary_increase := greatest(least(co_increase,co_max_increase)
,co_min_increase);
end set_salary_increase;
function salary_increase return types_up.sal_increase_type is -- NOSONAR: non-deterministic
begin
return g_salary_increase;
end salary_increase;
end employee_api;
/
|
Example (good)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 | create or replace package constants_up as
co_min_increase constant types_up.sal_increase_type := 0.01;
co_max_increase constant types_up.sal_increase_type := 0.5;
end constants_up;
/
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; -- NOSONAR: non-deterministic
end employee_api;
/
create or replace package body employee_api as
g_salary_increase types_up.sal_increase_type;
procedure init;
procedure set_salary_increase(in_increase in types_up.sal_increase_type) is
co_increase constant types_up.sal_increase_type := in_increase;
begin
g_salary_increase := greatest(least(co_increase,constants_up.co_max_increase)
,constants_up.co_min_increase);
end set_salary_increase;
function salary_increase return types_up.sal_increase_type is -- NOSONAR: non-deterministic
begin
return g_salary_increase;
end salary_increase;
procedure init
is
begin
g_salary_increase := constants_up.co_min_increase;
end init;
begin
init();
end employee_api;
/
|