Are you mired in a JavaScript codebase full of classes? Are you new to JavaScript and tempted to reuse patterns from object oriented languages? D...
For further actions, you may consider blocking this person and/or reporting abuse
Ummm. I don't see why you are trying to avoid classes, they are useful and as you mentioned, soon they will be getting more powerful. And you haven't replaced classes with modules, you replaced them with closures. And after removing the comments and blank lines, both implementations of your book class/closure took the same number of lines.
Seriously, your point flew over my head. You are replacing classes with something less flexible, with no gains at all. Modules are nice, and they can be used to wrap classes just like they wrap closures. So, the module point is out of the window.
And about being "more behaviorally consistent", "more pleasant to maintain", "less cumbersome to write", and "easier to read". Really? In what way? Shouldn't you have explained these before concluding them?
Instead of telling people not to use classes, this would have been a nice article about closures and how they can be used for those who have class-phobia.
Thanks for reading! To be honest I care less about how people code and more that they understand the language that they are coding in. I tried to bring that point home in the end so sorry if that didn't come across. I'll do better next time ;)
I use functions over classes and I like it. I dont see the need to write a class in nodejs for my use cases.
To use a method in a class you need to import the entire class in the file you are wanting to use the method... modules allow you to pick and import specific functionality.
I like the fact that classes scope functions
product.get()
orproduct.create()
- but I use good naming conventions on my functionsproductGetAll()
andproductCreate()
and my IDE loves that because when i start typing 'prod' it gives me a list of all available methods for products - and this works for my db queries, router, utils etc.For me its about developer experience and patterns to make coding in my projects easy. I just dont see how classes would benefit me with the code i write - but that doesnt mean i avoid them, i just use what I feel is best for my projects.
Hey! Nice work with the Article, but I think the code focus way to much on high level implications rather than low-level ones. Meaning the implications of using Classes and how they really relate with JS prior ES6.
Overall, Classes came to allow more people easily start using the concept of Object without fully needing to understand/learn Prototype Oriented Programming which is what JS implements under the hood. Along with that, Classes does pretty more couple of things that easies the need for dealing with
this
and for instances Classes and Instances as well.The Article quite implies that modules are better than Classes which is not the case, and they shouldn’t be compared as are totally different things. A more real comparison is to construct Objects out of Functions and export them, or use Prototype for attaching methods and more.
Again, will be better to compare it to other things instead of directly against modules :)
Hi Charlie, thanks for reading! That focus was intentional because users such as yourself have a better low level grasp and aren't as quick to use these patterns. In my honest opinion if you know what you're doing, you can do whatever want, but many people have limited exposure and tend to run with whatever they've seen.
Regarding classes vs functions with methods, that's exactly how JS classes work under the hood so it wasn't an alternative I was interested in exploring. Good point though!
Hi Johnny :)
Sure you’re right on your first point, for new adopters it can be easy pick this approach mostly if your coming from a OOP language background like Java or C# (which are the most common), and I also do agree that as long as you’re confortable with what you’re doing it, should not be a problem at all :)
Sure! I felt it like more natural to compare as even that the JS Modules kinda can work like this, sometimes new adopters can confused them with what the Classes are really trying to achieve in JS. Thanks a lot for the feedback! Keep it going 🙌
I actually think it's more confusing having two paradigms. I sometimes open Javascript files that are written as classes and it takes me a little it of time to understand exactly what they were trying to accomplish since I'm used to working differently in JS. I'm sure it's the same if a OOP programmer opens a prototype/object based Javascript file.
Anyway, I'm not even sure classes in Javascript really give OOP programmers all the flexibility that classes in other languages do. Fortunately that's changing with the inclusion of things like decorators. Since classes in Javascript are purely syntactic sugar, I also wonder what extra you are getting? It's not like there's extra functionality that comes with classes.
Hi Johnny! Thanks for reading! It's definitely best if teams discuss beforehand which patterns to use and which to avoid. Consistency I find is usually more important than the patterns you end up sticking with.
Well, object oriented is a pretty strong and established programming paradigm. And it was introduced mainly for code organization! And object oriented is not about classes. It's about encapsulation, polymorphism and inheritance. The alternative that the author is suggesting is STILL OBJECT ORIENTED! Just a different syntax. If he was suggesting a different paradigm, like function or data oriented, maybe the article would have been more useful.
The reason why the article is getting heated comments is because the author is asking for them. You can clearly see that from the graphics used in his article. Besides, the use of strong language, like "Don't use classes" gives you the feeling that you are going to behold a great change. In a field where there's no absolute right and wrong, you expect someone telling you not to do something to have a pretty strong argument. Honestly, I feel like I was click-baited.
Classes in Javascript are very basic. The real benefit is DI when using decorators with Typescript. In one of my previous work I saw that if there's no clear structure in place it becomes a mess and over time I feel now that JS development suffers from a common structure, conventions. At scale the benefit of DI becomes useful but then when you reach that stage then you already have a mess that is too big to tackle and not worth it business wise. Developers create low quality code as result and best practices are an ideal in theory. Functions with 600 lines were looked over like it's fine and the company was just 5 years old. We really need to use something like Nest.js.
Nest.js is one of the few exceptions I make when it comes to using classes in Node. Thanks for reading!
DI becomes useful immediately with 0 lines of code. The mess will slow you down in minutes, not years. There is no excuse not to use best practices such as TDD and applying design patterns even for personal projects.
You definitely can replace classes with modules in the same way as you can just use static classes/methods in Java/C#/etc instead of object instances, but...
DI allows you to achieve loose coupling in your codebase and convenient mocking of different subsystems in your project's unit tests.
This very helps if you're working on a relatively large monolith project.
If it's the right tool for the job, by all means. Thanks for reading!
I've gone back and forth with classes, however I absolutely love typescript and we use it exclusively and as such I've come to appreciate classes more especially when paired with MobX. Mobx can automatically bind class methods and I basically never have to worry about "this context" being hijacked, it's just not a thing. And even if you want to create a method on a class that isn't a mobx action or flow, you can still enumerate all the functions in a class and automatically bind them all.
And with Stage 3 decorators coming classes are about to get really amazing. And writing little functions like "createBook" that returns it's methods/getters etc is really troublesome.
In typescript I can do this
Vanilla js, yeah classes are kind of meh, you can create classes via functions, but it's cumbersome to do that in Typescript. Typescript strongly prefers using classes when a class like thing is deseriable.
Very good
Thanks for reading!!
I didn't want to use classes in my latest project for some of the reasons stated here, but they're actually much faster in some use cases (at least from my tests creating thousands of instances).
If you want the following features: inheritance/extending, overriding getters/setters on sub classes (key word "overriding"), then you can't beat classes in javascript.
I've toyed around for ages with factory function+mixins, and prototypes. I don't know what's going on under the hood but there are huge penalty's with non-class based patterns that allow for getter/setter overrides. Unless someone can show me a pattern that works (it's a hard topic to find information on actually), then I'm running on the assumption that browsers have optimized classes in some special way when it comes to my use case.
I'm guessing the browser translates class code to objects/prototypes for each sub class. Meaning that it builds one generator it re-references for each sub class and thus avoids going through the slow mixin process that assigns/joins objects on every instance in a factory/prototype pattern. (You need mixins to override getters/setters as far as I know, but I'd love some guidance if another way).
Nice rant.
There's nothing wrong with organizing your code in classes. It's actually a very good way when language supports it. I'd say it is the best way generally. Everyone understands classes. If they don't understand classes, are they even really a programmer?
So? There's nothing wrong with having a class even when you create only one instance, same as there is nothing wrong with having a closure when you only have only one instance. I often enough create classes in other languages of which I only have one instance at runtime but it makes it easier to test the module(dependency injection and substitution with mocks or objects with specific state in tests).
Anyway, in your rant about classes vs closures this paragraph of yours doesn't add any value and isn't an argument against classes in the classes vs closures debate. Having one instance at runtime is just fine in either case. Moving on.
Having fields is not an attribute of an object in OOP. And it's easy to demonstrate. Take any interface, then create an object that implements that interface and make that object save its state in the database by calling some static functions in a namespace. Now you have an object that fulfils your requirements, implements an interface, stores its state in a database. You can program against an interface, use that object successfully, yet, that object has no fields.
Wrong again. Not long ago I've created a
IKeyboardGateway
interface with methodGetKeyboardState
and created an implementation of that interface:KeyboardGateway
that returns an array of size 255 with the state for each key of the keyboard. TheKeyboardGateway
object didn't operate on an object's internal state. TheKeyboardGateway
object called system'sGetKeyState
function(Windows in this case for me).Other modules that used
IKeyboardGateway
object didn't know it was implemented using theKeyboardGateway
class. All the other modules knew isIKeyboardGateway
and about one method:GetKeyboardState
. That's where OOP is happening: in programming against interfaces. Not in creating classes with a bunch of fields and methods. You can have solutions with classes all over the place in each and every file, and have nothing other than classes, and do no object-oriented programming: all of your dependencies will be hardcoded to specific implementations.Uncle Bob nicely explains what OOP is and what an object is here:
youtu.be/oar-T2KovwE?t=3246
Yeah, there's nothing wrong with using classes in JS. And yeah you can write very bad code with classes. Same as with closures.
That's too vague and needs some concrete example which would demonstrate that. And I doubt it will happen. If we implement the same thing with closure, it'll be just as hard to understand.
JS modules aren't alternative to classes in JS. Alternative to classes is closures. In your example later you provided alternative solution with closure, not module. Module can export either a class or a closure.
False again. You don't need to declare fields in a class(outside of functions). You can just set them in a constructor, same way you did in a closure. You'll just have to add
this.
.This is additional boilerplate code: you need to return a whole struct with variables in it.
In classes you declare private fields with
this.#myVariableName
and in closures you return the struct with public fields available for use. That's around the same amount of boilerplate code.No. It's not about redundant code. It's about managing the dependencies.
While everyone is hanging on to classes, massive frameworks like React (hooks) and Vue (composition api) are moving away from them? We will come back full circle once we realize that classes are not really needed,
this
is one of the most confusing things you can teach to a beginner, and composition > inheritance.I actually think the author did a decent job, but this argument is the winner in my opinion though. I hate the
this
keyword. There's a reason most of the popular packages out there adopt a "just works" philosophy. I think languages should adopt a similar philosophy. I recently converted one of my personal projects from classes to functions and the bugs and head scratching started to fade.Wrong. They're not competing. They're just different tools for different situations. It's like saying "saw > hammer". In some situation the hammer is better, and in other the saw is better.
They're absolutely not needed. You can just create one method
main
and put all your global variables about it and code it like that, sure.On our First Date you will probably tell me to hold the fork in my left hand.
That's hilarious! Thanks for reading!
Encapsulation is associating the code with the data it acts upon. It has nothing to do with inheritance. Closures do the same, they associate the code with the data.
It's ok to say we don't need classes. It's not ok to say "Hey! Don't use classes. They are inferior!". The author has shown a nice technique to avoid using classes, but he didn't state valid reasons to avoid them in the first place. Yet, he was very assertive about his stance, which some of us find less appealing. This could mislead some beginners into believing his -so far- baseless assertions. He could present his findings as another way to do things, not as the "correct" way to do things. That's the whole point I'm trying to make.
This is pretty cool! I never curry as much as I would like to in practice! Thanks for reading!
Re: heated comments....it's not to bad here on dev.to but on the medium cross post....LOL
I don't find this a particularly strong argument. And this is coming from someone who generally avoids classes in JavaScript. That said, I don't think referencing a module-level variable is a "closure." A closure is defined as:
"A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function."
I think what is commonly meant as a closure is the private scope of a function's outer scope. A closure is another function that "closes over" that private scope. The local variables are not observable or mutatable outside the function's scope.
A module-level variable, on the other hand, is observable by either other functions in the module, and even functions outside the module (if exported).
One of the reasons your argument isn't persuasive is that I'm not sure you've done your homework.
A more reasonable way to accomplish what you are trying to do is by actually using closures and returning functions that close over private state. This is, in fact, probably what the class based syntax transpiles down to when using Babel.