Article summary
Every project falls somewhere on a spectrum between extremes of short-term, get-it-done-ism and eternal, future-proofed longevity. Unfortunately, while you may have a ballpark sense for where a project fits on this spectrum at the outset, each user story needs its own consideration. Working out the right tradeoffs for each of these stories is the project.
To help our team navigate these tradeoffs as we turn our focus to new capabilities, I’ve developed this rule of thumb:
Pick a coherent strategy which aligns with business goals that can be well-executed within reasonable time and budget.
Sounds simple enough, but implementing this rule takes three crucial steps:
- Know what you’re aiming for–understand how the feature fits into the bigger project and how it relates to business goals.
- Identify options–generate a set of internally consistent, coherent strategies for pursuing that feature or capability. Formulate each as a one-or-two sentence soundbite.
- Choose a strategy–one that aligns with business goals and that you can capitalize sufficiently and execute well.
Each of these components has its own nuance.
1. Know What You’re Aiming For
To identify the right strategy for a feature, we must first develop a clear idea of how its capabilities relate to the overall project goals, situation, and perceived business value. I like to ask a few questions to get to the bottom of this.
Core, supporting, or generic?
First, I ask how central this feature area is to the overall project, the target user, and the business. I find borrowing the following terms from domain-driven design to be helpful. Is this element:
- Core: A key differentiating aspect for the project, directly tied to the fundamental reasons for doing the project
- Supporting: Needed and specialized to our use case, but not a critical component in the overall big picture
- Generic: A basic capability that could make do with an off-the-shelf component
Categorizing a feature or user story upfront provides immediate clarity for whether you should invest the time to work through all the details or make do with something that meets minimal requirements. It seems trivial to spend so much time and attention on the project’s raison d’être, but if you don’t, it’s easy to lose sight of its boundaries and waste time on supplementary things that just aren’t that important. Gaining a clear accounting of what’s really important and what just needs to be there helps keep you on task.
Confidence in the solution?
What level of confidence do we have in the solution? Are we confident in the necessity of this specific approach and the value its implementation will generate? Should we seek to explore options in a lean way or invest in what we believe to be a long-term solution?
Easy to delete or replace?
Is this capability something that will be built on later, entrenching it and making it difficult to change? If so, additional investment may be warranted to insulate the rest of the system from its particulars, even if the capability itself is generic.
2. Identify Simple, Coherent Strategies
Next, identify a small number of clear, coherent strategies for proceeding, and describe each in a sentence or two. Take the big picture into account. Don’t just look at software features. You should also consider any lurking future liabilities like documentation, automation, or migration costs. Each option should make sense as a coherent and reasonable way to approach the problem.
Here are a few examples of strategies:
- “Carefully design and implement this user interface component. We’ll be using it all over, and it’s crucial to effectively meeting our users’ goals.”
- “Find an off-the-shelf solution. We will subordinate design and feature details to its capabilities.”
- “Pursue the cheapest, fastest possible strategy that enables us to X for now, even if it means extra manual work. We’ll improve the solution if it becomes a pain point later.”
- “This story is the first in a series of similar capabilities; let’s invest additional time to consider them together and build a model that can support the upcoming work.”
You can use a few different heuristics to come up with options:
- Maximize or satisfice–What’s “best” and what’s “good enough”?
- Research, experiment, or commit–Do we need to learn more, are we ready to solve this problem for real, or should we do more research or run some experiments?
- Build or buy?
- Solve for meeting a constraint or relax the constraints, e.g. what we can afford vs. what it would cost to “do it right.”
- Look for 80/20 options–Can we get most of the value at a fraction of the cost by removing some requirements?
You can start by generating a few options with the right people in the room. As you discuss approaches, unpack the implications. For example, does one option imply a major new piece of infrastructure? What would it take to integrate that properly into development tools, continuous integration, and development, staging, and production environments? Unwinding the implications of a strategy a few steps can help clarify the true costs involved.
Unpacking the implications can also help you identify strategies that don’t really make sense once you think it through. Do you want to explore a generic solution? Then take care not to over-specify the solution to the point that no existing solution can meet your needs. Does the ideal technical or design solution exceed available time or budget? Note that option will be incomplete without a budget or timeline change. The possible strategies usually shift around a bit, changing in character as you think through and reconcile the implications.
Ultimately, the options usually entail some combination of design, technical, and project considerations. You need to understand the implications for both the software and the overall project to properly evaluate a strategy. Don’t just look at what it takes to implement the feature, but also what it takes to properly test, deploy, document, and isolate the implementation decisions of that feature, and how it relates to budget, timeline, and opportunity costs. The goal here is to avoid options that provide bad combinations of cost, completeness, future-proofing, etc.
3. Choose a Strategy You Can Execute Well
Once you’ve formulated a few plausible strategies, test them against the importance of the feature and the level of investment that the product owner (and team) will make. Prefer strategies that the project can properly capitalize, versus a partial implementation of a more ambitious strategy.
For example, let’s say a user needs an interface component to accomplish a goal. Is the interaction core enough and hard enough to change that you’re willing to:
- Invest in a detailed discussion of detailed capabilities?
- Have a designer to mock up every required state?
- Iterate on that design?
- Ask a developer to potentially spend days implementing it from scratch?
If that level of attention and investment seems like too much, decide so upfront. Instead, pursue a strategy that avoids that work, such as using an off-the-shelf component. However, if the UX is core to your application, it may be wise to make that investment for key interactions.
Let’s look at another example where a feature is the first instance of a pattern that will manifest many times throughout the application.
- Can we plausibly design a solution that will scale well across the set of known instances, even though it may need adjustment?
- Could doing so lower the overall cost of the project? Then perhaps we should plan to take appropriate steps upfront.However, if we lack certainty about the solution, it may be better to start simple and gradually refactor over time.
Your strategy should make sense in the overall arc of the project. If something’s important, invest in it accordingly. If something’s uncertain, pursue a strategy of little experiments to learn more about the problem and solution spaces. If something’s more of a supporting capability, choose an approach that avoids excessive planning, design, and implementation effort. Pick the right strategy, and invest accordingly.
Designing Your Approach
Ultimately, this is about designing the activities of your team. When a team works together to produce a piece of software, that’s an artifact. The real product of a team is made up of the discovery, decision-making, and activities of the people involved. While the software itself needs to be well-designed and implemented, the process of design and implementation should also be thought-through and tailored to the purpose and situation of the project, one step at a time.
I find this step to be a lightweight, high-value activity when beginning to plan a feature. It’s easy to wade into the details planning something that’s just not that important. It’s also easy to go full steam ahead implementing a single feature, when the project may be better served by building some new infrastructure along the way to support three similar features that will follow. Stepping back, formulating your approach, and executing well will produce better outcomes for everyone.