Tuesday, September 1, 2015

Incremental Change

Applying Incremental Changes to Our House
A key to success with programming is learning to experiment and make incremental changes. Testing those increments is critical to understanding if your change achieved your goals or made wider reaching impacts than expected.

From year to year, environmental changes are incremental and often barely register in our lives, but from evolutionary or geological perspectives, what is happening is explosive change.

David Suzuki

Like evolution, our code evolves slowing as we add features, we break things, we fix things, and push for the release line. Many commits are required to build the bedrock of the apps we ship and the features our users take for granted.

Sometimes in the rush to ship we miss testing some of these changes. Like evolution, these missed increments can explode when they reach our customers.

I hit my first shipping crash in one of my apps in the AppStore this past week. In this case it was with Selfie Band, my camera remote for the Microsoft Band. Selfie Band tries to install the camera remote tile (it's app view) on it's paired Microsoft Band.

It looks like one user had a very bad experience when they ran into the bug. They tried repeatedly to get past the problem but it looks like they crashed multiple times during this. I know this since I use Crashlytics crash reporting in my apps.

The bug manifested itself when the Microsoft Band had no remaining space for tiles and returned an error. I had incorrectly changed some error handling code and forgot to retest it.

So, being in Swift, my null point access crashed the app instead of silently failing as many of us Objective-C programmers are used to.

It was a silly mistake and I have fixed it and shipped the update to the AppStore. I just need to pass review and the fix will be live.

This bug reminded me to slow down and verify that incremental changes don't lead to a crash.

The competing priorities to ship and to create quality software can be hard as an indie when you have no teammates looking over your shoulder to review your code. The end user will feel the brunt of your mistakes and so will the impression you give your customers.

For me here is how I am addressing this as the sole programmer:

  • Commit often to git
  • Review my checkin like I would someone else's code
    • Why did you do this?
    • Was it tested?
    • Are there loose ends?
    • Should this be committed or reworked/retested?
  • Using branches to switch between features that I want to revisit
  • Reevaluating a change when it gets too large
Don't let your incremental changes lead to explosive releases.

Thursday, August 27, 2015

Constraints Give Focus

The more constraints one imposes, the more one frees one's self. And the arbitrariness of the constraint serves only to obtain precision of execution.
Igor Stravinsky

I've spoken of this before, as a creative person, the hardest job can be to know when to stop/when to ship.

Building an app, creating a work of art, planning the weekend, deciding what to make for dinner; all of these things can get out of hand if you don't limit yourself. You need a plan and you need to set a bar for:
  • What is the bare minimum needed to achieve your end result? The Minimum Viable Product.
  • What is the desired feeling you want your consumers to experience? Utility? Joy? Full?
  • What are you desired goals with this product? Ship an app? Showcase your skills?
All of these things need to be considered but many times we want to deliver everything with a dime store budget. This is seldom possible.

My wife, from her experience in product management, was the first to introduce me to the concept that you can have a product Cheap, Fast, or Good. Pick Two! This is called the Project Management Triangle.

As an indie with a full time job and a family, I run into this problem all the time. I feel I am asking too much to pick two when having one with limited time is hard enough.

Here's how many of my projects go:
  • Brilliant Idea!
  • Crave out a block of time to put in a mad dash to get a prototype working.
  • Start to design a MVP.
  • Start to implement the MVP.
  • Run into corners I never foresaw.
  • Start slogging through the corners, rounding everything out.
  • Invest too much time into after hours indie work.
  • Crash, burn, burn.
  • Put project on back burner.
For every project I have completed, there is a mountain of projects I have abandoned.

Is this bad?

Only if you let it get to you. I look at that mountain as wisdom.

Here is what I take away from my "failures", if you want to call them that:
  • Experience
    • To know when I am adding more features than I can complete.
    • To know which ideas will take too much time.
  • Knowledge
    • With new techniques, skills, APIs, etc.
    • Few jobs offer training. As a contractor, I must think of my own training. These side projects help me to expand my skills and train.
  • Resolves
    • To find better ideas to solve, build, and deliver.
  • Efficiency
    • The more projects I work on the better I become at solving problems.
    • The more I projects I deliver the better I get at delivering solutions.
Constraints add focus.

Figure out how to use those constraints to improve your projects.

Learn from your mountain of failures and learn where you can add constraints to increase your pool of successes.

Wednesday, August 26, 2015

Paddle Mate Post Weekend Update

Night Testing

As some saw, over the weekend I took Paddle Mate for a night test and it went well. Here is the workout, which I posted from the water to Strava. This was a final field test after a previous couch test with a shorter test run from a past day.

Backgrounding Bugs

After the successful test on Saturday night I added more features on Sunday. When I went to try out the app for a longer 2 mike kayak I ran into several bugs. The major one being backgrounding related. This raises the issues that I need to refactor my PADDLE view to handle resuming when the app is relaunched after being stopped by the system while in the background.

This is one of the final 2 big bugs to shipping the app for testers. It will be my area of concentration when I find time this week.

Sunday's Features

  • SHARE view
    • Refactored from PADDLE END view
    • Send to Strava complete
    • Send samples to Paddle Mate (this is for testers or users so they can upload samples so I can add them to my testing and algorithm training)
  • WAKE view
    • The WAKE view as I have discussed is the view for looking at previous sessions.
    • Tweaked the scrollview to layout elements with more space for map and charts.
    • Add delete option to delete a session you do not want to keep.
    • Add SHARE option
    • Hooked in Map and Charts
  • PADDLE view
    • Added Map view back in. I was getting distracted by tweaking the Map (for maybe an hour) and put it on the back burner until I had a couple bugs in the PADDLE view metrics fixed. This made it back in and I really like it.
    • Add ability to have Map and Stats view force screen to not sleep. This is on now for my testing but I think I should expose this with an option. I will address that when I fix the backgrounding bug I have.

Next Steps

Well, I am back to reality. My family arrived back home from a visit to Canada and I am back to my normal schedule. This means a decrease in posts and slowing down of the progress I was able to make over a weekend. I can not pull a 29+ hour effort on Paddle Mate for the foreseeable future but I will need to spread that time out.

Ok, so now that I am back to my normal schedule I will refine my list of what I need to ship the MVP. Here are my upcoming tasks I need to ship for testers:

  • Address the backgrounding problem. Not a big deal and I have a handle on how to get the resumption working.
  • Second big bug: I found some limits in the iOS-Charts library and was able to not only freeze my app but my phone (until the system could kill my app and it's out of control chart generation). The library was spinning the CPU up to 100% with a lot of nested CGImage creations as it tried to draw a chart for a very large sample set. I need to address this before I ship and find the upper limit on the libraries chart sample size.
  • Style the DOCK view of Wakes of previous sessions. I have some ideas here and it is not critical to get the app out the door but I need to move from the current placeholder UI.

Follow Up: The Chart Bug

For one of my charts I was using it to view accelerometer samples while testing and am planning to convert it over to a chart with your speed over the workout. The issue I ran into (which I am happy I did since I have an upper bound to work back from) is that I selected the chart with my 28 minutes of accelerometer data and it's approximately 6700 samples kicked the charts ass.

To solve the problem I am going to limit my sample size based on the time. I need to find that upper limit and then calculate out a sample set size that has less entries than the upper limit for reasonable performance for expected kayaking times.

Monday, August 24, 2015

Reuse in App Design

END PADDLE view reused as
SHARE view
Code reuse is important and we take advantage of it all the time with open APIs. When we are designing our own code, UI, or UX we can also get code reuse. Here's how I reused the END PADDLE view for the SHARE view.

I left the implementation of the Past Workouts view (called the WAKE view) and it UX until after I had the basic app functionality working. Once I started to implement the WAKE view I began to see I could make some small changes to the existing END PADDLE view to reuse it as a SHARE view.

Here is the scenario.
Jane is kayaking and is outside of data coverage. She ends her kayaking and can not upload to Strava to share her workout with friends. Jane wants to be able to upload her workout when she gets to lunch where she knows she will be back in data coverage.
To handle this scenario I decided I would put that option in the WAKE view so that you can see which past paddles have been uploaded. From here you can also upload that past paddle.

Here is where the reuse comes in.

The END PADDLE view contains the sharing options; to Strava for example.

So, I refactored the END PADDLE view to support both the End Paddle workflow and the Share from Wake workflow.

This decreases the amount of code I need to write, reduces the number of views in my app, and let's me move faster.

Look for ways to implement your views with reusability in mind. You may be able to save yourself work in the future when you need similar functionality from another location in your app.

Sunday, August 23, 2015

Feature Decisions

I started Paddle Mate 3 weekends ago. The first weekend I started with proving out the the initial algorithm, setup a way to collect and test sample data, and then began the hard work.

Once I decided the app was viable, I began to polish the app for release. First I had to come up with my wish list and then trim that down into a Minimum Viable Product (MVP) list of features.

The MVP features I desire being:

  • Stroke counting
  • Real time workout stats
  • Location tracking
  • Upload to Strava
  • Import into Health App
  • Submit Samples for Stroke Detection Refinement
  • View Past Workouts
  • Delete Past Workouts

It has been a busy 2 weeks and I am into the final stretch before my wife and kids get back from a visit with family in Canada. With them away I was able to throw myself into creating the app. 

Over the last two weeks I have put in about 65 hours over 5 weekend days. I have not tracked the weekday nights as well but needless to say, I have invested time on many nights researching, designing, and cranking out code.

All the work is paying off. Yesterday evening (9pm) I took Paddle Mate for a spin around the lake. I put in just over 2 km with the app over 28 minutes. Notes from that:
  • Dark Mode for nighttime kayaking worked out very well.
  • I need to add an option to not turn off the screen.
  • I am missing an activity indicator during the sample submission file generation.

Yesterday's Features

  • Sample Submission
    • User has ability to choose the data to send.
    • Submission is through a Mail Compose view so the user can view what they are uploading and choose to cancel at multiple stages if they do not want to upload samples.
  • Tweaked my use of the Realm Database to:
    • Decrease write calls.
    • Add delete.
    • Improve use with tableviews.
  • Initial hookup work for Past Workouts (WAKE view) is done.
  • Submit to Strava
    • Hooked up but my GPX data format is being rejected. 
    • More testing/tweaking needed here.
  • Created converter and file writers for my location and sensor data models to support CSV and GPX output formats.

Yesterday's Commit List

  • Updates to UI design in PaintCode.
  • Added tintColor constant.
  • Refresh DOCK tableview when returning to view.
  • Added Delete button to END PADDLE view.
  • Switched navigation from push detail to push in PADDLE workflow to allow pop to root without animation warnings.
  • Added PaddlingEffort enum for user submitted samples.
  • Added logic for incrementing workout id.
  • Added stroke data to sample submission format.
  • Added submit samples to Paddle Mate via email submission.
  • Added convert location data to sample submission format.
  • Fixed warnings in FRDStravaClient.
  • Wrote converter from location readings to GPX output.
  • Wrote converter from location reading to location CSV output.
  • Wrote converter from sensor reading to CSV output.
  • Improved use of Realm with Dock TableView.
  • Improved MathController default configuration.
  • Added Uploading activity indicator and dimmer view.
  • Added upload to Strava method. - GPX file format issue at moment.
  • Hooked up controls in WAKE view to workout values.

Today's List of Features

  • Strava upload
    • Fix GPX format
  • Past Workouts
    • Add Delete option
    • Add Submit Samples Option
    • Add Upload to Strava Option
    • Enable Charts
    • Enable Map with route from workout

Friday, August 21, 2015

UX Testing, Where Bad Designs Go To Die

Bad Design Be Gone

I made some UX decisions during design that I thought would work out. They didn't.

Back to the drawing board.

While testing the app over the past few days (walking the dog, running, driving) and I realized some things did not flow well. So I took Tuesday night to reevaluate the design and work out how to solve some of the flow problems.

Two things I did:
  • I reviewed multiple fitness apps to understand how they handle some of the UX I was having problems with.
  • I showed the app to more people to gather feedback about the UX.
Both of those things brought to light multiple areas that could be improved.

So, I redesigned a couple views, added some missing views, and jotted down some great feature ideas I received. The features I captured for a post V1 release.

Missing Interstitial View

In particular, a problem area I had was the Paddling/Workout workflow. Here is what I had:

  1. User taps PADDLE on the main view.
  2. Transition to Prepare To Launch view.
  3. User chooses if they want to track location and use a paired Microsoft Band.
  4. User taps Play button to start paddling workout.
  5. Transition to PADDLE view, the main workout view.
  6. User decides to stop workout, they tap Pause button.
  7. Transition to Paddle End view.
It was steps 6-7 that had a problem. Here are what the views looked like.
Missing a Pause/Stop Confirmation View

The main problem with the above design is that I am trying to do too much in the PADDLE_End view. I am trying to cover several tasks:
  • CONTINUE: You paused by mistake, did you want to go back?
  • DONE: End the workout.
  • Upload to Strava: Did you want to upload the workout?
  • Send to the Health App: Did you want to store your workout in the iOS Health App?
  • SEND SESSION TO PADDLE MATE: (Too long) Are you a tester and want to submit samples?
Here is what I have done so far to fix a major flaw.

I added an interstitial view between 6&7 which is a Pause view. This will let me move the CONTINUE from PADDLE_End back to the main view.

I think this offloads the decision to end the workout to this new PADDLE_Pause interstitial view. Now the user is not thinking about should they continue or end on the next screen, lower the cognitive work on the PADDLE_End view.

New Paddle Pause with interstitial Pause/Stop Confirmation view added before Paddle End view

At first, I left the CONTINUE in but realized I needed to remove it since the decision to CONTINUE/UNPAUSE is on the interstitial view. Now, I think I have a cleaner UX for ending the workout.

Change Design, Test, Repeat

Then, on Wednesday night I completed the integration of Microsoft Band data, CoreLocation data, and workout metrics into my Realm backend. This is cool since I had implemented the code to load the DOCK view, the main view you land on when launching the app, previously when I designed the data model.

Now I have a lot of workouts showing up on the main view as I test the PADDLE workflow.

Then I released I needed a way to delete a workout on the PADDLE_End view when a user (me) wants to delete a session they do not want to track. So, for this I added a DELETE button to the PADDLE_End view.

I do not think this adds to much to the cognitive load since a review of multiple fitness apps those that many use this concept on their end workout view. I also think it fits to have the DELETE | DONE on the top so the user can choose if they want to keep/delete this workout.

They are along the same line visually and hence they are giving you two options along the same line of vision.

Now with Pause interstitial and Delete option
Now it's time to retest and see how this new design's UX feels after repeated use.

Thursday, August 20, 2015

Adding Custom Fonts to Paddle Mate

Snippet of Console dump of available system fonts
For Paddle Mates design I want a font that has a tight set of numbers on the paddle view (also know as the workout view in other fitness apps). For that I did some research and a lot of looking at fonts last night.

I have a couple fonts I will be testing in the next few internal releases until I settle on the one for the app.

If you need to add custom fonts to your iOS App, a good walk through was done by Chris Ching over at Code with Chris called Common Mistakes With Adding Custom Fonts to Your iOS App.

Some of the sites I reviewed looking for fonts included: