Even Swaps, a rational way to choose a library
— decision-making, opensource — 4 min read
As developers, we are fortunate enough to have at our disposal a never-ending selection of high-quality libraries to choose from when we want to solve our problems. This creates a new challenge: which one to use and why?
The main question this article helps answer is how to methodically choose a library that will best fit your needs and will save you time on unwanted refactorings. This method is most useful when a clear alternative is not clear, and there are several options to choose from
Who are our users? 👨💻🙋♀️
There are two users we should keep in mind when choosing a library. Each one has his own needs and expectations.
The first type of user is, of course, the final user of our application. This person expects an easy to use, performant, and beautiful product. She doesn't want to spend time learning how to use your UI or have to read somewhere else what are the steps they need to do their job or solve their problem.
The second type of user is the developer, who will be using the library. This person expects an easy to use API, plenty of customization available, smart defaults, proper documentation for the library, and that the project is still maintained.
What are the exact needs your product has?
This is the first question you should be asking. What features are they expecting your library to have? What are the use cases for it? How does the design look like?
Do you need a library? 🤔
After understanding the need, you should ask if you need to use an existing library. If the use case is very simple, you might be better off just creating the code yourself or making use of a feature from JavaScript (don't forget to check things in stage 3 of the standard). Just keep in mind the pros and cons of using a library:
Pros:
- Battle-tested
- It's usually highly customizable
- Best practices baked-in
Cons:
- Has a learning curve
- Might require making decisions you might not like (depend on another external library like moment.js, using CSS classes instead of styled-components)
- You'll have to keep it up to date for security reasons
- Adds to your bundle size
The method to choose a library (Even Swaps)🔄
Alright, let's say you have decided that you are going to need a library, now it's time to apply the method for evaluating the best choice. This is based on a Harvard Business Review publication called "Even Swaps" from authors John S. Hammond, Ralph L. Keeney, and Howard Raiffa published in 1998. For this example, let's say you have decided you need to choose a datepicker library that will be used in several screens of your app. We'll be creating a matrix of library vs. dimension to evaluate our decision.
Part 1: Choosing dimensions
Here's where knowing your two types of user counts, what does each one need? First, let's see what a final user would expect from such a library. We'll assign numbers to qualitative dimensions:
- Good UX (easy to use) (1-5, 5 is best)
- Mobile friendly *
- Supports localization *
How about the developers? Here are a couple of ideas:
- Proper documentation (1-5, 5 is best)
- Bundle size (smaller is better)
- Dependencies (no dependencies is ideal)
- Easy to style (1-5, 5 is best)
If any of the other dimensions is a must, then you can mark it with a * for part 4 of this method. For this particular case, I've marked mobile friendly and localization as musts.
Part 2: Finding relevant options
List out all the options you find after a quick google search. Make sure you also search for alternatives to the first result. You can do this by typing "FIRST ALTERNATIVE vs." and google will autocomplete other options. Finally, you can also tweet or post questions in communities such as Reddit or Spectrum.
Part 3: Creating a consequence table
For this part, you'll have to read the docs and preferably play around with the library.
Afterward, you can create a table with the libraries in one axis and the dimensions from step 1 in another axis. This is called a consequence table in the original method. For measuring bundle size, I recommend using bundlephobia.com
Library | UX | Mobile Friendly * | Supports localization * | Good documentation | Bundle size | Dependencies | Easy to style |
---|---|---|---|---|---|---|---|
react-dates | 5 | Yes | Yes (using moment.js) | 5 | 231kB | moment.js | 5 |
react-datepicker | 3 | Yes | Yes (internally uses date-fns) | 3 | 63.5kB | None | 3 |
As you can see, react-date-picker has been discarded because it's not mobile-friendly, which was one of our must dimensions.
Part 4: Doing even swaps
This is the core of the method. It will allow us to narrow down our options to a single one. I'll let the original authors explain it much better than I can:
What do we mean by even swaps? To explain the concept, we need to state an obvious but fundamental principle of decision-making: If every alternative for a given objective is rated equally—for example, if they all cost the same—you can ignore that objective in making your decision. If all airlines charge the same fare for the New York to San Francisco flight, then cost doesn’t matter. Your choice will hinge on only the remaining objectives.
In short, we want to make two options have the same values for all their dimensions except one; then, we'll use that last dimension to pick the dominating option and discard the other one, as simple as that.
How do we do this 🤷? We must determine what it would take to make two options have the same value in one dimension. For example, let's say we want to ignore the UX dimension; this would mean we want two options to have the same values. We then ask, how many additional kB of bundle size would I add to give an option two extra points of UX? Let's say it's 150 kB. Let's add 2 UX points to react-datepicker and increase its bundle size by 150 kB.
Library | UX | Mobile Friendly * | Supports localization * | Good documentation | Bundle size | Dependencies | Easy to style |
---|---|---|---|---|---|---|---|
react-dates | 5 | Yes | Yes (using moment.js) | 5 | 231kB | moment.js | 5 |
react-datepicker | 5 | Yes | Yes (internally uses date-fns) | 3 | 213.5kB | None | 3 |
Now, the first and second option are almost the same. Let's ask, for two additional points of documentation, how many kB would we add? Let's say it's 80 kB
Library | UX | Mobile Friendly * | Supports localization * | Good documentation | Bundle size | Dependencies | Easy to style |
---|---|---|---|---|---|---|---|
react-dates | 5 | Yes | Yes (using moment.js) | 5 | 231kB | moment.js | 5 |
react-datepicker | 5 | Yes | Yes (internally uses date-fns) | 5 | 293.5kB | None | 3 |
The remaining options are almost the same. Finally, we can choose how many points in easy to style we would take if we were to remove moment.js. Let's say it's 2. This will allow us to select the final winner 🎉
Library | UX | Mobile Friendly * | Supports localization * | Good documentation | Bundle size | Dependencies | Easy to style |
---|---|---|---|---|---|---|---|
react-dates | 5 | Yes | Yes (using moment.js) | 5 | 231kB | None | 3 |
As you can see, doing swaps correctly requires experience and criteria, the more you use it, the better you'll get at it.
Part 5: Documenting your decision 📖
Once you are left with only one option. I'd recommend you add the information about why you chose this library for your teammates to understand why they are using this library. A good option is creating a markdown file where you document the consequence table and method you used.