
LeftPad and Go: can tooling help? - divan
https://divan.github.io/posts/leftpad_and_go/
======
gravity13
> A little copying is better than a little dependency.

I actually disagree with this. Given that we're already working with projects
that can have several hundred dependencies - I think the goal ought to be in
removing the weight of including the dependency.

sindresorhus says it better than me though
[https://github.com/sindresorhus/ama/issues/10#issuecomment-1...](https://github.com/sindresorhus/ama/issues/10#issuecomment-117766328)

I imagine it also depends on whether your place of employment is writing one
giant single-repository codebase vs. several modular applications, as the
latter clearly affords a package manager while the former eschews the
complexity of composing systems.

~~~
blub
It's the third time I see that link already, he's wrong, so please stop
posting it :)

The way to reuse N lines of code is to refactor them in a function. The way to
reuse functions is to pack them into libraries. This is something that
probably everyone agrees with.

Many have issues with the idea that one should create libraries containing one
function only! You've touched yourself upon the why: having hundreds of
dependencies adds both technical and cognitive overhead. It's very hard to
design things to be extended, so in practice one ends up with a fragile
module, not one that can be improved by improving a dependency (I wonder how a
function that checks if a number is negative can be improved...).

As far as I know there is no other toolchain on this planet where it's done
this way, which together with the clarification above should be telling you
and sindresorhus something!

~~~
dozzie
> As far as I know there is no other toolchain on this planet where it's done
> this way [...]

If by "this way" you mean microdependencies in JavaScript, you should also
look at Ruby, which goes in a similar direction. And at Python, which
apparently tries to follow the lead.

~~~
pjmlp
Somehow I see a common theme there...

~~~
workusername
Yes, let's dig into it.

~~~
pjmlp
From my point of view, all dynamic languages usually used by people without CS
background.

~~~
steveklabnik
My first five years after getting my CS degree, all of my paid work was in
languages with dynamic typing.

~~~
pjmlp
Some people apparently took my comment personally, but it doesn't change the
fact that many in those communities aren't from a CS background.

Which is why some decisions, like the whole npm modules, or the ruby gems
before bundles (if I get it right), get to be taken without consideration how
it works in large scale.

Of course people with CS background also use dynamic languages. I have Python,
Smalltalk, Lisp, Perl, JavaScript on my CV.

~~~
steveklabnik
There are lots of people from both kinds of backgrounds in all kinds of
communities; how much of classic hacker lore is about high school dropouts,
let alone college dropouts?

A CS degree doesn't mean you'll be a good programmer in industry.

~~~
pjmlp
No, but it helps.

I have a technical school specialization in computing and a CS degree.

Many of the things we learned at technical school only made sense afterwards
when I got into CS.

Also some of the design problems we had, which were solved by the usual"try
something until it works", became basic programming exercises with the right
CS information.

Yeah, it isn't a magic solution, but it helps in what concerns designing
software in the large.

Most other backgrounds aren't exposed to such issues.

------
pfooti
One of the weird problems here is performance, though. A naive approach to
left-pad, might involve (new Array(n+1)).join(padChar), for example, since
javascript doesn't actually have a consistent language-native way to create an
arbitrary-length string. That technique ends up, in some javascript runtimes,
taking orders of magnitude longer to run compared to a for loop with string
concatenation. The array.join method is one line though.

So, imagine the scenario where you've got a commonly-used function that gets
vendored and from there copypasta'd into a lib/common or some other location
in your project. You've basically just cut yourself off from any updates that
the module author might make when new javascript optimization hacks come
around (or obscure corner-case bugs need protecting against). It's a small
problem, but it is at least worth considering.

There's also this whole thing with licenses - there's a fundamental difference
between using a library and copying its source into your build tree. The MIT
license doesn't care, but the LGPL certainly does.

I do like the idea in general. You should extend it by doing tree-shaking or
dead-code analysis. "This library is big, but you're just using one function
call, let's just copypasta that one in here".

~~~
esailija
The code needs to pass threshold of originality to be copyrightable, otherwise
you don't need to care about the license. For example `(new
Array(n+1)).join(padChar)` is definitely not copyrightable.

------
iofj
In case anyone wonders : yes. Left-pad left-pads a string. That's all it does.

Not to worry though : it's now going to be implemented as a linux kernel
syscall:
[https://lkml.org/lkml/2016/3/31/1108](https://lkml.org/lkml/2016/3/31/1108)

------
catnaroek
The author seems to make the assumption that the problem with left-pad is how
small the library is. But that's just the symptom. The real problem with left-
pad is how little functionality is actually provides. A 200-LOC C library that
only left-pads strings should be subject to just as much scorn as the original
11-LOC JavaScript one. Unfortunately, it's difficult to assess how much
functionality a library provides just from its LOC count.

~~~
TickleSteve
Maybe a complexity metric would be a better measure?

~~~
catnaroek
I don't think any algorithmic analysis of the code can determine how much
value it provides to the user. Some things simply require human judgment.

~~~
TickleSteve
but we're trying to infer that things _dont_ have value to the user based on
complexity.... the lower threshold is an easier target.

------
gtirloni
I don't know if the Node.js project has the resources for this, but if they
did, it would be much better if all these 10-line dependencies everybody loves
to use could be included in some sort of standard library. That way they could
all benefit from centralized services (e.g. security vulnerability handling
process) and offer a smoother developer experience.

------
thegeekpirate
@divan, any reason why you haven't submitted this for inclusion into
gometalinter yet?

I'm sure Alec would be more than happy to include it =)

~~~
divan
After some polishing and testing on large projects, it will probably will be
submitted.

------
brad0
IMO the best way to move to the next generation of dependencies is through
tooling.

Instead of ignoring node_modules in source control, why don't we commit it and
allow the tooling to handle upgrades?

Disclaimer: I haven't thought about the implications of committing external
packages to your own source control at all. I'm guessing I'm missing
something.

~~~
petetnt
> I haven't thought about the implications of committing external packages to
> your own source control at all. I'm guessing I'm missing something.

Committing external dependencies to source control means tons of bloat to the
repos themselves. Want to clone huge_framework just to change a tiny thing?
Well too bad, you'll need to clone the hundred megabytes of external
dependencies too. Multiple libraries/frameworks/modules containing same
versions of same modules? Too bad, everyone needs to commit their
dependencies. Frameworks shouldn't commit their dependencies then? Or just
libraries? Or just modules? Where is the line and what are the rules?

Why not just handle dependencies manually? Because that's a pain in the ass
and exact reason why package managers exist in first place.

~~~
scrame
>Committing external dependencies to source control means tons of bloat to the
repos themselves. Want to clone huge_framework just to change a tiny thing?

Oh, geez, the first thing that makes code _legacy_ code is people checking in
"slightly modified" library/framework code.

Not to mention different lib versions. Things like java's Spring libs where it
seems like the jar layout, names and hosting changes every couple minor
versions. Different dependencies that need different versions of things.
Different apps in the same ecosystem that rely on newer versions than the
legacy in-house libs they are compatible with.

I've put up with a _lot_ of dependency nonsense on many different stacks over
the years, and am trying to adapt to devs bringing in NPM modules for dev use,
but for sure I've learned that letting devs check in random libs into source
control just because its convenient ends up with a lot of problems. That
includes java, php, ruby, perl, and python.

That its yet another generation of landgrabbing devs re-inventing a broken
wheel, or people just permanently checking in libs for convenience seems like
a devils choice.

...until you see the dev that tries to write it all from scratch themselves.

~~~
jerf
"Oh, geez, the first thing that makes code _legacy_ code is people checking in
"slightly modified" library/framework code."

For myself, I consider the ability to have a dependency and cleanly put a
patch on top of it, such that the tooling can help me when I'm upgrading the
dependency, is a basic requirement.

Few, if any, tools seem to consider this a first-class need. Based on what
I've seen, I imagine this is because most people tend to prefer putting in a
thousand lines in their own code to contort things around to hack the
underlying library to mostly do what they need most of the time even if it
shreds every abstraction their code is nominally creating rather than making a
three line change in the framework itself, even before we're discussing
tooling making it harder to patch. Most of the remainder tend to, as you say,
hack the library in such a way that it can not be usefully tracked; for this I
would suggest the tooling should be considered at fault.

------
XorNot
In Go tooling does help. Vendor everything, commit it to source control,
filter vendor/ when looking at diffs.

