The title may not be too descriptive, but I couldn't think of a better one. I'm sorry for that.
So, the problem I am having here is one I have come across a couple of times now. It's really about design patterns and principles, and is language independent as long as you have OO facilities in your language. I'll take you through the current problem I am having, as it is hard to explain what the problem is without an actual example.
So, I am using some classes to describe logic statements here. Think of something like this:
condition = new And(new Equals("x", 5),
new EqualsOrOver("y", 20));
Now this is all dandy and all, but the problem comes when I want to use this class system. Right now, I am making a system where the condition needs to be translated to an SQL WHERE clause.
I could do this in several ways, but none seem to adhere to the Open/Closed principle. For example, I could have the Database
class parse the condition and make it SQL. The problem is that in this way, I can't extend my Condition
without the need to change my Database
, thus we're not following Open/Closed.
Another way - which would seem logical here - is to add a toSQL()
function to my Condition
s. However, in that case, I am unable to swap my Database for one that (just to name something) uses XML, that doesn't want the condition in SQL format.
One way I have worked around this problem in the past has been to use a factory. The factory method in this case would look something like this:
turnIntoSQLCondtion(Condition c)
{
if (c instanceof Equals)
{
return new SQLEquals(c);
}
else if (c instanceof EqualsOrOver)
{
return new SQLEqualsOrOver(c);
}
else if (c instanceof And)
{
return SQLAnd(c);
}
}
This isn't all that nice, but it will reduce the violation of Open/Closed.
Now, you can subclass your Database just fine. You will just have to subclass your factory as well, and you will have to make a new bunch of Condition
classes specific to your Database
as well. You can also work your magic on the Condition classes as well. You can make a new Condition
s, but you will have to make companion classes for each Database
as well. Lastly, you will have to modify your factories.
It's the smallest violation we have seen so far, but we are still violating Open/Closed. But as a matter of fact, I would much rather not violate it at all. Is there a way to do this while sticking to Open/Closed all the way?