10 indicators you work in a healthy development environment


Motivation

Over the past 6+ years, I’ve been helping startup companies to start and scale as a freelancer. I’ve worked and met dozens of them in all stages: pre-seed, post-seed, unicorns, post-exit and also those which failed.

As someone who is consulting for architecture and development processes, I had to find a way to assess the state of the company and have a good grip on how well the development process and environment currently are. Here are some questions I ask the companies when doing so.

Disclaimer

Those indicators are according to my own experience and knowledge, of course, there can be others which are more suitable to your company, but I found it suits a lot of today’s startup companies.

Also: You can’t always have everything in place, nothing is perfect and you should prioritize your goals. You can be fine without having any of them in your company (at the price of something else) but even improving one or a few indicators can increase the quality of your development environment and culture and help the people in it.

The indicators

So how do you know if you work in a healthy development environment?

1. Your code has type checking 🔒

Whether it’s typescript or python type hints the important thing that every entity in the system has a definitive shape. You know for every interface, class or function its fields, their types and how they are connected.

Why?

  • it helps to find bugs before reaching deployment.
  • Auto-documents the code without adding a single comment.
  • creates a contract between the different functions/libraries in the system.

2. Services have a clear interface 📜

This means you use OpenAPI/Swagger to document all the endpoints in your REST API or use GraphQL which auto-documents itself. This way every service has clear external documentation which shows for every endpoint:

  1. what the endpoint receives (request body, query params, GraphQL arguments)
  2. what the endpoint returns (response interface)
  3. all the models involved in the process (User, Task, …)

Why?

  1. Every developer can work with a new service without looking at its code.
  2. It creates a contract between the different services in the system.
  3. Allows to share entities between services and find duplicates easily.

3. The code is verified with a linter (and a formatter) ✅

Before a new code is pushed to the remote branch (via git hook) and for every Pull Request before it’s merged into the main branch (via CI/CD) the code is run against a linting library (ESLint, Pylint, XO, ..) which catches bugs. You should also have a formatter (e.g prettier, xo) which creates a well-defined code format.
I also recommend sharing those linting and formatting configurations and re-using them inside and outside the team as much as possible.

Why?

  1. Catches many bugs before reaching production.
  2. Creates a unified coding structure between all developers and reduces friction (”Spaces vs tabs”).

4. Your local development environment is dockerized 🐋

When you work with Docker in your local development environment it’s both easy to onboard a new developer and prevent system-specific bugs and dependencies (if you hear “Oh no you don’t have Mac/PC” - you are not dockerized).
You can use docker-compose, local Kubernetes or similar solutions. it doesn’t matter as long as there is a sandboxed way to develop locally which is not related to the brand of the laptop developer is using.

Why?

  1. fast onboarding
  2. prevents system-specific bugs (or “polluted systems” bugs)
  3. easy to create a new environment for testing/production
  4. aligns the development environment among all developers.

5. You have tests 👌

You have unit, integration and e2e tests and run them on your CI/CD before the code is merged (and after). This is a huge topic on its own so I won’t elaborate much but ask yourself if you have tests that:

  1. make your code more robust?
  2. prevent regressions after a bug is found?
  3. verify the connection between different services in the system?

All those are done via tests which keep the code working and healthy over time.

6. There are isolated environments - dev/staging/production 🎯

You have a separation between your development, staging and production concerns. developers are developing code without worrying if the others will clash with them together because they are working on the same database/Redis etc’.

Also, You can test changes before deploying to production in an isolated, production-like environment (staging). You can also have test environments or per-branch ones (review apps) but having these basic 3 (dev/staging/production) is the base for any rapid development and deployment.

7. You can see the UI screens without using the system 👀

There is a place which defines all different UI screens in the system. This includes both the functionality of the screens (product-wise) and their look (design-wise).
It can be easily done with tools such as Notion, Confluence for product and Figma, Adobe XD and similar for design purposes.

Why?

  1. Creates a clear map of the system for onboarding
  2. Synchronizes production, development and design teams with a shared language on what the system looks like and functions.

8.You can tell others what you are doing with a single URL 🔗

This means that if someone asks “What are you doing right now?”, you can answer with a single URL to JIRA or Github Issues which shows the issues you are currently working on and planning to.

It encourages visibility among the team and company, improves the quality of verbal synchronization in meetings and encourages well-documented issues as well.

Why?

  1. It shows the issues are well-defined and assigned
  2. It reduces the need (or creates better) sync meetings

9.The communication in the company is (mostly) asynchronous ⌚

This means most of the communication in the company is done via sharing written data and letting others work on it and manage their own time.

Instead, if most of the communication in the company is done by meetings it creates a weak (or non-existent) knowledge base without a long-term memory for the company.

Having communication which is done (mostly) via sharing written ideas, issues, API designs etc’ creates an environment where the work is managed in a well-documented and led by strategic thinking, instead of having everything solved in an endless stream of tactics meetings (which unfortunately most of them are inefficient).

10.People help each other 💙

When someone gets stuck or asks a question you see people trying to aid. This separates talents from teams. It doesn’t mean when someone is stuck you should leave everything you are doing at once but if you see more people collaborating than competing with each other you are in a good place. This demonstrates a powerful company which strengthens itself and nurtures the people in it.

Summary

So how many indicators have you got? 1? 3? 10? Feel free to share the number in the comments or suggest more indicators you see for knowing when a company is a good place to be in. Any other comments are welcomed as well. Thank you for reading.