iCloud Drive – What a disaster!

So, I’ve been working on a new version of my app Songbook Simple and I want to improve some of the file sync code.  Up until now I’ve been supporting Dropbox, with the original idea that a user can edit and modify all his/her songs from the convenience of their desktop, and it would just sync on the device.  This *has* worked, and *still* works, though it always seemed like a quick and dirty solution to me.

Enter Apple TV.  I thought it would be fun to make Songbook Simple Apple Tv compatible, but in order to do that, one basically has to support iCloud for syncing data.  As the Apple TV won’t be an editor, but just a viewer, we need to get data from somewhere, and I’m not so sure Apple TV is entirely Dropbox friendly yet.

So, I’m trying to implement iCloud support in Songbook.  I followed the excellent 4 part tutorial series written by Ray Wenderlich himself.   It all seemed to work brilliantly.  Files were syncing across iOS devices.

But wait.  Now what about using my Mac to edit files?  Well, turns out this is where iCloud Drive is a complete and utter disaster.  On icloud.com, there is no folder associated with Songbook.  On iOS, the iCloud Drive app DOES show my app folder and its contents.  On OSX, in the iCloud Drive folder, you don’t see anything associated with Songbook.  So my user workflow, namely, editing songs on your Desktop, is broken.

I’m all for “Automagic” for the sake of better User Experience, but if it’s “Autobroken”, then get rid of your magic because you’re killing us.

In order to restore the ability to edit the contents of my SongbookSimple folder, I had to open a terminal window, and do the following:

cd ~/Desktop
ln -s ~/Library/Mobile\ Documents/iCloud~com~softwarebarn~SongbookSimple/Documents/

Then, from Finder, navigate to the Desktop, then either move that Alias that just got made (called Documents) to somewhere better, or simply drag it into my Finder’s sidebar.

Great feature, Apple!  All these years to mimic Dropbox and it’s still a failure.  Yes, I followed ALL the instructions, and spent 3 hours this morning making sure I didn’t miss any.

Advertisements

An Open Letter to (mobile) Server Devs

On basically every project I’ve ever worked on that involves a server, I seem to notice the same things that happen over and over and could be preventable with proper planning.  When mobile devs discover server bugs, it often blocks our work and halts development (not to mention the costs associated with that, which are NOT trivial).

So I thought I’d just list the things that I wish server developers would think about when they start building a system, and rant a bit about the mentality we’d hope for in any server dev.

 

Design for the failure case, not the ideal case.

Servers fail all the time.  You should consider what will first go wrong before you focus on what will go right.  If you set up your architecture correctly at the beginning, this becomes easier.  Yes, your project has more boilerplate at the beginning, and you can’t just dive into the things that make programming fun, but remember you are a server; you serve others.  The quality of your work is measured by how close to perfect your work is.  Nobody knows when things are working correctly, but they DO know when they’re not.  It’s a tough life as a server dev because you get very little love.  But you chose that, so what should I say?

Consider at the very start how you’re going to deliver errors to the clients.

 

Think of responses like a textual representation of an object.

I come from Object-Oriented Programming.  Think of responses as objects, and you need an application-wide “baseclass”.

{
    "data" : {
        /* YOUR ACTUAL RESPONSE PAYLOAD HERE */
    },
    "errors" : [
        {
            "code" : 401,
            "domain" : "HTTP",
            "description" : "Unauthorized",
            "recovery_suggestion" : "Your access token may have expired.  Try logging in again."
        },
        {
            "code" : 1001,
            "domain" : "Our Server Form Validation",
            "description" : "Email address invalid",
            "recovery_suggestion" : "Make sure your email is formatted correctly."
        }
    ],
    "message" : "Any arbitary message that is relevant to the response itself.  This response isn't supposed to make sense for any specific context.  They're example fields.",
    "response_time_in_ms" : 1234,
    "status_code" : 200
}

 

It’s not 1982

Mobile Clients prefer textual representations in the response.  Your responses can be verbose and at times redundant.  If you have to echo the http response status code in the payload, why not?  All the pertinent information is in the same place.  To an extent, of course.  It just makes your API that much more easy to work with.

 

The Importance of a Documented API

Your server may be down.  When your server is down, your mobile developer is often stuck when he doesn’t need to be.  Most of the time, mobile devs need any data, so long as it can be used to populate the contents of the UI.  The Server API is a contract.  It specifies what the server team will deliver, and what the mobile developer can expect.  It ensures that two mostly separate teams can work happily in parallel.

If you provide a documented API before it’s even implemented, the mobile dev can get his job done.

It just needs to be simple.  Send these parameters with this method to this endpoint, and you can expect a response of:  (most verbose response here that shows all possible fields that might be defined.  Mark in comments beside that value if NULL can be expected.)

Then you highlight the error scenarios.  Possible error codes and why.

 

Interactive API via Postman

Postman is a very valuable tool.  It’s generally how you resolve disputes with the server devs to the effect of “Server’s broken!  No it’s not!”  You can make your requests outside of the app and inspect how the server is working.  It also makes your bug reports more believable to a server dev, where he can’t really say “stupid user error”.  It’s of course up to the server dev to keep environment variables up-to-date and provide some documentation on how to use Postman in the way the server dev expects you to.

 

This is sort of a working draft, but on almost every project, I wish there would be devs that understand how their work makes its way into the end product.  And if you ensure that your role is one of service, and your customers are mobile developers, keeping a service-oriented mentality, like the Maître d’Hotel, where you derive your happiness when your customers are happy, this surely is the way for you to become a rockstar.

Excellent Definition of a Senior Software Engineer

Found this on Quora and it certainly justified my job title! 🙂

What does this mean for a software engineer: “You are not at a senior level”?

QUOTE:

The Perils of Hackers in your Team

I’ve currently joined a project as the only iOS Developer.  I’ve inherited a codebase that’s passed through the hands of 4-5 guys over the course of 3 years.  3 years is already at least a yellow flag in terms of iOS Development.  In my view, the only reason the same project should be allowed to live for 3 years is if you have older devices to support, or a massive userbase and a fat client architecture (making loss of data an issue).  For startups, you should always consider re-writing your Minimum Viable Product, as so many lessons are learned, so many pivots are made, so many corners are cut, to get you to where your codebase is today.  Cruft (look it up) is your biggest problem.

Poorly structured code will hurt your bottom line.  It becomes increasingly expensive to work with, and adding new features will not be easy, and the chances of introducing bugs will be high.  As much as one can talk about Test Driven Development (TDD), I’ve rarely heard of teams (in the startup world at least) that write tests, and if they do, they write them *after* the code has been written.  (This has proven to be the most expensive way to implement tests).  So, fine, the world is not perfect.  In these cases I would hope that if you are a developer reading this, you will at least put comments in your code and also NSAssert statements (the poor man’s sanity check / testing shortcut).

Let me now define what I mean by Hacker in the context of this post.  A Hacker is someone who may look good to any non-developer.  He gets the job done.  The code “works”.  He appears passionate as he types away in a frenzy, trying to make things ‘just right’.   The thing about a Hacker is that he may be self-taught and completely lack the principles of good software design.  He writes spaghetti code (that works).  He may say things like “I don’t need to put comments, the code should speak for itself.”  (If that’s true it is saying “Help me!” or “I’m taking hostages!” or “Your time now belongs to me!”).  But the worst thing about a Hacker on your team is that he will write code that is often a testament to every anti-pattern you have ever known, and to have to work with that person’s code is like being sabotaged before you can even begin.  Because to work with that code, you essentially have to rip out everything he’s done to make the codebase useable again.  So before you can begin to be awesome,  you have to weather the storm of management (who can’t possibly know your struggles) saying “I’m noticing progress is slow”, or “but it’s working now, what do you mean you need to rewrite it…?”

In short, a Hacker in charge of your codebase is basically signing a death warrant for your current codebase, or paying for a huge financial hangover after he’s gone.  A Hacker on your team can have some benefit (thinking outside the box, enthusiasm), but be wise and make sure he’s not in charge of architecture, and make sure you do code reviews.

Don’t learn your Localization lessons the hard way

There’s a great word in German.  It’s called “Arscharbeit”.  It literally means “ass work”.  But what it really means is a task that basically just sucks.  Is brute force, requires very little thinking, and is just boring and tedious.

Today and tomorrow I have to do some “Arscharbeit” because we didn’t plan localization well enough and now want to re-organize a lot of the way it is done.

We chose a wishy-washy, not clearly defined key-naming system.  In the end it wasn’t quite clear what context the key was defining, so we just had a mash-up of weird key names.  The task now is to rename all of these, put certain keys into specific tables so that re-use will be easier.  And I know that in the end the entire app will still require a complete visual inspection because of values for keys gone missing. 

I won’t go into the details of the refactoring job because it got messy.  I will provide you with two links and just say “Don’t waste time and money.  Read these and do something about them AT THE BEGINNING OF YOUR PROJECT.”  Fixing later is annoying, boring, and expensive. 

http://www.objc.io/issue-9/string-localization.html

http://www.innovaptor.com/blog/2013/02/07/a-localization-workflow-that-works-well-in-practice.html

On the Separation of QA from Development

I don’t know maybe it’s just me, but it’s very important for me to be able to be “in the zone” when I’m programming.  If I’m in the zone, I feel superhuman and am able to accomplish the work of 2 or more people at once.  Being in the zone, in computer techie parlance, is like having a large store of volatile RAM completely loaded with all the information you’re working on trying to solve the problem.  Any time someone turns up to distract you, it’s like they’ve just pulled the plug on your computer.  Now you have to boot back up, load all the data, re-orient yourself with the task, then continue working.  Until the next distraction.

I notice I get extremely hostile when this continues to happen on any given day.  I request home office time a lot, not because I don’t like my co-workers or my work environment, quite the opposite actually, it’s just that I love being in the zone and know that it’s also good for me to be there from a business perspective.

We’re now going through a small QA cycle and so of course there will be bug reports.  What I’ve come to realise is that it’s important to keep testers away from developers.  Because testers will find a bug and feel that they need to tell you about it right away.  But, as mentioned before, they pull the plug each time they do so, then of course probably don’t understand why I slowly want to rip their head off.  “Dude, what’s your problem?”….

Well, here is my problem.  I just explained it.  Use Trello.  Put it on a card list.  Let me get to it asynchronously.  It’s better for everyone that way.  If I need clarification, I will come find you.  Not in any elitist sense, but purely business – my time is worth more than yours.   It’s best to prioritise my efficiency over yours.

Code Police – The Importance of Code Style Consistency

It’s not my intention to talk about which coding style is the best. Everyone has a specific style and their reasons for it.

I do recommend thinking about this topic, and to that aim there is a very interesting tool out there on the market called ObjectiveClean

I’ve enjoyed working with my colleagues on my current project and have a very friendly relationship with my boss. I do however have to chide him from time to time for not sticking to a clean coding style. I joke about being the Code Police. He jokes about keeping me on my toes.

There are certain style conventions that should however be adhered to for the following reasons:
– Conventions create consistency.
– Consistency allows you to make assumptions about how the code is written
– Assumptions allow you to refactor more easily.

What? If for example I have in my codebase the requirement that we write:

someString = @"SomeString";  // note the spaces between the equal sign

I can then easily find strings by searching for = @". You might not think that this is a big deal. You probably haven’t refactored a lot of code.

I spent over one hour refactoring some constants purely because they didn’t follow a standard. Imagine error codes defined like this:

static int const errNotConnected = -1;
static int const errWifiOff = -2;
static int const errFileIOError = 1;

2 absolutely horrible things result by trying to define error codes like this:

i) I provide no context for these error codes. I have no idea what class they relate to, what functionality.
ii) do a find and replace for these. if you put in a Project wide search term “err”… you are going to basically get thousands of results.

Now, the know-it-alls amongst you are going to say something snarky like “well, why don’t you just write a regular expression that will find exactly what you’re looking for?” The answer is practicality. Regex is a bit of Voodoo for most programmers and it’s not exactly pretty syntax despite how powerful it is.

You could just provide a context, and even better, pack these in an enum

typedef NS_ENUM(NSInteger, HSConnectionManagerErrorCode)
{
  HSConnectionManagerErrorCodeNotConnected = -1,
  HSConnectionManagerErrorCodeWifiOff = -2,
  HSConnectionManagerErrorCodeFileIOError = 1
};

From the name alone, I gain a few things:

i) I know which class it relates to
ii) I know what the error was all about
iii) Any time I’m coding I can just type in HSConnectionManager and Autocomplete will give me a list of the enums I’m looking for, so I don’t even need to go digging through header files.

Good habits allow us all to do our jobs more quickly, and make it easier to work with each other’s code. I highly recommend caring about the quality of your work. You can be proud of yourself and others will enjoy coding with you.