Reputation: 21
I'm wondering if the Interface segregation principle applys to my codebase.
Here's some example code:
First Class:
public class EntityGroup {
public List<Entity> tests;
//returns true if the EntityGroup is valid
public boolean validate() {
for (Entity test : tests) {
if (!test.validateFieldA() || !test.validateFieldB()) {
return false;
}
}
return true;
}
}
Second Class:
public abstract class Entity {
protected String fieldA;
public abstract boolean validateFieldA();
public abstract boolean validateFieldB();
}
Third Class:
public class EntityChild extends Entity {
private String fieldB;
@Override
public boolean validateFieldA() {
if (fieldA.equals("valid")) {
return true;
} else {
return false;
}
}
@Override
public boolean validateFieldB() {
if (fieldB.equals("valid")) {
return true;
} else {
return false;
}
}
}
Fourth Class:
public class EntityChild2 extends Entity {
@Override
public boolean validateFieldA() {
if (fieldA.equals("valid")) {
return true;
} else {
return false;
}
}
@Override
public boolean validateFieldB() {
return true;
}
}
This is a greatly simplified example from my real codebase but I think it illustrates the problem well. My EntityChild2 class is forced to implement a method it does not need or want to know about.
I know that it would be more correct to have a Interface that would contain the validateFieldB() method and only have EntityChild implement that interface.
With the understanding that this would take a significant amount of effort to refactor into this solution, I'm having a hard time justifying the time it would take to implement this solution in my real code base.
What potential problems will I run into down the line by leaving my code this way?
What benefits will I gain from refactoring my code to have a separate interface for validateFieldB()?
tldr: Why is the Interface Segregation Principle so important?
Upvotes: 1
Views: 146
Reputation: 5210
You make use of the interface segregation principle but with wrong abstractions.. Your different Entity
-types differ only in they behavior.
Because of the shared behavior you have duplicate code in the methods validateFieldA
of EntityChild
and EntityChild2
. The method validateFieldB
looks very similar to validateFieldA
just the filed for checking the equality is an other.
Entity
With the Strategy-Pattern you will have no duplicate code:
class EqualValidationStategy() implements ValidationStategy<T> {
@Override
public boolean check(T a, T b) {
return a.equals(b)
}
}
class TrueValidationStategy() implements ValidationStategy<T> {
@Override
public boolean check(T a, T b) {
return true;
}
}
public class Entity {
private String fieldA;
private String fieldB;
private ValidationStategy<String> validationForA;
private ValidationStategy<String> validationForB;
// all-args consturctor
@Override
public boolean validateFieldA() {
return validationForA.check(fieldA, "valid");
}
@Override
public boolean validateFieldB() {
return validationForB.check(fieldB, "valid");
}
}
// Validates fieldA and "ignores" fieldB
Entity example = new Entity(fieldA,
fieldB,
new EqualValidationStategy(),
new TrueValidationStategy());
Upvotes: 1