Engineering

IOS Open Source Hell

Open source hell

Hey folks! I came up with a great idea, I will write a library that ... does the same as ten others do.


Welcome to the open source utopia, where our projects depend on dozens of powerful libraries maintained by great software developers, frameworks that perform a lot of sophisticated work. Where every problem is handled by separate library and we're finally able to say that development is as easy as Google Search. We're not afraid of any new challenges because there is always a solution on github.com for that. This is where utopia becomes an unmaintainable hell.

Let's look briefly at open source problems of modern iOS applications and try to find a simple rules of thumb for each of them, however you can apply most of them to other platforms.

When should I consider adding a library?

Once you'll face a challenge in development, it's always a good idea to ask yourself the questions below:

  1. Is there a native solution? If there is, does it work properly? How much work does it require?

  2. Is it known as your platform's common problem where everyone uses library?

Imagine you need to implement a feature aim to display images from a remote source, caching and compressing them. The native way to do that well on iOS might require huge amount of work while there are great tools like Kingfisher or SDWebImage to do that hard work for you. Another example is working with SVG images, it's almost impossible to use them natively on iOS, so it's definitely a topic where you should take a look at the third party code.

On the other hand, if someday you will need to handle a concurrent task in you application, like reading asynchronously data from a file, there is absolutely no need to add any dependency for that i.e. very powerful ReactiveSwift or wrappers around GCD like Queuer. GCD API itself is very easy to use and understand in a few hours. Maybe when you plan to use data binding or have a lot of concurrent code, it's worth considering such tools, but I believe that for small and simple tasks ,it can quickly mess up your code base.

Please also keep in mind that every library that you add increases the build time, application launch time and package size.

Which library should I use?

  1. Select the one that is tested well. I always try to look at the tests and wonder if they make sense.

  2. It's important to use a library that is often contributed, especially if you want to use the one written in Swift (because of Swift versioning compatibility problems).

  3. Don't use a library with ten stars and a lot of issues, this may not be critical criteria, but you should always consider it.

  4. If a library is not as simple as firing a couple of functions you should also keep in mind how easy it is to take advantage of documentation, this might help you a lot.

Frameworks might be very helpful, but you should always think twice before using them and never trust them completely. There are some exceptions to the rules above like third party SDK (Facebook, Spotify, etc...). Anyway, if SDK is total rubbish, you should negotiate that with the product owner.

Maybe I should create my own library?

What might lead you to create your own framework?

  1. You came up with a really unique idea that is not covered by open source already, or is not written very well.

  2. You've used other libraries and all of them have disadvantages that makes them rubbish.

  3. Swift equivalent of some Objective C library.

This paragraph is probably the most important one. It's very popular to create a library that already exists in the open source world. It's even harder to count all those AutoLayout or Keychain wrappers, helpers and proxies. To be clear I'm not against writing another library for AutoLayout as long as it is written well.

The biggest problem of creating your own library comes about when you, and only you, will be using it. You create library that fits only your project and the whole code base depends on that library. It's not a problem when it's easy to replace that library with some native solution or other library, but what if it's not?

Will others be happy to work on this app while using my library?

My favorite example is DataSource framework that "simplifies" everyday work with UITableView and UICollectionView in a way that is almost impossible to replace with any other code.

Also please keep in mind that sometimes it might be much better idea (for both you and the world) to contribute to already existing library rather than creating your own.

How to add library?

I don't think this article is a proper place to describe when you should use Cocoapods or Carthage, but if you want to read more about this topic, you can take a look at my other article.

Anyway, there are cool libraries that contain one file and it's not worth adding them via dependency manager because they would be build as a separate dynamic framework which would increase iOS app startup time. In my opinion, in such cases, it's a good idea to add them as a submodules and compile along with the application.

If it's your own library maybe it's also better to add it as submodule because it's more possible then to fix the library's problems.

How to use libraries?

Finally! You've selected a library that is proper for your project and added it. How should you use it?

  1. If it's possible, wrap it around with your code that will allow replacing it with something else in the future. I.e. let's say you've added some the HUD indicator library (Which you should never do, by the way). Instead of calling directly HUDLibraryA.showHud() from every controller, define simple wrapper, in this case it may be an extension to UIViewController. Then, if one day, you would like to replace it with some other framework, it would be as easy as replacing one line of code.

  2. Use them wisely, read documentation and make sure you are using it properly. A common example can be wrong usage of reactive programming libraries. ReactiveSwift / RxSwift are huge, powerful libraries that you should read about first, before using and making your code smell.

  3. If you find it hard to use the library you've added, maybe it's better to remove it before destroying your code completely.

Good practices

balance

To wrap it up, I want to share with you some of the practices which I found while experiencing a lot with third party software (and making some of the mistakes I listed above as well).

  1. Always try to minimize number of frameworks in your project.

  2. Do not mix two libraries that were created to solve the same problem. (i.e. RxSwift and PromiseKit).

  3. Always read source code / tests of a library that you want to use in the project.

  4. Please don't create another library which does not bring anything new.

  5. Take your time to contribute with other developers.

  6. Look at your own library from other developer's perspective, ask your friends or developer groups what they think about it, before using it in a production code.

  7. Remove libraries that you don't use anymore.

  8. Don't create another Keychain wrapper 👊.