Choosing a software library or framework
While developing software projects, knowing when to use a library/framework and choosing one among many, isn’t as trivial as it seems. A systematic approach should support the process.
I’ll try to abstract from the language/runtime/platform (PHP, Java, .NET, etc.) in use, as the concepts are generic.
Before starting, just a bit of terminology. don’t confuse libraries, frameworks, services, boilerplates, and APIs:
- Library: a set of related resources (methods, functions, images, etc.) that you can include and make use of (e.g. jQuery, Apache Commons for Java, Intervention Image for PHP, AFNetworking for iOS, Math.NET for .NET).
- Framework: proposes a specific way to design the architecture of one or more software layers (e.g. AngularJS, Spring for Java, Laravel for PHP, Ruby on Rails for Ruby); a framework can embed libraries.
- Service: a set of capabilities offered by an external party to the application, on a local host or in the cloud (e.g. Firebase).
- Boilerplate: sample project used as a starting point when creating a new project (e.g. HTML5 Boilerplate); it can be setup by a generator (e.g. Spring Initializr).
- API: the “face” (inputs and outputs) of a system (e.g. a class, a library, a service). An API is the interface for the programmer the same way a GUI is the interface for the user.
A library is a set of reusable functions or data structures that are yours to use. A framework, on the other hand, has an architecture or programming model, which requires an application to be designed (divided into modules) in a certain way (application architecture) to use it. I like to think that while you use the library, the framework uses you.
Why use libraries and frameworks?
Reusability is a watchword in software engineering. Avoiding “reinventing the wheel” is the rationale for using libraries and frameworks. Don’t develop software that is not the “core of your business”. It doesn’t make sense to redo code that is created, tested, and maintained by others who are dedicated to it. That’s why there are “packaged” features, ready to be used.
An application of average complexity (e.g. an intranet, an iOS app) can use dozens of libraries and some frameworks. Most are free and many are open source.
The “problem” is that there are numerous ways to solve the same kind of problem. The web has countless offers. Where to start? How to filter? Sometimes, obvious choices may be dangerous as those may hide people’s prejudices. Be humble to follow a process that removes those prejudices.
Need a new dependency?
Firstly, you should ask if you really need a new library or framework. Is the problem you are solving a common problem (from other people/projects)? If so, surely someone has already thought about it and solve it. The use of a library/framework becomes compensatory in cases like:
- common algorithms, such as ordering or processing data;
- import/export from/to a format (Excel, PDF, etc.);
- creation of a cache;
- authentication and authorization;
- animations (graphic effects);
- serialization and deserialization of XML or JSON;
- consume or provide a REST API;
- abstract network communication;
- multimedia player;
- security algorithms;
- template system;
- mediating objects and tables/relations (ORM);
- widget toolkit;
- … among many others.
If you’re only going to take advantage of a tiny part of a library/framework you might not even need to use it. Does the language/runtime bring most of what you need? Do you need only a micro-library/utility and not a giant framework?
When you decide to include a library you should take into account:
- the extra resource consumption (network latency, time spent compiling, deploy and runtime, memory costs)
- the creation of another technological dependency thus having to rethink your software architecture to correctly isolate it;
- learning time;
- the inclusion of unknown code;
- possible incompatibilities with the rest of the software.
When using a framework, in addition to the points mentioned above, you should also consider:
- some risk of lost time/effort if the choice was poorly made;
- that programmers may forget or ignore what’s happening “under the hood” (e.g. they may be generating slow queries without knowing);
- possible impositions (i.e. a framework can impose a way of working and make it difficult not to use it).
In conclusion, it’s okay to add libraries/frameworks to the project if you are aware of the weight of their drawbacks.
How to begin?
Now that you have decided to use a library or framework, what do you do? It’s time to search and prepare an initial survey. There are probably dozens of libraries/frameworks to help you with your goal. Let’s go by eliminating hypotheses. It’s not the time to decide, so abstain of in-depth analysis at this stage — remember this is only an initial survey.
It’s imperative that you know very well the problem you want to solve: there are problems with different levels of abstraction (e.g. ordering a list is lower level than creating an online store), so you should match the library level to the problem level. Consider only solutions linked to your development environment (Node.js, Java, Swift); ignore those that have little or nothing to do with the problem to be solved; discard those that do much more than you will use in the medium/long term.
Stack Overflow, Wikipedia and opinion and/or comparative articles are good starting points. Projects hosted on GitHub have the great advantage of giving you metadata (e.g. stars, pull requests, contributors, etc.):
It is likely that you were left with around 6~10 candidates at this stage.
How to filter?
In addition to search engines, library repositories are sometimes excellent starting points (as many have good categorization, lots of metadata, and implement some “natural selection”). For example:
- for Android, Android Arsenal;
- for PHP, the Packagist;
- for Java/Kotlin, the Maven Repository;
- for iOS, the CocoaPods;
- for Node.js, the npm registry;
- for Ruby, or RubyGems.
Analyze the mission of the library/framework, its documentation, samples/demos, and its forums/communities. If you can, avoid versions “1.0” (and below); it is likely that they have not yet reached the required maturity. Review software licenses, eliminating those that don’t fit with what you can use in the context of your problem.
Libraries and credible enterprise frameworks or open source foundations (e.g. Google, Facebook, Pivotal, Apache Software Foundation, jQuery Foundation) offer more trust than those made by unknown individuals (but there are exceptions).
After this analysis you should have reduced the candidates to 2~5. If it’s still confusing or if the choice is decisive for the project (applies more in frameworks than libraries), refer to decision matrices (optionally weighted). Such matrices can help to consolidate/document these studies and present them to decision makers.
In the example of Wikipedia below we see the comparative features of web frameworks for Java (the lines are switched with the columns, compared to the previous table):
How to decide?
Don’t ask the question, “What is the best library?”; rather than “What is the best library for this problem?”
Avoid deciding something based on a whim or curiosity. Run away from empty, emotional or subjective arguments:
- «I already used it and I loved it»
- «Facebook uses and it’s spectacular…»
- “It’s on fire! everyone is using it! »
Focus only on technical and factual arguments:
- What is the degree of correspondence between the library and the problem to be solved?
- What is the quality/quantity of documentation?
- How frequent are the versions (and which was the last)?
It’s time to make experiments (PoC , prototypes or pilots). Focus on implementing one or two key “top-down” functionalities that allow the library/framework to show its strengths and weaknesses. To do it, think about decisive operations in your problem/project. For example: “it’s imperative to have a data table with sorting, filters and inline editing”. What are those features that can’t be missing and without them, the project will fail? These are the ones you want to test in the pre-selected libraries/frameworks.
The effort involved in a decision must be directly proportional to its importance. For smaller libraries, spend less time. For decisive frameworks, spend more. On the other hand, you do not need to apply all of the methods mentioned. Sometimes a good reading of GitHub is enough to feel confident in a pre-filtering or even decision.
The purpose of the PoC is to consider/discard something if it doesn’t fulfill an objective that you consider fundamental; so balance the detail you go into. Each PoC can be done in parallel (by different programmers). You could store them in branches in your versioning repository.
Depending on the requirements, consider also comparative performance tests. For example, if you are evaluating a library for JSON parsing, make an exhaustive test battery that allows you to evaluate each under extreme and exceptional conditions (e.g., heavy files, large nodes, etc.). To complement the analysis and help you in the decision, do “A vs. B” type searches (e.g. “volley vs robospice”, “ imageloader vs glide”) and consider opinions from those who have already used the tools.
Finally, choose a PoC as the winner. The chosen PoC codebase can be availed for the project.
Before deciding to use a library/framework, ask if you really need it, because using it doesn’t bring advantages only. Do a quick cost-benefit analysis: will the disadvantages outweigh the benefits?
- The investment of a few days in these experiments can be very rewarding, since the wrong choice can have a much greater impact on the project;
- Don’t label an experiment/PoC as “time lost” if it wasn’t a success; something failing is also valuable knowledge;
- When arguing, try to bring factual arguments;
- The fact that tool X has worked well in project Y is not a strong argument (unless projects are very similar);
- Be humble and assume if you have made a bad choice, if any — the sooner you do, the better; whether you have chosen right or wrong, there are lessons to be learned;
- If you have to make the same choice again, repeat the selection process; libraries/frameworks are born and die sporadically, and the paradigm of the problem is itself evolutionary;
- Be a “devil’s advocate”: instead of trying to show why the library/framework should be used, try to show why it should not be used — if you can’t, it’s a good indicator.
Finally, remember that there are no libraries that solve everything or libraries that don’t solve anything. Each problem requires a careful and personalized choice of one or more libraries.