Engineering for Product market fit
Tags: webdev, startup, programming, javascript
Published: 2024-05-13 13:57:27

Product market fit is the **_only_** north start that you early stage startup should be chasing. Engineer your product to support you in that journey. 

Do not get in your own way with overly complex engineering. Keep it simple!

## 1. Journey of product market fit

### a) Research 
Market is the most important component of product market fit journey. Market is alive even if your product is not, vice versa is _not_ true. While building your product you'll research the market throughly. Come up with ideas and hypotheses to serve some unserved need and keep doing it over and over again until a **fit** is found.

### b) Experiment
This journey involves a lot of experimentation and hypothesis testing. Your rounds of user interviews, sales calls and analyses will result in product specifications. These product specifications are your bets on things that can close the identified gap in the market.

![Product spec chasing market](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/99mdv3opy3c5gweykc9e.png)

### c) Grind
You then need to develop this product and actually test your theories in the market. On real user testing:

- Your hypotheses can be proven wrong
- You might need to make adjustments to product
- Try a new product direction
- Seek an entirely new market

The grind is inevitable and it is costly. Unfortunately, you can make your life harder by doing _unfit engineering_.

**Unfit engineering**: Engineering practices that are not suitable for this grind.

In a nutshell job of engineering is to:
- Develop on product specifications, fast
- Change directions quickly
- Let go of artifacts completely, if required


## 2. How to engineer for product market fit

Objective for engineering is to create a software to test your product theories quickly. 
Objective for engineering is **not** to support millions of imaginary users.

As your understanding of problem space changes, the shape of your product will change drastically. This will result in running many experiments and iterations of developing product and testing with users.

Your aim, through these iterations, should be to test out your hypotheses about market as precisely as possible.

When market rejects your product you should have conclusive answer to following questions:

- Why my product failed?
- What should be my next move to improve things?
- What does not work in this market?

You should have business answers to all these questions and none of the answers point to the flaws in your engineering. Using market feedback to learn engineering practices is prohibitively expensive!

Therefore, it is crucial to map product specifications for each iteration precisely to code. So that product failures reveal the lack of understanding of market rather than poor engineering.

You should not end up in a position that your product is so bad that user could not use it at all. Leaving you without answers: whether your insight of market is right or if user could try the product to produce reliable data points.

### Write throw away code

Do not carry any tech debt between product iterations. Write throw away functional code that is loosely coupled such that it is easy to delete large parts of code. If you do not remove unused code between iterations it'll get harder and harder to map new product specifications to code, which greatly diminishes the quality of your product testing.

Steer clear of object oriented programming. OOP has an inherent disadvantage at this stage of product. OOP requires developers to create mappings and relations within application data. However, it cannot be adequately done because real relations in the problem space are yet to be discovered.

Avoid creating complex data mappings in your data graphs and API contracts. These inaccurate mappings get in the way when you want to change things quickly and many of previously created relationships are proven incorrect. 

When stuck with bad data mappings or inheritance structures, developers start to cut corners and start to project their code's poor representation of world back on to the world, which results in disastrous user testing and inconclusive understanding of problem space.

_Bonus: Read [Avoid Hasty Abstractions](https://kentcdodds.com/blog/aha-programming) by Kent C. Dodds._

**Golden rule: Engineering chases Product Spec, and Product Spec chases Market**

![Engineering chase Product spec chase market](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4xmfjq9qxcxmlvjay74j.png)


This relationship should never be inverted, otherwise you are in trouble!


### Use commonplace technology

New technology is unproven and adds needless uncertainty in your quest to product market fit. Your success should not hinge on whether a new technology or framework succeeds, it is simply foolish. 

Using commonplace technology is awesome! You will not have to work on unproven things to make things barely work. Librating your attention span to focus just on finding your product market fit.

Additionally, you'll reap following benefits:
- Support: 
  - Plethora of libraries and packages to choose from
  - Your questions have many hits on StackOverflow/GPTs
- Access to large talent pool for hiring
- Standardized engineering patterns to follow

### Follow best practices

- Your job as an engineer is write maintainable code that serves business needs.
- Your job is **not** to use all the features of programming languages. Many features tend to be bad features.


![Good parts small subset of all parts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lhd6k2gy4d8olbc60lui.jpeg)


_Q. Why do bad parts exist in programming languages and frameworks?_

_A. Because they are created by humans!_ Humans tend to do mistakes.
- Create features that do not deliver on promise
- Do not solve any real problem
- Lead to bad programming patterns

Language builders go through their own journey of product market fit. In this journey, just like yours, they create messes.
 
Unfortunately, none of the bad parts can be removed due to backwards compatibility - all the code written using bad parts need to be supported.

Fortunately, you can choose not to use any of the bad parts and steer clear of the mess and focus on what really matters - your quest of product market fit.

### 3. Advice for good engineering 

**a) Constantly learn** - In 2008, Douglas Crockford wrote "Javascript - The Good Parts", which is a valuable resource. However, as languages and frameworks grow they continue to add several new bad parts. The onus is on you to keep separating the good parts from the bad ones and only use the good parts in you business software. 

To do so, keep learning from good/authentic resources. Focus on finding out how things actually work and use those principles.

Use side projects to experiment with new technologies to identify and validate rising stars, but only use proven ones in software of business significance.


**b) Do not do speculative coding** - Do not abstract because you may need it in at other time. Abstract functionality only when 2nd usage is encountered. You will avoid writing extra code and your abstractions will be better mapping of real world. 
Do not create columns in database because you may need them some day. Spoiler alert - you won't!


**c) Refactor your code** - After any sprint, ensure that you have mapped real world to code. Additionally, ensure you are not projecting relations of your code or data on to the world - that is you are not trying to fit market to your product. 

Clean the code:
- for good mapping of world/problem-space to the code.
- to ensure you are using only good parts of languages and frameworks.
- so that it is easy read, because you'll need to remove a lot of it in for the next iteration.

Overall simplicity is your friend when you want to move fast. Therefore, slow down and simplify passionately before starting the next sprint!


**d) Readable code is better than Optimal code** - In programming world it is a common advice that readable code is better than optimal code. Though for an early stage startup this relationship is super amplified. Something like:

```
Readable/maintainable code >>>> Optimal code
```

There is no point in optimizing a code that will not last more than one week. Therefore, optimization efforts are waste of precious resources - time and energy.

Readable and loosely coupled code provides you best leverage on your scarce resources. You can iterate fast and stay focused on what really matters - product market fit!