Never use a dependency that you could replace with an afternoon of programming - <AUTHOR> https://blog.carlmjohnson.net/post/2020/avoid-dependencies/ <comment><USER2> My rule is, don't use a dependency to implement your core business. Is JSON parsing our core business? No, so why would we ever write -- and thereby commit to supporting for its entire lifetime -- JSON parsing code? All the code you write and support should be directly tied to what you as a business decide are your fundamental value propositions. Everything else you write is just fat waiting to be cut by someone who knows how to write a business case.

To be clear, this is about the _lifetime support_ of code. It's very, very rare that code can be written once and never touched. But that long tail of support eats up time and money, and is almost always discounted in these conversations. I don't even care that Jackson JSON parsing has years of work behind it, when I can hack together a JSON parser in a day. I care that Jackson will _continue_ to improve their offering without any further input, while that's not true of my version.

<comment><USER3> > don't use a dependency to implement your core business

In logic language, you're saying "If X is your core business, don't outsource X".

> Is JSON parsing our core business? No, so why would we ever write -- and > thereby commit to supporting for its entire lifetime -- JSON parsing code? > All the code you write and support should be directly tied to what you as a > business decide are your fundamental value propositions. Everything else you > write is just fat waiting to be cut by someone who knows how to write a > business case.

The rest of your argument is interpreted as "If X is not your core business, don't in-house X".

These two logical implication statements are not equivalents of each other, but are converses. Casual language often conflates If, Only-If, and If-And- Only-If.

<comment><USER4> Since we're in pedanticville, these aren't converses, but inverses. The converse goes "If you don't outsource X, then X is your core business".

<comment><USER3> Thanks, you are right. A converse is logically equivalent to an inverse, so I'm only half wrong. =)

<comment><USER5> Ah, yes, everyone knows the three values of Boolean logic...

<comment><USER6> true, false and null

<comment><USER7> Actually it's True, False, and FileNotFound. :o)

[https://thedailywtf.com/articles/What_Is_Truth_0x3f_](https://thedailywtf.com/articles/What_Is_Truth_0x3f_)

</comment></comment></comment></comment></comment></comment></comment><comment><USER8> Probably good advice, but when was the last time a programmer accurately scoped a problem when they said it will take "an afternoon" to build?

<comment><USER9> I came here just to say this.

"This'll take an afternoon" \- three weeks later......

Programmers are notorious for this.

BUT even apart from this problem ... you absolutely should use every dependency you can that will save you time.

Try to write less code not more. When you write code you write bugs, add complexity, add scope increase need for testing, increase the cognitive load required to comprehend the software, introduce the need for documentation..... there's a vast array of reason to use existing code even if you truly could estimate it and build it in an afternoon.

You also assume that you understand all the edge cases and fickle aspects of the dependency, all the weird ins and outs that the dependency author probably spent much resources understanding, fixing and bug hunting.

There's a hard fact that proves the above poster to be wrong..... how many dependencies took only an afternoon of time in total to write? Hard to say (maybe look at the github commit history) but I'd guess almost none. It didn't take the dependency author an afternoon, so why will it take you an afternoon?

Even worse .... you just lost an afternoon coding features for your core application.

Multiply this by every dependency that "you could build in an afternoon" and you'll be in Duke Nukem Forever territory.

I'd advise doing the opposite of this articles suggestion.

Find a dependency that will save you an afternoon? Grab it.

<comment><USER10> Found the NPM user.

Dependencies have costs:

\- Dependencies break over time. They have a nonzero maintenance cost.

\- They impose API boundaries on you that may not fit your existing data structures

\- It's harder to change underlying bugs

\- They might introduce security issues

Sure, use dependencies. But there's a reasonable position between "never write any code" and "never take on dependencies". Of which NPM is one of the only ecosystems being at one extreme.

<comment><USER11> I could say all of the same things about the in house tools that the "architect" wrote three jobs ago - including the bespoke ORM, object mapper, and logging framework.

Or two jobs ago where two developers who had worked at the company for 10 and 15 years respectively were maintaining a bespoke 15 year old EHR written in PowerBuilder and depended on SQL Server 2003 - in 2016.

Every company thinks they are their own special snowflake where cross cutting concerns can't be handled by a third party.

<comment><USER12> I've worked with dozens of guys who loved to reinvent config and logging frameworks, because ... I don't know why.

I suppose because it was easier than working in the actual problem domain, which they knew little about and didn't care to learn.

<comment><USER13> Herding devs to work on the boring-useful things instead of the interesting- solved things is slightly easier than herding cats.

</comment></comment></comment></comment></comment></comment><comment><USER14> A year ago I needed a min-heap to build a priority queue at work.

So first I grabbed 'heap' from npm (272k weekly downloads) and set it to work. But a few days later I realized my code was executing slower than expected because it sometimes needed to clone the data structure, and the clone instantiation would break the heap invariant in the array internals. It turned out there's been an issue open about this since early 2017.

Then I went for the 'collections' package (35k weekly downloads) and brought in its heap implementation. That worked like a charm for about six months until a bug came in that made it seem like a completely different package was breaking. After almost a whole day of debugging, it turns out that 'collections' silently shims the global Array.from function (scream emoji) without mimicking its behavior when dealing with non-Array iterables presented by the other package.

So finally I wrote my own heap -- well, I cribbed from Eloquent JavaScript [0] but I did have to briefly remember a little bit about how they're supposed to work. So while I don't totally buy the "Never..." rule in the post title, thinking more carefully about writing versus importing a dependency would have saved me a great deal of headache in this case.

[0] [https://eloquentjavascript.net/1st_edition/appendix2.html](https://eloquentjavascript.net/1st_edition/appendix2.html)

<comment><USER15> Wow. Could not be more glad I'm not in the javascript world.

</comment></comment><comment><AUTHOR> OP here: A lot of people are objecting, "What if you estimate wrong, and it takes more than an afternoon?" This objection is very bad.

It is not possible to add a new dependency in less than afternoon because you need to evaluate alternatives, test it, learn how it works, make sure it's not accidentally GPL, etc. So there are not two methods, the less-than-an- afternoon method and the more-than-an-afternoon method. There are two methods that both take at least one afternoon. If you estimate wrong and you can't write the code in an afternoon… Then stop working on your handwritten version and find a dependency? But now you know what the dependency is really supposed to do and why it's non-trivial, so you're in an even better position to evaluate which ones are good.

<comment><USER16> > But now you know what the dependency is really supposed to do and why it's > non-trivial, so you're in an even better position to evaluate which ones are > good.

I came in here to say this. If you think you're not qualified to write the function, you're probably also equally unqualified to choose someone else's implementation of it.

There is a lot of stuff out there-- stuff which is widely used-- which is not fit for your purposes, ... perhaps not for anyone's. And there is no replacement for a bit of domain expertise.

<comment><USER17> Not a lot of people can correctly write cryptography code on the first try, but we definitely advocate for people pulling well known cryptography libraries and using them instead of building their own, for obvious reasons. Not many people are qualified to write a lot of things, but are capable of making sound dependency judgements with heuristics. The trick is to use good heuristics and to not use a library for every tiny thing.

<comment><USER16> It's my experience that people very often do not make sound dependency judgements on cryptography dependencies.

They probably do better than writing it on their own, but that isn't necessarily saying much-- and I think the difference isn't actually that great (essentially the thing they pick will often tend to have same flaws as what they would have written, because essentially we're drawing from the same distribution).

I agree that heuristics could help but not much time is spent discovering and socializing what those are, particularly to the extent that they are domain specific.

Naive heuristics can also backfire. E.g. it can be easy to mistake contentious behaviour with flaws and end up preferring code that has absolutely zero mitigations against an attack over code that discloses the limitations of their mitigations.

</comment></comment></comment></comment><comment><USER18> This sounds like pre-mature optimization. If the library does what you need it to do, use it. If it becomes a problem later, _then_ optimize it.

That last thing you want to do is spend a bunch of time reimplementing code when: 1) It may not matter at all, 2) You might miss important edge cases, or 3) You got everything right but you still have to maintain it forever.

If it's going to take you three days to integrate the library, maybe it's not such a good library, or maybe it's really complicated because there are a lot of edge cases. In that case, dig into the code and see if you can figure out what it's doing.

But if you think you can spend an afternoon rewriting a library that would take three days to integrate, there is a good chance you might be missing something important.

<comment><USER19> I remember starting with an overloaded library from NPM where I used some basic functionality. That worked fine for a while. When later I got lost fixing a defect in the tangle, I just ripped out the parts I needed and made a trimmed version. The interface remained the same, for the parts I was using. Nothing to adapt.

In this way I had little investment in the beginning. And once I knew what I needed, it was another small investment to clean the code.

</comment></comment><comment><USER20> It's a matter of judgement, but here's a few observations:

\- With a little experience, you know what gets fiddly and what doesn't. Today for instance, I needed a way to remove tags in an SVG document, which looks a lot like HTML tags. I quickly ended up finding that Regex is not the solution (a well known guy on SO wrote an answer that looks like a huge warning sign). I also couldn't enumerate all the corner cases. So I found a lib that does it, along with an SO answer that turns it into a two-liner.

\- Dependencies vary in quality. Some are basically like another standard lib. Boost for instance is very well used. The tough ones are where the lib seems to be "finished", where there seem to be few commits recently, but the project was once lively and functional. IIRC libev comes to mind here. And then there are the totally dead projects, where there's a load of issues open and nobody saying anything.

\- Try to lock down versions. If you get a thing working with a certain version, there's no reason you need the newest new as soon as it's pushed. You can probably live with doing a scan for updates now and again.

\- Your afternoon of programming needs to have a clear end. That hashmap you wrote will very likely spew out issues over the next few days. CSV parser, maybe. Bessel function, that'll work.

<comment><USER21> > a well known guy on SO wrote an answer that looks like a huge warning sign

For those who are in today's 10000, you might mean this piece of art: [https://stackoverflow.com/questions/1732348/regex-match- open...](https://stackoverflow.com/questions/1732348/regex-match-open-tags- except-xhtml-self-contained-tags/1732454#1732454)

<comment><USER20> That's exactly it! Luckily I hadn't started coding when I found it.

<comment> yoz-y The old classic. I still end up using regexes when I need to clean up HTML because even though it's not the right way, it's the way that is sufficient 95% of the time.

</comment></comment></comment></comment><comment><USER22> Avoiding dependencies is a noble goal, and something to be valued, but this simple rule is too simplistic.

The problem lies in the fact that there are a great many things I can hack together in an afternoon to "replace" some kind of external dependency, but the quality discrepancy of these hacks is highly variant. My understanding of what can or should be done in an afternoon might differ with my colleagues'.

Unfortunately, like all things in engineering, you have to carefully reason about the pros/cons, requirements, and costs. After that analysis, you can make a judgment on depend vs. build (also, buy vs. build).

<comment><USER23> Agreed. For libs that are "afternoon-y" in their scope (so, not an HTTP server or crypto), if you need to get off the fence you can use some cheap heuristics to assess the quality of a library without auditing its code. For instance, you can look at its popularity (in downloads or Github stars), its release/version history, its number of open issues, and its development activity. If I see high issue counts and many major releases with breaking changes, I'm going to avoid it. If I see 2+ years of stability with mostly minor releases, low issue counts, and high use rates, I figure it's going to probably be better than whatever half-baked solution I could scribble in an afternoon.

<comment><USER24> I wouldn't consider a high number of open issues a problem on its own. All big popular projects with a history have a high number of open issues. There are some exceptions, who may be closing isses aggressvely, but it is more about a style of managing of those issues, not about project health.

Over time an issue tracker inevitably becomes a collection of hard-to- reproduce bugs, incomplete patches, underspecified feature requests, random tracebacks, etc. Maintainers can choose to just close everything which is not actionable immediately, or be in comfort with such issues, and let them live in the bug tracker. I personally like a style when an issue is closed only if it is fixed, or if it doesn't contain useful information, or if it is a duplicate.

A better indicator is activity and responsiveness of the maintainers in the issue tracker.

</comment></comment></comment><comment><USER25> Carmack weights in: [https://twitter.com/ID_AA_Carmack/status/1293311943995002881](https://twitter.com/ID_AA_Carmack/status/1293311943995002881)

"This HN discussion [https://news.ycombinator.com/item?id=24123878](https://news.ycombinator.com/item?id=24123878) is topical for me: at this very moment, I am implementing C++ MFCC code myself, because my attempt to integrate Kaldi (on windows) was unpleasant. It already took more than an afternoon, but I learned good things! \ I'm more sympathetic to the Use-All-The-Dependencies crowd than some might suppose. It definitely isn't my way, but I see them as a fellow subclass of programmer, evolved for other environments. It is _amazing_ what can be cobbled together in a weekend now. \ The old Knuth vs McIlroy story is relevant: [http://leancrew.com/all-this/2011/12/more-shell-less- egg/](http://leancrew.com/all-this/2011/12/more-shell-less-egg/)

Generally, use-the-tools is correct, but sometimes you really do want a Knuth (or maybe a Carmack)." "

<comment><USER9> When Carmack speaks it's worth listening to.

However in almost all cases, you - the reader - cannot achieve in an afternoon what Carmack can achieve in an afternoon.

Few developers have the ability to build an alternative to a speech recognition dependency.

</comment></comment><comment><USER26> > Many times, the best approach is first searching online and reading the code > to a few other solutions, then writing your own with the knowledge you've > gained from seeing how they work.

I think this is a great approach. Any general solution library will be much larger and more complex than one project's use case. Seeing how other people have solved a given problem can give a dev a nice jump start on creating a compact solution to their given problem.

For whatever reason many devs just _love_ using dependencies and almost always underestimate the long term costs, in terms of maintenance and vulnerability risk.

I once had to write a simple utility script that was literally 5 lines of Python. All it did was loop through a list and perform a couple simple actions. As I mentioned it to the PM, another dev jumped in and said, "Oh hey, there's Library_X that we can install that will totally handle that for you". I responded that the library could very well be great, but script was already done, had only taken about 15 minutes to write, and would be very easy to reason about and update down the line. Reading about and implementing a whole new library to do the same thing just didn't seem useful.

The other dev sounded unconvinced.

<comment><USER27> In my experience this is quite typical in the python community, I think it's a consequence of the batteries-included philosophy. Many people are very averse to using primitive data structures and operations to solve their problems, so working with a python codebase is like gluing libraries together

</comment></comment><comment><USER28> I tend to avoid dependencies, if at all possible. I wouldn't mind spending a week of programming to avoid some dependencies.

Of course, there is no "one size fits all" rule, here. If it's a "one-off" internal tool, without much impact, then it would not be worth spending much time on, and a dependency might be exactly the right thing (famous last words).

I'm pretty obsessive about quality, and like to ensure the best quality possible in all my work. The weakest link, and all that, so dependencies need to be vetted _very_ carefully.

There's some things that just can't be done without dependencies; sometimes, crappy ones (like SDKs), but that's less frequent than you'd think.

<comment><USER29> That's interesting. Kudos for your craftsmanship.

IME those who write code instead of using a dependency are those who DON'T seem to care about quality. They can't be bothered to see if the problem is already solved. They can't be bothered to design a good interface and extract the code into a re-usable module. Just just solve their own immediate problem, which then gets re-solved in different ways a dozen times in different projects in the company. This is what I find frustrating and what I find 3rd party dependencies protect against. They define a set of culturally accepted/known APIs/Functionality that is consistent and doesn't have to be relearned between repositories.

<comment><USER28> In my experience, I have seen some Jurassic-scale disasters, because of poor dependency choices.

I think a lot of people just google for dependencies, and then add the first one that has a slick Web site, without thinking much about the code they are adding.

I am not a "never dependency" person, but I am _anal_ about quality. Totally obsessed. I feel that quality is something that many, many programmers eschew, in favor of bling and buzzwords.

For me, I won't put my seal on something until I have tested it six ways to Sunday. In some cases, it may be unit tests, but, more often, it is a test harness, which can be a much more ambitious project than a few XCTests[0]. In fact, I am running into a lot of folks that don't know what a test harness is; which is jaw-dropping.

Since I do a lot of device control stuff, unit tests are not particularly useful. In order to create unit tests that would be effective, I'd need to design a huge mock, and that would not be worth it; likely introducing more problems than it solves.

An example is that I am currently developing a cross [Apple] platform Bluetooth LE Central abstraction driver[1]. This needs to have test harnesses in all the target systems (iOS/iPadOS, MacOS, WatchOS and TVOS). I actually have it driving a released app[2] (which is really just a "productized" implementation of the iOS test harness), but I do not consider the module ready for release, as I have not completed all of the test harnesses. I am in the middle of the WatchOS harness now. I may "productize" the MacOS test harness. My test harnesses are really serious bits of code. Complete, ready- to-ship apps, for the most part. Going from a test harness to a shipping app isn't a big deal.

[0] [https://medium.com/chrismarshallny/testing-harness-vs- unit-4...](https://medium.com/chrismarshallny/testing-harness-vs- unit-498766c499aa)

[1] [https://github.com/RiftValleySoftware/RVS_BlueThoth](https://github.com/RiftValleySoftware/RVS_BlueThoth)

[2] [https://apps.apple.com/us/app/blue-van- clef/id1511428132](https://apps.apple.com/us/app/blue-van-clef/id1511428132)

</comment></comment></comment><comment><USER30> A hundred afternoons later my small application is finally completed; now I must maintain update and document it all for ever rather than relying on third party components. What I really wish is people would look closer to home; for example use some of the thousands of functions that ship with your operating system before downloading a package.

<comment><USER31> I have this problem at work with our node apps.

With things like reduce, map, the like their is less need to rely on lodash or underscore for them.

<comment><USER32> The problem with node is that it doesn't ship with a stdlib.

That being said, lodash has worked great for utility stuff. It encapsulates like 99% of utility functions I need in my apps.

</comment></comment></comment><comment><USER33> Frankly my own code is usually the worst dependency I could have.

<comment><USER34> so true :(

</comment></comment><comment><USER35> Even if this is true, the problem is you don't know what's going to take an afternoon of programming. How many times have we all said "should only take an hour" just for it to take four days?

If someone spent the time and effort building something you need, I don't see a problem with using it. It all depends on what kind of system you're building, what the security and stability guarantees are, and in general what trade-offs you want to make.

In other words, "never" is usually bad advice.

</comment><comment><USER36> Especially when it comes to JavaScript, I tend to follow "never use a dependency that you could replace in a _month_ ".

Here is something that has happened to me more times than I care to count: I have a dependency on some library. It's working well for me. I build some sort of small project with it, like the info website for my mother's business. Doesn't need to be updated very often, just needs to be there and have her contact information. A year later, I get some automated email telling me some dependency of a dependency of my dependency has some kind of obscure security issue. I'm busy. This project isn't supposed to be a core, constantly making project. I don't really have time to evaluate if the problem is an issue for me, so I go to just upgrade everything and appease the squawk box. Oh, turns out that in the time between when I used the library and the security issue was discovered, the developers have completely redesigned the whole thing and the only version that includes the security fix is a version that isn't compatible for my config scripts anymore.

All because I didn't want to spend the time to write some stupid simple string concatenating code for writing an HTML template, I now have to spend time completely relearning this library. And probably rebuilding the build scripts, too, because nobody can just leave well enough alone.

"Oh, but if you wrote the code, you might have written a security bug, too". And I could fix it on my own, too.

When did programmers stop programming? Most of the arguments I see for ridiculous levels of package integration come from a place of devs not trusting themselves to write stupid simple code. Like left-pad. "Someone smarter than me has figured at all the edge cases". You don't need all the edge cases. You need to just learn how to do your job.

<comment><USER37> JavaScript, capitalizing the W in "worse is better".

</comment></comment><comment><USER38> So true. Oftentimes I will look at the source of a simple ruby gem or node package and see that it is actually really just one single file, with 100 various .yml/spec/lint/test/cloud/coverage/cov/tox/blah landmines in the repo to confuse you. In those cases, I'll copy-paste the code with attribution back at the top of my source file.

The headache is not worth all of the pomp and circumstance for some of these tiny little tools.

</comment><comment><USER39> Dependencies are part of the same calculations that normal programming follows.

Easy to program vs Easy to maintain vs Easy to understand vs Easy to scale vs Easy for the cpu to do.

Dependencies are easy to program, you include them.

Dependencies are hard to maintain, in that you can't expand or change their behavior.

Dependencies can be either hard or easy to understand (compared to your own code).

Dependencies are hard to scale, something you coded yourself can avoid validating inputs that have already been validated, or otherwise be smarter about how it does things to avoid overhead.

(one example would be a system for parsing info from a large amount of data, most dependencies will make you either store it all in one place on disk or memory, where a custom solution can more easily stream it to avoid memory or disk overhead. (take a ftp server that wants to calculate and store 5 hashes for each of the files uploaded, it can either have 5 libraries each read the file after upload, or it can load the entire file back into memory after upload or it could just stream the info to 5 custom rolled hashing systems that handle calculating the data _as its being uploaded_ and written without needing to re-read it from disk after upload. one will be faster and scale better.))

So half the articles about dependencies on hacker news can be broken down to one message:

Don't use a dependency when rolling it yourself is better for your use case.

The other half are about conveying why and when rolling it yourself can give you benefits for your use case.

</comment><comment><USER40> I've always called this the "guy in the basement" effect.

In the beginning, the guy in the basement would have an awesome idea for a library. He would spend 27 hours a designing it, coding it, testing it, and making it awesome.

The "guy in the basement" moves out because his partner wants to spend time with him. They start to live lives outside of the world of maintaining open source libraries. The partner asks, "Are you getting paid for all of this?" and the guy says, "No. It's open source. It's a good thing." but in saying it out loud to his partner, his priorities shift.

Over the next year, the library deteriorates. It gets forked, other people ask to maintain it, he relents, but no single person has the vision. The library becomes a mish mash of priorities and no longer has the awesome cohesion it once had.

Everyone using the library is very sad. Some are angry. An awesome replacement appears from another guy in the basement.

The cycle repeats.

</comment><comment><USER41> (1) Most programs don't have that many _direct_ dependencies, especially smaller dependencies. It's often dependencies of dependencies. In npm, adding just `jest` will make your `node_modules` directory explode.

(2) if Linus's Law is "given enough eyeballs, all bugs are shallow", then having fewer eyes on a library means more bugs.

(3) Oftentimes you _think_ you can replace a dependency with an afternoon of programming, but it turns out, it's not quite as simple as you think.

(4) Sometimes you only use a small piece of a library to start with, but over time use more and more. If it's your own code, then you're going to be continuously refactoring, updating, rewriting it. If it's a library, then you can just start using the additional pieces as you need.

</comment><comment><USER42> The single best way to avoid dependencies is to use a language with a large standard library.

Given the variance in standard library coverage, it's rarely productive to argue about this topic in a language agnostic way. Using only stdlib in Go is very different from using only stdlib in JavaScript.

<comment><USER43> The best way to avoid dependencies is to use a language that is built in a way such that dependencies are worthless. Like APL, J, or kdb+/q. All of these languages are incredibly small, have almost non-existent standard libraries, and yet are designed in such a way that a large standard library becomes superfluous.

Having a large standard library speaks poorly of the composability and orthogonality of language primitives.

<comment> yoz-y Sure, if the problems you are solving are well suited for languages like APL, J or kdb+/q...

<comment><USER43> Call me an iconoclast, but I think array languages are more suitable for general purpose programming than even general purpose languages.

<comment><USER44> As someone who is not well versed in APL/J/K, how do they deal with structured data like JSON? Is there some sort of DSL like jq built into them?

<comment><USER43> Because kdb+/q has such few datatypes and you can't define anymore, it's very easy:

      q) .j.k"[2.2, 3.5]"
      2.2 3.5

Serialization is also trivial:

      q) .j.j 0 1 2 3
      "[0,1,2,3]"

In general, sending stuff across memory boundaries (files, network, ram, etc) is exceedingly trivial in kdb+/q. To execute a function on a remote server, simply connect to a server and send across the call to the handle. For example, to send synchronously compute 1+1:

      q) h:hopen `::6666
      q) h(+;1;1)
      2

You can send over anything you want, even the entire source code of program to be executed! This is a really flexible environment, where you can create really powerful app-engines. All members of a cluster can send code, data, and messages to any other node, async or sync.

Much like Common Lisp and SmallTalk, you can easily connect to production nodes and modify code while the service is running.

It's rare to find such a dynamic, flexible, and interpreted language that also has world class performance, even often beating hand written C. Combined with an integrated database, you get a distributed system that can't be beat, at least performance-wise. And the craziest thing is that all of this sits in at 650kb executable with libc has the only dependency. And all probably in less lines of code than a simple javascript webapp!

</comment></comment></comment></comment></comment></comment><comment><USER45> Never use store-bought bricks if you can replace them with an afternoon of brick making.

[https://youtu.be/D59v74k5flU](https://youtu.be/D59v74k5flU)

<comment><USER46> I knew which video it would be before clicking... But to your point they're often not really "store-bought" bricks though. More like bricks someone was giving away on the side of the road, you're free to use them to build your house but with no guarantees they work and the instructions are missing or incomplete. Oh and they're the wrong shaped brick but you only figure that out later.

<comment><USER47> What sorts of dependencies are you guys adding to your projects? I've never had these sorts of issues with external dependencies.

<comment><USER46> Ah I'm mostly joking. I haven't done much js work lately but sometimes wading through npm did feel like the above.

</comment></comment></comment></comment><comment><USER48> Adding a dependency is like adopting a puppy. Sure it seems free.. but it's not. It may be the best thing to do, but go in with eyes open on the costs.

Something like left-pad, absolutely never worth it. Something like OpenSSL, basically always worth it (warts and all). Everything in the middle, evaluate carefully.

When adopting a dependency you're adopting all their development practices. Do they break backward compatibility every minor release because compatibility is for the boring people? Never address CVEs? Every additional dependency constrains your future self by a little bit. These add up.

</comment><comment><USER49> I once decided to write my own UI pagination component. I thought it would be fun and, why bring in a library for something so simple? Three years later, we now use this component for all our pagination. Probably four of us know it really well by now as it turns out, there have been many bugs around it. Turns out pagination was not such a trivial problem to solve when you consider all the edge-cases and crazy PM requirements.

Every once and a while some engineer who's fixing a bug on it will ask, "why in the world did we write this? Why don't we just use this bootstrap pagination instead?". I ask in return, "would it fix the bug you currently have with it?". Every single time the answer has been no. It's almost always centered around the state of how the parent component is using it. I wrote with the intention of using querystrings to store pagination state in the url, but someone else at some point decides to store their pagination data in memory and just adds a few props and now it's doing it two different ways, etc...

I think the criminal offense here was not writing pagination from scratch. It was that I didn't extract it into a library and write some basic documentation.

<comment><USER50> It does sound like you're agreeing with the premise of the article.

Pagination is hard but it's even harder to find a library that meets all your requirements and doesn't have bugs.

</comment></comment><comment><USER51> I'm the opposite. I always think I can solve it in an afternoon and always realize there are a lot of intricacies.

Fuck making popup positioning in browsers. That shit is hard to get just right.

<comment><USER52> Ugh please just don't use popups at all. I block every single one I see with custom CSS rules. GDPR cookie warnings, "please subscribe", stupid "can i help you" chat popups, everything.

</comment></comment><comment><USER53> I recall using an unusual library a while ago where the author had embedded their own log4j-style implementation. I couldn't configure that the same way I configured other logging.

Hardly a problem today since I just write to `stderr` and have the container log aggregator push elsewhere but boy was it annoying.

</comment><comment><USER54> When coding, be prepared to put it in the garbage bin! If you're prepared for this, you can code things more quickly, and not worry about the code slowing you down later. This works when you're unsure exactly what to build and need to iterate (agile). First build is an iteration, not arbitrary "sprints" or "increments"!

The cost of rebuilding MUST be budgeted though. If you don't have this freedom, things are bound to suck one way or another. Then, next best thing, build it as simple as you can, and put effort into making it composable and pluggable. So you retain freedom to swap out components. This is also an investment, and takes some more time and effort.

If you even can't even have that, results are bounded by those restrictions.

</comment><comment><USER55> I agree with this in principle. There is nuance, but the only way I look at 3rd party dependencies is as liabilities, normalizing for function.

The only question for me from this point is "Which dependencies are the biggest liabilities for us?" The answer to this question depends wildly on what exactly it is that you are trying to do.

Overall, our strategy is to typically use a 3rd party dependency by default in order to quickly get a MVP rolled out. Once we have a clearer picture of how we can solve some particular problem in a concrete way, we make a decision regarding whether we should drop that dependency or keep it around. Most of the time, we will develop an interface which exposes our need for the dependency in a vendor-agnostic way. Then, we can target any arbitrary implementation against this interface and quickly swap them around as required in DI.

The biggest question in these discussions is always going to be "Well... how long would it take to write our own?". Even if someone is being realistic and gives you something 2x as long as you were hoping for, you should consider all of the other factors. Keep in mind that if you write it yourself, you can probably iterate on it without much difficulty as well (i.e. custom change requests that a 3rd party would completely ignore). Conversely, if you have to maintain it and its really buggy, you can't hope someone else is going to eventually solve your problems for you.

</comment><comment><USER56> A huge benefit of using dependencies in your codebase is that other members of your team (including future members) have a good chance of already knowing how the dependency works, and how to use it.

If I rewrite package Foob because it only takes me 3 hours to write (let's call it Boof), and my colleague Mary on another team also does so, then the chances that our needs, specific implementations & usage patterns are the same, is pretty low. When I transfer to her team six months from now, I have "my" code that I know how it works, and I also have "her" code that I don't yet understand. I've got to relearn the new interface.

Or, if we see this as opportunity to unify our needs across codebases/teams, one of our libraries get the features of the other bolted on. In this way, we're just spending our combined time building a less-good Foob, instead of actually doing something useful.

But instead, if Mary says that Foob is high-quality because she looked at the code, checked the community, etc, then I can just trust her judgment. Foob already has most the features that I thought I ain't gonna need. I can re-use Foob in multiple projects, and the documentation for Foob is certainly better than what I would have written in an afternoon, so future team-members will also pick up Foob faster than my Boofy custom implementation.

<comment><USER57> I had this experience with a particular React hook recently. We ended up with like 5 teams implementing very similar functionality, and then when developer #6 came along and tried to replace them all with a common implementation it broke 2 out of 5 use cases because of very subtle edge cases. I guess React runtime behavior is kind of high on the scale of how hard code is to reason about, so maybe this wouldn't happen in an easier codebase. But still a very instructive exercise.

</comment></comment><comment><USER58> This reminds me of the Node left-pad module problem in a way. I think if something is so trivial to write, you should write it rather than using a dependency.

If it is non-trivial, I prefer the official standard libraries for a programming language. That is if a solution exists in the standard library.

I think the Go standard library with its batteries included mantra and the level of support it gets is good example of a library that should be used when a solution exists within it or by utilizing it.

<comment><USER59> Or just C&P the relevant open source code (license allowing).

Removing a dependency doesn't have to mean writing from scratch.

<comment><USER60> If you copy the code into your project you at least need to keep track of the original authors and licensing or you're in violation of the copyright 99% of the time.

<comment><USER59> Oh, of course. Definitely.

</comment></comment></comment></comment><comment><USER61> For small dependencies it's often not the implementation that matters as much as the tests. And even if you think you can write all the tests in an afternoon, they're often born out of actual usage, which you can't replicate so easily.

I'd say if a dependency is small enough that you can write it in an afternoon, you can even more easily read it's source and tests and decide if it's high enough quality to use as-is.

</comment><comment><USER62> I think the mistake described in this blog post needs a name. Let's call it premature dependence.

Like premature optimization, premature dependence compounds your maintenance burden over time because you predicted a problem which, if you had waited for evidence, would never have materialized.

In premature optimization, you imagine that a simple solution won't perform adequately, so you invest in building a more sophisticated solution up front. In premature dependence, you imagine that a simple implementation won't adequately address your needs, so you bring in a feature-rich dependency right away.

Both are driven by the fact that we spend the vast majority of our time, effort, and emotional energy dealing with rare cases. You don't spend hour after hour, day after day, meeting after stressful meeting talking about the database that scaled fine or the code you wrote once at the beginning of the project and never touched again. If you don't account for how the successful stuff disappears into the background, your model of reality will be skewed by rare traumatic events. (Which is kind of the point, evolutionarily speaking, since it serves as a kind of crude risk analysis, but it's not hard to do risk analysis better than your amygdala does.)

Of course, applying the rule in practice requires judgment. Some problems are inherently difficult; some explosions in complexity are predictable; you don't have to pay long-term costs on POCs and failed experiments; if you say you support ISO-XXXX format then you had better support every obscure corner case; etc. But it's good to keep in mind that the long-term cost of an extra dependency can be greater than the long-term cost of a few hundred lines of unchanging, unit-tested code.

</comment><comment><USER63> What about "do not re-invent the wheel"? If you are schedule driven, then you'll want to get the coding done ASAP. Take an action for later to reduce dependencies, and prioritize it appropriately. Also, keep a local copy of the version you pulled and reference that for builds so you are not at the mercy of some maintainer/repository that has no stake in your game.

</comment><comment><USER64> I mean... this depends. I use Rails mostly in my work, and in recent years I've pared down the libraries I would use (ie. that will go into the Gemfile). I generally stay away from any other externalities beside this list of libraries, and so I make it so that they're almost "my own." Seems to be a good balance between getting too dependency dependent vs veering off to reinvent the wheel.

</comment><comment><USER65> On average programmers produce average quality of software. Libraries available online are often shitty - but most probably they are still over the average quality of all software, because there is a selection bias and more people are looking at them etc. So if average programmers replace average libs - then the expected result is that the overall quality of software would go down.

</comment><comment><USER66> Totally agreeing with this but the issue is maintenance. Sure, I can find a package and copy and paste a few files and make it my own — or do it from scratch even!

But then, that's not really my core domain, so I'll most likely never touch that piece again anytime soon. A quality package tends to have that covered (with a small risk, too if it's an untrusted source).

</comment><comment><USER28> I should mention that one thing that I _always_ do with dependencies, these days, is encapsulate them.

I use things like Dependency Inversion or Dependency Injection, or simple "glue" APIs.

This is from being burned by integrating dependencies into my projects, and painting myself into corners.

It helps to do things like swap out DB backends, or things like mapping libraries. YAGNI is important, but it's also important to encourage flexibility. Dependency encapsulation is pretty much perfect for that.

Of course, there are probably cases where it's impossible to use some dependencies without making them integral parts of the project, but it's been my experience that I can write lots of stuff, based on modules.

My work is basically a clump of dependencies; it's just that I wrote the dependencies.

I like modular architectures, with each module/layer as an independent- lifecycle project; complete with testing, documentation, and APIs. Takes a bit longer to write the modules, but the integration is quite smooth.

</comment><comment><USER67> This is interesting, because I had this issue. In one java lib I wrote, I needed to build an URL, so I naively pulled apache http common URL builder, got it done in one line, and went on.

But a few time later, I realized (well someone reported an issue) that depending on the android version, it would break. My first reflex was to try to bundle just what I wanted using some graddle class renaming plugin, it was a nightmare.

Then I just realized how stupid and lazy I had become, being able to just pull dependency for anything made me forgot I could just write the code.

In the end I dropped the dependency and wrote what I needed myself.

If you are interested, commit here: [https://github.com/kuon/java-phoenix- channel/commit/2a3a976d...](https://github.com/kuon/java-phoenix- channel/commit/2a3a976d3a189d762c4eac739d7ad824e6ce6380)

</comment><comment><USER68> I agree with this philosophy. I see the writer has used popular memes to convey the problem with humour. I would also add this quote from the movie "Heat":

 _" Don't let yourself get attached to anything you are not willing to walk out on in 30 seconds flat if you feel the heat around the corner."_

</comment><comment><USER69> Agree-ish - buttt makes me think: How about... dont _keep_ a dependency you could replace with an afternoon of programming?

Factor, re-factor, and (most especially) DELETE should be tools in the toolbox -- but see if you need it/keep it (e.g. protoype it in, etc first) before you re-write.

<comment><USER70> > Factor, re-factor, and (most especially) DELETE

Lines of code is a passable metric for the quality of work if they are considered "spent", not "created". That is, the programmer's work is better, all else being equal, if it takes fewer lines of code. Who said so? Knuth, Wirth, Dijkstra, Perlis?..

</comment></comment><comment> loup-vaillant Those are reason why I like small "single" file libraries in C and C++ (one header, one source file): you know where the source code is, reviewing it is relatively painless, and adding it to your project is dead easy.

Yet I have seen people ignoring the benefits of a 2K lines dependency (in a single compilation unit), over an otherwise equivalent 20K lines dependency (in 100 compilation units) that requires the autotools. (The disadvantages of a particular lightweight dependency is a separate topic.)

You want your modules do be deep: minimum interface for maximum functionality. Dividing the size of an interface by 10 for the same functionality is a pretty sweet deal in most cases. In my opinion, that deal is often underrated.

</comment><comment><USER71> I agree with the spirit of this article.

However, the problem is that most of the time when we think "I could build that in an afternoon!" we are underestimating the complexity involved.

Sometimes it takes an afternoon of coding and months of debugging.

</comment><comment><USER72> Typical programmer, wholeheartedly believing they can build a something in an afternoon and be done with it. I don't care how well you scoped the project -- it almost always takes longer. It's naive and all this does is cost businesses time and money. It's usually much more economical to go with a third-party than to build everything in-house, which needs to account for the costs of new-feature dev and long-term maintenance. I have an entire business running on that premise.

</comment><comment><USER73> That's too simplistic and not realistic.

I'd rather go for an heuristic that's the dependency management equivalent of "Ask for forgiveness, not permission":

1.Find the best library that is good enough to solve your current needs, double-check to understand its capabilities and shortcomings (to internalize any known future needs), and code against it.

2\. Invest the time to build your own stuff only when you start to see limitations in future iterations. By this time you'd also have a battle-tested understanding of both the dependency's shortcomings and your own requirements

</comment><comment><USER74> I'm not sure if I agree - commonly-used packages will have known and documented faults, while validating something you (your organization) created can be challenging.

Dance with the devil you know and all that.

</comment><comment><USER75> Does it really take people "a few hours" to integrate a dependency? For personal projects it's more like 15 minutes, and even for stuff at work it doesn't generally take longer than an hour.

Broadly I find that FOSS libraries are great when you stick with their happy path. If you have unique/specific requirements, it may make sense to build it yourself. But there's no reason you can't spend an hour trying to use something for free before re-writing from scratch.

</comment><comment><USER76> Dunning-Kreuger, the long and short of it is many problem appear "simple" and take an afternoon.. right? For something that converts a date from ISO format to American (M-D-Y) sure it might be simple, but anything that listens or talks to the network (DNS? APIs? etc.) I guarantee you didn't think of all the corner cases.

Also all those afternoons add up.

Also the comment "You'll know exactly how it works and what its shortcomings are."

Hahahahaha. no. If that was true bugs wouldn't be a thing.

</comment><comment><USER77> Controversial to say the least. While I know the value of in-housing as much code as possible; I only think it should be done once ([https://luord.com/2016/06/25/nih](https://luord.com/2016/06/25/nih)).

After that one time, I've strove to limit the in-house code only to the actual domain and business rules of the application/system.

</comment><comment><USER78> At lest in web development, the website is always changing thus so is the code. Therefore the maintenance burden favours bespoke code over libraries as the former is easier to adapt to changing requirements.

However ultimately in reality a decision based on product ownership culture, when it's more important to produce results now ( velocity) rather than in a few months time (maintainability). It's hard to change culture.

</comment><comment><USER79> I'm sure I could write a basic HTTP client implementation for the current needs of my project in an afternoon. That doesn't mean that I shouldn't be using libcurl or whatever instead, though.

It's perfectly reasonable to conclude "my need is a subset of a larger but well-defined task for which there's a bunch of mature, proven and widely available libraries – I should leverage them".

</comment><comment><USER80> 20 afternoon dependencies -> now you have month of work, more code to test (and write tests), more code to support in the future, more code to understand for new developer. Add edge cases which you are not aware of, you are screwed

my basic rule if dependency has small code base (<300-500 lines) I will copy/paste that chunk of code into repo and refer original repo (assuming LICENSE is appropriate)

</comment><comment><USER81> I would actually advise another way: if you have to waste the whole afternoon putting algorithm together, then it probably going to be a week after you implement all tests and fix all the bugs. But even if it was just afternoon, still not worth it. You don't want to maintain what you don't need to maintain

</comment><comment><USER82> I once worked for a startup that had a custom C++ basic library for strings, arrays, smart pointers and things like that. At some point I spent the better part of a week looking into a bug that, long story short, was caused by a bug in our custom String class. Please don't do this. Every line of code in your project that your team maintains is a liability.

</comment><comment><USER83> I am biased because the ecosystem I work on most of the time has good libraries for important stuff (hint, not javascript).

I am not sure how this advice is supposed to work though : the number of problems that are solvable "in an afternoon" is very small.

Especially the problems I know will take only an afternoon to solve and won't need to be maintained afterwards.

</comment><comment><USER84> In my 12 year professional career and 10 years of programming before that, I can't count how many times I thought something was an afternoon of programming and I was terribly terribly wrong.

Generally good advice to be conscious about taking dependencies, but it's also worth sanity checking that something is really "an afternoon of programming."

<comment><USER85> Agreed. One has to learn to be realistic, and account for time spent thinking, debugging and testing when coding from scratch. _left-pad_ is an afternoon project. SQLite connector may be a week project. Full JSON parser? Let's book a month to be safe.

</comment></comment><comment><USER86> I like this, but not things I wrote instead of using existing lib took weeks, not an afternoon. And I didn't think they would take an afternoon.

If it's trivial, probably use existing lib.

I don't know what my rule for deciding this is....I don't think I have one. I just make decisions. If I don't like a library I won't use it.

</comment><comment><USER87> Obviously each situation is unique, however, I've been burned more often by trying to clean up hand rolled out code than using a library.

I can recall quite a few instances where engineers, even experienced ones, went down this path ended up trying to reinvent such age old technologies as version control system, web server, just to name two.

</comment><comment><USER88> yeah nah, life is far too short for that.

Part of the reason why I use python is not because its "brilliant" its because it has most of the stuff you need built in. I'm too old for supporting my own tech debt.

Yes, its slow, yes there are bits that stink of poo. But 95% of the time there is something that'll do the job, most of the time. I'm not going to put my self on the hook for supporting the 0.5% cornercases the appear in 85% of all incident reviews.

Should I need something specific, then of course I'll write it, but only after google has said no, or the libs I've found don't work.

Its a silly rule, and I imagine stems from a young buck wanting to prove them selves. Thats great, but I finish at 17:00, and I don't ever intend on staying late. I suggest everyone tries it at least once. It'll make you a better engineer, honest.

</comment><comment><USER89> Time it takes to build something is not even remotely the best metric for value or ease. Programming is never a box and things that took one afternoon to write at first could be thousands of lines long a year from now. To me this is as horrible as advice as it is to use dependencies for everything.

</comment><comment><USER90> Never take afternoon advice from a programmer about how to run a business.

Because at the end of the day, that's what team management and engineering teams are. Functional units of a business. And advice like the OP's will lead you to death by a million shed bikes.

But for side projects, sure, have fun with it.

</comment><comment><USER91> I agree with the author in that you should think twice about adding a dependency. I'd be willing to invest way more than an afternoon, depending on the circumstances. Adding a dependency is also work. How much depends on your work environment, so you should think for yourself.

</comment><comment><USER37> So... why not just take the source of something you like and include it?

Probably if one "thinks" they can do it in a half an afternoon, you can look at the source of something that simple for two or three things and just clone/renamspace/whatever to the source.

</comment><comment><USER92> It works great up to the point that you have one week to deliver a feature, and that one afternoon is the difference between you delivering a half-tested or well-tested feature.

Also, as pointed by other comments, people are generally not good at estimating.

</comment><comment><USER93> Mike Perham in 2016: [https://www.mikeperham.com/2016/02/09/kill-your- dependencies...](https://www.mikeperham.com/2016/02/09/kill-your- dependencies/)

</comment><comment><USER94> Never having thought about it before, I realize I usually go the opposite way. By writing about a days worth of code on something - if only to realize its true scope - then going in search of a lib of some kind to handle the dirty bits.

</comment><comment><USER95> From the GO Proverbs:

,,A little copying is better than a little dependency."

[https://www.youtube.com/watch?v=PAAkCSZUG1c&t=9m28s](https://www.youtube.com/watch?v=PAAkCSZUG1c&t=9m28s)

</comment><comment><USER96> why not just copy the code from the dependency into your own sources?

<comment><USER97> You don't believe in software licensing, do you?

<comment><USER98> Vendoring dependencies is usually not the same thing as ripping off someone else's code.

It usually just boils down to keeping a copy of the version of a dependency you used.

<comment><USER97> Copying someone else's code and putting it in your software repository is an excellent way to find yourself violating a wide variety of open source licenses.

This is actually one of the most common causes for GPL violations. And companies have gotten into serious trouble for that.

Either rewrite the code, or maintain it as a dependency and follow the licensing rules. Don't simply copy code from it into your project unless you have explicit reason to believe that that is OK to do.

</comment></comment></comment></comment><comment><USER99> My rule scales with the scope of the dependency:

"If you think that creating a wrapper around the library is too expensive, then the dependency is not worth having".

</comment><comment><USER100> Shared dependencies can also reduce, code though. Do you really want 10 slightly different implementations of the same thing after you've brought in a few large dependencies?

<comment><USER39> That almost never pans out because they all end up pinning different versions of the same library.

<comment><USER101> "Almost never" is still more frequent than "never," so it's still positive.

</comment></comment></comment><comment><USER102> Many others have mentioned the problem with estimating time cost. I think the core issue is that very few things actually take _only_ an afternoon of programming to build.

One good example of this is a general application framework like Dropwizard or Spring. These are relatively giant dependencies; and you could fairly easily do without them early-on in a project (or maybe for the life of a project). But, odds are, you'll spend an afternoon (or several) in the future refactoring to use such a framework, because xyz feature would benefit from that foundation. The judgement call of using it early or late is why we get paid the big bucks!

</comment><comment><USER103> Clarify: actually within an afternoon, not looks-like an afternoon (include debugging, testing, docs, api design, etc see Brook's 3x). So, e.g. leftShark().

</comment><comment><USER104> Never spend an afternoon programming something that you may have to waste future time debugging and supporting when a dependency already handles it perfectly.

</comment><comment><USER105> I rather take the afternoon for dealing with business related stuff, documentation, unit tests, architecture diagrams, improving the CI/CD pipeline.

</comment><comment><USER106> This is not good advice for these reasons:

\- Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law. -> It's gonna take longer than an afternoon. Always

\- Opportunity cost: Your app needs to DO something, and spending time building dependencies steals quality from your core business proposition, even if it's a small (Haha: see previous point) dependency.

\- While there are a ton of crap libraries out there, there are also a lot of good ones, which include hard lessons learned, about even simple tasks. You _could_ rewrite a very simple http client in an afternoon (telnet hostname 80\n GET / HTTP/1.0\n\n), but you'll probably have a ton of glaring flaws just waiting to bite you _badly_.

</comment><comment><USER107> I don't have enough afternoons for this.

</comment><comment><USER108> Be right back, going to delete my html parsers deps and roll my own with some regex. [https://stackoverflow.com/questions/1732348/regex-match- open...](https://stackoverflow.com/questions/1732348/regex-match-open-tags- except-xhtml-self-contained-tags/1732454#1732454)

</comment><comment><USER109> BRB, going to go roll my own AES -- what could possibly go wrong?

<comment><USER16> > BRB, going to go roll my own AES -- what could possibly go wrong?

Probably not much more than picking an AES library written from someone else.

It's fairly unlikely that your custom AES would function at all unless it was functionally correct.

Your bespoke AES will likely have timing sidechannels, but so will most AES you go pick off the shelf. (in fact, if you happen to need CBC mode, virtually any AES you pick off the shelf will end up having timing side-channels, because most code that doesn't is GCM only)-- particularly because it's hard to be both high performance and side-channel free without using SIMD, and to do that you need to operate on multiple blocks at a time.

In fact, since you happen to know your environment is targeting only hardware with AES-NI (in my hypothetical), you'll just use that and you'll even be free of side-channels too.

The "abstinence only cryptography" advice was originally about inventing your own blockciphers and such, not implementing existing ones.

Okay so you're smart and so you'll want to go take your AES from some highly reviewed sourse with lots of smart people. You pick.. say.. the Linux kernel. Welp if you picked the plain C implementation in it, congrats, you just got yourself a bunch of timing side-channels.

There are, of course, plenty of things that can go wrong in making your own implementations-- so it's not entirely misplaced to apply it to implementations-- but sadly you are not more likely to avoid them by simply picking one written by someone else. If you understand the domain then you can select a good library and evaluate it, but if understand that you could likely also write your own. :(

On the plus side, a simple blockcipher isn't the sort of dependency that is likely to have a substantial on-going cost either. It won't randomly change its behaviour (we hope, at least not until haxors take over the upstream repository), its functionality is simple and well specified, etc.

So it is probably fine to use one from a library and the OP's advice doesn't apply. But all the reasons why the code you wrote would probably be broken? They probably still apply to the library.

<comment><USER109> Yes, yes, yes, and yes, but the crucial difference is that vulnerabilities in the library are more likely to have the benefit of disclosure.

<comment><USER16> Eh. Yes, _more_ likely, though unless you're talking about something with openssl level ubiquity it might not do much.

For example: my post pointed out that Linux's naive AES has a huge timing sidechannel (e.g. the same bug JoeBob's would). This isn't news. It's also not fixed.

Many times I've been asked to review a cryptographic library and found that it had problems, had them for been for years.. Sometimes the issues had been reported and just ignored.

In some cases reporting the issue just causes the author to take it down... creating its own problems for people who were depending on it!

At the moment I have two private outstanding bug reports for total breaks in cryptosystem library code that I just stumbled into while browsing the internet where the authors/maintainers haven't replied and it's been more than a month. After a bit longer, I'll make the reports in public, but I expect the software will continue to go uncorrected (or just be taken down in response).

One piece of advice I'd give for anyone taking a dependency: go read through its bug tracker of open bugs (and recently resolved ones) -- and their public patch queue if they have one. Also do the same for all transitive dependencies. You can gain some pretty valuable knowledge and more benefit from shared bug finding.

Of course, if you're not a subject matter expert you might not be able to judge if a report is correct or if the subject is serious-- though you will probably be able to tell if the maintainers are active/responsive.

I gave a talk once on the problem of "Selection Cryptography"\-- where I argue that merely _picking_ an implementation of cryptographic code (much less the primitives to use) is an act of rolling your own cryptography that triggers similar risks to writing some which also must be managed.

</comment></comment></comment></comment><comment><USER110> My strategy: Use dependencies, but don't depend on them.

</comment><comment><USER111> nothing takes an afternoon of programming if it needs to be QA'd. At least this is not good advice for a company. Possibly for personal projects.

<comment><AUTHOR> But you can add a dependency in less than an afternoon?

The exact same objection applies in both cases.

</comment></comment><comment><USER112> Afternoon = around 10 lines of code

</comment><comment><USER113> This is horrible advice. There's a reason that you don't write your own hashtable implementations.

Yes, I can write a hashtable implementation in an afternoon, but it's going to have bugs that I'll spend the next year fixing, and still not achieve the performance of the pre-built version.

All that work of finding existing solutions and learning how to use them? That's part of the job.

Find a bug in the dependency? Submit a patch.

Worried about the dependency changing? Lock the version.

Too many external repos to retrieve those dependencies? Use a local cache.

Don't reinvent the wheel.

<comment><USER114> > I can write a hashtable implementation in an afternoon, but it's going to > have bugs

If it has any bugs that would surface in a year of production (while the dependency version wouldn't) then you didn't write an equivalent in an afternoon.

The advice, if it's to be useful at all, must be things _that you could completely replace in the same quality, in an afternoon_.

It's the left-pads and is-odds, to begin with.

<comment><USER70> > that you could completely replace in the same quality

And the quality of the original might be questionable for many cases.

</comment></comment></comment><comment><USER115> That's like 90% of NPM.

</comment><comment><USER116> I'd say the opposite

</comment><comment><USER117> Total bullshit

</comment><comment><USER118> This is a bad rule and even worse advice.

</comment><comment> yoz-y Not Invented Here Syndrome[1]

[1]: [https://en.wikipedia.org/wiki/Not_invented_here](https://en.wikipedia.org/wiki/Not_invented_here)

</comment><comment><USER119> No. Some reasons:

1) As everyone else has said, we are horrible at estimating.

2) We think we might only need 1% of an external dependency, until we do not. Case in point: By this criteria, no one needs a grid/datatable library.So we write it "in an afternoon". Then we're asked for an export to Excel. Later on we're asked for pagination with large data sets. And then an export to PDF. How many afternoons did that cost you?

3) Writing new code is an excellent opportunity to create new bugs and implement bad design because we're on hurry since it took nowhere near an afternoon of code to write and we cut corners.

Anyway, those are just three that come to mind immediately.

This is not an argument against the "afternoon rule", but is really an argument against making simple-sounding black and white rules to solve to problems that are inherently complex, and are thus, gray areas.

<comment><USER120> > We think we might only need 1% of an external dependency

I've seen the opposite just as often. Someone things an external dependency can just plug in and solve the problem, then 16 hours later they've made the basic thing work with an external dependency with a bunch of internal code on top of it. Now you have a pile of fragile code which breaks when the dependency changes underneath you, you have a bunch of in-house code supporting a thing which might not be getting up-line support anymore, and you still have a bunch of internal code to maintain.

> Case in point: By this criteria, no one needs a grid/datatable library.So we > write it "in an afternoon". Then we're asked for an export to Excel. Later > on we're asked for pagination with large data sets. And then an export to > PDF. How many afternoons did that cost you?

You can always migrate to a library at a later date if the scope changes. More-so, you don't _know_ how the scope is going to change, how do you pick a dependency based on future scope changes?

<comment><USER119> That's exactly what my point is: This is way too complex to boil down to a simple rule of thumb to apply to all cases. There are arguments and counter arguments (and real-life examples and counter examples) ad-nauseum.

It's better to say: "Hey experienced people: How would you decide whether to introduce an external dependency or roll your own if the immediate requirement at hand seems small enough to write on your own in half a day?". Then we can get into a fun conversation that will boil down to "It depends."

<comment><USER120> Developers should try to build things before they reach out and grab a package. Usually it doesn't take too long to figure out if you are making a giant hairball. By trying to implement it yourself, you get a better understanding of the problem regardless.</comment></comment></comment></comment>


Mozilla ponders the ultimate minimal browser, looks like your start menu - <AUTHOR> http://www.geek.com/articles/geek-pick/mozilla-ponders-the-ultimate-minimal-browser-looks-like-your-start-menu-20110526/

<comment><USER2> Ubiquity was awesome; I hope it makes a comeback soon.

It was/is headed in the right direction as far as the future of the "minimal" browser goes. Instead of telling the browser "where we want to go," (go to URL) we'll tell it "what we want to do" (book airline tix for location / map this address instantly) . . . more like command-line interface, but custom to the capabilities of the web.</comment>


Physicist advances a radical theory of gravity - <AUTHOR> https://bigthink.com/surprising-science/physicist-radical-theory-of-gravity <comment><USER2> The paper by Prof A.T.K Assis called "Gravitation as a Fourth Order Electromagnetic Effect" written in 1995 discusses gravitation as an effect of electric dipoles at the atomic level. He has a couple of papers discussing this on his website [https://www.ifi.unicamp.br/~assis/papers.htm](https://www.ifi.unicamp.br/~assis/papers.htm).

What I found interesting with this idea is that it gives an explanation for only ever observing gravitational attraction and the size of the calculated resultant forces was at the experimentally measured order of magnitude. Whether or not it can be further developed and appropriate experiments designed, who knows.</comment>