What I learned after writing my first open source libraries

Sang-gon Lee
4 min readMay 8, 2021

I worked on my side project for the past 4 months. It consists of the main tool (plum) and two supporting libraries (monochron and pogo).

I didn’t spend crazy amount of time on it, but I definitely needed to work in consistent pace. My Saturday mornings were pretty much dedicated for this.

And here are my learnings (other than technical stuffs) from this journey!

It’s not hype-driven

Most of my previous side projects were hype-driven. I would find a new and cool technology, and say “I gotta try this out!”. And then I would spend every night for a week building something with it, and quit before its completion.

In retrospect, these were the reasons for it:

  • New technology is not as mature, and not as rich in its ecosystem. This means there are likely to be more bugs, less learning resources, and less people who paved the way for it. And naturally you will more likely to pull your hair out as you’re working with it, leading to frustration.
  • I was too greedy. I wanted to make the best use of my time, so tried to learn too many new things with one project. This somewhat helped me learn those new things, but had a lot reduced productivity. And because the pace was so slow getting things done, I would quickly lose interest.
  • Still hype is good and all, but it shouldn’t be the #1 driving force in the project, unless your sole purpose is to learn it. There are too many elements that can lead you to reduce the hype, and in general hype doesn’t last too long in its nature.

For this project, I used Go and React — what I’m most familiar with. Still I tried a couple of things new to me — tailwind css, recoil.js, and docusaurus. recoil.js was also a strategic decision because I felt redux or rxjs were too heavy for this project.

Battle between flexibility vs ease of use

One of the most challenging things creating libraries was the balance between their flexibility and ease of use. I have seen very obscure interfaces of some libraries before and I really wanted to make my libraries as easy to use and readable as possible.

As an example, related to the BDD, I wanted users to be able to read my APIs in pogo as smoothly as possible, like this:

rows, err := pogo.Query().For(
pogo.StatDatabaseView.With(
pogo.StatActivityView,
...

So that it can be read like “pogo, please Query For StatDataBaseView With StatActivityView”.

But going this way, I couldn’t support querying with the database client of user’s choice. In other words, it didn’t have the enough flexibility I was aiming for. So I had to resort to:

rows, err := pogo.Query(queryor).For(
pogo.StatDatabaseView.With(
pogo.StatActivityView,
...

where queryor is an interface that users can provide the implementation for. I was pretty happy with the compromise here!

You can’t just start writing a library

You always want to have a strong use case for it.

If possible, write a program/application first, which would use your future library (obviously your program would be in a broken state, so don’t push it to production!).

Even better, write the entire thing in your program/application, even if you’re 100% certain you will write the library. And then separate the library part out into a library.

This way, you:

  • have automatically written an integration test for your library.
  • will have a stronger sense of how your library will be used, so you can come up with a better design.

Documentation, documentation, documentation

Documentation is critical in software development in general. But when it comes to library, it’s even more important.

You have to communicate how to use your library to a complete stranger — also one-way — after all.

Use your best methods to document the following non-exhaustive list:

  • APIs (including function/command/class signature, parameters, options, etc etc)
  • Examples (this is not required, but in reality most first time learners learn best by examples)
  • Visual helpers (for many people, visual interaction is the easiest way to understand)
I’m pretty proud of the visual explanation for monochron’s RootBucket type — it tells you what part of the chart one RootBucket represents.

Spread the word

What good is a library if no one will use it or knows it even exists?

If you’re proud of your work, definitely spread the word!

I recommend using multiple channels; here is the list (I didn’t use all of them):

  • Hacker News
  • Twitter (works amazing if you have a lot of followers)
  • Write on Medium (like here)
  • Share on various slack communities
  • LinkedIn

It’s also a great idea to create a network of related projects. Reference other ones from another project (like plum, pogo, and monochron).

Closing remark

My conclusion is creating libraries is a worthwhile experience for developers. It lets you see development from other angles, and you can possibly contribute to the community! It might also help you find jobs if you’re looking for one.

While working on libraries I also got inspirations for other libraries. So even if your idea might not sound super useful, it might eventually lead to the most useful library ideas.

Thank you for reading.

--

--