Hacker News new | ask | show | jobs
by RealDinosaur 2702 days ago
For me (Javascript Developer), you have to stand on the shoulders of giants if you want to compete. Any code you re-invent is code you have to maintain.

I've found though, some engineers love to create everything from scratch, and this greatly hinders their ability to hire/fire as everything is proprietary, and usually not documented.

Most decisions are pretty grey, but for me, choosing to handle stuff yourself is never a good choice. In the same way as no-one should ever try and create Unity from scratch, no-one should try to create React from scratch. You simply can't compete with the support and effort of a global development team.

If you wanna learn though, that's a different kettle of fish. Reinvent the wheel all day. Just don't use it in production.

9 comments

Re: Any code you re-invent is code you have to maintain.

But the flip side is that any code you borrow you have to fix, debug, and/or replace if it doesn't work as intended. I personally find it far easier to fix my own code than others' code.

I'm not claiming one should reinvent most wheels to gain control, though, only that there are trade-offs for each. If you borrow code, you should have an alternative(s) in mind if it stops working in the future or key bugs are found in it.

For example, using a JavaScript date-picker gizmo for forms is usually not a big maintenance risk because there are multiple to choose from. If you had only one choice and that choice went kaflooey, then you'd be stuck.

Well, the user could hand-enter dates. For internal software that's an acceptable temporary work-around, but not for commercial software, because every customer expects a date-picker (and the HTML5 ones currently stink if you want mm/dd/yyyy formats).

In short, don't heavily depend on any external part you don't have a "Plan B" for.

> I personally find it far easier to fix my own code than others' code.

This is a problem with larger teams though if anyone else needs to work on the code, and results in code that doesn't have documentation/support available.

Not documentation as in 'He didn't make a confluence' page, but documentation as in 'If I google this error message will I get a good answer'

I'm not sure what your googling-error-message example is intended to demonstrate. And again I'm not claiming self-rolled is always better; but merely responding to a specific claim. The bottom line is one has to weigh the trade-offs using multiple metrics and factors. A large part of managing technical projects is the balancing of tradeoffs.

IF an app depends heavily on a feature AND there are not many external alternatives, then a shop should lean toward rolling their own.

A related issue is the volume of code. If the in-house version is 500 lines of code and the external (downloaded) version is 5,000 lines, then the internal one may be easier to debug and fix. (Yes, I realize that lines of code is not the only factor to consider.)

Common factors to look at:

1. Complexity of the part, including dependencies on other parts.

2. Swappability of the part for alternatives.

3. How well the part is written and documented.

4. Need for the part. If it's merely a "bonus", then dependency may be less of a problem/risk.

If you use an external library, it's much more likely that you can google any issues you have with it, rather than having to reverse engineer it. The reason the GP quoted this:

> I personally find it far easier to fix my own code than others' code.

is that if you work on a team, you're fixing others' code either way. The difference is that with an external library there's usually documentation, a community, etc; but with a home-rolled solution, you're usually on your own.

External libraries usually have to cater to wider usage and thus have more code and more parts and more options. A "dedicated" in-house module will typically be much less code because it has one job, meaning less to read, reverse engineer, test, etc. I'm not saying one is always better than the other, only that one brings in a rather complex wad of code in most external libraries that could be a bottleneck.

The "community" often ignores my bug fix requests, I would note. Maybe I ask wrong, but we don't all have wonderful asking skills. If you do, that's a nice feature of your personality, but doesn't necessarily extrapolate to all code users.

I'm not sure how long you've been a JavaScript dev or how senior you are, so forgive me if this sounds condescending. For what it's worth, I'm genuinely not trying to be condescending.

As I matured into the profession, I went through stages of dependency. In the beginning, I wanted to build everything myself because I was learning. In retrospect, this was a good choice because I was way too green to pick a dependency and at least I knew my own code was crap. Then, I reached a place where I wanted to stand on everyone's shoulders - I agreed that any code I had to write myself was code I had to maintain myself.

Lately, I see all the grey in between those two points. I'd sooner not try to reinvent React because that would take me an obscenely long time. But, for more trivial things like left-pad or escape-string-regex, I've discovered that it's cheaper to implement and maintain it myself than to go through all the steps to vet a new dependency.

There's a strange place in this industry where rolling your own solution is cheaper in the long run.

I never suggested left-pad myself, but what I would do is copy and paste a function off stack-overflow, name it appropriately, and encapsulate it, maybe write a test that is the flavour of the month.

Then leave a link to the page I got it from in the comment above.

I'm about 5 years into my career, and have re-invented the wheel in the past myself. It's great fun to make these huge rude-goldberg-esque inventions but for making an MVP, it simply isn't worth it.

Specifically avoiding libraries like express, react, ORMs or crypto though... People love to do that, and far too often it ends up living for eternity.

I always advocate... don't bother. :)

I don't recall meeting a developer honest/confident enough to admit to copy/pasting off of Stack Overflow. That takes one heck of a lot of courage.

I don't actually know you, but I like you. That was really great to read!

I've been a professional developer for 15+ years, I don't think I've ever seen anything posted on stack overflow of high enough quality that I would happily paste it into a production system.

Great to use a guideline for a problem... but copy and pasting from stack overflow (even with a comment to that page, which i've seen!) just no!

I'm inclined to agree with you, though I still think that RealDinosaur deserves a lot of credit. He or she was still honest and forthcoming about that. It's impossible to start teaching better practices if people aren't honest about what they do!
I am a JavaScript developer fulltime for more than a decade.

> you have to stand on the shoulders of giants if you want to compete

Hold on there cowboy. We are what we are. Nobody starts out as a rockstar coding ninja. It takes practice. Just take it one step at a time. Solve for problems as you encounter them. The challenge you go through to provide that solution will open your eyes to other potential solutions to other ever challenging problems you never would have seen otherwise.

> Any code you re-invent is code you have to maintain.

If its code that has found its way into your code base you are maintaining it anyways. That is why dependencies are debt. If you have not reviewed the tests and/or validation of those dependencies you are introducing untested code into your application on blind faith.

> In the same way as no-one should ever try and create Unity from scratch

I don't think anyone is really trying to create Unity from scratch (unless they're trying to compete with Unity). But that doesn't necessarily mean you should just use Unity. Unity is complicated, and designed to be a general purpose game engine. Which means for any given game, it may or may not be a good fit. A lot of times you can get up and running faster in Unity, but soon start to hit walls as you try to do something more advanced. If you wrote your own engine, you would just modify it to meet your needs, but with Unity you end up trying to find workarounds for its shortcomings.

I also think your example with React is flawed. There's a big difference between left-pad and React, and I think the most interesting packages to discuss is the range of things between those two.

> no-one should ever try and create Unity from scratch

Some game developers do write their game engines from scratch. I know of at least one successful example: Jonathan Blow, with Braid (2D engine) and The Witness (3D engine). Note that in both games, a generic engine wouldn't have worked, or at least would have required such an amount of customisation that it's not clear it would have cost less, or looked and felt as good. Sure, don't go rebuild a generic engine from scratch. But a custom one, tailored to a very specific use case? That's not such an obvious no-no.

Another example would be Monocypher¹, my crypto library. Why would I write such a thing when we already have Libsodium? The reason is, I saw that I could do better for my use case: an opinionated, easy to use, portable package. The result is massively simpler than Libsodium. I don't care that I cannot compete with the support and effort of Libsodium team. I made sure I didn't need to.

[1]: https://monocypher.org/

> Another example would be Monocypher¹, my crypto library.

I don't know who you are, nor what Monocypher is, beyond what you have written here, but this example should come with some caveats listed.

It is generally considered "best practice" to -not- attempt to roll your own cryptographic system and use it for production purposes, unless or until it has "ran the gauntlet" of peer review - and that review may be long and harsh.

Maybe your library is a wrapper around existing functionality to make that functionality simpler to use; or maybe your library has "run the gauntlet" and you are also a "well known" person in cryptographic circles, and so your work is trusted.

But again - the general developer should never think to create and distribute their own cryptographic library system, and one would be cautioned that even a crypto library that is "only a wrapper" around other crypto algorithms or libraries should also be thoroughly vetted before incorporating it into your project, especially if that project is anything more than a hobby grade system.

> this example should come with some caveats listed.

No longer. You would know if you spent 10 hours reviewing Monocypher (which I reckon is not a good use of your time), so it's natural that you don't.

> It is generally considered "best practice" to -not- attempt to roll your own cryptographic system

I am keenly¹, painfully² aware of what it takes to write production grade crypto. And I didn't really roll my own. I only implemented primitives everyone trusts. And I wasn't alone either. I've had lots of reviews, as well as substantial external advice and contributions. That you can confirm by scouring the GitHub repository and the Monocypher website for 15 minutes.

[1]: http://loup-vaillant.fr/articles/rolling-your-own-crypto

[2]: https://monocypher.org/quality-assurance/disclosures

---

With that all said, your overly generic advice sounds like you didn't even click the link… did you?

Braid and Witness could have been written in Unity though.

I'd argue that dealing with high level concepts such as game/level design and art direction and low level stuff like graphics and rendering simultaneously is insane. I don't know how Jon Blow did it, but personally being able to abstract away all that low level stuff makes the design process way easier for me.

There was a recent game, 'Return of the Obra Dinn', which went the opposite way. It was the dev's first game with Unity, and he attributed most of his success to the Engine.

It doesn't look like a Unity game, it doesn't play like a Unity game, and it has won several game of the year awards.

Come to think of it, there's Antichamber, a non Euclidean labyrinth based on Unreal Engine (4, I believe).

As for how Jon Blow did it, I suspect having his own engine let him explore gameplay ideas more readily than using a generic one. The time travelling in Braid and all its variations would be pretty hard to bolt on a generic engine: it's not just rewind, it's partial rewind, with some entities being immune to the rewind. There's even a level where time goes forward and backward depending on the position of the main character. Go right, forward. Go left, backwards.

For The Witness, it's a bit more subtle, but about a third of the game required pretty crazy 2D projective analysis of the 3D world (the "environmental puzzles", don't look them up if you don't want spoilers). While it didn't en up being central to the game, it was basically the starting point.

The engines of Jonathan Blow's games are more central to their gameplay than for most games. Still bloody impressive, but probably less unnecessary than one might originally think. Also, Jonathan Blow has pretty strong opinions about game development, and I got the feeling that he disagrees with most generic engines out there. Working with them would probably caused suffering, whose cost he didn't want to pay. (Speaking for myself, my productivity drops pretty sharply when I spot stuff I too strongly disagree with, and I can't fix it.)

Maybe Braid and The Witness could have been written in Unity, but it's not at all clear that it would have saved any time, or that it would have resulted in something as good.

There are a lot of issues I've seen devs run into with using Unity, sometimes much earlier on than you'd expect. Unity was designed to be a generic engine, which means it won't be ideal for every use case.

There's a greater issue that is often ignored here. If React is so large/complex that one ought not create their own version from scratch (I actually question this assertion, but will grant it for the sake of discussion), it begs the question as to how risky it is to bring into your stack. How trivial is it to replace if its so complex? Vendor lock-in can be a real problem for teams.

Remember the React license fiasco? What if Facebook hadn't caved there and removed all the controversial patent language (by relicensing as MIT)? What if, as a matter of existential risk, you had to make the business decision to remove React from your app?

As such, I think the other component of this particular decision tree should include how much you become dependent on a particular library/module/framework and the consequent risks that introduces to your organization.

There’s a nuance here that I’d like to dive into, though, as well. There’s a parallel that any code you don’t invent, I’d argue, is harder to maintain, if necessary.

Find a bug or want to add new functionality? You’re either now maintaining an internal fork or working through legal to get a patch pushed to OSS (Personal experience, but the idea of there being work involved with changing a dependency is still generalizable, I believe).

The result of this friction, I’ve found, is one of two scenarios. The first is that there is just a lot of glue code. This glue code bridges different libraries in an idiomatic way so that the team can now understand how different parts interact. The second method is the wrapper method. Every piece of useful functionality is abstracted out so that the wrapper writer can do additional things in between and also buffer API churn.

Even with that said, I often fall into the “If someone else can do it for me, I’ll manage this dependency risk” category, as I assume you do as well.

> Any code you re-invent is code you have to maintain.

Any code you pull in is code you are responsible for. And you aren't in nearly as a good position to maintain it.

The issue I seen is problems like this

I need to make a thumbnail from a video

What a regular backend developer would do is to call ffmpeg from his language

What a JS/node dev does is to find a random package on npm that does that for him, maybe has no idea what ffmpeg is, has no idea that he can change parame6ters and options, he just reads the package readme, installs it and it's 10 dependencies and job done.