| >Decoupling your dependency seems reasonable, but you can do it much simpler. > type GetProject = (...) => ...
> type ProjectCRUD = { get: GetProject, set: ... } > constructor(private projectCrud: ProjectCrud) Yep that is a more concise way of doing the same thing. I've considered that approach and it seems perfectly reasonable, even cleaner. The only reason I haven't is because constructors offer a more standardised approach to object creation for service type objects that other developers are familiar with, rather than higher order functions or function constructors. Although my method is kind of bespoke anyway so I could go either way. Another advantage of your approach is composing finer grained functions or objects with methods into more expansive services becomes delightfully easy. >[1]: https://news.ycombinator.com/item?id=31547975 - I'd love to hear opinions on that. I've tried to use TypeScriot DI containers... Oh I've tried..
But eventually they all just feel gross. These days I'm perfectly happy having a bootstrap / createServices method for the application, or with multiple entry points each requiring a subset of services with different configurations, different create<command>Services functions. Works well for CLI apps. Downside is when there are too many entry points with different depenencies, like an HTTP API, you don't want to create a bootstrap method for each entrypoint. In this case I create all services once on bootup. I pass the request context as method argument. Don't have a perfect way yet of doing request-level services like GraphQL caching. Currently I lazy load request level services on request context. |
> Yep that is a more concise way of doing the same thing
Your interfaces still dictate a method name and signature that must be known by both parties. I would argue that this connection is the concern of the integrating layer. If either party changes, here's where the error should occur:
Naturally, this needs some caution. If the boundaries aren't chosen well, the integration layer grows.I think you're right that our fundamental difference is the desire to stick to a more standardized class-based architecture. I like js-classes to communicate that something is stateful. But conceptually, they're more hindering than helpful.