That never happens in the real world. One always has limited time to produce a viable product. There is always some extrinsic constraint to how much time can be spent taking your time and understanding what you're doing.
Moreover, if you are operating in any commercially viable product space, you're always competing against other firms for finite market share. If it takes x years to ponder and understand how to build and ship a masterful feat of engineering, while some other company ships a "sort-of-works" product with bugs and engineering flaws in <<< x years, the other company will usually win in the marketplace.
Your company usually goes bankrupt, and all the engineers will complain at their next jobs about what a wonderfully designed engineering system they were building, and how awful it is that nobody appreciates such things these days.
How often does substandard technology and technical debt become a drag on a business not long after that first move, allowing someone else to overtake because the poorly built system couldn't scale to production levels or wasn't adaptable enough for changing requirements or failed so often that the early users drifted away? How often do we see developers advocating shortcuts and showing limited understanding of basic software development or computer science ideas, only to see the product they work on being rewritten within a year or two, or the whole team shut down?
You can try to be fastest always. You can often succeed, at first, if you take enough shortcuts. But you can't sustain that pace without enough quality in your people and your code. Planning to throw each implementation away and rewrite with more resources every year or two is a very unicorn-like strategy. It reminds me of VCs whose strategy is to invest liberally, who are fully aware that most of those investments won't work out but they're hoping for one or two in each batch to become the next big hits.
Real engineering isn't done in a vacuum and its goal isn't perfection. Real engineering takes issues like costs and timescales and staffing into account and aims to find a solution that is good enough on all counts. But it still has to be good enough. Producing junk but quickly and cheaply is an effective strategy until it's not and the success of any product using that strategy comes down to little more than the luck of the draw.
My post was addressing the common case where an engineer seems to ignore the 'resource constraints' side of the equation altogether.
Balancing these factors is more art than science. No two projects have the same set of resource constraints, nor the same set of engineering challenges. Luck is a big factor. The solution depends heavily on the exact details of each particular case.
IME retrospectives rarely sound like "We hired a team of strong developers, they did a solid job, but then the business failed as a result". The kind of developers who are strong enough to do a solid job are probably also experienced enough to recognise the other considerations in play and adapt if necessary.
While this is obviously true, I don't think it depicts the actual decision making process that leads to messy codebases and crappy products. In my experience lack of experience and/or laziness play a big part.
A competent tech lead that's passionate about quality AND is willing to be annoying for the greater good makes an enormous difference. I'm talking multiple orders of magnitude difference.
It's the difference between spinning up a k8s cluster + service mesh vs tiny single server vps with basic failover. The former is thousands of hours of dev time across multiple disciplines while the latter a seasoned engineer can handle by themselves.
This is precisely why I try to interview tech leads about what they shipped rather than what they built. There are a lot of otherwise very talented developers out there who will spend years playing around in your codebase, writing beautiful code, but not actually shipping anything useful. Replacing them with shipping-focused engineers, even if they're not as technically competent, usually results in big productivity boosts.
This isn't a popular opinion among developer communities, but it's a common theme in the management forums I'm part of. It's important to have fun and budget some time for things like open-source contributions and library building, but the top priority must always be on shipping product.
Realistically, a couple of engineers writing a library from scratch isn’t going to be higher quality than adopting a mainstream, battle-tested library that accomplishes the same thing.
Writing your own implementations of everything can be fun, but it’s not possible to compete with all of the iterations and reviews that a mainstream library collects over time.
An open source library is necessarily generic and has to be battle tested to make sure it fulfills all use cases, while the library you write only has to cover your own needs that makes it easier to understand, extend and debug
That's true but the vast majority of what you find on NPM is not mainstream, battle-tested libraries.
Libraries that do clear that bar tend to be widely useful but that suggests generality you won't necessarily need for any single use case. A couple of good engineers might struggle to beat a well-established open source library at everything it does, but that is rarely what they are trying to achieve. They just need something that is better for their own specific needs at that time, which might be a useful and realistic target.
Also many "battle-tested" libraries are not really very high quality - they all have bugs, unnecessary complexity and technical debt. Higher degree of testing they get is often offset by the higher number of feature requests, and more features means more complexity and more bugs.
And in reality I saw it many times when a niche library written by a solo developer is of a higher quality than a super popular behemoth written by hundreds of developers over 10 years.
- ubiquitous things, like data structures
- hard to get right things, like time
- implementations of specs, like Unicode
- hardware interfaces, like CUDA
For everything else, I'll take the above and roll my own solution.
> - ubiquitous things, like data structures
There are a few basic data structures in JS, but almost everything else is in user-land.
> - hard to get right things, like time
Date is a notoriously bad API in JavaScript.
- implementations of specs, like Unicode
We just get a String type in JavaScript which is UTF-16, so...
Well, no, we aren't. We are talking about the Elm language, which compiles to JavaScript.
There are also other excellent languages that target JavaScript that have these things.
I've also seen many developers for years adopting mainstream libraries and frameworks wrongly.
The atrocities I've seen built with Ember, Rails, Angular, and the like.
Often these people built their own (albeit less powerful) libraries and could work much better with them.
In my experience, if someone fails at using mainstream libraries, they will also likely fail in creating their own, at least if it is to later be used and maintained by anyone else successfully.
The problem with mainstream libraries is to grasp the mental model of their creators.
I met a bunch of developers who understood software design patterns as they are taught in the GoF book, but couldn't see them when applied in a framework/library. Often this was because the design patterns weren't used 1:1 or framework creators simply used the wrong name for a pattern.
It's not that simple. I realize this may be uncommon, but it's possible to work on a product that is truly worthwhile, that improves peoples' lives, and whose target users urgently need a solution to the problem you're solving. I recently developed a product that I believe meets this description (I won't plug it here). I chose Elixir for the web application. While I think that's a defensible choice, given the real-time nature of the application, I sometimes wonder if I would have been better off choosing a more mainstream language -- one with an official Stripe client library, for one thing. Any day I spent unnecessarily reimplementing something because I chose Elixir is a day that the target users couldn't benefit from my product. And, bearing that in mind, I should get back to work.
Choosing non-popular languages is a trade off yes but not as much as people think especially if you have a good team willing to learn them.
There are also benefits apart from technical ones like better job retention and attracting finer talent without having to filter hundreds of resumes. I will say if your business is made around hiring and making anyone work of the shelf then it's a bad idea.
It gets really hard to maintain after 10 - 15 years. I wish we had rolled our own libraries for some of the simpler functions. Even in PHP this would have made life so much better.
Good. The longer I do this, the longer I realize that unless your in a race-to-the-bottom industry (something like vying for eye balls to increase ad spend), then this is categorically a bad thing. I would prefer the quality of engineering required in knowing how to do some of these things yourselves.
Take your time. Understand what you are doing. Some of the world class technologies we all know and use daily use minimal dependencies.
And with more malicious code entering more package repositories, it might be apt advice more than ever today.