There’s an important concept that good programmers have internalized, whether or not they realize it: they optimize their workflow.
The idea here is pretty straightforward: when we make a change, we want to know as soon as possible if our change is working as intended. It’s frustrating and time-consuming if we have to wait to see what happened. In other words, we want a tight feedback loop.
It’s pretty easy to see why quick feedback is useful. Something less obvious is that many tasks that we do involve feedback loops. Let’s look at some examples.
When we run a test suite, we’re looking for feedback as to whether or not our code is functioning correctly. How do we ensure that our test suite runs quickly?
The speed of each test depends on the type of test it is. Unit tests test isolated logic and are easy to configure and test. Additionally, we’re likely to have many more unit tests than any other types of tests. Unit tests need to be extremely fast since we want the entire test suite to finish quickly. At an average speed of .05s will take just under a minute to run. An average speed of .5s would still result in fast individual tests, but the entire suite would take over 8 minutes.
Integration and end-to-end tests are much more time consuming to run since they require more setup and interaction between different systems.
When we need to run all of our tests, we want to run unit tests first. They run the most quickly, so we have a much tighter cycle by looking for failing unit tests before looking for failing acceptance tests.
As we write new code, we want to see that it’s working. This is easy for small or isolated components, but it can be quite time-consuming if there is a lot of setup that we need to do in order to see our change.
For example, suppose we’re building a shopping cart and want our cart to paginate when there are 15 or more different items in the cart. To test this, we’d have to add 16 different items to the cart, then navigate to the cart and ensure things are working correctly.
The process of adding these 16 items is a tedious setup step. We can speed this up by creating a script that adds items to our cart on its own. Or, we can just pre-populate our cart with items (i.e. hardcode it). Because we don’t care how our code got into a testable state, it’s completely fine to add some (temporary) code that quickly forces our code into a testable state.
The standard code review process is to write some code, upload it to a review tool, and have someone take a look at it. We then have to wait for the review, which can take varying amounts of time based on our reviewer and the complexity of our change.
When it comes to our reviewer, we can always poke them if it seems like they aren’t looking at the review.
More importantly, however, is structuring our commit to make it easily digestible. Code reviews are harder to do when they deal with complex pieces of code and/or when the reviewer needs to juggle multiple things in their head to understand the code.
One of the most effective ways to do is to break commits down into digestible chunks. If your code has three main components, each one of them likely belongs in a separate commit. Breaking commits up limits their scope, which in turn makes it easier to follow what the commit is doing.