[et_pb_section bb_built=”1″][et_pb_row][et_pb_column type=”4_4″][et_pb_text]

When you set out to build your next custom software project, be it a web app, mobile app or API, cost is and always should be a concern. Custom software projects are almost always accompanied by a substantial amount of development hours to bring them to life, the cost of which can be a hard pill for cash sensitive startups, entrepreneurs and organizations to swallow. So you’ll likely find yourselves faced with the question: do I hire local or outsource overseas?

Today, we’ll be discussing the details of overseas development and why a local software team can often save you in the long run.

Communication, Communication, Communication

In our experience, a project’s success often hinges on successful communication between the client and the development team.

Yes, practical details such as time zones and modes of communication are important (Can you pick up the phone and call the development team? What about a face-to-face meeting? Will your questions be answered in an acceptable amount of time?), but beyond the nuts-and-bolts, it’s important to place value on the ability for your development team to truly understand your project. Do they understand what you are asking to be built? Does the team understand your overall strategy for the app? Are they able to push back and offer alternative solutions or advice during technical challenges?

Building a custom app is rarely a cut-and-dry project and quality communication as your big idea is being brought to life can make all the difference.

Total Cost, not Hourly Rate

It almost goes without saying but is still important to mention here that when considering the dollars and cents of the development team you hire, think about what the total cost will be, not the hourly rate.

An hourly rate of $150+ for an experienced local developer may seem like a lot when compared to an overseas developer charging one-third of that (or even less), but take the time to consider the value that can be provided during that hour. An experienced local developer may work more efficiently and avoid many more pitfalls than a potentially inexperienced overseas developer. In the end, you may find yourself coming out even or ahead by staying local.

Quality of Work

Building a web app or mobile app is no easy task. Besides the strategy of the app itself, you’re also juggling marketing, revenue models, operations and more. The last thing you want to worry about is the quality of the work you’re paying for.

At Oak City Labs we know the value of quality assurance, continuous integration and automation, which shows in our final product. Whether you’re working with a team based locally or overseas, it’s incredibly important that you feel confident in the quality of the work being produced. When your app has its public launch in the app store and you see hundreds and thousands of downloads that first day, you won’t want to find out at that time that the quality is far less than you expected.

As you are evaluating the quality of any software team (local or offshore), consider the following questions:

  • How often is the software team going to provide beta releases so you can review and test? How soon during the development phase will you see these?
  • Who on the development team will you be talking to during the project? Will you be able to speak with the developer working on your project? Does the team provide regular status updates or weekly reports reviewing progress?
  • Will you have access to the code base (even if you aren’t technical) should your relationship go awry?
  • What is the software team’s experience with the release process? Have they successfully released projects to the App Store, Google Play Store, etc.? Do they have a tried and true method they follow for QA, bug fixes and releases?
  • What is their philosophy on building products from scratch vs. using existing third party libraries?

If you’re looking to get started on developing your custom app idea and need help navigating the pros and cons of working with a software team locally vs. overseas, we’d love nothing more than to chat with you further!

[/et_pb_text][/et_pb_column][/et_pb_row][/et_pb_section]

If you’re in the process of preparing to release an app into the Google Play Store, you may find these quick tips helpful.

Package Name

Before releasing your app into the Google Play Store, you should review and confirm your app’s package name. It cannot be changed once the app is released. The package name looks something like “io.oakcity.appname” and is your app’s unique identifier on the Google Play Store and on Android devices. For the most part, it is not visible to users, but it is in the URL for your app’s listing on the Play Store. That means a user may see it, but it also means it can affect SEO and your app listing’s discoverability. You’ll definitely want your app’s name included somewhere in the package name.

Discoverability

Discoverability of your app may be challenging at first. Searching your app by name in the Google Play Store may not yield your app anywhere in the search results right away. More installs, ratings, and reviews will of course help, but you should make sure your app’s description and all other text content in the app listing contains relevant keywords as well. There is a ton of content on the web detailing ASO/SEO (App Store Optimization / Search Engine Optimization), this post provides a good overview.

Automation

You can automate the process of uploading builds to the Google Play Store (as well as generating your apk, running tests, and a whole host of other things) with a tool called Fastlane. Specifically, the supply tool can be used to upload your apk to any track (alpha, beta, or release) along with store listing description and other text content, images, and even app screenshots.

The App Store is huge. Open the Store and you’ll have more than 2.2 million apps to choose from. Getting noticed when you’re a little fish in a giant ocean is one of the hardest challenges when launching a new app. One way to leverage your fledgling, but growing, user base is to help them spread the word by sharing your app with their friends. And one of the easiest ways to do that is by providing current users with a way to link directly to content within your app using Universal Links.

What are Universal Links?

Imagine you’re a user named Yoshi64 using our new app called Kart2K. You might have a profile page with a web address like http://Kart2K.com/users/Yoshi64. We can make this a Universal Link by giving our Kart2K app permission to handle links for our app’s website Kart2K.com. Now when an iOS user taps on a Kart2K.com link, iOS will open the app instead of opening Safari. Tapping on Yoshi64’s profile link will open the Kart2K app and show Yoshi64’s profile, making the link Universal! iOS users who already have the app will be taken straight into the native app. Those who don’t have the native app on their device will be directed to the web page.Since that’s a pretty high-level overview, let’s answer the question of how does this work in practice? As detailed in the documentation from Apple, there are two steps to making your app and website support Universal Links. First, on your website, you need to add an app association file. This is a simple file that enumerates which parts of your website should be handled by an app. The sections of your website are defined by matching paths – so basically subtrees off the domain name.  The corresponding apps are defined by their bundle id. You could specify several apps that were responsible for handling different sections of your website. In practice, you typically would only have one app, but there may be some sections of your website (marketing material, support forums) that you still want to behave as normal web pages. You also need to add an entitlement to your app that advertises which domain the app supports for opening Universal Links.

When your app is launched in response to a Universal Link, iOS hands the app an NSUserActivityObject which contains the universal link.  Your app will need to be able to extract the link from the user activity and display the corresponding data. NSUserActivityObjects are also used for registering activity with Spotlight. This lets your app data show up in Spotlight searches which drives user engagement. Supporting a universal URL scheme and activity objects allows your app to easily adopt several discoverability features in iOS and is well worth the development effort.

So now you’re all set. Your app is primed and ready for Universal Links! Ship it!

What Could Go Wrong?

No Plan Survives Contact with the User

When you open a Universal Link in the app, iOS shows a button in the top right to open it in Safari instead.

If your user taps that link, it disables Universal Link support in your app! All future links will open in Safari instead. This is quite disappointing because it’s so easy for a user to do. A simple tap to see where that button goes now disables the entire feature. Now when you tap a link, you go to the website without a clue that you should really be in the app. If the user scrolls the web page back up, a link back to the app is revealed, but it’s certainly not obvious. Hopefully the user will stumble upon it.

Special Cases Galore!

iOS only respects Universal Links in some cases. Behavior depends heavily on context.

If you tap on a Universal Link in Safari, it works. If you copy and paste a Universal Link into Safari’s location bar, you get the web view. If you scroll the web view up, you get the hidden “Open in App” link like above, but it’s unlikely the user will discover it.

If you tap on a Universal Link in a Safari View Controller screen, it works, but if you programmatically open a Safari View Controller with a Universal Link, it doesn’t cause the app to open. Instead you get the web view, with no option to open in app.

Most third party apps use a Safari View Controller for links.  If you post a Universal Link in Slack and a colleague taps it, Slack opens a Safari View Controller with the link, so you only get the web page again, with no option to open in app.

This all makes it very difficult for third party apps to offer strong support for Universal Links, even the ones that are really trying to “do the right”.

And the Special Snowflakes

At some point hopefully Apple will fix this problem with Safari View Controller and all those third party apps will suddenly play nicely with Universal Links. However, there are always holdouts — the special apps that feel they need to provide their own custom in-app browser.

The big standout here is Facebook. Facebook’s in-app browser is completely custom, likely to retain their ability to track the user for profiling and advertising purposes. Regardless of the reasons Facebook implements its own browser, it doesn’t support Universal Links.  Facebook always opens the link in a web browser rather than redirecting to the app. If you tap the button to “Open in Safari”, iOS takes over and the link opens in the target app, but that step is a bit obtuse for users, so the experience is confusing, to say the least.

Since our goal is to allow users to share direct links to content and improve the viral growth of our app, the lack of support from Facebook is quite disappointing, since it’s a primary (if not the only) means of sharing for many users.

There’s a company called Branch that has a whole platform for linking content. They’ve got a lot of great content about which apps that work (and sometimes work) with Universal Links. We haven’t used their product but they have an interesting turn-key solution for all your deep linking needs.

Universal Links in iOS 9 and later are a great way to increase sharing in your app and put your users to work, recruiting their friends into your app’s user base.  It’s a win-win scenario, where you get more users and your current users can share links directly to in-app content they want to share.  Adding support for Universal Links in your app also opens up integration with other iOS technologies like Spotlight Search and Handoff. There are a few gremlins to keep an eye on and sharing via third party apps can be a bit hit or miss, especially with Facebook, however, all in all, Universal Links are a great way to provide a positive experience to your users and share relevant useful content to prospective users.

As a web and mobile app development shop, we love to talk about technology choices. Many people don’t really care what technology solution is used to solve a problem as long as the problem itself gets solved. And that’s OK in the “Wild West” days of a startup. However, as a business matures, sometimes the technology choice will hinder you during the growth phases. When a business reaches a certain scale, they will often end up rewriting the entire application. It’s not always avoidable but we like to try our best to manage the risk of a full rewrite later on.

At Oak City Labs, we approach technology choices with what we like to call a “sniff test.” It’s called a sniff test because it’s brief and not all encompassing. It’s also not meant to delve into great detail since we aim to make timely decisions looking at trends. This sniff test is very much business oriented, which really ought to be the driver behind most of your choices. It’s also why we don’t recommend cross-platform development and why we don’t throw the latest Javascript framework into production heavy work. That’s a whole other discussion which should be aided by beer, wine or your calming beverage of choice (Mt. Dew counts!).

Sniff Test Quiz

1. How long has the language or technology been around?
We’re not looking for the most mature, but we like to see longevity for projects and languages. This tends to influence answers for the rest of our quiz.

2. Is there widely available support, including forums or consultants?
This is very related to #1. Is a fix at 2:00 am in the morning just a Google or Stack Overflow search away?

3. For open source projects, how active is the community?
When was the last commit? How often are releases? How many contributors?

4. Is there support from scalable cloud services like AWS and Google Cloud?

5. Can we easily and readily hire a developer with little ramp up time?

6. Is the project or language trending up or down?
Not always a perfect measure but can be telling. Google Trends and Stack Overflow can help with this analysis. Again not perfect but it’s what we’ve got without in depth technical analysis. Here’s an example over the last five years between three prominent languages.

7. Was the project or technology bought or started by a large company?
This can be a good thing but we tend to shy away from backend service providers that might get shut down as Facebook did with Parse. Our preference is to build an app so the full stack is modular and not reliant on a single provider.

Ultimately we want to make choices that will provide long term growth and scalability for our clients. For example, while PHP may be a great choice for some niches it might be tough to hire in your local area for a PHP developer or it could even be on the decline in usage. And sometimes we’ll use a technology for a small part of an app but not for the whole application. For example, a database like MongoDB might be good for caching trivial data but we wouldn’t use it for mission critical features of an application.

We also like to choose technologies that fit business cases. Let’s say a company is in the life science market and will be performing data analysis. We would likely recommend Python because it’s somewhat mature and has all the science and math support needed for detailed analysis. It’s also widely used by the scientific and research community. If you’re in the Fintech space, you might choose Microsoft products because of the enterprise level support and prevalence of .NET developers already in finance.

The sniff test still remains the same when considering long term viability of the technology stack regardless of the market or software application. It doesn’t mean all of your choices, or ours, will be correct up front, but it does mean you can help manage the risk. If you’re thinking about an idea for a web or mobile app, contact us today and we can discuss performing a sniff test (and more!) for you.

We’re in the thick of testing on a large project right now. It’s a (delicious!) new release that we can’t wait to share more about later this summer. While it goes without saying that any release, big or small, should be thoroughly tested, you can often find yourselves in crunchtime near the end of a project. That crunchtime can lead to the choice between meeting a looming deadline and thorough quality assurance. Today we’re sharing all about testing and why it’s so important for your mobile app’s success.

Testing 101

When we talk about testing your mobile app, we aren’t just talking about making sure all the buttons work. Thorough testing goes well beyond that!

At Oak City Labs, we begin testing as early as possible in the development process. We’re an agile shop, so we place a lot of value on getting a (semi-)working version of the app in front of our clients for review as soon as possible while development is still in progress. As soon as we have a working, somewhat functional mobile app ready, testing begins.

Our testing process is just that: a process – a very detailed and thorough process. Armed with our trusty QA Checklist, we thoroughly test the mobile app inside and out. We try to break it in as many ways as possible (better now than when in production!). We work through each and every screen in the app comparing it with the designs, testing it against our use cases, proofreading copy and looking at scrolling and swiping behavior. We check how the app integrates with other apps, we test push notifications, observe screen orientation and more.

I said before that we test each mobile app inside and out. More than just a common phrase, we really do test inside our mobile apps. On the “inside,” we evaluate performance by testing battery usage, install/uninstall process, loading, network connection and the list goes on!

We also place priority on testing the app from the perspective of a first time user. As we near release, it’s all but certain that we’ve been using and testing the app for months. It’s important to take a step back and evaluate the app with fresh eyes to make the user experience for those who interact with it for the first time is optimal.

Why It Matters

You may be saying, “Wow, that seems a lot of work! Is it really worth it?” The answer is YES! Statistics tell us that about 25% of users use an app once and then never use it again. Add in crashes or a mediocre performance experience and you are sure to see that percentage rise.

Trying to break into a crowded market? There’s no easier way to differentiate yourself – in a bad way – than with an app riddled with bugs and performance issues. We’ve shared before about the importance of reviews for your mobile app and negative reviews left by customers frustrated by an untested app aren’t a great way to start.

Testing matters. At Oak City Labs we place high value on thorough and complete testing before a mobile app’s release. If you are looking to create a mobile app – one that is sure to be thoroughly tested – we’d love to hear from you!

Welcome back again to this series! Over the past two weeks, we’ve reviewed a checklist of necessary steps to take before launching your next iOS app. From your Product Page listing to marketing your app, if you’ve been following along, chances are, you’re off to a good start. Today, we’ll wrap up the series as we talk about what happens after that momentous launch into the App store!

Reviews and Analytics

Just as you would with a website, implementing, monitoring and learning from your iOS app’s reviews and analytics is a critical part of a successful app, both at launch and in the long term. Knowing how customers are using (and not using) your iOS app will provide valuable information and should influence decisions throughout the app’s lifecycle.

  • Define Success Metrics: Take time to think through what metrics would indicate to you that your app is a success. Is it a high number of downloads? A specific revenue amount? Engagement through daily active sessions? The answer will vary based on your business model. Once you have those success metrics defined, you’ll have a clear path for how to integrate, measure and review your analytics moving forward.
  • Integrate Analytics: Luckily there is a host of options available for integrating analytics into your app. While there are plenty of options to choose from, we always like to share the following with clients. Running the gamut from basic analytics available in iTunes Connect to heavy hitters like Mixpanel, the following services are a great starting point as you begin the selection process.
    • App Analytics from iTunes Connect: For basic info about your iOS app’s sales, usage, crashes and app store presence, definitely look into App Analytics from iTunes Connect. It’s free (yay!) and they are always adding new features, however, it’s important to note that most of the information is fairly basic and if you’re looking for an in-depth report, you’re going to want to explore one of the other services we discuss below.
    • Fabric Answers: A step up from iTunes Connect, Fabric Answers (via Crashlytics) is a great solution for those looking for more details. It’s also free and allows you to track common events such as sign-ups, logins, purchases and more, all in real time.
    • Mixpanel: If you’re ready to take your analytics game to the next level, consider Mixpanel. They have a free version, but you’ll most likely need to upgrade to the paid subscription as your app launches and grows. Mixpanel’s strengths lie in the details in that you can track where users are dropping off in your funnel, send push notifications to specific user groups (say users from Raleigh who haven’t visited your app for two weeks), powerful A/B Testing, in-app surveys and much more.
  • Reviews: We all know that once your app has launched, the story doesn’t end there. To have a sustainable app for the long haul, you have to constantly improve features behind the scenes. Be aware of what users are saying on social media and the ratings/reviews about your app. Their feedback will show you what features most resonate with users, as well as where your pain points lie. Don’t allow (sometimes) harsh criticism to fall on deaf ears. Consider what you can do to improve the feature: is it through a better workflow, different positioning, bug fixes?

After launching your app, set specific times to review your app analytics against the success metrics you established. Note where people are spending the most time, what trends you see in user flow through the app, how your daily active users and monthly active users stack up against your goals, etc. Taking time to review your analytics and customer feedback will show you how to plan for future releases.

We hope these past few weeks have been helpful as we’ve reviewed all the basics of preparing to launch your iOS app. If you’re in the process of creating your own app, we’d love to chat with you!

NinePatch drawables in Android offer a way to create resizable bitmaps that only stretch the sections of the image that you specify. This is useful for creating backgrounds for TextViews, Buttons and any view whose size may vary depending on the content, as well as when creating splash screens that have a logo whose aspect ratio you don’t want to be distorted.

NinePatch drawables consist of the original image surrounded by a one pixel border of empty pixels by default. The top and left side one pixel border is used to specify (with black pixels) what vertical and horizontal slices of the image can be stretched to make the image to fit its container (instead of simply stretching the image and changing its aspect ratio). This way areas of the image with content you do not want to be stretched can remain at their original aspect ratio. The bottom and right side one pixel border is filled in with black pixels to specify the area of the image that any content that sits on top of the image should reside in (essentially, the padding for the view that this image will serve as the background for).

The following is an example of a NinePatch image:

The black sections of the top and left one pixel border are circled in red. The logo in the center will maintain its aspect ratio while the vertical slats designated by the top one pixel border will be stretched horizontally and the horizontal slats designated by the left one pixel border will be stretched vertically. When two or more stretchable slats are specified for a dimension as above they will maintain their size relative to each other when stretched (so the logo will stay centered).

It is important to note that if you don’t want to specify the content area (the padding) and would like content to fill the entire image, you should fill the right and bottom side 1 pixel border with black pixels as in the example above. If the content area is not specified (the bottom and right sides consist of only empty pixels), the content area will default to the area designated by the top and left side one pixel border.

Android Studio has a tool to generate and edit NinePatch drawables. To access it, right-click on your image file in the Android Studio file browser and find the “Create 9-patch file…” option. You’ll want to give the new 9-patch file a unique name so it doesn’t conflict with the existing image resource (or just delete the original). Now find the newly created NinePatch image (it will have “.9” prepended to the file extension, i.e. your_image.png becomes your_image.9.png) and open it. A full tutorial for the Android Studio NinePatch editor can be found here.

Welcome back to this series! Last week, we started walking through a checklist of necessary steps to take before launching your next iOS app and reviewed all the details about your Product Page listing. Today we’re discussing how to effectively market your iOS app.

Marketing Your App

Before you even launch your app and long after its first release, marketing should be a top priority. The more awareness you can bring to your idea, the more users you’ll see downloading your app. Consider the following as a part of your core marketing strategy.

  • Website: Your online presence can begin with a simple landing page. Start by claiming your app’s domain and setting up a basic website with a contact form, social media links and a short description. From there you can expand with more content as you have it. Use your website to collect leads from interested users that would make good beta testers or want to be notified when the app hits the market.
  • Social Media Channels: Twitter, Facebook, Instagram, Tumblr, LinkedIn…the list goes on. Think through the social media channels your target audience are using regularly and start building a presence there. Before launching your app, use social media to share updates, behind the scenes details and sneak peeks, as well as solicit feedback and ideas on features. As you near your launch date, you should use social media to build hype and excitement for the big release. And once the app launches, remember to continue monitoring your social media to drive downloads and respond to customer feedback.
  • Press Kit: Depending on your marketing strategy, a press kit may or may not be a necessity. If you plan to pitch your app to get press coverage leading into your launch, a press kit is a must-have. Your press kit should be a one stop shop for bloggers and journalists who you want to cover your app. Make sure to include visual assets like your app’s logo and icon (in all sizes, resolutions and file formats), as well as screenshots and a demo video if you have one. Content such as your app’s description and basic business information (launch date, price, platform, etc.) is also essential to include. Remember your goal is to make easy for someone to want to cover your app.

Join us again next week as we close our series talking all about app analytics – a crucial step for long term success! Update: the series continues here.

Last time on Pragmatic Dependency Injection in Swift, we discussed the horror of global variables and the duplicity of singletons, globals in disguise. Dependency Injection (DI) can help us avoid these pitfalls, but how do we implement DI in Swift without incurring a prohibitive amount of overhead? To find out, we join our regularly scheduled blog post, already in progress…

DI in Swift

So, DI is awesome. Now I want to use this in my Swift project. Let’s consider a standard mobile app. You might have a whole list of objects that had been singletons in the past. Some devs like to call these Manager objects.

  • LocationManager — keeps track of GPS coordinates
  • DataManger — handles data storage
  • ApiManager — coordinates communication to a server
  • LogManager — aggregates debug/error messages to multiple destinations
  • NotificationManager — receives and interprets APNS notifications

And that’s just the tip of the iceberg. In a current project, I’ve got fifteen of these manager style objects. With DI, we need to pass these down through our object hierarchy, but all those init() methods start to look a bit cumbersome with fifteen arguments. Maybe we could just pass what’s needed? That’s a good idea, except the table view cell ten levels deep in the view controller hierarchy suddenly needs access to the LocationManager. You’ll have to create a path to pass it all the way down through the full view controller tree.

So we’ll need to pass everything down, but clearly it’s too cumbersome to do that for each Manager. Also, if you add a new one, you’d need to update a ton of code. We need some kind of Manager holder to encapsulate these into one object that can easily be passed through our application. I like to think of it like a drink caddy that holds multiple bottles of sweet cherry goodness.

Now that we’re moving away from singletons, we’ll change the name from Manager to Controller. Our container object is really a Controller for Controllers, so we’ll call it a MetaController.

Show Me the Code!

Let’s talk about semantics for just a moment. When I say we’re moving away from singletons, I mean the “singleton pattern” of an object that guarantees that it’s only instantiated once and accessed through a static method, like a global variable. In most cases, our Controller objects in the app are single instances, but they are created like normal objects and explicitly passed around via the MetaController. Nothing prevents you from creating more than one of the controller objects, but it’s just not necessary in most cases. If you do need more than one, you have that option.

Back to the MetaController. Here’s what it looks like in basic form.

class MetaController {
    var locationController: LocationController? = nil
    var logController: LogController? = nil
    var apiController: ApiController? = nil 
    var dataController: DataController? = nil 
    var notificationController: NotificationController? = nil 
}

And that’s it! Okay, it’s just the beginning. Like other components in the system, the controllers themselves often need access to the other controllers in the system. For example, the ApiController needs access to the LogController to log network issues connecting to the server. To make this more convenient, we add a little didSet action in the MetaController to pass the MetaController itself to the payload controllers.

class MetaController {
    var locationController: LocationController? = nil { didSet { passController(locationController) }}
    var logController: LogController? = nil { didSet { passController(logController) }}
    var apiController: ApiController? = nil { didSet { passController(apiController) }}
    var dataController: DataController? = nil { didSet { passController(dataController) }}
    var notificationController: NotificationController? = nil { didSet { passController(remoteNotificationController) }}

    func passController(target: AnyObject?) {
        if var target = target as? MetaControllerConsumer {
            target.metaController = self
        }
     }
 }

Here’s our first glimpse of the MetaControllerConsumer protocol. This swift protocol is adopted by every object in our system that uses the MetaController. The basic definition is super simple and just declares that the consumer will have a place to store the MetaController

protocol MetaControllerConsumer {
    var metaController: MetaController? { get set }
}

And that’s all that’s necessary, but we want to make this easy to use as well. Every time we access the dataController, it would be a pain to type metaController?.dataController. The great thing about Swift protocols is that you can add default implementations for protocol compliance. This lets us expand the properties required by the protocol, but also define default implementations of synthetic properties to fulfill the protocol requirements. That’s a mouthful. Here’s what that looks like:

protocol MetaControllerConsumer {
    var metaController: MetaController? { get set }
    var locationController: LocationController? { get }
    var logController: LogController? { get }
    var apiController: ApiController? { get }
    var dataController: DataController? { get }
    var notificationController: notificationController? { get }
}

// default protocol implementation to return the sub controllers from the meta controller
extension MetaControllerConsumer  {
    var locationController: LocationController? {  return metaController?.locationController }
    var apiController: ApiController? { return metaController?.apiController }
    var dataController: DataController? { return metaController?.dataController }
    var userController: UserController? { return metaController?.userController }
    var remoteNotificationController: RemoteNotificationController? { return metaController?.remoteNotificationController }
}

A MetaControllerConsumer still only has to declare a real property called metaController to hold the container, but can now access the sub-controllers like dataController directly via the default implementation of the computed properties.

We can add more default implementations for other convenience operations too. Logging is a good candidate for these sorts of shortcuts.

extension MetaControllerConsumer {    // Logging shortcuts
    func debugLog(message: String, _ path: StaticString = #file, _ function: StaticString = #function, _ line: UInt = #line){
        logController?.debugLog(message, path, function, line)
    }
    func errorLog(message: String, _ path: StaticString = #file, _ function: StaticString = #function, _ line: UInt = #line){
        logController?.errorLog(message, path, function, line)
    }
}

With this in place, the logging functions debugLog() and errorLog() are now available in every MetaControllerConsumer. By leveraging Swift protocols like this, it’s easy to add general methods in one place that are accessible everywhere.

BTW, the #file, #function, and #line arguments in these functions are tokens that the compiler recognizes and replaces with the current filename, function name, and line number. Adding a debug statement like debugLog("Bazinga!") can print out

LocationController.swift (line 34): updateLocation(): Bazinga!

which is pretty handy.

Another useful function allows us to quickly pass the MetaController to another object, using the MetaController itself to first check if the target object can consume it.

extension MetaControllerConsumer {
    func passMetaController(target: AnyObject?)         
        metaController?.passController(target)
    }
 }

This is especially useful when programmatically instantiating a new object in the code or configuring a child view controller in prepareForSegue().

We load up the MetaController early in the app bootstrap process (from the app delegate’s didFinishLaunchingWithOptions) and pass it down through our object hierarchy. Initialization is really straightforward.

metaController = MetaController()
metaController?.logController = LogController()
metaController?.locationController = LocationController()
metaController?.apiController = ApiController()
metaController?.dataController = DataController()
metaController?.notificationController = NotificationController()

The MetaController is also handed to the root view controller which handles propagating it down through the view controller ranks.

Testing

With the MetaController construct, we reap all the normal DI benefits for testing. For each test, we simply construct a new MetaController, add the controllers that the test needs (replacing with “Fake” subclasses as necessary) and go. This is a little bit of compromise, since we need to know which sub-controllers are required by a class, but it’s a trade-off for the convenience of this proxy model of direct injection. In the strictest sense, we could still provide a fully loaded MetaController if the software under test were truly a black box. In the end, we still have a highly testable framework where we can easily satisfy dependency requirements and create robust, maintainable, explicit test suites.

Solving DI with Swift

Building an app by relying on singletons quickly leads to a mine field of Spooky Action, unintended consequences and unexpected explosions. By moving to a direct injection model, we remove the magic and hidden pitfalls of implicit dependencies and replace them with clear and explicit declarations of dependencies between the components of our app. With the MetaController model and heavy use of Swift protocols, we’re able to encapsulate the overhead of DI in a way that makes it easy and fast to apply DI to our app development process.

At Oak City Labs, we’re always trying to find ways to improve our code’s stability, testability and maintainability. Today we look at the problem of singletons, global state and how to avoid these landmines in the context of Swift.

The Problem

Let’s talk about global variables. Most everyone can agree that global variables are A Very Bad Thing. Globals are undoubtably a code smell and religiously avoided by experienced programmers. Globals are problematic for lots of reasons, but mostly because of Spooky Action At A Distance. If two pieces of code both access a global variable, they can interact via the global variable, often in unexpected and undesirable ways. In this article, Misko Hevery (the Angular guy) dives deep into the many ways this can go pear shaped quickly.

New developers sometimes try to fix global variables by switching to singletons and maintain state within a magic object that is just a static method call away. I’ve heard more than one developer exclaim “Oh no, we never use global variables. We use singletons instead.” The ugly truth though, is that singletons are really just fancier global variables. You still get Spooky Action. You still have implicit and hidden dependencies. Try to write a unit test on a class that relies on a singleton. You can’t look at the exposed interface for this class (think header file) and know about the secret, hidden dependence on that singleton. You must inspect the code and it’s a matter of tedious and confusing mocking of static class methods to try and make this testable. Then write a second test and discover that the tests fail depending on the order in which they run. It’s crazy making!

The most disappointing aspect of singletons is that Apple uses them so often in their own API — UIScreen, NSNotificationCenter, NSUserDefaults, etc. It seems as if they’re encouraging us to use singletons, even when it makes applications fragile and testing difficult.

The Solution — Dependency Injection

“Dependency Injection” (DI) sounds intimidating. And complicated. And scary. People write long, drawn out blog posts about it. But it’s not nearly as intimidating as you might think. At the core, DI just means that you explicitly supply a class with any dependencies, either through initialization or a method call.

Consider this class that uses a two singletons:

class SocialInfo {
    func connectionCount() {
        let twCount = TwitterApi.sharedManager.followerCount
        let fbCount = FaceBookApi.sharedManager.friendCount
        return twCount + fbCount
    }
}

The connectionCount() function returns the total number of connections on FaceBook and Twitter, using the singleton managers to access those two different APIs. But if we just look at the API, it’s not clear that SocialInfo depends on FaceBookApi and TwitterApi. For all we know, it’s valid to write

let count = SocialInfo().connectionCount()

but looking at the code for that class, we can tell that TwitterApi and FaceBookApi need to be set up and configured first. Imagine if this were a closed source library. We would have no way to know about these implementation details. And we shouldn’t have to care about implementation details anyway.

Now think about what it means to test the SocialInfo class. Our tests shouldn’t rely on network resources, so we’re going to have to mock those singletons. I’ve used several mocking libraries and these are always finicky at best. In Swift especially, the mocking libraries are quite young and this sort of thing is still difficult.

Now let’s consider the same class, rewritten a little for DI.

class SocialInfo {
    let twApi: TwitterApi
    let fbApi: FaceBookApi

    init(twitterApi: TwitterApi, facebookApi: FaceBookApi) {
        twApi = twitterApi
        fbApi = facebookApi
    }

    func connectionCount() {
        let twCount = twApi.followerCount
        let fbCount = fbApi.friendCount
        return twCount + fbCount
    }
}

With the updates, it’s clear that SocialIinfo depends on a valid instance of TwitterApi and FaceBookApi. Getting a connection count looks like

let count = SocialInfo(twitterApi, facebookApi).connectionCount()

It’s clear that we need to have a configured instance of the Twitter and Facebook API objects ready to pass in so that SocialIinfo can use them to connect with the services.

And testing is much easier too! Instead of having to build mock objects when can create FakeTwitterApi and FakeFaceBookApi objects that are subclasses of our real objects and just hardwired to return known values for the counts. This is really straightforward, readable, and doesn’t require any mocking.

So that’s dependency injection — simply the idea that dependencies are passed in explicitly rather than pulled out of the ether via some magical singleton or (gasp!) global variable.

Tune in next time for the exciting conclusion and the implementation of pragmatic dependency injection in Swift.