Hacker News new | ask | show | jobs
by teddyh 765 days ago
I see two huge bad habits here. The first is the obvious one, as pointed out by many commenters here: Don’t implement standards haphazardly, if you even should do so yourself. Either give the implementations the necessary care and attention, or use a pre-made library.

But the other thing is: Don’t vendor your dependencies. Those libraries you use need to be updated regularly and timely, and absolutely not “only as necessary”. If updates lag behind or are avoided entirely, bugs like this can be huge problems even when the upstream code has been fixed, for people who thought that they should update only when they, themselves, see a problem or need.

2 comments

> Don’t vendor your dependencies.

The alternative seems worse: your own application's stability is now at risk against upstream changes that could break your code. Sure, you might not get a fix immediately, but I'd rather know I'm making a change because I need a fix than introducing instability and additional risk that I don't want to subject myself to. "If it ain't broke, don't fix it."

I like Go's approach, which ensures that all upgrades happen when you choose to do some upgrades.

(For apps, a lock file will do it too.)

Taking dependency updating to the extreme, some Google projects adopt a "live at head" philosophy, where their projects depend on their dependencies' top-of-tree main commits, not a release branch:

https://chromium.googlesource.com/chromium/src/+/HEAD/third_...

You can choose to either live at the slightly-bleeding edge (as determined by “stable” releases, etc), or to live on the edge of end-of-life, as discussed here: <https://news.ycombinator.com/item?id=21785399>

(And surely you should have tests to verify all your own functionality after upgrading a dependency?)

That "should" is load bearing. Unfortunately thorough automated testing isn't frequently done by application teams, and even fewer automated testing of dependencies is done by them. Most developers assume, for better or worse, that testing of dependencies is the responsibility of their respective authors.
> Don’t implement standards haphazardly, if you even should do so yourself. Either give the implementations the necessary care and attention, or use a pre-made library.

I agree 100%.

Famous last words at >50% of the companies I've worked: "Just implement as much of standard X as you need to ship an MVP of feature Y!"
Can you share a story?
I had a very difficult to track down bug that ended up losing us a very big fish client, that came down to parsing a binary file with an ad-hoc parser that looked for the index of a header. They didn't realize that after the header was some metadata, so a small amount of metadata was interpreted as data. I fixed it by writing a proper ad-hoc parser that actually worked on a header-by-header level. But the damage was done and we had looked like buffoons to the client.

Was very hard for the team. There was a shouting match over it, some hard feelings. The code was written in the spirit GP alludes to by an enthusiastic executive who wanted to help lighten the load. I should've rejected the PR but was intimidated to reject the exec's code (not an engineering reason for an engineering decision!). The exec was a good data scientist but not as strong a coder as me, and parsing binary files is one of my specialties.

Friends don't let friends parse using "indexOf()".

As the sibling comment already mentioned, file format reading is a big one. Oh, a customer needs us to ingest CSV data. Let's just roll our own CSV parser, the file format is simple, right? What could go wrong? Same for graphics formats. We need to read PNG files, so let's just figure out the format and implement just enough to read the handful of files we have on hand. Even though libpng exists.

Another, more domain specific one: We have to talk to a GPS receiver that connects via RS-232 and outputs NMEA formatted data. This device, like all such devices, outputs a small subset of the standard. So parse just enough of it for that one device we have to get working, and ship it. Then someone attaches a different device that outputs a different subset of the standard and the software fails (sometimes gracefully, sometimes not).

That reminds me of the Windows Mobile 6.5 device with built-in GPS receiver, where on the 31st day of the month, the API would actually output the date as the 0th day of the following month. This wouldn't have been a problem, except that we were using that to set the system clock. The devices would reset their clock if allowed to go completely flat, but they didn't have reliable NTP support either. I believe the OS would just ignore our attempt to set the date to an invalid value, leaving it at the system default date.

It was a struggle to get the vendor to even acknowledge the problem, since it would only happen on 7 days out of the year, and usually 60 days apart. (There are only two consecutive months with 31 days, July and August.) It did eventually get fixed.

I seem to recall writing a workaround, but then it being stalled by our customer's Change Control Board.