How to Deliver On Time
Adventures in the Software Development Life Cycle
If you've been in the software industry a while, you've probably heard "the launch was delayed" more than a few times. It may even seem that projected release dates on new products or large new features are rarely met. The causes of delays are many and multi-faceted. From planning, to company culture, this article provides an overview of the many factors in creating and successfully meeting a product launch date and release schedule.
Develop a Product Roadmap
All successful business endeavors begin by identifying an untapped market and envisioning a product or service that meets the needs of that market. A product roadmap is a high-level visualization of the product goals, plan, and steps required to execute your product strategy. The roadmap serves the following functions:
Outlines and defines phases of the product strategy
Serves as a guideline for setting quarterly goals and milestones for the product
Is a reference for stakeholder review and alignment on product goals
Facilitates communication to all company departments, employees, and external stakeholders, such as customers and investors
Identify Business Goals
Product design and feature requirements can be verified by:
Stakeholder/Expert consultation - experience in the market provides insight into market needs
Competitive analysis
Market surveys
Prototyping and user testing
Prioritize Goals
Define the most important features required to make a successful product. It is often more important to get to market as soon as possible, instead of taking the time to build every feature imagined before launching. Which leads to the next section…
Define a Minimum Viable Product
The Minimum Viable Product (MVP) is a minimum feature set required to launch.
Eric Ries defined the term as, “the Minimum Viable Product is that version of a new product which allows a team to collect the maximum amount of validated learning about customers with the least effort.” Defining an MVP gets the product to market as fast as possible and allows the gathering of critical feedback from early adopters which will inform and verify the priority of further feature development.
Stakeholders often fall into the trap of wanting to only launch once the product is perfect, with every desired feature already implemented. This is often a critical mistake as the product will get bogged down in perfectionism and scope creep, causing missed deadlines and launch dates. This risks allowing competitors the opportunity to capture the market, with perhaps an inferior product, but one that gains wider adoption due to being first to market.
The following criteria should be used to decide which features to include in the MVP:
Level of effort to build the feature, including design and testing
Importance of the feature - critical, important, nice to have. Example - a video sharing platform:
Critical: file upload, including upload, conversion, adding thumbnail, title, and description
Important: metatags for videos, which would allow categorization and recommendations.
Nice-to-have: Comment system. This will encourage user engagement, but level of effort is high and not a core requirement of sharing and playing videos.
Get Stakeholder Sign-off
All stakeholders should be aligned on the product roadmap. It seems obvious, but in practice often one or more stakeholders may not have a full understanding of what is planned for the product launch, and successive releases, leading to disputes and scope creep during the development cycle. The roadmap is a living document that will often change based on feedback from users, and new market developments. Stakeholder review of the roadmap should occur whenever changes are considered.
Planning for Success
Whether launching an MVP or large new feature, a successful release is the result of a well laid plan. The stages of building software is referred to as the Software Development Life Cycle (SDLC).
Software Development Life Cycle
At a high level, the stages of an SDLC are typically defined as:
Analysis & Requirements Gathering
Project Planning
Design
Coding & Implementation
Testing
Deployment
Maintenance
Define the Process
To implement a solid plan it is important to define exactly what will be required at each stage of the SDLC. Following is a granular breakdown of a project plan that I have had success with:
Project Kickoff
Gather requirements
Review requirements and agree on the feature set to be built
Project Planning
Create high level work estimate and timeline
Create epics and user stories in project tracking tool
Design & Developer Setup*
UX design begins
Create UI style guide if needed
UI design begins
General project setup
Developer environment setup (VMs, git repos, IDE config, lint rules, etc.)
Backend setup (code frameworks, test tools, database setup, etc.)
Frontend setup (code framework, test tools)
Backend development can begin, but it is premature to start building frontend views
Build CI pipeline for dev and staging environments
Begin setting up instrumentation (Datadog, New Relic, Splunk, etc.)
Development underway
Stakeholder review of UX/UI prototypes
Frontend development begins
Backend development continues
Build CI pipeline for production environment
Instrument production environment
Review and sign-off for launch
QA testing
Load testing
Complete instrumentation
Stakeholder review
User Acceptance Testing (UAT)
Deploy release
Monitor production for issues
Maintenance cycle
Bug fixing and additional changes post-launch
* In stage 3 of this plan, I recommend holding off on frontend development beyond initial setup until the UX and UI has been fully signed off on and approved. It can be as much work to change already built views as it is to build them from scratch. If the frontend team starts building designs while the designs are still subject to review and change, it can significantly increase the work effort of the frontend team. Similarly, I recommend the UX develop wireframe prototypes for complex features, and have these prototypes approved before handing off to the UI team, as they too may be subject to extensive changes, causing the design team additional work.
Design and Prototyping
When reviewing an initial product design, it is very difficult to fully understand and visualize the user experience of the completed software. Everyone who reviews the product design will imagine a somewhat different end result. This often leads to unmet expectations and unplanned change requests towards the end of the development cycle, which can delay release.
Misunderstanding can be prevented by creating clickable prototypes that demonstrate the look and feel of the software. Tools like UXPin, InVision, Figma, etc. allow UX and UI designers to create functional prototypes of the different views of the user flows. These prototypes communicate exactly what the product team is proposing, serves to get understanding and feedback from stakeholders, and gives explicit instruction to the frontend dev team on what to build.
Designing System Architecture
When planning the system architecture, whether your team has a dedicated systems architect or not, I have found it beneficial to have brainstorming sessions with the entire development team. Even the most junior of the team can provide valuable feedback and questions. When starting a new project, some questions to ask are:
Are there any existing, similar successful systems that you can use as example and inspiration?
Does it make sense to use third party solutions, or managed services for some components of the system, instead of building in-house?
How will you handle data reporting and deletion requests for CCPA/GDPR compliance? It’s far easier to plan for handling PII deletion before building, than it is to add this feature after a system is built. Do not overlook PII that may be stored in system logs, as well as databases.
Microservices or Monolith? There are pros and cons to both. You can also do a hybrid approach, where a large part of the system is a monolithic codebase, with certain features supported by services.
Estimation
Break Down Features into Small Component Parts
Smaller units of work are easier to estimate accurately. Say we need to implement a file uploader tool. This should be broken down into its component parts, then each component can be estimated realistically. Following is an example breakdown of this project, allowing for a fairly accurate estimation:
General Project Setup
User experience (UX design)
Wireframes
Prototypes
User testing
Stakeholder review
User interface (UI design)
Graphic design
Stakeholder review
Git repository setup
Developer environment
Lint rules
Test tooling
VM config
IDE config
Instrumentation setup (Datadog, New Relic, Splunk, etc.)
Documentation
Internal documentation (primarily for dev team)
QA test plans
UAT test plans
External documentation, e.g. customer facing API docs
Backend
S3 bucket to store files
CDN to serve files (CloudFront or other)
Infrastructure setup scripts (e.g. Terraform scripts to build S3 bucket and related infrastructure)
Database to store pointer to file and file info
Define DB schema
DB cache for read requests (e.g. Redis)
Infrastructure setup scripts
Load testing
Service to handle file upload to S3 bucket
Code framework
Endpoint definitions and associated documentation
Infrastructure setup scripts
Unit tests
Integration tests
Functional tests
Load testing
Frontend
Hosting setup (e.g. a React Single Page App hosted on S3 with associated CDN)
Infrastructure setup scripts
Frontend framework setup
UI build - views defined by the UX and UI design, which may include:
Upload dialog and input form
Progress bar
Edit form
Project Completion
QA testing
Integration testing
Load testing
User Acceptance Testing
Documentation review
Estimate for the Unknown
Okay, so you’ve created a granular work estimate and timeline. Most likely this is based on an optimistic, best-case scenario, where no unknowns pop up and no additional changes are requested during development.
In practice there are always unknown challenges that crop up, and unavoidable feature or scope creep during the development cycle. I’ve found it advisable to add a large factor, as much as 1.5 times of the original estimate, to account for the unpredictable and unavoidable. In a best case scenario, if all goes perfectly smoothly, you get to deliver early. But an extra buffer for the unknown will allow you to just make your deadlines in most real-life scenarios, while avoiding excessive crunch time.
Create Development Timeline with Milestones
An agile development process typically consists of defining project features as epics, then adding the granular parts that make up a feature as user stories. These should be tracked in a project tracking tool like Jira.
Define major milestones on the development timeline, which will help verify that a project is on schedule. If a milestone is missed, I recommend the following course of action:
Post mortem to discover the cause or causes that led to missing the milestone date
Develop strategy to ensure it doesn’t happen again and, if possible, accelerate future product development to meet original launch date
Adjust timeline and launch date if necessary
Review your findings and recommendations with all stakeholders to understand the impact and strategy going forward
It’s critical to let all stakeholders know as soon as possible if the launch date is in danger of being missed. I have seen situations where an expensive marketing campaign was purchased for a product launch, but the launch date was going to have to be pushed back, and yet the marketing department was not made aware of this issue until it was too late to reschedule the campaign. Communication is key in order to avoid these types of disasters. It may mean that the project will need to be triaged, paring down the features available at launch, etc. The earlier you communicate, the better positioned you will be to have a successful launch.
Building a Team
Importance of a Product-first Mindset and Culture
Generally speaking, there are two mindsets when it comes to business endeavors. A project mindset, or a product mindset. The Project Management Institute defines “project” as “...a temporary effort to create value through a unique product, service or result. All projects have a beginning and an end.”
A “product” is defined as a good or service that is marketed or sold as a commodity. When it comes to software, a product mindset is highly beneficial, as software, especially when it comes to SAAS applications, is never complete. It will always need to undergo improvements and upgrades to stay competitive.
Product-first means:
Prioritizing the user experience
Focus on achieving business goals
Define Key Performance Indicators (KPIs) and metrics for measurement
Measure performance and acquire user feedback
Iterate based on these results
A common pitfall of a “project” based approach to development is the lack of team understanding on what the project goals are, or how to achieve them. A company leader, or customer, makes specific requests on a feature to build, or changes to be made, and the dev team follows that direction in lock-step. The fallacy of this approach is that the project stakeholder has specific goals they are trying to achieve, but their proposed solution may not be the best way to achieve those goals.
An empowered product manager and team will be allowed to ask what the goals are, then propose solutions that can fulfill those goals, which often may be different than the original request. And then, after each release, measure the results, and iterate upon this new found knowledge.
A solid product team consists of the following roles:
Product Manager - responsible for determining value and viability of solutions to meet business goals, and leading the Agile development process
UX designers - are responsible for providing easy-to-use interfaces, and assist in designing features needed to build the proposed solutions
UI designers - responsible for the look and feel of the product, and style-guide compliance
Developers - responsible for determining feasibility of solutions, as well as building the software
Product Management is a Full-time Job
Whether you are a lean startup or a fortune 500, product planning and management is a lot of work. Between building and maintaining the product roadmap, gathering feature requirements, running kanban, or leading sprint planning and sprint review meetings, creating and assigning tasks, and managing project tracking software (such as Jira), there is quite a bit of work involved. In my experience, all dev teams can benefit from a dedicated product manager. It is possible to split the product management duties amongst leadership of the dev team and company stakeholders, but this additional workload will take away from time allotted to employees’ primary roles.
Cultivating a Culture of Feedback within the Dev Team
I’ve encountered two different types of developers: a developer who will follow instructions strictly as they are given and deliver exactly what was defined in the specification, and a developer who will begin work on a specification, and perhaps identify an issue where the instructions don’t make sense, or where the user would be confused by the feature as described.
The latter, product minded developer, is highly valuable as their upfront feedback will often prevent many wasted hours of work and redesigns after a feature is built. Encourage developers to think like a user when building a feature. When reviewing user stories in sprint planning ask if the story makes sense as defined, and if they see any issue during development, to bring it to the team’s attention so it can be addressed earlier rather than later.
Shielding the Dev Team from Distraction
It’s important developers stay on task to meet their goals per sprint. A common problem that often occurs is when stakeholders, or other people outside the product team, ask for work directly from developers, e.g. a member of the sales team asks a developer to edit some copy on the company marketing site. This might be a quick change, but such requests can add up significantly. If a developer is working on a complex issue when this request comes in, the simple act of context switching may set the developer back hours in their work, before they can “get in the zone” again.
I have found success with assigning a different developer each sprint to be the only person that handles bug fixes, tech support issues, and change requests that need to be addressed quickly. This allows the rest of the team to focus on the sprint work at hand without distractions.
Scope Creep and Managing Stakeholder Expectations
Adding features and scope will push back milestones and require timelines to be adjusted. Invariably stakeholders will ask for additional features or changes during a development cycle. I don’t encourage a culture of saying “no” to these requests. Often they can be insightful and important. However, it is critical that all stakeholders involved understand the impact of these changes to the development timeline. Milestones and other delivery dates should be adjusted accordingly and all relevant stakeholders should sign off on the schedule adjustments before going forward with the additional work.
Continuous Integration
Continuous Integration (CI) is the practice of merging feature branches to your main branch and deploying new releases to production often (Continuous Delivery or Continuous Deployment), as often as multiple times per day. It requires a solid foundation to do successfully, but when that foundation is achieved, a team that practices CI will be able to deliver high quality software faster than an old school approach to software development. Let’s take a look at what comprises a solid CI process.
Environments
As code progresses through the SDLC, it passes through different environments, typically, Development, Staging, and Production. Depending on the size of the organization or other factors, there can be multiple development and staging environments.
Development
This is a developer sandbox, where code in progress can be deployed and tested by the dev team. Things may be broken here, however, care should be given by members of the dev team not to leave things broken for too long, rolling back any breaking changes as soon as possible. With a shared development environment, communication is critical. Let members of the dev team know when and what you are deploying, so that if any issues appear, they will know who to contact to help resolve. A dedicated Slack channel is a good way for the dev team to communicate regarding deploying to the development environment.
Staging
This is where “ready-for-release” code is deployed for testing and review. Care should be taken by the dev team not to deploy breaking changes to the staging environment. For example, if a release is deployed to staging that breaks unrelated functionality on a feature the QA team is currently testing, the QA team will be completely blocked until that release has been rolled back. The dev team should communicate with all other teams that use staging when staging releases are being deployed, so that a rollback can be requested if needed.
Staging should be used for QA, stakeholder review, and UAT. I prefer to have separate staging environments for QA and for review. I have found it’s better to have stakeholders only review releases after they have passed QA - that way stakeholders’ time isn’t wasted reporting bugs that QA would be finding.
Staging should be made as close to production as possible. This will reveal environment specific issues that can arise. For example, a development environment might run entirely on a single server, whereas production may have load balanced server clusters, separate database and database cache instances, etc. Certain things that work in the development environment may be broken in production due only to the differences in environments. By having a staging environment as close in infrastructure to production as possible, these issues can be revealed prior to going live on prod.
Production
Releases get deployed to production after passing QA, stakeholder review, UAT, and automated testing. It is vital to have thorough instrumentation on your production environment to monitor for any issues with every release. Thorough instrumentation will allow you to identify issues in new releases and correct those issues before your customers notice.
The process to rollback a deployment should be made as easy as possible, and something that any senior member of the dev team can perform. Unforeseen issues can occur on production, sometimes days after a new release. Having an easy process to rollback a problematic release, that multiple members of the team can perform, allows you to easily return production to normal as quickly as possible.
Automated Deployment
Tools like Jenkins, CircleCI, Gitlab, etc. are used to deploy to the different environments. Whichever CI/CD tool you choose, it should be configured so that deploying a release to any environment, and rolling back a release, is as simple as a few button clicks.
Automated Testing
Unit Tests
Unit tests should be performed automatically. Set up a git pre-commit hook to run your lint checks and unit tests automatically before a commit. If your test suite becomes so large that it takes an unacceptable amount of time to run before committing, then set up a post-commit hook to run these tests on push, with an alert configured to let the developer know if the tests fail.
Integration Tests
Integration tests will assure that code changes will not break seemingly unrelated functionality. They should be run automatically when deploying to staging and production environments. I don’t recommend running integration tests automatically on dev, where integration tests can fail just because work is in progress.
Functional Tests
Functional tests, also known as End-To-End tests (E2E) verify that your application works from a user perspective. They feed user input into the application interface and test for an expected result. For instance, to test a login screen, input user name “johnsmith” and password, then click the login button. Application should display a welcome page containing the test “Welcome back John”.
Load testing
Production load can be extremely hard to replicate. Care should be given to match anticipated production traffic as much as possible when load testing new software. Of the many load testing tools available, my favorite is Locust.
Quality Assurance
Two old jokes come to mind:
A developer’s partner asks them to “go to the store and get a quart of milk, and if they have eggs, get a dozen.” The developer comes back with 12 quarts of milk.
A QA engineer walks into a bar... and orders a beer. Then orders 2 beers. Then orders 2147483648 beers. Then orders -1 beers. Then orders a dragon. Then orders a DROP TABLE.
QA testing is a skill unto itself. Developers should not QA their own code as they often don’t imagine all the different ways a skilled QA engineer will use to break the software. A test plan for every feature should be documented, and updated as feature changes occur. When changes occur that may potentially impact many different parts of the software, e.g. a new database migration or system upgrade, a full regression test of all the features should be done by the QA team before release.
Instrumentation
Without thorough instrumentation in place on the production environment, you are flying blind. If a release causes an increase in latency, or downtime, perhaps due to production traffic being different than what was tested on staging, you want to know as soon as possible, so you can correct the issue before most of your customers are impacted, or keep the impact minimal.
Instrumentation will also alert you to issues that might occur through spikes in traffic, bot attacks, or hacking attempts.
I recommend Datadog, especially if your infrastructure is deployed on AWS. Datadog’s integration with the many services AWS offers, including Lambda integration, is unmatched by New Relic and others.
Conclusion
When it comes to building software and getting it released on schedule, these are the main strategies I have found success with. By no means is this an exhaustive list, and I could go into much greater detail on all the topics above, but this post is already getting overlong. Stay tuned and subscribe for further posts on all of these topics and more!
