Monday, September 27, 2010

Dependency injection aids copy and paste coding

In the presence of good documentation or sample code, I love to copy and paste directly out of the documentation or even unit tests, straight into my code.

For example, I was wondering how to add an instance variable to a class in Pharo Smalltalk. Well, I just search my code base for occurrences of addInstanceVariable, and I find this test:

| refactoring |
refactoring := AddInstanceVariableRefactoring
variable: 'asdf'
class: RBTransformationRuleTest.
self executeRefactoring: refactoring.
self assert: ((refactoring model classNamed:
directlyDefinesInstanceVariable: 'asdf')

Well, that's great, the first few lines are what I need. Some more browsing shows that line 6 is deeply irrelevant for me: the test uses a highly artificial way of executing the test, different from the canonical one.

Is any of that surprising? Not really. There's some papers establishing that this is how a lot of people work: forking work off sample code, but only if it's complex enough to match the use case (cite?).

I think it has an interesting implication for writing unit tests: They should be as close as possible to the intended end user usage. In the example above, my hunch is that the unit test wasn't written in the way that the end user would use the library, because the author feared side effects.

I think here we see one of the great strengths of dependency injection: by moving the part of the unit test that avoids side effects to another level of abstraction, the unit test itself can look exactly as if it had side effects, and thus can serve better as a basis for new work.

Circular problem solving in computer science

Here's the rules: Find a genuine problem in a framework called X. Then write your solution in framework Y that depends on X. Then, rewrite X using Y such that the problem goes away.

Because rewriting of X depends via Y on some older version of X, I give bonus points for using a framework that allows calling older versions of X from within X.

Wednesday, September 22, 2010

Three degrees of inversion of control.

Inversion of control is a paradigm by Martin Fowler that advocates for separating things that don't belong together during object creation.

What exactly should be split from what? Different frameworks answer the question slightly differently. They do at least 1 of these three:

  1. Eliminate direct constructor calls. All dependency injection frameworks do that.
  2. Strictly separate business logic from object creation. Google Guice, among others, allows that, but doesn't enforce that.
  3. Eliminate all static references. Newspeak makes all lookups dynamic, thereby eliminating global state.

All three are compatible with one another. Can they be combined in practice? I'm working on it …