Comments (2)
This is a perfectly valid approach to get things done quickly. I used to work like this for the SimpliField back end, we used to call it the context
object which is kinda similar to the example you provided.
That said, it has downsides that a DI system can resolve.
An HTTP server depends on the database. If this is the only dependency of your code, the context
object may be enough. But when you have several databases/connections to manage (a message broker, several databases, IPC, WebSocket ...) it quickly becomes a great mess.
You keep repeating yourself by creating startup and shutdown code depending on inter-relations of those services. Code that you have to test/maintain/debug. It simply doesn't scale and there is a point where it becomes error prone.
With a DI system based on Inversion of Control, you simply declare dependencies and things gets up with no extra work.
The fact you express those dependencies statically also have nice side effects.
- lazy service instantiation/shutdown: you may open a DB connection only when needed. With the
context
object approach you have to do it once for all, every services are singletons. - easy service swapping: with the context object approach you hard set dependencies so that if you need two instances of the same service at some point, you have a whole bunch of instantiation/shutdown code to change.
- Dependency graphs out of the box: You may do it with the require system too but you graph would be much complexer since the pure libraries would sit in it.
- composable webservices: I can easily create web services by composing the endpoints I need. That way, if it needs a database it will be instantiated, but if, by chance the composed webservice never need a db connection, it will just be ignored and consume needed resources only.
- strong dependencies: with the
context
object approach services/controllers are not tied with the actual services they depends on. Thecontext
object is like a god object that may or may not contain the service you need. It may take some time to debug situations like a service rename/split. With a DI system the code break and you just have to fix it up. - fatal errors handling: if a required service goes wrong (typically a connection broke) you can handle it simply and properly crash the process. Handling such a situation by hand and gracefully shutdown is typically complex and error prone if you have to do it by hand.
That said, I agree with you on the statement that a DI approach may not be the good approach especially for small/PoC/MVP backends. This is why I made efforts to fit with the context
object approach so that you may just not use knifecycle
and til use services that where primarily build for it. Basically, a knifecycle
service is a function taking the context object as a first parameter and returning a promise of the actual service instance. A provider is a bit more complex since it returns a promise of an object with the actual service instance but also has hooks to shut it down and listen to fatal errors.
It has the nice side effect to also help reuse service that were primarily designed for the context
object approach. Using your get GetTimeRoute.js
file in my apps would simply looks like this:
const GetTimeRoute = require('./GetTimeRoute')
// (....)
$.service('time', $.depends(['now', 'logger'], GetTimeRoute));
// let's say someday I need it but with a distant timer:
$.service('time', $.depends(['now:remoteNow', 'logger'], GetTimeRoute));
I hope I answered well to your wonderings, if not, let me know I'd be happy to give your ore input.
Edit: There are some choices I am not happy with, for example, dependencies declarations. The 2th version should be better on that particular matter and improve the compatibility with the context
object approach #24
from knifecycle.
Worth mentioning, the problem has already been discussed in Stack Overflow. The chosen answer tends to the context
method while the next prone DI. http://stackoverflow.com/questions/9250851/do-i-need-dependency-injection-in-nodejs-or-how-to-deal-with
Both has valid arguments, in a way, the Knifecycle approach reconcile them by not tiding code to it and allowing using the both approach without changing your services implementation.
Closing since it is clear that trade-off exists for both approaches and it is a matter of taste.
from knifecycle.
Related Issues (20)
- An in-range update of eslint-plugin-prettier is breaking the build 🚨 HOT 3
- An in-range update of browserify is breaking the build 🚨 HOT 3
- An in-range update of karma-browserify is breaking the build 🚨 HOT 1
- SPECIAL_PROPS types declarations are bad
- `init` for services initializers, `provide` for services provider ?
- Detect autoloading dead locks
- Better naming for `serviceName` / `mappedName`
- Export initializer map as a public API
- Consider using an overridable `Services` interface
- Integrate the `whook` `SERVICE_NAME_MAP` in this library
- Allow building with internal dependencies
- Consider changing some internal services to singletons HOT 1
- In some very particular situations, the `run()` method ends up with a 13 exit code
- Document `$*` internal services types
- Consider moving `$destroy` to a Knifecycle method?
- An in-range update of metapak is breaking the build 🚨 HOT 5
- Improve the `$injector` service HOT 1
- `$injector` should accept flags
- An in-range update of sinon is breaking the build 🚨 HOT 1
- An in-range update of sinon is breaking the build 🚨 HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from knifecycle.