What Should Your Development Environment and Tools Do for You?

Currently it seems like most tooling makes it more work to ensure standards are upheld and increases overhead on developers. This shouldn’t be the case, your development path should make it easier and faster to do what is best. Giving a time and effort reward to someone who meets the standards not making the person put in more time and effort just to make sure things go through properly.

The main reason for this is that doing good work should not have to feel like a chore but doing the wrong thing should incur some cost so that it is discouraged.

Things that should be encouraged:

  • commit to the main branch frequently ( daily or more)
  • small commits that can be reviewed quickly and easily
  • allow more testing without having to wait an ever increasing amount of time for tests to run
  • create modular software libraries that can be shared across the code base
  • allow for faster developer feedback loops locally and for production changes
  • deploy changes to production frequently ( daily or more)
  • have visibility into production deployments and have be able to mitigate problems quickly and easily.
  • Consistent environment for everyone to make pair programming and helping others easier.

Now we can go over what current setups usually look like and how some small changes can make everything much smoother and easier for everyone involved.

Starting with the commit frequency and size as they go hand in hand. Currently most github commits require 3 steps to get merged in the push or the pr a review and then a final merge into the main branch. While this seems fine the last step shouldn’t really require a developer to circle back and finish this. It should be done automatically once a pr has been review and can be merged because it passes all it prerequisites ( tests, builds, linting and more). That way time doesn’t have to be wasted when everything is ready go and a simple action that doesn’t add anymore value is blocking. The size of the prs fits with this because if you want people to review your prs very quickly you need to make it easy for them to review. This means smaller cleaner prs that can be reviewed and merged faster are rewarded. While large prs take more time to be reviewed and might not get merged in as quickly possibly creating merge conflicts in that time. So this creates a reward for small clean prs as they can be merged in much faster than large prs. By removing the need for a developer to circle back around and finish off a merge manually we have moved the limiting factor to the quality of the pr that is submitted for review initially. Hopefully encouraging the developer to create a better pr to begin with so that it can be reviewed quickly and merged in.

Decreasing the build and test time is key so that there doesn’t have to be so many trade offs between development speed and the number of tests you can run to feel confident about your changes. This is usually the case when you are running tests on your local development machine that only has a certain amount of parallelism. In contract if you adopt bazel with remote execution you can could run all of your tests in parallel if they don’t rely on each other. Meaning even with an ever increasing number of tests you still only have to wait as long as the single longest test. This gives developers the freedom to write as many tests as they need to feel comfortable and doesn’t require trade offs that could undermine that confidence. To go along with the remote execution of tests bazel also automatically allows tests to be cached and only reruns them when code that is relevant to the test has changed. This means that for small changes most of your tests won’t have to be rerun saving compute cost and time. All of these things work together allow developers to write as many tests as necessary to feel confident in their code without having to worry about making trade offs to keep test times low for their ci pipelines. This rewards developers who write more comprehensive tests that allow them to make changes faster in the future without slowing down their ci pipelines.

Right now most builds and tests are done from a clean slate to ensure their correctness because the different caching systems could never really be trusted. But if you could trust your build systems cache how would this change how you write code? One of the big rewards you would start to see is that creating more modular and focused libraries would be rewarded. That is because those libraries would not have to be rebuilt if nothing was changed in them. Allowing the library to be cached and shared with every other developer saving everyone time. This helps to align everyone and give them noticeable rewards for making their code more modular and reusable for everyone. It also encourages code sharing while at the same time making it easier to maintain a single library for a set of tasks vs multiple similar but different libraries all spread out in the same project.

Combining all of this together creates a much faster feedback loop for local development and for production data as well. Locally you can make large changes and still have them build and test in a short period of time with bazel remote execution and cache. This is the same for your ci pipeline as well so two of the possible longest dead periods in a feedback loop have been decreased. It also allows you to increase the number of relevant tests that are run for a change in a short period of time giving everyone more confidence without slowing others down. Then your tooling also encourages you to commit to the main branch regularly by reducing the time and effort it takes to get a commit merged. This increases the speed of your feedback loop in production, making it reasonable to commit multiple times to main in a single day and getting feedback on those changes. This setup also encourages modular libraries that can be shared as the library can be cached and not rebuilt at every stage. Encouraging developers to write libraries that save themselves and other time as well. This also encourages code sharing so team members don’t have to keep rewriting common things or feel the overhead of using a shared library is to high at build and test time.

Deploying to production regularly is key for developers to get feedback as quickly as possible so that they can understand if they are moving in the correct direction or need to change. Improving the speed and efficiency you can get commits merged to master is great but if you don’t get end user feedback on those changes for days or weeks it does’t really change anything. But if you push a change and can get feedback on it from end users that same day or short time after then you can really react to it. This can remove the guess work around what users will like or how to reduce latency or anything else you want to measure or test. Closing this feedback loop allows everyone to make more directed progress with less effort. Your users want the thing you made for them to be better and if you can show them you are constantly making changes in the right direction they will want to use it even more because it’s constantly improving for them. So take that idea and change the frequency that you can release those changes. Maybe you release once a month or once a week, what if you could take that down to daily or multiple times a days. They would be smaller changes but they could get user feedback right away and help guide your developers. Then in meetings about what to work on you can use real user feedback not just your guess or intuition about what users want to focus your tasks. This can make a big difference over a period of time compared to slower feedback loops.

Importantly to go with this deployment speed you need to have visibility and confidence in your deployment system. Along with your ability to handle and recover from errors or problems automatically or with one-click. This type of safety net is key for your developers to feel safe having their changes go into production so regularly. Even with all the testing, validation and reviews bugs will still get through so your system should be able to handle this gracefully minimising the impact on your end users. Giving your teams breathing room to fix the problem without users being impacted while working on a fix is key. This means a fix can be worked on under normal conditions and because commits are now smaller and more manageable it also much easier to track down what the cause of the problem was. This way you don’t have any alarms going off as users can’t do anything while your boss hovers over your shoulder waiting for you to fix the problem. You can just rollback the last change to the previous deployment which ideally would have been from earlier that same day. You also don’t have to worry about undoing days or weeks of work by simply needing to rollback once. Then when you have a fix go back to rolling things out as usual again and go back to the work you were doing earlier in the day. This helps reduce the apprehension or fear around deployments and makes them more common things that happen multiple times a day and have regular and understood processes in place to deal with any problems quickly and efficiently without disrupting everyone’s day.

As it becomes more difficult to collaborate in person with a remote team you want to make it easier for team members to collaborate and problem solve together. The two main times when people collaborate are when you pair program together, coding or designing something together and when you have to debug something either in an ide or in your build pipeline to see what happened.

This can be done with web based IDEs so that users can see what the other person is doing and can recreate the same environment or simply share the same environment and work together. This makes pair programming or working together much easier as each person doesn’t have to try and figure out what dependencies or installed software is different between their machines and who needs to upgrade or downgrade what. This is not a task either party wants to do but if you could simple and quickly spin up a new environment that is identical it would remove all that friction. This makes not only helping others on your team easier but also helping other teams or contributing to any project easier.

Another piece that is often overlooked as well is the ability to understand what flags, features and versions your build system is using without having to go through a bunch of log lines trying to memorise and compare everything. There is a better way to do this that makes it much easier to find these differences between your local builds and ci builds or between the builds from different developers. A central site where all relevant build information is sent and displayed making it easy to find relevant information to solve these problems. This site can be seen as a simple source of truth for builds. Just like your source control is a source of truth for your code this site can be seen as the source of truth for builds. Making it much easier to debug things in a distributed team and also a team where everyone might not have access to debug or change a ci build. This is especially true if you are executing your build across hundreds of machines with remote execution, you can’t be expected to look through the logs from each machine and figure it all out.

A remote and distributed team needs tools and systems that help them become more efficient not less efficient. Teams already develop software that takes advantage of the scale and ease of use that comes with cloud tools why not bring the same ease of use to your developers and your development to make it faster, safer, easier, more collaborative and a better work experience. That’s exactly what we want to do at CosmoDev make your development experience better by providing all the tools you need in one place.

For more information email us at info@cosmodev.tech