Software Ages!
Although software is intangible, it ages. Even if you never touch it, people will less and less want to work with it over time. It is necessary to invest in a software product to keep it up to date technologically and from a requirements point of view. As a consequence, software company regularly start refactoring projects to modernize their applications. I regularly get engaged in software architecture workshops that should pave the way for such projects. Over the years, these projects have taught me a lessen:
Without a design-to-cost approach, redesign projects lead to inconsistent "Frankenstein" software containing numerous different solutions for similar problems.
Beware of Inconsistent Monsters!
Why? Because considering costs as an important non-functional requirement, projects are often stopped before they can be completed. Typical reasons are budget cuts, lack of resources, stakeholders demanding new features instead of refactorings, etc. If you stop a refactoring project half-way, you have a massively inconsistent software (e.g. using plain SQL for data access vs. using Entity Framework). Do that multiple times and Frankenstein is born. Your software will be hard to maintain, extend and support.
Here are some examples I have seen in real-world customer projects in the last 12 months:
- Three entirely different data access technologies in a single monolithic application (ADO.NET, custom OR-mapper, Entity Framework)
- Three different UI-technologies in a rather small business application (WinForms, WPF, embedded web browser)
- Four different programming languages in the UI-layer of a single program (Delphi, C++, C#, VB)
Design-to-Cost Approach
What is Design-to-Cost?
The Design-to-Cost approach describes a systematic approach to controlling the costs of product development and manufacturing. The basic idea is that costs are designed "into the product", even from the earliest concept decisions on and are difficult to remove later. Thus costs are seen as an equally important parameter besides feature scope and schedule [...] (Source: Wikipedia). For cloud-based SaaS software, we have to consider two different types of costs:
- Development costs
- Operational costs for running the SaaS solution in the cloud
Consequences on Software Design
As software architects and developers, we try to build beautiful designs that scale, are modular, are easy to maintain, etc. However, we must not ignore the consequences of our design decisions in terms of costs. This is especially true for refactoring projects as fundamental changes means changing large existing code-bases. Do you have the time, resources and money to get through this until the end?
Ensuring affordable quality and making design converge on cost rather than allowing cost to converge on design is the essence of design to cost (Source: Michaels, Wood: Design to Cost).
Short-sighted Costs Savings Instead of Good Software Architecture?!
Sacrificing good software design for short-term cost savings? Isn't that short-sighted? I agree that many existing applications would benefit in terms of long-term maintenance costs from fundamental redesigns. However, don't you achieve the exact opposite if you redesign parts of the software and have to stop early?
I believe that sometimes you have to accept software design trade-offs and prefer affordable small changes over unrealistic large refactoring projects.
Five Tips to Protect Against Frankenstein
Here are five tips that can help protecting against "Frankenstein" software:
1. Create Realistic Estimations Before Starting a Refactoring Project
This one is hard. Refactoring existing, non-trivial software products is like renovating an old building. Unpleasant surprises will be found around every corner. Nevertheless, you need a realistic estimation of project duration and necessary resources. The following things could help:
- Do time-boxed prototypes with limited scope.
- Focus on the hard problems first to fail fast if you fail. Don't invest half of the project budget on refactoring the easy things just to find out that your ideas are not appropriate when it comes to the complex parts of your product.
- Ask others for help and different opinions.
- Don't just work out one software architecture. Create multiple alternatives and put them up for discussion.
- Sharpen your estimation skills.
If you want to learn more about the last point, our article How Good Are Your Estimation Skills? might interst you. It also contains a quiz you can use to assess your estimation skills.
2. Ask Yourself: Do We Have Enough Resources?
If have been sitting in numerous software architecture design meetings where I had to be fun killer. People proposed smart and beautiful refactoring ideas. When I asked "who has the time to implement all this", there was no satisfying answer. Product planners didn't want to slow down delivery of new features, management didn't agree to increased dev headcount, and no team members were sitting around bored waiting for something to do.
Make sure to have your management team's commitment for your refactoring project. Either it will cost additional money or it will slow down other things. As usual in IT: There is no free lunch!
A time tracking history with high-quality data is incredibly useful in this area. With products like our time cockpit, you can analyze what your team is spending time for. You can systematically look for time killers and solve them to free resources for refactoring projects.
3. Be Open and Honest in Your Communication
Most refactoring projects are a long-term effort. Be sure to track progress and effort and communicate it openly and honestly. This is an important trust-building activity. You will need the trust of stakeholders because some crises are inevitable in larger refactoring projects.
Do you know our article Project Reporting in Agile Projects? It describes how we report progress and effort in customer projects.
4. Create Business Cases with Quantifiable Goals
When I work with customers, development teams often complain that they do not get sufficient budget for code refactorings. Stakeholders always value new features over structural code and design enhancements. In my experience, the reason why this complaint is so common is that we developers often argument poorly. We promise that after refactoring, code will be much easier to maintain. How much easier? What will change specifically? Can we prove our claim based on quantifyable case studies of refactoring projects in the past?
As developers and software architects, we have to learn to write business cases for refactoring projects.
We have to collect data before and after our refactoring projects. Presenting quantified consequences of our refactorings will make stakeholders more confident that future refactoring proposals from our team make sense.
5. Continuously Deliver Value
Don't forget to continuously deliver value. Refactoring projects must not entirely stop development of new features. Refactoring projects have to demonstrate their value although they have not been completed. Here are some examples:
- Maybe there is a support case that could be handled smoothly because the recent software design change?
- Look for a new feature for which you can comprehensibly describe how much time and/or resources could have been saved because of recent refactorings.
- Present numbers showing that you could deliver new features although parts of your team restructured old code.
comments powered by