This is such an important topic that feels like it's hardly ever talked about. In the common lisp world, it's pretty much a cultural norm to use as few dependencies as possible and stick close to the spec, because part of the strength of CL lies in it having an extremely stable spec with a lot of high quality implementations. Adding dependencies reduces the stability of your project and potentially its portability, which are both serious downsides to consider that are worthy of auditing. Also, in my personal opinion, another strength of CL is that you can get a lot done with far less, which usually makes relying on third party dependencies less necessary, and you can consequently usually fit other people's code in your head pretty easily.
In the nightmare hellscape of mainstream languages like JS and Python on the other hand, it's common practice for projects to have dozens, hundreds, even thousands of dependencies -- and that's without even taking into consideration the dependencies of those dependencies, and then furthermore whether those dependencies are pinned. But since this is JS or Python, the dependencies are almost certainly pinned, which causes even more headaches that makes packaging software in a reproducible and auditable way practically impossible for certain languages. And since there's no stable spec and usually only one implementation, no one thinks about portability at all either; you get what you get and if you're lucky it's not impossible to port to an OS other than Linux. This problem of portability is only compounded on by the potentially massive amount of dependencies some of these projects will have. I don't understand how anyone lives like this but people really need to start being more responsible with the code they put out into the world.
Or one could just take up Drew's satirical software eco-terrorism as the only possible viable praxis for abolishing the present state of software development...
I would say another thing about the CL ecosystem is that all the "little utility functions" on the order of left-pad are all bundled into one dependency — Alexandria — and there are a handful of other libraries that are cross-implementation compatible and widely enough used to be de-facto standards. Three or four dependencies in CL will often get you what would be hundreds of dependencies in JS.
JS has lodash as a very good (IMO) "little utility function" library. But for some reason people decided that instead they would rather shatter it into 1000 pieces.
I expect things to change after the recent series of high profile supply-chain attacks like that of SolarWinds, at-least with sensitive projects.
I wouldn't be surprised if the software development contracts outright blacklist aforementioned programming languages and ecosystems notorious for senseless dependencies in the name of 'Getting things done'.
The frontend javascript ecosystem can only be described as deranged. If anything, it's a miracle that malicious packages don't happen more often than they do. One of my side projects has over 1000 indirect dependencies (according to ls -l .yarn/cache | wc -l), and it's not a project I'd consider especially fancy. Alacritty has 200 indirect dependencies, and as far as I've seen that's the upper bound for most rust projects. For NPM, it's the lower bound.
Running yarn in firejail/bwrap helps, but it's not easy to set up and sandbox escapes can happen (same with docker).
Still, though, could there not be a similar scheme where instead of unpublishing the module, the maintainer intentionally inserts a divide by zero somewhere and pushes it as a minor update?
This is a wonderful idea. I know it’s a joke, but we need to start thinning the numbers of js trash packages. There won’t be a software industry if 1 in X deps installs ransomware, rats, infostealers and miners.
This is hard to convince developers to reduce the number of direct (and indirect) dependencies. I already try to reduce dependencies of Ava - a JavaScript test runner. However, I encountered obstacles such as [1]. I gave up and switched to a by-design zero-dependency test runner named oletus [2].
I mean, that isArray example is exactly the kind of code that 99% of developers wouldn't come up with on their own, since it's not intuitive at all to check whether or not the value is an array in that way. If anything I would just be in favor of a name for the package that made it clear that it's intended for legacy compatibility.
That points to the underlying problem: a crap standard library. If extremely common functionality has to be outsourced to (short but) completely non-obvious third party modules, the standard library has failed at its core task.
JavaScript is in a situation different than most other languages. Any addition to the standard library has to be implemented by every browser on earth, and that's already unsustainable. Any imperfections or mistakes in the standard library (we are still distraught with the Referer bs) can't ever be fixed as all code has to be perpetually working.
That's just an excuse and a poor one at that. Many languages (C, Fortran, C++) have multiple implementations and don't get to fix design flaws in the standard library; JavaScript is not unique in these requirements.
The only special thing about JavaScript is that after 25+ years the standard library is still grossly inadequate.
They could find it on StackOverflow and copy-paste it. Searching for "Javascript is array" on DDG or Google even returns the SO answer before the NPM package.
There's tons of little utility features like this that are IMO the core of why people use libraries in javascript, but could easily be replaced by a common library offered by the browser.
Base64/hex/binary conversion, type checking, DOM access shortcuts, etc. etc.
It’s also wrong because the representation wasn’t exactly always deterministic in 2013 across all js engines. The right way to check for an array is value.constructor === Array, which also doesn’t really make any sense because an array in JS really is just an object with a length key and respective keys names 0…n.
I've been using JS on and off in various incarnations, and this sort of blows my mind. First because I don't think I've ever seen that approach used anywhere, and second because it would probably take me upwards of an hour (possibly a day) to work out whether that would actually work.
The constructor check would unfortunately not work for cross-frame arrays. Each frame has its own global object, with its own Array constructor. So:
var iframe = document.createElement('frame');
document.body.appendChild(iframe);
var value = iframe.contentWindow.Array();
value.constructor === Array // false
value instanceof Array // false
value instanceof iframe.contentWindow.Array // true
Stringifying the constructor works even for cross-frame values:
I've some modules I built just because it looks cool to have npm modules with N downloads on your CV. I don't really need that now.
No idea who the hell use them but I very rarely receive a PR or issues. They're basically unmaintained.
It's a bit like having 200+ projects on GitHub and a lot of green squares, people are just going to look at the whole thing without digging much further.
I got some work leads just from people telling me "Yo, I've seen your GitHub, wanna work?"
Somebody need to write busybox of node_modules and alias all the single-liners out to subdirectory of it, i.e. dependencies: { isArray: "busybox/isArray" }
The author forgot the "iTard" effect: once the author deletes the module, the disappearance of the feature will cause major turmoil and people will complain to the repository owners to restore it asap.
This will also create a new opportunity for someone else to...recreate the module, and chances are that it will likely include some malicious or even more broken code.
If you want to "improve" the situation, you update the module with code that triggers an exit with a warning message. That will fix the problem.
Why not build a scanner for common structures like "isArray" and automatically submit a PR to replace the usage with built-in tools or something like lodash.
(I know program comparison is akin to the halting-problem, but for simple templates it should work).
controversial opinion - I actually like having all these libraries that do the same thing, because I have a nicely documented searchable catalogue of code snippets to put into my own utils.js!
What about people who value helping others more than the money? and Disagree about the value of the "help" an `npm` package actually is? I like this idea but I can see there's room for disagreement.
Say there's a particularly problematic package... are you justified in hiring a bounty coder to replace it? How about a bounty hunter to eliminate its current maintainer? Is the action more moral if many people gang up to fund and direct the bounties' goals?
Telling people their "gifts to the world" shouldn't exist isn't likely to make you popular. The dumpster fire of NPM being a public hazard is hard to argue against too, so its a hard one.
I see your point but I disagree. The solution is having a standard library (even very small), implementing basic features that the language is lacking but are terribly useful and basically everybody implements them on their own (or just import a package as it seems). Other languages managed to do it somehow (with better or worse results), why the JS community can't?
Instead of being constructive and contributing positively to humanity, ddevault takes his talents and attempts to play scorched earth at every turn in the road.
There are constructive solutions to this problem. The solutions do not entail breaking literally millions of builds and suggesting that a developer should torch their reputation for, what, $710 (LOL, give me a break, Drew).
What we have here is performative attention-seeking, known clinically as "maladaptive coping." It's a shame to see this stuff day after day voted up to the HN homepage.
If a million builds can break for $700, maybe those builds deserve to break. Then the million developers might actually write resilient software. Where do I send my $700??
How does this fall under the definition of satire?
“the use of humor, irony, exaggeration, or ridicule to expose and criticize people's stupidity or vices, particularly in the context of contemporary politics and other topical issues.”
In the nightmare hellscape of mainstream languages like JS and Python on the other hand, it's common practice for projects to have dozens, hundreds, even thousands of dependencies -- and that's without even taking into consideration the dependencies of those dependencies, and then furthermore whether those dependencies are pinned. But since this is JS or Python, the dependencies are almost certainly pinned, which causes even more headaches that makes packaging software in a reproducible and auditable way practically impossible for certain languages. And since there's no stable spec and usually only one implementation, no one thinks about portability at all either; you get what you get and if you're lucky it's not impossible to port to an OS other than Linux. This problem of portability is only compounded on by the potentially massive amount of dependencies some of these projects will have. I don't understand how anyone lives like this but people really need to start being more responsible with the code they put out into the world.
Or one could just take up Drew's satirical software eco-terrorism as the only possible viable praxis for abolishing the present state of software development...