Tuesday, October 12, 2010

To learn is to abuse

I know sort of a strange title but I feel like there is some order of operations I'm following in my growth as a developer.

Learn thing -> abuse use of thing -> actually start to understand thing (hopefully) -> use thing appropriately -> learn new thing -> ...


My thoughts are interfaces are starting to change...mature? I think the .NET convention of an 'I' (ex: IEncryptionAlgorithm) prefixed defeats part of the point. I think that encourages us to see it as an interface code construct and not the required object description that your module/class/method wants. Perhaps Java's '*able' (ex: Runnable) is a better one. I hope that makes sense but I'm starting to think a lot of developers have focused on "this is a class" or "this is an interface" when both are actually an object description and when you take that in as a parameter you are saying I require these members. When I start thinking that way I start thinking that class methods should be virtual by default and that in general we probably don't use interfaces correctly (hell a lot of people don't use them at all I'm sure). Just having a class by default have virtual methods means we could mock a class the same as an interface. This does mean that you couldn't rely on a class's implementation at runtime but you shouldn't be programming against the implementation anyway.

Of course then I think about how it's easier to reason about a class if it's sealed up nicely. It's also easier to reason about code interactions if types are explicit, but then again it's easier to write tightly coupled code if types are explicit. Perhaps since class members are by default non-virtual, proper use of things like TypeMock should be encouraged. 

My biggest objection is if it allows you to open up the class and mock out a hidden internal dependency. If you needed to mock an internal dependency to properly test a class then perhaps it should be an explicit dependency instead (pass in through a parameter). 

Beyond mocking, interfaces should be encouraged as well since they are what provide real modular and reusable code. Type hierarchies only project shared/related implementation reuse which I don't think helps an application on a whole, just a piece of a subsystem or layer. They are best at describing related types, perhaps that's all they should be used for and not for passing around or interacting between subsystems.

I think this has been influenced by my interest in dynamic and message passing style languages. I also think this is just my understanding of object-oriented design hopefully increasing (you never can judge your own aptitude). So I'm thinking I'm leaving behind a phase of my understanding where I probably overly used classes and probably about to enter one where I overly use interfaces. Of course this only really matters in static languages where you have to worry about types. Maybe I'm over thinking things...or maybe I should just go back to Ruby or Python.

2 comments:

  1. We had this conversation before, and I definitely agree with your point that the "I" notation kind of defeats the idea. (I'll probably find myself using the "able" notation in my .NET code at some point, unless co-workers specifically don't like it from an ongoing maintenance perspective.)

    I tend to see the "proper way" of thinking about object interfaces in the OO world as "contracts." Object A doesn't really care what Object B is, only what it can do. If it can satisfy the dependencies in Object A, then it can be used. The "type" doesn't matter, just the contract. This works out really well in dynamic languages, naturally.

    This is really why I like the idea of dynamic languages in .NET and hope that the push for them continues. In the past few years people have really begun digging deeper into best practices in .NET (as opposed to plain old rapid application development) and a strong focus on IoC and contract driven development (behavior driven development? I'm not a terminology guy, I don't know) have emerged. As the "type" becomes less important than the "behavior" then strongly-typed development starts to show more of its inefficiencies.

    ReplyDelete
  2. I will say that it's probably not a good idea to ditch the 'I' prefix simply because it's just such a standard convention in the .NET community. I'm guessing that a lot of developers are expecting it.

    I do think that having the interfaced named what something is, or what it can do, and the class that implements it named according to how it does it.

    An example I gave while discussing this idea was: DomainEventDispatcher (interface) and InProcessDomainEventDispatcher (class) or AgathaDomainEventDispatcher (class).

    To expand on it a little further with the 'able convention, you could have something like Watchable (interface) that provides the contract needed to monitor for events (probably a literal .NET event) and then the DomainEventDispatcher could have the method to add things to watch.

    Just a quick example, but those conventions I think more accurately express what you are trying to do.

    Man, I need to take a serious dive into Ruby I think. Perhaps like you suggested before the code dojo could try to do a hackathon where we just try to play around with the IronRuby codebase. Most of us are .NET developers and we are trying to learn Ruby, what better way to do that then work with the compiler in a language we are comfortable with and contribute to open source.

    Any other thoughts on typing and object-oriented design I would love to hear.

    ReplyDelete