Via email, Peter Sacréas, pointed out that my Complete and Await Reply script loses links in the notes of the tasks you apply it to. The script was making a new note by getting the text of an existing note, manipulating it, and then setting the note property of the duplicated task. Applescript is notoriously bad at handling rich text. By round-tripping the entire note through Applescript, I was losing the link.
In practice, the script just needs to insert some new text at the beginning of the note. So, instead of replacing the full text on the note, I switched to using an incantation that inserts plain text before the existing note, leaving the rich text unchanged:
set textToInsert to notePrefix & ((current date) as text) & return insert textToInsert at before first character of note of theDupe
Bug fixed! You can grab the updated version here.
Share and enjoy!
A lot of the discussion around the final/sealed-by-default issue focused on the ability in ObjC to extend frameworks or fix bugs in unforeseen ways. Framework developers aren’t perfect, and being able to patch a broken framework method can be the difference between shipping and not. On the other hand, these patches become compatibility liabilities for libraries, which have to contend not only with preserving their own designed interface but all the undesigned interactions with shipping apps based on those libraries. The Objective-C model of monkey-patchable-everything has problems, but so does the buttoned-down everything-is-static C++ world many of us rightly fear. However, with the work we’re putting into Swift for resilience and strong versioning support, I think we’re in a good position to try to find a reasonable compromise.
The essence of the idea is to provide specific, language-level support for declaring a patch to framework code from client code. Joe also sketches a corresponding mechanism for assisting framework authors in evolving their code while still supporting apps that rely on previous, buggy framework behavior.
There are lots of details that would need to be worked out, but mostly I’m gratified that Joe so clearly articulates the concerns that many of us in the app development community share.
The video of my talk on OAAppearance at Seattle Xcoders in December is now posted. I’m sorry that the audio quality isn’t great. I had some technical difficulties with the lapel mic, so we only captured the audio from the built-in mic on my Air.
I’m excited to be able to speak at CocoaConf Seattle in May. There are some great speakers lined up, including several folks from the terrific Seattle Xcoders community. Early-bird registration is open now.
I have a few ideas for topics that I might talk about:
- My December Xcoders talk on runtime hacking in
OAAppearancewas well received. I could revise and update that material. The downside here is that CocoaConf tends to be forward looking—most talks use Swift examples. Runtime hacking is mostly an Objective-C thing currently.
I could give an intro to functional reactive programming. At Omni we’re currently using a bit of reactive programming in OmniFocus for Mac. Rather than use an existing library, we rolled our own. That’s a fairly typical approach at Omni; we don’t like to have dependencies on other third-party tools when we’re trying to ship on OS release days.
My post on generic state machines in Swift was fun to write. I could talk about state machines in general and how Swift’s generics can help us write a concise, reusable state machine. This talk would probably include two or three practical examples of using state machines in sample apps.
What do you think? Are any of those topics interesting to you? Are there any topics about Cocoa development in general or development at Omni in particular that you’d like to hear about? Let me know!
A recent thread on the swift-evolution mailing list has me very concerned. My professional interests are primarily around developing productivity apps for end users. More people from our slice of the Apple developer community need to get involved. Perhaps this thread can be a call to action.
I’m incredibly impressed with the work Apple has done to make Swift truly an open source project with the community driving discussion. As someone who’s spent some time doing language design work (MultiJava, JML, MAO), I’m particularly enjoying the proposals and discussions regarding possible improvements to the language and libraries. These mostly happen on swift-evolution (archive here, sign up here, description of the evolution process here).
As you’d expect from a just-opened community like this, swift-evolution is high volume. A great many of the suggestions aren’t very well considered. (I’d list examples, but don’t want to call out people who are earnestly trying to contribute.) Other suggestions primarily come down to “just syntax”. For example, this proposal to “Require self for accessing instance members” and this (accepted) proposal to “Remove C-style for-loops with conditions and incrementers” don’t inheritly change the language or what we can do with it.
On the other hand, there are some suggestions that will have long term effects on the language and the ecosystem that develops around it. These are the ones that I find most interesting, because they’ll have outsized effects on the language I’m likely to use for the rest of my career. An example of this is a discussion thread on “Final by default for classes and methods”.
I often just dip a toe into the water of these interesting threads to check the temperature of the conversation and to see if members of the Swift core team are chiming in. Partly I’m interested in how the team is fostering community—they’ve been incredibly gracious—and partly I suspect suggestions that provoke core team interest are more likely to become formal proposal and be considered for inclusion in the language.
A Surprising Direction
In this spirit, I was skimming the suggestion to make classes and methods
final by default. The thread starts here and ends here at the moment. Browsing long threads in the web interface is … challenging, so I’ll recap.
Here’s the core of the suggestion:
“It is not uncommon to have a need for a reference type without a need for inheritance. Superclasses should be intentionally designed to be subclasses and the author required to opt-in to subclassing and member overrides where that is required by the design.”
That is, the suggestion is that subclassing classes and overriding methods should be implicitly banned unless the framework author takes specific action to permit such indignities. The idea has evolved a bit over the last two+ weeks, to suggest that this implicit ban only apply across module boundaries.
I was shocked to find many members of the Swift team at Apple agreeing with this suggestion. When I’d mentioned the suggestion to co-workers and to friends in the app development community, to a person they said it was ridiculous. Most made some variation of the argument that I posted to the mailing list:
Anyone who tries to ship products on release day of Apple’s operating system updates spends most of August and September writing horrible hacks so that their users are insulated from OS bugs as much as possible. All software has bugs, frameworks included. Please don’t take away our tools for working around those bugs. Making classes final by default assumes a level of perfection on the part of framework developers that is not achievable.
Yes, subclassing a class that wasn’t designed to be subclassed has serious risks. Thoughtful developers sometimes take on those risks in order to serve their customers.
Frankly, I think having
finalin the language at all is a mistake. While I agree that we should prefer composition to inheritance*, declaring things final is hubris. The only reasonable use case I’ve seen is for optimization, but that smacks of developers serving the compiler rather than the converse. Bringing an analog of
NS_REQUIRES_SUPERto Swift would be most welcome; that’s as far as I’d go down the path of dictating framework usage.
*- and am thrilled with the property behaviors proposal for this use case
I was further shocked when Jordan Rose at Apple replied (elisions mine):
Okay, so I probably shouldn’t be putting this so bluntly, but the ship has already sailed on this. Supporting arbitrary code injection into someone else’s framework is a non-goal for Swift, perhaps even an anti-goal.
[…substantial detail elided…]
If you replace a method on someone else’s class, you don’t actually know what semantics they’re relying on. Of course Apple code will have bugs in it. Trying to patch over these bugs in your own code is (1) obviously not an answer Apple would support, but also (2) fraught with peril, and (3) likely to break in the next OS release.
TLDR: It’s already unsafe to do this with the existing set of Swift features. Yes, this makes things “worse”, but it’s not something we’re interested in supporting anyway.
That prompted me to write:
Presumably a goal for Swift is that application developers will use it to build user-facing apps for Apple’s platforms. And presumably a goal for Apple is that developers help promote Apple’s platforms by shipping apps that take advantage of the new OS features when they ship. I fear that you and others dramatically underestimate the difficultly of doing that. I acknowledge your three points. But understand that we are professionals trying to serve our mutual customers. Temporary hacks in the service of shipping is the nature of the business.
I don’t know how to make the case more strongly than I already have. This thread makes me worry that the team does not understand what it’s like for third party developers trying to serve our mutual customers.
Then I got snotty on Twitter:
Very troubling thread on making final default for classes/methods. Swift team seems hostile to app developers.
Here’s the Deal
Doug Gregor rightly called me out for painting with too broad a brush. That said, I still fear that the team fails to understand how hard it is to ship on Apple’s platforms. As third party developers we:
- don’t have the code for Apple’s frameworks,
- can’t communicate with the framework authors, and
- can’t even attempt to change the priority of a framework bug when it’s critical to our “tent pole” features.
Swift does help us avoid major classes of bugs. Swift does not mean that Apple will ship bug-free frameworks. All software has bugs. As app developers we need tools to work around Apple’s bugs in the service of our customers.
So, What’s to be Done?
I love that Apple engineers are actively posting on the mailing lists. I don’t want my little snit to suppress that, and certainly don’t think I really have any influence on that one way or another.
The beauty of a community process is that all of us can participate. If you’re an app developer on Apple’s platforms, please sign up for the swift-evolution mailing list. You don’t even have to read it. Just set up a rule to file the messages.
Once a week, or when people lose their shit on twitter, take a look to see which threads are hot. If you see a proposal gaining traction that you know would make it harder to ship apps, well, you know where the reply button is. And if your reaction to
final-as-default matched mine, that thread might be a good place to start.
We need to step up and be a part of the community. Otherwise we may find that we’re developing with a language that doesn’t work for our needs.