5 ms·
> The users of this software would be very disappointed if any of these indirections involved adding any number besides 3. What? No, it works great to add numb
by gregmac 8y ago
> The users of this software would be very disappointed if any of these indirections involved adding any number besides 3.
What? No, it works great to add numbers beside 3:
class Sample {
public Sample(IThreeProvider threeProvider) {
_threeProvider = threeProvider;
}
private readonly IThreeProvider _threeProvider;
public int AddThree(int val)
{
return val + _threeProvider.Get().AsInt();
}
}
public class MyCustomThreeProvider() {
public int Get() { return 4; }
}
Now you can just do:
var sample = new Sample(new MyCustomThreeProvider());
sample.AddThree(2);
And get 6, as you'd expect. ..So long as you read and fully understood the entire codebase first, anyway.
I think this actually highlights one of the bigger problems in adding unnecessary indirections: that it practically begs for strange work-around and hacks and strange layers added on top. It becomes too difficult to change the underlying classes -- eg, changing the AddThree method to handle an arbitrary number means also changing the entire concept of ThreeProviders and everywhere that calls or tests any of the related code -- and as a result it's faster to workaround.
- JustSomeNobody 8y agoInstead of constructor injection, you really should have used an injection framework for this. Preferably one that uses an xml config file so that I would have to read and understand THAT also.
- vbsteven 8y agoThe whole point of having an injection framework is that you should not have to understand the whole framework or the implementation to use it. In this case you want a ThreeProvider and you don't care at all how it is implemented or where the value comes from. It's good that the dependency on the ThreeProvider interface is defined in the constructor, that makes it clear that there is a required collaborator and your class cannot be constructed with an invalid state. If your injection framework is any good it can use this constructor to do the wiring. For example in Java Spring the only thing you need to do is add @Autowired to this constructor. And on a side note: Spring does not require any XML for DI configuration since at least 10 years ago.
- zlynx 8y agoGreat, so now it's magic and no one knows how it works. The last time I had to work on Java (more than ten years ago) it was easier to load the app into the debugger than to understand the source code. That's f'd up.
- vbsteven 8y agoAnd that was 10 years ago. We've come a long long way since then. Nowadays it would look something like this @Configuration public class ThreeConfiguration { @Bean @Profile("dev") public ThreeProvider devThree() { return new DevThreeProvider(); } @Bean @Profile("production") public ThreeProvider prodThree() { return new ProdThreeProvider(); } } @Component public class Sample { private ThreeProvider threeProvider; @Autowired public Sample(ThreeProvider threeProvider) { this.threeProvider = threeProvider; } public int addThree(int val) { return val + threeProvider.getThree(); } } And that's about it. The Sample class does not need to worry where it ThreeProvider comes from. And the configuration about all the different implementations and in which cases they will be used are bundled together in one class.
- TickleSteve 8y ago...and the whole (non-java) software world cringes while the Java guys look puzzled wondering whats wrong with it.
- vbsteven 8y agoCan you explain why this is so cringeworthy to non-java devs?
- JustSomeNobody 8y ago1. There's Magic. 2. It is derived from the desire to create not applications, but application frameworks that can handle any conceivable change request that the PO might come with. This is architecture astronaut territory. It's frustrating to work with. It's hateful to debug.
- titanix2 8y agoExactly my thought when reading the article: the example with threeProvider goes against the point made by the author as it allows more scenarii to occur.