If you are starting out as a developer, you might run into these conflicting schools of thought: should I write "functional style" with its "pure functions" or go with "object oriented classes"?
The answer would be really long and this is going to be just a quick tip.
If you are going to have several similar objects that persist over time (i.e. you keep them around for a long time and you regularly) and have some form of state that you access a
classis a really good choice. However if you just need to transform an object to another object a
functionis your best bet.
The symptoms of not needing a class
The feature a
class is truly giving us is accessing
this in any of the defined
functions. When some or more of your class methods do not access
this and only the parameters passed and they also return the result, then you will need a
function. Even better if you can make the
function pure (in other words none of the parameters passed in are mutated)...
The algorithm to refactor this
- Find a class method that do not access
this. Extract it into a method and update the depending methods.
- Check the class again, if the changed methods no longer access
this: move them out as well.
- If every method access
thisyou have the real class that is actually managing its own state.
Only for the curious
The classic example of breaking the functional paradigm is that on an array
.sort() method mutates the array, while
.map() returns you a new array instance. This is inconsistent and creates regular problems.
function of an
object and lose its
this. You can also bind a
function to a totally different
object. There is a lot of frustration voiced when this phenomenon dawns on a developer coming from real object oriented background.
Questions, mistakes or do you wish examples? Blogging and learning is a collaborative effort, I need your help to help you. 🤝 Let me know in the comments! Cheers!
Top comments (11)
My answer would be that you don't need classes. If you need encapsulation you can use the module system, and if you need to hold internal state, you can use closures, or even generators, so you don't need classes for that either. My general advice is: Try to code something and before defaulting to a
class, think how can you write that if it was only a function. Generally that solution is cleaner, easier to maintain and test.
It depends very much on the programming paradigm you apply. Traditionally OOP applications benefit from classes in JS, but is that the kind of JS we want to write? Do we prefer functional programming, or do we want to go back to using the actual design of the language and relying on prototypes?
Functional programming is certainly seeing a new renaissance in JS, but rarely in the terms that are actually related to traditional functional programming (pure functions, higher-order-functions, declarative programming). Prototype-based programming is all but gone, save for polyfills. It's certainly an interesting development.
A very common misconception is that OOP and classes are the same thing, or that you need classes in order to do OOP. They are related, but only because classes are "one way of doing encapsulation", in languages like JS/TS there are better ways. Just because you don't use classes, that doesn't mean you aren't doing OOP. There's a great article by Eric Elliot about this, but long story short is that you can do OOP without classes (and I'm not talking about using prototype, because that's just a more verbose way of using
I agree with most of this (particularly the relative verbosity of class vs prototype), though I would argue that classes in JS are still the better way to do OOP. OOP isn't just about encapsulation, it's about polymorphism and data transmission just as well. All of those are certainly helped by a clear class structure over module-based encapsulation.
classkeyword or not - the objects instantiated still rely on prototypal inheritance. And in performance conscious code bases constructor functions are still "assembled" - that way method implementations can be shared by otherwise unrelated constructor functions (see Preact).
Class free OOP doesn't relate to implementing inheritance with prototypes. "OOP with functions" typically refers to a plain literal object holding references to functions that share data through the closure of the factory function that created them.
More often than not I hear people complaining about brittle, deep, complex class hierarchies.
"Favor object composition over class inheritance"
Gamma, Erich et al. "Design Patterns Elements of Reusable Object-Oriented Software". Putting Resuse Mechanisms to Work, p.20, 1994
So a "clear class structure" doesn't seem to be a pit of success for OOD/P in practice.
Tell me you're planning on writing an article. Every time I read a comment of yours is excellent 🤩
Prototype-based programming is truly gone, I only realized it when I failed an interview question about prototypal inheritance. "Well" I said "I haven't written anything prototype related in the last 4 years."
Onto the other approaches: since the language was not designed for either, doing them as they were written requires ugly hacks and clunky solutions. For the love of god I despise for example when I see a trainwreck like
myThing(354)('adf')((_, stuff) => stuff.process()). If you stick to the basic rule of being as clear as possible with the least amount of boilerplate you won't use anonymous function compositions nor you won't fire up a whole dependency injection system just you can mock two dependencies for a test.
Imho I prefer the functional programming over OOP.
I know you're going to react to this and I want to learn more.