In this post I will discuss super charing your development team using practices that will increase productivity, lower risk, and collectively strengthen team members’ knowledge portfolios. After having worked professionally as a software engineer for a few years I have learned about a few practices that I feel I could not work effectively without. Over the course of my career I have worked on teams that utilize the processes I will describe as well as teams that do not, so I have the unique opportunity of being able to compare these two different experiences. This comparison allows me to determine what I feel are important practices that every team should be utilizing to super charge their development process. In no way is this an exhaustive list, these are just a few of the practices that I find most valuable for a development team.
The single most valuable source of growth in my career has been provided to me by the peer reviews I have received from my teammates. In conjunction with that, reviewing other developers code is a great way to get exposed to different approaches to solving problems as well as different parts of the code base. Peer reviews are a great way to increase the fluidity of your teams knowledge portfolio. For example, a design pattern one developer uses in a pull request is exposed to multiple reviewers who in turn see the pattern and are given the opportunity to learn the design pattern in the review process. If it is a good pattern they will begin using it themselves in their pull requests which other reviewers will see. Given the example, I think you can see how design patterns can proliferate themselves through a development team with peer reviews.
I believe the main benefit of code reviews is to find issues prior to them being merged to your products baseline. In addition, to that it provides an opportunity to dissect the implementation of a feature or a bug fix. Is the implementation thread safe? Is this code going to run on the right thread? What happens if some value is null
? Is the implementation sufficiently generic enough to support the desired amount of reuse? These are just a few of the questions reviewers should be asking themselves when looking at a code review. The questions will obviously change based on what technologies you are working with. Lastly, we all make mistakes. Perhaps you forgot to negate a boolean in an if
statement or perhaps you used >
when you meant to use >=
. We are not perfect these types of mistakes are going to happen. Ideally, we can catch them ourselves prior to doing a code review but if not we know we can rely on our reviewers to help us weed out simple mistakes.
Peer reviews support a fluidity of knowledge between team members and allow for issues of varying degrees of severity to be caught and discussed prior to integrating into the products baseline. This leads to an increase in the teams knowledge as well as reduced risk when making changes. The team now owns the changes being made, not just the individual making the changes.
Prior to starting a task I may have an idea of how I am thinking I will implement the solution but I may be unsure of how exactly one piece of the solution will work. In this case I will seek out a teammate that knows the specific piece of the code base I need to touch and go over my solution with them. Most of the time, this teammate ends up mentoring me on the solution and guiding me in the correct direction. Either by telling me why my solution would not work or by assisting in clearing up any issues I have with my solution.
I have been thinking of these teammates as “task mentors” or tech leads for a specific task. Now the person doing the mentoring will change based on what task you are working on. The benefits of having a task mentor are high. From the start of a task, if you consult with another teammate with regards to the solution you are going to work towards and they sign off on it you will have technical buy in from that teammate who will be able to guide you during the implementation process. In addition to that, they will most likely become a reviewer on your code review since they understand the approach that was being taken better than anyone else but yourself. This means if you both agreed on a specific approach to solve a problem that this teammate will be your biggest advocate during the review process.
Instead of working in a vacuum, always seek out a mentor that can mentor you on your current task. This will reduce risk because multiple people will be on board with the approach you are going to take prior to even implementing the solution. In the same vein, if you don’t seek out a mentor on your task, you may end up taking an approach that the team does not agree with resulting in rework needing to be done for the specific task.
Not every team member will need a task mentor but I think developers that are new to a specific team or new to development entirely will benefit from this practice. I often find that I am mentoring one or two people at any given time while being mentored by one or more people at the same time. This results in team based mentorship where nearly everyone in the team is actively mentoring someone while being mentored themselves. The practice of the team as as a mentor is another practice that will increase the teams knowledge fluidity. The best way to learn is by teaching; if you have the opportunity to mentor someone on their solution, take it.
Imagine if you did a refactor of your application that touched every single source file. How confident would you be that you didn’t break anything if you had to manually test everything yourself? Personally, I would not feel very confident unless I had a suite of unit and integration tests that I could automatically run to ensure I did not break anything on accident. In conjunction with that, tests can act as a form of documentation that ensure your implementation is adhering to the interface’s contract correctly. Increasing confidence when making changes will subsequently reduce the amount of risk of those changes being made.
If you have a high percentage of test coverage and made the refactor that was previously mentioned and all of your tests pass, you can assume you didn’t break anything. If some tests fail, they should very quickly point you in the right direction of what exactly you need to fix to get the tests to pass. After all, how do you fix what you don’t know is broken? Automated testing will allow productivity to increase because you can now more confidently make your changes. Granted, there are some caveats, what if your tests are wrong? What about the 5% of your code base that doesn’t have test coverage? Put simply, just because your tests succeed does not mean your application works correctly. Further, it would be prudent to do some manual testing of your system as well. The benefit is that you don’t have to exclusively rely on manual testing and now you should be doing much less of it due to your suite of automated tests.
Continuous integration is something I would not consider working without for both my personal open source projects as well as anything work related. Continuous integration is the process of building your application from scratch on specific source control events such as a push or a pull request being opened. The benefits of this are that you will know your code works on a fresh install and it is not just working on your machine.
Imagine a scenario, you made a very simple change and thought you would not build locally because of how simple your changes are (please always build locally). When you push your code up, a test that you didn’t consider is now failing. Thankfully due to CI we caught this automatically without the need of any reviewers to find the issue for us. If we didn’t have CI set up it is possible this change could be merged to your baseline and cause it to be in a broken state for anyone who ends up using it. Utilizing CI with a good suite of automated tests will reduce the risk of your development team breaking your baseline to nearly zero.
All of these practices together start to form a symbiotic relationship. Seeking out a task mentor results in you having your first peer reviewer when you are done making your changes. Your peer reviewers can confidently accept your changes when they see that the build is passing that runs your suite of automated tests after freshly installing and building the software you made changes to. In closing, I really enjoy using these practices together because they reduce the amount of cognitive load I have to deal with at any given time. More importantly, these practices can significantly reduce the risk when changes are being made which will in turn lead to an increase in the team’s productivity. If you aren’t doing some of these practices I recommend incrementally trying them out. After a couple of weeks have your team reflect on how much more productive your team was or wasn’t. I would be interested in hearing about how you apply these changes to supercharge your development team.