I built a SPA recently and learned pretty quickly to replace `on('scroll', handler)` with a set-flag-and-sweep-at-slower-interval solution to bring down CPU usage.
While something like React alone isn't slow, building a SPA means you're taking on a lot more responsibility, and there's a lot more things that can go wrong.
Even something like "when user clicks an item, make loader spin until server response, and then render the detail page with the data" can feel much, much slower even though it's not from a clock-time standpoint.
Aside: Using a slow device as your main testing device is a life-changer if you want to catch this stuff early. It's hard to ignore this stuff when you have to feel the pain yourself on every refresh. Good reason to always keep your old phone around.
I prefer WPF :-). Touche, but Google has more of a habit of killing off perfectly good stuff. But MS does it too. With Silverlight market forces, especially HTML5/mobile and Apple policies most likely killed it.
Looks like they improved a ton with the v4.0 release. I used this just a few months ago and it was painful. Undocumented components, lack of basic customization, some bugs. Seems like that stuff has been addressed. I remember Evergreen adding about 60kB to my bundle size though (mostly due to its icons). I hope that's been reduced.
Hi. I maintain the library along with some others at Elastic. That warning is essentially us being good open source citizens and being very clear about how we maintain it. A lot of these other libraries are built specifically for their own products, no different then us. We just wanted to make it clear that the direction of the library and its maintenance is primarily driven by the needs of Elastic, rather than as some general community UI kit.
All that said, it certainly works fine as a general kit, and we build it with that practicality, it's just not something we officially support.
As far as stability, my team is pretty well resourced (and growing if there are any engineers interested!). We're using the library in many places around Elastic and its not going away anytime soon.
I've looked through most of the kits out there and they all have their pros and cons. Likely our biggest selling point is that it aims to be fully accessible and comes with a lot of fun charting libs. That puts its sweet spot for use in enterprise applications. It's also completely themable with about 8 lines of Sass variables.
That uses React to attach onClick, so obviously yes. I'm saying without React. You said:
> The only difference between if this were a web component vs a React component is that the consumer would not capitalize the name. Instead of `<Button appearance="primary">` they would do `<evergreen-button appearance="primary">`.
If you're not using React, you obviously can't do `onClick={...some function here...}` with Web Components, you have to use the shitty DOM APIs.
I guess I see what you're saying that web components can seem be consumed as expected from a React app. I thought we were talking about not using React at all.
But I would expect this still would not work as expected with props like `children` or other props that accept React elements. It seems like the web component would be expecting Node instances, not React elements. Since components can decide whether or not to render their children, they wouldn't be backed by Nodes yet when the web component received them. So it seems like it'd have to know whether it's dealing with React and use ReactDOM.render directly.
Of course you can set props on a WC, it's just a DOM node. You can do everything you can do with any other standard node + exposed API. You could use jsx/vdom any other solution to set up props/events.
IMO saying 60kb of react+vdom code vs 6kb of templating library that builds on top of template literals is equally non-standard is not a fair comparison.
I realize you can set properties, obviously. Those are not the same as using attributes, which is what React's props are more equivalent to. e.g. you can't do <my-button onClick={...some function here...} />. So using it does indeed suck the same way using normal DOM elements sucks: you need a reference to the created node, addEventListener, etc.
That's what makes the grandparent's statement incorrect:
> The only difference between if this were a web component vs a React component is that the consumer would not capitalize the name. Instead of `<Button appearance="primary">` they would do `<evergreen-button appearance="primary">`. That's it.
You can with lit-html/stencil, but yes you need something to take care of that for you, which is very small dependancy. WC's are NOT supposed to be consumed directly unless you do very simple things.
According to netmarketshare[0], on desktop[1], Edge currently has 3.8% market share, more than Safari and Opera together. Combining mobile+desktop Edge has 2%.
Edge cannot be ignored if one is serious about any kind of business: that's 3-4 out of every 100 desktop users (existing or potential customers), or 'just' 2/100 if one includes mobile.
— Honestly, it seems that you are trolling. But I post the above stats in case you are not. But I also back it up with my own personal 'anecdata': I build business-to-business ecommerce, in our specific market our users are primarily (>95%) using desktop browsers, we have many thousands of existing business relationships, we cannot mandate which browsers they use — we draw the line at having the site simply work in all "modern browsers", which obviously includes Edge.
It doesn't really matter whether it's "many browsers" that don't support Web Components, or whether it's just one major browser. For many businesses, choosing WC is simply not a viable option for the foreseeable future.
You are reading it wrong, it is not me that mandates the browsers.
I have written already in multiple answers, it is the customers that decide which browsers should a given project support, by explicitly stating them on the project delivery contract.
So your customers care about EDGE, fine. Many don't.
I don't think I would support this in an engineering organization. There are so many people focused on solving these problems, that I believe not being able to make an existing solution work well is for lack of trying. I'm a bit out of the loop on React, however if I had to guess Segment would be better off investing in adapting an existing framework, no matter how nice this one might be.
Mobile is all about Safari and Chrome in what concerns Request For Proposals and delivery acceptance testing.
So real world customers don't care about anything else. If it happens to work, or a team member decides to go at it on their own outside project budget, it is a nice to have feature that's it.
I just had to come back to this comment after testing in a couple of browsers, focusing on Safari and Chrome.
Going to https://www.reddit.com/r/whatisthisthing/comments/9oz5sa/wha... and scrolling is OK in Safari but actually pretty laggy compared to old mode. It's definitely not how a modern web site should perform. Testing with Chrome, it was fast in the beginning, but if you scroll up and down for about 15-20 seconds, CPU load goes up and my laptops fan start spinning.
So no, I do not believe reddit's new design is "performant" at all.
One has to wonder - if Reddit's engineers can't get React right (I'm sure they hire smart people), is it really not a problem with React in the end?
> No, we're talking about 2-3 line functions. Stop arguing with a straw man. You're taking what you know to be true about complex code, and then asserting that those things are also true with simple code. That doesn't work.
The library in question is literally 50 lines of code. About 30 when you remove the exports and comments at the top. I find it somewhat ironic that you are so opposed to using utility libraries and you didn't even bother to look at the one in play here.
> The beauty is that because we are rolling our own function, we only need to support the single function signature we decide we're going to stick to in our codebase. Supporting every use-case becomes a moot point.
No it doesn't. All the use-cases are useful. You use strings when you need default classes and objects when you have conditional classes. You can't implement both of those in two lines of code.
> The author of the library has to support the 10^5 people who use his code, meaning he's more likely to merge silly pull requests like "should take objects",
It's always taken objects as properties and for good reason: it's a clean way to separate conditional classes from unconditional ones.
But sure dude, all those features are insane. Put his code up to a solid 30 lines. Really saving the bacon by rolling your own that doesn't do the same thing.
> Learning dozens of APIs takes just as much time as implementing them for a certain set of functions. That set is different for everyone, but it is not the null set for anyone.
Yeah, that's why everyone writes their own lodash. It's just a set of trivial functions.
You're absolutely wrong. If reading the docs were harder/more work than writing the code we'd have 100s of implementations of lodash. Instead people use lodash.
Dependency boundary? If you can't figure out what a function called classNames does in the context of a React render function in which the output of classNames is put as a value in to "className" attributes, you need to find a new job.
Dependencies cost time, effort and brain power when they actually require those things. Be thoughtful when using something that actually requires investigation. But honestly, a trivial function should be self-documenting or it really isn't trivial, is it? If I had an npm library called array-flatten are you seriously going to read the docs, or assume it flattens nested arrays?
I never said anything about writing the dependency. I'm talking about reading and writing code that uses it.
Of course it's easier to read a trivial function than the docs for a trivial function. That's what makes it trivial, it's not abstracting away anything meaningful. And of course I can easily figure out what classNames outputs.
You know what I can't figure out trivially? What inputs it takes. It's a polymorphic function. Me and Bob load up a new codebase, I open a few files and see classNames used a couple of times with an object parameter. I can now be pretty confident what the API of the function is. Bob opens up a couple of different files and sees it used with an array parameter a few times. Now he's pretty confident he's got the hang of it too. We both go off to write new components. I've got a bunch of this everywhere:
{ foo: true, bar: true, baz: true }
And Bob has a bunch of this everywhere:
[foo ? 'bar' : null, baz ? 'boop' : null]
Bam, inconsistent code. Could have easily been solved by reading the docs before using something though. And hey, at least we'll both remember for next time...
...Unless our team imports 100 of these libraries and tries to enforce a consistent use of them across the project.
There's only so much API surface area one dev can keep at the front of their mind while coding. Good devs understand this and minimize it. Bad devs pile in trivial dependencies because they don't understand their cost.
Oh, and how do I know whether flattenArray is recursive or not? What if it is and I only want to flatten one level? Does it take a second integer parameter? Or an options object? Since we're talking about JS, does it flatten Array-like objects? Is that the same API or a different one? It's almost like your example proves my point...
Yeah, and in CR you should be told not to use the object form when you have "true" as the value, as it's pointless. That's what string form is for. The "docs" are literally 5 lines where you learn you can send object literals, arrays and strings.
> There's only so much API surface area one dev can keep at the front of their mind while coding. Good devs understand this and minimize it. Bad devs pile in trivial dependencies because they don't understand their cost.
Yes, because if you implement a similar feature the remaining members of your team all know it through osmosis. The surface area of these functions is tiny, but apparently your implementation requires no investigation by anyone.
> Oh, and how do I know whether flattenArray is recursive or not?
Holy cow, man. Do you literally hand-implement EVERY utility function you've ever needed?
> It's almost like your example proves my point...
Your point seems to be: you can't manage to infer ANYTHING from a function signature AND that apparently somehow your team members can ALWAYS infer everything needed from any function YOU write.
Use code inspection and you'll never open the docs for flattenArray or anything like it again. If this is the amount of effort required for flattenArray for you, how to you actually use large libraries with HUGE surface areas?
> Yeah, and in CR you should be told not to use the object form when you have "true" as the value, as it's pointless. That's what string form is for. The "docs" are literally 5 lines where you learn you can send object literals, arrays and strings.
What a dumbass argument. So instead of writing a one line abstraction, I should invest a bunch of CR time explaining to my whole team which of 3 different APIs they should be using in this dependency I've brought in?
> Holy cow, man. Do you literally hand-implement EVERY utility function you've ever needed?
No, just the trivial ones. Have you been actually reading this thread?
> Your point seems to be: you can't manage to infer ANYTHING from a function signature
No, my point is that you can't infer the full API of a function from the arguments passed to it's invokation when the function is polymorphic.
> AND that apparently somehow your team members can ALWAYS infer everything needed from any function YOU write.
If the function is trivial, which is exactly what we've been talking about this whole time, then No. Fucking. Shit. The function is trivial and they have the source code right there.
> So instead of writing a one line abstraction, I should invest a bunch of CR time explaining to my whole team which of 3 different APIs they should be using in this dependency I've brought in?
It's not a one-liner because it doesn't support the same feature set. It supports a basic use case that may be great for trivial apps, but in the real world it isn't.
> No, just the trivial ones. Have you been actually reading this thread?
And said trivial ones must still be "learned" by your co-workers. You've saved exactly zero time.
> No, my point is that you can't infer the full API of a function from the arguments passed to it's invokation when the function is polymorphic.
You can with a glorified text-editor these days with Code Inspection. I guess that's advanced stuff we shouldn't expect our co-workers to use?
> If the function is trivial, which is exactly what we've been talking about this whole time, then No. Fucking. Shit. The function is trivial and they have the source code right there.
Yet, if the function is trivial AND is imported via npm, it suddenly requires reading docs. On one hand you argue "triviality requires reading docs" and then suggest that you can implement a similar trivial function and everyone can just look at the source code.
You're conflating a trivial function with a trivial API. The whole reason I jumped into this thread is because classnames is a great example of a trivial function with a non-trivial API. Yes, you do need to look up either the docs or the implementation to understand how to use it. I think my past examples made that clear.
What I'm saying is that it's EASIER to understand the source code than it is to understand the documentation for classnames. That's because it abstracts nothing away. It's replacing one simple API (template strings) with another one that's very similar and of roughly the same power. By turning it into a dependency you're adding an artificial barrier between it and your code base, that makes it harder for everyone to grok. Not much harder, but enough to be a pain in the ass in any codebase where that same tradeoff is made over and over.
If you can't understand that, then I don't know what to do for you. Keep writing shit JS code and making the web worse than it already is.
> There's some irony here -- all of this just to avoid dealing with string templates:
By that argument, we can just avoid everything by not making our apps dynamic!
> The classNames utility is a completely unnecessary abstraction.
The only necessary abstraction in programming is assembly since 0's and 1's are hard to reason about. The "need" in this case refers to needing to mix different primitives to make your app dynamic. Your arbitrary example above doesn't do anything because you still have conditional logic to determine what class1 class2 and class3 are, you are just doing a bunch of ugly crap in the render function rather than abstracting it. Or implementing your own version because you're smart.
It's a stupid hill to die on here... you want to argue about importing the entire lodash library because you like .chain, have at it. But I guess you can keep patting yourself on the back for avoiding importing a no-dependency 50-line library.
> Not quite, that would imply time and effort. I'm talking about reinventing the toothpick (2-3 lines of code), which is much different than reinventing a complex library for the sake of reinventing it.
Re-inventing 1000 versions of a tooth pick is reinventing the wheel.
> That's nice, but you're addressing a straw man.
You keep using that term and I'm not sure you understand what it means.
> It was said that no one is suggesting you recreate a non-trivial dependency for the sake of reducing your dependency count.
And my argument is that dependency count is one of the dumbest metrics to be interested in. Size, sure as that impacts bundle size, which in-turn, effects latency. But "count" is meaningless.
> Humor me -- the next time you use classNames for a small project
I use styled-components exclusively for React projects now.
> For example I've seen things similar to "classNames({myClass: true})" in code before.
So? Bad code is bad, that's not a library failure. Now that is a straw man.
> Can you see what is wrong with this line?
Of course I can, because I'm actually good at my job. I also wouldn't do that. Using your toaster in a bathtub is also REALLY stupid, but that doesn't mean we should ban toasters.
> When people get comfortable with abstractions, they completely forget how to write the simplest code.
No that's called laziness and it has nothing to do with dependencies. You have twice in this thread accused me of straw men inaccurately, and now wrote a paragraph dedicated to a huge straw man.
42 comments
[ 4.9 ms ] story [ 72.4 ms ] threadhttps://npmcharts.com/compare/carbon-react,antd,@blueprintjs...
I built a SPA recently and learned pretty quickly to replace `on('scroll', handler)` with a set-flag-and-sweep-at-slower-interval solution to bring down CPU usage.
While something like React alone isn't slow, building a SPA means you're taking on a lot more responsibility, and there's a lot more things that can go wrong.
Even something like "when user clicks an item, make loader spin until server response, and then render the detail page with the data" can feel much, much slower even though it's not from a clock-time standpoint.
Aside: Using a slow device as your main testing device is a life-changer if you want to catch this stuff early. It's hard to ignore this stuff when you have to feel the pain yourself on every refresh. Good reason to always keep your old phone around.
If it doesn't make the list, it is a nice to have only, in case someone on the team bothers with it.
Microsoft by using mostly Chrome at BUILD 2018 has given the sign to many businesses that it isn't worthwhile to list EDGE as a requirement.
All that said, it certainly works fine as a general kit, and we build it with that practicality, it's just not something we officially support.
As far as stability, my team is pretty well resourced (and growing if there are any engineers interested!). We're using the library in many places around Elastic and its not going away anytime soon.
I've looked through most of the kits out there and they all have their pros and cons. Likely our biggest selling point is that it aims to be fully accessible and comes with a lot of fun charting libs. That puts its sweet spot for use in enterprise applications. It's also completely themable with about 8 lines of Sass variables.
> The only difference between if this were a web component vs a React component is that the consumer would not capitalize the name. Instead of `<Button appearance="primary">` they would do `<evergreen-button appearance="primary">`.
If you're not using React, you obviously can't do `onClick={...some function here...}` with Web Components, you have to use the shitty DOM APIs.
But I would expect this still would not work as expected with props like `children` or other props that accept React elements. It seems like the web component would be expecting Node instances, not React elements. Since components can decide whether or not to render their children, they wouldn't be backed by Nodes yet when the web component received them. So it seems like it'd have to know whether it's dealing with React and use ReactDOM.render directly.
IMO saying 60kb of react+vdom code vs 6kb of templating library that builds on top of template literals is equally non-standard is not a fair comparison.
https://custom-elements-everywhere.com/
That's what makes the grandparent's statement incorrect:
> The only difference between if this were a web component vs a React component is that the consumer would not capitalize the name. Instead of `<Button appearance="primary">` they would do `<evergreen-button appearance="primary">`. That's it.
^ wrong.
Edge cannot be ignored if one is serious about any kind of business: that's 3-4 out of every 100 desktop users (existing or potential customers), or 'just' 2/100 if one includes mobile.
— Honestly, it seems that you are trolling. But I post the above stats in case you are not. But I also back it up with my own personal 'anecdata': I build business-to-business ecommerce, in our specific market our users are primarily (>95%) using desktop browsers, we have many thousands of existing business relationships, we cannot mandate which browsers they use — we draw the line at having the site simply work in all "modern browsers", which obviously includes Edge.
It doesn't really matter whether it's "many browsers" that don't support Web Components, or whether it's just one major browser. For many businesses, choosing WC is simply not a viable option for the foreseeable future.
[0] No affiliation, just googled it. [1] https://netmarketshare.com/browser-market-share.aspx
I have written already in multiple answers, it is the customers that decide which browsers should a given project support, by explicitly stating them on the project delivery contract.
So your customers care about EDGE, fine. Many don't.
So real world customers don't care about anything else. If it happens to work, or a team member decides to go at it on their own outside project budget, it is a nice to have feature that's it.
So no, I do not believe reddit's new design is "performant" at all.
One has to wonder - if Reddit's engineers can't get React right (I'm sure they hire smart people), is it really not a problem with React in the end?
The library in question is literally 50 lines of code. About 30 when you remove the exports and comments at the top. I find it somewhat ironic that you are so opposed to using utility libraries and you didn't even bother to look at the one in play here.
> The beauty is that because we are rolling our own function, we only need to support the single function signature we decide we're going to stick to in our codebase. Supporting every use-case becomes a moot point.
No it doesn't. All the use-cases are useful. You use strings when you need default classes and objects when you have conditional classes. You can't implement both of those in two lines of code.
> The author of the library has to support the 10^5 people who use his code, meaning he's more likely to merge silly pull requests like "should take objects",
It's always taken objects as properties and for good reason: it's a clean way to separate conditional classes from unconditional ones.
But sure dude, all those features are insane. Put his code up to a solid 30 lines. Really saving the bacon by rolling your own that doesn't do the same thing.
> Learning dozens of APIs takes just as much time as implementing them for a certain set of functions. That set is different for everyone, but it is not the null set for anyone.
Yeah, that's why everyone writes their own lodash. It's just a set of trivial functions.
Dependency boundary? If you can't figure out what a function called classNames does in the context of a React render function in which the output of classNames is put as a value in to "className" attributes, you need to find a new job.
Dependencies cost time, effort and brain power when they actually require those things. Be thoughtful when using something that actually requires investigation. But honestly, a trivial function should be self-documenting or it really isn't trivial, is it? If I had an npm library called array-flatten are you seriously going to read the docs, or assume it flattens nested arrays?
Of course it's easier to read a trivial function than the docs for a trivial function. That's what makes it trivial, it's not abstracting away anything meaningful. And of course I can easily figure out what classNames outputs.
You know what I can't figure out trivially? What inputs it takes. It's a polymorphic function. Me and Bob load up a new codebase, I open a few files and see classNames used a couple of times with an object parameter. I can now be pretty confident what the API of the function is. Bob opens up a couple of different files and sees it used with an array parameter a few times. Now he's pretty confident he's got the hang of it too. We both go off to write new components. I've got a bunch of this everywhere:
{ foo: true, bar: true, baz: true }
And Bob has a bunch of this everywhere:
[foo ? 'bar' : null, baz ? 'boop' : null]
Bam, inconsistent code. Could have easily been solved by reading the docs before using something though. And hey, at least we'll both remember for next time...
...Unless our team imports 100 of these libraries and tries to enforce a consistent use of them across the project.
There's only so much API surface area one dev can keep at the front of their mind while coding. Good devs understand this and minimize it. Bad devs pile in trivial dependencies because they don't understand their cost.
Oh, and how do I know whether flattenArray is recursive or not? What if it is and I only want to flatten one level? Does it take a second integer parameter? Or an options object? Since we're talking about JS, does it flatten Array-like objects? Is that the same API or a different one? It's almost like your example proves my point...
Yeah, and in CR you should be told not to use the object form when you have "true" as the value, as it's pointless. That's what string form is for. The "docs" are literally 5 lines where you learn you can send object literals, arrays and strings.
> There's only so much API surface area one dev can keep at the front of their mind while coding. Good devs understand this and minimize it. Bad devs pile in trivial dependencies because they don't understand their cost.
Yes, because if you implement a similar feature the remaining members of your team all know it through osmosis. The surface area of these functions is tiny, but apparently your implementation requires no investigation by anyone.
> Oh, and how do I know whether flattenArray is recursive or not?
Holy cow, man. Do you literally hand-implement EVERY utility function you've ever needed?
> It's almost like your example proves my point...
Your point seems to be: you can't manage to infer ANYTHING from a function signature AND that apparently somehow your team members can ALWAYS infer everything needed from any function YOU write.
Use code inspection and you'll never open the docs for flattenArray or anything like it again. If this is the amount of effort required for flattenArray for you, how to you actually use large libraries with HUGE surface areas?
What a dumbass argument. So instead of writing a one line abstraction, I should invest a bunch of CR time explaining to my whole team which of 3 different APIs they should be using in this dependency I've brought in?
> Holy cow, man. Do you literally hand-implement EVERY utility function you've ever needed?
No, just the trivial ones. Have you been actually reading this thread?
> Your point seems to be: you can't manage to infer ANYTHING from a function signature
No, my point is that you can't infer the full API of a function from the arguments passed to it's invokation when the function is polymorphic.
> AND that apparently somehow your team members can ALWAYS infer everything needed from any function YOU write.
If the function is trivial, which is exactly what we've been talking about this whole time, then No. Fucking. Shit. The function is trivial and they have the source code right there.
It's not a one-liner because it doesn't support the same feature set. It supports a basic use case that may be great for trivial apps, but in the real world it isn't.
> No, just the trivial ones. Have you been actually reading this thread?
And said trivial ones must still be "learned" by your co-workers. You've saved exactly zero time.
> No, my point is that you can't infer the full API of a function from the arguments passed to it's invokation when the function is polymorphic.
You can with a glorified text-editor these days with Code Inspection. I guess that's advanced stuff we shouldn't expect our co-workers to use?
> If the function is trivial, which is exactly what we've been talking about this whole time, then No. Fucking. Shit. The function is trivial and they have the source code right there.
Yet, if the function is trivial AND is imported via npm, it suddenly requires reading docs. On one hand you argue "triviality requires reading docs" and then suggest that you can implement a similar trivial function and everyone can just look at the source code.
And you don't see the irony here.
What I'm saying is that it's EASIER to understand the source code than it is to understand the documentation for classnames. That's because it abstracts nothing away. It's replacing one simple API (template strings) with another one that's very similar and of roughly the same power. By turning it into a dependency you're adding an artificial barrier between it and your code base, that makes it harder for everyone to grok. Not much harder, but enough to be a pain in the ass in any codebase where that same tradeoff is made over and over.
If you can't understand that, then I don't know what to do for you. Keep writing shit JS code and making the web worse than it already is.
By that argument, we can just avoid everything by not making our apps dynamic!
> The classNames utility is a completely unnecessary abstraction.
The only necessary abstraction in programming is assembly since 0's and 1's are hard to reason about. The "need" in this case refers to needing to mix different primitives to make your app dynamic. Your arbitrary example above doesn't do anything because you still have conditional logic to determine what class1 class2 and class3 are, you are just doing a bunch of ugly crap in the render function rather than abstracting it. Or implementing your own version because you're smart.
It's a stupid hill to die on here... you want to argue about importing the entire lodash library because you like .chain, have at it. But I guess you can keep patting yourself on the back for avoiding importing a no-dependency 50-line library.
Re-inventing 1000 versions of a tooth pick is reinventing the wheel.
> That's nice, but you're addressing a straw man.
You keep using that term and I'm not sure you understand what it means.
> It was said that no one is suggesting you recreate a non-trivial dependency for the sake of reducing your dependency count.
And my argument is that dependency count is one of the dumbest metrics to be interested in. Size, sure as that impacts bundle size, which in-turn, effects latency. But "count" is meaningless.
> Humor me -- the next time you use classNames for a small project
I use styled-components exclusively for React projects now.
> For example I've seen things similar to "classNames({myClass: true})" in code before.
So? Bad code is bad, that's not a library failure. Now that is a straw man.
> Can you see what is wrong with this line?
Of course I can, because I'm actually good at my job. I also wouldn't do that. Using your toaster in a bathtub is also REALLY stupid, but that doesn't mean we should ban toasters.
> When people get comfortable with abstractions, they completely forget how to write the simplest code.
No that's called laziness and it has nothing to do with dependencies. You have twice in this thread accused me of straw men inaccurately, and now wrote a paragraph dedicated to a huge straw man.