4 ms·
Classes: JavaScript developers couldn't be arsed to learn prototypical inheritance, so they added class-based inheritance. Except they didn't really--classes in
by kerkeslager 6y ago
Classes: JavaScript developers couldn't be arsed to learn prototypical inheritance, so they added class-based inheritance. Except they didn't really--classes in JavaScript are just an abstraction built around prototypical inheritance. So now you have to understand prototypical inheritance to understand how the class abstraction leaks. It's fewer lines of code, but it brings in a bunch of implicit complexity.
Promises: this is just syntactic sugar around callbacks, and does nothing to address the underlying problems of why callbacks were painful. It does introduce two ways of doing the same thing though, so now if you want to write any sort of abstractions you have to handle both ways.
Leaning hard into global frameworks that actively resist reusability and composition: Angular, Ember, etc. just start from the assumption you're writing an SPA. React is a rare gem of an exception, and is an awesome project, but there you have Flux/Redux/etc. trying to turn every React App into an SPA. This is probably the clearest example of JS projects being unsustainable: if you sacrifice reuse and composability in order to have a framework that does a lot for you, that lets you spin up projects quickly, but the project will slowly grind to a halt. React projects are great as long as you can fight the fight to keep Redux et al out, but eventually Redux fanboy gets it in and it quickly consumes your project. Global state is bad, folks. And don't tell me about reducers: I know, and if you think that means there isn't global state, that's only because you don't understand what global state and/or reducers are. I also am not interested in hearing about the other library you use to clean up your Redux code--instead of piling on more libraries to fix the problems you introduced, don't introduce the problems in the first place.
- no_wizard 6y agoSo, I see small bits here, that all boil down to developers not understanding enough about their language of choice. The web being the vast platform that it is and JavaScript eating so many domains may very well be a situation where not having full mastery of a language will still get you very far perhaps - which says a ton of positive about the platforms imo- but that’s the heart of what I’m seeing here. So, perhaps the issue Heyer is lack of education, not that the ecosystem itself is unquestionably broken? Also, curious, how do you handle state full actions without some kind of global? Genuinely curious
- kerkeslager 6y ago> The web being the vast platform that it is and JavaScript eating so many domains may very well be a situation where not having full mastery of a language will still get you very far perhaps Sure, it gets you into a project far enough to commit a lot of resources to it, and then falls over. > So, perhaps the issue Heyer is lack of education, not that the ecosystem itself is unquestionably broken? The problem may be a lack of education, but that becomes a problem with the ecosystem when the uneducated are determining the direction of the language. Classes are a feature of JavaScript now: that's irreversible damage done to the language. We can educate people about prototypical inheritance and explain to them why hacking classes over top of them is a bad idea, but that's too little too late: we can't remove classes from the language because there's already too much code that depends on them. And we can't even add classes into linters and say "don't use them", because as another commenter pointed out, core language features now depend on it. At this point, we have to embrace the suck. And there's a fundamental opposition in the JS community to education. Education starts with admitting you don't know something, and you can see in this thread a lot of people jumping in to defend the JS ecosystem. But the type of defenses you see are telling: instead of discussing the technical merits of the decisions made, people are shooting the messenger[1] or taking it personally[2]. The only defense of JS that's vaguely technical is brundolf's post, which isn't so much a defense of JS as a strategy for writing good code in a crappy language. Not a single post here is actually defending the JS ecosystem on technical grounds. > Also, curious, how do you handle state full actions without some kind of global? Genuinely curious Let's say you are writing a configuration interface for virtual servers. You have three attributes on sliders bars: memory units, CPUs, and solid state drives. There's also a total cost field. The Redux global state way looks something like: 1. Have the CPUs, Memory Units, SSDs, and Total Cost in a global store. 2. Create 3 actions and corresponding reducers that update the Total Cost when any of the slider bars change. 3. Create 3 slider bar components, which dispatch to the global store with the proper actions. 4. Create a base component that renders the whole thing. This approach already runs into some problems: 1. First, you've got three slider components that are basically the same. You can pull out the rendering code into a Slider superclass, and that reduces the repetition, but your reusability is limited: every time you want to add a slider elsewhere in the app you have to write a whole new component. And when you look at those components, you've got a lot of implicit code being pulled in by the superclass, which means you have to switch between the component and the supercomponent to understand what's going on. 2. Your reducers operate on changes in different pieces of data, but ultimately each all have to know about all three data sources to calculate the total. You can check out "Reusing Reducer Logic"[3] and that's certainly a better idea than repeating yourself three times, but you can see that there's a complexity explosion happening here. 3. In actuality, what happens too often is the duplication is just left in the three slider classes, and you have three reducers since reuse is too complex. Even if you're very disciplined about it, the complexity of achieving reuse sometimes mean you don't have time or energy to do it. In short: this design punishes reusability and rewards duplication. 4. If you want to have multiple private servers, you now have to change literally every single one of these components, because every single one needs to know in some way which server it's operating on. Let's design the same functionality, without Redux: 1. Have a slider component which accepts a min, max, initialValue and onValueChanged callback as props. 2. Have a parent component that holds the three values in its state, and renders the three sliders with onValueChanged callbacks that update the parent component's state. The total can be rendered without being stored in state, but if you want to have multiple servers on the page, you might want to put the total in state. At first glance, each of these components is slightly larger, and it seems annoying to have to pass all the info into the slider components. But consider the benefits: 1. All your server state is in one place. No one else stores information on servers, and nowhere else even knows that servers exist. It's decoupled. 2. Because of this decoupling, the slider is a reusable component. You can use the same slider to modify literally anything with a min/max/value, favoring composition over inheritance[4]. 3. The only thing you have to understand here is React components. The complexity is greatly reduced. 4. If you want to have multiple servers on the page, the parent component is already most of the way to being a reusable component. All you have to do is expose props for the initial server configuration, and an onServerChanged handler. There's one gotcha here: changes to the sliders need to propagate up to the parent of the parent component and still trigger the proper events and re-rendering. Pitfalls can be avoided here by using an immutability library--I prefer Immer, but I imagine ImmutableJS can do the same things. You could even roll your own, since you really don't need much to handle this--a simple set of copy-on-write functions would be adequate, although they would stop being performant if your data structure gets more complex. [1] "This sounds like the sort of thing I hear from folks who have only passively dealt with the Javascript ecosystem" [2] "Almost every comment thread, regardless of topic, has someone shitting on front-end developers and it's extremely demoralizing." [3] https://redux.js.org/recipes/structuring-reducers/reusing-reducer-logic https://redux.js.org/recipes/structuring-reducers/reusing-re... [4] https://en.wikipedia.org/wiki/Composition_over_inheritance https://en.wikipedia.org/wiki/Composition_over_inheritance
- csnover 6y agoThe classes thing is even worse than what you are describing since it is the only way to create correctly functioning sub-types of built-ins (e.g. `Error`). So not only is it still syntactic sugar for prototype-based inheritance for most things, there are also these edge cases where there’s actually no fully functional prototype-based equivalent.