DaedTech

Stories about Software

By

Dependency Injection or Inversion?

The hardest thing about being a software developer, for me, is coming up with names for things. I’ve worked out a system with which I’m sort of comfortable where, when coding, I pay attention to every namespace, type, method and variable name that I create, but in a time-box (subject to later revisiting, of course). So I think about naming things a lot and I’m usually in a state of thinking, “that’s a decent name, but I feel like it could be clearer.”

And so we arrive at the titular question. Why is it sometimes called “dependency injection” and at other times, “dependency inversion.” This is a question I’ve heard asked a lot and answered sometimes too, often with responses that make me wince. The answer to the question is that I’m playing a trick on you and repeating a question that’s flawed.

Confused

Dependency Injection and Dependency Inversion are two distinct concepts. The reason that I led into the post with the story about naming is that these two names seem fine in a vacuum but, used together, they seem to create a ‘collision,’ if you will. If I were wiping the slate clean, I’d probably give “dependency inversion” a slightly different name, though I hesitate to say it since a far more accomplished mind than my own gave it the name in the first place.

My aim here isn’t to publish the Nth post exhaustively explaining the difference between these two concepts, but rather to supply you with (hopefully) a memorable mnemonic. So, here goes. Dependency Injection == “Gimme it” and Dependency Inversion == “Someone take care of this for me, somehow.” I’ll explain a bit further.

Dependency Injection is a generally localized pattern of writing code (though it may be used extensively in a code base). In any given method or class (or module, if you want) rather than you going out and finding or making the things you need, you simply order your collaborators to “gimme it.”

So instead of this:

public Time getTheTime() {
	ThingThatTellsTime atom = new CesiumAtom();
	return atom.getMeTheTimeSomehow();
}

You say, “nah, gimme it,” and do this instead:

public Time getTheTime(ThingThatTellsTime whatever) {
	return whatever.getMeTheTimeSomehow();
}

It isn’t you responsible for figuring out that time comes from atomic clocks which, in turn, come from atoms somehow. Not your problem. You say to your collaborators, “you want the time, Buddy? I’m gonna need a ThingThatTellsTime, and then it’s all yours.” (Usually you wouldn’t write this rather pointless method, but I wanted to keep the example as simple as humanly possible).

Dependency Inversion is a different kind of tradeoff. To visualize it, don’t think of code just yet. Think of a boss yelling at a developer. Before the ‘inversion’ this would have been straightforward. “Developer! You, Bill! Write me a program that tells time!” and Bill scurries off to do it.

But that’s so pre-Agile. Let’s do some dependency inversion and look at how it changes. Now, boss says, “Help, someone, I need a program that tells time! I’m going to put a story in the product backlog” and, at some point later, the team says, “oh, there’s something in the backlog. Don’t know how it got there, exactly, but it’s top priority, so we’ll figure out the details and get it done.” The boss and the team don’t really need to know about each other directly, per se. They both depend on the abstraction of the software development process; boss has no idea which person writes the code or how, and the team doesn’t necessarily know or care who plopped the story in the backlog. And, furthermore, the backlog abstraction doesn’t depend on knowing who the boss is or the developers are or exactly what they’re doing, but those details do depend on the backlog.

Okay, so first of all, why did I do one example in code and the other in anecdote, when I could have also done a code example? I did it this way to drive home the subtle scope difference in the concepts. Dependency injection is a discrete, code-level tactic. Dependency inversion is more of an architectural strategy and way of structuring (decoupling) code bases.

And finally, what’s my (mild) beef with the naming? Well, dependency inversion seems a little misleading. Returning to the boss ordering Bill around, one would think a strict inversion of the relationship would be the stuff of inane sitcom fodder where, “aha! The boss has become the bossed! Bill is now in charge!” Boss and Bill’s relationship is inverted, right? Well, no, not so much — boss and Bill just have an interface slapped in between them and don’t deal with one another directly anymore. That’s more of an abstraction or some kind of go-between than an inversion.

There was certainly a reason for that name, though, in terms of historical context. What was being inverted wasn’t the relationship between the dependencies themselves, but the thinking (of the time) about object oriented programming. At the time, OOP was very much biased toward having objects construct their dependencies and those dependencies construct their dependencies, and so forth. These days, however, the name lives on even as that style of OOP is more or less dead this side of some aging and brutal legacy code bases.

Unfortunately, I don’t have a better name to propose for either one of these things — only my colloquial mnemonics that are pretty silly. So, if you’re ever at a user group or conference or something and you hear someone talking about the “gimme it” pattern or the “someone take care of this for me, somehow” approach to architecture, come over and introduce yourself to me, because there will be little doubt as to who is talking.

By

Agile: False Hope and Real Promise

I went shopping for jeans last weekend, which was, as always, somewhat of an aggravating experience. It’s not just jeans, but, really, any wearable thing: shoes, work shirts, belts, even socks. The source of my irritation is the fact that I can’t simply replace items I have that are worn out because the thing you bought last time is always decommissioned. Strangely, major things like cars have better staying power than clothes. There’s a very simple use case missing: As a shoe wearer, given that I love a pair of shoes and thus wear them out in 2 years, I want to go back to the same store and buy the exact same pair of friggin’ shoes so that my life is not interrupted. And the software of life fails to perform.

The reason for this is the nebulous concept of fashion. Naturally, wearable manufacturers and retailers don’t want to be ‘stale’ so they churn things at a rate that prevents me from being pragmatic with my shopping and turns my trips into maddening treasure hunts instead of simple errands. So I contemplate fashion a bit with a natural bias toward annoyance, and this has informed a pretty cynical take on the subject. I have an ongoing hypothesis that the thing that drives fashion isn’t some guy sitting in Paris, saying “I’m going to make those idiots wear really tight jeans this year and then laugh at them.” Instead, its the shifting tectonic plates of poor people trying to look like rich people and rich people trying not to look like poor people.

By way of narrative, guy in Paris releases skinny jeans and charges $700 for them. They’re new and expensive, so rich people buy them so that they can be seen wearing new and expensive things — signaling their wealth and cosmopolitan tastes. Bulk clothing manufacturers start knocking off Paris designer and selling it to the masses for $39 a pair and they sell out like crazy as everyone wants to ape the A list celebrities and influencers wearing these things. Rich people get annoyed that they’re no longer distinguishable on sight and this demand drives Paris guy to dream up some new, weird thing that they can buy to look rich. Rinse, repeat.

FashionKing

This narrative isn’t limited to the arena of rich and poor people with clothes, however. It also extends to things like industry thought leadership and buzzwords. Crowd of cool kids starts doing something and succeeding/making money. They give it a name and everyone rushes to mimic their success, adopting this thing. Imitators adopt it en masse, bring mediocrity and misunderstanding to it, and the cool kids lament that everyone is getting it wrong and that it’s time for another industry shake-up. Queue the “Is {Insert Tech} Dead” link bait and search for the next great thing.

“Agile” is probably the poster child for this sort of thing in the development world. Back around the turn of the millennium, various industry thinkers were experimenting with ways to move software development away from software development practices that mimicked construction and physical engineering since the results produced by this traditional, “waterfall” approach were spotty at best. A group of representatives of some of these experiments came together to find common ground and the result was called, “The Agile Manifesto.” In the interceding 13 years, the industry has come to accept that the Agile approach is “the right thing” while agreeing that, by and large, no one does it right.

Off the top, I’ve heard the following expressed recently (paraphrased from my recollection):

  • Agile is dead.
  • Scrum is a scam that makes grunts stand while they deliver their status reports.
  • If XP doesn’t work it’s because you’re doing it wrong.
  • Agile is stupid because you really can’t work sanely without comprehensive documentation and specs.
  • Agile is a marketing gimmick to create phony demand for meaningless certifications.

And yet, you’d be hard-pressed to find any non-agile shop that didn’t look down shamefacedly and mumble “yeah, we do waterfall.”  So, the reasonable conclusions from this are:

  • Waterfall (or pseudo-waterfall things like RUP) are really out of style.
  • Agile is mainstream, but the real fashionistas are so over it because everyone’s messing it up and ruining it.
  • Cool kids are looking for what’s next: a post-Agile world.

Agile, Distilled

I’m not certified in Scrum or XP or anything else. I have no project management credentials and no letters after my name. I certainly have experience in these methodologies and understand the ceremonies and the roles, but I’d hardly count myself an encyclopedia of how everything should operate. It’s always bemused me that arguments emerge over the finer points of the exact approaches to these methodologies and that people can actually be certified in exact adherence when the focus of the Agile Manifesto seems to me to be best summarized by the idea of bringing pragmatism and empirical experimentation to software development. But, opportunities for snark notwithstanding, it’s easy to see why people become disillusioned. Anytime there is some sort of process and any failures are blamed on a lack of true, absolute adherence, you have a recipe for quackery.

But at it’s core, I think Agile methodologies can be distilled to a single compound principle: tighten the feedback loop and improve the feedback. Think about the different things that are done in various flavors of agile: automated testing/TDD, short sprints, pair programming, retrospectives, big/visible charts, etc. All of it is about delivering feedback faster, delivering feedback more obviously, and acting quickly on the feedback. This is really, really non-controversial. The sooner you get feedback on what you’re working on, the sooner you can improve. So, where does everything go off the rails?

Is it that things don’t go well because people aren’t following the processes right? Is it that the processes themselves are broken? Is it that the processes are good, but a bunch of hucksters are peddling fools’ gold? Is it that people are just too entrenched in their ways to be compatible with these principles? Personally, I don’t think it’s any of this. I think that the fundamental problem is one of expectations (though some of the hucksters do nothing to mitigate this). Specifically, I think the main source of woe is the assumption that “going Agile” will cure what ails you because the only thing standing between the broken, over-budget pile of crap you’re about to ship and software nirvana is having a different set of meetings and adopting a different desk arrangement. The Agile promise isn’t realized by tweaking process; it’s realized by getting a scheme in place for receiving meaningful feedback and using that feedback, with a lot of practice, to get better at making software.

10,000 Hours

Wait, what? Practice? That doesn’t have anything to do with Kanban boards, swim lanes, stand-ups, and all of the other Agile stuff that gets so much focus. In the words of the esteemed Alan Iverson, “What are we talking about? Practice? We’re talking about practice, man.” The wide world is talking about the magic dust you can sprinkle on a team to make it crank out better software, faster, and I’m in here talking about practice.

During my semi-weekly drive to Detroit, I’ve been listening to audio books, including, most recently, Malcom Gladwell’s “Outliers.” Without offering up too much of a spoiler, one of the things that he talks about is that people like Bill Gates don’t reach the incredible levels of success that they do by being dominant in a vacuum, but rather they combine incredible fortune and opportunity with cleverness, ingenuity and a whole lot of really hard work. Bill Gates was born at a time where him being a teenager coincided with the very first machines that allowed for desktop based computing, rather than punch cards. He had the incredible good fortune of gaining access to such a computer in the late 60’s, as a teenager, when almost no adults or professionals on Earth had such access. Addicted to the fun of programming, he worked nights and weekends during his teenage years, programming, at a time when few others in the world had that opportunity. By the time he was an adult, ready to start Microsoft, he was one of the few people on Earth with 10,000 hours of experience programming this way.

The hypothesis for which the book is best known is that 10,000 hours of deliberate practice is the general average amount of time put in before a person acquires mastery of a field. As I understand it, there has been some corroboration of this hypothesis as well as some counter-evidence, but the broad point remains that achieving mastery requires a whole lot of deliberate work and concerted, sustained effort to improve. You know how you get really good at delivering software? Do it for years and years, constantly learning from your mistakes. You know how you don’t get really good at delivering software? By having slightly different meetings, shipping crap more frequently, and hoping for different results.

The way I see it, big A Agile, at its core, is not about fixing you or your software. It’s about making your practice more meaningful and efficient. To return to the basketball metaphor, Agile isn’t a weekend retreat that turns you into Michael Jordan. It’s a weekend retreat that shows you how to do a bunch of layup and dribbling drills that, after 10,000 hours of practice, will make you pretty good, as long as you keep challenging yourself. The great shame of Agile or any other kind of movement is that of false hope in easy fixes. Done well, it will expose your pain points more quickly, provide you with tools for removing obstacles, illuminate a path to improvement, and show you how to self-evaluate regularly. But it won’t make you awesome. Only practice and continuous learning will do that.

By

Chess TDD 19: DoesPieceExistAt and Housekeeping

Another night in the hotel, another episode of ChessTDD.  I’m doing my day to day work mainly in Java-land these days, so this is about the only time I write .NET code anymore.  Anywho, in this episode, I’m just planning to pick some housekeeping cards and move them across, starting with one I created after receiving an astute observation from Jeff in the comments from last episode.

Here’s what I accomplished in this clip:

  • Fixed a subtle bit of weirdness that may have caused future problems.
  • Cleaned up the screwy logic around default board size.
  • Factored the test classes more toward the new naming paradigm.
  • Implemented a DoesPieceExistAt() method to get away from GetPiece() == null

Here are lessons to take away:

  • This is kind of a combined lesson from last time to this time.  The comment I received and my resulting attention to the issue he pointed out is an excellent example of why pair programming (or at least code review) is full of win.  I may or may not have caught that logic error before shipping this thing to (an imaginary) QA or production, but with that review, it’s at the fore and I can do something about it.
  • “Boy Scouting” isn’t just about improving production code.  It applies to anything, including your tests.  Wholesale, quixotic refactoring efforts are not necessary if you’re constantly improving the code a little bit in the areas that you’re touching anyway.  In other words, you needn’t always go out of your way to refactor — it’s often advisable to wait to touch production code until you’ll be in there anyway.
  • I like to default to immutability whenever possible.  In the case of board size, why make that a settable property?  How often does it come up that you want to change the size of a chessboard that already exists with scissors or tape and cardboard?  (Modeling the physical world just makes for a funny mnemonic — faithfully modeling it isn’t actually that important.)  Seriously, what advantage is there to that being mutable. In my book, none.  You want a different board size, make a new board.  Not having board size be mutable makes your life much easier — no reasoning about what happens if you shrink the board when pieces are on it and other things like that.
  • Class level preconditions passed into a constructor are important to guard against.  Don’t let your consumers pass you things that would render you in a nonsensical state, such as accepting negative 1 as a board size.  When this happens, fail quickly, loudly, and visibly with an exception, and make it clear why and how in your tests.

By

The Humanized Expert Beginner

I was going to write a post about my recent fascination with Selenium tonight, but with the current bandwidth I’m getting from my hotel wifi connection, I won’t have successfully installed Firefox until Thursday. Undaunted, I decided to go through my drafts folder and move a card out of that sizeable backlog. The one that I settled on came as a response to Damien’s comment in my first Expert Beginner post. Periodically, people happen across that post and continue to comment, and I continue to find the subject relatively interesting since this theme is one that doesn’t seem to be in danger of going away. The portion of his comment about which I thought I’d muse is as follows:

You’d have to be mind-numbingly ignorant to fall into Expert Beginnerism. All you have to do to illuminate your ignorance is read a blog or book by highly experienced software engineers. If you’re an Expert Beginner in software, you’re likely an Expert Beginner in every area of your life.

I’ve been thinking about this a little bit here and there over the last couple of months. The question essentially boils down to one of whether Expert Beginnerism is a specific, learned approach to one set of problems or whether it’s a general approach or even a personality trait (defect?). Is it possible to be woefully mistaken about your own competence in one area of life while otherwise being a relatively normal, well-adjusted and pleasant individual in other arenas? Operating hypothesis: yes, it is. Tentative evidence: karaoke. I’m serious.

karaoke

Make your way down to a local place that does karaoke nights and suffer through the whole evening. I can almost promise you that you’ll find a nice, social, well-adjusted person that, to everyone’s listening displeasure, thinks they’re really good at singing. Most likely, they’ve never thought of making a go at it professionally and so no one has ever told them the hard but kind truth about their abilities. People just wince inwardly and say, “oh, sure, that’s GREAT!” And so the would-be Aretha Franklin or Frank Sinatra, through various merciful white lies in the face of unimportance, comes to believe wrongly that she or he is a good singer in spite of easily available evidence to the contrary.

That’s all well and good, however, because no one is paying these room-clearers to sing or, worse still, to teach others to sing. Is it possible to be a professional Expert Beginner without being insufferable across the board? At one time, I created a taxonomy of Expert Beginners (at least those with whom I’ve interacted) and group them according to their tolerance for cognitive dissonance. A poor-man’s interpretation of that might be how red they’d turn when asked, “Sir, have you no shame?”

In the parlance of that taxonomy, we have Master Beginner, Company Man, and Xenophobe. To recap, Master Beginners are consummate blowhards that believe themselves incapable of being wrong (no shame at all). Company Men have a basic, queasily pragmatic operating philosophy of circular reasoning: “if I have it, then I must have earned it by merit.” (They’d bristle some at suggestions to the contrary, turning slightly red). Xenophobes are those who have hissy fits when faced with the prospect that there might be some kind of gap in their knowledge (they turn beet red). I’d argue that the redder you turn, the less holistically defective you are when it comes to realistic self assessment.

We can pretty much set aside Master Beginners; these are seriously demented individuals that will be equally insufferable in all theaters. Company men are probably not far behind since they let their narrative be written as they go, with each instance of them not being taken down a peg bolstering their self confidence, however unjustifiably. So, even if they start out reasonably, after a bunch of years of “moving up by merit” they probably assume that they’re simply becoming awesome at everything. That leaves us with poor Xenophobe, who leads a high stress life, constantly on the brink of being exposed.

And this, I would argue, is the counter-example. Xenophobe is what happens if, while our karaoke singer is ‘performing’ on stage, someone comes along and says, “hey, I’m a musical talent agent and, while I’ve never heard anyone sing before, I’m sure that you’re just what we need, so here’s a few million dollars and some fame!” The stakes are high, the pot is sweet, and the dream is tantalizing, so our singer inks the contract, silences the “this is too good to be true” voice and engages in an odd dance that can only be described as, “make it then fake it.”

If we go away from the singer metaphor and into the more realistic scenario of “amateur techie at small, but growing, company,” you (might) start out with a decent, if naive, person that takes the road less advised when faced with “too good to be true.” And once that decision is made, it gets harder and harder with each passing day to go back, until you’re haggard somewhere, in an office, shrieking at junior developers that you don’t want to hear another word about this functional programming crap!

I’d imagine that this type of Expert Beginner, having arrived at the path described here, could actually be pretty reasonable in other areas of life. Sure, he must have some capacity for self-delusion, but can any of us honestly say that we don’t — that we haven’t indulged in basking in blatant flattery from time to time? I’m not saying that we could all make a lifetime of it, but what I am saying is that I think there’s a narrow cadre of expert beginners out there that might be decent people and even relatively modest in other areas of life.

By

ChessTDD 18: RemovePiece and Housekeeping

In this episode, I managed to pry myself away at a slightly shorter length of recording time.  You can seem me at the end wavering and and wanting to continue, but I know myself, and I’d have been hustling to wrap up under 25 minutes next thing I knew, so I thought I’d call it at a reasonable stopping point.

Here’s what I accomplished in this clip:

  • Implemented RemovePiece.
  • Made the public interface of Board a little nicer.
  • Minimized the usage of the array in favor of readable abstractions.

Here are lessons to take away:

  • Make yourself feel the pain of duplication.  Around 3:15 I fought off the temptation to copy and paste the setup of another test class to the new one, but I retyped it instead.  Copy and paste is like taking morphine and then walking on lava — you’re easing your pain when you should be letting it inform your actions to improve the situation.
  • Having identical setup in multiple classes is a test smell that’s making subtle suggestions.  Maybe the tests should be in a single class or, perhaps, there should be something in production code making that setup easy, if it’s really that common.  (I view the alternative, a lot of helper code in tests, not to be a better option).
  • At around 7:20, I did something subtle.  I looked for references to Board’s _pieces array and looked to eliminate as many references to it as possible.  The idea here is to minimize the use of a primitive abstractions in favor of the more descriptive ones I’ve created (GetPiece, RemovePiece, MovePiece).
  • More compact isn’t always better.  If you inline a variable, check for readability.  The beauty of a robust test suite is that you can really whip things around to maximize readability and feel good that you’re not breaking anything.