These days a question popped out in my mind:
Does the way we Javascript go against almost everything that is considered a good practice in traditional Software Development?
I have a series of question/observations related to this statement, but in order to respect StackExchange's format, it will be better if I split them into different questions.
Module requiring
Standard Javascript code nowadays looks like:
const someModule = require('./someModule')
module.exports = function doSomethingWithRequest() {
// do stuff
someModule.someFunc()
// do other stuff
}
Advantages
- Encapsulation: the module works standalone and know everything it need to perform its functions.
- As a colorary, it's easier to clients to use the module.
Disadvantages
- Poor testability: this is standard when not using DI, but in dynamic languages, such as Javscript it can be circumvented* by modules like
mockery
orrewire
. - It certainly violates the DIP -- not to be confused with Dependency Injection. -- since I can only import concrete modules.
- It probably violates the OCP -- for example, imagine that I have a log module that writes to the file system (through
fs
module). If I want to extend this log module to send it to the network, it would be very hard.
* This might work with CommonJS or even AMD modules since they are implemented mostly in the user-land. However, I'm not sure how this could be possible with ES6 import
syntax.
Dependency Injection
Using dependency injection, it would be more like:
module.exports = function doSomethingWithRequest(someModule) {
// do stuff
someModule.someFunc()
// do other stuff
}
Advantages
- Increased testability: now it's easier to stub/mock
someModule
, even using the ES6 syntax. - It's possible to honor the DIP: not necessarily though, as the client module can still be programmed to the implementation and not an interface.
Disadvantages
- Broken encapsulation: the main question remaining is:
Ok, then who will create/require the dependencies?
- Doing that in every client of the module seems very WET.
- This would probably require me to use a DI Container in order to be feasible in a real project.
So, the real question here is:
Why Javascript developers tend to lean towards the first approach?
Is this just "the Javascript way"?
I myself write code like this most of the time. I've had my fair share of test setup using mocking libraries, but it always felt kind of wrong doing so.
Am I missing something?