This column describes an issue arising when implementing two opposite desired design attributes (the Interface Segregation Design Principle and the orthogonally concept) and a draft proposal of how addressing it.

Under the Object Oriented Programming paradigm every system concept should be represented as an object with fields and procedures. In turn, it’s a common software development practice splitting related procedures into smaller and specific interfaces to make the program easier to understand and maintain.

Let’s consider the following DAO[1] with two simple operations: List and Delete.

public class TableDAO
 {
 public object List(object contextData)
 {
 //Code to list data from a data repository
 return null;
 }

 public void Delete(object contextData)
 {
 //Code to delete data from a data repository
 }
 }

In order to meet the Interface-segregation principle stating that [2] “CLIENTS SHOULD NOT BE FORCED TO DEPEND UPON INTERFACES THAT THEY DO NOT USE” we should provide the specific List and Delete interfaces as described in the following code.


public interface IList
 {
 object List(object contextData);
 }

public interface IDelete
 {
 void Delete(object contextData);
 }

public class TableDAO: IList, IDelete
 {
 public object List(object contextData)
 {
 //Code to list data from a data repository
 return null;
 }

 public void Delete(object contextData)
 {
 //Code to delete data from a data repository
 }
 }

A potential consumer of the TableDAO services might want to invert the dependencies (as stated in the complementary Dependency Inversion Principle[3]) to consume separately the specific interfaces as illustrated with the following Client class.


public class Client
 {
 public void TestIList()
 {
 IList daoObj = new TableDAO();
 daoObj.List(null);
 }

public void TestIDelete()
 {
 IDelete daoObj = new TableDAO();
 daoObj.Delete(null);
 }

}

The issue arises when you want to access both services (List and Delete) within the same block in a computationally efficient and engineer friendly manner. Consider the following three solutions for the previous scenario.


public void TestBoth()
 {
 //Solution # 1
 TableDAO daoObj = new TableDAO();
 daoObj.List(null);
 daoObj.Delete(null);

//Solution # 2
 IList daoObj1 = new TableDAO();
 daoObj1.List(null);
 IDelete daoObj2 = new TableDAO();
 daoObj2.Delete(null);

//Solution # 3
 IList daoObjn = new TableDAO();
 daoObjn.List(null);
 ((IDelete)daoObjn).Delete(null);

}

The three solutions are flawed because they sacrifice at least one of the gained benefits. The solution number 1 removes an abstraction layer. The solution number two wastes memory space and processor time and the solution number three forces the developer to do casting thus loosing static type checking [4] and fluency [5]. None of the sacrificed attributes should be accepted, which leads Software Engineers to find alternatives solutions.

A rational triage could be including the List signature into the Delete interface so consumers of the List interface would see the List function while the Delete consumers would see the List and Delete functions, which solves the need of using both of the functions within the same block at the expense of consumers wanting to use the Delete operation only. This approach is contradictory to the Single Responsibility[6] and DRY [7] design principles but it’s tolerable depending on the project size.

The project size is important because in small systems is tolerable having two different classes implementing the two different interfaces despite they belong to the same concept. For instance: a small project with 7 DAOs implementing List and Delete operations would require 14 classes. This approach promotes scattering [8], low cohesion and reduces maintainability because it would increment the quantity of code that needs to be understood to make even a small change.

In order to address the described issue (coded in C# language) segregated interfaces should be combined to attach a set of low coupled and highly cohesive relations in medium to big projects. The following pseudo code illustrates how orthogonally attachable interfaces might be used to allow static type checking, fluency programming, efficient computation (no casting) and orthogonally.


orthogonal<IList, IDelete> ortObj = new TableDAO();
 ortObj.List();
 ortObj.Delete();

The previous code does not pretend to be an ultimate solution because no formal research has been carried out; it only illustrates how from a Software Engineer point of view the issue could be addressed with this new Orthogonally Attachable Interfaces concept; however, the final definition could include operators to define them (e.g. var daoObj = IList + IDelete).

Cheers,

Javier Andrés Cáceres Alvis

Microsoft Most Valuable Professional – MVP
Intel Black Belt Software Developer