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.

Let Them Perish

Last week, Red Queen Coder’s blog post about iOS job interviews was discussed a lot. The interviewers asked her to sketch how to implement a linked list on a whiteboard. She couldn’t. And thinks it is pointless. (I agree.) But then people on social media responded that she should just learn (that is: memorize) that kind of stuff to get a good job. Read her transcript, it’s a well-written story of how a job interview and the onslaught by narrow-minded people who defend the status quo (and their own status as the establishment) made her wonder what’s wrong with the community at large.

When I studied sociology at University, there was a nice figure of speech; the German term is “Stallgeruch”. A translation seems to be farmyard smell, though “barn smell” would be the literal translation. In English, the figurative translation is “being from the same stable.”

That’s what interviews are good for: to filter out participants who don’t match. Their smell is too different from the rest of the animals, so to speak. Every entry barrier is a means toward that end, interviews being only one way of many. Employing anybody without assessing their skill somehow would be nuts. I don’t want to hire my neighbor as developer for my team – he’s a janitor. I want to make sure I get a developer who fits the task. Putting up some sort of filter or entry barrier is mandatory.

Red Queen Coder mixes up a few things, as is Russ Bishop in his blog post reply (which I recommend you read, too). Russ argues that formalized interviews are bad predictors of job performance. It seems both are accusing companies and recruiters to do a bad job at hiring good people. But that’s not really the point.

I am rather lazy and would be kind of pissed were I to travel to, say, Munich (5+ hours of train travel), only to be presented with pointless interview questions. What a waste of time, indeed! But neither RedQueenCoder nor Russ Bishop is annoyed by stupid interviews alone. They don’t complain that their time got wasted. (Merely venting these feelings would be a boring story, too, by the way.) Instead, they complain that these companies are doing a bad job.

Let them continue, I say.

Nobody has a right to be employed. We don’t just deserve good jobs.

We struggle to find a good fit – or we “go indie” and create our own future.

I don’t know what’d have happened if I hadn’t thought about job interviews this week, but were I to be interviewed in the future, I’d laugh and leave if the recruiters asked me to sketch a linked list algorithm. Because, honestly, what good a fit is that company? Let them continue, and let them perish. It’s their responsibility to keep the business alive, not mine.

“The community” doesn’t appear broken to me, either. This year, I got in touch with a bunch of developers around the world. I hang around in iOS developer Slack channels with amazing people. I went to my first conference and talked to folks and had a great time. All of these people seem to be genuinely nice. It’s not the community per se which is sick. It’s business. That’s only natural, since a company is not not a human being. It’s part of economy (as a social system), operating to the code of profit. If you and I talk to each other, our topics may shift and we may get to know each other from different angles; to a company, you’re only a means to its ends. Interviewers play the role of gate-keepers. They may as well be sexually attracted to you, for example, but that doesn’t change the company’s perspective a teeny bit. (As long as they do their job properly, that it.)

People make a difference. Small teams looking for friendly and skilled people can show their attitude. A 1000+ people corporation has no face to show. If you end up flabbergasted because an interview was shit, you may just as well have tried to seize the wrong opportunity.

A few months ago, I skyped with 3 folks from The Soulmen, makers of Ulysses, who are still looking to expand the team. Founder Max Seeleman and 2 developers (I think it was Friedrich and Götz) were on the call. Relaxed, smiling. They were friendly and we chatted about our plans and expectations. When I met them in person at a conference, I still found them to be very likable. They are a crucial part of the team and do a good job representing … themselves. They are the team. There’s not much of a role they have to play. Of course I don’t know either of them from the perspective of a family member, say. I got to know them a bit as developers. If you’re looking to be part of a team of developers, that’s all you need to know: can you like the people and can you relate to their work? The Soulmen as a team isn’t fragmented like a big organization. It makes no sense to even try to say the same for a company that scaled well beyond 30 or so people and begins to establish hierarchy. You start as a team; if you scale up, you end up with an organization where people may not know each other in person anymore.

Formalized interviews are part of bureaucracy. Formalization itself is a crucial part of bureaucracy and thus organization. It helps to reduce uncertainty. It helps form expectations about the outside world. The Soulmen, for example, don’t have to formalize the process; they have the luxury of being small enough to just get to know people and then see if things work out. It’s personal. A company or organization cannot be personal, because there’s no representative persona available. Heroes don’t count, either. Apple wasn’t Steve Jobs. In a company, your closest co-workers matter more than other departments. That’s part of human group-think, I guess. If a single group is all there is, if the company is really a small team, things look totally different.

Sure, bad interviews are bad filters. The organization will suffer from them. It’s not our problem, though.

As a side-effect of bad interviews, talented and well-spirited people feel bad for being treated like a commodity. I can relate to that. But that’s the world we created for ourselves over the last 200 years. It’s not pretty. I don’t like the way things work. But you know what? I like to develop apps. And I’m struggling to survive. Literally. I live below the poverty line for years now. I understand this is a risk not everyone wants to take. I don’t believe “getting a job” is a viable solution for folks like me, though. Even if the interview process isn’t stupid, the work may turn out to be a drag. Because organizations cannot offer fulfillment. They use your time and skill and trade it for money. Being indie offers a totally different perspective. Teams like The Soulmen do, too. You may find fulfillment there; a place where you can express yourself through the work you do. Organizations which conduct formalized interviews at all, not so much.

So let these corporations continue their stupid practice. It’s not your business or responsibility. Worrying about stuff outside your circle of influence only drains energy. I’m not here to advise corporations how to recruit really talented people. You probably aren’t, either. I believe in talented and inspired developers, though, as developers, not as cogs in a machinery. I want to empower developers to learn, to become better at what they do. No computer science degree required. I don’t care if my writing helps getting a job because I don’t care about jobs. If you worry about being employable, you worry about the wrong end of the stick.

This isn’t an elitist speaking. Quite the contrary. If you had to categorize me, you’d say I’m a punk, not at all part of the establishment. I don’t think economy at large has anything to offer for people. That’s why I say: let them perish, let them burn, then fill the holes with something better.

Being a working-class child myself, I know how much effort it takes to break out of the system of beliefs which puts employment first, “making” a family second, and recreation and luxury third. (Where’s self-expression on that list, pa? How does spending all your waking hours for someone else’s goals give you satisfaction, mom? I think I know what makes you sad and feel excavated: it’s our heritage itself.) Changing attitude can be done. And if you’re done, you don’t care about a stupid job interview anymore.

My best friend’s father used to say: tell me, why should the mighty oak tree worry when a boar rubs its back on its bark? You can’t hide from the boars out there; but you can grow strong enough to not be shaken by their behavior.

Let them continue their practice. It’s a process like evolutionary selection; find out on which side you want to stand in the process. Things will be fine if you figured that out. One way or another.

Let them continue, and let them perish. You’re better than that.

Clean Swift aka VIP Architectural Approach

The folks at wrote a blog post about iOS software architectures. The comparison of VIPER and Clean Swift/VIP is very interesting: the VIP approach favors uni-directional flow, which I like very much. The article is worth a read for that alone!

They falsely consider MVC and MVVM to be software architecture approaches, though, and too point out that MVVM and MVC suffer from similar drawbacks.

My Declarative Breakthrough: Wherein I Stop Thinking in Terms of Object Collaboration

I just grokked how value transformations can not be a pain in tests. I’m writing a simple export module which takes a table from TableFlip and renders it as LaTeX. So the input is a Table and the output a String.

But the module is not just a single function, mind you. That’d be a huge function, and not very open for configuration changes later. I factored it into a few sub-components, of course.

Now how do I write tests for the object which does convert a table to a string when I also have to write tests for the sub-components without merely duplicating the test cases and without writing integration tests?

That’s when it clicked.

How I First Ended up With an Integration-Test Situation

The conversion is made up of these components:

  • LatexRenderer – the module’s public interface
  • LatexExportBuilder – used to configure rendering
  • LatexTableBody – converts tabular data to strings with “&” etc.

The LatexExportBuilder accepts 5 different settings and its build() method uses a LaTeX template to render the actual string. One of its non-optional settings is the LaTeX table body, a string itself. The builder only puts the values into proper places in the template; that’s all it does. That’s enough of a responsibility already.

From there follows that rendering the table body is the responsibility of another object. I call it LatexTableBody; it doesn’t do anything, it is the body. You put in a table upon initialization and it exposes methods to access the string rendition (or serialization) of the table. In Java-inspired object-oriented design, this would be a LatexTableBodyRenderer with a render() method. These are action based names. I chose data-based names without a notion of activity; its methods are called bodyRows() -> [String] and headerRow() -> String?. For convenience, it also exposes joinedRows() -> String. You see, no activity, just state transformations.

Then there’s a class which sets everything up. Its the LatexRenderer. It configures the builder and has a method render() -> String which delegates to the other objects for conversion.

I wrote LatexTableBody tests already. And I wrote LatexExportBuilder tests for template configuration. The renderer uses them both. How should I write assertions for the renderer when its behavior is basically the product of both existing test suites?

Changing the Interface to Stick to the Core and Expose the Resulting Builder

Testing the string results of the renderer won’t cut it. I’d have to duplicate template assertions all over again. With variations of the table body. It’d be a mess of essentially duplicate test cases across 3 test suites. Then there’s another solution, equally unattractive: rewriting the objects to be reference type objects (class) and using mocks to verify the renderer delegates properly.

Thinking about stuff I read in the past couple of weeks about declarative interfaces and how value objects are data things instead of behavior-rich classes, I came up with a different solution.

I made the LatexExportBuilder equatable; the actual build() call isn’t very interesting from the renderer’s point of view. It matters that calling build() produces the same result for similar configurations. That’s what its tests ensured. When two builder configurations are equal, the resulting string is going to be equal, too.

This opened up a new way to test the renderer. Instead of writing assertions about the resulting string, I could write assertions about the resulting builder configuration.

That means I won’t duplicate the actual string rendition tests. And I won’t need mocks, either.

Minimizing the Integration Layer (and not testing it at all)

The renderer becomes a “configurator”. Client code obtains a builder and can even alter the default configuration if needed. Tests verify the correct setup. All is good and well with this functional core.

I stick with “renderer”, though. A convenience render() function returns the result of That’s a single line which I will not even need to test. The core functionality is well-tested, and this super thin shell around the core will not get better when I write integration tests for it. It’s so tiny that its impact is negligible. And integration tests are a scam anyway.

So that’s this declarative power everyone talks about. Thinking in terms of good old OO design, I was stuck with thinking in terms of writing assertions about the delegation itself: assertions for the method calls of collaborating objects. With a declarative, black-box, input–output-mindset, I could instead use value objects to encapsulate and represent the transformation steps – and write assertions for them instead of the primitive string result.

How to Refactor Messy Apps for a New Architecture?

When facing a legacy code base, changing the mess to an orderly architecture can cause confusion: where to start? What to do? An exemplary question:

How do I refactor a Big Ball of Mud into layered architecture?

Refactoring1 the existing code base seems like a logical step; after all, refactorings are designed to improve existing code, and improvement is what you’re up to.


  • Changing the existing mess is a confusing process because your mental model from deciphering the legacy code gets in the way. You cannot interpret existing code one minute and come up with great new designs independent from the mess you have the next.
  • Seemingly clear cases get in the way: moving a view controller sub-type into the UI layer sounds trivial. It’s misleading, though, since most view controllers are a mess of responsibilities. So filing away the object as a first step will not be helping at all.

My advice:

Create a new model of the application. Start from scratch, and start with drawings on paper. This is an exercise to understand the problem and solution space in a new way. Then you may decide if your legacy code can be re-used to fit the better architecture or if you have to rewrite parts of it. If you look at the old stuff all the time, you can only force yourself to make incremental improvements, not re-designs.

It helps to factor the new model into modules and submodules in advance to start somewhere. Instead of stopping at 4 layers in your app with a bunch of objects in them, identify submodules and communication paths, too, so you can hunt for a small-ish part of the app that you can improve.

To learn how to apply a particular architecture, it’s better to start with a greenfield app or a toy project so you can get a hold of the concepts first without worrying about breaking a shipping app. With experience, it’ll be easier to identify new seams in old code bases and change things for the better.

  1. This is only a refactoring on the app level, as in “improving its code,” but not in the usual meaning: “Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior.” ( I’ll go with the colloquial use of the word here anyway.

MVVM’s Place in Your App

Picking up on my post MVVM Is Quite Okay at What It Is Supposed to Do”, here’s a few images which illustrate the problem of mistaking MVVM for a solution to a structural problem. It’s the whole post in 2 images.

Model–View–View-Model helps with the view layer. It can be a tool to break up a view controller into smaller things. But it’s still only a refactoring of view components into more objects.

diagram of MVVM in the view layer
MVVM in the view layer

That’s useful and not a problem itself. But it doesn’t help if your overall app is a mess.

The technical term for “mess” on the level of software architecture is “Big Ball of Mud”; combine MVVM and BBoM and you have … MVVM in a BBoM.

diagram of MVVM components in a chaos
MVVM in a BBoM. Kind of rhymes, doesn’t it?

There you see that MVVM can affect the picture of your architecture – but not by much. It’s a design pattern you can use to solve a particular coding problem, but it can’t bring order (or structure) to the chaos.

Developer Documentation App Dash Removed from App Store – and No-One Can Do a Thing

Dash was removed from the macOS and iOS App Stores: Apple terminated the developer’s account without further notice and does not provide additional information.

This is a very sad thing to happen to Bogdan Popescu, sole developer of Dash: as far as I can tell, Dash is the only app he is selling at the moment, and now the exclusive iOS store was taken from him. The macOS App Store was probably more lucrative for Bogdan than selling licences on his own – at least that’s what other developers consistently report when they sell on both platforms.

So here’s another reason why Apple’s App Stores are risky for developers. Not only will search ads skew the results. And not only do you have to make up for the 30% cut by Apple. Developers have no way to defend themselves against giants like Apple (or Amazon in the realm of books, for that matter). There’s no separation of powers. The companies own these channels. It feels weird that they can do as they please, but there’s nothing to complain, really.

The power of the customer is limited, too. Do you know anybody who doesn’t have a strong opinion why his smartphone is better than someone else’s? Anybody who would switch platforms at will? Who won’t lose anything in the process or find it painful? – I don’t, and so there’s no real pressure for Apple in the long run. Not paying for the next iPhone and using Android instead is not an option for most iPhone users. It’s probably even worse with Macs. I wouldn’t want to use a Windows or a Linux PC if I can help it.

TableFlip Launches

I pushed the button. Now TableFlip is here!

TableFlip is a text-based visual table editor. It will become your go-to application to edit tabular data because it’s blazingly fast, lightweight, and fun to use.

You can use it to quickly create tables from scratch and copy the result anywhere – or you can use it to edit tables in existing documents. That’s what “flipping” stands for:

screenshot of TableFlip
Open your document in TableFlip and you can it in your editor AND in TableFlip simultaneously!

TableFlip is designed to remedy a pain in your Markdown workflow: handling table markup. Typing Markdown tables sucks. TableFlip lets you edit data in a slick visual interface. And then it saves the result as clean Markdown – right into your existing documents where you want it.

Get TableFlip at 20% off until Oct. 15th, only!

Apple Introduces Search Ads

So now you can place ads for your app to pop up in search results.

I don’t like this move. Because it changes the chances of developers to make it in the list of search results. The App Store’s aren’t a great place to discover a fitting solution. Now, the search results aren’t even guaranteed to be 100% relevant.

If I had the money, I’d use Search Ads to try to increase my revenue. Without money, you’re screwed, though.

At least the pricing sounds good: you pay for a tap and you can put a daily cap on your ad budget. So literally everyone can try to use Search Ads to increase the odds. The thing is that each tap is priced according to the market, though. If your competitors are willing to spend a lot more than you, chances are a limited budget will not make it:

You determine the maximum amount you are willing to pay for a tap on your ad. Using a second price auction, Search Ads calculates the actual cost of a tap based on what your nearest competitor is willing to pay for a tap on their ad, up to your maximum cost-per-tap bid, so you’ll always pay a fair market price. (Source)

Apart from the amount of fairness of pricing and other technical details, I find the very move to place Search Ads in the App Stores troubling in itself.

Breaking NSLocale API Changes Revisited

Apple have responded to my issues with broken NSLocale property availability. The properties are actually convenience accessors which you can re-impement youself for use before iOS 10.

These properties are new in iOS 10, and you could add equivalent properties for older OSes using an extension like the one shown below:

extension NSLocale {
   var compatabilityCurrencySymbol: String? {
        return objectForKey(NSLocaleCurrencySymbol) as? String

Although that might work, the argument isn’t sound: the properties were available before iOS 10. rdar://28363526

→ Blog Archive