Mysterious Trousers

Quality software and amazing support since 2010

We’re a small team dedicated to making you happy. We achieve this through synergizing analytics and best-of-breed social blah blah blah hard work and honest-to-goodness customer service.

Extend not a library more than you are able.

When shipping apps, especially those that deal with CoreData or otherwise keep track of data, you often need to normalize that data or somehow make a correction if things become inconsistent. This often comes at app update time, and it’s usually a block of code you want to run once and only once. For each app I build I end up writing some custom logic to handle it. Today I decided to wrap that logic into a library called MTMigration, available on GitHub. The API looks something like this:

[MTMigration migrateToVersion:@"1.1" block:^{
    [obj doSomeDataStuff];
}];

However, the point of this post is to explain that the API I decided upon varies a bit from my original attempts. It looked like this:

[MTMigration migrateToVersion:@"1.1" 
                      options:MTMigrationOptionOnFreshInstall | MTMigrationOptionOnUpdate
                        block:^{
                            [obj doSomeDataStuff];
                        }];

and this:

[MTMigration migrateToVersion:@"1.1" 
              ifMigratingFrom:@"1.0"
                        block:^{
                            [obj doSomeDataStuff];
                        }];

Though I’d already identified a real-world problem that needed solving, namely allowing a block of code to run once on an update, I began imagining all the different scenarios MTMigration might also cover. “You might want to only run the block if you’re updating, or if you’re on a fresh install!” I pontificated, “Or maybe you only want to run it if you are upgrading from a specific version!” said I.

I quickly realized that I was no longer solving a problem I actually had. As I began thinking about the implementation details, it became clear I had no real use-case to test my bright ideas on, and it began to get messy. So I scrapped it.

This principle extends to all aspects of building a library. None of the APIs I had debated about are “bad” or “wrong” in any way, I’m just not in a position to implement it. I have no real-world use for them, so I’d likely do it wrong. I really hope someone comes along that is having those exact problems, as they’ll make a killer extension to MTMigration, with the experience to back it up.

I’d encourage all developers to keep this in mind next time you’re writing a library. Are you trying to solve problems you actually have, or at least have had before? If not, consider dropping the feature. Add it when you do have the problem, or if it’s open source, let someone else take a crack at it that’s actually experiencing the problem. If no one is actually experiencing the problem, well, there’s your answer.

MTQueue

Just released a new cocoapod called MTQueue. We encourage you to check it out:

https://github.com/mysterioustrousers/MTQueue

dispatch_async statements are hard to read and hard to type, even with code snippets. I’ve been using it in lots of projects and it is so much easier to read code that looks like this:

[MTq network:^{
    // a network call
    [MTq main:^{
        // display the data from the web
    }];
}];

It comes with 8 shortcuts for the most commonly used queues. So, add pod 'MTQueue' to your Podfile and give it a whirl.

Code Styling and Formatting

Opinion vs Fact

I’m going to share my opinions about some code styling rules and then back them up with facts about why they are more efficient to try and convince you to agree with me.

General

  1. Do not be agnostic about coding styles. Code styles help train your eyes to recognize and read code faster. Everyone should use the same styles per language.

  2. The creator, or the person/group that made a language popular gets to set the coding styles for the language. This includes casing, naming, spacing, etc.

  3. If #2 is impossible, you should do a search on github to find out the most popular styles for the language and use those.

  4. Don’t be an annoyingly stubborn renegade. How you style/format your code has no affect on your ability to write elegant, clean, correct code. (Notice I didn’t say creative code, no one appreciates a creative alternative to quicksort…unless it is actually faster, in which case you’d be famous).

  5. If you are unwilling to break old habits, please resign fom the coding game. Your brain will go stale, get rigid and you will become more and more resistant to things that will make you faster, better and more efficient. It will no longer be able to think out of the box enough to innovate. Change and break habits regularly…hopefully towards greater unity with all other coders. I have a dream where we all can read each others code and think we wrote it.

Specifics

  • Asterisk placement: the asterisk goes by the variable name, not the type. This is not logical, it’s practical. The asterisk is contributing to the type, indeed, good thinking, but because of how pointer languages are designed, a multiple declaration statement needs an asterisk by every variable. Fact: the majority of people put it by the variable, that is reason enough.

  • Alignment: If you have a series common statements, go to the extra effort to align them. Usually this is in the form of aligning equal signs on a series of variable assignments. Fact: if you would rather open a raw csv and scan the data instead of opening it in a spreadsheet application so that the columns are aligned, you are weird and cannot relate with normal people, but please align code anyway to help the rest of us.

  • Whitespace: Again, to help your eyes group things together logically. I saw objective-c code the other day without a single line between methods. It was very hard to scan with the eye. It is also good to add more spacing between supergroups (logical groups of goups. e.g. Classes separated by more space than methods within each class). It depends on the language but 1-2 spaces between methods of the same purpose, 4 between groups of methods, 8 between classes, etc. is very easy to distinguish.

  • Braces: this is the most heated debate, but I’m about to put it to rest forever: both. Assuming the language uses braces, put the brace on a new line if the signature of the block (usually a method or function) is abutted against the left side of the document. Then, braces belong on the same line for everything else, like control statements, blocks, lambdas, etc. A brace on a new line when scanning down a file helps the signature stand out against the code of its body and makes it more visible as you scan down quickly the left edge of the file. If you put braces on new lines for everything, your code starts to look like mostly braces and it becomes too vertically stretched to distinguish groupings by spaces. It also doesn’t look as weird if you omit the braces in the case of a single statement after the control flow statement. Your eyes can effortlessly tell the difference between functions/methods and if/else/for etc.

  • Wrapping: only wrap code if you can do it in a clean way AND only if it goes past ~100 columns. Code that you have to scroll for miles to read is inefficient and people with wrapping ticks keep their code to about 20 columns and it is very difficult to tell where one logical line statement ends and the next begins.

  • Horizontal spacing: always put space between operators and constants. for(int i=0;i<20;i++) is simply cryptic!! Why do we see this so much! I’m embarrassed for us that I have to mention this. Fact: for(int i = 0; i < 20; i++), enough said. Some people go overboard with this, be reasonable, do what’s popular. Lastly, if the parameter of a method is syntactically busy, pad it with a space before the braces so that your eyes can read it as its own statement. No need for simple sqrt(4); stuff.

  • Misc: give up any other weird crap you don’t see anyone else doing, like putting a space before every semi colon at the end of the line. Putting the dot at the end of each line instead of the beginning when method chaining, etc.

Conclusion

No man is an island. Increasingly, you have read others code and, more scary, other people have to read yours. Lets be considerate of one another and write code that we can scan, navigate, distinguish, recognize and read more efficiently because its all consistently styled, logically grouped, spaced and aligned.

Core Data + Concurrency

So after many tries I have learned many very bad ways to design a concurrent + core data app. I think the best I’ve come up with is a singleton where every method has a callback and the singleton makes sure every core data operation happens on the main thread.

Why? Because when you want to display an objects data on the screen you are going to pull it out of managed object and assign it to some UI element. In doing this, you may fault the property causing a read, which if your context wasn’t created on the main thread, COULD cause an exception.

The alternative is to pull everything off an object into variables (copied?) and then use the variables to update the UI. Sounds super tedious, there’s gotta be another way.

I think that if you keep your commits small (so if you need to commit something huge to core data, break it up and jump on and off the main thread making only small commits each time), I don’t think you’ll see any interface jitters.

So that’s my best “simple rules” idea for now, if you’ve come up with something better, please e-mail me at adam@mysterioustrousers.com and I’ll post your superior design. Or I’ll try and shoot holes it in with you ;)

Zeus

Zues is a really cool gem that preloads your Rails environment so commands like rails console, rails server, rails generate, etc. boot in less than a second. Works as advertised. All sorts of awesome.

© 2013 Mysterious Trousers, LLC. All Rights Reserved. Background photo by hsld