| Barbara Liskov and Bertrand Meyer both have talked about separating decision making from execution. And though there work predates widespread adoption, I find this happens to work remarkably well for unit testing as well. The thing to remember is that when Java was young, the pool of people who grasped OOAD was very small. Nearly all of us were making it up as we went along. So Design Patterns came out and everyone glommed onto that book, and then went out and wrote code so awful and convoluted that it's now a joke. J2EE was built up in that space, on a foundation of bad assumptions and unfounded theories. I was simply amazed that the same company that brought us the Eight Fallacies of Distributed Computing brought us the J2EE 1.0 spec. I was so appalled at its quality that I switched to UI development until well after the 2.0 spec was out and implemented. It says something profound that every vendor that had any succes with those versions of the spec did it by defying the spec and supporting local dispatch. A lot of people couldn't scale their app past two machines, but load balancer eventually came around and fixed that. Anyway, my point is you have a bunch of APIs written by newly minted experts, many of the foundational ones by people with absolutely no awareness of the physics of distributed computing, it's going to take a lot to spackle to cover those sins. Some did, others doubled down, but overall every problem was solved by another layer of indirection. When refactoring came to the fore I hoped the industry would hastily reverse course. Spring was supposed to fix a lot of this but from my view, Spring became the thing is sought to replace. Full of cryptic levers and dials and massive indirection. I think it was Mike Feathers who attributed this to cowardice. People afraid to make decisions put all the decisions behind a layer or two of indirection so they can "cheaply" change their minds later. But again we are back to Meyer and Liskov here. If A then B (where A is the decision and B the action) allows you to change A without adding much if anything to B, or add to B without changing A. If this shows up in an inheritance hierarchy then you need about half as many overridden methods for the same call tree. Which means a shallower call tree, and code you can speak out loud. |