When you have a large task to accomplish, how do you approach it? Do you start with data modeling? Do you start with diagramming communication between related services? How do you decide what to do first so the rest of it can be built on top of a foundation?
One of the core skills of any software engineer worth their keep is being able to break down a deliverable to varying levels of granularity, and containing the blast radius of their decisions. This is a necessary ingredient in continuous integration and continuous deployment.
This is a skill rarely taught to engineers. Instead it's one you're expected to pick up either by luck, or by ad hoc mentoring, as part of your journey to becoming a senior(+) engineer. This creates many problems because improperly broken down work is impossible to work in parallel, or often serially. It's also difficult to deploy incrementally without surfacing bugs or bringing down production, especially without reaching for tools like feature flagging. (A very valuable tool, but not the first and only tool in your belt.)
Breaking down work into bite-size chunks has a few implications. From a lean perspective, if you can break everything down into pieces that can be delivered once or twice per day, it right sizes everything, getting your cycle time to a consistent 0.5-1 days per deliverable. You can better focus on doing no harm as you ship code continuously to the mainline branch and to production. It does this by forcing you to have small batches that are easy to review, and by thinking about your work to find the right seams ahead of time.
Once you can break work down, you can easily work in parallel with your team, even with code that is very tightly coupled.
So how do you do this?
If you're working in an MVC architecture, like Rails or Django, you've already got your work cut out for you. You have database backed schemas, contexts/service objects that encapsulate business logic, background jobs, controllers, and views. If not you may have to think a little bit more, but you likely have similar patterns you could find seams along.
Until you actually invoke the code above by some action in your application you don't need to do anything to prevent it from negatively impacting your application, so you've done no harm. You can add tables and columns to your database structure without bringing down production. (Assuming you follow a few simple rules based on your database engine.) You can also add new functions to models, and even add endpoints to controllers without causing problems. As long as the user isn't using the new endpoint or triggering a new function to be called, your changes won't cause any problems. In nearly every case, it's safe to add an code as long as it’s unexercised, but will be exercised in a near-future iteration.
Once you get to a point where you're either exposing a controller or view, or kicking off an action with this new code based on an existing code path you should then reach for a feature flag to prevent it from impacting until the desired code is feature complete.
Each of these pieces can be created and modified independently given a well defined initial data structure, and a few of the key interfaces each layer will adhere to. Spend a bit of time up front defining that schema, writing it down, and the rest will easily fall into place. Start breaking down your work today, and reap the rewards of being able to work with a team.
If you'd like to learn more about how to better break down a piece of work, and how this feeds into a greater system of software development, sign up to receive my emails.