January 2013
Great article, and I love the video. Especially the part where you explain how 4 principles are naturally conflated to 2. Rings bells with how things have evolved for me. I'll try and keep an eye out for the specific side effects you describe being caused by removal of duplication, and the search for better names.
January 2013
I liked the translation of a fairly abstract "principle" into a number of coding "practices", eg. moving 'new' up the call stack. I think the article could do with a few more of these, because "details", "implementation choices" and "specificity" are all relatively vague terms.
1 reply
January 2013
▶ kevinrutherford
I wasn't trying, with this article, to define "details". I don't think I need to, and I don't think I can, concisely. I don't want people to remember only *rules*, and forget the principles. :)
As for "implementation choices", I think that's quite specific, but I didn't define it. I mean specifically the choice of implementation class. In other words, if a few of your controllers depend on a CustomerRepository interface, then the "implementation choice" in your entry point might be SpreadsheetBasedCustomerRepository or HibernateBasedCustomerRepository. I hope this clears that part up.
1 reply
January 2013
A few people have asked me when I'm going to add code samples to this article. Probably never.
*You* need to try this. Pick any code and try it. You need to see the results for yourselves. If you want to post gists and ask me to comment, then feel free. *I* know that this stuff works; I don't need to convince myself by working through more exercises. I've done it!
It's your turn.
January 2013
Greate article and video. For me the connection you explained between D.I. and D.I.P is quite valuable. And your image "move up 'new' in the call stack" was very intuitive for me.
Though I know what you mean I found the section "Abstraction in Code; Details in Metadata" too abstract to grasp easily. Similar your "generic patterns" and "the server". The same objection I have against Uncle Bob's "High level modules should not depend upon low level modules". I mean, what is a "high level module"? Not easy to understand for a student. Sadly I have no better alternative, but as I remember you are good at improving names. ;-)
I usually explain it with a concrete example everybody knows. Replacing
GUI -> Domain -> Persistance
with GOOS / Ports & Adapters style
GUI -> Domain with Repository Interfaces <- Persistance
1 reply
January 2013
Thanks JB for this write-up. I totally agree with what you are saying, and I second your idea that everyone should try doing this.
Going to your question "how do you explain DIP to others", I usually explained brifly this concept during trainings and coderetreats, but never at large. I like to tell people that I arrive through refactoring at a graph of objects that communicate with each other. The main advantage is for me that I end up at the core OOP pattern "messages and dispatch", I just have abstractions sending messages when needed. I also explain that these abstractions are easier to be transformed into entities respecting the principles "low coupling & high cohesion". The less I need to couple the abstractions, the happier I am.
Also, especially working on old code bases, when I refactor I end up with a code that is more efficient, because a lot of the logical branches disappear. All the control is moved at the entry point, and only the needed abstractions are used, not more and not less.
What are your thoughts on that?
1 reply
January 2013
▶ disqus_L4zk6YgTtX
I, too, explain DIP in terms of coupling: mostly about avoiding cyclic dependencies. I tell people "Framework calls you; you call library; you never call framework". I remind people that cyclic dependencies cause build times to explode, especially if they work without incremental compilation.
I like the idea of refactoring removing logical branches, and therefore making code easier to understand, easier to write correctly, and even performing better. I usually tell people that when I refactor I remove bugs without even realising it, but I don't have a really good example of that, so I usually just hope that they take my word for it. :)
January 2013
▶ davidvlkel
Thank you for your kind words.
"The server" is just "the thing I'm talking to", whereas "the client" is "the thing doing the talking".
As for "high level modules" and "low level modules", I think Bob and I both rely on a general, intuitive understanding of those terms. "High level" usually means "less concerned with details" and "low level" usually means "more concerned with details". A module that handles processing orders is higher level than a module that writes data to a database. This last module is higher level than a module that writes bytes to a stream. And so on.
As for "generic patterns", I would expect that to be intuitively clear on its own. "Selecting items from a collection that satisfy a predicate" is a generic pattern, as opposed to the detail of "find all customers with pending orders".
1 reply
January 2013
▶ jbrains
For me these notions are fine, but that's because I already knew the DIP before. I interpreted your questions in the direction, that you want to teach the DIP and thus are searching for the most intuitive explanation, weren't you? I tried to imagine that I'm in the role of a student that is taking your lesson and has problems to grasp these quite abstract concepts and ... OK ... is eager for some examples. ;-)
1 reply
February 2013
▶ davidvlkel
Examples: maybe, eventually.
I'm happy to answer specific questions to supplement the article. If I find the answer particularly significant, I'll add it into the article itself. To write an article, however, requires making some assumptions about what terms people know, otherwise the article runs to 10 kwords. :)
February 2013
February 2013
▶ jbrains
Thanks, the article and the discussion taught me alot. Especially the specific example about the Repository. Lately been experimenting with the Repository pattern in some side projects in an attempt to make my code more modular. I find it very difficult to do with rails-like frameworks (django, rails, grails). Well, to be honest, I find it difficult to do with any framework that is very opinionated. Your article lit a light bulb in my head. Okay, now I'm going to try to express those ideas in code.
June 2013
Great article, a different and simplified way to look at 'DIP'. I hope this will also help me in explaining the DIP to other team members.
May 2014
I dislike spring for the same reason I disliked Zeus. I don't like band-aids and I don't like running tests or development code in a different context than 'production'. :)
2 replies
May 2014
▶ thatrubylove
love the article and vid with corey!
May 2014
▶ thatrubylove
By definition I run tests in an context other than 'production', so I can't agree with that the way you've expressed it. Maybe you mean something else?
As long as Spring calls your stuff, and your stuff doesn't call Spring (directly), most of the typical Spring annoyances disappear.
1 reply
May 2014
▶ jbrains
Spring and Zeus are runners that change the way your environment works to implement 'fast' running.
If you write tests that are heavily tied to Rails, then you may need something like zeus or spring. However, I never needed Zeus as I like isolated tests. If I don't need to load Rails top test my DOMAIN objects, then I don't need the band-aid that is Spring.
This may just be a precog bias.
1 reply
May 2014
▶ thatrubylove
(1) Wrong "Spring". I was thinking of the Enterprise Java one, so ignore my comment entirely. (2) I write few tests that depend on the framework (example: Rails) precisely so that I don't have to run the framework in its container to check my stuff.
1 reply
May 2014
▶ jbrains
ignore mine as well then! damn these generic names! #bunnybuddhism
1 reply
May 2014
▶ thatrubylove
I have updated the article to reflect this confusion. Cheers.
July 2017
July 2017
▶ dave_falkner
Thank you. In legacy systems, I often refactor at first towards Service Locator, and then slowly push the Service Locator access up the call stack until I have only one instance of the Service Locator, and then it disappears.