Use of Abstractions in Dynamic & Static Languages | Dru Sellers
The more and more that I code in .Net the more that I notice we like to layer our own abstraction on top of 3rd party abstractions. In general (and I don’t have enough experience to really say) I feel that dynamic languages don’t do this as often.
Examples of this concept in .Net (C#)
When you go into a .net code base and you see an interface that is a shallow wrapper over the third party’s interface. A well known example of this is: an IRepository abstraction over the NHibernate ISession. I have seen this done for SmtpServer, file system IO and many other things as well.
Examples of this concept in Python and Ruby
I am not sure if its because the projects I have observed are small or that I just haven’t seen the right projects, but I see Ruby projects just taking (in my mind) a hard dependency on things like ActiveRecord and Python projects do the same thing with a hard dependency on Django’s ORM. Often times they seem to pull in the lib they want to use and just get to work. To be clear, ORMs are probably a bad example, but in general I don’t hear about my friends who program in dynamic languages adopting this pattern.
Why do static language programmers (more specifically me) do this?
Now that we have discussed what it is we are talking about, what causes this behaviors? Are they bad? Are they good?
Often times I do this to isolate a library from having to be referenced in each project. Instead I can add the reference once, and then its just a project reference elsewhere. I think this is me doing something that made since at one point in my career but now I just don’t get it.
I also think that underneath the covers is a fear that the 3rd party lib will change (or that we will want to switch out 3rd party dlls) and we want to protect ourselves from it. I feel this is one of my sillier reasons, because we get those compile time errors and we get test failures (and we are writing tests right?) we should have absolutely no reason to fear a 3rd party API change.
Its too bad that the fear part in my .Net code exists and this thought exists that I can just magically change out the provider to the interface, and everything will still work. So much effort to give myself a warm fuzzy feeling.
Testing (in .net)
In .net since we have static typing, we almost always have to create a ‘shim’ interface to make testing simpler. We do this because we can’t just shove any object into any parameter unlike in our dynamic language friends who have duck typing already (so they don’t need to build an abstraction on top of the other code to mock it out). This is by far my best reason for practicing this wrapping behavior, especially in areas that would need to access external systems. But I still need to be careful not to over do it.
So, what can we take away from this?
I think the biggest thing that I plan to take away from this is a new level of awareness to my code. Most importantly I should NOT do this out of fear. If I am afraid something is going to break, than I should do the only thing that WILL protect me. I should write a test to pin down the behavior. No amount of my clever abstractions are going to protect me as much as the time I spend in writing the 2-3 tests that will pin down the correct behavior.
Another take away, for me, is the question. Do dynamic languages have it easier / better? Inherently, I don’t think that they do, but like dynamic languages often tout, they sure do have a lot less ceremony to go through. Which is an important thing, a low ceremony code base is a happy codebase.
Well that’s my sunday morning thought.
Please share your thoughts on the subject in the comments. I look forward to our conversations there.