On Reaching Mastery

The following isn’t a universal truth. It’s a report about my observations of a recurring theme in everything that’s great. First you imitate. Then you improvise. And then you may innovate. Imitation means repeating existing things to reach a deeper understanding of how it was done in the past. Improvisation means connecting the static patterns in creative ways to solve problems. Innovation means deviating from the known patterns in new and effective ways.

Continue reading …

Implementing CollectionType in Swift 2.x

I ran into trouble with custom collections the other day and wondered how to reliably find out what the bare minimum for a custom CollectionType is. The compiler will only help a bit: It’s conforming to neither CollectionType nor SequenceType. Now I know SequenceType requires the generate() method – but don’t let this fool you. CollectionType will provide that for you if you meet its requirements.

Continue reading …

Revamped Blog Archive

I just changed the blog archive to show all past articles reduced to the titles on one page. There still are annual collections of the old-style excerpts. I hope it helps to browse the stuff I published over the years. Still I find the sheer mass of topics unwieldly. That’s why I started to work on a curated and commented list of articles, like a table of contents. Will let you know when it’s ready.

Continue reading …

Splitting the View Models of TableFlip, a Short Aftermath

Teaser image

I executed my plan from earlier this week to split TableFlip’s monolithic view model into sub-view models. The process wasn’t too complicated. The highlights: The current hierarchy of controllers in the view layer is as follows: The window doesn’t look too complicated and there truly are not that many view components involved, but still it’s quite some work to keep things well coordinated. The TableViewController file clocks in at about 400 lines of code although it mostly delegates stuff to other objects. There’s still room for improvement, but I have to see patterns, first. I even extracted NSTableViewaDataSource and NSTableViewDelegate into different objects months ago. Today I doubt this was a good idea in the first place. We’ll see.

Continue reading …

I’ll Split Up the Monolithic View Model in TableFlip. Here’s What I Expect to Happen

The upcoming changes in TableFlip’s user experience made me ponder how I structured the app’s modules. The bottleneck I created in my app is simple: there’s one presenter which transforms the model into a view model; the presenter defines a protocol for the view it expects and passes the view model to the object that satisfies this contract.

Continue reading …

How PlanGrid uses a Flux-Inspired Architecture to Simplify State Management

Benjamin Encz published an article about the architecture of PlanGrid.

They moved to a Flux-inspired “unidirectional flow” approach where state changes are performed in a Store (in the backend, if you will) and updates pushed to the user interface (the frontend). No ad-hoc view updates, no shortcuts. User events are emitted, handled by the store, and state updates affect the view. That’s it. So it’s always obvious how the user interface got into the state it’s in: all the details are plainly visible in the current state object.

Ben’s post is very deep and detailed. You’ll learn a ton from it:

  • architectural discussion: why “unidirection flow”, and why Flux?
  • setup of actions/events and the store type
  • basic state–view bindings via Reactive Cocoa
  • how testing stores (and views) is straightforward with this setup

I can’t wait for the next post in this series. Most of this easily applies to ReSwift, too, of course. And guess who just got inspired to refactor TableFlip so the model and view become even more loosely coupled?

Iteratively Improving Your App: Decoupling Components at Module Seams and Adding Facades

Teaser image

Façades are very important tools when I flesh-out the modules of an application. They turn out to be only the logical consequence of basic object-oriented programming principles, internal cohesion of objects namely, paired with decoupling of application modules (like “model” and “view”). Take a complex view that has many subviews. When you need to update a single piece of the user interface, how do you get there?

Continue reading …

First Contact with AppKit for iOS Developers (Under the Radar #26)

During my rather relaxed late evening workouts I catch up on podcasts now. Although I don’t enjoy listening to people talk (I prefer reading), this is a great source of inspiration and seems to be the premier way in which people share their experience.

Marco Arment and David Smith run Under the Radar. In episode 26, they talk about Marco’s deviations into AppKit—Mac app development. (Their shows are always under 30 minutes, so I suggest you give it a try.)

Marco’s app Quitter is available for free. He couldn’t put it into the Mac App Store because its main feature is to quit other apps. That doesn’t work with Sandboxing. So Marco had to release it directly.

I found a few things especially noteworthy:

  • Direct distribution means you have to worry about installation, updates, and payments yourself. It’s more work. So Marco made it free. (P.S.: I wrote a book on direct distribution.)
  • Marco was rather afraid to ship an update: maybe he didn’t test thoroughly and introduced a bug; it seemed to me he missed the safety net of app reviews.
  • Then again, shipping a bug fix update is fast and easy, too. It takes zero time to make an update available to customers.

The absence of app reviews in direct distribution is both frightening and liberating. I am afraid to ruin my customers’s lives with every Word Counter update I ship. It’s true, you can break things. But you can also make things right within the hour. You don’t have to wait for anybody else. (Even though iOS app review times have improved a ton, from 7 to 2 days!)

I am astonished that both Marco and David have years of experience working with UIKit but didn’t ship a single Mac app in the meantime. Or do contract work back in the day. “iOS exclusive” sounds insane to me, but for them it has worked quite well!

What’s your experience? Do you remember your first contact with AppKit? Are you afraid to try? Comment, email, or tweet me your response!

I love Swift’s Expressiveness

Take optionals, for example. Optionals demarcate when something’s not there at all. When an optional is nil, this may signify something went wrong. That’s much more explicit than relying on a convention like returning -1 for failed requests. This is convenient and changes the game of handling edge cases completely. Because whenever you receive an optional, you have to deal with its two-fold nature. Checking for -1 can slip your mind. Forgetting to unwrap an optional is unlikely.

Continue reading …

UIStackView For Showing And Hiding User Interface Controls

Animating and (de)activating Auto Layout constraints always leaves me puzzled at first. When on iOS, I try to not add constraints with explicit width/height values to train myself to rely on relative values. This helps me cover multiple screen sizes with the same settings.

I asked Lawrence MacFadyen on Twitter recently if his UIStackView animation wouldn’t work without an explicit width. Seems it does, so he published an updated post.

Conflicting Mental Models in TableFlip’s Interface Design

A beta tester of TableFlip suggested I make the table grow automatically when one navigates to the edge of the table and presses the arrow key in direction of the edge. I am conflicted about this proposal. On one hand, being able to grow the table easily is important. Spreadsheet applications usually present you with an infinite canvas. This is behavior people know (and maybe even expect).

Continue reading …

Separating ReSwift Actions from UI Events

Teaser image

Today was the second time during the development of TableFlip that I started to implement a new feature in the wrong way: starting with an explicit event type that is triggered by pressing a button in the user interface. This is a 1:1 mapping of user intent to an event that performs changes in the model. Next time I’ll start from another point of view instead to not rush too many minuscule changes until I hit a roadblock and hate myself. Here’s what went wrong.

Continue reading …