Not quite the same thing. If we suddenly want a file instead of a socket, we need to replace all instances of "socket" in all 1000 files with "file", while LogManager stays LogManager no matter what the internal implementation is - I don't have to modify a single file (ecxept for LogManager itself). Your code isn't flexible when it comes to refactoring. And it's not a synthetic example - we've had real cases like that in real projects.
>Because you can REDEFINE a function as well. You define the function in one file and it's used in 1000 files. You redefine it in one place it's redefined in everywhere.
If you pass dependencies via function arguments, your new implementation of the function will most likely need a different signature (as it requires new dependencies) - thus you will also need to patch all call sites in all 1000 files to conform to the new signature. With interfaces, I don't have to do it.
>So? I can initialize dependencies and pass it around as well. Same thing as passing a log manager everwhere.
In this example, you're basically reinventing OOP with structs, just without the syntax sugar, such as polymorphic functions. If you use that approach properly - dependency injection in constructors with clean method signatures - I agree it's the exact same thing as OOP so I'm not sure what we're arguing about here.
>Injecting the dependency into a class necessitates the ENTIRE class to be passed around
>Think of LogManager as SocketWrapper.
Usually in real code it's not "the entire class", but an interface, which is just a lightweight implementation-agnostic protocol which announces what kind of functionality is available. Your SocketWrapper is indeed an example of passing an entire class around. Readability is also lacking: "Logger" tells exactly what it does: "I can log". If I see SocketWrapper or WrappedSocket, it's not immediately clear what "wrapping a socket" means. And your example passes the logger as a function argument - that's not how properly designed object-oriented code works - you inject your dependency in the constructor of your class as part of the dependency tree which is initialized somewhere once. Of course if you pass it as an argument every time there's no difference.
>Just putting a socket in a wrapper doesn't change the fact that you have to pass it around all over the place.
See my argument above that mentioning "socket" everywhere isn't as flexible when it comes to refactoring.
>d1 and d2 are reusable. and modular. I can reuse sockets and files with other things. With a logManager I don't even have access.
A socket instance can be injected in the logger's constructor and shared by other classes as well, I'm not sure why you think OOP is less modular in this regard.