Welcome to part two of “The Most Difficult Project I’ve Ever Worked On”.
We’ve come a long way and had a lot of great learnings during the process of developing this app. In Part One of this series, I’ve highlighted the key learnings when dealing with 2 or more teams when it comes to communication. For Part 2, I’m going to share the learnings on the more technical side.
Choosing the Right Project Management Tool
As I’ve mentioned in the previous post, it is extremely important to have a single source of truth, especially when using several different communication tools. We had to decide which project management software was the most suitable for our needs. Of course, everyone had their own preferences, but at the end of the day, it should depend on the team setup, and on the type of communication you want to encourage.
In this case, JIRA was eventually chosen. Plenty of people were initially against this decision, but despite this, it turned out to be a great choice in the end. JIRA is one of the most complete project management software products on the market. For our purposes, it worked like a charm. We obviously used the software to track our own development stories, but it also allowed us to track other issues we encountered and deliverables from other teams.
When we were close to finishing the project, we would track external issues daily in order to expose where the priorities were and implement proper fixing. The rigidity sometimes became a pain and caused a sense of frustration, but on the other hand, JIRA worked great for the project environment. For the most part, we were aware of every epic status and task completion.
Choosing the Proper Framework
Another critical decision we made was choosing React Native as a base framework for the mobile app. I had a decent amount of experience with it, and it felt it was the right call since we were only dealing with Android. We negotiated a base OS version in order to support fewer legacy devices and make the app more maintainable. The great thing about React Native is that its community has evolved quite a bit since late 2016. There is a fair amount of documentation and lots of libraries for the common stuff like navigation, HTTP requests, encoding, state management, etc. to name a few of the main ones used in the project. The integration and delivery platform Buddybuild made client deliverables effortless. I’m sad they’re shutting down support for Android, but I’ll elaborate more on that later.
Below are my main takeaways from the technical standpoint:
Automate whatever you can automate
I have to be honest. We had a really hard time integrating with the tools developed by the two other teams. I found many faults in their tools and created tickets for them accordingly. As time went on and the tickets remained unresolved, I found myself creating multiple tickets for bugs associated with the previous issues. Since I didn’t want to keep introducing more problems on top of the existing ones, I chose to focus on solving the basics first.
As this cycle continued, it got to the point where I even questioned whether or not I contributed to the lack of productivity. In a situation where three separate teams were working at the same time, I had to at least be absolutely certain the issues weren’t coming from my end. To solve this, I spent a lot of time testing, and developed automated scripts and routines that would keep me confident and minimize human error. Later on, when an issue came up that I knew wasn’t my fault directly, I had concrete proof that I did my proper testing before bringing up a new issue. Tools like Postman and Assertible are great for this.
Have a good release strategy and expect the unexpected
Changes are inevitable in product development. As a software engineer, you need to be aware of that. I tend to be optimistic, but over the years, I’ve come to learn that surprises are always just around the corner.
Having a good release strategy allowed us to be very flexible. We followed Gitflow for this, which translated into having two stable branches in this case. One branch for production stable code, and the other for ready for production stable code. Every feature had its own experimental branch.
Only by the time of release did we create release branches (which happened twice). However, none of these two were used intensively, but as I mentioned before, they did come to be useful. Just as a reference, we created around 20 tags for different milestones and deliverables.
Rely on a consistent “continuous delivery“ system
This section is sort of an extension of the previous point. We chose Buddybuild and we were not wrong to. In one instance, we had 3 environments to test against, which meant 3 different Android builds. We started researching and we came up with automated scripts for generating the builds.
What’s the major benefit on this? Well, especially before releasing, all teams had access to the app at different development stages. Every new component(s) was clearly tracked on JIRA so there was no confusion about which version of the app had it (again circling to one source of truth).
Setting up this “continuous delivery” flow would create a clean environment for making the builds. Since this was being built by an external service, we didn’t need complex or hard to figure out systems and integrations in order to have a version of the app.
Take advantage of your team and make code reviews happen
I have seen many projects go under the hood as they approach release just because there was no time for quality and code review. It makes me wonder…who would be responsible for this? Is it on the project manager? Was the chosen technology not suitable? Was the estimation too rough?
I don’t have an exact answer to that question but I do know that code reviews make software more consistent and gives some level of quality control. I believe in keeping an open mind on what the best practices are, how a refactoring can improve readability or even just understanding other code writing approaches. Fortunately, I was working with a great partner on my team who held similar beliefs to me. Lastly, for someone who’s not a technical person, code reviews would keep track of software decisions and divide an application into small pieces of code for a better overall understanding.
Ask for quiet times, or sneak them in, quietly…
Again, as a developer you need to fight for making that delightful refactor, create a suite of unit tests or have that “state of the art” library integrated into the project. We fool ourselves into thinking the quiet times will come naturally, but the truth is…they won’t. So how do we find them?
It’s very important to track down the momentum of a project. When the team involved is experienced, development sprints usually have some “down time”. These are perfect slots to put in some extra refinements and deal with technical debt that has accumulated.
Technical debt: “implied cost of additional rework caused by choosing an easy solution now instead of using a better approach that would take longer.”
If you’ve done your part well and correctly, you could allocate the downtime after product releases to fix bugs and perform maintenance. This is also a great time for adding that refactor or conduct extra testing.
Finally, it’s a good idea to directly ask for these time resources as it’s a good source of discussion and a great way to put the matter out there. We got some fair moments to improve our code. In this specific case, we found this great library for making the whole Redux pattern more clear and enjoyable to write. It took us 3 months to figure out the momentum in order to include it in the sprint as part of an improvement.
The issues I’ve mentioned above are more technical than in the previous post, but they expose real struggles and problems you’re likely to encounter while working with people who don’t share your own work culture.
I’m excited to share the third and last part of this series related to project management learning. Stay tuned!