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.

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.1

This is the case for Japanese martial arts. It’s the same for gymnastics. First you progress towards being able to hold your body. Years of practice; not much that’s interesting along the way. Then you add some flow to the game. And then you can come up with sequences and, magically, have become incredible strong in the process.

Or take musicians. Without learning how to play properly, you cannot produce beauty. You have to make hitting chords second nature early on. You become better at playing music others wrote, finding your style of interpretation and deepen your understanding of how music works. Only then can you begin to jam and improvise properly. Without really grasping the basics your own songs may be played correctly but will lack depth and appeal.

Properness is the key term, really. It’s about meeting the expectations and high standards that are already present in the tradition of the respective craft or art.

I can tell you from experience that it’s just the same with painting and drawing. You know that Picasso infamously told people he had to study fine arts only to then unlearn the dominant notion of beauty that was superimposed upon him – and draw like a child. Kind of. Turns out copying Picasso’s style isn’t so trivial after all.

When you run a randomized algorithm that puts colors on the screen, one of the many resulting pictures will eventually resemble the Mona Lisa. Or you let chimpanzees throw paint on canvases for years. By chance something they produce will look just like a well recognized piece of art. But it’s not the product that counts and makes art; it’s the performance. We value the whole process and person which brought a beautiful painting into life. The years of practice seem to matter, too. All the thoughts that went into the product, all the blood and sweat and tears – that’s the kind of stuff humans seem to revere. It’s the hard work and the dedication.

Or maybe it’s just the flip side of our ideal that hard work pays off to value “overnight successes” for the years of hardship they endured. (Oddly, though, this seems to have changed for the worse: media doesn’t mention the years of hard work at all and focuses on the dream of making it big in a couple of life-changing hours.)

My point is: the pattern is the same in every art or craft: You are an apprentice first whose job it is to learn and listen. Only later can you enter a productive discourse with your teacher and innovate in light of the tradition you were brought up in. (After all, it matters from which master you learn your craft as everyone embodies her own piece of tradition.)

There’s no compelling reason to make learning to program an exception. Programming apps without a formal education in the field or a computer science degree is possible. Programming without adhering to basic principles of “good” coding practices is possible, too. When you don’t learn the former, you’ll have to look up more stuff on the web. When you don’t learn the latter, you’ll end up writing code that works first but breaks later. And you’ll have a harder time fitting into existing teams which do adhere to some standard.

You can throw together an app as a newcomer and release it on the App Store in a few short weeks. The barrier to entry is very low. The barrier to succeed is very high.

Making it quick and making it big will be mutually exclusive for most people. There’s always the lure of Flappy Bird. Don’t bet your life on it, though.

If you want to get good at programming, there’s no way around learning to be strict in the style of your craft first. You will learn how to improvise quickly when you combine components creatively. You need to learn some basics of the How, though, to make informed decisions in software engineering.

A mentor can help you a lot, too. Just ask people you admire for tips and resources. You’ll have to do the hard work yourself anyway. But a mentor can help you reflect upon the process and make sense of it all.

Some will yell at me and claim all this “doing it right” attitude is only slowing you down. Don’t listen to them. Don’t just listen to me, either. Find out for yourself what you’re looking for in the first place.

The stuff you value is what matters. Do you want to quickly jump on the wagon of desperate iOS gold diggers and try your luck? That’s fine with me.

But if you want to make a career of this and if you value the craft itself, you may consider dropping me a line and ask for help.

  1. I had a very inspiring conversation with my friend and trainer Sascha Fast about the topic of giving any practice its proper attention, and how this conflicts with the addict’s mindset of getting your quick fix here and now; a trope I got from Silverman’s Love Sick, a great book if you’re interested in humans. The point is that all of us are nowadays conditioned to become this kind of addict. That we become shallow. And that depth requires some sort of dedication.

What Projects Do You Identify With? Maybe They Drag You Down

David Sparks and Jason Snell started a new podcast about going indie in general called Free Agents. The first episode, The Temptation of Yes, is so packed with good stuff that I recommend you listen to these guys for 35 minutes.

There was one thing in particular that stuck with me: the framework for making decisions and taking on new stuff. Jason put it this way:

  1. There are things I want to do,
  2. there are things I have to do, and
  3. there are the things I do.

At first the enumeration sounded familiar: “Eisenhower, got you.” But it ended weirdly and the 3rd option didn’t make sense until they explained: I take on this new project because it fits the things I already do. It’s a conservative mindset. One that doesn’t incorporate change or growth or deliberation or anything you’d call making a conscious decision.

It’s the category of things that stop you from making long overdue adjustments to your schedule. It’s the stuff which attracts more of its kind: work you can do but not enjoy, for example. Or work below your skill level. Easy work.

As an indie, you want to go out there and do amazing things. Especially us programmers don’t want to stop once we roll: work projects, side projects, research, everything revolves around new technology. Imagine being a freelancer when node.js was so new it wasn’t even hyped. Imagine you were still only taking freelance jobs for HTML and CSS front-end web development. The Future was just around the corner. But you’re a front-end web person, so why bother? There’s time to do that later. Always later.

So the three Snell Categories of Work translate to this:

  1. My vision or mission; things that make me grow.
  2. Supporting work to keep everything else moving. Chores, errands, taxes, invoicing. Basis-of-existence level maintenance. Greasing the wheels.
  3. My circle of comfort. Easy stuff. Stuff that keeps me where I am right now. Security.

Nobody particularly likes leaving her comfort zone.

Where’s mine?

There are open source projects that interest me but which I cannot really grasp at the moment. Because I have to learn something new first. For example:

  • xi editor, a Cocoa front-end app that delegates all the real editing work to an RPC backend service. I have no clue about the language Rust and what the background service does.
  • ReactiveCocoa or RxSwift to finally get to know reactive programming.
  • Programming an Electron-based cross-platform app in JavaScript/node.js.

Then there are challenges within the Cocoa sphere: I am not fluent with CoreAnimation, video and image editing, or working with CoreText. All these are excellent candidates for a “learning” list to keep track of where I want to go.

Being honest and transparent with yourself is important to make good decisions. A list of things you want to learn can help staying sharp.

In a similar vein, David has “No” list: a reminder what kind of projects he turned down. He can compare incoming requests to projects he declined in the past. Nobody likes to say no. But this list helps him gauge if declining a request should really make him uncomfortable: didn’t he turn down even cooler projects for valid reasons in the past? Magically, this realization discounts the severity of declining.

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:

struct Foo: CollectionType {}

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.

You’ll need:

  • startIndex,
  • endIndex, and
  • subscript.

The indexes have to be of the same kind; the parameter for subscript, too. Here’s a very simple custom collection that raises an exception when you reach a point past the end, just like Array does:

struct Foo: CollectionType {

    var startIndex: Int { return 0 }
    var endIndex: Int { return 10 }

    subscript (index: Int) -> String {

        precondition(index < endIndex)

        return ".\(index)."
    }
}

print(Foo().map { "x\($0)x" })
// ["x.0.x", "x.1.x", "x.2.x", "x.3.x", "x.4.x", "x.5.x", 
//  "x.6.x", "x.7.x", "x.8.x", "x.9.x"]

You can leave the precondition out for stuff like mapping and return an optional String? instead. Works well, too, but changes you collection’s type, of course:

struct Bar: CollectionType {

    var startIndex: Int { return 0 }
    var endIndex: Int { return 10 }

    subscript (index: Int) -> String? {

        guard index < endIndex else { return nil }

        return ".\(index)."
    }
}

print(Bar().flatMap { $0 }.map { "_\($0)_" })
// ["_.0._", "_.1._", "_.2._", "_.3._", "_.4._", "_.5._", 
//  "_.6._", "_.7._", "_.8._", "_.9._"]

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.

Splitting the View Models of TableFlip, a Short Aftermath

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:

  • I found 3 quick fixes that I never got rid of, where a view controller reached 2+ levels deep into the main (and only) view model.
  • I reduced the TableViewController by 60 lines of code, moving 3 object dependencies to the new SelectionViewController.

The current hierarchy of controllers in the view layer is as follows:

  • TableWindowController, which acts as a Facade, implementing DisplaysDocument, DisplaysTable, and DisplaysSelection.
    • TabBarController: DisplaysDocument shows tabs to switch between multiple tables in a document.
    • TableViewController: DisplaysTable takes care of updating the table view and reacting to some user interactions.
    • SelectionViewController: DisplaysSelection moves the selection highlighter.
screenshot of TableFlip
Screenshot of TableFlip v0.6

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.

Now that the single app state results in updates of 3 different view models, I can begin to plan performance optimizations: did the selection change? – then don’t redraw the table at all.

I love creating complex models and write unit tests for them. I really do. The view stuff, not so much. But now things really get interesting again as I try to improve the user experience and sometimes have to roll custom solutions instead of using the default AppKit stuff. The level of challenge increases. That’s always nice.

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.

A single view model for everything comes with quite a few downsides. In hindsight, it doesn’t make much sense that updates to the cell selection affect the TablePresenter which updates the view with a TableViewModel. It was convenient to have these two together in the beginning. Now this design decision doesn’t serve me well anymore and I see the inherent flaws more clearly.

In effect, there should be 3 view models for a TableFlip document window when I’m done with the next step:

  1. Document: which table is selected? How many tables are in the document?
  2. Table: which cells should be displayed in the window?
  3. Selection: where’s the selection rectangle located?

Part of the bottleneck the TableWindowController. It acts as a Facade to the whole view module by satisfying the contract of the presenter. Upon updates it actually recognizes two different parts of the model at the moment: it does take care of updating the TabBarController with document info; and the rest is delegated to the TableViewController.

Pulling selection management out of the TableViewController into another object will help encapsulate handling arrow keys, for example. That’s a different kind of event than typing text and changing table contents.

I imagine this re-structuring at the seam of application logic and user interface will help improve performance, too. With 3 different view model types I can make atomic view updates with less hassle.

At the moment, TableFlip still runs my initial (and naive) implementation: moving the cell selector with arrow keys triggers an update in the app state. The updated state is transformed into a view model by the presenter and then pushed to the view where a full update (!) is issued. Not very performant. “Diffing” for changes in the table model is useful to make this even faster. Updating the selectors independently from the table goes into the right direction.

From that separation will follow even more changes that’ll improve the code because I can now think and design in different terms. Each document window will then be composed of 3 parts, each satisfying another contract to show information to the user. Instead of a monolithic view, there’ll be 3 large sub-components.

I’m going to add some basic reactive bindings or even employ ReactiveCocoa for the table to make user interface updates more performant. I have no clue which way is the best to create bindings for a 2-dimensional table of varying size, yet. Let’s figure this out when it’s time.

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?

TIL: How to Make NSTextView Reject Newlines

Today I learned that a NSWindow’s field editor cannot trivially be set to “single line mode.” A field editor is a NSText subclass like NSTextView, but NSTextField is only a configurable widget that uses the field editor.

How does the “single line mode” setting do what it does? I have no clue.

So how do you make custom field editor classes reject newlines both through pressing return, alt-return, and pasting text with newline characters? You override its NSResponder hooks!

class CustomFieldEditor: NSTextView {

    // ... imagine some relevant customizations here ...
    
    override func insertNewline(sender: AnyObject?) {

        // consume and discard
    }

    override func insertNewlineIgnoringFieldEditor(sender: AnyObject?) {

        // consume and discard
    }

    override func paste(sender: AnyObject?) {

        let pasteboard = NSPasteboard.generalPasteboard()

        guard let pasteboardItem = pasteboard.pasteboardItems?.first,
            text = pasteboardItem.stringForType(ContentTypes.text)
            else { return }

        let cleanText = text.stringByReplacingOccurrencesOfString("\n", withString: " ")

        self.insertText(cleanText)
    }
}

enum ContentTypes {
    static let text = "public.utf8-plain-text"
}

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

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?

Take a common split-pane application, no matter if it’s on Mac or iOS. There’s some button or label in the right detail pane’s table view’s first cell. I want to change its label and adjust its state to “enabled,” say. I highlighted the widget in question with a grey fill in the diagram.

diagram of an app view
Diagram of an application screen

Again, how do I get there? (How would you?)

Let’s explore this iteratively so you see why I end up with the solution I usually do.

Extract the subview update responsibility

One of the first attempts might be this: you create a Presenter for that part and wire it to the specific view component. Maybe put the presenter into the Storyboard or Nib so you don’t have to worry about its creation programmatically.

When data changes, you tell the presenter to updateView(_:) with new contents and it takes care of the rest. It’s a pretty simple setup: a one-to-one connection from a controller object to a view component object.

A presenter would be part of the applications control mechanisms; it is itself not part of the user interface layer. It controls the view, it is not itself a view.

Since a presenter is a POSO (Plain Old Swift Object) and doesn’t depend on any AppKit or UIKit types like UIViewController, it’s easier to reason about its role in all this. For some people it makes sense to say that a UIViewController subclass is itself a view; others insist the term “controller” implies the opposite. (I’m in the former camp.) A custom presenter type doesn’t have this problem, so we don’t have to argue.

With this seemingly innocent approach, you have wired your application control structures deeply with the user interface layer, though. They have coupled tightly.

Looser coupling promotes flexible designs: you are able to change stuff only when modifications don’t ripple ripple through all of your app. If they do, making changes is going to suck. If changing stuff sucks, you will not want to improve the code. Or add features. Not good.

So a 1:1 presenter–view connection can help to push UI updates but couples the two very closely.

Next step: apply some “decoupling”, whatever that means.

Decoupling dependencies

We can “decouple” things on multiple levels. Objects can be coupled. Modules of the app can be coupled. Overall app and 3rd party frameworks can be coupled.

The cure is to insert abstractions as buffers. I’m going to show an example and then explain the benefit.

Decoupling on the micro or object level can be achieved through abstractions to interfaces—protocols in our case as Cocoa developers. Defining a protocol for the Presenter’s view component will help a bit. It will not go all the way, though, as we’re going to see. But it’s a start:

protocol DisplaysBanana {
    func showBanana(bananaViewModel: BananaViewModel)
}

class BananaPresenter {
    typealias View = DisplaysBanana
    
    func updateView(banana: Banana) {
        // create banana view model & show it
    }
}

This is an improvement for two abstract-ish reasons I’ll try to make more concrete in a second:

  1. You can change which class in your UI layer will implement the protocol.
  2. You can hide details of the concrete implementation from client code, in this case: the presenter.

I admit: The first reason is strange. It’s not very likely you want to switch an ABCViewController for a XYZViewController once you got this far. This kind of flexibility is faux flexibility.

There’s a point, though. When the concrete implementation is unknown to the caller, you don’t have to change the BananaPresenter’s source code when things change in the UI module. The presenter’s module dictates what the protocol is like.

The real benefit is hidden in the 2nd reason. The Presenter doesn’t know anything else about the concrete view object it interacts with except the things the protocol dictates. So the Presenter’s “module” is in control.

diagram of dependencie
Interdependency before the introduction of the protocol and relaxed co-dependency after

Before decoupling the objects through a protocol, the Presenter and a concrete View type were coupled through mutual dependencies. The arrows in the above diagram indicate who is controlling whom. The view implemented an showBanana(_:) method as part of its published interface (accessible to callers). The Presenter depended on this method to work. If you change the view to work differently, you’d have to change the presenter, too. This is a kind of control. On the other hand, the view cannot do anything without receiving data in the first place. So the presenter kind of has a veto through not using the method at all, while the view dictates how things are going to work.

After introducing the protocol, the presenter’s module dictates what the contract really is like. Whatever object is used to display stuff: it has to adhere to the rules the protocol imposes. It’s not the presenter itself who dictates the rules. It’s the presenter’s module. The “stuff that shows data in the UI when data changes” module. I like to call it “the Application layer.”

We have inverted the dependencies. Instead of the presenter relying on the view type directly, their connection is mediated. The protocol is effectively a buffer. When the protocol changes, the view has to change, too. But the view can change independently as much as it wants as long as the contract is still satisfied, as long as updateView(_:) is still implemented.

Simply put, we can change the view to our liking and refactor like hell and the compiler will help us not break anything or accidentally affect dependencies. And looking from the other side, our presenter’s controller code can never reach deeply into the concrete view’s object graph and increase coupling.

You know how sometimes it’s just too easy to violate boundaries, reach deeply and call something like viewController.someLabel.text = newValue? It’s impossible now because the presenter doesn’t know about someLabel being present. (You could conditionally cast from DispaysBanana to ConcreteBananaViewController, of course, but that’d be stupid and the stupidity clearly shows in code.)

Now that on a micro or object scale the decoupling is sufficient, step back once more. If you have N view components, it’s not feasible to create N presenters, each with its own view protocol. Although the initial design of MVC did exactly that, I find this approach very cumbersome. You’d create a useful buffer layer of abstractions between (Presenter_1...Presenter_N) and (View_1...View_N). But the amount of connections can become overwhelming and hard to maintain, too.

That’s where next-level decoupling comes into play.

Simplifying the dependency graph through Façades

The complexity of dependencies can explode with a complex view and one presenter for each of them. It will be maintainable. It will not be easy to wrap your head around things, though, and instead of adjusting how the objects work you’re probably going to replace them entirely because they are so super-focused. That’s not a bad thing, mind you. I think there’s a more scalable way.

I picture the problem of having N views, N presenters, and N view–presenter-connections to look like tons of cables on a desk, one from each device into the computer. The cable problem can be simplified through a bottleneck, like USB hubs and cable canals. Voilá, the mess is gone.

A Façade is a Design Pattern that does just that. With it, we can take the decoupling even further by abstracting away the multitude of objects and hide them behind a single interface.

Thanks to the view protocol abstraction, the facade can be introduced as another mediator:

class ConcreteBananaDisplay: NSView /* or UIView */, DispaysBanana { 
    
    func showBanana(bananaViewModel: BananaViewModel) {
        // view setup logic here
    }
}

class BananaFacade: DisplaysBanana {
    
    @IBOutlet var bananaDisplay: BananaDisplay!
    
    func showBanana(bananaViewModel: BananaViewModel) {
        
        bananaDisplay.showBanana(bananaViewModel)
    }
}

The presenter is wired to the Façade object which then delegates to affected sub-components. It hides implementation details (“which object does what?”) from the outside world, whereas “outside world” in this case means “every other part of the app that’s not in the UI module”. With this approach you promote decoupling of modules in your app.

Say you have even more fruit, see how this is scaled:

class FruitFacade: DisplaysBanana, DisplaysApple, DisplaysOrange {
    
    @IBOutlet var bananaDisplay: BananaDisplay!
    @IBOutlet var appleDisplay: AppleDisplay!
    @IBOutlet var organgeDisplay: OrangeDisplay!
    
    func showBanana(bananaViewModel: BananaViewModel) {
        
        bananaDisplay.showBanana(bananaViewModel)
    }
    
    func showApple(appleViewModel: AppleViewModel) {
        
        appleDisplay.showApple(appleViewModel)
    }
    
    func showOrange(orangeViewModel: OrangeViewModel) {
        
        orangeDisplay.showOrange(orangeViewModel)
    }
}

Sure, the repetition gets kind of boring. But this component now is the bottleneck where all view updates will go through. It’s one single place to worry about.

For that matter, the sub-components wouldn’t even need to implement the various view protocols: since they are not passed to objects outside the UI layer, nobody cares about their protocol conformance anyway. The Façade could do things in entirely different ways behind the scenes and nobody will notice. As a personal preference, I tend to make both the Façade and the object it delegates to implement the same protocol to show through protocol conformance which view component is designed to fulfill a certain purpose. But you don’t need to.

Real Life iOS/UIKit Application

On iOS, your problem view could be a UITableView. The design of UIKit encourages you create a Façade without thinking twice about it: a UITableViewController. When data changes, you pass it to the view controller, not to the table view directly. The view controller takes care of configuring the table’s cells.

This whole design is based on a lot of indirection: you don’t push changes to the UITableView. Instead you tell it to reload itself so it fetches missing views from its delegate and the contents from its data source. The UITableView doesn’t care which object in your app implements these protocols. Traditionally, you use a UITableViewController for this. But it could be any POSO, anywhere in your app, as long as you wire the table view to it.

A UITableViewController hides implementation details of its table: how cells are set up and what they look like.

I bet your view model will resemble a sequence or collection, most prominently using arrays. But you don’t have to make model data respond to UIKit’s UITableViewDataSource needs. The view controller does that. And so the app’s glue code worries about setting up a proper model for the view controller, not about the table view.

OS X/AppKit Specification

Let’s say there’s a NSDocument based app with a window open that shows the split pane from above. The window has NSOutlineView to the left and a content pane to the right, ultimately including a NSTableView. Let’s say you use it to edit items in projects, much like Xcode, for example.

Now the project data changes under your feet because the user deleted a file on her disk and your app receives a notification and updates the data. Instead of reaching to the outline view directly and replace the list, you tell the document or its window to showProjectItems(_:). It then delegates to its outline view appropriately. If the currently viewed item was deleted, this will also take care of clearing the detail pane to the right.

Programming for OS X, I often find a window to be the best candidate for Façade. It contains all sub-view controllers anyway.

In fact, the Word Counter’s menu bar panel is the Façade for 3 NSViewControllers, each with their own Nib. They in turn are a Façade for the actual NSView components that display stuff: table views, labels, buttons, and charts. Isolation of modules and components all the way down.

This way you let the view module achieve inner consistency and coherence for a meaningful change. The alternative is to reach into the view module with controllers and replace the outline’s contents in one step and worry about the detail pane in another. Then the coherence criteria are exposed to the controlling objects. Thus the view module is opened up to being manipulated in a way that results in an inconsistent view state. So you have to add even more checks and tests to the controllers and dumb down the view components themselves.

View components should be dumb inasmuch as they should not know anything about real business logic and how to process network requests, for example. But they can be smart enough to care for themselves.

In a nutshell

“Smart enough” objects is the whole point of object-oriented programming: object boundaries are used to maintain consistency on the inside. State is encapsulated and objects expose methods to perform meaningful change. If you don’t do it that way, you create mere data containers and end up with all the logic in one place, most notably view controllers, which then overwhelm you with their intricate complexity.

Decoupling reduces complexity by keeping object boundaries intact: strong coupling forces you to think about all objects involved. Clear separations through protocols as interaction contracts help you to reason about an object and what it does.

More objects isn’t better to grasp where information flows per se, because a multitude of cleanly separated objects is still hard to hold in your head. That’s where designing bottlenecks comes into play, for example as Façades. All of this makes sense with objects that are autonomous only, or you’ll end up with [train-wrecks][] like facade.subcomponent.detailView.label.text and wouldn’t gain a thing.

Subscribe to the Clean Cocoa Newsletter!

Write clean code effortlessly and become a happy programmer. Let me help you get the latest recommendations on time. No spam, guaranteed.

* indicates required