Third-party libraries are not required in the project

Third-party libraries are not required in the project

Preface

During my eight years at Lyft, many product managers and engineers often wanted to add third-party libraries to our app. Sometimes it was necessary to integrate a specific library (such as PayPal), sometimes it was to avoid developing very complex features, and sometimes it was just to avoid reinventing the wheel.

While these are all valid concerns, the risks and associated costs of using third-party libraries are often overlooked or misunderstood. In some cases, the risk is worth it, but it’s important to be able to clearly define the risk before deciding to take the risk. In order to make risk assessment more transparent and consistent, we have developed a process to measure how risky it is for us to integrate it into our app.

risk

Most large organizations, including ours, have some form of code review as part of their development practices. For these teams, adding a third-party library is like adding a bunch of unreviewed code that was developed by people who are not part of the team. This breaks the code review principles that the team has always adhered to and delivers code of unknown quality. This poses a risk to the way the app runs, the long-term development, and for large teams, a risk to the overall business.

Runtime risks

Library code generally has the same level of access to system resources as the app, but they don't necessarily apply the best practices your team has put in place for managing those resources. This means they have unrestricted access to disk, network, memory, CPU, and so on, so they can (excessively) write files to disk, use unoptimized code to eat up memory or CPU, cause deadlocks or main thread delays, download (and upload!) large amounts of data, and so on. Even worse, they can cause crashes, or even crash loops. Twice.

Many of these cases are not discovered until the app is already in the store, in which case fixing it requires creating a new version and passing it through review, which often takes a lot of time and cost. This risk can be controlled to some extent by having a variable control whether it is called, but this approach is not foolproof (see below).

Development Risks

To quote a colleague: "Every line of code is a burden", and this is even more true for code you didn't write. Libraries can be slow to adapt to new technologies or APIs, which hinders code development, or too fast, resulting in over-developed versions.

Libraries can be slow to adopt new technologies or APIs, blocking the code base, or too fast, resulting in deployment targets that are too high. Whenever Apple and Google release a new OS version every year, they usually require developers to update their code based on the changes in the SDK, and library developers must do the same. This requires a coordinated effort, alignment of priorities, and the ability to complete the work in a timely manner.

As mobile platforms are constantly changing, and teams are not static, this becomes an ongoing risk. When the library being integrated no longer exists and the library needs to be updated, a lot of time is spent deciding who should do it. It turns out that once a library exists, it is rarely and difficult to remove, so we view it as a long-term maintenance cost.

Business Risks

As I said above, modern operating systems do not distinguish between app code and library code, so in addition to system resources, they can also access user information. As app developers, we are responsible for using this information appropriately, and we are also responsible for any third-party libraries.

If the user gives the Lyft app geolocation permission, any third-party library will automatically have to grant permission as well. They can upload that data to their own servers, competitors' servers, or who knows where else. It's even more problematic when a library requires permissions we don't have.

Likewise, a system is only as secure as its weakest link, but if it contains unaudited code, then you have no idea how secure it really is. Your carefully crafted secure coding practices can be undermined by a misbehaving library. This is true of any policy implemented by Apple and Google, such as “you may not track users.”

Reduce risk

When evaluating a library for use, we first ask a few questions to understand the need for the library.

Can we do it internally?

Sometimes we just need to simply copy-paste the parts we really need. In more complex scenarios, where the library communicates with a custom backend, we reverse engineered that API and built a mini SDK ourselves (again, only building the parts we need). In 90% of cases, this is preferred, but not always possible when integrating with very specific vendors or requirements.

How many users benefit from this library?

In one case, we were considering adding a very risky library (according to the criteria below) designed to serve a small subset of users, while exposing all of our users to it. We risked creating problems for all of our users for a small subset of customers that we thought would benefit from it.

What transitive dependencies does this library have?

We also need to evaluate all dependencies of the library for the following criteria.

What are the exit criteria?

If the integration is successful, is there a way to move it in-house? If it is not successful, is there a way to delete it?

Evaluation Criteria

If the team still wants to integrate the library at this point, we ask them to "rate" the library based on a set of criteria. The list below is not comprehensive, but should give a good idea of ​​what we like to see.

Blocking criteria

These standards will prevent us from integrating this library either technically or due to company policy. Before we can proceed, we must resolve:

Too high deployment target/target SDKs. We support the mainstream operating systems (versions) in the past 4 years, so third-party libraries need to support at least as many.

Incorrect/missing license. We bundle the license file with the app to ensure we can legally use the code and attribute it to the license holder.

No conflicting transitive dependencies. A library cannot have a transitive dependency that we have already included but at a different version.

Does not display its own UI. We take great care to make our products look as uniform as possible, and a custom UI would be detrimental to that.

It does not use private APIs. We don't want to take the risk of having our app rejected for using private APIs.

Main focus

Closed source. Access to the source code means we can choose which parts of the library we want to include, and how to bundle that source code with the rest of the application. A closed source binary distribution is harder for us to integrate.

Compile with warnings. We have "Warnings Treat as Errors" enabled, and libraries with compilation warnings are a good indication of the (declining) overall quality of the library.

Poor documentation. We would like to have high-quality inline documentation, external "how to use" documentation, and meaningful changelogs.

Binary size. How big is the library? Some libraries provide a lot of functionality, and we only need a small part of it. Especially without source code access, this is often an all-or-nothing situation.

External network traffic. Libraries that communicate with upstream servers/endpoints that we don't control could bring down the entire application if the server is down, bad data is sent back, etc. This is also the same privacy issue I mentioned above.

Technical support. When things don't work properly, we need to be able to report/escalate the problem and have it fixed in a reasonable time. Open source projects are usually maintained by volunteers and it's hard to have a timeline, but at least we can make changes ourselves. This is impossible in closed source projects.

Cannot be disabled. While most libraries specifically ask us to initialize it, some are more "active" when instantiated and can do work on their own without us calling it. This means that when a library causes problems, we cannot turn it off via a function variable or other mechanism.

We assign points to all of these (and a few other) criteria and ask engineers to tally up those points for the libraries they want to integrate. While low scores aren't hard to reject by default, we usually ask for more justification to move forward.

at last

While this process may seem very rigorous and in many cases the potential risks are hypothetical, we have real-world examples of each scenario I describe in this blog post. Documenting the assessment and making it public also helps communicate the relative risks to people who are not familiar with how mobile platforms work and demonstrates that we did not assess the risks arbitrarily.

Furthermore, I don’t want to claim that every third-party library is inherently bad. In fact, we use a lot at Lyft: RxSwift and RxJava, Bugsnag’s SDK, Google Maps, Tensorflow, and a few smaller ones for very specific use cases. But all of these have either been fully vetted or we’ve decided the risks are worth the benefits, with a clear understanding of what those risks and benefits really mean.

Finally, as a pro developer tip: always create your own abstractions on top of a library's API, and don't call their API directly. This makes it easier to replace (or remove) the underlying library in the future, again mitigating some of the risks associated with long-term development.

<<:  CI build performance issues caused by upgrading JDK 11 on Feishu Android

>>:  Is iOS 16 worth upgrading? Here’s a sneak peek at the main features of the official version

Recommend

iOS 13 shortcuts add "automation", what changes will this bring to the iPhone?

Workflow was originally a third-party efficiency ...

Can Microsoft Surface 3 compete with Apple iPad to the end?

The Surface series has been around for so long. I...

How much does it cost to develop a food delivery app in Jinchang?

How much is the quote for Jinchang takeaway devel...

An explosion! Send us into space? Exploring the energy secrets of spacecraft

Endless explosions could send hypersonic vehicles...

A self-help guide for visiting relatives during the Spring Festival

Mixed Knowledge Specially designed to cure confus...

After the "disruption" wave, traditional TV manufacturers are forced to run fast

In the past two years, as more and more Internet ...

Brands must do these 5 things to stand out!

I believe that many people who do brand marketing...

Why reinvent the wheel?

A few days ago at the React-Europe conference, I ...

What is a botanical garden? You may have never visited it correctly!

The National Botanical Garden was established on ...