Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

You'd have a good point, if all of those tiny but probably useful modules were given the use you're describing.

Discoverability though is so poor that most of those modules are most likely just used by the author and the author's co-workers.

If a typical npm user writes hundreds of packages, how the hell am I supposed to make use of them, when I can't even find them? Npm's search is horrendous, and is far from useful when trying to get to "the best/most supported module that does X" (assuming that random programmers rely on popularity to make their choice, which in itself is another problem...).



The isArray package has 72 dependent NPM packages, it's certainly not undiscoverable. The leftpad package gets 5000 downloads a month, that's quite a bit of testing for edge cases, compared to the none that I would have gotten had I implemented this myself.

Intuitively, this thread wouldn't exist if your assertion were correct.


Edge cases for a padding function? Your comments make me think that the author's point is valid.


Edge case for left padding - when you provide empty string as padding filler. It can go into infinite loop if not written correctly.


Write a damn unit test for your padding function. We should share unit tests, not one-line libs. Libs with unit tests can be one-liners and be as fine-grained as we like, since it's something your users don't have to download


> We should share unit tests, not one-line libs.

Most of the small libs I've shared are mainly sharing unit tests.

Here's a function I've shared on npm:

  var kind = function(item) {
    var getPrototype = function(item) {
      return Object.prototype.toString.call(item).slice(8, -1);
    };
    var kind, Undefined;
    if (item === null ) {
      kind = 'null';
    } else {
      if ( item === Undefined ) {
        kind = 'undefined';
      } else {
        var prototype = getPrototype(item);
        if ( ( prototype === 'Number' ) && isNaN(item) ) {
          kind = 'NaN';
        } else {
          kind = prototype;
        }
      }
    }
    return kind;
  };
The tests:

  suite('kind', function(){
    test('shows number-like things as numbers', function(){
      assert(avkind(37) === 'Number');
      assert(avkind(3.14) === 'Number');
      assert(avkind(Math.LN2) === 'Number');
      assert(avkind(Infinity) === 'Number');
      assert(avkind(Number(1)) === 'Number');
      assert(avkind(new Number(1)) === 'Number');
    });
    test('shows NaN as NaN', function(){
      assert(avkind(NaN) === 'NaN');
    });
    test('Shows strings as strings', function(){
      assert(avkind('') === 'String');
      assert(avkind('bla') === 'String');
      assert(avkind(String("abc")) === 'String');
      assert(avkind(new String("abc")) === 'String');
    });
    test('shows strings accurately', function(){
      assert(avkind(true) === 'Boolean');
      assert(avkind(false) === 'Boolean');
      assert(avkind(new Boolean(true)) === 'Boolean');
    });
    test('shows arrays accurately', function(){
      assert(avkind([1, 2, 4]) === 'Array');
      assert(avkind(new Array(1, 2, 3)) === 'Array');
    });
    test('shows objects accurately', function(){
      assert(avkind({a:1}) === 'Object');
      assert(avkind(new Object()) === 'Object');
    });
    test('shows dates accurately', function(){
      assert(avkind(new Date()) === 'Date');
    });
    test('loves Functions too', function(){
      assert(avkind(function(){}) === 'Function');
      assert(avkind(new Function("console.log(arguments)")) === 'Function');
      assert(avkind(Math.sin) === 'Function');
    });
    test('shows undefined accurately', function(){
      assert(avkind(undefined) === 'undefined');
    });
    test('shows null accurately', function(){
      assert(avkind(null) === 'null');
    });
  });


If you've called it with an empty string there's probably a bug in your calling code which you'll want to test for anyway.


And when a bug is found, instead of fixing it in one place once, you now have to hope that all of your deps and all of their deps update themselves appropriately.


Which is great if you are one person and you fix the bug in your own code. What you're ignoring is that if everyone writes their own version, then the same problem exists. That bug has to be fixed across every (buggy) implementation. A well-defined dependency system where it is easy to discover and update to a new version isn't a matter of hope.


Remember that download counts for package indexes are often misleading. Between scrapers, deployments and continuous-integration systems (all of which download a package -- in the case of CI, sometimes it downloads on every single test run), hitting the thousands-of-downloads level is not hard at all.


Discoverability though is... poor seems like an argument for improving discoverability, not against having small modules.


Doesn't apply to Javascript, but something like Haskell's hoogle (stackage.org/hoogle could help with a small module approach. It lets you query for functions matching a certain type signature, like this: https://www.stackage.org/lts-5.9/hoogle?q=%5Ba%5D+-%3E+a+-%3...


Discoverability happens with standardization.

Why search through millions of unknown packages when a standard library would have it all right there?


Because the standard library is where modules go to die. Slaving the release cycle of a library to the release cycle of the language is bad for the health of that library, especially in the case of javascript where code often has to be written to run on old browsers with old versions of the standard library.

Now having a metalibrary that depends on a curated collection of popular/useful utilities is probably a good idea - but isn't that exactly what many of the libraries that broke due to depending on left-pad were?


I've wondered why the official committee doesn't have a recommended list of libraries for specific purposes.

That way I can get a curated list of great functions I can trust.

Essentially a standard library for all intents and purposes.


Yeah, I think the natural question here is: why doesn't TC39 round up all these basic packages and add them to the standard library? I've seen other languages criticized for having too large a standard library, but if this is the alternative...

left-pad was released under WTFPL, so in this particular case there'd be no legal barriers to it. (And I'd assume that, for any libraries with a restrictive enough license, it wouldn't be a hard sell on TC39's part -- if they put out an announcement that they were going to do that, I'd go panning for street cred, and I wouldn't be the only one.)

An alternative could be to pull all this stuff together into one big bucket of Legos and package it with a code analysis tool at the beginning of your build process to strip out everything you don't need from the bucket... but I'd guess that's either already been done or a stupid idea for reasons I don't know yet.


Its not about legal barriers, its about the incredible amount of work to precisely specify everything, which is required for any web standard.


Can we ever achieve this?

We can't exactly search the code to find out what it does, otherwise you'd basically be reading all the code to discover it's true behavior, which negates the usefulness of modules in the first place...

Any search will have to rely on developer-made documentation, and/or meta data. This is great in theory, but documentation is rarely well maintained, and/or someone changes the code but neglects to update the documentation.

This leaves us with the situation we have today. A search that somewhat works kindof, and mostly you rely on googling the feature you need and looking for what seems to be the most popular choice.

I'm not sure how this situation can be made better, especially if we continue down a path of having all these "one-liner" libraries/modules that anyone can make and stick out there into the unsuspecting world. When I need a square root function, and my search returns 800 one-liner modules, how am I supposed to pick one that I know is reasonably well done, and does what it says it will do, without looking under the hood - you'll end up just picking whatever seems to be popular...


In most languages, things as common as square root would be part of a standard library which everyone uses, so there wouldn't be any question. That also means it would obviously be well-tested and vetted, because everyone depends on it. Perhaps the solution is avoiding one-liners and moving towards more comprehensive libraries, but that doesn't seem to be what npm devs want (not a JavaScript guy so I'm just observing from the outside).


> Any search will have to rely on developer-made documentation, and/or meta data. This is great in theory, but documentation is rarely well maintained, and/or someone changes the code but neglects to update the documentation.

This is why types are better than textual documentation - the system enforces that they're kept up to date.


We could have something similar with full dependent types a la Idris: you could write a proof and search for a function that satisfies it. If such a thing were popular and huge amounts of Idris code were written, you could write only proofs for your program and the Idris system could go download and piece together your program!

That would be very cool, but I'm not sure how much easier it would actually turn out to be. Also to do anything useful you'd probably have to restrict the language to be non-Turing-complete.


Similar idea but what if you were to write your tests first and then upload them to a site that pieces together the required modules to pass them and generates an API against the modules.


Because finding code that passes arbitrary tests is undecidable in the general case.

(Same reason the pseudo-Idris language would have to be non-Turing-complete)


I was joking clearly. Thought the ridiculousness of the idea make that clear.


You're totally right. Most developers don't develop this way, and that makes the benefits of this approach far less pronounced than they would be if they did. It also doesn't negate the benefits entirely, of course.


Another benefit of small well understood components is that they are easier to write tests for. Do these npm modules have good test coverage? Did the leftpad module have a unit test that would have caught the issue?


No, leftpad has four test cases and they are all obvious, given the leftpad API.

Would I write tests for my own leftpad implementation if I were not farming it out to a dependency? Its possible. More likely I would want to understand the intent behind using leftpad in my application or library, and have test for "formatTicket" or whatever it is that I'm actually doing. But for all the talk about tiny modules that cover surprisingly tricky edge cases, this is not one of them.


which issue? I thought we were talking about the random removal of left-pad and a couple hundred others.




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: