I remember late nights browsing support forums ready for any answer to help. Writing a post, pleading for help, hitting refresh, and waiting for someone to reply was not efficient. But when that's all you know to do, it had to work.
Sleepless nights like those are much easier to avoid if you more carefully choose dependencies.
When I've got a problem to solve, I often look around to see if someone else has already solved it. I never want to waste my time reinventing the wheel.
Ruby has a healthy community. There are so many available gems it's not surprising to find your problem already solved. Dropping a gem into your project is easy. But if you don't understand the impact, you too could be up late begging the internet for help!
Over time I developed a few steps of figuring out what to choose.
If we're going to depend on one of these gems, we'd better make a good decision. Here are some questions to ask when I find a possible solution for my projects.
1. How many stars/watchers does it have?
I've often seen this used as a major deciding factor of choosing a new dependency. A large and active community can keep a project healthy. Yes, if many people use it, that means finding help might be easier. But it's foolish to stop there. A collective mind is great guide, but it's no replacement for taking responsibility.
2. How many active issues or pull requests are there?
Are the project's issues loaded with bug reports or confused developers? Do the maintainers categorize the issues according to how they will be addressed? For any old issues, is there active discussion?
3. When was the most recent release?
Is the project active? When was the last time the gem was released? Or is the code so simple that regular updates aren't necessary?
4. How many of its own dependencies does it have?
Are you prepared to pull all these dependencies into your project? What will happen if your project needs a newer version of one of these but this gem prevents it? Or if you need an older version but this requires something newer?
The more dependencies a gem has, the more impact these questions will have.
5. Are the maintainers friendly?
Whether in a bug ticket, a forum post, or anywhere else: do the maintainers act helpful? Can you count on them to help you when you need it?
There is the corollary to that: are you helpful? When it comes time to ask for help can you provide steps to reproduce an error?
6. How many forks with un-merged changes exist?
The GitHub network graph is a great place to find out if a project has a disconnected community. Are there many forks with good updates that the main project has ignored? Will you need to gather commits from those forks to get a feature working?
7. Does it have documentation?
Is there a clear place to go that gives you example uses? Can you understand what the gem does and how it works from the provided documentation?
8. The crazy one: Can you understand the code?
When things go wrong, as they inevitably will, have you chosen something you can figure out? Or is this dependency something that will stop in your tracks?
I don't actually go through those other steps above until I've first looked at the code.
Most often, the first thing I do is read code.
I recall a past project where my pair and I were researching a dependency. I immediately dove into the "lib" directory and he (who preferred other languages to Ruby) said:
Is this what Ruby developers do? Don't you look for documentation?
I don't know about other Ruby developers, but it's absolutely what I do first. If I think a project might be a fit for my problem, I want to see what kind of code will become a part of my application. My pair was a fantastic developer and his question was in good fun. But it made me realize that this code-first approach might be unusual.
If it works now but the code is a hot mess, what will my life be like when things don't work?
Here's my checklist in the order I do it:
- Can you understand the code?
- Does it have documentation?
- Are the maintainers friendly?
- How many of its own dependencies does it have?
- When was the most recent release?
- How many forks with un-merged changes exist?
- How many active issues or pull requests are there?
That's it. I always start with reading the code. The order of the rest of them may change here and there but that's typical. I may have to make concessions with one because the answer to another is compelling.
You may notice that I left one out...
I don't care how many stars or watchers a project has. If I can't answer the above questions with satisfaction, watchers means nothing. And if I am satisfied with the answers, watchers means nothing.
When you bring in a dependency, you own it; you must be able to figure it out.
If you're an experienced developer you may think differently about answering these questions. But one reason I look to the code first is that junior developers will need to be able to do it too.
You may find that no existing tool does exactly what you want and you might then build your own. But if you cannot evaluate the code well, how would you know if you should build your own?
What do you do? Write a blog post about it and share your experience.
Get in touch with me to help you evaluate your projects.