09 November 2011

Coincidental Cohesion in PL/SQL


Cohesion is a measure(or can be viewed as a software metric) of conectivity among routines,functions or elements in a module, package or class. High cohesion is one of the first rules of software design. Cohesion –in general- has 7 forms. The worst form of Cohesion is Coincidental Cohesion. By this type of cohesion, packages(modules) have some irrelevant functions(elements) that do different actions. Suppose that you have a package that is named  CHECK_CONTROL and contains CheckFlightCode and CheckSSN functions:

CREATE OR REPLACE PACKAGE BODY CHECK_CONTROL IS

  FUNCTION CheckFlightCode(pin_FlightCode IN NUMBER) RETURN BOOLEAN IS
  BEGIN
    --do some computations
 
    --for now return true
    RETURN TRUE;
  END CheckFlightCode;

  FUNCTION CheckSSN(pis_SSN IN VARCHAR2) RETURN BOOLEAN IS
  BEGIN
    --do some computations
 
    --for now return true
    RETURN TRUE;
  END CheckSSN;
 
  --
  --  some other checks like CheckZipCode
  -- ...

END CHECK_CONTROL;

Actually this two functions have no common point. Flight code check is an attribute of Flight  and SSN check is an attribute of Employee. If you encapsulate this two function in a single package, you will cause Coincidental Cohesion. Flight and Empoyee packages will be dependent of CHECK_CONTROL package. The best way to implement this is removing CHECK_CONTROL package and putting related functions in its own package(e.g., put CheckFlightCode function in FLIGHT package):

CREATE OR REPLACE PACKAGE BODY FLIGHT IS

  FUNCTION CheckFlightCode(pin_FlightCode IN NUMBER) RETURN BOOLEAN IS
  BEGIN
    --do some computations
 
    --for now return true
    RETURN TRUE;
  END CheckFlightCode;

  FUNCTION GetFlightName(pin_FlightCode IN NUMBER) RETURN VARCHAR2 IS
  BEGIN
    --select some table
 
    --for now return DUMMY
    RETURN 'DUMMY';
  END GetFlightName;
 
  --
  -- some other insert/update/delete/select procedures
  -- ....

END FLIGHT;


Otherwise, the packages that are only interested-in only one function in the package, will use(or refer) entire package. All other functions do not have any meanings for that package. Changing an irrelevant function in the check control package will also affect that package indirectly. Compiling the check control package will also invalidates all other packages that are referred. May be this is not a problem for Oracle because of invalid packages are automatically recompiled; but in order refresh session’s memory, the session should re-instantiniate its state. This is a problem. Another situation is grant issue. If you grant Check Control package for some user(say the CR in airport) who shall only allowed to use one function, (s)he will be granted to execute all functions in the package.

In general, this type of cohesion occurs when you do not want to have smaller pieces of packages. It can be seen that having more packages(more pkb,pks or pck files) will make hard to maintain project. Please note that, having low cehesion is harder to maintain. During time, general utility packages(like check control package above) will be used or referenced in different projects in different packages. In order to get more maintainable and stable applications, it will be better to avoid Coincidental Cohesion.

Another example will be Utility packages that is used accross several packages/projects. Most of utility packages exist in the toolbox of DBA or developer. The main aim of this utilty package is to complete all stuff in one place. People thinks that having more packages will make your code to run slower. Making contex-switches during function calls is a performance bottleneck. I admit that, this approach will not make your programs slower; in contrast, grouping similar functional units in seperate packages will avoid big package instantiation time J. If you want to have packages that are more manageable and  less affected on change(because we are doing live systems and they change usally) , you should consider software development rules-especially cohesion and coupling.
Please note that Oracle has a utility package which is named DBMS_UTILITY and it contains some functions which are irrelevant from each other. For instance, it have COMMA_TO_TABLE, FORMAT_ERROR_BACKTRACE and EXEC_DDL_STATEMENT functions. In my opinion seperating error related functions in seperate package( and etc, grouping similar functions in a seperate package) would be better.


No comments: