G-7180
🆓Try to keep the complexity of functions, procedures and triggers simple.
Reason
The Cyclomatic Complexity is a metric to assess the complexity of code. The metric basically determines the number of paths through the code. The more paths, the more test cases are required for full branch coverage. The Cyclomatic Complexity is categorised as follows:
| Cyclomatic Complexity | Complexity |
|---|---|
| < 11 | low |
| < 51 | medium |
| other values | high |
PL/SQL units with low complexity are typically easier to understand, test and maintain.
Examples
Non-Compliant Example
create or replace package job_util as
function max_salary(in_job_id in varchar2) return integer deterministic;
end job_util;
/
create or replace package body job_util as
function max_salary(in_job_id in varchar2) return integer deterministic is
l_result integer;
begin
case in_job_id
when 'AC_ACCOUNT' then l_result := 9000;
when 'AC_MGR' then l_result := 16000;
when 'AD_ASST' then l_result := 6000;
when 'AD_PRES' then l_result := 40000;
when 'AD_VP' then l_result := 30000;
when 'FI_ACCOUNT' then l_result := 9000;
when 'FI_MGR' then l_result := 16000;
when 'HR_REP' then l_result := 9000;
when 'IT_PROG' then l_result := 10000;
when 'MK_MAN' then l_result := 15000;
when 'MK_REP' then l_result := 9000;
when 'PR_REP' then l_result := 10500;
when 'PU_CLERK' then l_result := 5500;
when 'PU_MAN' then l_result := 15000;
when 'SA_MAN' then l_result := 20080;
when 'SA_REP' then l_result := 12008;
when 'SH_CLERK' then l_result := 5500;
when 'ST_CLERK' then l_result := 5000;
when 'ST_MAN' then l_result := 8500;
else l_result := 0;
end case;
return l_result;
end max_salary;
end job_util;
/Issues
| Line | Column | Message |
|---|---|---|
| 8 | 4 |
This example has a complexity of 20. Why? Each when clause in the case statement makes the code more complex. The else branch does not add to the complexity.
In this case, the function is easy to read. The case statement (switch statement in other languages) is one of the criticisms of this metric. There is no perfect metric. But the technical solution is simple.
Compliant Solution - ★★★★☆
create or replace package job_util as
function max_salary(in_job_id in varchar2) return integer deterministic;
end job_util;
/
create or replace package body job_util as
function max_salary(in_job_id in varchar2) return integer deterministic is
begin
return case in_job_id
when 'AC_ACCOUNT' then 9000
when 'AC_MGR' then 16000
when 'AD_ASST' then 6000
when 'AD_PRES' then 40000
when 'AD_VP' then 30000
when 'FI_ACCOUNT' then 9000
when 'FI_MGR' then 16000
when 'HR_REP' then 9000
when 'IT_PROG' then 10000
when 'MK_MAN' then 15000
when 'MK_REP' then 9000
when 'PR_REP' then 10500
when 'PU_CLERK' then 5500
when 'PU_MAN' then 15000
when 'SA_MAN' then 20080
when 'SA_REP' then 12008
when 'SH_CLERK' then 5500
when 'ST_CLERK' then 5000
when 'ST_MAN' then 8500
else 0
end;
end max_salary;
end job_util;
/This solution has a Cyclomatic Complexity of 1. Why? Because we use a case expression in the return statement. There is no additional path through the PL/SQL function.
Compliant Solution - ★★★★★
create or replace package job_util as
function max_salary(in_job_id in varchar2) return integer result_cache;
end job_util;
/
create or replace package body job_util as
function max_salary(in_job_id in varchar2) return integer result_cache is
l_result integer;
begin
select max_salary into l_result
from jobs
where job_id = in_job_id;
return l_result;
exception
when no_data_found then
return 0;
when too_many_rows then
raise; -- data inconsistency, we cannot determine max salary
end max_salary;
end job_util;
/The Cyclomatic Complexity is 3. Why? Because each exception handler adds to the complexity.
This solution is superior to the previous one, because it queries the table content without compromising the performance, thanks to the result_cache clause. There aren't many values, so it doesn't take up much memory. However, when the underlying data is changed, which should not happen often, you need to call the sys.dbms_result_cache.invalidate('HR', 'job_util') procedure to ensure that the latest changes are considered.
Parameters
Use parameters to customize the rule to your needs.
| Parameter | Description | Default Value |
|---|---|---|
| MaxCyclomaticComplexity | Maximum Cyclomatic Complexity of a function, procedure and trigger. | 10 |