How to Avoid Unnecessary Technical Debt in Mobile App Development Projects
As published on Better Software Magazine
While many aspects of the mobile app market are maturing, sloppy practices can erode the foundation of mobile projects, create sustainment nightmares, and even cause projects to fail completely. In software development, the accumulation of errors in architecture, design, and poorly written code is referred to as technical debt.
Technical debt comes about when businesses prioritize short-term results over the longevity of a solution. A common adage is “You can have it better, cheaper, or faster—just pick two!” In software development, the two chosen are often cheaper and faster—to the detriment of better. Speed to market is prioritized because customer-facing features are always of more importance than cleaning up the backroom, and because development work is expensive, businesses are always trying to keep costs down. Inevitably, to make the deadline and stay on budget, something has to take a hit, and that usually ends up being the quality of the code.
Technical debt is supposed to be paid off incrementally every time new code is released, but it often continues to build because sub-standard code quality cannot be seen or felt by the application’s users, and therefore it becomes less important to the business. Imagine, for example, an electrical panel of disorganized wires held together by wadded foil and duct tape. As long as the lights turn on and the mess is hidden behind a door, what is the incentive to fix it? If that image bothers you, then you belong in the camp of people who think technical debt is a poor term that plays down the seriousness of the problem.
Without proper software design, technical debt grows at a greater rate than is optimal, resulting in increasingly higher costs to make subsequent changes to the software. The marginal cost of each software release, as well as the time it takes to complete a release, also increases, as shown in figure 1.
If not addressed, technical debt can make an application so expensive to maintain that it takes a toll on the ability to change anything. Eventually, it will lead to total paralysis, and in order to move forward, the application must be redesigned and rebuilt at a potentially obscene expense.
Technical debt is impossible to avoid completely, but when it comes to mobile, some organizations add to it unnecessarily. The worst case is when technical debt is planted as a seed by neglecting to lay a proper foundation before any code has been written. Although this is completely avoidable, many businesses have the perception that because mobile changes so fast, there is no need to spend time on planning.  When this happens, innocent errors can snowball into an avalanche.
For example, AIM Consulting was brought in by a new client to analyze why its enterprise-level iOS mobile app, under development for more than a year, had failed Apple submissions. We discovered that the code, which the company had developed in house, did not follow any discernable design patterns, was all original, and was therefore unreliable and difficult to debug. The resulting technical debt was so high that the client was actually served best in the long run by scrapping the project and starting over, ultimately costing the company millions of dollars.
This situation is more common than you might think. Too often, companies plunge into software development without properly setting up the project and end up creating something that is very costly to deploy and difficult to maintain. This is particularly true with mobile software apps because there’s a perception that the feature set is more restrictive and easier to build and deploy. Avoiding these mistakes and the technical debt associated with them becomes more manageable if, while laying the foundation for your mobile projects, you follow some basic best practices: adhering to standard design patterns, embracing open source code, and understanding the project APIs.
Adhering to Standard Design Patterns
Design patterns allow engineers to create reusable solutions. In many cases, engineers may be writing design patterns without knowing their technical definitions. Following patterns will create a solid project structure and a well-organized set of decoupled solutions. This way, when you’re in the middle of development and the project pivots to a place where you need to refactor, you know the role of each solution component. Having a solid core of design patterns and making sure your team follows those patterns helps manage technical debt.
The following are some examples of popular design patterns—not only for mobile, but for all software development:
MVC design pattern: Classes or objects in your application will take on one of three roles: model (represents your application data), view (user interface), and controller (manages the communication between the model and view by taking the data from the model and feeding it to the view for display). Conforming to this pattern helps ensure that your code is easier to understand. A common mistake is putting everything into the controller (jokingly known as the MassiveViewController in iOS). Properly breaking it up makes the code much easier to manage.
Observer design pattern: In this pattern, the observer handles and manages all communications to and between dependents. Think of a parent communicating to children either individually or all at once. Within iOS, this can be done very broadly with NSNotifications or more granularly with key value observing.
Façade design pattern: Commonly used in object-oriented programming, this design pattern provides a simplified interface to a larger, more complex body of code. The façade acts as a gatekeeper of sorts, communicating only with specific components of an application at specific times, enabling efficiency in the app. It is often used in very complex or difficult-to-understand systems.
Singleton design pattern: At its core, Singleton is a very simple design pattern. It creates one instance of a class or object and gives shared access throughout the app. For example, you can imagine an app having one user and set it up using the Singleton pattern. Once established, you can access the one instance of user throughout your app.
When considering the possibility of not using a standard design pattern, it’s easy to see how the technical debt in your development projects can accumulate quickly. When your project pivots, prompting discussions about refactoring, having these design patterns in place will help mitigate and organize the work that needs to be done.
Embracing Open Source Code
Another major way for organizations to avoid massive technical debt is to leverage reusable solutions from open source libraries. Open source communities have done a terrific job creating, contributing, and maintaining reusable frameworks. When developing solutions, it used to be a build versus buy discussion. Now there’s typically a public GitHub or other repository where someone has already figured out the problem you are trying to solve and provided a working solution.
The important factor is knowing which to use and which not to use. When reviewing open source code, look at how
often it’s been updated. If the code is fresh and has been used and updated by many contributors, it’s likely solid. However, if it was written two years ago and has never been updated, you are better off avoiding it. You can pull open source code into your apps, alter it in whatever ways you need, and then redeposit it to the open source collective. This makes it a better product for the community.
One point of consideration is that, while it’s typical for enterprises to take advantage of reusable solutions, some organizations
desire to write the code themselves for the purpose of owning the copyright to the solution or product. Creating code
from scratch carries the risks of adding complexity and bugs to the app and increasing the technical debt for the project. However, depending on the project, this might be the only way to go.
The only other consideration is attribution. Most apps normally include a license view in an About menu item. Contributors usually ask that you give them credit in this section for using their open source solutions. Often the attribution is referenced
by the MIT license, which is a free software license originating at the Massachusetts Institute of Technology (MIT). This license permits use of reusable code in a proprietary software application, provided all copies of the software reference the MIT license.
Understanding the Project APIs
In simplest terms, APIs allow programs to communicate with each other. In the discovery stage at the beginning of a project with a client, we need to understand what state the client’s APIs are in and how we can best leverage them. With mobile app projects, the APIs often don’t exist yet. It’s part of
our job to help the client define the best APIs for the intended use of their data. We ensure that our clients understand the importance of APIs—how they’re like the blood and nerves of an application—so we can avoid technical debt and delays later in the project due to lack of availability or usability.
The two most dominant API models for web services are Simple Object Application Protocol (SOAP) and Representational State Transfer (REST). The SOAP API was first proposed in the late 1990s and has been a popular protocol for moving structured XML data between applications. Though SOAP is still widely used today for exchanging data on the Internet, it’s considered “heavy” because it requires data to be sent back and forth from application to application.
The most common API in use for mobile apps today is REST, a term often used interchangeably with RESTful. The REST API was conceptualized about the same time as SOAP and has become popular in the past several years. REST is more lightweight than SOAP in that it breaks up data so only
the pieces that are needed are sent back and forth between applications. This lightweight data exchange is more responsive to user needs and requires less code—and for mobile applications, the fewer lines of code, the better.
REST has become synonymous with the term stateless. Stateless implies that no data is stored or cached when a request is made; stateful means some data is kept for use. While using an application where your next request is based on your previous request, it’s better to store the data and go stateful. However, with mobile apps, stateless is the way to go because it’s preferable to have less data stored locally on a mobile device. Fresh data is a prime reason people use mobile apps.
The important thing to note about APIs is you must make sure from the beginning that they are accessible and capable
of supporting features and the overall project. At the start of a project, current APIs don’t fully support project needs, and updates are done in parallel (or not at all). It’s important to be collaborative and flexible while working toward a solution.
Avoiding Unnecessary Technical Debt
Applications with high technical debt are costly to maintain, risky to the business, and make estimations impossible. This leads to the undesirable situation where your development resources will need to spend all their time fixing problems rather than developing new features for users. You will avoid unnecessary technical debt by establishing solid practices and patterns at the start of your mobile development projects. Ultimately, when you lay a proper foundation, your development resources will be used far more efficiently, and your technical debt will be minimized and mitigated.