Hacker News new | past | comments | ask | show | jobs | submit login

A little copying is better than a little dependency. https://go-proverbs.github.io/

As a developer at a large software company, every dependency that is not part of the language runtime itself is a pain because legal paperwork and evaluation has to be done for each individual component before I can use it / ship it.

NOTE: I am not referring to copying I would be doing, but to the crates thats have little dependencies that should consider including a copy of their little dependency instead via whatever method is appropriate for licensing.

This makes languages like Python, Go, Perl, etc. preferable over languages/projects like node.js, rust, etc. because (at least I) don't generally end up with tens/hundreds of dependencies since the standard library is rich enough for most work.

Additionally, I personally despise have many, small dependencies because it means I have more to think about and manage. Instead of just being able to think about the version of the compiler/standard library I'm using, I have to consider every individual crate.

I'm well aware of why rust chose to make certain tradeoffs with crates, but having numerous pieces of what many of us consider "basic functionality" as a third-party dependency is frustrating. Languages with richer standard libraries have spoiled us all.




> A little copying is better than a little dependency. https://go-proverbs.github.io/

I really disagree with that quote. Copying is how you get bugs sticking around in software for all time (for example, doing binary searches in a way that avoids overflow is surprisingly tricky, and the endless copying of naive binary search code is why this bug is so difficult to eradicate). Honestly, that quote is just an excuse to avoid the hard work of making the language ecosystem handle dependencies properly.

> As a developer at a large software company, every dependency that is not part of the language runtime itself is a pain because legal paperwork and evaluation has to be done for each individual component before I can use it / ship it.

How is copying better than dependencies in this regard? You presumably need legal signoff either way.

> Additionally, I personally despise have many, small dependencies because it means I have more to think about and manage. Instead of just being able to think about the version of the compiler/standard library I'm using, I have to consider every individual crate.

This is what the "Rust platform" is designed to address. It is nice to be able to refer to a specific version of the Rust platform, but that doesn't mean you have to give up on the massive ergonomic benefit of the Cargo ecosystem relative to copying and pasting code.


I believe they mean, each time a source code is downloaded and used that contains a LICENSE file, a legal review must occur. So if it's bundled into one licensed work "Rust With Lots Of Crates Bundled", then that's one form to fill out, but if it's "Rust" and then "Download And Use Crates", that's one form per addon to fill out.


But you're bound by the license even if you copy and paste the code into your project instead of using Cargo.


I think this is where reality meets theory. In reality, the developers are probably just taking the code as if they had written it, and the people that may know, such as immediate supervisors, don't care to point it out for the same reason the developers are stealing it, it's much easier than the alternative. The code vetting team is just left in the dark.

Employees take shortcuts around bureaucracy all the time. Sometimes (often?) that bureaucracy is for legal reasons.


I'm not going to endorse copying over package managers on the grounds that copying makes it easy to get away with violating big companies' legal procedures on the use of third-party code.


I wasn't endorsing, just providing an explanation of why while in theory copying and package inclusion are the same from a license standpoint, they likely often aren't in reality. That doesn't mean it's a good thing.

Your argument is the correct moral and legal one. Unfortunately that doesn't always matter. For another example, see the cognitive dissonance many express regarding ad blocking (not to come down entirely on one side of that issue, it's complicated).


> and the people that may know, such as immediate supervisors, don't care to point it out for the same reason the developers are stealing it, it's much easier than the alternative.

If your company gets aquired one day, the code will probably be audited during the due diligence process. If licence violations related to copy-pasting is found, your team will be asked to remove the infringing code and your supervisor may be fired. This happened to my team in the first company I worked for (not the firing part though) : we had a lot of code which was just copy-pasted from lodash and the audit found it.


Yes, anytime source code is retrieved that isn't an existing, approved version, legal review of some sort must occur. This includes even referencing it despite what the other poster mistakenly believed I was implying.


I see what you mean, would something like cargo-vendor[0] help with this?

[0]: https://github.com/alexcrichton/cargo-vendor


I think the argument is where that line is. Maybe copy/pasting binary search code is too much, but do you need a dependency for left pad? There's a line somewhere.


Left pad was a problem for a number of reasons, none of which apply to Cargo (cargo yank never breaks code, by design, while the npm equivalent did). It's not relevant at all.


Sure it is. We're talking about what should and shouldn't be a dependency. The acute problem with left pad was npm's design, but the cultural problem (if you consider it a problem) was that anything depended upon something so small in the first place.


The circumstances that led to the left-pad fiasco were because of Javascript's uniquely anemic standard library (at least until very recently). Rust's stdlib is not small in the same way that Javascript's historic stdlib was. Rust's stdlib is narrow, yet deep: a relatively small number of modules that themselves provide a very large number of operations and convenience functions. Rust dependency graphs can get pretty big, but in practice they're nowhere near as big as the dependency graphs you'll see in big Node apps because the stdlib is so much more fleshed out. That order of magnitude difference is crucial; one might call it "microdependencies versus minidependencies".


Agree 100%. I think Rust's stdlib is useful and coherent, and shows the way for other libraries. It's a great piece of engineering.


Rust has the capability to, and I believe the developers have expressed they are amenable to, internalizing crates that become the best solutions for a problem.

Would you rather a flawed, or later deemed incomplete internal solution be implemented and then the language is forced to support it in perpetuity, or would you rather one or more solutions get tried and the best implementation and syntax eventually accepted into core?

EcmaScript can do the same, and finally has[1], but it moves so slowly and has so many competing interests that it seems to take forever for that to happen.

1: https://www.ecma-international.org/ecma-262/8.0/index.html#s...


Oh God no, haha. I started out in Python and I'm pretty sure all of us have fallen out of love with batteries included.

You can see what happens when you go too far the other way though. C has effectively no basic data structures like strings, lists, hash tables, etc., so anything you interface with has its own idea on how to handle that stuff. Library X might return an array of Things that's NULL terminated. Library Y might return an array of Thangs and a size_t output param. Or like you pointed out in JS, its standard library is full of holes so you get tiny projects that attempt to plug them, or larger projects that try to make JS into a specific kind of language (Underscore), or full on programming languages that transpile to it.

I just don't think the problem is definitively solved though. Personally I think Bytes should be in Rust's stdlib. I think bit and byte manipulation is a fundamental part of a language and there should be a standard way of doing it, especially if there are things like TCP/UDP and hash tables in there. I understand the arguments against; I really like the design of Rust's stdlib, but I feel like there's room for disagreement. That's all I'm saying :)


> the cultural problem (if you consider it a problem) was that anything depended upon something so small in the first place.

It's not a problem, in my view.


How is copying better than dependencies in this regard? You presumably need legal signoff either way.

I wasn't referring to copying that I would do myself, but copying that other crates would do.

That is, if a crate only needs a little bit from a little dependency, then copying it into their crate can make everyone else's life easier (obviously taking licensing into consideration when doing so).

In short, the context here was the bytes crate, which is fairly tiny. If rust is going to insist on not including the bytes crate, or a copy of it, in the standard library, then I would hope others that consume it would consider embedding a snapshot of it into their own crate for their own, private use so that I don't have to worry about it.

I'm well aware there's a fine line here, hence my reference to the Go proverb.


> so that I don't have to worry about it.

What would you be worrying about?


The short version is that a component distributed with an embedded copy of its dependencies means a single legal review since it's a snapshot in time of a particular version of that component and its dependencies.

A component that instead references its dependencies and that have their own release schedule/versions, etc. requires a legal review for that component and each of its dependencies.

This has been true at multiple employers I've worked for, so seems unlikely to be a consideration unique to my current employer.


Again, that's what the Rust Platform is for. It's a better solution than copying code, because it doesn't throw away all of the benefits of Cargo just to make some legal policies at some large companies a little easier.


We're going to have to agree to disagree.

This is where I actually prefer Go's "vendor" approach to dependencies. It would be great if rust / cargo eventually had the same and more authors adopted it or simply copied their little dependencies instead of having external dependencies on them.

Something like this proposed command, except for crate maintenance instead of distribution:

https://users.rust-lang.org/t/cargo-cook-subcommand/10288


I sincerely hope that people never start copying code into their packages. I see virtually no upsides, except for making it easier to dodge bureaucratic hurdles at some big companies, and a huge number of downsides (basically forgoing all the benefits of Cargo).


FWIW `cargo vendor` already exists, just not part of Cargo itself, but rather a tool by one of the core devs.

It's even used for releasing the official Rust tarballs as we now employ crates.io dependencies in the standard library and the compiler.


Does it do more than using relative paths in a Cargo.toml would do?

I think this thread is about copying and pasting code versus using a small library in the Go case, which might be a philosphical difference with Rust.

It might help to point out that vendored crates are compiled from source making the required review process referenced by that poster just as possible with server crates.


Gotcha, thanks.


"Dependency" doesn't imply "third-party library." There are plenty of crates that are maintained by the Rust organization itself. You could think of them as a "non-standard library."

(This isn't uncommon; it's also true in, say, Elixir: there are a few useful Hex packages owned by the elixir-lang GitHub org itself. And I believe it's true in Haskell as well.)


It usually does for legal review purposes, in my experience. If those things aren't part of the "standard distribution", they have to be evaluated separately. Especially if they have a different release schedule.


Hmm. I guess this might justify the Erlang/OTP approach: shipping a "platform" or "distribution" release that contains your core packages/stdlib—along with a bunch of other, seemingly "extraneous" packages that you also take responsibility for—bundled together as your language's SDK.

Unlike a huge stdlib, a "distro"-style SDK is still factored into packages (in Erlang terms, "applications"), that can be included or excluded from any given release of your project. But it's all released monolithically, and comes as one big package. Probably helps a lot with getting legal sign-off for using the relevant packages. I wonder if that's why they (still) do it?


I personally agree with this philosophy - more the "use the standard library" than "copy stackoverflow".

I can't count the number of times we've had problems with the requests library, either because of the huge tree of dependencies (both explicit and implicit) that requests has, and because of some of the assumptions made by requests.

On the other hand, when a bit more time is taken (yes, this means a few lines of boilerplate) and the code uses urllib2, it rarely has to be touched again.




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

Search: