| I keep our stack mostly functional and that’s how it was done before me on our current project. A few objects contain state like say a DB connection/client or a RequestContext you pass down through your request handler middleware’s. Those are an OOP class with an interface definition. Everything else is just functions and closures. We also generate interface objects from our GraphQL types but that’s not a real OOP type, it’s just an interface. If you keep to that structure, you’ll largely avoid the whole polymorphism OOP type hierarchy hell and all the dangers that come with it. As for DI (dependency injection), that’s honestly just a fancy form of passing parameters down through function calls. Technically, the RequestContext I mentioned before is a “ball of mud” provider pattern DI code smell. So maybe down the road we will use DI to create more constrained context scopes. If I do go that route for DI, I would likely strongly follow a CQRS style class pattern to inject objects and keep them nicely named and organized. Would also fit nicely pattern wise with the existing function + closures architecture. But yeah, overall, stick to functions and closures, use OOP style classes sparingly and you’ll get the best of all worlds. |