CXO Leaders Summit

 

We attended CXO Leaders Summit in Sydney last week, here are some top line takeaways for those who couldn’t be there.

The event kicked off with Steven Marks, founder of Guzman Y Gomez, talking about how he spun up 80 restaurants in Australia and 94 worldwide. He’s a charming and ambitious Brooklynite, a really scrappy hustler, who arrived in Sydney via Wharton Business School and Wall Street. Got fed up betting on other people’s companies and decided to launch his own. Big focus on brand to start with – notice that their type font is made with black tape, like the cheap and cheerful taquerias in Mexico.

Guzman_y_Gomez_logo.jpg

Also a big focus on culture during the early days – “I look after them, and they’ll do anything for me”. Then, once they’d established the building blocks of great product and culture, they focused on optimisation – remove all the bottlenecks.

Key quotes:

“When did fast food become bad food? We’re gonna take on McDonalds”

“The app took 20% of their orders when it launched, but has been growing quickly ever since.”

“I didn’t even know what CPA stands for – all our marketing is word of mouth, and personal. We want to nurture and cultivate raging fans”

Our take: Culture is king but often fades from sight in large organisations. It takes guts and perseverance to drive impact in large organisations, and it’s virtually impossible without leaders setting the right examples.

__

Then a panel with LJ Hooker, Catch Group and ANZ, moderated by Prudential – How to build a customer centric brand.

Interesting, the person to my right spent the session complaining about ANZ, and on my other side was someone complaining bitterly about LJ Hooker. So it begs the question, what’s the point in doing CX work if it doesn’t affect public sentiment? 

ANZ and LJ Hooker talked proudly about their activities – customer journey mapping, experience walls, customer for life programs and the such. In contrast Catch Group were talking about getting closer to actual customers, and working hard to get the voice of the customer fed back into their actual products (not just design assets).

ANZ and LJ complained about the challenges changing the culture – “Waffle” said the lady to my left. The previous speaker had just illustrated that cultural leadership has to start at the top. In contrast Catch Group are more nimble, and talked about empowering customer facing staff, and hiring entrepreneurial people as a strategic priority.

Our take: Focus on business outcomes, rather than design outputs. Get something in market quickly with feedback loops in place. Design Thinking has it’s place, but Lean UX will more often get you where you need to go.

__

Then a game of buzzword bingo with Genesys. He spoke quickly and said little. #cloud #experience #customers #empowerment #AI #BigData #Uberisation #trends #IOT. Then some very badly designed screens with tiny illegible writing, and a weird voice driven interaction that forced people to juggle between text and web. So much for Digital CX!

Our take: sponsor presentations shouldn’t focus on the sponsor. Pick an interesting topic and let your knowledge speak for itself. Standard presentation rules apply.

Then we were in 121 sessions with some of the speed dating sessions the organisers had set up with attendees. On a personal note, they were great! Pretty much everyone who came to these had a current need relevant to our new Mobile & Emerging Technology positioning. Big thanks to Blake and Nick for the organisation. It did mean that we missed some of the workshops, but we got what we needed out of the event.

__

In the afternoon, Karen Ganschow of nab gave a talk on Customer Life Cycle vs Product Life Cycle which should trump? She observed that what you measure is what you manage. All banks focus on the same metrics e.g. number of products (how’s this for an acronym: CW4P – customers with 4 products!). As a result, propensity models are receiving a lot of focus, but even still only a tiny number of customers are likely to respond to upsell and cross sell overtures. Rule of thumb: let the customer behaviour trigger the focus. Death to propensity models.

Our take: Karen’s an engaging speaker, and it was good to hear some challenging thinking about propensity models. Data and the use of it is simply a means to an end – you still need a great product to drive behaviour. Perhaps her talk focused a little too much on customer journeys and life stages, and not enough about actually shipping software and increasing speed to market / customer feedback loops.

__

For day two, the opening keynote was held by Stephanie Myers of Prudential – Customer Experience and Engagement: How to Build a Customer-Centric Brand. It was refreshing to see a focus on mobile first as a principle and attitude and not just an approach to design. Our customers are constantly connected to the internet and to each other, and this should drive the way we approach the design of services. However the danger is that native apps exist in a very competitive space – the top eight apps are all owned by Google and Facebook, and about half of all apps are deleted within one month of installation. Unless your app offers significant utility and or entertainment, it won’t get used. She recommended focusing on, and designing for, mobile only journeys. Think of desktop as optional – it drives the best mindset.

Our take: We couldn’t agree more! We’ve had clients who want us to build e.g. marketing apps for the top of the conversion funnel and we’ve generally pushed back on this. Think through what value the customer needs via mobile devices for their whole lifecycle, and let this influence the role of web vs native. Rule of thumb: go native for repeat users, and earn their trust and respect to drive the loyalty and advocacy that you’re looking for.

__

Next up was a panel discussing CX: The new battleground for marketing Organisations. All present agreed that a key current trend is a focus on value of advocacy / advocates, and how this ties back into repeat business. It begs the question: Who owns the customer? It’s trite to say ‘everyone’ – better to break it down. Marketing can be the catalyst for improvement, but initiatives and teams driven by the C-Suite can also have a big impact.

The panel discussed ‘voice of the customer’ initiatives – suggested focusing on the positive feedback as much as the negative. For example, “we’re hand writing a note to thank a member of staff after you left positive feedback”. Customers and staff given a boost.

Our take: customer feedback in a native app context is a balancing act. Yes, you want people to rate your app highly in the app store, but ideally you also want to drive advocacy and potentially up-sell / cross-sell / refer-a-friend activity as well. Do too much of this and your customers will become fatigued, so plan this activity with taste and due consideration for your customers’ time. And then track engagement carefully.

One more thing. ‘Who owns the customer?’ is a trite question. If you have to ask it, then your challenge isn’t organisational, it’s cultural. Your whole business needs customers more than they need you, so a better question to ask is ‘How can we all help the customer to achieve their goals?’.

__

Into the final straight now, with a panel on Winning over the skipping generation. Much has been written about millennials and their habits, but it’s rarely constructive. One solid piece of advice came from Chris Dodson, Head of Marketing for Youtube, who said that authenticity comes from putting creative power into the hands of the creative people in front of the camera. For example,  Casey Neistat is an influencer appointed by YouTube as part of his “Do what you can’t” program. He was given complete creative control over the content, rather than being told what to do by a traditional Creative Director at an ad agency. Interesting.

Our view: Millennials aren’t as unfathomable or fickle as people like to make out. They’re just better at filtering out bullshit. And as this forces companies to deliver actual value on the terms of the customer, I’d say we all benefit from this.

__

Finally, Facebook gave a talk called Eventually, everything connects. Promising title, but it was just Facebook talking about bots. They showed a few case studies where call volumes dropped, but we know the score – while the situation is gradually improving, none of these bots would pass a Turing test. But their handover protocol looked interesting, breaking down the problem and then combining automation tech and conversation tools to make it happen.

Our view: there’s definitely value to be had with bot implementations, but also a danger of over-reaching. By properly understanding the limitations of the technology you can find the right balance between bot and human interaction, the sweet spot where customers will be happy to interact with a human back-up at their discretion. Then you can carefully push the boundaries.

__

That’s all! The main takeaway for us at Bilue is that speed is of the essence. Get a tasteful and respectful product in customers’ hands quickly, and make sure solid feedback loops are in place. Plan product development around this feedback. Your customers will thank you!

An API First Strategy

People say a lot of things about taking a mobile first approach to building their digital experiences, “We absolutely need to be mobile first”, “Consider the customer”, “Build for the devices customers are using day in and day out”.

This is short sighted.

There I said it.

Yes, I am an avid fan of mobile devices, of mobile apps and of the entire smart phone ecosystem that we’ve built up in recent years. Bilue was founded on the back of my passion and enthusiasm for building amazing mobile experiences. But it is patently untrue to state that our technological future hangs on this fleeting interest in everything mobile. Limiting yourself to a fixation on the mobile experience above anything else supposes that mobile devices are and always will be the main touch point for the customer.

Mobile apps are the present, they’re what your customers are using now. Today.

You can ask me what the technology of the future will be, but I will not have the answer. Anyone who says otherwise probably has deeper underlying interests of their own. Hear them out, shake their hand, and then make a break for it. Run for the hills.

People said HTML was the future, the Web was the future, Augmented Reality was the future, Virtual Reality was the future and this list of things that weren’t quite what we made them out to be only continues to grow, into the future. No one really knows what the future holds.

When investing in technology, think as long term as you can. Technologies like ‘The Web’ or ‘HTML/CSS’ are all content delivery technologies. They’re great at what they do and they will continue to be great at what they do, and you will need to continue to invest in them, but they’re client side technologies. By and large the popularity of that technology is not defined by, or decided by you. Your users will ultimately decide where they want to interact with you. If they don’t choose to use the Web, then they won’t. If they don’t want to use an iPhone, they won’t.

This is where APIs (Application Programming Interface) come in. APIs enable one piece of software to communicate with another piece of software. APIs are nothing new, they’ve been used to communicate between software systems since writing software began.

APIs come in many flavours, and as you can imagine, engineers have many opinions about what makes a good API. With everything from SOAP (Simple Object Access Protocol, BTW, if this is the simple version, I’d hate to think what the complex one looked like), to RESTful (Representational state transfer), then there’s the various opinions on RPC and Hypermedia, XML, JSON, and there’s always the cool new kid on the block GraphQL.

This is a complex landscape, but one that with the right direction, and a proper strategy driving it, really opens up the possibilities of what your business can achieve.

Invest in APIs and you’ll find yourself able to react to the needs of your customers faster than ever before. With a good API Strategy you can serve websites, mobile apps, interface with your partners, vendors & clients, create interfaces for things like Facebook Messenger, Amazon Echo, Google Home, Apple TV, Chromecast and even a SmartTV or a SmartFridge. When you provide an interface to connect your software to other software, you create a promising opportunity and potential for your business to exploit. If you want a competitive advantage, develop a solid API strategy today. The only known thing about the future of digital technology, is that software talking to other software will be the driving force behind it.

Issues Faced With Kotlin During Android Development

Kotlin seems like the future of Android development. It is a new statically-typed programming language that runs on JVM, with a very refined syntax and enhanced features. There is a lot to love about it. Kotlin is interoperable with Java, which should reduce the risk of future incompatibility. The additional language features such as Function Extensions and High Order Function make it much more extensible and scalable. The code is concise with data classes, single expression function, infix and many more… enough said. Kotlin is just great!

Screen_Shot_2016-08-10_at_2.10.19_pm.png

I started working on some real apps using Kotlin that have since been published on the playstore. I have to say it was relatively smooth sailing. Nonetheless, there were some hiccups along the way that are worth sharing.

1. Method Count Increase.

Method count increase was one of the issues I was fully aware before starting with Kotlin. At the time of writing, there are an additional 7’191 methods adding to the total method count. This would add more than 10% to the 65k methods limit. Nonetheless, I didn’t worry that much as the MultiDex support is there to help to overcome this issue.

2. Using Libraries that require Annotation.

There are many cool libraries that can assist with making Android Development much more efficient. However, when switching over to Kotlin, using some of them becomes a challenge. There are two libraries which I can’t manage to use directly after switching to Kotlin, i.) Icepick and ii.) EventBus. The main reason is that the Annotation (i.e. @State and @Subscribe) is not picked up by the code. Fortunately, with EventBus, I managed to work around this by creating a composite class object using Java Code. Note that this doesn’t mean all libraries using Annotation would not work for Kotlin. I managed to use Retrofit 2.0 and Dagger 2.0 (where both use Annotation extensively) in Kotlin directly.

3. Mocking Need Open Class/Function.

By default a class and function is considered final for Kotlin. Mocking (using Mockito) requires a non-final class. So in order to have that, we have to explicitly open a class if we would like to mock it for testing. If this is not done, it would error out easily. The more tricky issue is the function. If the function is not open, there would be no error issue when running the test. Instead of intercepting the function, it would call the actual internal function, where the test would fail with NPE. Without knowing the function needs to be open, the root issue might not be easily discoverable.

4. Java to Kotlin Converter Limitation.

The Kotlin Plugin for Android Studio is just great, especially allowing to auto convert from Java to Kotlin. However, the conversion might not be ideal. e.g.

 

is converted to

class SimpleClass(memberVariable: Int) {

  internal var memberVariable = 0

  init {

      this.memberVariable = memberVariable

  }

}

Whereby it could be as simple as

class SimpleClass(val memberVariable: Int) {}

Anyway, it’s always good to review the converted code and explore so that we don’t just have Kotlin code in Java style, without the real advantage of Kotlin.

5. Other Converter Issue.

I love writing a new function from an object, and pressing Alt-Enter to trigger the auto-function creation. If you are writing on the Java side of code, and call a Kotlin function (that you just intended to create), sorry you are out of luck. Android Studio will only auto create that function for you in the Kotlin code.

At times for experimental purposes we would also like to convert from Kotlin to Java, given that it was inter-operable with Java. This is not possible however the tools only allow you to convert from Java to Kotlin and not vice versa. Perhaps this is by design, and I could imagine it would be difficult for Java to handle conversion of more advanced Kotlin language features.

None of these issues are show stoppers. The advantage and fun of learning new things outweighs them in any case. The language features are richer and there is so much to explore. I haven’t really faced many issues from Kotlin’s language as yet. I’m sure I’ll uncover more issues, but I don’t expect them to “kill me”. Java is always there to the rescue 🙂

As with any new thing, one other challenge is finding community support. Suppose you are experimenting with new Android Features and face a road-block. If you post your question to Stackoverflow using your Kotlin code, you are unlikely to generate support.

So… you might as well be the one who supports others… which is in itself a good thing! 🙂

Accurate Apple Device Reporting in Google Analytics

For some reason Google Analytics doesn’t expose a dimension that represents which specific model of iPhone/iPad that the user is using (iPhone 4, iPhone 5, iPad Mini 2, et al). This makes it very difficult to track your mobile users’ usage by specific device type.

This article describes the technique that Bilue uses to provide a comprehensive, accurate, future-proof solution.

Possible Solutions

Firstly, let’s look at a couple of other techniques that are often considered and discuss the shortcomings of each.

Option 1. Raw values from utsname

Apple offers APIs to retrieve the raw identifier (eg. iPhone7,2). For example:

#import <sys/utsname.h>

struct utsname un;
uname(&un);
NSString *identifier = [NSString stringWithCString:un.machine encoding:NSUTF8StringEncoding];

This identifier can then be sent to Google Analytics as a custom dimension.

However, the values returned from this API (eg. iPhone7,1) are not fit for human consumption. Business stakeholders don’t want to see reports containing these values. Not only that, it is virtually impossible to look at the values and know which specific identifiers are related to which physical devices.

This is a technically correct solution, but offers little business value.

Option 2. In-app mapping

This seems to be the most commonly chosen solution, and basically involves the app having a big lookup table that maps the raw device identifier mentioned above into something more readable (eg. iPhone 6 Plus), and then sending this translated value to Google Analytics as a custom dimension.

The big problem with this is that the lookup table is hard-coded into the app at the time the app is shipped. The lookup logic will not know what type of device it is running on for any phone that was launched after the app was released. At that point, it has two choices:

  • Send a generic value like Unknown. In this case, Google Analytics will have a whole collection of events that are all lumped in together as coming from unknown devices. Consider the case when Apple launches 3 new phones… all three phones will be reporting as the same type: Unknown.
  • Send the raw identifier iPhoneX,Y. This is a more technically correct solution in that it doesn’t lose the raw information, however, the output in the reports will continually have to be massaged because it will contain a mixture of human readable device names and raw device identifiers.

Every time new devices are launched by Apple, the only hope for correct reporting is to release a new version of the app and hope that users choose to upgrade.

This is a brittle solution.

Option 3. Screen resolution

Out of the box, Google Analytics does provide a Screen Resolution dimension that contains values like 375x667. At a high level, these values can be reverse engineered to determine roughly what type of device it was based on the following table:

  • 320×480 => iPhone 4 (and smaller)
  • 320×568 => iPhone 5
  • 375×667 => iPhone 6
  • 414×736 => iPhone 6+
  • … plus some other values for iPad

Again, this has problems in the reporting space because the translation of the resolutions to specific models is non-obvious to the casual observer. It also is very general in that you cannot differentiate between, say, the iPhone 5, 5c and 5s.

Data Mapping in Google Analytics

An oft-overlooked feature in Google Analytics is the ability to upload a mapping file that can be used to translate custom dimensions from one value to another. We can use this to our advantage to get Google Analytics to perform the mapping.

Solution Overview

Broadly speaking, the solution involves the following steps:

  • When setting up Google Analytics, a mapping file is created to map the raw identifiers (iPhone7,1) into human readable variants (iPhone 6 Plus)
  • At run-time, the phone sends up the raw device identifier (iPhone7,1)
  • Google Analytics maps that raw identifier into the human readable value
  • Run reports using the mapped human readable version value
  • Profit?

When new devices are released by Apple, the mapping info can be updated in Google Analytics without having to ship a new app.

Another awesome benefit is that Google Analytics will also apply that new mapping info to historical events, so even if you take a few days/weeks to update the mapping info after a new device is released, it will be retroactively applied.

Implementation Details

Creating Custom Dimensions in Google Analytics

We are going to create three new Custom Dimensions in Google Analytics:

  • appleDeviceModel – Contains the raw device identifier sent from the device. eg. iPhone5,3
  • formFactor – Contains a reasonably general description. eg. iPhone 5
  • formFactorDetailed – Contains a pretty exact description. eg. iPhone 5c (GSM)

To do this, click on the Admin tab at the top of Google Analytics, and navigate your way to the Custom Definitions/Custom Dimensions menu for your property. Add 3 new Session dimensions with the names outlined above.

Google Dimensions

Your dimension numbers may be different depending on how many custom dimensions you are already using. Take note of the dimension numbers; you will need them in the next step.

Creating input data

Now you need to create a file that contains the mapping info.

Important: The first row of the mapping file must contain the dimension numbers of the dimensions you just created. The first one is the key (appleDeviceModel), and the next two are the values that will be mapped (formFactor and formFactorDetailed).

For reference, our latest file looks like:

ga:dimension7,ga:dimension8,ga:dimension9
"iPhone1,1","iPhone 2","iPhone 2G"
"iPhone1,2","iPhone 3","iPhone 3G"
"iPhone2,1","iPhone 3","iPhone 3GS"
"iPhone3,1","iPhone 4","iPhone 4"
"iPhone3,2","iPhone 4","iPhone 4"
"iPhone3,3","iPhone 4","iPhone 4"
"iPhone4,1","iPhone 4","iPhone 4S"
"iPhone5,1","iPhone 5","iPhone 5"
"iPhone5,2","iPhone 5","iPhone 5 (GSM+CDMA)"
"iPhone5,3","iPhone 5","iPhone 5c (GSM)"
"iPhone5,4","iPhone 5","iPhone 5c (GSM+CDMA)"
"iPhone6,1","iPhone 5","iPhone 5s (GSM)"
"iPhone6,2","iPhone 5","iPhone 5s (GSM+CDMA)"
"iPhone7,1","iPhone 6","iPhone 6 Plus"
"iPhone7,2","iPhone 6","iPhone 6"
"iPhone8,1","iPhone 6+","iPhone 6s"
"iPhone8,2","iPhone 6+","iPhone 6s Plus"
"iPod1,1","iPod 1","iPod Touch (1 Gen)"
"iPod2,1","iPod 2","iPod Touch (2 Gen)"
"iPod3,1","iPod 3","iPod Touch (3 Gen)"
"iPod4,1","iPod 4","iPod Touch (4 Gen)"
"iPod5,1","iPod 5","iPod Touch (5 Gen)"
"iPad1,1","iPad 1","iPad"
"iPad1,2","iPad 1","iPad 3G"
"iPad2,1","iPad 2","iPad 2 (WiFi)"
"iPad2,2","iPad 2","iPad 2"
"iPad2,3","iPad 2","iPad 2 (CDMA)"
"iPad2,4","iPad 2","iPad 2"
"iPad2,5","iPad Mini","iPad Mini (WiFi)"
"iPad2,6","iPad Mini","iPad Mini"
"iPad2,7","iPad Mini","iPad Mini (GSM+CDMA)"
"iPad3,1","iPad 3","iPad 3 (WiFi)"
"iPad3,2","iPad 3","iPad 3 (GSM+CDMA)"
"iPad3,3","iPad 3","iPad 3"
"iPad3,4","iPad 4","iPad 4 (WiFi)"
"iPad3,5","iPad 4","iPad 4"
"iPad3,6","iPad 4","iPad 4 (GSM+CDMA)"
"iPad4,1","iPad Air","iPad Air (WiFi)"
"iPad4,2","iPad Air","iPad Air (Cellular)"
"iPad4,4","iPad Mini 2","iPad Mini 2 (WiFi)"
"iPad4,5","iPad Mini 2","iPad Mini 2 (Cellular)"
"iPad4,6","iPad Mini 2","iPad Mini 2"
"iPad4,7","iPad Mini 3","iPad Mini 3"
"iPad4,8","iPad Mini 3","iPad Mini 3"
"iPad4,9","iPad Mini 3","iPad Mini 3"
"iPad5,1","iPad Mini 4","iPad Mini 4 (WiFi)"
"iPad5,2","iPad Mini 4","iPad Mini 4 (LTE)"
"iPad5,3","iPad Air 2","iPad Air 2"
"iPad5,4","iPad Air 2","iPad Air 2"
"iPad6,8","iPad Pro","iPad Pro"
"AppleTV2,1","Apple TV","Apple TV 2G"
"AppleTV3,1","Apple TV","Apple TV 3"
"AppleTV3,2","Apple TV","Apple TV 3 (2013)"
"AppleTV5,3","Apple TV","Apple TV 3 (2013)"
"i386","Simulator","Simulator"
"x86_64","Simulator","Simulator"

Importing Custom File

Using the Admin/Data Import menu item for your Google Analytics property, perform the following actions:

  • Create a new Data Set
  • Choose Custom Data
  • Give it a name like Apple Device Identifier to Form Factor Mapping
  • Choose which view you want it applied to (you probably want all views)
  • Click on Next Step
  • Select appleDeviceModel as the key
  • Select formFactor and formFactorDetailed as the imported data.

Your settings should look like the following screenshot.

Google Data Import

  • Click on Save
  • Click on Finished

At this point, you’ve defined how the mapping will be performed but you haven’t loaded any data.

Choose the Managed Uploads option for your newly created data set, and upload the file containing the mapping data. Google Analytics will verify that your data matches what it expects (for example, the header rows match the custom dimension numbers, and the coloumn count is correct). You will notice that the Status field will be temporarily be set to Processing – sometimes this takes a few minutes to change to Completed.

At this stage, the import is successful and the data will start to be mapped.

Posting from App

The behaviour within the app is pretty straightforward. You just need to send the raw device identifier to Google Analytics as a custom dimension (making sure that you reference the correct number). In the example above, the appleDeviceModel dimension is 7.

#import <sys/utsname.h>

struct utsname un;
uname(&un);
NSString *identifier = [NSString stringWithCString:un.machine encoding:NSUTF8StringEncoding];
[tracker set:[GAIFields customDimensionForIndex:7] value:identifier];

Downsides

So far, the only downside with this approach is that the mapped custom dimension data is not available in the Real-Time view of Google Analytics. For us, this hasn’t been a real problem but it is worth mentioning.

And, of course, it is worth mentioning that there has to be a very real discipline of updating the mapping data in Google Analytics when Apple releases new devices. As I mentioned before, though, at least these updates can be made outside of the app release cycle.

Yow! 2015 Conference

On Thursday 10 December, once nothing more than a $10,000 credit card debt and now a Sydney-based technology startup, Atlassian raised $US462 million in a much anticipated Initial Public Offering (IPO). It goes to show that now is as good a time as ever to push forward, break down barriers and achieve something bold.

Australia is an amazing country with a thriving technology industry that is only destined to grow.

At the forefront of this technological growth are Software Developers, Engineers and Technology Architects. The impact of technology on us all is entirely at the hands of these men and women, the systems they build and the problems they solve.

Also on Thursday 10 December, Yow Australia held the Yow! 2015 Conference in Sydney. As a proud sponsor of the largest independent event for software development across Australia, Bilue attended both the Yow! 2015 Conference and Yow! CTO Summit in Melbourne and Sydney.

Attracting the sharpest developers from across the country, the conference is an opportunity to sit infront of a diverse range of experienced, innovative and influential speakers from around the world.

Unlike your off-the-shelf technical conference, Yow! is an event focused on fostering open-mindedness, practical learning and richly engaging discussions. This year’s schedule is split into three well crafted tracks on topics ranging from Cloud Infrastructure to People & Processes, Security, Mobile, Architecture & Design, Languages, Big Data and ofcourse Software Engineering. It includes an amazing line up of well known speakers who have in many ways defined their respective industries, including – Dave Thomas, Kathleen Fisher, Sam Newman and so many more.

While there’s still another entire day’s worth of sessions about to begin, I’ve already seen talks that are going to change my perspective and approach on my work as a developer for years to come.

On Thursday morning I attended Ben Tesse & Sam Ritchie’s ‘Rethinking MVC with React Native & ReactiveCocoa’ which cast quite a unique light on Functional Reactive paradigms through the lense of Javascript’s React Native framework.

I also sat front row during an eye opening, insightful talk by Mike Magruder – ‘Mobile Performance at Facebook’ that revealed the extremly extensive efforts from Facebook sacrificed in the name of Performance testing. Aaron Bedra’s ‘Adaptive Security’ introduced me to the core concepts behind system security and how adapting to change will improve our chances against malicious attackers.

One talk that stood out as a brilliant testament to the core beliefs, intentions and driving forces for us at Bilue was Dave Thomas’ talk ‘Rigor Mortis (Avoiding)’. Put simply, Dave told his audience to ‘Think Differently’ and ‘Program Differently’. He put forward the idea that language is a limiting factor to the world around us.

What we can’t express with words, we can’t comprehend and by knowing this we can reason that by keeping an open mind, learning new languages and experimenting with different ways of solving problems we can achieve a deeper level of understanding in our work.

This concept applies extremely well to software and it holds up just as strongly when applied to everything that we do. Through an open mind, through seeking new ideas and through exploring new ways of thinking we expose ourselves to experiences and solutions we would otherwise have not even thought possible.

Yow! 2015 Conference has so far been amazing and informative for all of us at Bilue who’ve attended. New, unique and exciting ways of thinking are the creative forces driving the great work we strive to do each day. As we start to process these new ideas and perspectives from the sessions we’ve attended we’ll spend some time writing them down and sharing them with you. If you too attended Yow! 2015 Conference, enjoy today’s sessions and remember to program differently.

The State of iOS Dependency Management

Dependency management is a tricky problem to solve, even more so on iOS projects where we have to concern ourselves with things like code signing, embedded binaries, and so on. In recent years, a couple of solutions to this problem have presented themselves, each with different approaches and guiding philosophies, and each with their own tradeoffs to consider.

Manual Integration

There’s a lot of ways to integrate third party dependencies without using third-party tools. Most OSS projects use Git for source code management these days, so we can include those dependencies using Git submodules. Failing that, we can simply download the latest snapshot of a project and copy it into our project’s source tree.

With some basic knowledge of setting up Xcode projects, this solution actually gets us pretty far. It’s not the simplest or easiest approach, but it has its advantages. For one, not relying on third-party tools mean other team members can easily build your project without installing additional tools. This method is also the most resistant to breaking changes introduced in newer versions of Xcode, as there’s no waiting on a third-party to update their tools.

However we quickly run into issues as we add more dependencies to our project, especially when those themselves also have dependencies. Eventually we’re going to run into a case where two dependencies require two different versions of a library, and at that point we have to do a lot of messy manual resolution. Take the following example:

dependency_graph_conflict-1

Here we have a project that uses ReactiveCocoa and the (somewhat less well-known) ReactiveCocoaLayout library. In this situation, both our project and ReactiveCocoaLayout depend on different versions of ReactiveCocoa, so in a manually integrated project we have to do the hard work of resolving this conflict ourselves.

Beause of this, and various other problems, a new solution soon arrived.

CocoaPods

CocoaPods is a Ruby gem that handles the task of resolving dependencies for us, generating an Xcode project that builds those dependencies, and generating an Xcode workspace that lets us integrate them into our project. To include a dependency through CocoaPods, someone has to write a Podspec that describes how to build the framework, and what other dependencies it has. CocoaPods keeps a public repository of these Podspecs for open-source frameworks, and you can specify your own sources for private Pods.

If we wanted to recreate our example from the previous section, we’d create a Podfile in the root of our project with the following contents and then run pod install:

source 'https://github.com/CocoaPods/Specs.git'

platform :ios, '8.0'

pod 'ReactiveCocoa'
pod 'ReactiveCocoaLayout'

This approach is very much inspired by tools like RubyGems, and it has a lot of advantages. For one, it makes integrating dependencies extremely easy by taking over the duty of configuring your Xcode project for you. It also aids in discoverability, with CocoaPods.org providing a searchable repository of open-source pods, and CocoaDocs.org publishing easily searchable documentation.

It’s also widely adopted, with most frameworks offering official Podspecs, and those that don’t often having community-maintained specs that are kept relatively up to date. This popularity also means that when you do run into issues with CocoaPods, you’re rarely the first to and there’s likely StackOverflow answers already out there to solve your problem.

For authors of libraries, it can also reduce the maintainence burden of updating projects to build on new versions of Xcode, as CocoaPods handles the entire build process and updates whenever new Xcode versions are released. This does however mean that projects which also want to build without CocoaPods need to specify build steps in multiple places.

However, CocoaPods’ ease of use comes at the cost of quite a bit of complexity and a certain loss of flexibility in how you set up your project. For more experienced developers that feel they know how best to set up an Xcode project, the way CocoaPods wrests that control away from you can be frustrating. For library authors, it can also seem redundant to have to create a Podspec that mostly just reiterates information that’s already contained in Git and Xcode.

Finally, CocoaPods was initially designed to build static libraries and for a long time lacked any sort of support for frameworks. Initially, this was something only OS X developers really cared about as iOS didn’t have framework support prior to iOS 8. However, with iOS 8, not only were frameworks supported, but they became a requirement for using Apple’s new Swift programming language. Despite framework support eventually coming to CocoaPods, it has always felt like something of a second-class citizen.

So along came another solution.

Carthage

Carthage is described by its creators as “ruthlessly simple dependency management.” Its aim is to act as a simple coordinator between Git and Xcode, that picks compatible versions of dependencies, checks those dependencies out with Git, and then builds frameworks with Xcode.

To recreate our example project with the ‘standard’ Carthage setup, we would create a Cartfile at the root of our project with the following contents and then run carthage bootstrap:

github "ReactiveCocoa/ReactiveCocoaLayout"
github "ReactiveCocoa/ReactiveCocoa"

This would pull down our dependencies and build them as frameworks, but we would still need to manually integrate them. To do this we’d simply add references to them in our Xcode project and add them to the linked frameworks section of our target’s build settings.

Compared to CocoaPods, it’s a much simpler tool, though perhaps not as easy to use. Carthage does not integrate dependencies into your project in the same way CocoaPods does, instead leaving that task up to the developer. The upside of this is increased flexibility in how you integrate dependencies: whether by embedding the built frameworks, or by creating a workspace that includes all the cloned Xcode projects of your dependencies. In fact, Carthage can add all your dependencies as Git submodules, removing the need for other devs to install Carthage at all.

For library authors, supporting Carthage couldn’t be easier. You simply need to make an Xcode project that can build your framework, and then share the build schemes contained in that project. Compared to CocoaPods’ spec-based approach, this is refreshingly simple. There’s no need to submit a spec to any sort of central repository, instead users simply refer to a GitHub repo or Git URL in their Cartfile. This decentralised approach also simplifies the use of private frameworks and forks.

Carthage also tends to speed up builds in a few key ways. Firstly, frameworks are built once when you bootstrap or update your project, and then simply embedded on subsequent builds. Secondly, Carthage integrates with GitHub’s Realeases feature to download precompiled frameworks wherever possible.

Compared to CocoaPods, Carthage doesn’t have quite as much traction. There’s still the occasional project out there that doesn’t expose any shared build schemes, but this is usually simple to resolve with a quick pull request. Carthage also doesn’t help with discovering new libraries to use, your best bet there is to search GitHub.

Swift Package Manager

Announced as part of Swift going open-source, the Swift Package Manager, or swiftpm, marks the first time we’ve had something akin to an official dependency manager. It’s perhaps a little soon to say too much about swiftpm, it’s still very early and not officially released, but the current implementation and the package manager community proposal provide a lot of food for thought.

With swiftpm, developers create a Package.swift file in the root of their project that describes their project and its dependencies. swiftpm then resolves those dependencies based on git tags, pulls them down, and builds them as static libraries.

The Swift Package Manager is similar in certain aspects to both Carthage and CocoaPods. Like Carthage, it uses a decentralised approach to dependency resolution, and builds those dependencies as standalone binaries. Like CocoaPods, it uses specification files to define libraries and their dependencies — though this perhaps makes more sense for swiftpm, as it has to run on platforms where Xcode and by extension xcodebuild don’t exist.

As swiftpm builds static libraries as opposed to frameworks, there’s currently no way to include resources like XIBs or image files in a library. However, this is highlighted by the fairly in-depth package manager community proposal as something to add in future releases, alongside numerous other features that would make it more feasible for iOS projects.

In fact, looking at the proposals set forth in that document, it seems clear that the Swift Package Manager will eventually become the de-facto solution for dependency management on iOS projects. Just not today.

Which One Should You Use?

As with most things, the answer is ‘it depends’. If you want to easily bootstrap a new project, CocoaPods will take care of most of the work for you. If you want more flexibility in how you set up your project, or you want to more easily use private libraries that aren’t in a central repo, Carthage is probably the better option.

NSCamp 2015

You can only move fast and break things for so long. At some point you need to slow down, step away and gather a little bit of perspective. Last weekend the Bilue team helped organise and attended NSCamp up in Brooklyn, New South Wales. For the entire weekend we accompanied a group of talented developers, designers and creatives from as far as Perth and Melbourne to spend some time away from the regular routine of life and instead challenge ourselves with focus, growth and passion for the work we truly care about.

Part social getaway, part hack weekend, NSCamp created the perfect environment to nuture and encourage attendees to work on side projects, as well as meet and collaborate with like-minded creatives. There were small impromptu talks around the island on a range of different topics including ‘Designing iOS apps in Storyboards without Code’, ‘Pirate Metrics’, ‘Building apps with tvOS’ and even ‘Brewing Coffee’ by a professional Barista.

Internet was a scarce commodity, instead of Google and Stack Overflow attendees were encouraged to apply elbow grease, knuckle down deep into documentation and raise a hand to direct any questions at peers. Writing code was by far not a requirement of camp. A big focus for me throughout the weekend were three things – People, Reflection and Inspiration.

A great community of smart, talented and creative people attended camp which for me was a fantastic opportunity to discuss ideas and learn from people whom I rarely get to see face-to-face. We shared beers, ciders and whiskey over a campfire on the beach, strengthening friendships and forming new friendships all around. Designers helped developers add the sparkle their apps desperately needed, developers shrugged beside designers as they considered ways of making their ideas into reality and many creative thinkers discussed ways of improving their apps beyond just interface and code.

One of the most compelling aspects of camp was the lack of schedule and all around do-what-you-want attitude. There was nothing but time to think, and I loved it. I found myself an amazing spot hidden out on the rocks near the water, where I hid myself from the rest of camp a few times. It felt great to escape where no one could find me and just introspect about where I am, where I want to be, how I want to get there and where technology fits in with my broader life goals. Something that we as fast moving developers, designers and creative people rarely find time to stop, step away and do.

We look at code, at interfaces, at urgent problems every single day. It doesn’t take long for the pressure to build up and scar our creative side. We tend to fizzle out, feel un-inspired and corner ourselves.

At camp we had a rare chance to leave our outer shell at the wharf and to forget all expectations. There were plenty of challenges – the slackline challenge, the coffee machine, the blazingly hot showers, the lack of dry firewood and the scarcity of internet. All of these challenges enforced new and unexpected restrictions on us that forced us to open our minds, change our perspective and think of new ways to solve the problems we were faced with.

Through dedication many attendees were inspired to overcome the slackline, help build an amazing beach fire and embraced the lack of internet settling disagreements the old fashioned way – an alcohol infused argument and hefty bets on either side.

A highlight of the weekend had to be the absolutely amazing job that our own Duncan Campbell and Cameron Barrie did in preparing a feast of Ribs, Pulled pork and Lamb Shoulder rivalled by none other. It was also the fantastic coffee, the endless supply of beer and wine, the insanely great location and tear jerking game of Cards Against Humanity.

Thanks to all who were involved in making NSCamp 2015 possible, we look forward to an even better camp next year!

A little somethin’ on the side

If you’re anything like me your closet is littered with the slow painful decay of an endless pile of corpses that once resembled your latest and greatest venture into the unknown. Wielding your idea like a sword you marched into battle with a sense of fervour, nothing could stop you on your road to success. An innocent enlightened grin painted itself across your face as you made your first move `git init`.

On night one you spend hour after hour sipping furiously from a bowl of coffee, not a single clock to be seen. Momentarily you step outside of yourself and watch as an aura of code glistens across your beautifully excessive three screen canvas. A bedroom wall, once bare and hopeless, now corrupted with ideas, dreams and coloured post-it notes.

Commits fly. With each new line of code the click and clack of the cherry MX switches on your swanky new mechanical keyboard serve only to heighten your trance. Swinging around in your Herman Miller chair you chuckle to yourself silently almost as if to commend yourself for such ingenious levels of code reusability. One day in the distant future you’re going to love yourself for naming that class method the way you just did. A world of purely functional, purely stateless and purely bug free ninja-level perfection. You are the one true god.

Three months later you stare through the car window, music pumping through your ears. You remember. That project was going to change everything. Your ticket to the big leagues. A blank cheque. It was your chance to put your best practices into action and make the thing you always saw yourself making. The project you’ve always wanted and truly deserved to make.

You dedicated yourself to that project. That time was going to be different. You pulled out all the stops, spent hours thinking about the architecture, the business plan, the interface design and user experience design. You created a build pipeline that would’ve made all your friends’ jaws drop. Every mistake you’d ever made was covered and you had practically thought of everything.

But what happened? Where did you go wrong? Why did it never work out? Why does it never work out?

A new idea pops into your head.

This time it’s going to be different…

logo-outline

Contact Info

Sydney
Level 1 6 Bridge Street, Sydney, NSW, 2000

Melbourne
Level 1 520 Bourke Street, Melbourne, VIC, 3000

Copyright 2018 Bilue Pty Ltd ©  All Rights Reserved