Monday, May 18, 2015

App V1: Knowing When To Stop

Fishing while taking a break
from building Heart Relay.
I have to stop at some point. The hardest part of shipping software you design and write yourself is shipping it. Like any creative activity, you have to know when to stop.

I had a "working" prototype 3 weeks ago in about 3 hours. It had next to no UI, was not intuitive, had no settings, persisted nothing, did not handle Bluetooth disconnects, and many other missing bits and pieces.

The have been plugging away 2-3 hours a night when I can so I can ship a V1. Here are some of the items holding up shipping:

  • Completing the list of V1 features for Heart Relay. There are not that many, mostly make it intuitive, performant, and not look like it was designed by a code monkey.
  • In relation to one, I am not happy with some of the icons. I should just ship what I have but I want more consistency in the icons and to replace words with icons (harder to understand maybe but I would like the user to not be hit with a screen of text).
  • Animations
    • I wanted to add some custom animations for both the connecting event (instead of using the default activity indicator spinner) and the Heart Rate measurement (a beating heart).
    • Animations and custom icons take time.
  • Testing:
    • While testing, I discovered that in noisy Bluetooth environments (work) the Bluetooth connection sometimes drops. Due to this I needed to work on reconnect and how to help the user to recover from this.
    • Testing takes time.
While doing all this new features have come to mind. Here are things I have cut from V1 or are feature creeps that I will consider for V2.
  • Free, Paid, IAP, or Ads?
    • Free: For V1 launch.
    • Paid: For Pro version later with some whiz-bang additions.
    • IAP: Research shows IAP is not worth the work.
    • Ads: After launch.
  • Heart Rate Zone Tracking
    • Going to keep for Pro version later.
  • Heart Rate Zone Alerts
    • Going to keep for Pro version.
    • Will buzz band when you drop out of or rise above your zone target.
  • Heart Rate Export
    • Going to keep for Pro version.
    • Let you export to CSV so later import to whatever app you want.
So, I am still plugging away.

I am debating if I will redesign the app icon. Probably not for V1.

Ok, back to drilling down some reconnection features.

Tuesday, May 12, 2015

Microsoft Band Kit: Swift Samples for iOS

I just finish posting the latest Swift ports of the Microsoft Band Kit SDK Samples for iOS. You can find the original Objective-C samples at http://developer.microsoftband.com/.

My ports can be found at:

Monday, May 11, 2015

Microsoft Band Kit: BandTileEvent Sample ported to Swift

If you want to add buttons to your Microsoft Band Kit App tile and are using Swift then head over to GitHub and check out my port of the BandTileEvent sample app: https://github.com/mthistle/BandTileEventSwift

This sample shows how to add a button to your Microsoft Band Tile and then receive button and tile events for your tile.

Friday, April 17, 2015

Blitz Talk Preparation Notes

Blitz Talk Preparation Notes

I have spoken about my talk at NSNorth previously here (NSNorth 2015: Stretching Myself) and here (Blitz Talk: Microsoft Band).

After giving two talks recently, here are some tips and things I plan to do for my next talks:
  • Practice speaking with a mic in my hand (I happen to have one for recording).
    • Reason: Get used to holding the mic at a steady distance to reduce volume changes.
  • Write slides a couple weeks before time and tune leading up to the event.
    • I copy my presenter notes into OneNote and then reread them and tune them over time.
  • If using autoplay (when the slides automatically advance every 15 seconds) then practice with that.
    • I practiced at first by manually progressing the slides to work on transition text between slides.
    • I figured out I could say about 3-5 sentences (a short paragraph) during the 15 seconds a slide was up.
    • Once I had the transitions worked out I started to practice with autoplay on.
    • Once I had the presenter text down, I started to practice with no presenter notes.
  • Practice speaking in front of the mirror.
    • Once I started this I felt I found a lot of flaws and was able to really improve the rhythm of the talk.
  • Stay calm
  • Make sure you use White on Black or Black on White fonts/background.
    • Some of the presenters had Grey on White, etc which bled together when the lighting was not ideal.
  • Place your twitter or email or webpage on each slide (if appropriate).
    • I put my twitter handle in the bottom left of each slide that had space available.
One complaint I received was that some slides had too much text and that since I was adding so much information it was a lot to take in. That was part of my goal to share as much information as possible and to let the slides stand alone for those that come across the slides after the talk.

Good luck on your next talk.

Thursday, April 16, 2015

NSNorth 2015: Stretching Myself

Photo: Martin Reisch
via NSNorth.ca

NSNorth 2015


NSNorth has come and gone and I was so happy I could make it this year. This was my first year to NSNorth and back to see my Ottawa Cocoaheads friends who run the conference and are attendees.

I few months back I had to make the decision to go to NSNorth or play the WWDC lottery (given that I am paying my way without a company to help with conferences I had saved up for one conference). So I went for NSNorth this year and figured I would skip this years WWDC lottery.


Meeting New People


Given that I am contracting now and have to be on the look out for new opportunities I decided I should stretch myself at NSNorth with a couple goals. I decided, I should throw off my shyness in a crowd and network! Though it may not appear so, I have to force myself to be outgoing in a crowd.

I think I did a decent job at it and if you did not get a business card then you missed out on one of these babies (a series of 5, each with a different color and quote about software design, I have more if you want one):

Blitz Talk (ie. Public Speaking)


I figured another good way to find opportunities would be to give a talk about the Microsoft Band SDK that I have been a part of this past year. As one of the ~15 people on the SDK team, I concentrate on testing the SDK for Apple platforms; including implementation of test infrastructure and verification of the public SDK for 3rd party use. (You can read more about my talk and see the slides at my company Blog: Blitz Talk: Microsoft Band Kit SDK.) The response was positive and many people let me know they were happy to learn about the Band and the SDK.

By far, I was way more relaxed after the Blitz Talk on Saturday morning (thanks Dan and Phil for getting me on early in the lineup). I was a bag of nerves going into the talk. I practiced a bunch but still felt unprepared going into it. This was also the largest group I have spoken in front of. There were ~120 people at the talk, with my previous talk in February being ~60.

I have not done public speaking for many years. I used to do it more often as a team lead in an previous startup and at a company where I lead process improvement and system architecture. So, after 5 years of not speaking in front of people it was a little daunting. I even had to use a hand held mic, which I was not prepared for.

Reconnecting With Friends


Another goal I had for this trip. Reconnecting with old friends I have missed on some previous trips back to Ottawa. I was able to do that by going to NSNorth and seeing my Cocoaheads and NSCoder friends. I was also able to fit in some meals/beers with coworkers from past jobs. This was an important part of the trip as well and we always try to see any many friends as we can when we get back to Ottawa.


I also got to play Hope Inhumanity by my friend Derek Gour. We had a great time playing the game at the Saturday night games night. Home Inhumanity is a survival/horror card game. It has a partial cooperative and role playing aspect to it that I think will make each play through (especially with different people) unique. Great job Derek and my copy is on the way.

Monday, March 30, 2015

iOS Swift Example of Connecting with the Microsoft Band SDK

Here is a quick example of connecting to the Microsoft Band from iOS using Swift.

I posted this on Github at: https://github.com/mthistle/SendHapticSwift

Let me know if you have questions.

I will flesh this post out more once I have time to do a deeper dive.

Thursday, February 12, 2015

I Ain't Afraid of No NSError: Adventures in API Design

These are the notes from my Lightning Talk at Xcoders Seattle on February 12, 2015. A Lightning Talk is a 5-10 minute presentation that gets to the heart of an idea, problem, solution, quibble, etc. They are popular at conferences (also called Blitz Talks) where multiple will be held over 60-90 minutes.

The local Xcoders has begun running this as a way to let those without a 60+ minute presentation bring new ideas into the local developer community. I think it's great and if your developer meetup is not using them, then give them a try.

--
Adventures in API Design

My Point

NSError's userInfo dictionary is the right way to return errors from your API. Let me elaborate.

Designing an API

Everything is a trade off. When designing your API there are multiple things to consider:
  • How much of the internal API should I expose?
  • Should I provide logging?
  • How long is too long for a method name?
  • How should I return errors?
Let's focus on errors. Those are easy, right?


Throw an Exception?

We have several options available and if you are coming to Cocoa (Objective-C) programming from other languages then you might think using NSException to throw exceptions is an option, right? 

Wrong!

Apple has made it clear through it's use of NSError that exception throwing is not the answer. Exceptions are things you should fix/not handle in code and continue on.

With Swift they have now codified this desire. Swift has done away with the ability to catch exceptions.

Ways of Using NSError

Ok, so exceptions are definitely not the way. So how can we pass errors back to our users? And how can we do that if we want to provide more info than NSError provides?

A quick review of some popular 3rd Party APIs shows that we have several options for error handling:
  1. Subclass NSError.
  2. Use Categories to extend NSError.
  3. Use NSError and it's userInfo NSDictionary.

Option 1: Subclassing

This Sounds like a great idea if you come from other OO languages. But with Objective-C we run into a corners that can catch us up.  Here are some problems:
  • Friction. 
    • Devs need to handle NSError and YourNSError.
  • Crashes
    • Crashes make 3rd party dev mad!
    • Why crashes? If you have an API call that says it returns YourNSError but you return NSError thinking no problem (or by mistake) then what happens the the 3rd Party Dev calls one of your new methods that you added to YourNSError? Their app will crash since the selector (method) is not available on the NSError you actually returned.
  • Slowed code
    • After a crash due the scenario listed above the 3rd Party Dev must use reflection using NSObject's respondsToSelector: to verify that your returned error objects contain the listed methods. Reflection is slow, why add the overhead to a 3rd Party Devs App?

Option 2: Add a Category

Ok, so subclassing is perhaps not the answer but what about just adding a Category to NSError and adding your new properties and methods to this category?

First, if you do not know that you can add properties to an existing class using a category, then look up Associated Objects. I don't recommend you try this. You warp the very foundations of the classes you are using and cause more harm than good in most cases.

But, given that some popular APIs use just this method. What are the pros to extending NSError like this?
  • Less Up-Front Friction for Devs
    • No messy switching between a subclass and NSError.
What are the cons?
  • Crashes
    • Ok, so you decided to add some new properties using the magic of the Objective-C runtime. You learned about Associated Objects ability to extend a class with a property and found a "back door" around subclassing.
    • The thing about adding a property through object association is that if the API does not set the property then it has not been associated with the object. Again, we have a missing selector and we have caused a crash.
    • Dev no like crash! 
  • Slower code
    • We are back to having to use reflection (respondsToSelector:) to verify your error objects support the properties you listed. Boo!!
Option 3: It's So Not OO

A common complaint I hear about Apple APIs is the reliance on NSDictionary. NSError is one of those culprits with it's userInfo. It does not feel OO so many poo-poo it as an aberration.

So what? It's how it's done and it has good reason. So why use a pure NSError and pass back additional details in userInfo?
  • Less Friction
    • No learning a new NSError class/category.
  • No Reflection = Faster Code
    • No reflection needed to validate your error objects support your listed properties or methods.
  • Reduced Crash Vector
    • If the user makes a call to [userInfo objectForKey:] on a non-existing key, then instead of a crash they will receive nil which in Objective-C is a no-op (meaning no crash). This is unlike a call to a non-existing property/method (when misusing a Category or subclass) which will crash with an NSInvalidArgumentException with "unrecognized selector sent to instance".
  • For the high runner case you don't need more than NSErrors (domain, code, and localizedDescription).
  • For the low runner cases you can extend NSError with additional details in the userInfo dictionary by adding new keys, publishing them in your API docs, and then let the app developer decide if they want that added detail.
  • If the dev doesn't really care, they can just print the entire userInfo and get all the details of your error.

Avoid friction.
Don't slow down code.
Avoid skip crashes. 

The right way to expose your API errors is with NSError.

References


For further reading, start here: