Enforcing Interfaces
This is my second installment of the series related to my small side project that I started. I mentioned in the first post that one of the things I wanted to try out with this project is coding by interfaces. There's an article over at CodeProject that I once read (I'm struggling to dig it up now, arrrrrghh) that really gave me a different perspective about using interfaces when I program. Ever since then I've been a changed man. Seriously.
The main message behind the article was along the lines of: Have your classes implement your interface, and to be certain nobody is going to come by and muck around with your class's API, make sure they can't knowingly make an instance of the class. One of the easiest ways to do this (and bear with me here, I'm not claiming this is right or wrong) is to have a hidden (private or protected) constructor on your class and static methods that let you create new instances of your class. However, the trick here is your static method will return the interface your class implements.
An example of this might look like the following:
[csharp]
public interface IMyInterface { void Xyz(); }
public sealed class MyImplementation : IMyInterface { // we hid the constructor from the outside! private MyImplementation()
public static IMyInterface Create()
{
return new MyImplementation();
}
public void Xyz()
{
// do some awesome things here
}
}
[/csharp]
Interesting Benefits
I was pretty intrigued by this article on enforcing interfaces for a few reasons and if you can stick around long enough to read this whole post, I'll hit the cons/considerations I've encountered from actually implementing things this way. These are obviously my opinion, and you can feel free to agree or disagree with me as much as you like.
- (In theory) it keeps people from coming along and tacking on random methods to my classes. If I have an object hierarchy that I'm creating, having different child classes magically have random public APIs changing independently seems kind of scary. People have a harder time finding ways to abuse this because they aren't concerned with the concrete implementation, just the interface.
- Along with the first point, enforcing interfaces makes people think about what they're doing when they need to change the public API. Now you need to go change the interface. Now you might be affecting X number of implementations. Are you sure?
- Sets people up nicely to play with IoC and dependency injection. You're already always working with interfaces because of this, now rolling out something like Moq or Autofac should be easier for you.
- Methods can be leveraged to do parameter checks BEFORE entering a constructor. Creating IDisposable implementations can be fun when your constructor fails but and your disposable clean up code was expecting things to be initialized (not a terribly strong argument, but I've had cases where this makes life easier for me when working with streams).
- Stats are simple structures representing an ID and a value
- Enchantments are simple structures representing some information about modifying particular stats (slightly more complex than stats)
- Items are more complex structures that can contain enchantments
- Actors are complex structures that:
- Have collections of stats
- Have collections of enchantments
- Have collections of items
I have a good handful of classes and associated interfaces that back them. I've designed my classes to take in references to interfaces (which, are of course backed by my other classes) and my classes are largely decoupled from implementations of other classes.
Now that I've had some time to play with this pattern, what are my initial thoughts? Well, it's not pure sunshine and rainbows (which I expected) but there are definitely some cool pros I hadn't considered and definitely some negative side effects that I hadn't considered either. Stay tuned
(The previous post in this series is here).