Successful product delivery heavily depends on the software engineering team. However, even teams composed of brilliant engineers can be trapped by an obsession with functional value and get the developed product to the point where delivering new features becomes extremely hard and expensive.
In this article, we dive deep into the concept of a product’s business value and explore its two main components: service value and functional value. We provide detailed product service value analysis explain why focusing solely on a product’s functionality leads to failure and show how you can effectively balance your attention between your product service value and functional value.
Finally, we discuss why outsourcing product development is the key to successful and stable delivery and outline four key characteristics that may help you distinguish a good outsourcing team.
When talking about a software product, we often use the term value to refer to the product’s worth and the benefits the end user might get from the product. Originally used in various management theories, the concept of value has a long history before becoming a meaningful part of the software development process.
Nowadays, the term value is mostly associated with business success and the importance of a specific product. However, the business value of software products is composed of two major parts:
- Functional value — Determines the product’s value based on the functional capabilities that matter most for end users and stakeholders.
- Non-functional (service) value — Determines the possibility and the cost of implementing a product’s functional value within the current context.
Functional value is usually measured based on several criteria:
Each of these characteristics allows us to see whether a product is useful for end users.
At the same time, calculating the overall value of a product by simply summarizing its functional characteristics doesn’t much fit the idea of lean manufacturing or the initial meaning of the term value. When doing so, you may miss some meaningful aspects of value, such as:
- Additional components of the value chain — The infrastructure and technologies used and the people working on the product
- Product development flexibility — Being able to quickly respond to changes and ensure sustainable development and technical excellence as valued by the Agile Manifesto
- Project communication — Establishing communication and a culture of trust within the project team
These aspects form a product’s service value.
It’s noteworthy that software creators always pay significant attention to functional value, as both developers and users care a lot about a product’s functionality. Service value, in turn, is sometimes sacrificed for the sake of functionality. Yet the value that the project team must enhance to ensure effective product development and growth is always composed of both these components. Let’s explore why service value of a product is just as important as its functional value.
Related services: Distributed Enterprise Networking Solutions
Historically, software doesn’t get smaller over time. The volume of code constantly increases alongside any new functionality, and so does a product’s resistance to change. Even when already implemented code requires no significant improvements, it still requires maintenance. The more functionality you implement, the more legacy code you need to support and, therefore, the higher the maintenance cost. This is why it’s important to distribute a team’s efforts proportionally between the project’s functional and service value.
Let’s assume we have a project where the relative cost of maintaining existing functionality doesn’t grow with time. Still, the more iterations we release, the more legacy code we need to support. So assuming that maintaining the functionality developed during an iteration costs 10% of the total cost of that iteration and assuming that this maintenance cost must be paid during each subsequent iteration, the more iterations you need to support, the more you'll spend on maintenance:
Unfortunately, the older your code gets, the more resources you’ll have to spend on its maintenance. If we assume that for each next version of the product the maintenance cost will increase by 10% from the cost of maintaining the previous version, the overall picture changes significantly:
We should also keep in mind that project budgets aren’t limitless. Let’s assume we can’t exceed the initial budget by more than 20%. In this case, the situation with distributing project funds will soon get complicated:
As you can see, with each iteration, the possibility of implementing the expected volume of functional value decreases. Now let’s compare the cumulative volume of implemented functional value to the expected numbers:
As you can see, by the third iteration, the team won’t be able to stay within budget even though the volume of required changes remains the same. At the tenth iteration, the team will still be working on functionality that was supposed to be implemented in the sixth version. And the seventh version may never even reach the market.
And this is when only 10% of the overall functionality cost goes to maintenance.
Meanwhile, service value is often exchanged for functional value, especially at the early stages of product development. When the decrease in development speed finally becomes noticeable, the most common solution is to hire additional staff and, therefore, increase the budget.
Let’s see how this would work if we, say, doubled the budget at the sixth iteration:
As you can see, soon enough, the situation will repeat itself — the development team will spend more and more time maintaining already released code and not writing new code.
This mostly happens because developers and project managers on internal teams tend to choose new product functionality over non-functional investments. If you ask the average project manager which part of the product is more important — the service value or the functional value — they’ll most likely choose the latter. Furthermore, many software developers share the same belief, as the product’s functionality represents the end result of their work.
However, non-functional improvements such as improvements to the software architecture will pay off eventually, just not right away. These improvements aren’t about adding new functionality but rather about making it simpler to add new functionality. And since the first few versions of the product usually need to be released fast, service tasks often get postponed until “better times.” Vital activities like code reviews and testing often get excluded from the development routine, resulting in malpractices such as code duplication.
The key question is whether increasing the service value is worth the effort. A fictitious project can help us find the answer.
Let’s assume that in order to completely eliminate the growth of maintenance costs, we need to invest equal money into functional and service components. At the same time, around 10% of the overall investment in each iteration will go to some sort of bugfixes. In that case, the general picture will look like this:
The maximum budget overrun of 20% is now a buffer that allows us to spend 55% of each iteration’s funds on functionality. So by releasing ten versions, we can implement 550% of the product functionality.
Now if you go back to Figure 3, you’ll see that while having the same budget, we can implement 592% of the functionality in ten versions. However, in that example, releasing the tenth version is already impossible, as all of this version’s funds will go to maintenance.
Therefore, even though only one half of the budget is spent directly on product functionality, we can still benefit from decreasing our maintenance costs.
For a product team, the thing that matters most is usually the product they have today and not the one they’ll be working on in six months or a year. Therefore, prioritizing service value gets challenging. The temptation to focus solely on functionality is simply too high: there’s always a demo to improve, urgent bugs to fix, or project development plans that put all non-functional tasks aside.
What can you do in situations like this? There are two major options:
- Adjust the team’s perception and switch their focus to introducing new functionality in a stable and predictable way. This will most likely require reevaluating your current development culture and enhancing it with new practices as well as introducing new tools and approaches and educating your team members on them.
- Hire an outside development team that’s already using all the practices, technologies, and tools and possesses the skills and experience needed for implementing your project. Being less tempted to focus solely on functionality, an outsourcing team is more likely than an in-house team to keep their heads cool and distribute their efforts proportionally between both components of product value.
While you’re always free to choose the first option, keep in mind that it may take a lot of time and effort to make experienced professionals do known things in an unfamiliar way. Working with the right outsourcing team seems to be the more beneficial option here, so let’s take a closer look at it in the next section.
So how to increase a product’s value? Leading software engineering outsourcing companies understand the importance of non-functional value. Cooperating with one of these companies can help you improve the overall product business value with minimal efforts.
A competent outsourcing company is more than just an intermediary between the customer and contractor. It’s a provider of quality, full-cycle engineering services that has its own software development culture and knows how to build development processes in a productive way.
Such a company has three main goals:
- Establish a stable and predictable flow of new and useful functionality
- Make sure the developed product meets the client’s quality requirements
- Stay within the time frames and budget determined by the client
Focusing on a product’s service value allows the outsourcing team to keep a stable development speed for a long time. Due to their rich experience and unified software development culture, outsourcing teams can quickly establish new internal processes and adjust them to the client’s needs.
A qualified outsourcing team also always keeps track of system maintenance and continuously improves it. In this way, they can ensure productivity and predictability of the development process.
Such a team constantly improves their profitability for the client so that with time, they can provide better quality and results within the same budget.
All these qualities allow a good software development outsourcing team to successfully reduce the cost of implementing changes by:
- increasing the efficiency of development for useful product functionality
- decreasing costly yet inefficient project expenses such as for reworking code, fixing bugs, project downtime, and any additional activities that aren’t aimed at developing useful functionality.
To achieve all these goals, outsourcing teams need to implement various practices:
|To ensure stable development|
| || |
|To ensure stable development|
| || |
|To ensure development process flexibility|
| || |
|To ensure team efficiency|
| || |
|To ensure continuous improvement|
| || |
By applying these practices, a software development team can significantly improve the non-functional value of the product, which will inevitably lead to increasing its functional value. In the next section, we describe an example from our company’s practice that illustrates how working with an outsourcing team can affect a product’s value.
Integrating the above-mentioned practices can be trickier than you may think. In this section, we illustrate how you can deal with different challenges based on a short case study of one of our recent projects.
Our client provided us with a challenging task and a strict deadline to complete it by. We needed to build a series of native in-proc Component Object Model server dynamic-link libraries (DLLs) as pluggable extensions for a huge legacy product. Each DLL would be a separate data processing solution involving networking, data serialization/deserialization, databases, file system storage, cryptography, compression, and other things needed to maintain the required operations.
Since we were starting this product from scratch, we designed and estimated it with all the best practices we already knew and applied. We had solid experience implementing similar products and knew key pain points to keep in mind when estimating the project.
For a team of two developers and one quality assurance (QA) engineer, the initial estimate was two and a half months for each extension. But as often happens, our client’s planned release schedule didn’t match our proposed timeline — the client wanted the product to be implemented in one month.
While we had a certain vision of the product development process, the new timeline made it impossible to implement. So we had to exclude or minimize such activities as continuous integration, code reviews, and multi-layered testing activities.
Therefore, we targeted the functional value of the developed product, discarding all planned processes and estimating the simplest solution we could come up with. However, it appeared to take a month and a half and still didn’t fit the required schedule.
As we couldn’t descope any significant parts of the functionality, we came up with a strategy that would speed up development. Along with the strategy, we also finalized our tactical goals for the project:
The team agreed on using test-driven development (TDD) as the main development methodology. TDD encourages implementing small yet complete functional parts and simplifies change implementation, which was exactly what we needed.
We also agreed on maintaining and running automated acceptance tests daily to provide safety against regressions.
Rapid delivery of functionality was made possible by applying continuous integration/continuous delivery (CI/CD) pipelines running all automated tests.
Complex architectures are one more thing that slows down development. We knew we would work on similar extensions later, so it would be great to have some flexibility planned in the design from the start. But in the current situation, we couldn’t afford this. We also knew that by building the simplest possible solution, we would be able to easily change it when needed.
To spend less time on documentation, we started development with only a few documents describing:
- interaction interfaces of the extension
- third-party libraries used and their versions
- the development process strategy mentioned above.
But even with all these optimizations, there still was too much additional work not targeting the implementation of new value: integrations, merging, code reviews, debugging, bugfixes. We eliminated the unavoidable and significant cost of integrating a new repository by adapting pair programming. With this practice:
- there was no integration cost because there was only one pair of developers
- code refactoring was done as soon as the technical debt was spotted
- debugging was reduced with automated tests
- two pairs of eyes controlled each new line of code and design decision.
Fixing bugs was one of those activities that took the most time, so we agreed on the following rules:
- What is found by a machine during autotests and prevents us from passing acceptance tests gets fixed immediately.
- What is found by humans (QAs, developers, PMs, or the client) is revisited and planned for the upcoming implementation.
To spot possible issues in the development process, we also included in our project schedule one hour per week for discussing any problems we encountered.
All these measures helped us to shorten the final estimate by one week, so we only had a week above the original timeline set by the customer. Since there were no other ways to speed up development without violating product quality, we prepared a phased plan and proposed it to the customer.
The first phase was dedicated to building a mocked solution. This solution was supposed to have all the required interfaces and acceptance tests but provide mocked data. It wasn’t supposed to have any of the core processing logic. The mocked solution made it possible to start the integration process on the client’s side earlier, and it could be replaced with the actual product as soon as it was ready.
The second phase focused on implementing the core business logic in place of the mocked solution. Since we had acceptance tests, we could build new features daily, simply replacing the mocked implementation with the real one.
Finally, the third phase was dedicated to including all the non-critical features into the final product.
The new plan fit into six weeks, exceeding the estimate set for us by the client by one week. Still, since the new plan met the client’s real timeline, they accepted it.
We started the development process in accordance with our strategy and the new estimates. It’s noteworthy that we spent the first two days without writing any functional code. Instead, we set up the infrastructure for automated testing, integration pipelines, and other service activities.
Once we had released the first extension, we started working on the second. The tricky thing was that this time we had to fit into an even shorter timeline for implementing a larger scope of work.
We started the second extension by simply copy–pasting the already implemented extension project within the same solution and repository, pursuing the KISS principle and discarding things that weren’t going to be required in the immediate future. During implementation, we started to extract common parts of code and improve them or adapt them to the new product.
These decisions increased the maintenance cost. However, since there also was an integration period planned by the client, we knew we would have enough time to split these two extension projects and resolve this issue.
So while adding a bit more service value with every new iteration, we continued working on this family of extensions. Our chosen practices allowed us to get to the point where almost all our efforts were targeted at developing new functionality:
When we inspected the efforts put into improving the functional and service values as well as the maintenance costs per iteration (see Figure 8 below), we saw several interesting things.
We had thirteen week-long iterations for two extensions. The first iteration is the initial start of the product development process. The sixth and thirteenth iterations mark the beginnings of subsequent projects.
You can see that for the first iterations of new products, the percentage of time dedicated to creating service value was much greater than for subsequent iterations. This was required to maintain sustainable development during upcoming iterations.
Another thing to note is the amount of maintenance for this project. The maintenance effort doesn’t grow over time, while new functional value is created day after day. Starting from the fourth iteration, the amount of functional value delivered is pretty stable and varies between 8 to 12 percent of all efforts throughout the rest of the project.
You can also see that in subsequent iterations of the same product (1–6, 7–11), the service value decreases with time while the functional value keeps growing.
And the anomaly of the twelfth iteration is caused by moving the copy–pasted product into a separate repository during integration on the client’s side.
As a result, this project is lightweight and stable. While it counts more than 20 products, the overall codebase is only around 400,000 lines of code. We run 31,724 unit tests and more than 3,000 acceptance tests every day. Product issues are detected by issue monitoring and detection systems before any customer even reports them. And yet about 80% of the developers’ efforts are focused solely on product functionality.
What made such success possible was our team’s paying attention to the service value and building effective collaboration with the client’s internal team.
Now that you know how this service value-focused approach works in practice, let’s move to outlining the key characteristics of a good outsourcing company.
What distinguishes a professional external software engineering team is that they do exactly what you want while focusing on the things you need to successfully deliver your product. However, it’s crucial to understand that simply hiring an outsourcing team (let alone separate engineers) won’t give you this advantage right away.
There are several aspects you need to pay special attention to when looking for a software engineering outsourcing team:
Corporate culture. Benefiting from cooperating with an outsourcing company is only possible if that company has and maintains a proper corporate culture. So when choosing a team to outsource your project development to, pay attention to the company itself and the values it puts in place.
A company’s corporate culture should be applied to all internal processes, from recruiting and HR management to customer satisfaction reviews. It also should include continuous learning and experience exchange, thus targeting engineering excellence at the company level.
Service value. Effective external teams know how important functional value is for a product. But they also pay close attention to the service component of business value of a product. They understand that excluding service value from the development process may eventually halt the production of the functional value altogether.
Communication and a clear project vision. Maintaining a clear understanding of the product’s values and plans is crucial for external teams. It allows them to adjust to the constantly changing project scope and reflect the business flow and data model in the software they produce.
An internal product representative. This person has to be available during the whole development process. Many decent outsourcing companies provide a business analyst, project manager, or product specialist as part of their software engineering services. If this role is required to make the development process valuable, this person should be in place.
Full scope of development services. There are a lot of freelance developers and companies providing remote developers to get work done. Still, the choice of companies providing a full scope of software development services — from business analysis to project management — is quite limited.
Also, it’s important to hire a well-tuned team. If you’re hiring separate engineers, all the additional effort required to make them work as a team will become another piece of work that you’ll need to do on your side. And in this case, the advantages you could get by hiring an external team will most likely vanish.
Learn more about
Apriorit dedicated engineering teams
A product’s service value plays a key part in ensuring stable, predictable, and efficient product development and delivery of new features. To ensure that a product is delivered to market at a constant or even an increasing pace, the development team needs to continuously work on the maintainability — or the service value — of the solution.
Cultivating a service value-centered culture in an in-house development team takes a lot of time and effort. Outsourcing your project to the right external team, on the other hand, can help you get the best result while staying within your deadlines and budget.
At Apriorit, we have nearly two decades of experience bringing to life our clients’ ambitious ideas. We continuously improve our internal culture and implement new practices to make sure the products we develop meet our clients’ requirements and are delivered on time. Take the first step toward predictable and stable product development by getting in touch with our team in the online chat window or by filling out the form below.