Make Money Outside the Mac App Store book cover

My book is out: Make Money Outside the Mac App Store.

Own your products and know your customers: sell outside the Mac App Store. In a few hours, you’ll have in-app purchases, a trial mode, and piracy protection all set. The book includes fully functional sample projects and code ready to be copied into your app.

Magic Numbers Represent Concepts

Literals represent something.[p 94, 1] Magic numbers are a form of literal.

The number 79 can truly represent the result of 80–1.

When height = 80 and offset = 1, the resulting number 79 represents a relation between the height and an offset.

Working with “magic numbers”, that is numbers that are not named using variables/constants in the first place, poses a problem when constraints or relations change. You cannot reliably “Search & Replace” every occurence of 79 in your project with height - offset – some 79’s could have meant something different before.

Thinking about readability first when you write code reduces these problems to a minimum later. Give literals meaningful names.

Swift accidentally provides namespaces for stuff like this with enums without cases. Then you don’t clutter your functions with constant definitions. The following example is quite convoluted, but brings the point across:

enum Layout {
    static let height = 80
    static let width = 100
    static let padding = 1
    static let margin = (top: 0, right: 10, bottom: 0, left: 10)

func putStuffOnScreen() {
    let previousFrame: CGRect = // ...
    // ... 
    let newFrame = CGRect(
        x: previousFrame.x + previousFrame.width + Layout.margin.left,
        y: previousFrame.y +, 
        width: Layout.width + 2 * Layout.padding,
        height: Layout.height + 2 * Layout.padding)
    // ...

  1. Edward Yourdon and Larry L. Constantine (1979): Structured design, Englewood Cliffs, N.J.: Prentice-Hall.

Swift 2.3 NSLocale UIKit API Changes Break iOS 8 Compatibility

We’re converting a rather big and clumsy project to Swift 2.3 at the moment. Strangely, NSLocale gives us a lot of headaches. The API hasn’t changed visibly, but the implementation seems to have.

From Objective-C’s point of view:

@property (readonly, copy) NSString *currencySymbol 
API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

And from Swift’s:

extension NSLocale {
    // ...
    @available(iOS 10.0, *)
    public var currencySymbol: String { get }
    // ...

That property certainly isn’t new. Neither are the dozen others in that header file from Foundation.

iOS 10 Foundation API diffs reveal:

Added NSLocale.currencyCode
Added NSLocale.currencySymbol

Huh? But they were there all the time! The app used these properties since iOS 8. It is clear something is wrong here. The compiler forces us to now access these properties with availability checks for iOS 10 and newer. The else clauses (for <10.0) don’t know nothing about these properties at all, though. It’s a compile-time constraint for a runtime issue (kind of).

Shadow protocols don’t work:

protocol Swift22LocaleFallback {
    var currencySymbol: String { get }
    var currencyCode: String? { get }
    var localeIdentifier: String { get }

extension NSLocale: Swift22LocaleFallback { }

The result is another compiler error, this time in Foundation.NSLocale, “Protocol ‘Swift22LocaleFallback’ requires ‘currencySymbol’ to be available on iOS 8.0.0 and newer”. No chance.

You know what does work? performSelector.

if #available(iOS 10.0, *) {
    formatter.currencySymbol = locale.currencySymbol
} else {
    let result = locale.performSelector(Selector("currencySymbol"))
    formatter.currencySymbol = result.takeRetainedValue() as! String

This is a strong indicator for me to upgrade other projects to Swift 3 instead of 2.3. #radarorgtfo rdar://28363526

On Proprietarity of File Formats

The latin root of “proprietary” indicates this is something someone created in a special way. We can say it is owned by someone, intellectually. But then again, every file format was conceived by a human being; so the origin alone doesn’t suffice to grasp this concept.

Take a look at the general introduction of “Proprietary format” on Wikipedia. Accessed today (2016-09-18), it reads (highlighting mine):

A proprietary format is a file format […] that contains data that is ordered and stored according to a particular encoding-scheme, designed […] to be secret, such that the decoding and interpretation of this stored data is only easily accomplished with particular software or hardware that the company itself has developed. The specification of the data encoding format is not released, or underlies non-disclosure agreements. A proprietary format can also be a file format whose encoding is in fact published, but is restricted through licences such that only the company itself or licencees may use it. In contrast, an open format is a file format that is published and free to be used by everybody.

In a nutshell, it is …

  • a secret file format: only people from the original source know how to use it;
  • based on (usually unpublished) specifications;
  • not meant to be used by everybody.

These are different things. Let’s explore them further.

I can use XML or JSON and come up with a specification for my apps data storage. If I don’t publish the specs, how would you know how to use it? It’s plain text, so you can reverse-engineer the specification. But that won’t be 100% reliable; also, app updates could break your interpretation of my format since I don’t promise to not make changes.

A fantasy specification like this is not open. When the specs aren’t open, no 3rd party can rely on the format. When nobody can rely on the format except the inventor, then this format is closed for use.

Open formats, as cited above, are based on published specs and free to use.

Even without any documentation, a short notice of not intending to break the current version of the format can help 3rd party developers build programs using a format. Their reverse-engineering then is more likely to stay functional. “Freezing” the specification this way facilitates growth of an ecosystem around that format, even if the spelled-out specs are only available inside the head of the inventor. Without freezing the format, we cannot safely assume that we’re welcome as a 3rd party. Is a frozen but private format proprietary or not?

Here’s a suggestion to differentiate “open format” further:

  • Technological openness: can you open the file with a standard editor and read it? Applies to plain text-based formats, but also SQLite database files. Reverse-engineering binary formats with HEX editors or similar isn’t very fun.
  • Intentional openness: can you safely assume that the author wants you to work with the data, read it and write your own? Or is it likely the author will consider you an intruder?

I suggest the term “proprietary” to be used for formats even if they are based on plain text, when the intention is to keep the specs to oneself.

  • Markdown is an open format: it is technologically and intentionally open. This has helped a lot to create an ecosystem around the format. (Same with reStructuredText and Textile, both less popular, though.)
  • Day One v1 used XML, technologically open, but intentionally … not so much. It was stable, but only accidentally, not intentionally. There were 3rd party tools to create Day One journal entries using scripts, which was fun and probably added to the appeal of the app. (Day One v2 switched to a fully closed format.)
  • Apple’s office software (formally called iWork) uses technologically and intentionally closed formats: .pages, .keynote, .numbers. (I’d love to make Pages’ files monitorable in the Word Counter, but it seems I’m out of luck here.)

It took the world a while to get a published specification for PDFs, Photoshop files, and the like. Chances are the applications you use each have their own file format to make storing data easy for developers and to provide some extra features.

So even if it’s easy to use someone else’s (i.e. “owned”) custom file format, it doesn’t automatically mean that it’s open. Like library and API design for public use, designing file formats for use by the general public requires a different mindset of responsibility. Honestly, I wouldn’t want that responsibility, either, if that means limiting my options to improve my software. (I guess that’s why creating Day One v1 journal entries did work well but wasn’t officially documented.)

Narrowing down to text-based user data: in the end, only plain text is really durable. Day One v1 stored journal entries in XML files that added very easy to understand metadata to Markdown body text. I’d say YAML front matter (see an example) would’ve worked even better in terms of data portability, but basic XML was okay. People could easily create an exporter on their own.

Plain text is also a format where users can screw up the data easily. Nobody would open a PDF in a text editor to make changes and destroy file integrity. Sticking to the example of YAML front matter, it’s easy to introduce parsing errors accidentally when you have lines like:

title: New idea: break this parser

Which would have to read:

title: "New idea: break this parser"

… so the parser knows where the meta data key (title) ends and the value begins.

I design my software around plain text and use TXT files as an API. (Most of these projects you don’t know, yet.) Because then 3rd party developers can chime in and provide shortcuts, overviews, or otherwise participate in the ecosystem of handling textual data. It’s more work than coming up with my own format.

There’s a good reason that Excel files are so complex; or that Numbers doesn’t store files in CSV format. The advanced features don’t map to simple textual representations easily. On the downside, Numbers changed file formats in recent years, and so did MS Excel. Microsoft’s format is owned, but it’s published and they clearly want developers to build upon it.

The thing is: for most people, a textual representation would be sufficient. Calculate a sum of values in a column doesn’t require a sophisticated file format. (Few business use cases stop here, I admit, but lots of private use cases do.) This could be done with a few clever conventions, maybe using MultiMarkdown table syntax to have prettier layout.

Plain text “databases” can be used on any platform (ignoring file encodings for the sake of argument) and with any editor. Migrating from one app to another is easy. (And oftentimes not encouraged, of course; vendor lock-in can be a tool.) If an app states that it cares about you, your data, your life, family, dogs and cats, it better use a widely adopted file format. Open formats are even better, plain text being the king of all.

Comment On “Real World Flux Architecture on iOS

The Flux architecture Benjamin Encz describes for the PlanGrid iOS app is like ReSwift only on a per-component basis: the user interactions fire change events that a store takes care of to mutate its state. The state then becomes the input for the view again.

It’s much like MVVM, whereas here the view model is the store’s state.

This Flux-like approach is still a big improvement over convoluted view controllers or not thinking about data flow at all. But I wonder if the gain is so much higher compared to properly separated MVC. Who reads the store’s state? Only the views? Then the state is truly a view model; but how do side-effect populate to the rest of the app, like renaming or deleting things? I’d tend towards dispatching the change event to other stores, too, which may or may not react to the event. Then the view component’s state is updated independently from the database, say, using the same event dispatch mechanism.

To model the flow of truth on a component basis (which is still uni-directional: from store to view) compared to a single global app state (ReSwift) sounds like a very easy to do component redesign. You can start with anything and “fluxify” it. Then move on to the next component that’s particularly convoluted. You may not even want to convert all your components to this data flow approach when some components are simple enough as they are. Symmetry of component design will suffer, of course, but if you’re aware of this and conclude it’s better not to convert everything, that’s fine.

With ReSwift, I interpret the global app state to be a state with real (Domain) Model objects. To make a state displayable, I derive view models from it. This came very natural to me. But Ben’s posts got me thinking: could there be situations where keeping view model state around is better than keeping “real” model state?

TableFlip Will Be Released in October!

Screenshot of TableFlip
TableFlip’s roadmap as seen form within TableFlip

It is time to go public: I’ll release TableFlip in October.

Sign up for the release notification:

Much love goes out to my beta testers! ❤️ You are great! I didn’t anticipate that we’d have so many discussions. Thanks for all your amazing feedback so far. The past 12 weeks were wild; now it’s time to calm down a bit and make things right.

Tests Are Just Code, Too

From “Testing, for people who hate testing”:

The thing is, tests are just code. If you have a hard time constructing your own objects with some particular state, it might be a sign that your API is hard to use!

This is all there is to the magic of test-driven development, we could say. A test is client code. This means it doesn’t have the inside perspective of the object or module under test. It has an outside perspective. Through tests you see how your production code is used (by other parts of your code or by other people in the case of libraries, say).

You start with a test. This means: you start with an outside perspective, asking yourself questions like “What would be a good (public) interface for this?” – The opposite is ad hoc reasoning, something along the lines of “I have this NetworkManager there and maybe just call it and return the JSON. Okay. Oh, now JSON doesn’t work, I need to send a custom object along, so I’ll just parse the JSON and create an object. But if that fails, hmm, I cannot send nil, so I’ll force unwrap and let someone else deal with this.” Or something. These improvised solutions can cause trouble because all they do is focus on the perceived requirements of the object you’re writing, ignoring the requirements of code that uses the resulting code.

Writing tests first kind of equals writing your app outside-in, starting with the calling code, then implementing the code that’s to be called. Only test cases are super focused and you verify a lot more behavior and setup code with a single run than you could ever do with manual testing.

Experienced programmers will be able to switch perspectives even without writing tests. Their experience helps them to make it less likely to produce waste, whereas “waste” is code you write and then discard because you find it doesn’t fit.

Global State Was Preferred Because Typing Sucks

According to Ed Yourdon, in the 1970’s global state was actually widely preferred over passing parameters to functions or subroutines.[79–80, 1] I had to laugh when I read the paragraphs on the most common objections, but this seems to have been a serious issue.

The objections listed are:

  1. Typing parameters means more typing, i.e. more work
  2. Getting the parameter list right is error-prone
  3. Accessing global state used to be more efficient

Yourdon dissipates the objections:

  1. Typing more parameters takes a bit of time now, but hunting bugs due to global state takes lots of time later.
  2. Errors in getting parameter lists rights are local and easily fixed; again, hunting bugs which appear because of global state involves way more detective work.
  3. Even in ’79, machine time was less expensive than “people time”: hunting bugs isn’t worth the premature optimization.

But think about this for a moment. How spoilt we are using Xcode’s or any other IDE’s auto-completion feature to actually tell us parameter lists when we need them. Having to remember parameter lists and getting the sequence of unnamed parameters right was a problem sooooooo severe, people rather used global variables instead.

Crazy. Today people still have to be meticulously taught when and why global state causes trouble. In object-oriented programming, Singletons are the reincarnation of global state.

  1. Edward Yourdon and Larry L. Constantine (1979): Structured design, Englewood Cliffs, N.J.: Prentice-Hall.

Programmer, Interrupted

Okay, interruptions kill productivity. Another recent article mentions planned interruptions to make things even worse. They talk about meeting appointments, for example.

But I dare say: interruptions are only ruining your day if they are external. If you take a break, things don’t look that bad. You can train yourself to re-focus. And I argue this is a useful skill.

It took me a while to train this skill, but nowadays I’m interrupting myself at my home desk every 30 minutes, get up and move a bit to stay healthy. I don’t need 10 minutes to refocus. I sit down, take a deep breath, and continue to write code. Just like that.

Heck, I even wrote an annoying break timer to force me to get up.

Talking makes things worse, though; makes it harder to re-focus. That’s pretty obvious, isn’t it? After all, you switch contexts and engage in a different activity that uses a lot of your attention. Socializing is important to us pack animals, so there’s no way to not read faces and listen for subtleties in intonation. It’s just what we do. And it pulls all of our attention away from other things.

If I have the work break for myself, though, I can continue to mull over a problem in my head. In this case, getting up and leaving the keyboard means to interrupt an activity that may not lead anywhere at the moment. I bet you know this situation: you can’t seem to figure out how to fix a bug because some components are too entangled; whenever you try to change something, something else breaks. (Of course this never happens in your own projects.) A break then interrupts the need to type on the keyboard and produce code. It helps switch from typing mode to thinking mode. It’s like facilitating the proverbial ideas you always seem to get in the shower.

If you’re afraid of interruptions eating away your productivity, I challenge you to install controlled breaks every 30 minutes to get used to the flow. Sitting for an hour straight already kills your body. You won’t notice if you’re not reasonably healthy; it just feels normal, but it isn’t normal.

I bet that my training to do regular work breaks makes me more resilient to short external interruptions. Put me in an office and see for yourself 😀

On Software Feedback

For some reason, I couldn’t find or load Dave Winer’s comments, so I decided to blog about it instead: Dave reported that after announcing to shutdown of his outliner Fargo in 9 months, now users just get in touch with him for the first time.

This makes me wonder: is it too hard to provide feedback from inside Fargo?

Making it easy is not the best thing to do at all times. I know one person who could say something along the lines of: “I don’t want to make things easy for people. I want to attract the right kind of people instead, those that really care.” That’s good advice. Especially if you do client work. Nobody really wants to deal with disrespectful/irritating/stupid/lazy/… people. So some kind of entry barrier can help filter folks out.

But I don’t want to make it hard for consumers and regular users of my software to get in touch. Now Fargo is free software. There’s that saying that people tend to behave worst when the product they’re complaining about was free or very cheap. One oft-mentioned benefit of “pro-pricing” is that you will attract customers who will care more about the software, provide better feedback, and are overall less annoying.

Side-note: All the users of my software seem to be recruited from Happy Land, where only smart and nice people reside. Thanks for being part of this, folks!

So what if Dave encourages users to write outlines in Fargo and send them as feedback? Would that help? Would it make matters worse? Will he drown in shitty e-mail? (Because he’d then be helping users stay dumb/unresponsive?)

On a related note, Brent Simmons wrote about feedback forums in beta testing. That, too, is a topic of collaboration and communication.

I plan to experiment with this. I will integrate ways to provide feedback right from within the app. Maybe even tie this to events. For example “user launches app for the first time in X days: do you miss something?” makes sense for a tracking app like the Word Counter. (Not so much for an app like TableFlip.)

→ Blog Archive