In Praise of Swift

In Performance These Days I argued that developer productivity is more important than the speed of a given language. And while I wish for an Objective-C without the C and with the cool parts from Swift, I also realize that it’s not going to happen, and I’m fine with that. * * * I’m at the point where I get bugged if I have to write Objective-C code. I don’t think I’m actually more productive in Swift yet, but that’s not the fault of Swift — that’s just how it goes when you switch languages and the previous language was your primary language for more than a decade. Writing Swift code feels like driving a hot rod. Sometimes it feels like driving a hot rod into a brick wall. But still: it’s a goddamn hot rod. If I had just two feature requests, they’d be: Allow Set<SomeProtocol>. This is a major part of protocol-oriented programming for me. Comes up all the time. Support KVC. (Note that I specify KVC and not KVO, which I don’t care for.) I use KVC only rarely, but when I use it it saves a ton of tedious, error-prone code. Both of these issues keep me tied to some degree to Objective-C — or at least to NSObject and the Objective-C runtime — for now. * * * Okay, I have a third feature request. And it’s a big one. It’s kind-of for the Swift team, but it’s really for everyone who works on developer tools at Apple. I’d like to see those teams look at a whole bunch of actual Xcode projects and source for shipping apps and do some analysis. Where do developers struggle? What takes too much work? The goal is to use these projects to keep answering the question: how can writing high-quality apps be made easier? It’s not enough to look at apps written inside Apple — these apps should come from outside. I’d bet that many developers would be happy to (confidentially, of course) submit their projects for this effort. I certainly would. And it’s not enough just to hear what developers say. (Though that’s important too.) There’s no replacement for seeing what they actually do. It’s kind of like when you work on performance issues. You may think you know what’s slow, but there’s no replacement for actually running the profiler and seeing what’s slow. Same with this: there’s nothing like actually seeing what problems need solutions. Maybe this is already being done and I just don’t know about it. If so, then cool. * * * Did I mention that Swift is a hot rod? And I need to go work on some Objective-C code, and I’m procrastinating because it’s Objective-C and I want to go drive my fast car instead. PS Daniel Jalkut suggests writing unit tests in Swift. Me, I’m writing all new code in Swift. But if you haven’t started writing with Swift yet, then you should listen to Daniel.

Posted by on 29 April 2016 | 4:05 pm

Performance These Days

Mike Ash reports that objc_msgSend takes 2.6 nanoseconds on his Mac and 2.7 nanoseconds on his iPhone. This shouldn’t come as much surprise — we’ve known since Mike’s first report in 2007 that objc_msgSend is fast. (Though this function isn’t the only measure of Objective-C’s speed relative to other languages, it’s indicative.) So Objective-C is fast — but it hardly matters, because almost all of your code might as well be written in Ruby. (Or in any relatively slow scripting language.) Pushing a view controller onto a navigation controller takes the time it takes. Your text fields won’t draw their strings any faster just because you’re using Swift instead of Python. Hitting the disk is still hitting the disk. There may be some things your app does that need to be super-fast. Parsing email messages or RSS feeds, for instance. Processing audio. You wouldn’t want to use a scripting language for those — you’d want something like Objective-C or Swift, or even C or C++ — to make those parts fast. (And you probably want to move those things off the main thread.) But that’s the minority of your app, by far. Imagine a typical RSS reader — what percentage of the code makes up the feed and OPML parsers? Well under 1%, I’d bet. The rest might as well be in Lua or JavaScript, and users would never feel the difference, because there would hardly be a difference. Maybe Swift is faster than Objective-C, or will be. But that also hardly matters. Performance does matter That’s not to say performance doesn’t matter. It totally matters. If an RSS reader blocks the main thread while parsing feeds — and is slow at parsing feeds — it’s going to suck. But making things fast has to do with choosing fast data structures and algorithms, moving things off the main thread when needed, and figuring out which of the other things Mike Ash lists as slow (such as object creation and disk access) you can avoid. Switching to Swift — or whatever — isn’t going to make a slow algorithm appreciably faster. Another kind of performance Instead of language performance the focus should be on developer productivity. Developer performance. That’s the thing that counts these days. Swift makes a bunch of leaps forward here and some leaps back. Awesome things: type inference (I could stop right there and be done); not having separate header files; easier syntax for blocks; let for immutable variables; map and filter (though easily done in Objective-C); protocol extensions; etc. And yet it’s stuffier than Objective-C, and in some respects feels like a lower-level language. We’ve given up dynamic dispatch (largely) and gained optionals and a stricter type system. We’ve also given up simplicity (assuming you know C, and you should, the “Objective” part is pretty small) for a much more complex language. Objective-C has way too much housekeeping, yes. Totally. And yet, in Swift, I sometimes feel like I’m filling out a form in triplicate before I can use a variable, or faxing various department heads before I can call a method. Where Swift is awesome and not-awesome As a system programming language, Swift is, I strongly suspect, utterly brilliant. I want that kind of programming to be buttoned-down. Absolutely. Swift seems like the answer to the question: “What would a language for system programming look like that’s both safer and better for productivity than C and C++?” The problem is, the answer to that particular question is not necessarily the same as the answer to the question, “What would a language for app programming look like that’s both safer and better for productivity than Objective-C?” The safer part is easy: remove the C. Huge win right there. But I think Swift otherwise gives and takes away — we get type inference and all the lovely things I mentioned before, but we end up fighting the type system, standing on our heads to deal with optionals, and working with a language that’s much larger (demonstrably) than is needed for writing great apps. It solves a whole bunch of problems that didn’t need solving (for app-writing). I’d rather we focused harder on making writing high-quality apps easier. A scripting language, or something spiritually close, that took the best parts of Swift, but was much smaller and simpler, more supple, that ran on the Objective-C runtime — dynamic dispatch and all — would have been ideal. I could fly in that language. Yes, I realize that would have meant pushing some errors from compile time to run time, in exactly the same way Objective-C does right now. But I don’t care — I’d take that trade-off every single day of the week.

Posted by on 21 April 2016 | 12:06 pm

Quantify.app

The folks making “App: the Human Story” have just released their own app: Quantify. The idea is that while you’re shooting video — an interview or whatever — you can rate the action as it goes along, and then you have that when you go to edit. Saves a ton of time. If I made videos, I’d get this app. PS The latest update on the documentary: We’re pushing hard and plan on showing you the film the first part of June, right before WWDC. Good timing.

Posted by on 13 April 2016 | 1:27 pm

High-Level Events

I wrote, in The Objective-C Version, that one of the major advances of Cocoa over the Macintosh Toolbox was event routing. Both frameworks were event-driven, but with Toolbox code you had to dispatch events manually to their proper places, while in Cocoa you hooked-up events and methods more directly. Which was genius. But now we’ve been doing it the Cocoa way for years (and decades, for some people), and we take it for granted. We take it for granted so much that we’re now able to realize what a pain it can be. The thing Cocoa is missing — and what the reactive-programming folks get — is the notion of high-level events. If events such as IBActions, NSNotifications, KVO-fires, timer-fires, delegate callbacks, and so on are primitive events, then a high-level event should be a composition of primitive events and conditions that don’t have to happen at the same instant. Example Consider again that live-search textfield from Comparing Reactive and Traditional. There are two high-level events that could be described like this: Textfield search event: Primitive event: textField.stringValue changed Condition: textField.stringValue.count >= 3 Condition: textField.stringValue unchanged for 0.3 seconds Action: runFetch(textField.stringValue) Refresh button search event: Primitive event: refresh button action method called Condition: textField.stringValue.count >= 3 Action: runFetch(textField.stringValue) I’m not saying we want to describe them using the syntax above — but it’s clear (from the above, and from RxSwift) that it is possible to specify high-level events. It’s also clear (self-evident, I hope) that declaring high-level events means less code that synthesizes high-level events by querying and maintaining state (which is where your bugs come from). (It’s also clear, I hope, that this is not all that RxSwift does. But it’s the part I’m interested in.) How Apple might do it It’s tempting to say that our synthesizing high-level events by breaking them down into small, logical pieces is why they pay us the big bucks. It’s what we’re trained to do, after all. But that argument could be used against every single advance in app-writing, so let’s forget it. Instead, let’s imagine how Apple might solve the problem. Since high-level events are a UX thing, there would be some way in Interface Builder for your designers to specify high-level events. A drag-and-drop, point-and-click thing. You’d wire up some triggering event (the primitive event), then create a predicate (the conditions), set some attributes (coalesced or not, coalesce interval), and then link it to an action method. Because magic is disallowed, there would also be a way to do it in code. You could instead instantiate an NSHighLevelEvent object and set the trigger, conditions, and action. You could write NSHighLevelEvent yourself — or HighLevelEvent, since it’s not Apple’s if you write it yourself — minus the editing interface in IB. To get an idea of its API, imagine something like this (quickly-typed thing) in your view controller: let textField​RunSearchEvent = HighLevelEvent​(observationTarget: self, key: "currentText") textField​RunSearchEvent.​coalesced = true textField​RunSearchEvent.​coalesceInterval = 0.3 textField​RunSearchEvent.​condition = NSPredicate​(…) textField​RunSearchEvent.​target = self textField​RunSearchEvent.​action = #selector​(runSearch(_:)) What it means: when viewController.currentText changes (let’s assume HighLevelEvent always considers distinct changes), it coalesces changes for 0.3 seconds. Then it evaluates the predicate — and, if true, it then calls target.action(sender). Obviously this is an object-oriented approach and is unlike reactive code. It has the benefit of fitting in better with the existing Apple frameworks (and the style of code most iOS and Mac developers have been using since OS X came out). I do not suggest that this solves all the same problems RxSwift solves — but I do suggest that this approach would make app-writing a bit easier. You let the HighLevelEvent handle state (including setting up and tearing down a timer when needed). Aside from setting up the HighLevelEvent, you’d have code that looks something like this in your view controller. Standard stuff: func textDidChange(textField: NSTextField) {   currentText = textField.stringValue } @IBAction func runSearch(sender: AnyObject) {   … } In other words, this would fit in nicely with the way people write apps now, and would be something I’d use.

Posted by on 12 April 2016 | 3:47 pm

The Objective-C Version

In Comparing Reactive and Traditional I linked to two solutions to a specific problem: one in RxSwift and one traditional (but also Swift). To round things out, a friend of mine wrote an Objective-C version. You can see the main view controller as a gist and you can download the entire sample project. (Because it’s not all in the gist.) My friend writes: The rules outlined in Comparing Reactive and Traditional represent the business logic for contacting the server: coalesce requests over a timeout period, coalesce non-unique consecutive requests, and ignore requests shorter than a specified length. If I’ve learnt anything in nearly 30 years of writing software, it’s you don’t want to put business logic in the UI. Working with UI is complicated enough without embedding your business logic there. That’s why the business logic is embedded in the Fetcher object – mostly in the -fetchQuery:error: method. Because we’re coalescing calls, having a method with a completion handler isn’t appropriate. One unifying theme in Apple’s use of completion handlers is they are ALWAYS called – either with a result or an error – the block is never just ignored. Because we plan to ignore many calls to our query method based on the business logic, either a property with a handler block or a delegate is appropriate. I chose a delegate, because they still have slightly more historical precedence. I inferred from Brent’s implementation the rule that new queries should cancel incomplete queries. I’m not certain whether that’s correct, but it seemed appropriate to prevent responses coming out of order. * * * Also: Jorge Bernal’s post From traditional to reactive is worth reading — he takes the traditional version to the next level (closer to something you’d actually write), by creating a Throttle object. He writes: There’s no silver bullet, and that’s also true for RxSwift, but I believe it can help. I can’t imagine reasoning about all the possible states in a more traditional design. And: I also would argue (although someone might disagree) that any time you use NSNotificationCenter, NSFetchedResultsController, or KVO, you are already doing some sort of reactive programming, just not in a declarative way. In the Macintosh Toolbox days we wrote code that polled the event loop via GetNextEvent. Our code examined the event and handled dispatching it to the right place in the app. This was a huge pain, and you can be glad if you’ve never had to write code like that. I first experienced the joy of AppKit when I created a menu item in Interface Builder, wired it up to an action method, and then wrote the code in that action method to handle that specific command. Responding to events in this way is far better than the old-fashioned method. I don’t know if I’d call it reactive, though — I’d just go with event-driven. (Even the Toolbox version was event-driven — it’s just that it didn’t help with event routing, which is a thing we now take for granted.)

Posted by on 11 April 2016 | 3:48 pm

Reactive Followup

Junior B. posted a good follow-up to his post that I had replied to previously. See To React, Or Not To React. Other followup… On using other people’s code Brian Gerstle asks: @brentsimmons is it fair to say your only criticism of Reactive is that—in this case—its 3rd party code? If it was Apple, you'd use it? I’m cautious with third-party code. I do use some: FMDB, for example, appears in every app I’ve started from scratch in the last decade or so. I like FMDB because the code is available (which is an obvious must-have); it’s relatively small; it does one job — providing an Objective-C wrapper for SQLite — and does it well; and it’s used in just one small section of my apps and has no impact otherwise. Another example: recently I looked at at Fletcher Penney’s MultiMarkdown parser, which I might use in an app I’m working on — and I like it for the same reasons I like FMDB. I don’t have hard-and-fast rules about when to use other people’s code and when not to. But I’m most likely to say yes when the code is essentially a library that performs one conceptual function (database access, Markdown parsing, etc.). I ask myself: what if something goes wrong and I can’t use Framework X anymore? Can I replace it somehow? Some amount of effort is fine, but rewriting and re-testing vast portions of the app is not acceptable. I could write my own SQLite wrapper if I had to, and I could write my own Markdown parser. (Or find replacements written by other people.) What if Apple made RxSwift? Were Apple to provide reactive UIKit and AppKit and say, “Here’s how you make apps in the future,” I would expect that the tools would support this new style, and I’d expect it to play well with accessibility and AppleScript support and everything else. It would be well-integrated. I’ve spent decades following Apple’s lead. People who don’t follow along end up in tight places — wishing for 64-bit Carbon, for instance. That’s not say it always works out. Garbage collection, for example, was a dead-end (but with ARC it had a great replacement). But, yes, I’d follow Apple’s lead into the reactive future in that case. Not my only criticism I wouldn’t be that happy about following Apple’s lead into the reactive future — if, that is, their implementation looked much like current versions. So, no, not-being-Apple-code is not my only criticism. Another of my criticisms is that it’s difficult to read. I’ve had a number of conversations with other developers on the subject, over many months, and almost every single developer that I talked to uses strong and inflammatory language about its unreadability. If you’re a fan of this style, you might think that developers shouldn’t feel this way. My point is that, like it or not, they do. You might not remember what it was like to look at this code before you understood it. Or you might be the kind of person who naturally takes to this particular style, and maybe it never seemed alien to you at all. Totally fine, of course, but remember that you’re not typical. The revolution I agree strongly with reactive proponents who say that the current standard ways of writing apps are broken. Too much state, for sure, and not enough ways to specify flow. The less state we have to manage, and the more declarative code we can write, the better. I’m totally on board. But if the revolution is about using this specific set of APIs, then I’m not on board. My hope is that we’re using this specific set of APIs as a stepping-stone on the path to something better, something that appeals to a broader set of developers. In the meantime, you could insist that there’s no readability issue, but I think that if you do then you’re potentially holding back the larger goal. You could say, instead, “Yes, I know it sometimes looks like Perl in a blender. But we’re making the future here, and it doesn’t always start out pretty and it certainly doesn’t start out universally liked. This is step one. This is how we get from here to there.” If so, then you’re taking one for the team, and I’m not — and I thank you. PS Attribution note: the Perl-in-a-blender bit comes from Martin Pilkington: I’ve yet to see reactive code that didn’t look like Perl shoved in a blender, even though I like the idea in theory PPS I may not have this story entirely right, but it went something like this: Picasso invents Cubism, and people think it’s ugly. Because it is. Then Braque, or Derain, or both (I forget) come along and do a prettier version. Picasso remarks that it takes a genius to do the first ugly version, and the people who make it nice don’t have to be geniuses. (Or maybe it was Stravinsky, and it was some musical thing. Whatever. I like the honesty about the first genius version being ugly.)

Posted by on 10 April 2016 | 2:12 pm

Comparing Reactive and Traditional

My friends Jamie Pinkham and Casey Liss wrote a short sample meant to illustrate the kind of code you’d write in RxSwift to implement a text field that runs a search via the web and then updates a table view. The rules: Changes to the search text must be coalesced over a period of 0.3 seconds. When the search text changes, and the text has four or more characters, an http call is made, and the previous http call (if there is one) must be canceled. When the http call returns, the table is updated. And: there’s also a Refresh button that triggers an http call right away. Basic live search text field, in other words, with just the added wrinkle of a Refresh button. Because I thought it would be fair to compare to a traditional version, I wrote one. Both samples — theirs and mine — surely have errors, and neither compiles. They’re for the sake of discussion rather than meant as actual, running code. Here they are: Reactive version by Jamie and Casey Traditional version by me Status Quo The traditional version is, in general shape, the same code you’d have written 15 years ago. We have blocks and Swift and ARC now, and so it’s smaller and simpler — and more readable and maintainable — than it used to be. But the main idea is the same. And we’re all just plain tired of writing code like this. The two biggest knocks against it: Dealing with mutable state sucks. Every time you add something it gets more complex. “State” is a fancy name for “where bugs live.” There’s no high-level view of what’s actually happening, unless it’s in a comment. It’s a collection of small functions and properties without a linear story. It’s not all bad, though. It sticks close to the frameworks and the language, and so any Cocoa developer can understand it, even the newest member of your team. The properties and functions are named reasonably well, and they’re small and logical. It’s the least clever thing you can imagine that still does the job. New Coolness The

Posted by on 8 April 2016 | 12:44 pm

The Non-Reactive Solution

The Reactive Revolution in Swift intrigued me not only because the solution was different from what I’d normally write but so was the problem. Here is what’s going on (I think): A view controller, part of a chat app, initiates reading data from a socket. The view controller parses that data into a message object. The view controller adds the parsed message to its array of messages. (And, presumably, updates the UI.) The Old-Fashioned Way The old-fashioned way is presented like this: On a background queue, load the data and parse it. Then call back to the main thread and update the messages array and the UI. This is clearly wrong. The author is absolutely right to call this “callback hell” — he’d be right to use stronger language. This is not how you do things. In fact: any time a view controller is making network calls, it’s wrong. Any time a view controller references any kind of queues or background threads, it’s wrong. (View controllers — and views — are main-thread-only creatures.) The New-Fashioned Way The new-fashioned solution, according to the author, is to use Reactive Programming via RxSwift. I think, but I can’t tell for sure, that roughly the same thing is going on. (It’s hard for me to read, which surely can be explained by my not knowing RxSwift. The addDisposableTo(disposeBag) part especially worries me, since it looks like a parallel memory management system.) But let’s set that aside and talk about how I’d solve this problem. How I’d Actually Write It First thing: the view controller should not be reading data from a socket and parsing the data. Instead there should be a separate network controller object whose lifetime is not tied to the view controller’s lifetime. It may be that the view controller needs to tell that network controller to do a thing — such as download more messages — and that’s fine. So give the view controller access to the network controller. A refresh() method or whatever. Ideally, the network controller makes an http call via NSURLSession — this is almost always preferable to sockets. But let’s assume that the server API uses a socket. So that network controller has a background queue of some kind, which could be a serial queue if needed. Or an NSOperationQueue. Whatever. On that queue it… Loads data from the socket. Parses the data into a JSQMessage object. (JSQMessage is from the original blog post.) Then, on the main thread, it posts a NewMessage notification meaning that there’s a new JSQMessage. This way the network controller knows nothing about any view controllers. It knows how to pull data and turn it into an object, and it does so without blocking the main thread. Yes, you might use GCD, or you might use NSOperationQueue + performSelectorOnMainThread — but, either way, the use of background threads is entirely hidden inside the network controller. The outside world can’t see in and doesn’t know those implementation details. This way threading issues don’t leak out of the network controller, which is crucially important. And though you’re potentially using a callback (depending on how you do it) you don’t have to nest them into some kind of hellish situation. It’s minimal, readable, and debuggable. The chat view controller then needs to do three things: Subscribe to the NewMessage notification. Handle the NewMessage notification by appending to the messages array. Update the UI when the messages array changes. The second step looks something like this. (Typed into MarsEdit, not actually compiled; might not be completely correct.) dynamic func newMessage​DidDownload​(notification: NSNotification) {   if let message: JSQMessage = notification.​userInfo​[messageKey] as? JSQMessage {     messages = messages + [message]   } } The messages property should have a didSet method which calls the thing that updates the UI. This way, any time you change that array, the UI updates. (In the real world, by the way, it’s probably plural — you don’t handle one new message but potentially many new messages.) NSNotificationCenter is, I grant, old-school and totally not glamorous. It just plain works, simply and reliably. Among other things, it has the advantage of being a well-known part of the Foundation framework, and you ought to be able to count on every Mac and iOS developer to know how it works and how to use it. No Locks Needed From the original article: Asynchronous programming is not just about running tasks or perform computation in a separate thread, at some point, we will need to synchronize values across threads and the most common solution is to add locks. As soon as locks are introduced, the complexity of the code raises of at least one order of magnitude and one big new component is added to the complexity equation: unpredictability. There are no locks in the solution I outline above. (I’ve used that general pattern in NetNewsWire, Glassboard, Vesper, and in my two in-development apps — I know it works.) At most there might be a serial queue, but I don’t think I’ve ever used a serial queue with networking. (I do use them for database access, though.) Here are the tricks: views and view controllers should be main-thread-only. When you have a task in a controller that can block the main thread, make it isolatable and use a background queue of some kind — but keep that implementation detail hidden from the rest of the app. And any networking and parsing must be done in an object whose lifetime isn’t tied to the view controller’s lifetime. * * * I’m not saying that Reactive programming is bad, or that RxSwift is bad. I totally don’t know enough to say. However, there are problems — such as the one the author presents — that have existing solutions that don’t require callback hell, or locks, or tricky-to-understand threading issues. I don’t think the author intends to misrepresent current best practices — they may just not be as well-known as I think they are. Hence this article. PS Definitely read Marcus Zarra’s Exploring MVC-N in Swift. While Marcus and I might implement some details differently, those details are matters of style — in broader terms we are absolutely sitting at the same counter. PPS I struggled with this article because the last thing I want to do is discourage a developer who’s presumably younger than I am (safe bet) to stop writing. Note to the author: if you’re of a mind to, please write a follow-up! I’ll happily and very gladly link to it.

Posted by on 4 April 2016 | 4:22 pm

On UIKit for Macs

Every time it comes up that Macs should support some sort of extended UIKit rather than AppKit, I think about all the differences between Macs and iOS devices. On iOS you don’t have to deal with multiple, resizable, movable windows open at the time. Or with being open but not frontmost. Or with a window moving between screens with different resolutions. You don’t have menus (for the most part), and I’d bet most iOS developers don’t have to think about the responder chain much, or about enabling and disabling user interface items. There’s no AppleScript support. And sandboxing is a whole other thing on Macs. Etc. * * * There are plenty the two platforms have in common — and, indeed, we use some of the same frameworks: Foundation and Core Data, for instance. It’s already true that an app can share its under-the-hood code between Mac and iOS. You can even share some UI code via Quartz and Core Animation. However, there are areas where AppKit and UIKit have the same things but with slightly different APIs: tables, for instance, are similar but different between the two platforms. NSView (Mac) and UIView (iOS) are nearly the same, but aren’t actually the same. And there are things Macs don’t have at all — navigation controllers, for instance, since they don’t make sense in a context where you can just show the hierarchy via multiple panes. * * * Were Macs to get some form of UIKit, it would have to be extended with all the things Macs need. Let’s assume we’ll still have multiple, resizable, movable windows; we’ll still have a menubar; we’ll still have AppleScript and Services and similar. Anybody bringing an iOS app to the Mac is going to have to learn those things and handle them. This is a much bigger deal than just getting an iPhone app working on iPads. I think the premise is that the porting job would be quicker if Macs supported things like UITableView — you wouldn’t have to rewrite your table view to make it work on Macs. But I have to wonder. Given that there’s a bunch of stuff you’d have to learn and do in any case, how onerous is the difference between NSTableView and UITableView? They’re extremely similar already. Your biggest challenge is probably just that the dimensions of a table view (or most any view) can change arbitrarily, at any time, on a Mac — and you’d have to deal with that whether you were using UIKit or AppKit. * * * I have a theory on why there aren’t more Mac apps. One is that the additional stuff — menus, live resizing, AppleScript, etc. — is enough of a burden that people just don’t want to do it. You’d still have those things even with UIKit for Macs: they’d have to be added to UIKit, and so that particular burden is not going away. But I think the more important reason is that Macs aren’t exciting to most developers in the way iOS devices are exciting. Macs are where people quietly get their work done, in much the same ways they did 10 and 20 years ago. There’s your spreadsheet and your word processor. Web browser and email. Graphics editor and text editor. Chat window. You may be swiping a bit these days, but you’re also still just clicking with a mouse. It’s boring. (That is, until you realize that Mac users love software that helps them get their work done. They support indies and small businesses passionately. Doing great work for these folks is terrifically exciting — but I realize you’re not going to listen to me.) How do you fix that? How do you make Mac apps exciting to developers? I think — perhaps surprisingly — that you bring UIKit to the Mac. Even though I’ve spent just about this entire post explaining why it’s not needed and wouldn’t be particularly helpful, I think you do it anyway, as marketing to developers. There’s a risk, though — once developers realize that UIKit for Macs doesn’t get them out of dealing with all that extra stuff Mac apps need, they may complain that Mac apps are still too much work. Sure. But I think you do it anyway. Note to Apple: go for it.

Posted by on 1 April 2016 | 1:50 pm

Sound Off Round 2 - UIKonf

Sound Off is raising money for live captioning at UIKonf: Live captioning for UIKonf is not only going to open up the conference to the deaf community and the hard of hearing, but will be indispensable for many of the attendees for whom English is not their first language. Donate now via GoFundMe.

Posted by on 30 March 2016 | 3:11 pm

How It Went at the Caucus

On Saturday morning we went to a nearby school (in my neighborhood in Seattle) and attended the caucus for our precinct. Sanders beat Clinton 94-35 — four delegates to one. I was nervous, since I hadn’t been to a caucus before, and since I knew I’d be voting on the losing side. I was afraid my wife and I would be the only Hillary people there! But we weren’t. I was also a little nervous that the proceedings might be other than completely civil. And there was one guy — Mr. Well Actually — who interrupted Hillary speakers until other people reminded him that everybody gets their turn. That was the worst of it, which means it wasn’t bad at all, and I needn’t have worried. * * * On the night before we pre-registered online and printed out a form and wrote in our initial preference. On Saturday, just before 10 am, we took our forms and went to a gym room at the school and waited with a few other precincts for about half an hour. Then the guy running our precinct’s caucus called us together, and we walked out into the hall and found the particular hallway where we’d be caucusing. It was crowded and hard to hear, so the guy suggested we go outside. We went outside. It was warm enough and sunny, so it was nice. The people who run caucuses aren’t professional caucus-runners, obviously, so we didn’t totally stick to the script. We missed doing the initial tally. We did split physically into three camps: Sanders, Clinton, and undecided. Undecided had just a half-dozen or so people. * * * Then people volunteered to speak for Sanders and Clinton, and they alternated. There were four of five speakers for each, and each spoke for about three minutes. Nobody had a practiced speech that I could tell. (I didn’t speak, though I was tempted.) (One undecided voter spoke too.) Only one of the speakers was at all provocative — a woman who said that Clinton supporters were “voting out of fear,” which elicited a bunch of head-shaking and audible no’s. The speakers who did best were the ones who talked about why they were for their candidate, rather than why they were against the other candidate. * * * Very few people changed their votes. We turned in our forms to the person running the caucus, then people huddled around him and did arithmetic. It took a while. About half the crowd left during the math phase. But we wanted to stay for the whole thing, because that part is democracy too, and we like democracy. (It ended before noon. It’s not like it took ridiculously long.) Once that was done, and the tally and delegate totals were announced, then each side elected their delegates. For us (since we had just one delegate), it was easy. A person volunteered, and we all just agreed. We needed two alternates, and people volunteered and we agreed. Simple. Those delegates go to a local convention. There are layers of conventions before there are delegates to the national convention. So it’s no giant commitment to be a delegate — but still, it’s very cool of those people to volunteer. * * * I expect to caucus again next time. It’s kind of fun. But I still massively prefer a secret-ballot primary system. You get way more participation that way: it’s more democratic. I’m not saying the outcome would have been any different — probably not. I just think it’s fairer. More people have a voice and feel like they have a stake when they can actually participate. It’s why we’re Democrats, after all. * * * It was my 48th birthday. For my birthday I got to cast a vote for the person I believe will be the first woman President of the United States of America. It felt great. (No offense meant to Sanders supporters. I like Sanders too — I’ve been a fan for years. I think Hillary would be a better President, so I voted for her. Reasonable people may disagree.)

Posted by on 28 March 2016 | 3:44 pm

OmniOutliner 4.5.1

The latest OmniOutliner for Mac is up. (It will be in the app store once it passes review. This week is my guess.) Changes include some printing bug fixes — and also a fix for a cosmetic bug that was driving me crazy: in the sidebar, when you collapse or expand the Styles, the Contents outline will now stay in place. (Previously it was changing position then changing back. Animatedly.) The fix, by the way, was just to switch to a flipped NSView, so that 0,0 is at the upper left rather than bottom left. Given that we’re using auto layout, I didn’t expect the flipped-ness of a view to matter, but it does. (I should have known better.)

Posted by on 28 March 2016 | 2:13 pm

CocoaConf Seattle Sale

The Early Bird Sale for CocoaConf Seattle ends Friday night. Check out the great list of speakers! @natashatherobot is doing two talks. That right there makes it worth it.

Posted by on 23 March 2016 | 5:16 pm

Notes from a Conditional Breakpoint

Write some good songs — that people like and that make them laugh — and make some slides to go with them. Create an album of those songs that appears in the iTunes charts. Then write some more songs. Then — just to up the ante — do a bunch of live performances every year, but never with the same band. And be a great singer and entertainer every single time. And be an intelligent, friendly, and good person. A person anybody would be glad to call friend. That’s James Dempsey. Because the songs are nerdy and funny, because James looks like a guy who’s just having fun, it might be easy to overlook what an achievement all this is. You try it! * * * I’ve played with James several times, which makes me a Conditional Breakpoint. (Including most recently at the Yosemite Cocoaconf.) I’ve played campfire guitar and the occasional piano-found-in-a-bar — but never, before James, have I played with other musicians with a set list and a crowd. It’s such a pleasure, and one that I never expected in life. So much fun. I have James to thank. And I’d also like to thank, from the most recent Yosemite show: Jim, Laura, Allen, Jean, Serenity, TJ, Daniel, Christopher, and Jonathan. That right there is a super-group. PS I remember a few spots where I messed up. The ending of a couple songs, and coming out of the bridge on “Model View Controller.” I’ll nail those at Seattle CocoaConf. :) PPS In case you don’t already have it, you can get the album. PPPS With Jonathan there, how could we resist doing a live performance of the ATP theme song? We couldn’t. I assume there will be a video at some point and I’ll link to it. Update 3:30 pm: Here’s an iPhone video of the ATP theme song, recorded by Andrew Milham. And more of a close-up video recorded by Kim Ahlberg.

Posted by on 22 March 2016 | 3:20 pm

Nerds in a Room

At the Yosemite conference — which was wonderful, which you should attend if they do it again next year — I did the kind of talk I’ve been moving toward as I get away from technical talks. Technical talks are great and a needed thing, but I don’t love doing them, so I leave them to other people. Lately I’ve been doing what I think of as nightclub act. The idea is simple: do 15 to 20 minutes on something non-technical but, hopefully, interesting. Tell a story and throw in a few jokes. Roll with whatever happens. Get the audience involved. If the crowd is small enough (such as at Yosemite) I just go around and the room and have everyone introduce themselves. (Mic technique is key, there, and I flubbed it at Yosemite. The rest of the audience needs to hear what each person is saying, and I didn't have the mic close enough in every case. Lesson learned.) * * * I’m not necessarily suggesting this for anybody else or even giving advice. And I’m not saying I’m great at this — just that I’ve gotten to where I can reasonably pull it off. (As Laura Savino said in her fantastic talk: let’s not be afraid to be mediocre in public!) But people asked me about it, so I figured I’d write up how I approach it. The Goal A thing like this has to be the last talk, preferably on the first night, and my goal is to propel people toward the socializing that happens right after. I want the talk to feel intimate, relaxed, and fun — because that’s the mindset we should all be in as we stand up and start talking to other people. I also want people to feel as if they can talk to anybody. They’ve just heard and seen me be a big dork who goes around and does exactly that — and they can do it too. It’s as easy as asking “What’s your name?” How I Prepare I’m lousy at slide management, and I’ve realized I don’t really like slides. So I try to use as few as possible. This one had four, and I cut the first one (the one with the title and my contact info) at the last second, and so I had just three. And almost the entire talk was done with just one slide. (It was a giant, blurry photo of a raccoon in my back yard.) (I might go entirely without slides next time. For what I’m doing, slides are a crutch, and I don’t need them.) I wrote out my talk first. Then I spent about six hours rehearsing it over two days (and many thousands of steps as I paced), and revising it as I went. I do not try to stick too close the script when rehearsing — I let myself improvise. Sometimes those bits end up back in the written version, and sometimes not. But it makes me comfortable with improvising, which I then bring to the performance later. (Example: in the delivered talk, I had a made-up-on-the-spot thing about how the folks in the room were the people who wrote the targeting computer that Luke Skywalker switched off before blowing up the Death Star. We had unit tests! It would have worked! But no. Luke’s a jerk.) How I Perform I like to swing my arms above my head a few times right before starting. It gets a little adrenaline going and it loosens me up. It makes me feel like I can move. I’ll do that right off-stage — or even on-stage — because it doesn’t matter if people see me doing it. If people think, “Hmmm, that’s oddly dorky of him,” then that’s fine. I probably end up moving around during the talk more than I should, but I’d rather that than get trapped behind the podium. Then I keep in mind a few things: The audience wants it to go well. Of course they do! That’s why they’re here. They’re rooting for me and for every other speaker. And: time flows at a different rate for the speaker than for the audience. It feels like ten minutes for me equals one second in the audience — so I compensate and slow down more than actually feels right. Also: when my brain suddenly goes multi-threaded, I just pause, let it go back to a single track, then move on. My brain sometimes wants to comment on what’s happening — so while I allow for improvising, I filter out, as much as I can, the self-conscious things my brain comes up with. (Just as time is different for the speaker and the audience, attention-to-detail is also different. When I’m up there, I’m hyper-aware — and critical — of what I’m doing, but nobody else in the room is in that position. So I don’t sweat if I flub a sentence or lose the train for a second or whatever. If I remain cool, then it’s like we’re just a couple nerds talking. Which is totally what I’m going for.) So: having prepared, having rehearsed improvising, knowing that the crowd starts out on my side, having gotten ready to move, having slowed down my sense of time and turned on my self-consciousness filters, I then just hope that something happens. I want that particular performance to be possible only in that room, that night, that hour, with those people. And something always does happen. I went way too far stage-right and triggered some nasty feedback, and backed away slowly. (The subtext of every moment like that: we’re just nerds in a room! Total amateurs! Mediocre in public! We laugh and move on.) Even better, though: since it was Yosemite, I could bring a pint of Stella on stage with me. And then — unplanned, and brilliantly executed — Jim Dalrymple snuck up and refilled my beer right as I was getting to the main point of the talk. I couldn’t have planned anything better. (Lesson learned: I should always require that Jim is in the room when I talk. We understand each other.) Sure, you had to be there — but that’s my point. It worked right there and then, and it was unplanned yet so right. (I don’t actually recommend drinking, even beer, while presenting. It just makes the whole thing a bit more challenging, and if you go too far then you’re not actually going to give the audience their money’s worth. So let’s just say that it worked largely okay once and leave it at that.) Later Then I spend a week thinking about how it went and how it could go better. Next time I’m sure I’ll have a different story to tell — or I’ll have modified the story in some important ways to make it work better. And I vow to spend even more hours in rehearsal next time. The more prepared I am, the looser and more comfortable I will be — and the better able to roll with the room. Funny thing: the more I do this, the harder I work at it. I’ve gotten to the point where it’s fun, and I hope it shows.

Posted by on 18 March 2016 | 9:12 pm

Chug on Fixing the App Store

Chuq Von Rospach writes: I’m a strong believer that the indie developers are where the innovation comes from, not to mention the next generation of experts on the platform, and that it makes sense to invest in supporting them beyond what the revenue their apps will return through sales on the platform, but in all honesty, the revenue numbers and analytics make that a tough sell, and Apple is likely in that place where there are 300 proposals on the project list for the next year, and resources for 50 of them, so how do you choose which ones make the cut?

Posted by on 11 March 2016 | 6:24 pm

Indies and the App Store

Rene Ritchie, in What no indie developer wants to hear about the App Store, writes: Big apps get all the attention these days, just like big movie, music, or book releases — or big toy releases — and indies get what little is left, when there’s even a little left. The App Store is big business, and that’s how big business works. Only our nostalgia keeps us thinking otherwise. Just like our nostalgia for the corner store in the age of online and big box. On this same subject, Ben Thompson’s Why doesn't Apple enable sustainable businesses on the app store? is worth a re-read. * * * Obviously some companies are doing well — such as Omni, where I work — selling productivity apps on the App Store. And indies would do better than they are right now — possibly much better — if the App Store had trial versions, upgrade pricing, and a faster and better review process. (And the Mac App Store should make sandboxing either less onerous or, preferably, optional.) (And — since I’m listing the ponies I want — it would help if Apple took something like 10% rather than 30%.) But a couple other things are true: There was never a golden age for indie iOS developers. It was easier earlier on, but it was never golden. (Yes, some people made money, and some are today. I don’t mean that there were zero successes.) And there’s a good chance that many of the people you currently think of as thriving iOS indie developers are making money in other ways: contracting, podcast ads, Mac apps, etc. * * * Speaking of Mac apps: ten years ago you could make money writing and selling Mac apps. There was a small-but-awesome community of indie Mac developers. This hasn’t changed. The Mac has for a long time been overlooked — first because Windows was so huge, and then web apps, and now iOS. For my entire career people have said that the Mac is a bad bet, that it’s dumb to write Mac apps. In 2002, in Why I develop for Mac OS X, I explained that I write Mac apps for emotional reasons. Those emotional reasons still apply, and are enough, themselves, to keep me writing Mac apps. But my experience since then tells me that writing Mac apps is the best economic bet for indies. (Particularly if you sell the app yourself, so you can have a trial version and upgrade pricing.) It’s okay that you totally don’t believe me. I know you don’t. But Mac developers have been going against the prevailing wisdom — and making great apps — for decades. We’ll keep going. * * * Update 2:20 pm: See, from 2008, Advice for indies.

Posted by on 11 March 2016 | 4:08 pm

Question for Ted Cruz

In 2014 Senator Ted Cruz attempted, by use of a filibuster, to prevent Congress from raising the debt ceiling. Had he been successful, the United States would have defaulted on its debt, with unknown — but likely extremely dire — consequences. Cruz — throughout his Senatorial career and through this campaign — has often spoken of returning America to the rule of the Constitution. But there’s the matter of the 14th Amendment. From Section 4: The validity of the public debt of the United States, authorized by law, including debts incurred for payment of pensions and bounties for services in suppressing insurrection or rebellion, shall not be questioned. This was ratified after the Civil War, hence the “suppressing insurrection or rebellion” part. But the gist remains: the validity of the public debt shall not be questioned. If the only way to follow the Constitution is for the President to ask Congress to raise the debt ceiling, would President Cruz do so? (Historical note: the debt ceiling was raised 17 times during President Reagan’s time in office. It’s not a new thing.)

Posted by on 7 March 2016 | 3:43 pm

Lizcast

The Omni Group’s Liz Marley, who recently transitioned from testing to engineering, appears on the NSNorth 2016 podcast. She talks about… …challenges in engineering school, working with office cats, making the transition from software engineering to testing to developing and how knitting, like code, has the ultimate undo. Knitting is serious (though not somber) business here at Omni.

Posted by on 4 March 2016 | 12:11 pm

OmniOutliner 4.5

OmniOutliner 4.5 is up on Omni’s site, and should be in the Mac App Store within days. With this release — see the release notes — I helped work on, of all things, printing bugs and features. This is the first time in my entire career where I worked on printing support that was more than just the most basic possible thing. And that sounds weird for the year 2016, I realize. But here’s the thing: working on printing support is far from glamorous. You wouldn’t call it fun. But the people who need these features really do need them, and it’s a matter of respect for OmniOutliner users that we do a great job even with printing. But I sure am glad to get it finished and shipping. And I’m proud of the work we did — more proud than I expected to be. It’s solid, and I think the people who print from OmniOutliner will be very pleased. Now we’re on to other new features, including editing Markdown documents with OmniOutliner.

Posted by on 1 March 2016 | 12:15 pm