5 ms·
My least favorite example of when tests damage an API design is with dependency injection. There seems to be very little need to resort to dependency injection
by leorocky 12y ago
My least favorite example of when tests damage an API design is with dependency injection. There seems to be very little need to resort to dependency injection as a way to create a good API with easy to understand architecture many times, but dependency injection gets abused because it makes testing easier. You can supply your API with mock and stub classes at every turn if you use dependency injection everywhere, but the consequence is a more difficult to use API that requires the programmer who uses your API to understand more arbitrary and unnecessary implementation specific details.
For example, maybe I just want to open up an encrypted TLS TCP socket to a server. From a user perspective this could be really basic, you provide a library with an API that you provide with server address, port and handlers. It could be as simple as a few lines of code. But the dependency injection version of this would require maybe require creating an SSL Factory, which requires a 509x certificate provider, which requires a certificate storage locater. Then instead of an address you must provide it with an ipaddress factory method and a protocol factory which requires a list of available protocol implementors. Then 200 lines later you want to actually manage your connection and you must provide a connection manager and a byte buffer which itself involves tons of cruft.
Sometimes dependency injection is like a person walking around with their organs hanging outside of the body. When two people want to make babies they don't have to know low level biological mechanics of how sperm sends signals to a ready to be fertilized egg. They don't have to read and learn pointless documentation. They just insert the thing and everything usually works although under the hood it is maybe one of the most complicated processes in biology. That's how an API should work: making complicated things simple.
- WickyNilliams 12y agoCould you not have the best of both worlds by writing a facade over the public-facing API? I have used this approach in the past and it works well. The facade just handles grunt work of wiring the myriad of types together, as you described. It can be verified by blackbox testing or simply by eye (as it should not contain any logic beyond instantiation).
- TylerE 12y agoWhile there are valid use cases, this sort of thinking is why apps are no more responsive today than they were 20 years ago... everything is running through 20 translation layers.
- iand 12y agoI don't agree. I'm pretty sure we can make apps today equivalent to those from 20 years ago that are an order of magnitude more responsive even with all the indirection layers (640x480 resolution, 256 colours, no ui animations etc.)
- humanrebar 12y agoWhile that is a risk, it's not a necessity. Many of the classes in the C++ standard library are designed in exactly this way without runtime performance issues. All of the wrapping and indirection get inlined at compile time.
- marcosdumay 12y ago20 years ago (94!) one was always waiting for graphical applications to respond, and lots of people prefered command line applications instead, because of it. Currently, almost all interatcions with nearly all applications (Firefox and OpenOffice charged as guilty) are intantly.
- leorocky 12y agoAs long as the user facing API is simple, and the thing works well enough such the user doesn't have to know about how the underlying black box pastes its spaghetti together it doesn't matter. So I think what you are suggesting is fine.
- BorgHunter 12y agoI've solved this in past Java/Spring projects by having two public constructors, one default and one that takes all the "organs". The default constructor just delegates to the "provide me with organs" constructor but creates all the factories and providers and such itself. This doesn't work if you have long chains of singleton objects that get passed around to a lot of classes, but it works well for simpler cases.