A day in the life of a software developer is mostly a system of routines: you do your stand-up meetings, you portion out your work, you set your goals, and (hopefully) you accomplish them with a little extra time to spare. Some days, you demonstrate your work to the client, some days you set up a planning meeting to codify your sprint objectives, and some days you create a technical design for a more complicated feature.
Whatever your day ends up looking like, it likely falls into a pattern of an established cadence set by your employer’s standards, or through trial and error experience with the project—except when it doesn’t.
In my case, my place of employment, Olio Apps, mostly functions as a consultancy, taking on a variety of projects from different fields and disciplines—some greenfield projects and some that are already in production. For additional context, in my 14 months at Olio, I’ve personally worked on about six or seven different code bases for various clients.
Most recently, my boss, Aron, assigned me and my co-worker, Frank, to a prototype project where the client already had a deadline established. The delivery date they requested was about three weeks out from when we accepted the contract and the goal was to finish a prototype scheduling wizard that would be in a high-fidelity, demo-ready state.
As I mentioned before, software developers generally adapt to a “normal” cadence for their work flows; I have one as well, but this project required me to rearrange my “normal.” Aron coined the term “hard mode” to describe this paradigm for dealing with crunch, but what really makes “hard mode” different from what we deem normal and how did we successfully end up with a functional prototype that met all of the client’s requirements?
“Normal Mode” Versus “Hard Mode”
Let’s start with operational definitions of what “normal mode” and “hard mode” are. For me, “normal mode” looks like this: my team and I set sprint goals about once a week, tackling a few small features or one large feature, with the goal of a small but stable release. The project I’ve worked on that is most representative of “normal” for me is the project that has comprised the majority of my time at Olio Apps thus far. The codebase was already in production when the project started, and it used our standard React/TypeScript/Redux/Redux Saga stack.
The work was done on a per-feature basis, where the client would send a list of changes and bugs. This list was then broken up into individual Jira tickets and assigned to myself or my project partner. Though there was a deadline, we were rarely aware of it because there was no real crunch. Everything got done, we performed routine regression testing, and we would ship a build to the client every week.
This particular cadence had its moments of stress, especially when untangling unforeseen regressions, but overall, it had a lax and sustainable pace. Similarly, the majority of other projects I’ve worked on also had weekly checkpoints, where we had work scoped out at the beginning of the week, and we would release, demo, or at least check in on Friday.
In contrast, “hard mode” had a totally different rhythm. I’d experienced crunch before through hackathons and agile swarms, but usually only for an eight-hour block, as opposed to a two week project. Our pace was defined like this: Frank and I would set our goals in the morning, and we would do internal demos to our manager every afternoon.
On top of the time crunch, there were technologies in our stack that needed to be reconciled with the stack of the client, such as learning how to adapt our Sitka framework to work with ImmutableJS and using BEM SCSS instead of styled-components. There was also a sizable amount of legacy code whose patterns we wanted to emulate, to keep the app consistent and easy to continue building upon in the future. You can check out my blog post about how to handle legacy code here.
So that begs the question: how did we do it? How did we go from a set of mockups and a set of user stories to a full scheduling wizard in roughly 14 days with only two people working full-time on it? Let me count the ways.
One of the strategies we adopted for tackling “hard mode” was making certain we scoped blocks of work appropriately. In the case of creating the scheduling wizard, it felt natural to make each step of the wizard a discrete day’s work. Some days bled into each other when it came to fixing bugs from a previous step of the wizard, but overall, this scope and pace kept things organized and made daily goals clear.
Another thing that helped the workflow was having Frank and me stay highly specialized in terms of what we worked on. While I have confidence in my ability to handle Redux and business logic, my strength is in handling CSS/SCSS and translating the mockups into a high-fidelity user interface at a rapid pace. In contrast, Frank has more experience doing Redux and business logic and less experience doing design and CSS-oriented work. Dividing the work to match our strong suits made development faster and more efficient, and it prevented us from stepping on each other’s toes and creating merge conflicts while working on the same branch.
High Level of Communication
For this project, Frank and I forewent the standard practice of using feature branches, making pull requests and merging work after review in order to reduce time spent not building the wizard. As stated before, we worked almost entirely on the same branch. When done improperly, working this closely git-wise can cause merge conflicts, and work can be lost while resolving those conflicts. In order to prevent this from happening, my partner and I were in close communication. We both had a rough understanding of what the other person was working on, and we would ping the other person via Slack to commit their work and pull from our remote branch when substantial changes were made. An unforeseen advantage of working this way was that we were able to test each other’s work regularly on our two different machines to verify that everything functioned and compiled as expected.
Rigorous End-of-Day Demo
Another factor that made this project so successful was our project manager’s acute attention to detail. During every demo, which happened around 3:00 p.m., we would test obscure use cases in the flow of the wizard and put the user interface under intense scrutiny, directly beside the mockups. This allowed us to have a very concrete and approachable list of functionality and UI fixes, and having the demo a few hours before the true ending of the day gave us time to fix them. On a good day, this allowed us to tie off the step of the wizard we were working on and start fresh on the next step the day after.
The most crucial part of powering through “hard mode” was tracking and managing time. I did this by using Shoutbase, Olio’s time tracking application. Seeing where time sinks occurred while working on the scheduling wizard allowed me to get better at creating an appropriate timebox for when I should get a second opinion on how I was approaching a problem. This was arguably the most important part in terms of setting a cadence for the project as a whole, and it’s an important skill to have, whether you’re developing in “hard mode” or not.
When to Develop in “Hard Mode”
So when is “hard mode” the best way to get the job done over a normal, relaxed cadence?
For us, there were a number of factors that led us to adopt this workflow and cadence. The first factor was the tight deadline, which is pretty self-explanatory: a closer deadline means less time to get work done. The second factor was that the app was still a prototype. The combination of these two factors meant that features like unit testing weren’t necessary at this phase of the web app’s development. The third factor was that the features that were a part of our client’s requirements had few technical unknowns. Once we had BEM and ImmutableJS sorted out, and we had acquainted ourselves with the codebase, we were able to continue in a “business as usual” way, just faster and with a narrower technical focus. There was no need for any new algorithms or patterns or libraries in order to accomplish our goals, which was good, since researching new technologies to implement them into legacy code can make a hefty dent in your time budget.
Why It’s Not Sustainable
As I mentioned in the previous section, there are advantages to changing the paradigm to “hard mode,” but with the advantages come disadvantages that make this style of development unsustainable for any developer, regardless of experience.
For one thing, the fast pace of development left limited time to add in unit tests. Unit tests are an important part of production code for ensuring the maintainability of a codebase and the scalability of a codebase: you know what the input of a function is, and what the output should be, and Jest (or your testing framework of choice) will catch any bugs before you release a build as you grow the app. For more tips on transitioning from prototype to production code, check out my co-worker Stormi’s blog post about production versus prototype code.
Crunch is normal and expected in most development cycles—that’s just the nature of any work that has a deadline. I personally really enjoyed having daily milestones and the ability to finish work and receive feedback quickly, but despite the preparation we did and the adjustments we made to our workflow to speed up our development, it was still hard. It’s simply not sustainable to be working at that pace for a prolonged amount of time.
Not only can it be stressful when you start to run up against the clock, but that stress can also cause creative blockage when it comes to problem solving. We managed to mitigate a lot of the stress and mental fatigue by getting out of the office at 5:00 p.m., no excuses.
What I gained from this experience is learning how important it is to have a strong division between work hours and personal time. I haven’t had the experience of working longer than a regular eight-hour day to compensate for a crunch like this, but I can say that timeboxing the daily sprints and going home at the same time was paramount to keeping myself energized and focused throughout the busy workdays.
To sum it all up, there’s no right or wrong cadence or way to get your work done, as long as it gets done, but it was an enlightening experience to switch things up and try working at a “crunchier” pace. That said, even “hard mode” development doesn’t have to be a bad experience, provided that you scope well, communicate well, and work efficiently. These may seem like obvious tools for completing a successful project, but if you aren't already doing foundationally important work beyond your actual coding, putting additional constraints on a project will make that really apparent.
I’ve laid out a few of the tips that my team has tried while handling crunch, but I’m curious if there’s anything I missed. Feel free to @ me on Twitter (@ARC_Tangents).
What did we miss?
Please let us know by tweeting to @olioapps
Developer at Olio Apps
Thanks for reading!