DEV Community

Discussion on: A Successful IOC Pattern with Functions in TypeScript

Collapse
 
komanton profile image
Anton Komarov • Edited

Thanks Rasmus!👍
Very useful article especially for programmers with OOP experience.

For now, my question at this moment what is the best choice for my client and for the feature: write code only with higher-order functions, like you presented, or use only classes with constructors?

Collapse
 
mindplay profile image
Rasmus Schultz

That's a difficult question to answer without getting into religious territory. 😉

There are FP purists who will knock on OOP and ridicule most of the best practices we rigorously apply to ensure quality. I'm not a purist, and not experienced enough with FP to say how right or wrong they might be.

I can say this from my recent experience, which is what prompted me to write this article: I've been sticking exclusively to functions in this project, and the dependency injection pattern demonstrated here - and I've never had an easier time writing or maintaining my tests.

A function has precisely the dependencies it needs to do precisely the thing it needs to do - whereas, to test a method of a class, you need all the state and dependencies required by the entire class. Whenever your class has a new constructor argument, all the method tests and mocks need updates - you don't have this friction with functions.

I've found my tests are more resilient to refactoring somehow. With OOP tests, my unit tests would frequently break with refactoring - sometimes to the point where it's tempting to scrap the test or rewrite it. It has been much easier to adjust my function tests, even after major refactoring.

In fact, this week I introduced a class to the project, and immediately felt the difficulty of testing and then refactoring that class. Unfortunately, I can't get rid of this class, as it is part of a public API that must be backwards compatible with a legacy system. If I had the choice, I would definitely refactor that to functions.

It seems to scale to greater complexity as well. With OOP, I generally find that development slows down as the project grows - whereas with functions (and this IOC approach) my pace has been steady, even as this project grows larger and more complex. Dependency management is a no-brainer, it just sort of "happens" without much thinking about dependencies beyond the unit you're working on. It all just "unfolds" at run-time without much planning. The only pain that seems to carry over from OOP is the risk creating a circular dependency - this can still be a bit difficult to identify and fix.

The benefits are quite clear to me at this point, even if I still have some difficulty explaining the precise reasons. So this is subjective, but I feel like this is lighter, faster, and the functions are more independent, more fluid to work with than classes.

I would highly recommend you try it. 🙂

Collapse
 
komanton profile image
Anton Komarov

Thanks! I will try it exactly! Looks very attractive! 👍

Also, I noticed very similar approach in Rust programming language where no classes at all. Only structs and Traits (the concept which similar to higher-order functions in JS).