Take 3: Python, ISP, IoC, and OCP need a fundamental rethink.

In response to Julian’s thoughtful Dynamic Languages and SOLID Principles I’d have to argue he is about 95% there but is missing the last critical links needed to view this in a whole different light. For ISP, Julian says it all:

Ultimately, I don’t think ISP is changed by Python, it’s just kind of irrelevant, for better or worse.

Exactly!  Why even bother mentioning in the context of dynamic languages. A developer that understands it fully and one that does not will code the same way. Whereas LSP is still taught in dynamic languages, I’ve never seen it called that but I’ve seen many admonishments about subclass consistency, and not making client code aware of the differences, and is something that requires mentioning. With ISP we could ignore it’s entire existence and developers would code the same.

For OCP:

Well, the open closed principle is a goal, not a design practice, but let’s take a look at the danger points:

    * You can’t have non-virtual methods, so Python wins this hands down.
    * Your variable can’t be made too specific, so you’re safe there.
    * You can still compare against hard-coded values.  It’s just as easy to get this wrong in Python as it is in C#.
    * Same holds true for Law of Demeter violations.  If you pass the wrong object around, your code will be just as fragile in Python as in C#.

Python certainly reduces the scope for some OC violations, but you’ve still got lots of rope to hang yourself.  Think you still need to bear the goal in mind.

Bolding emphasis is mine. Enough of OCP is stripped and the primary ways its taught and demonstrated do not apply to the language at all. Focus on Law of Demeter, but having something that stands for “Open for extension” whenever everything is open and “Closed for modification” when nothing is closed would fall on completely deaf ears when presenting any of the associated ideas to a Python developer.

For Dependency Inversion/ IoC:

Let’s quote Ryan:

    Now all calls in this runtime, from any module, that reference the Output class will use XmlOutput or HtmlOutput instead.

Yes, but what if I wanted only half of them?  Maybe there’s Python techniques I don’t know about (I’m barely competent in the language) but as I see it, I’m going to need to change the code.  I don’t think that dependencies can "always" be injected.  They can only be done when it won’t cause damage.  In his case, he’s worrying about testability.  That’s fine, but we all agree there’s more to DI than testability.

Ok firstly, I didn’t just mention testability, in fact that the code you’re referencing there was no unit test for, it was about flexibility.  Secondly, call Output an “Abstract Class”,and then call XmlOutput and HtmlOutput concrete types and then add them to an IoC container like Windsor then let me ask yourself the question you asked me “what if i wanted only half of them”.  There would be a need for custom code to make this resolution work for this custom circumstance.  All I’m advocating is taking that same exact custom code and place it somewhere else in Python (yes you can override per method, per instance, etc, etc). 

I think there needs to be a principle that addresses the benefits of explicit interfaces and well formed custom composition cases…and in those cases DI makes a lot more sense, but certainly not as a defacto convention and certainly is not required to provide flexibility to existing implementations.  It certainly becomes apparent when you start looking into the actual way IoC works in static languages its all too similar to how a dynamic language runtime works. That code you’d use in a static language IoC to apply AOP, or custom composition rules, could just as easily be applied in a component in Python, because the primary mechanism for an IoC to work is as a factory, and the benefits and features they bring are all derived from having access to how objects are created and then returned, when you always have access to how objects are created and returned anyway as in dynamic languages, why should you implement it a second time. 100% DI’d code will be more effort to maintain because it would be in C# too…if not for that fact the language is so “structured” that the flexibility and testability benefits gained far outweigh the slightly increased cost (which is only brought down with the awesomeness of auto registering components).  In a language already with flexibility and testability whether you use DI or not AND without auto registering IoC containers the cost to maintain a full DI code base is I’d argue unacceptable.

Summary, for SOLID to make any sense whatsoever in a dynamic context it has to amended and modified to fit that world. Maybe make SOLID into SELL for:

S.RP

E.xplicit empty class for required overrides

L.SP

L.aw of Demeter

Maybe there is something containing other more valid concepts for the dynamic world that I’m probably not qualified to design or come up with. Anyway, I’ve enjoyed the conversation and I hope it brings about a firmer understanding of SOLID, and whatever we’ve not come up with yet for dynamic languages.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Ryan Svihla

I consider myself a full stack polyglot, and I have been writing a lot of JS and Ruby as of late. Currently, I'm a solutions architect at DataStax
This entry was posted in Dynamic Langs, IoC. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Louis Salin

    Awesome series of articles, Ryan. I’ve been thinking about the same thing (applying SOLID to dynamic languages) and I’m happy to see that you’ve gone into the same direction yourself.

    I never thought about monkey patching as a useful way to do dependency injection, which, incidentally, still remains dependency injection, no? It’s still a technique you can use that you must remain aware of. So maybe SOLID becomes SLID? :)

  • Daniel

    SOLID principles are akin to the step-by-step process McDonald’s employees must follow to create a hamburger. A great chef doesn’t need those rules, but in lieu of talent they ensure a consistent product. It might be worth asking if you want a Big Mac…or something better.

  • http://www.lostechies.com/members/rssvihla/default.aspx Ryan Svihla

    @louis yeah and from what I’ve seen Bob Martin himself has gone the dynamic language route (no idea what that means for his interpretation of SOLID).

    @Daniel I think there is a kernel of truth, but its more like you can’t be a great chef until you can make a proper omelet. You have to understand the SOLID principles well enough to know when to apply them and Bob Martin has often talked about them not being a dogmatic thing.

  • Christian

    “100% DI’d code will be more effort to maintain because it would be in C# too”

    I think this is a throw away comment and do not agree. Could you explain what you mean further?

    To me I think having all you dependencies created in a single place is vastly easier then having them littered through the codebase.

  • http://www.lostechies.com/members/rssvihla/default.aspx Ryan Svihla

    @Christian I think you’re suffering from my poor English writing skills, which is sad because I’ve only lived in the Midwest and do not have the excuse of having proficiency in any other language.

    If you keep reading the line passed the three periods in a row the rest of the statement clears it up, I’ll respond here without the three periods but a comma instead.

    “100% DI’d code will be more effort to maintain because it would be in C# too, if not for that fact the language is so “structured” that the flexibility and testability benefits gained far outweigh the slightly increased cost (which is only brought down with the awesomeness of auto registering components). In a language already with flexibility and testability whether you use DI or not AND without auto registering IoC containers the cost to maintain a full DI code base is I’d argue unacceptable.”

    So for example when I use IoC, I autoregister almost everything. My registration lines are maybe 10 or 12 for large code bases, and those are to handle the edge of the system typically.

    When I didn’t autoregister and instead maintained huge XML files (or explicit code later) the pain was quite severe. I was still willing to have this because the benefits in flexibility still far outstripped the cost. But trust me I was VERY happy to have auto-registration later on, its something the Java community has completely missed the boat on from what I’ve seen.

  • http://vtd-xml.sf.net anon_anon

    You might also want to look at vtd-xml for huge XML , the next generation XML processing model that is far more powerful than DOM and SAX

    http://vtd-xml.sf.net