Things to keep in mind before adding a Software Dependency to your project

By Agustin Aliaga, Mobile Developer at Santex

In my work experience, one basic thing I learned about software engineering is that you don’t need to “reinvent the wheel” every time you want to achieve some functionality. Open source projects have revolutionized the way we work in that we can reutilize existing software in addition to collaborating with others devs. In the web-development ecosystem, there are plenty of frameworks and tools that already simplify things like user authentication, routes, templating (client-side and server-side), state-management, database queries, web sockets, etc. On the other hand, however, sometimes the existing solutions are just not good enough or it may be that there are no alternatives at all, but that’s a completely different story.

The ability to know when to implement the feature yourself and when to use an existing solution will be a crucial asset for your team. Adopting a new library, language or technology as a dependency to build your product without extensive research could become headache in the future, so you should always ask yourself at least these questions about it:

1. Does it meet all your needs?
Sometimes you’ll find a solution for your problem that does not cover all the specific features you need. In that case, you might have to deal with forking and extending it (if it’s an open source project), and this means greater time investments and costs. Are your team and the client prepared for this scenario?

2. Is there any documentation?
If so, is it well documented? Just as an example, one of the things I like the most about Django (web framework) is the quality they put into the docs. It’s remarkably easy to find the topics you need for the framework version you’re using. https://docs.djangoproject.com/en/.

3. Is it supported by a “big” community and/or a private company? Having a company or a community behind it helps a lot when you’re having trouble and need assistance from others. You may have to send a “help-desk” ticket (probably if it’s a paid service), find information on blogs or StackOverflow, or maybe even post a question to those sites. If you’re relying on the community to help you, your chances of being helped are proportional to the popularity of the software dependency.

4. Is it an “external service”?
If you rely on services like “Google Maps API”, “Facebook Graph API”, “Google’s Firebase”, etc. be aware that they may change in the future without notice, or they could just stop working at any time (temporarily or permanently). SaaS/BaaS solutions are great but you should think twice before setting them up as a critical piece of your system. Just as an example, read about what happened to Facebook’s Parse: (https://techcrunch.com/2016/01/28/facebook-shutters-its-parse-developer-platform/).

5. Is it actively maintained and improved?
If hosted on Github, “Pulse” and “Graphs” tabs will give you an idea of the latest activity. You probably don’t want to set up an outdated library, because it could bring retrocompatibility issues to your project. Also, if it’s constantly evolving, sometimes it could mean you’ll have to update your code repeatedly.

6. Is it tested?
Some libraries use automated tools to build and test every change that is introduced (applying continuous integration tools like Travis CI, Circle CI, etc.). This makes the library more reliable.

7. Are you compromising another dependency if you adopt this new library?
Sometimes libraries don’t play well together.

8. Will it affect your product’s performance, speed, size, etc.?
You should always take this into consideration. In the “web environment”, a giant front-end library could affect the browser’s performance and also increase network transfer times. On the back-end side, you want to avoid server overloading. In the mobile world, things get even more critical because mobile phones don’t have as many resources as a desktop computer. In Android, an app that wastes memory and CPU is a real candidate to be killed automatically by the operating system.

What about Android ?

The core-functionalities that Android brings to the table are sometimes more than enough to build simple applications. You could build an entire app by using bare Activities, Fragments, Views, AsyncTasks, Services, Content Providers, Broadcast Receivers, etc.

But in my experience, sometimes this means you’ll have to write (and then maintain) a lot of repetitive/boilerplate code. In other words, sometimes sticking to the core framework means you will have to invest more time to taking care of all the details. Some examples of libraries that made me more productive in Android development are: Retrofit, Dagger 2, and Butter Knife.

You should also know that if you add too much direct and transitive dependencies (plus your own code), you might exceed the “64K-method limit”, explained by Android documentation:

Android app (APK) files contain executable bytecode files in the form of Dalvik Executable (DEX) files, which contain the compiled code used to run your app. The Dalvik Executable specification limits the total number of methods that can be referenced within a single DEX file to 65,536—including Android framework methods, library methods, and methods in your own code. In the context of computer science, the term Kilo, K, denotes 1024 (or 2^10). Because 65,536 is equal to 64 X 1024, this limit is referred to as the ’64K reference limit’.”

If you exceed this limit, you’ll have to change your application to support “multidex”, which means it will have to load multiple dex files. This will produce higher compilation times, and also performance/loading issues in the app itself. So I’d recommend to always be careful with the dependencies that you add to your Android project.

Conclusion

I have seen these concepts apply not only to Android development (a technology I use every day at work), but to all software development in general. Every product relies on dependencies (whether it’s an OS, a service, a framework, a library or some other kind of software). The goal is to pick the best ones to maximize your productivity, without affecting your product’s performance, scalability, and capacity to evolve over time.

Leave a reply