It's unfortunate how much software gets written and never actually ships and is used. This can't be wholly avoided because there are times when priorities do change. There are times when projects do need to get shelved due to more pressing needs. And if you're working at a company that values risk taking then projects will get canceled in an effort to fail fast.
As a software engineer not shipping due to changing priorities or having to shelve something in favor of a more pressing project were two of the most demoralizing things. Especially when I had worked on a project for N weeks or (even worse) N months.
Being able to ship software fast is one of the big benefits of Agile software development. Agile encourages you to ship at the end of every sprint. In the ideal world this would mean putting something in users hands that can be used at the end of every sprint. In reality, this is usually not the case. Often, you ship a series of smaller end-to-end pieces into production which at some point you'll tell your users about.
Here are some things to consider which will increase your likelihood of shipping software your users will use and decrease the chance that you'll build the wrong thing.
Understand your problem
While this sounds like a no-brainer, it's actually one of the things that I see get missed the most. Understanding your problem is not about requirements gathering. You gather requirements about a known problem space. One reason software projects can fail and never ship is because the problem was based on an idea that was never validated. You should always be able to tie your problem back to something a user has asked for.
Identify your milestones
Many software teams identify milestones from the beginning and move forward linearly in time till shipping. This is not a pit of success in that it's easier to miss a requirement than it is to not miss one. It's better to start with the last milestone and ask the question "what needs to happen right before this to achieve this milestone". Then you keeping going backwards in time asking that question and defining new milestones. Eventually you'll get to a requirements gathering milestone. You'll have achieved either defining all your milestones, or identifying ambiguity that would have likely derailed or delayed your project had you started defining milestones the other way around.
Know your risks and how they can be mitigated
Every project comes with risk. Being able to identify what risks are associated with your project will help you determine how your project will succeed in the event that one or more of your risks are realized. Some common risks to software projects include:
- Upstream/downstream software dependencies (often internal software being developed by another team) being late or failing to ship all together.
- Hardware/software purchases that need to be made.
- Making sure you're able to deploy to production.
- Not having user documentation.
- Not having a marketing plan for a new feature or product.
- Getting started with performance testing or security reviews late (or not realizing you need to do them at all).
Make sure you know what you need to measure
Milestones are great to help you know whether your project is on track. But they won't help you once your software is released. You need to identify the ways that you should measure your software to understand it's health. You should understand both your customer facing metrics (like the number of failures, the latency of requests, or etc) as well as your internal metrics (cost, performance, system health, etc). Talk to your product owners and your sales teams to understand what they need to measure about the software in order to aid them in their jobs.
Have an exit criteria for success
What is your definition of done? This doesn't mean you won't maintain or make changes. It just means that you've successfully delivered what you wanted to deliver. This should be a checklist of items that's been validated on both the business and technical sides of the house.