Wil, Chris, Waffle, Samuel, Soroush

Wil Shipley:

So Cocoa programmers are in a tizzy A TIZZY I SAY at the prospect of going back to the bad old days (eg, 1987).

And…

I urge anyone who's speculating about Swift's possible future missteps to look hard at the team that's brought us LLVM, clang, ARC, and Swift, and think, “it’s pretty likely they’ll handle this,” not, “OH GOD EVERYTHING I LOVE IS ENDING.” (The latter of which, incidentally, is my nightly mantra.)

The tizzy is part of the process. I like to think that the various blog posts and Twitter discussions are contributions to a discussion rather than just words expended for no reason. It’s not venting or declaring that the sky for sure will fall — it’s people doing their part to think and communicate about tools that are important to them.

Also: 1987? For Wil, 1987 may have been the last of the bad old days. For other people, 1997 is more likely — but for me it was 2002, and for other people the bad old days are even more recent.

Consider Elm. People have talked it up to me, and it looks pretty cool, and I’m sure it’s awesome in a bunch of ways, and there are probably a bunch of things to learn from it.

But look at this small example of handling button presses. There are two buttons, and there’s a case (switch) statement to handle the message.

In a small example like this it doesn’t seem onerous. But an app is a much bigger thing, and doing this kind of thing everywhere would work me into a tizzy.

* * *

Chris Eidhof:

Yet, techniques you don’t know will almost always seem more complicated at first. I tried arguing with a Haskell programmer that runtime programming can be useful. I tried arguing with a Ruby programmer that static types can be helpful. To both, it seemed unnecessary and complicated. They’ve been writing great code without those features.

* * *

Waffle:

What I also expect is there to be a dialogue right now about these kinds of details by people who know what they’re talking about, about how Swift could actually become more dynamic without copying the flaws of its progenitors and without selling out the feel, mechanics and (most of the) performance of the language.

* * *

Samuel Ford:

My experience working with type strict frameworks is that they are fussy. It’s like if the only way you could chop things when cooking is with an array of specialty chopping tools that have to be assembled from pieces every time you needed them. And you have one for garlic, another for potatoes, and so on.

Every time you start to cook, you’ll feel the weight of taking those tools out, assembling the pieces, then taking them back apart, washing them, and putting them away. What you’ll find over time is that the recipes themselves will adapt to require fewer chopping tools and will become more plain and more similar over time.

* * *

Soroush Khanlou:

Primarily, the big thing I got wrong last year was that Swift is just plain fun. This weekend, I had the pleasure of helping a friend with code-review. His project is completely in Objective-C, and our code review session reminded me how rough the rough edges of that language are, especially after spending any time in Swift.

A Definition of Dynamic Programming in the Cocoa World

When I talk about dynamic programming on iOS and Mac, I mean this:

  1. An app can learn about its structure at runtime.

  2. An app can do things based on what it knows about its structure.

  3. An app can make changes to its structure.

The first is things like knowing what methods an instance implements, or getting a reference to a protocol, class, or method from a string. (As in NSSelectorFromString and so on.)

The second is things like being able to instantiate a class where the name wasn’t known at compile time, or to call a method or reference a property that wasn’t known at compile time. (As with performSelector:, KVC, the responder chain, and xib and storyboard loading.)

The third is things like adding methods at runtime (a la Core Data) or adding classes — for instance, by loading compiled code from disk (plugins).

(Note — because people sometimes misread what I write — this definition is not advocacy for a particular style of programming, nor is it a judgment of Swift, which, I repeat, I love, and is my preferred language. It’s to help us know what we’re talking about when we talk about dynamic programming.)

Oldie Complains About the Old Old Ways

I saw a thing on Twitter that said I’m just an old guy complaining about the new ways. Then the tweet was deleted, to the credit of its author. But let me take up the point.

It’s not the new ways that bother me — it’s the old old ways. That is, how I wrote apps before I started using AppKit.

In those days it was common to use C or C++ — always C for me, thankfully — and you may or may not have used an app framework (MacApp, PowerPlant, MFC, etc.). The app framework might generate code for you, which was a source of fragility and bugs. But, even if not, you had to do things like this:

Menu item with unique ID is chosen
App’s central event handler is called
App looks at its context and dispatches event to the right function

There were lots of switch statements. To add, for instance, a copy (or whatever) implementation to a particular view, you’d have to edit your event dispatcher to know about that particular view and its copy function. Making changes required making changes in various places.

Sure, there were things you could to make this a bit easier. It didn’t have to be total spaghetti. But, even at best, it was bad code, and there was nothing you could do about it.

Contrast that with the first time I used AppKit about 15 years ago. I wrote an action method in a view, wired it to a menu item in Interface Builder, and it worked. No switch statements, no touching a half-dozen locations just to add a command.

I’m sure, that first time, that I didn’t even wire that menu item up to First Responder. It was wired directly. But, even still, AppKit used the runtime’s dynamic features to be able to find and call the right object and the right method. And that’s still true today. (Even in UIKit. Even if it’s a button. In other words, if you don’t think you’re taking advantage of Objective-C’s dynamic features, you totally are.)

It seemed like magic, then. I later came to understand how it worked, and then it just seemed like brilliance. (Brilliance is better than magic, because you get to learn it.)

* * *

So when people like me write about these problems, it’s not because we fear the future and new ways of doing things. We love learning new ways of doing things — particularly when they’re better solutions to the problems we have.

We’re not afraid of the future — we’re afraid of the past.

We remember how these problems were solved by the static languages of the day, and we don’t want to go back. In the words of Guy English:

If you see a switch statement or dispatch table they blew it.

So, again, I’m documenting the problems currently solved by Objective-C’s dynamism, and suggesting that Swift, as it evolves, needs to take these problems into account. The foundation should be built with some idea of what the upper floors will look like.

The answer doesn’t have to be that Swift is dynamic in the way Objective-C is, or even dynamic at all. But the eventual Swift app frameworks need to solve these problems as well as — hopefully better than — UIKit and AppKit do right now. And those solutions start with the language.

PS I think I’ll write about plugins next.

WA Primary vs. Caucus

While 230,000+ people participated in Washington state’s Democratic caucus, 661,403 (and counting) participated in the non-binding Democratic primary.

The results were even different — Sanders won the caucus by a large margin, while Clinton is winning the primary. Those results could be explained by several different factors, though, and that’s not my point.

My point is that the caucus system decreases participation, and is therefore less democratic than primaries.

In my state we have mail-in voting, which is more fair and accessible than caucuses or even going to the polls on election day.

Anyone who works or cares for children or adults — or who has other responsibilities that keep them from participating in a caucus — can still vote via mail.

And anyone for whom it’s physically or psychically difficult or impossible to attend a caucus has a much better chance of voting via mail.

As a Democrat, it’s disheartening to see my own party effectively locking out many thousands of people from participating. This goes against my values — and it goes against the values of the Democratic party. (Or so I thought.)

I wrote a note to the Washington State Democrats and argued the above. You can too.

* * *

The other thing people argue about is whether or not primaries should be open — that is, do you have to be a registered Democrat or Republican to be able to vote?

I like Washington’s system: you have to check a box on your primary ballot that you consider yourself a Democrat or Republican. That’s it.

I think it’s absolutely fair that a party would want members of its party to choose their nominee. You don’t want other people to choose your nominee for you.

But at the same time it shouldn’t be onerous to declare that you’re a Democrat or Republican. If you’re not willing to do that much — well, then, that’s a valid choice, but you don’t get to vote.

Paul, Daniel, Dave

Paul Kim, On Dynamism:

My problems aren’t performance. They aren’t type-safety (maybe it’s just me, but I rarely have issues with it and when I do, the time it takes to fix it is far less than the time specifying everything to a tee everywhere else). They aren’t being able to write clever VDLs. For me, it’s writing apps that solve my users’ problems and getting them out in a timely fashion. As it stands now, Swift (at least pure-Swift, or even current Swift as a non-ABI-stable moving target) does not do that for me.

Now maybe these same problems can be solved in a static way but what I’m not seeing from the static-camp are (decent) solutions. What I’m seeing are either hand-waving or the same crufty code-generation, write tons of repetitive boilerplate type of solutions that I had hoped we had left behind in the 90s.

What I do see makes me worry that it’s not the experienced app-writers that are being heard.

* * *

Daniel Jalkut, Not Perfected Here:

Swift is a fascinating, beautiful language. How will it evolve to prove superior, in the long-run to Objective-C? By providing a suite of impedance-matched frameworks that fulfill all the needs of current iOS and Mac developers.

* * *

Dave DeLong posted 12 tweets on the subject, starting here, and including:

5/ but one of the things I love about @SwiftLang is that, since the dynamism isn’t there, I have to think about problems in new ways

…and…

8/ I know that the people working on @SwiftLang are some of the most brilliant people in the world, and they all also love Objective-C

…and…

10/ so maybe we’ll end up dynamism. Maybe we won’t. What we WILL end up with is one of the most kick-ass languages in the world

Though I could ask about the frameworks (and I did), I can’t argue with Dave’s conclusion. I’ve said before, and will say again, that I’m writing all my new code in Swift and I’m enjoying it a ton, and I get bugged when I have to write Objective-C.

In other words — if you think that the various people writing about Swift and dynamism are anti-Swift, you’ve got it wrong.

Dynamic Swift Comments on Hacker News

I don’t generally point to (or even read) comments on Hacker News — because in the past I’ve found that they’re like other comments on the web.

However, I think the Hacker News comments on Michael Tsai’s Dynamic Swift post are worth reading.

Ash and Marcel

Ash Furrow, Adulterated Objective-C:

…maybe it’s not important to re-invent Objective-C’s dynamic runtime in Swift. The language is far more static than Objective-C. And besides, a dynamic runtime is only a set of tools used to solve problems. In a different context, like Swift, different tools might be better suited.

Problems currently solved with dynamic programming should have solutions just as good (if not better) in Swift and future Swift-only app frameworks. And “better” can’t mean, “Yes, it’s a big pain now and inelegant, but the compiler’s happy.”

I’m skeptical that there is a solution short of adopting the same kinds of dynamic features Objective-C has, but I’m only skeptical. I don’t say it’s impossible. I want to be surprised and amazed.

* * *

Marcel Weiher, What's Missing in the Discussion about Dynamic Swift:

The truly amazing thing about KVC, CoreData, bindings, HOM, NSUndoManager and so on is that none of them were known when Objective-C was designed, and none of them needed specific language/compiler support to implement.

Instead, the language was and is sufficiently malleable that its users can think up these things and then go to implement them. So instead of being an afterthought, a legacy concern or a feature grudgingly and minimally implemented, the metasystem should be the primary focus of new language development. (And unsurprisingly, that's the case in Objective-Smalltalk).

Updating Local Objects with Server Objects

I’ve spent much of my career writing apps that store objects locally that come from the web — and that may change on the web, and then need to be updated locally.

This kind of code can be tedious to write. Given a local object and an objectified version of some JSON or XML or whatever, I’d write something like this (translated to Swift for fun):

if localObject.foo != serverObject.foo {
  localObject.foo = serverObject.foo
  changeDictionary[fooKey] = serverObject.foo
}
if localObject.bar != serverObject.bar {
  localObject.foo = serverObject.bar
  changeDictionary[barKey] = serverObject.bar
}
// multiply above a dozen times and for several different classes
return changeDictionary

Maybe you spotted the bug in the above, and maybe you didn’t — and that’s part of my point. I’d write this code using copy-and-paste, and then go over it visually, line-by-line, to make sure it’s right, and sometimes I’d miss something anyway.

If foo and bar are both strings, for instance, the above would compile and all would be well. Except that I’ve written a bug where localObject.foo = serverObject.bar.

Eventually I found a better way — some code that I can write once, and that can’t have the bug I wrote above. See this gist.

* * *

The solution is pretty simple. You have two objects — which may or may not be the same class but where the properties have the same names — and then loop through an array of mergeable property names. (The two objects don’t have to have the exact same list of property names. They just have to have the mergeable property names and types in common, since those are the ones we care about.)

Then there’s a method that compares the local and server objects. For each property name in the list, it gets the localValue and serverValue using valueForKey:, and then compares them (via isEqual:).

When they’re not equal, then it uses setValue:forKey: on localObject to give it the serverValue. It also adds the property name and new value to a change dictionary. (That dictionary could be useful for efficient database updating, sending notifications, etc.)

There are places this could go wrong, and where the compiler wouldn’t complain. In the gist there’s this line:

static let mergeablePropertyNames = ["dog", "cat", "zebra", "numberOfAnimals", "fedTheTigers", "attendingDoctors"]

Obviously that line has to be maintained, and it has to be true that both local and server objects have those properties and those properties have to be of the same type. Yes.

However, you’re going to notice any error at runtime pretty quickly, since you’ll get an exception — while you may not notice the localObject.foo = serverObject.bar bug from the manual version any time soon.

Best thing: you can reuse that updateLocalObject​WithServerObject method for all the various local/server object updating you need to do in all your apps.

* * *

Even though we’re writing in Swift here, the solution uses the Objective-C runtime and KVC.

KVC is both awesome and to be used sparingly. Most of the time you want to write standard code that the compiler can better check — you want to write foo.bar = true. Absolutely.

But there are those occasional critical cases where KVC creates more reliable code that’s easier to maintain, debug, and reuse. This is one of those.

Layers Conference

In case you haven’t seen it mentioned already — Layers is a design conference in San Francisco taking place the same week as WWDC. It’s “like a party, but for learning,” and promises snacks, and people I respect tell me it’s wonderful.

Be sure to scroll down and look at the list of presenters. It’s amazing.

Gus and Craig

Gus Mueller:

Being able to write dynamic, responder chain-like code in Swift or Objective-C (or whatever) is extremely important to me. And if I had to give one reason why it would be this: Dynamic code is less code, and less code means fewer bugs and maintenance.

Craig Hockenberry:

The community around Swift’s evolution is amazing. The language is improving quickly and dramatically thanks to talented developers inside and outside of Apple. It’s a remarkable open source project.

My concern is that there isn’t a corresponding discussion about the things we’re going to build with this new language. As you’ve just seen, frameworks are important, yet there is no uikit-evolution mailing list. There is an imbalance between the tool and the craft.

Archive

Ads via The Deck