Code-First vs. Product-First
thezbook.com
thezbook.com
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Data models are a dime a dozen and are throwaway.
Your architecture can change.
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.
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.
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.
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.
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.
Thanks for all the feedback!
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.
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.
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.
Okay once in a while you can take on a bit of technical debt but a mature developer will pay it back quickly.
Product-first engineers build for the end user who wants to solve a problem.
Code-first engineers build for the next engineer who has to build on top of their work.
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 few nice abstractions that allow you to pivot quickly without too much thought. Everything underneath is irrelevant and replaceable.
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.
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.
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.
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.
- 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.
Guess which type I prefer.