8 ms·
Perhaps another reason for this is that Javascript is inherently unsafe. By relying on these small rigorously tested libraries they are avoiding the need to tes
by bluejekyll 11y ago
Perhaps another reason for this is that Javascript is inherently unsafe. By relying on these small rigorously tested libraries they are avoiding the need to test their own code, and thus avoiding basic null check or conversion errors.
Other languages handle this with compilers, may be strongly typed, and/or have features that don't allow nulls. Javascript doesn't exactly have that luxury. So maybe it makes sense in Javascript, where it wouldn't in other languages (though one could argue this is a flaw in the language design).
edit: to be clear I'm not really defending the practice, but trying to give a little perspective.
- drauh 11y agoThe equivalent in C would then be replacing #include <math.h> and "-lm" with #include <sin.h> #include <cos.h> #include <tan.h> #include <sinh.h> … and "-lsin -lcos -ltan -lsinh …" Which is nuts no matter what language you are coding in.
- e12e 11y agoOh, but javascript is dynamically typed, so it doesn't matter if your sin-module works with a different kind of arbitrary-precision decimal number module than your geolocation module, your cosine module or your openg-draw-triangle or opengl-draw-circle modules... /sarcasm
- gaius 11y agoIt's not sarcasm if it's true!
- tfm 11y agoOT but apt to this community - That's what I thought, but after a lifetime of 'correcting' people, I looked up the definition of sarcasm. Turns out that the sarcastic-sounding truths I'd been deploying for decades were indeed by-the-book sarcasm rather than 'I can't believe it's not sarcasm'. Key quote from brilliant word-talking-guy Henry Fowler: "Sarcasm does not necessarily involve irony [but it often does] ... The essence of sarcasm is the intention of giving pain by (ironical or other) bitter words." So, we circle back to Node.js by way of pain and bitterness. Sounds about right.
- imron 11y agoThe difference with C is that with a good linker, functions you don't call are removed from the resulting binary (or are maybe not even in the binary if you are dynamically linking to the c runtime). With javascript however, if you import a hypothetical "math.js" instead of just "sin.js", "cos.js" or "tan.js", then you'll need to download and evaluate a whole bunch of javascript that you might not need. I'm not defending javascript, because I dislike it and avoid it where possible, but I can understand some of the reasons why short, specific modules came about.
- TickleSteve 11y agowhat you describe is the "-flto" option in GCC and I believe the equivalent in JS is donr by Google Closure compiler.
- ansgri 11y agoHe described not Link Time Optimization (-flto), but the very basic linker functionality: to only include required functions. C/C++ has a weird compilation model where each source file is translated to machine code separately, with placeholders for unknown function addresses. Thus it is trivial to take only required functions. -flto, on the other hand, allows to reverse this process to allow interprocedural optimization across different translation units.
- TickleSteve 11y agoHe's describing unused-function removal... which "-flto" is the correct option to use (on GCC). like you say, without this, removal is only performed within the compilation-unit, but my statement was quite correct. @majewsky: what you're describing is more akin to "-ffunction-sections" and "-gc-sections" which will split ewach function into a separate section and garbage-collect those sections.
- majewsky 11y ago@TickleSteve below me: "without this, removal is only performed within the compilation-unit" Not quite. When you link to a static library (.a) with lots of .o object files in it, only those object files will be linked that are actually used by your program. I first learned about this when I looked at the source of dietlibc, and wondered about every function being in a separate file. That enables the aforementioned trivial optimization, even without -flto.
- MaulingMonkey 11y ago> #include <sin.h> #include <cos.h> #include <tan.h> #include <sinh.h> I've written worse - at least those cover multiple variations each (or overloads in C++ for float/double/std::complex?/...) While I'm not a fan of the enforced java route of 1 file = 1 class, I do trend towards 1 file ~ 1 (main, public) thing - which might be a single function with no overloads. #include <string_left_pad.h>? Better than #include <everything.h>, which I see far too often... I don't have to figure out which grouping of things my coworkers decided to throw something into if I can just #include by name - whereas aggregation headers more often than not will trigger a full project file-system search. Unnecessary #include s don't accumulate nearly so much when you don't have to audit 100 functions to see if any of them use features from said header. I don't trigger a rebuild of everything when the only things that #include stuff actually need it. Lots of benefits! > and "-lsin -lcos -ltan -lsinh …" Or sin.o, cos.o, tan.o, sinh.o... which suddenly sounds a lot more reasonable. I wouldn't bat an eye at string_left_pad.o either. Sure, I want to use tools to simplify the use of those micro-modules by aggregating them into libraries for convenience. But that's not a knock against micro-modules - just their packaging and tooling. Rewind time back far enough and I would've been manually specifying .o files on the command line and kvetching too...
- nradov 11y agoJava doesn't enforce 1 file = 1 class but rather 1 file = 1 public class, which is exactly what you asked for. You can put as many private classes in the file as you want.
- brandon73 11y agoThis isn't accurate either. Java does not enforce 1 file = 1 public class but rather 1 file = 1 public top-level class. For example this is totally legit: // ClassA.java public class ClassA { public static class ClassA_Inner_Public_Static { } public class ClassA_Inner_Public { } } // ClassB.java public class ClassB { ClassA classa = new ClassA(); ClassA_Inner_Public classA_Inner_Public = new ClassA().new ClassA_Inner_Public(); ClassA_Inner_Public_Static classA_Inner_Public_Static = new ClassA_Inner_Public_Static(); }
- kvakvs 11y agoYou can get approximate feeling if you get rid of a library and don't use -lm but instead unpack it to separate .o files and link against each.
- lmm 11y agoSo have libmath depend on libsin, libcos, libtan and libsinh. People who want the kitchen-sink version can get it. People who want just one specific submodule can depend on that. What's not to like?
- afandian 11y agoHaving a full set of math functions isn't kitchen sink, it's the right level of granularity for a module. If I want math functions I really want them to all be written by the same author and kept in lock-step as a unit. Why don't you want the whole module? Because it's bloat? Surely it's far less bloat than one submodule per function?
- shawabawa3 11y agoA lot of javascript is going to be deployed to a website. Every line of code that isn't used is bytes you're sending to every user unnecessarily > Surely it's far less bloat than one submodule per function? How is that bloat? It's the same LoC whether it's 1000 modules or 1 after it's been compiled/minified
- afandian 11y agoBloat in the source code, build system, dependency management, overheads per submodule, complexity. I'm not arguing that there shouldn't be a math module but that you shouldn't split it up into such (imho) crazy small parts. Closure Compiler can remove any unused functions.
- lmm 11y agoIt's not bloat in the source code - if you don't care which pieces you depend on you declare a dependency on math, if you do care you list the specific pieces. It shouldn't be (impactful) bloat or overhead in the build system or dependency management. That stuff should just handle it. Most of the time you don't care and can just declare the dependency on math and let the closure compiler handle it. But sometimes it might be really important that a project only used cos and not sinh, in which case you want to enforce that.
- saurik 11y ago> By relying on these small rigorously tested libraries they are avoiding the need to test their own code, and thus avoiding basic null check or conversion errors. In practice, many, if not most, of these one-line modules don't even work correctly, and it is difficult to get people to care to collaborate on fixing them instead of just replacing them with a new one-line module that works slightly better as the concept of complex collaboration to perfect one line of code is so foreign to a generation of developers who would rather just throw code to the world and never look back (an issue made all the worse as tiny bugs in these one-liners can almost seem dangerous to fix when you aren't really sure how they are being used: maybe it actually is better to not fix anything and just have people rely on the replacement better module :/).
- nailer 11y agoOdd, the ones I use all have tests, thousands of downloads, and active bug trackers. If I reinvented the wheel, or copy pasted, I wouldn't get those things.
- rantanplan 11y agoDoing a for loop is not equal to re-inventing the wheel. Words and phrases have lost their meaning nowadays. By the JS community's standards if I wanted code to capitalize the 3rd or sometimes 4th letters of a string, they would be 2 different npm modules. Maybe they didn't forget how to program, as the article implies; maybe they never knew how to program in the first place.
- nailer 11y agoWriting your own solution, when you could use a common widely known solution, exactly matches both writing your own left pad and inventing your own wheel. > By the JS community's standards if I wanted code to capitalize the 3rd or sometimes 4th letters of a string, they would be 2 different npm modules. If there was, it would have been published and people would be depending on it. Instead, people use the stdlib first, then big lego bricks like underscore, then (when they don't want the bulk of big lego bricks) smaller lego bricks. A single capitaliseMap() might be in there but it's a much more specific case than padding.
- rbobby 11y ago> basic null check What's funny to me is that leftpad(null, 6, ' ') outputs " null".
- ansgri 11y agoAm I right that len(" null") here is 5, so it's working incorreclly?
- rbobby 11y agoThought it was a typo on my part... but HN seems to be trimming running spaces.
- talideon 11y agoHN isn't: your browser is. Runs of whitespace are collapsed in HTML to single spaces unless specifically styled otherwise. You can verify that they're there by viewing the page source.
- deadowl 11y agoI like to use non-breaking spaces for that kind of thing, although they still might collapse that? At least it doesn't wrap non-breaking spaces.
- talideon 11y agoNo, they wouldn't collapse that: non-breaking spaces aren't considered whitespace in HTML. The side effect of that is that if you copy some text with non-breaking spaces, you'll get non-breaking spaces, so something that looks as if it contains spaces won't necessarily behave as such. In HN, if you need to quote something where space is significant, you're best off formatting it as a preformatted block by indenting it: Here is some preformatted text. It might break up the flow of the text, but if something like whitespace is significant, that's probably a good thing.
- 11y ago
- fla 11y agoI think it's a very valid (and concerning) point. JavaScript is made in way that one fears to implement isPositive or isArray.