Thursday, February 4, 2016

Xamarin vs Ionic: A Mobile, Cross Platform, Shootout

Ever faced with choosing among competing frameworks; needing to make a decision you/your customer won't regret?  If those frameworks are for building cross-platform mobile apps and are Xamarin and Ionic, hopefully this article will help.

The background is I had the somewhat rare pleasure of working on these competing frameworks on back-to-back projects recently.  Project #1 used Xamarin (and Xamarin Forms more specifically), the C# based framework for building fully native, cross platform apps.

Project #2 used Ionic, the Angular.js, Cordova/PhoneGap, HTML, and JavaScript based framework for building apps that look and act native, but are technically running in an embedded browser.

And what if I had to recommend one?  I'd probably want to think about a customer's budget, desired end product, and timeline.  I'd consider development speed, ramp up time, and maintainability.  Basically I'd evaluate based on the following six criteria:

1. Price: Ionic++


The single most obvious framework differentiator is price. Ionic's free price tag may seem like a no brainer.  However, $1,000 per developer per year for Xamarin is quite doable for most companies, especially if there is a compelling enough reason. Two very compelling reasons are:

  • We only have .Net developers; and
  • Our architecture is already exclusively .Net

If these bullets apply to you, then the price is likely justified, and the Xamarin choice obvious. However, if you have a mix of talent and technologies, then free is hard to beat.

2. End Product: Xamarin++


Your customers won't be able to pinpoint exactly why they prefer your competitor's fully native app, but you're more likely to lose in the end

Surprise: an HTML-based app, however well styled, will never look, feel, and perform like a native app.

How different is the Ionic look and feel? If you stick to the default controls and don't overly customize, I guarantee your users won't notice. However, faced with a choice your customers won't be able to pinpoint exactly why they prefer your competitor's fully native app, but you're more likely to lose in the end.

We were lucky enough to have a full-time design professional provide assistance on the Ionic project, and several of his (fairly time consuming) suggestions would not have been an issue if we'd gone with Xamarin.  Furthermore, the UI always felt a little laggy, even with theoretically GPU accelerated CSS3 transitions.

Simply put if you want the best, fastest, most authentic experience for your users, Xamarin is the clear winner.

3. Development Speed: Ionic++


If you need to get an app out the door yesterday, Ionic is your friend.

Development speed differs between the frameworks in two main aspects.  First is the amount of time from writing a line of code to seeing results. For Xamarin, pushing out code to an iOS device required several seconds of compilation plus 10 to 15 seconds of deploy time.  Ouch.

By comparison Ionic with a ripple emulator provided zero-compilation, sub-second feedback times. This feature alone significantly increased development speed.  Perhaps more importantly the fast feedback cycles actually made coding more fun.

The second development speed difference was in UI debugging.  Ripple plus Chrome tools makes debugging the UI in Ionic amazingly easy.  With Xamarin you have a very limited ability to figure out why an element is rendered exactly where it is at runtime, let alone tweak its attributes. In short Ripple + Chrome Tools makes UI work significantly easier in Ionic.

Overall, Ionic was a significantly better development experience.  If you need to get an app out the door yesterday, Ionic is your friend.

4. Maintainability: Xamarin++


This where I rag on JavaScript, right?  Well, before I start, I have to admit I made three architectural decisions off the bat that made working with a JavaScript app more palatable to someone with my background and um, well biases, frankly.

TypeScript


As much as I appreciate JavaScript, I value refactoring, a great IDE experience, and the free unit tests that a compiler provides. TypeScript gave us all that goodness back, and with it the possibility of working with a large codebase and/or a larger, more diverse team. Without TypeScript I personally could not recommend Ionic for anything beyond fairly simple or a single developer mobile app.

Visual Studio + ReSharper


You thought Visual Studio and Resharper were just for .Net apps? Wrong, they helped us immensely with things like Bower and NPM package management, code navigation, refactorings, and great static analysis, plus a full-on fantastic debugging experience like you'd expect from a .Net app. Microsoft thoroughly surprised (dare I say delighted) us by providing a fantastic IDE for a historically non-Microsoft tech stack.

Wallaby.js


Our app had a fairly complicated core engine and with it a lot of unit tests. Wallaby allowed us to run our unit tests continuously, as we typed, before we saved even. Everyone on the team knew instantly if they had broken a test, and it kept code coverage at the fore-front of everyone's mind. Karma would have been ok I guess, but Wallaby made working exclusively in JavaScript/TypeScript enjoyable.

Overall Maintainability


While these three decisions made our JavaScript application more maintainable, refactorable, and less prone to incurring technical debt; Xamarin continues to feel more maintainable.  There's no way around that Angular is extremely heavy on magic strings.  My co-workers and I simply felt less scared of creating obscure bugs while modifying each other's code or refactoring existing code when we had a real compiler double checking 95% of our work.

5. Unit Testing Experience: Conflicted


A good framework needs a great unit testing experience if you're going to bake quality into your app.  Unfortunately, as great as Wallaby is, even with Karma, I could not figure out how to breakpoint debug and inspect variables from within a unit test.  With Xamarin, on the other hand, unit testing is a first class citizen.  It's easy and powerful and with nCrunch, feedback is nearly as fast as with Wallaby.

Why conflicted?  Because I love this:

// describe + it blocks offers a hard to match level of expressiveness
describe('when you calculate dimension effects for a question', () => {
  // notice this generic helper function relevant to most/all of the tests
  var makeDimensionEffects = () => { ... };

  // nested describe -> I LOVE THIS
  describe('with a transformation', () => {
    // this 2nd helper is relevant to only nested tests
    var makeQuestionWithTransformation =  = () => { ... };

    it('should error gracefully if blah blah blah', () => {
      expect('actual').toBe('expected');
    });
  });
});

Even with SpecFlow, of which I am a huge fan, .Net fails to offer the same power, flexibility, and expressiveness.

6. Ramp Up Time: Xamarin++


The amount of ramp-up time obviously depends on your background.  However, with Xamarin it was just a little easier to fall into the pit of success.  Architecturally speaking, we made a wide variety of mistakes in Ionic that made things very messy for us later (notice how I switch to the third person when it's something bad that happened, sneaky, huh?).  Those mistakes mostly manifested themselves as poor memory management, although we screwed up our ngCache data structures too resulting in poor performance under load.

Now one might argue it's easy to mess up memory management with any new framework.  In Angular, however, upon which Ionic is based, it seems to be especially easy to create leaks.  By the time we finished our Minimum Viable Product and realized all of the anti-patterns we'd implemented we had a real mess to recover from.

Conversely, we had only one major memory issue with our Xamarin MVP, and we cleaned it up without issue.  Obviously if you have anyone on your team with prior Angular experience that mitigates this concern, but if not and you're choosing Ionic, consider yourself forewarned.

Summary


So what if I had to recommend a framework today?  Obviously the safe (and correct) answer is: it depends.  It depends on the team, the existing architecture, who's maintaining the app, the budget and timeline, and a host of other concerns.

However, just to be provocative I'll avoid the safe answer.

For me: I value quality over speed.  Just because you can build something with free tooling (#1), do it faster and have more fun doing it (#3); that's no substitute for building an authentic, top notch, responsive mobile UI (#2) on a clean, refactorable code base (#4) that will be ready for market when it hits first release (#6).

But perhaps time to market is more important for you.  Every circumstance is different.  Hopefully this has helped shed some light on what decision will be right in your case.