In 6 years of being in a startup environment, being fast never gave me any advantage.
In fact, being too short sighted and always reaching for the easy wins gave me a lot of fragile products. The value is in well-engineered stuff. But I used to prioritize product over everything. I'm a recovering product-first engineer.
My take now is different: I'm very well aware of product and code quality. But I'm resisting my compulsions to actively control myself. I just do.
I work on whatever problems I feel are important at the day. I usually end up having product cycles and code cycles automatically.
I'm happy with this strategy. A semi-technical boss that constantly whispers micro management commands in my ears is my worst nightmare now. I'm grateful, I don't have one anymore.
Also: Wat, you don't unit test? Well then have fun developing "fast" by having to manually test your app's IO.
I think the takeaway from you experience and the article should actually be recognize what your personal priorities are, the team's priorities, and make decisions with that in mind.
A start-ups needs to survive long enough to find a business model and profitability, and that becomes much harder when you're not a technology company and put technology first.
For every Google that succeeded, there a dozen Facebook and Twitter's that took a "good enough" approach. No shortage of well-engineered products in the graveyard.
Also keep in mind that if a company makes it long enough and you continue to grow, you're engineering team output will be many multiples of what it was when you made some earlier mistakes. Much easier for a few hundred engineers to fix problems created by a dozen.
Bad business models kill software much, much more than bad software kills businesses.
Fair enough, and I guess we have to differentiate between VC-funded and others.
E.g. your comment might be true for VC-funded. But it may not be true for other types, e.g. bootstrapping.
But then additionally, I'm super surprised how a well-engineered product can transfer trust to potential customers. Consider, now that we've all been on the Internet for 20 years, we have well-trained bullshit sensors. So I'd say there are shades of grey in all of this.
I think you could make a venn diagram out of 'building the right thing' and 'building it right' and the intersection of the two is the sweet spot where a successful and sustainable product might land. Or, more likely, it's where one might gravitate to over time as the business matures.
Even within that spot there's room to shift focus - sometimes you'll want to work on technical excellence, shoring up bugs, paying off tech debt. Other times it'll be a case of taking on a bit more debt in order to innovate. The proportions of building it right and building it the right way will shift but never so far as to abandon one of those principles.
I think this mindset can lead to missing opportunities to build products actually faster. Having both code-first and product-first in your company is truly complementary IMO.
CEOs that only wonder "can it be built fast" have a very short term vision. I keep hearing things like: "anyway, we are a startup so we will pivot hence code quality is not important right now, we need to push features!".
The thing is, you don't need to reach many years so that "average to bad" code makes a new feature 10x longer to be delivered. Any experienced developer understand how a good code is truly valuable to a company for delivering. And even if it's very true in long term, this is true as well at the very first stages.
But I'd say a very good developer is not product-first or code-first, he's both, you don't need to oppose both profiles. This very good developer is mature enough to know when a code refactoring will lead to a better productivity. And he's mature enough to know that this imperfect function is OK to keep as is because it has no real implication.
Having worked on some projects that were haste-at-all-costs piles of hacks, it can be a huge morale sink being told to just bolt more stuff on and not worry about the future.
On the one hand, sometimes you really do cut that stuff loose (writing a driver for hardware and ending up switching to a different vendor), but even in those cases, there's pride in having taken the time to do the job right.
Context is incredibly important. The author is writing from the standpoint of a startup trying to fine tune an MVP. Of course it doesn't matter if it lasts if you don't know what you're building and rewriting everything isn't hard.
Code-first matters a lot when you're trying to make a 15 year old cobbled-together system last another 15 when you don't have the resources to stop everything for the many engineer-years it would take to do a full rewrite. Anything you touch is going to have to last too and people have to care about adding more technical debt because it's already the 500lb sled they have to drag behind them every single day.
That's still not code first. It's always product-first, just with different timelines. If you're working on a system that need to last, you should still optimize for the product, but over a longer time span. The code is just the means to the end.
Takes about 2/3 of the article to say that the best programmers do both, but lean slightly toward shipping product faster with an eye on quality. I hope I saved you some reading.
I get what he is saying but you can't say build it fast without tests, don't worry we will have to rebuild anyway and say you care about quality.
Good quality code is code that has a low bug count and can be changed quickly. Over engineered code doesn't fit as it can't be changed quickly. But the same is true for a hacked together mess.
He has a good point the best programmers will create a simple easy to maintain system quickly. These are generally the experienced and expensive veterans. They won't be pushed into taking silly short cuts, nor will they play with new toys at the cost of the product.
Sometimes people claim to value “quality” of the product over engineering, but by quality they actually mean short-term profits increase, which is very valid for a startup if you ask me
Yeah I agree, I just like people to be straight up about it. In that sense you are building a medium to low quality proof of concept to get revenue. This is the only way many products can ever get off the ground. If everyone knows the costs go way up when you attempt to scale this up that is fine.
I come from a consulting background. Many companies are never willing to pay for that jump in quality. You end up stuck, with a customer that doesn't want to pay for improvements but is always complaining about the cost of new features. You have short deadlines and no scope to fix the mess. It becomes death by a thousand paper cuts. You pass by the same mess over and over never given the time to fix it. Knowing it would have paid for it's self if you had been able to do it a year ago. Sometimes this was something as simple as a database script to replace a manual task you are doing over and over. Once I created such a script but was told I had do it manually for the customer until they paid us for the script. It is truly soul crushing.
Good programmers know when to cut corners. Not having tests is always a contentious topic, but it's also hard to justify when you don't have a product market fit yet.
But then again, you might be building reusable components that you will reuse when rebuilding or relaunching. So it's better to get test coverage on at least those.
Overgeneralising as usual, but I tend to group engineers into 2 camps: builders and optimisers.
Builders build product, they can ship something from scratch, doing whatever it takes to take the product over the finish line and in the hands of customers.
Optimisers are the people who like to come to already built products and iteratively solve one bottleneck after the other that builders made while getting from 0 to 1.
Both camps are valuable and both are needed, albeit at different stages of a company life. I tend to think I belong to the first camp.
I think being purely code-first is a temporary phase and you tend to get into the first or the second camp at some point.
I not totally agree with this. Architecture is really important because it can make new feature less expensive in term of development. If you judge a work only in terms of final product UX, you miss this point.
I don't disagree with you, but I've also seen working products get thrown away because of "bad architecture", only to waste tons of money and time. The worst part: the users literally never cared either way, they just wanted the product to solve their problem.
They care later when new features cannot be added, changes are delayed. A bad architecture is sometimes what you need but it will only take you so far.
Architecture is important but not as important as getting the data-model right. We can refactor out bad architecture but a bad datamodel will have missing or inaccessible data since it was created and you cannot get that back.
Not if your company goes bankrupt trying to prematurely upgrade the architecture, which is usually a huge undertaking. I think that's the entire point of the article, the guy who wrote it is clearly using a startup POV.
It makes sense to build a cheap and dirty system to start. Especially if you want to build it then inject loads of cash when it takes off. But it is still a cheap and dirty system.
Too many people do build like this initially but are not willing to pay to fix the mess when it starts to get hard to add new features.
Your data model is the heart of your business. Let's say you have a genetic product and require the user to upload their dna results and certain datapoints are taken and stored. If you decide later you want different datapoints and have not saved the original uploaded file you can't offer past customers new products.
Saving the whole file or not is an architectural decision involving cost tradeoffs, technology capabilities, and business strategy.
Which data points you put in your OLTP is the data model and, as you just painted an example of, throwaway when the use cases change. Later you'll want different data points or different relations. And then you'll evolve your data model yo serve that. If you did your architecture right, it will change much less than the data in your databases.
Product-first engineers don't avoid architecture. They tend to know when you can skim on building it, or when the common development tools already provide enough of it.
Sometimes, it's as simple as "frontend, backend, and a way to deploy it".
Not to mention so many developer tooling products out there already decide on the architecture for you. Use anything firebase for example, and you'll be pretty railed in around the way your system is architected.
Sure; well rounded engineers care about architecture as well. But in the same way some “code first” programmers are myopic and only really care about the code, plenty of product first engineers only really care how the product looks. I’ve met and worked with plenty of people who don’t have the skill to be creative with architecture, or don’t know how to structure the code to avoid certain bugs showing up over and over again. Or have no idea how to make their code run fast. - So their software becomes a beautiful, laggy mess.
One “product first” engineer I worked with years ago made a database indexing system, syncing our data into elasticsearch so we could add text search to our product. For about 6 months after the feature launched we kept running into indexing bugs - where data was missing from the index and things like that. I (naturally code first) ended up helping rearchitect it. After we relaunched the feature we never had another indexing data bug as long as I was at the company.
Sometimes it’s faster to take more time to do it right rather than do it wrong and spend your life playing whackamole with bugs. It all depends on your context. (Is this a MVP to throw away? Or are you working on code that will probably still be around in a few years?). The best engineers know how to adapt their own personal process to the needs of the project. Sometimes that means quick and dirty. Sometimes it means thinking it through and building it to last.
We're arguing about semantics. What you define as "well rounded" I define as "product-first". What you define as "product-first" I would define as "inexperienced".
Yes, and what you’re describing as “code first” I define as myopic / inexperienced / single minded engineers.
Maybe the broader frame is to say there’s two perspectives to hold: the perspective of the user and the perspective of the code. Each orientation has its own set of supporting skills. Good developers are strong in one of those perspectives, but need other people on the team to balance them out. Excellent developers are strong in both, and can switch between them based on the immediate needs of the company and project.
Hi! I'm the author of the post. Glad folks found it interesting.
One comment I would add on top of what's being discussed here is that I actually am not arguing that the main engineering tradeoff is between quality and speed.
Instead, what I'm saying is the best engineers I've worked with work backwards from the user experience (the product) and engineer their system and app in support of it - e.g. they judge their work by how well the product works, not by some other metrics around the code in the abstract. They do tend to produce what you might consider great code (code that is simple, well factored, well tested), but the point to them is that they need to do that in order for the app to work really well.
As a code-first developer I never judge my work by code metrics or other things in the abstract. What does that even mean? I just cannot agree with most of the things said here.
The definition of great code is not simplicity and test coverage.
The best developers I’ve known have always been code-first developers. They care about the thing they are building, more than just the result. You don’t want a car that just rolls off a slope. You want a car that was pieced together with blood, sweat, tears and love.
As someone who lived through, and ran a startup during, the era of 1999-2006, I would say that at the birth of a new industry there is often a period where being first is a huge advantage. But it's important to realize this is a small window of time. In most industries (cars, telephones) it is at most 20 years, and it is well known that the Internet consolidated much faster than other industries -- we went from having nothing to having 30 search engines to have one monopoly during the years 1990 to 2008.
If you happen to be alive and working during the first 10 years of some new industry, then working fast can be an advantage. Just realize that such an era is an exception. There is no need to make a fetish out of being fast, for most industries, most of the time, there is no particular advantage to being fast, and it can be a detriment in the many mature markets that demand quality first.
This is the stuff nightmares are made out of, leading from security issues, to data loss and instability. I've lost weekends of my life tearing apart bad code because some manager wanted a feature shipped and didn't want to go back and fix the technical debt.
I don't believe a team can be effective past small MVP stage without some kind of automated test that covers their product's critical path(s) especially from the customer side, and especially as headcount goes up.
Though I agree there are programmers who are overly dogmatic to the detriment of products.
But I've also met several managers who are preoccupied with the idea that devs are too perfectionist even as their products are morasses of technical debt and untested code.
It seems to surface as a symptom of environments where management isn't technical enough and judge products and progress superficially.
HN seems to get more this sort of code fast posts of late, and it's a straw man argument. A mature developer can write good code by default mostly by keeping an eye open for code smells, no bloated classes or functions (I've seen 5000 line functions in established production code), no inconsistent abstractions etc. Just like you can keep your body clean and tidy by good daily hygiene it is possible to grow and mature a codebase by doing the right thing everyday.
Okay once in a while you can take on a bit of technical debt but a mature developer will pay it back quickly.
I never was a fan of the move fast, break things, and stay foolish mentality proposed in the startup world.
I can't count how often I was faced with the expectstion to build something in under a month that could take half a year, no problem.
And you see it day to day with product-first solutions out there. They don't want to dive too deep into technology but use high level solutions, and we get high latency APIs and memory hogging UIs.
I think code-first can win in the long run, but it's nothing that can be done with a 50k seed round and 3 months to MVP.
A lot of tech debt is just passing the buck from bad product leadership onto engineers. If product is chasing the new hot feature of the week maybe they don’t have a long term vision
Having a "feature factory" product team is a symptom of:
1. Having a weak product leader not willing to tell the C-suite and/or sales team "no."
2. C-suite is sales driven rather than product/engineering driven. "Build feature x so we can close this deal... it doesn't align with our vision but yeah yeah yeah let's get the deal!"
3. C-suite wanting to know why they aren't seeing their expensive in-house dev team pumping out new features.
Language, syntax, test
coverage, performance, coding style, linters, none of it really matters. No code is more beautiful than code that perfectly matches your problem domain. Being able to build a product in terms of high level building blocks that are sensible for the problem you’re trying to solve is what makes great code.
A few nice abstractions that allow you to pivot quickly without too much thought. Everything underneath is irrelevant and replaceable.
I agree in spirit. Setting up a linter takes an hour though and is a worthwhile investment even if you are a cash-strapped startup with no customers. Given how many static analysis errors it reports these days, it will pay off dividends with less debugging.
There is also the time dimension. Some tools (languages et al) are misfit for some problem domains and might compromise your time to market and the viability of your product idea.
Although some programmers care about both product and code and know how to balance it: based on the budget.
Code-first programmers might have not had to face a deadline and a company running out of money. Not all of them are like this, but if you find yourself in this camp, I encourage joining a startup with some eyeballs into the finances as a way to balance that tendency to infinitely nitpick over small code details.
There’s a good idea in the article, but I’m trying to distill it into something I can use:
I don’t think we’re bifurcated into two kinds, it seems more reasonable to say there’s a spectrum: at one end engineers are more predisposed towards the way a program behaves externally, on the the other side, an orientation towards quality of the internals.
On a separate axis we have development speed/competency, and in practice that really becomes a budget to be spent on external or internal quality. A top performer probably has time to do both. Someone struggling won’t do well at either.
I would hope that for a thoughtful, experienced and self disciplined engineer, regardless of predisposition, conditions would dictate their focus, such as: maturity of product, maturity of industry, importance of correctness (e.g. writing a database vs a CRUD app), and the goals of management.
My default methodology is Product-First, but I’ve worked on some projects where I behaved Code-First. My absolute favorite thing is to solve customer problems with high quality engineering. There are some customers I did not want to help — because of personal indifference to the customers and their goals. I still wanted a paycheck so I dived deep into thinking about clever abstractions or tried to cram in some new technology. I was engineering for engineering’s sake.
I’m lucky now to be working on projects and teams I care about, and I think first about what type of problem I should be solving, and then I think about what type of engineering would best solve that problem.
For large project code first is the only approach. You spend large amount of time in development actually using your own abstractions.
Code first done well actually allows you to work faster as you progress clarifying the domain model. You know you are doing it well when every new problem seem to have natural solution with the tools you have built so far.
I have seen so many projects start "product first" then stall or crawl to completion, then a lot of problems on deployment and requiring a rewrite almost from day 1.
"Product first" in my experience is just a blank waiver to employees to just fuck it and not care about quality.
Great write-up. Thought provoking and something I definitely have seen. I'm a little more on the product side ... However I might suggest a slightly better prism to shine the op's light through to suss out nuances:
- time frame: the more immediate your attention the more code emphasis you have. The more depth first the more code like you are. The more senior you are the more product you might be because you're able to see beyond the day to day noise.
- TQA v SQA: (Total quality attribute v substitute quality attribute): in fact neither code or a product emphasis can win because in truth the two are interrelated. Tqa is to product what sqa is to code.
Example:
The NYTimes buys rolls of paper to print newspapers with. They notice supplier A's rolls rip in the press which requires downtime to fix with subsequent spend of resources to remediate and greater effort to meet deadline. When NYTimes phones A you hear a guy yelling: your rolls suck. They are constantly ripping apart in our press (product or tqa complaint: roll should not rip).
To fix A is going to have to trace the tqa to it's sqas:
- what's average paper thickness? How much does it vary? Where? Why?
- how long did we bleach it because that may increase chance of tears. Maybe bleaching makes the paper brittle
- how hard does the press pull on the paper? Maybe it's too tough on the paper?
- is the roll sufficiently protected? Maybe shipping or storage knicks it and sets up failure in the machine?
- etc
So yah better have tqa on the brain. Customers do. And customers write checks or don't if dissatisfied. But better have sqa on the brain because that's how tqa (product failures) are fixed.
So? Teams in which persons fixate on sqa (code) or tqa (product) is the real poison. The more my counterpart cares about code only the more I have to care about product and vice versa. We'll wear each other out.
Therefore I might need a code first person to spend a little more time typing up usecases so we can see how better to architect and better see how features interact. I might need a product person to be more insistent on more thorough unit testing and less complicated class apis.
In fact, being too short sighted and always reaching for the easy wins gave me a lot of fragile products. The value is in well-engineered stuff. But I used to prioritize product over everything. I'm a recovering product-first engineer.
My take now is different: I'm very well aware of product and code quality. But I'm resisting my compulsions to actively control myself. I just do.
I work on whatever problems I feel are important at the day. I usually end up having product cycles and code cycles automatically.
I'm happy with this strategy. A semi-technical boss that constantly whispers micro management commands in my ears is my worst nightmare now. I'm grateful, I don't have one anymore.
Also: Wat, you don't unit test? Well then have fun developing "fast" by having to manually test your app's IO.