Open closed principle, refactoring
I'm trying to apply OCP to a piece of code that I have that the current state is really smelly in it, but I feel like I'm not getting to the end.
Current code:
public abstract class SomeObject
{}
public class SpecificObject1 : SomeObject
{}
public class SpecificObject2 : SomeObject
{}
// Smelly code
public class Model
{
public void Store(SomeObject someObject)
{
if (someObject is SpecificObject1)
{}
else if (someObject is SpecificObject2)
{}
}
}
This is really ugly, my new approach looks like this:
// No so smelly code
public class Model
{
public void Store(SomeObject someObject)
{
throw new Expception("Not allowed!");
}
public void Store(SpecificObject1 someObject)
{}
public void Store(SpecificObject2 someObject)
{}
}
When a new type SomeObject appears, I have to implement how that particular object is, it will violate OCP because I need to change the model class.
To move store logic to SomeObject also feels like the wrong reason, I will be breaking SRP (?) Because in this case SomeObject is almost like a DTO, it is incompatible with not knowing to store itself.
If there is a new implementation of SomeObject that has no implementation implementation I get a runtime error due to an exception in the Store method in the Model class, it also looks like a code smell.
This is because the calling code will be in the form
IEnumerable<SomeObject> sequence;
I won't know the specific types of sequence objects.
I cannot understand the concept of OCP. Does anyone have specific examples or links that are a little more than some Car / Fruit examples?
a source to share
The sample I present allows you to register handlers for specific objects. There should be a registerd handler for every type of object that can happen. If the handler cannot handle this, an exception is thrown.
You can load handlers (whatever implements IHandler
) dynamically from yours or from other assemblies, and instantiate and add them. Therefore, it is sufficient to create a handler class for any type that implements SomeObject
.
public interface IHandler {
bool TryHandle (SomeObject o); // return true iff handled
}
public class Model
{
private List<SIandler> _Handlers = new List<IHandlers>();
// registers a new handler
public void RegisterHandler (IHandler h) {
_Handlers.Add(h);
}
// this tries to store an object by letting all handlers attempts to store
public void Store (SomeObject o) {
foreach (var h in _Handlers) {
if (h.Store(o)) return;
}
// no handler was able to handle the type
throw new Exception();
}
}
public class Specific1Handler: IHandler
{
public bool Handle (SomeObject o) {
if (o is SpecificType1) {
/* store... */
return true; // we handled this object
} else {
// we're not qualified
return false;
}
}
}
I believe this would suit your needs. (By the way, I don't know if this template has a name, it would be nice to know if it does.)
a source to share