Hacker News new | ask | show | jobs
by smarx007 1474 days ago
It's a good advice but it has a cost. Where is the discussion about cost?

The product with less dependencies will live longer and give you better flexibility but it will cost more to build and more to maintain (incl. onboarding new engineers who need to learn their way around your custom stdlib+). It's a balanced choice but the stakeholders are not prepared to invest more. Furthermore, if the project gets cancelled, there will be all that library code investment that will be sunk.

8 comments

It's not that '... developers ... are lazy, and prefer to write as few lines of code as possible, sticking rigidly to the principle of "not reinventing the wheel"'.

They don't do that because they are lazy. They do that because of competitive pressure. In SW development, in most cases, particularly in enterprise development, "the fastest person wins". Whoever moves fast and delivers fast will get to do more projects and have more influence over direction of projects. "Not reinventing the wheel" is of course in vast majority of cases faster than reinventing it.

Because in most cases it's not important to write the best possible code, it's to write "good enough" code, on time and on budget. Insecure code is of course not "good enough", so competitive pressures will adjust accordingly.

That’s assuming you move faster with a given dependency and that there isn’t some non obvious mismatch between it and what you try to accomplish.
Reinventing the wheel is also decidedly unfulfilling.
“Fulfillment” in a developer’s programming tasks is not a valuable work product. Choosing whether to reinvent the wheel or not is ultimately a business decision that too many developers internalize.

If your product team and management team are blindsided by tech debt or liabilities that you add to the code base because you decided to quietly roll your own crypto (or any other OWASP vulnerability), you are substituting your short term enjoyment for the livelihoods of your coworkers.

Companies who make their developers do stuff they feel is pointless will not see all that much "valuable work product" either.
There’s a natural bias to prioritize near-term cost over long-term cost, which translates to there being a bias to just add yet another dependency. The advice is therefore to be aware of that bias and to actively work against it to counteract it. Of course, the involved trade-offs need to be considered to strike a good balance. If the stakeholders don’t enable you to strike such a balance, personally that would be an important reason to quit that situation, or to take care to not get into it in the first place.
Not everybody thinks that maintaining your own code is eventually cheaper and safer than adding a mature dependency.
Nobody said that it would. You’re putting up a straw man.
> will cost more ... to maintain

This is a reasonable and popular intuition, but for an enormous class of projects it turns out to be torturously false and a poor reason to choose dependencies.

How many times have you sat down on Monday to fix a bug in your product only to discover DoohickyLib 3.3.2 is no longer building correctly with the toolchain update that you just pulled in. So now you go to DoohickyLib's github page to see if it's been addressed yet.

You find that someone else reported the issue last week but the maintainers use a different toolchain themselves, and don't think this is a priority, and so they pushed back on the reporter to submit a PR if it's important to them.

Unfortunately, the reporter isn't experienced at contributing to open source and doesn't want to contribute. After a bunch of other people post "me too! when is this getting fixed?", some generous soul finally contributes a PR that should do the job.

But the maintainers are on vacation or just sick of this issue and don't respond. Finally, they reappear but aren't satisfied with the PR, so they push back on the contributor. In the meantime, that contributor just transitioned to their own fork and aren't tracking the issue anymore. So the issue has been tracked for a week and has 30 posts, and somebody shared a functional fix, but it still isn't merged and DoohickyLib still doesn't work with the toolchain you use.

It's now 1pm on Monday and you've spend most of the day trying to track down the issue and understand its status. You think about whether you can table this work until later in the week hoping that the fix gets merged into the mainline of DoohickyLib, or whether you should switch to a fork. But there's a lot of overhead to that, especially if you're on a team and need to run those kinds of ideas past a PM.

Blah, blah, blah, etc, etc, etc

This is what "maitenence" tasks look like when bring dependencies into your project. They're not really related to your project, they're not really something you have good control over, they don't feel like engineering, they often come up out of nowhere, and they're often showstoppers.

The truth is that it's very hard to anticipate where your maintenance burden will come, but when you choose to use a lot of depdendencies, you're not necessarily reducing that burden but you are making a profound choice about what it looks like.

Very much this. An external dependency gives you the free puppy, but the ongoing work is still yours.

One of the items, as you describe, is that external dependencies introduce unpredictable change on a timeline which is entirely out of your control.

A particularly annoying example that has happened many times is there is an exploit in library A which is now fixed in the latest version so we much upgrade. Oh but the latest version also bumps the dependency of some other library it uses to a version that removed a key feature we need. Infosec says you must fix the vulnerability immediately and of course the product team isn't willing to compromise on the feature loss. Oops. When you own the code you own these decisions.

Of course, some library projects are run very professionally and maintain a strict observance of compatibility within major releases, a long deprecation announcement process and so on. Other library projects, not so much. Definitely favor depending on the first kind and avoid the second kind.

> but for an enormous class of projects

> with the [latest] toolchain update that you just pulled in

In my experience, larger projects tend to be VERY conservative with toolchain updates. For example, I have Java JDK 8 (2014), 11 (2018), 17 (2021), and 18 (2022) installed; the larger projects are on JDK 11 or are just migrating from JDK 8 to JDK 11. Newer, smaller projects are on JDK 17, and only experimental projects use JDK 18.

> Unfortunately, the reporter isn't experienced at contributing to open source and doesn't want to contribute.

One more reason not to chase bleeding edge but to stay on LTS instead.

Bottom line, I am not removing Google Guava or Apache Jena from my projects because of a few CVEs they may have every few years. I am not sure I will write more secure and maintainable code. And even if I did, would the stakeholder really benefit from that?

And it will cost vital time to market. I am very conservative about introducing dependencies but there is a reason why they are proliferating and it is not just developer laziness.

Here’s a very good take from Joel Spolsky:

https://www.joelonsoftware.com/2001/10/14/in-defense-of-not-...

Not everyone has the resources of a Microsoft, though.

I agree that for core parts it matters. But quoting the post by Joel:

"If you’re developing a computer game where the plot is your competitive advantage, it’s OK to use a third party 3D library. But if cool 3D effects are going to be your distinguishing feature, you had better roll your own."

There’s also a cost to using an external library. For example bad maintainers, project being abandoned, project having breaking changes, dependency ballooning in size.
It is an optimization problem, and any strawman argument based on the alternative endpoints will be flawed.

It is also very difficult to measure the mitigation of issues caused by reducing dependencies and exposure to their issues. If you try to measure it, you'll wind up only seeing costs, and will wind up using all kind of dependencies up until you start seeing how hard it is to maintain your own CI and then you eventually get log4j'd.

> It's a balanced choice but the stakeholders are not prepared to invest more.

Well, that's not how "balanced" looks like.

Anyway, a lot of quality-driven activities pay out well within the initial development of a project, on what case, it's not a balanced choice anymore, it's a complete no-brainier. Still, I'm yet to see money-oriented stakeholders accepting those.

Build & support vs. buy or use

The cost of maintaining and supporting beyond simple cryptographic primitives is too steep for most projects.