Q: Creating all objects in a DI Container up front seems expensive, what about performance?
Yes and no. Even if most DI containers do support lady loading in various forms, an instance injected into another object still requires to be created first. And sure, there’s a risk that objects get created even if it wasn’t strictly necessary. On the other hand, if you constructors so that object creation is as cheap as possible, this problem might not even be a problem. As a general rule, creating an object should have no for few side effects. In the Hello Testable sample code, an obvious enhancement would be to let the Lyrics object defer loading the text file until it’s strictly needed.
Q: In the original post you kind of describe Interfaces but you never actually use or even mention them. Why?
I agree, the relationship between the main plugin class and the Lyrics class can be made stronger and more formal by defining an Interface and requiring that the object passed into the main plugin class constructor implements that Interface. The only real reason I didn’t do that the original post already tried to stuff too many concepts into a single piece as it was.
Q: If I implement my plugin like you suggest, another developer wont be able to use remove_action to unhook my code. That’s a big problem
Agree, this is an issue. My solution to this is to provide a static method to the needed classes (just the main plugin class in the Hello Testable sample) so that an external piece of code can get a hold of the correct instance for this purpose. I will add a separate post about this when time permits.