How To Pick The Right Swift Open Source Component

With so many options available, it’s not easy figuring out how to pick the right Swift open source component. There are literally thousands, if not hundreds of thousands, of open source projects written in Swift on the web. You can find anything from simple UI widgets, to entire frameworks to support functional reactive programming. With all these choices, how do you pick the right Swift open source component to use in your project? Initially, you first have to find a component that actually meets your needs from a functionality standpoint. But after that, and arguably just as important, that open source code base must meet a minimum set of requirements to be considered for use in a production application. Here are the proposed minimum requirements to pick the right Swift open source component:

  1. Composition over inheritance
  2. Date of most recent commit
  3. History of past commits
  4. Popularity among the community
  5. Dependency manager support
  6. License
  7. Tests
  8. Proper versioning
  9. Maintenance ownership
  10. README

While most of this article’s proposed items apply to any open source project on the web, the specific examples cited in this article will be focused on performing the evaluation within the context of GitHub.

Composition Over Inheritance

You must have heard of “protocol oriented programming” by now. Have you heard what Crusty had to say? (Or if you want a quick read, here’s a good one.) When looking to pick a Swift open source component, it’s very important to look for one that prefers composition over inheritance. It should be in the forefront of your mind when looking to pick a Swift open source component. Think though how you would use the component? Look at the example usage. Does the component require you to subclass something in order to use it? Does the component require you to override base implementations of a super class in order to customize behavior? If so, steer clear. This is a sign of an inheritance-based customization model. Instead, look for projects that provide behavior customization through protocol conformance. Look for Swift open source projects that require you to compose the component as a variable rather than subclass something. These are signs that the project has already made an effort to code in the Swift way, rather than hang on to techniques of the past.

Date of Most Recent Commit

This is an easy one to measure. Simply look at the date of the most recent commit in the project. There’s no hard and fast rule that says the most recent commit should be within X number of days, but it shouldn’t be so old that the current version(s) of Swift or Xcode aren’t supported. Additionally the date of the most recent commit is also a good quick representation of how active the project is under development. If the most recent commit is months old, yet there have been many recent Issues opened with no response from the author, that’s not a good sign.

swift open source component

History of Past Commits

Aside from the date of the most recent commit, it’s also a good idea to peak at the history of past commits. While the most recent commit could be a couple days ago, that could be the first commit in an entire year. That’s not good. It’s good to look for a steady stream of commits. A large number of commits can be a double edged sword as well. If you observe a large frequency of commits, that can also mean that the project has not matured to a stable state yet. And additionally, if not paired with a solid release versioning strategy where designated “releases” are indicated as such, a high frequency of commits can indicate instability of the current code base without a clear designation of when the last “stable” commit was.

Popularity Among The Community

A popular project is a sign of a healthy project. The more people using a project, the more likely it will be that the project will be up to date to begin with, and also stay that way. Github makes this easy. Two things I look for to evaluate popularity are: number of Stars, and number of different committers. These aren’t steadfast measures though. Many popular projects only have a single committer. Just things to peak at. It’s unlikely that a project has widespread community support if there are a small number of Stars and a single committer.

swift open source component

Dependency Manager Support

There are three popular iOS dependency managers available today, and each has a different level of maturity: CocoaPods, Carthage, and Swift Package Manager. If you haven’t used any of these, or are unfamiliar with what a “dependency manager” is, you should absolutely stop right now and go try one out. They will change your life, especially if you routinely use third party code in your iOS applications. When evaluating a Swift open source component, it’s always a good idea to check whether the project has already provided support for at least one of the dependency managers. This is a good indication that the project is mature, and also has at least a minimal release versioning strategy. Those familiar with the tools above will know to look for a Podfile, a Cartfile or a Package.swift file. If the project doesn’t have this it’s not the end of the world, you can be the first to take action with the author to attempt to move the project in that direction. Use the author’s willingness or responsiveness as a followup indicator of whether you want to build close ties with the project.

License

If there was one personal choice amongst this whole list, this is it. Everyone needs to choose for themselves which open source license is appropriate. The only unacceptable red flag to steer away from in a Swift project on the web is to have NO license.

Tests

It wouldn’t be the Clean Swifter blog if there wasn’t a pitch for tests. Unfortunately, this is probably the least likely thing to find in open source projects. Don’t consider it a hard requirement, but consider it a HUGE bonus if the project has tests. It’s an even bigger bonus if the tests are connected to a public continuous integration build process (like Travis or BuddyBuild) with an indication of test results in the README.

Proper Versioning

This is another style of icing on the cake, and may have varied levels of important depending on the popularity and size of the project. Sometimes for smaller projects, the HEAD of the master branch can be consider the most recent “release.” That can get sticky though, because it may require you to manually keep track of which revision you are using in your project. It also leaves it open to interpretation the advertised stability of the current revision. A solid versioning strategy indicated by the Releases view in Github is a good indicator of a well maintained project.

Maintenance Ownership

Finally, the last thing to consider when getting in bed with a Swift open source project is how maintenance of the project is handled. How many different people have committed to the project? How many open Pull Requests are there for the project? Are the Pull Requests stale, or actively under collaboration? How many open Issues are there? Are they under active collaboration? Does the owner of the repository even allow others to collaborate? Your guaranteed to eventually find something you’d like to tweak when using a Swift open source component. Make sure that you have an idea from the start of how you would ultimately get that tweak in place when the time comes.

README

There’s something about well polished documentation that gives a shine of professionalism on Swift open source components. For GitHub projects, this is often in the form of the README. It’s front and center when looking at a project. If the README is thorough, up to date, typo-free, and well formatted, that goes a long way to indicate the quality of the underlying code. If the README is empty, wrong, or sparse, that’s a red flag. Also, look beyond the README into the other documentation. Take a peak a commit messages and documentation in the code itself. Is it well documented?

Wrap Up

Even with the most rigorous of evaluation of Swift open source components, you should make careful architectural decisions and design choices so that the coupling between your code and the third party code is loose and easy to be changed. This is a hard lesson to learn if you don’t do it. And don’t forget, the best thing about open source code is that you can see the actual source! Beyond anything else mentioned in this article, feel free to dive down into the source and make an evaluation of the code itself. After all, you can code too.

What’s missing from this article? Are there any other tricks that you use when picking a Swift open source component?

Happy cleaning.

PS – If you use CocoaPods, the team has done a lot to automate much of this list in the form of their Pod Quality Index. You can get a quick summary of the overall quality of any given CocoaPod. Here’s an example for Alamofire. Here’s the documentation on how it is calculated.

Weekend Reading for August 19, 2016

Weekend Reading for August 19, 2016, click here

Happy Friday fellow Clean Swifters. Who’s watching the Olympics? There’s something that professional software engineering has in common with professional sports: practice makes perfect.

How do you practice your craft?

Reading is a big part of how I stay up to date, and I use the weekends as catch up time. Here’s what I’ll be reading this weekend.

Get “Weekend Reading” delivered in your email, as well as every other cleanswifter.com post, and receive a free screencast on iOS automated testing by signing up here. “Weekend Reading” is created through AWeber’s app, Curate, which I helped create and is entirely written in Swift.

Happy cleaning

XCTest Target Membership Rule #1

I just had to learn a lesson the hard way, and wanted to pass on to you what I’m going to call the XCTest Target Membership Rule. It took some head banging of mine to discover this rule, and I don’t want you to go through the same pain.

The XCTest Target Membership Rule

The actual implementation files for your app should not be included with the Target Membership for your XCTest target.

xctest target membership

If you were to check the box next to TestStaticTests you would start to see this error in the Console when running your tests:

objc[14049]: Class ViewController is implemented in both <path cut>/TestStatic.app/TestStatic and <path cut>/TestStaticTests.xctest/TestStaticTests. One of the two will be used. Which one is undefined. 

The runtime for XCTest is telling you that it has found the same class defined in two places, the two targets for which you specified the file should be included. And furthermore, you’re also being told that the behavior with regard to which implementation is used will be “undefined.” The funny thing was, I actually found this error message to be misleading. I found that in practice, both copies of the implementation are actually used if you can believe that!

Here’s an in-depth question I posted on StackOverflow documenting the odd behavior I noticed, and included a sample project demonstrating it as well.

Background

These past few weeks I’ve been working on an older project, specifically AWeber Stats. If you notice, that app hasn’t been updated since April 2015, that’s a while. As a result a lot of the dependencies were out of date, so one thing the team set out to do was update the dependencies, and CocoaPods seemed like a good place to start. We were previously on version 0.34.1 and planned to update to 1.0.1 (which at the time of this writing is the latest version). We use Ruby Gems to manage the dependency versions for CocoaPods specifically. This allows us to have per-project control of which version of CocoaPods end up being used. This gives us the reassurance that we must explicitly designate the desire to update a given project’s CocoaPod’s version, and thus accordingly test and verify the update.

I move forward with the update, bumping the version of CocoaPods to 1.0.1 as defined in our Gemfile. CocoaPods 1.0 actually defines a new schema for Podfiles so I subsequently migrated the Podfile to the new format, and successfully ran pod install. Everything has gone smoothly up to this point. Then I opened my Xcode workspace and attempt to run our test suite.

100s of failures.

In addition to the failures, I saw many instances of that Console warning from earlier:

...One of the two will be used. Which one is undefined.

Now the thing is, remember, at this point I hadn’t yet discovered the XCTest Target Membership Rule. And as it turns out, nearly every implementation file in the project for the app target, also existed in membership for the test target. And in fact, as I dusted the cobwebs off of my mind, and thought back to the original work on the project, I specifically remember needing to designate those implementation files as having membership in the test target. Specifically, it was errors like this that would appear of the class under test was not part of the test target:

Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_MyArrayController", referenced from:
      objc-class-ref in MyArrayControllerTests.o

So where did the need to include that file with the test target go? Why was Xcode now telling me that I shouldn’t include these files with both targets?

Well I never got to the bottom of it. I have two guesses at this point: something either in Xcode, or in CocoaPods changed to modify the behavior how XCTest integrates with the classes under test.

Closing Thoughts

I’m still digging to get to the bottom of this. In the meantime, I will not forget the XCTest Target Membership Rule. A couple other lessons surfaced:

  1. Don’t wait to keep your project up to date – It’s easy to launch an app on the store, or hand it off to a client, and semi-forget about it. The app is live, attracting customers, and functioning well. Just remember, at some point it will either need to be updated or die. And the longer you wait, the harder it will be to bring it up to contemporary standards. It’s much easier to make more frequent small changes, than wait 15 months, return to an unfamiliar code base, and try to bring it up to speed.
  2. Know your tool chain – I’m still not fully aware of what changed between the last app update and today such that such a fundamental piece of project functionality changed. I’m taking this as a kick in the butt to get my head wrapped around third party dependencies being used. And if you can’t do that (for whatever reason – time, complexity, interest, etc.), don’t use them. There are plenty of ways to manually install third party code, or even write it from scratch. Of course other people have already invented the wheel, just don’t blindly use the tools without a foundational understanding of how to troubleshoot them when they go wrong.

Happy cleaning.