Saturday, May 21, 2016

What's Missing in the Discussion about Dynamic Swift

There have been some great posts recently on the need for dynamic features
in Swift.

I think Gus Muller
really nails it with his description of adding an "Add Layer Mask" menu item to
Acorn that directly talks to the addLayerMask: implementation:

With that in place, I can add a new menu item named "Add Layer Mask" with an action of addLayerMask: and a target of nil. Then in the layer class (or subclass if it's only specific to a bitmap or shape layer) I add a single method named addLayerMask:, and I'm pretty much done after writing the code to do the real work.

[..]

What I didn't add was a giant switch statement like we did in the bad old days of classic Mac OS programming. What I didn't add was glue code in various locations setting up targets and actions at runtime that would have to be massaged and updated whenever I changed something. I'm not checking a list of selectors and casting classes around to make the right calls.

The last part is the important bit, I think: no need to add boiler-plate glue code.
IMHO, glue code is what is currently killing us, productivity-wise. It is sort of
like software's dark matter, largely invisible but making up 90% of the mass of
our software universe.

In case it’s not clear: with recent and future articles I’m documenting problems that Mac and iOS developers solve using the dynamic features of the Objective-C runtime.
My point isn’t to argue that Swift itself should have similar features — I think it should, but that’s not the point.
The point is that these problems will need solving in a possible future world without the Objective-C runtime. These kinds of problems should be considered as that world is being designed. The answers don’t have to be the same answers as Objective-C — but they need to be good answers, better than (for instance) writing a script to generate some code.

Again, that's a really important point: it's not that us old Objective-C hands are
saying "we must have dynamic features", it's that there are problems that need
solving that are solved really, really well with dynamic features, and really, really
poorly in languages lacking such dynamic features.

However, many of these dynamic features are definitely hacks, with various issues,
some of which I talk about in The Siren Call of KVO and (Cocoa) Bindings.
I think everyone would like to have these sorts of features implemented in a way
that is not hacky, and that the compiler can help us with, somehow.

I am not aware of any technology or technique that makes this possible, i.e. that
gives us the power of a dynamic runtime when it comes to building these types
of generic architectural adapters in a statically type-safe way. And the
direction that Objective-C has been going, and that Swift follows with a
vengeance is to remove those dynamic features in deference to static features.

So that's a big worry. However, an even bigger worry, at least for me, is that
Apple will take Brent's concern extremely literally, and provide static solutions
for exactly the specific problems outlined (and maybe a few others they can think
of). There are some early indicators that this will be the case, for example that
you can use CoreData from Swift, but you couldn't actually build it.

And that would be missing the point of dynamic languages almost completely.

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

If you focus on just messaging - and realize that a good metasystem can
late bind the various 2nd level architectures used in objects - then much
of the language-, UI-, and OS based discussions on this thread are really
quite moot.

[..]

I think I recall also pointing out that it is vitally important not just to
have a complete metasystem, but to have fences that help guard the crossing
of metaboundaries. [..assignment..] I would say that a system that allowed other metathings to be done
in the ordinary course of programming (like changing what inheritance
means, or what is an instance) is a bad design. (I believe that systems
should allow these things, but the design should be such that there are
clear fences that have to be crossed when serious extensions are made.)

[..]

I would suggest that more progress could be made if the smart and talented
Squeak list would think more about what the next step in metaprogramming
should be - how can we get great power, parsimony, AND security of meaning?

Note that Objective-C's metasystem does allow changing meta-things in
the normal course of programming, and it is rather ad-hoc about which things
it allows us to change and which it does not. It is a bad design, as far as metasystems
are concerned. However, even a bad metasystem is better than no metasystem.
Or to quote Guy Steele (again):

This is the nub of what I want to say. A language design can no longer be a thing. It must be a pattern—a pattern for growth—a pattern for growing the pattern for defining the patterns that programmers can use for their real work and their main goal.

The solution to bad metasystems is not to ban metasystems, it is to
design better metasystems that allow these things in a more disciplined and
more flexible way.