Archive for September 1, 2015

Tuesday, September 1, 2015

Swift Protocols

WWDC 2015 Session 408 (video, PDF):

This is a static type safety hole. Why did it happen? Well, it’s because classes don’t let us express this crucial type relationship between the type of self and the type of other. In fact, you can use this as a “code smell.” So, any time you see a forced down-cast in your code, it’s a good sign that some important type relationship has been lost, and often that’s due to using classes for abstraction.

So when you see Self in a protocol, it’s a placeholder for the type that’s going to conform to that protocol, the model type.

[…]

Now, you might think that forcing the array to be homogeneous is too restrictive or, like, a loss of functionality or flexibility or something. But if you think about it, the original signature was really a lie.

[…]

So, once you add a Self-requirement to a protocol, it moves the protocol into a very different world, where the capabilities have a lot less overlap with classes. It stops being usable as a type.

[…]

We find that, the more we decouple things with protocols, the more testable everything gets. This kind of testing is really similar to what you get with mocks, but it’s so much better.

[…]

You might ask, ‘what does it means to have a requirement that’s also fulfilled immediately in an extension?’ Good question. The answer is that a protocol requirement creates a customization point.

[…]

Swift 1 had lots of generic free functions like this. In Swift 2, we used protocol extensions to make them into methods like this, which is awesome, right? […] No more angle bracket blindness.

[…]

So, building bridges between the static and dynamic worlds is a fascinating design space, and I encourage you to look into more.

Marcel Weiher (channeling Crusty):

You see, I presented ADT (Abstract Data Type) programming to him and called it OOP. It’s a little ruse I use from time to time, and decades of Java, C++ and C# have gone a long way to making it an easy one.

[…]

So not only isn’t inheritance not the defining feature of OOP as I let on, it actually wasn’t even in the original conception of the thing that was first called “object-oriented programming”.

[…]

Because the idea was really to first get him all excited about not needing OOP, and then turn around and show him that all the things I had just shown him in fact were OOP. And still are, as a matter of fact.

[…]

My personal take is that our biggest challenges are in “the big”, meaning programming in the large. How to connect components together in a meaningful, tractable and understandable fashion. Programming the components is, by and large, a solved problem, making it a tiny bit better may make us feel better, but it won’t move the needle on productivity.

David Owens II (tweet):

Ok, so the heart, as I understood the talk, is about thinking of your types as in the form of protocols instead of base classes. The fundamental idea is to get rid of one of the really nasty problems of OOP - implicit data sharing. That’s great because that problem sucks.

It turns out, we can do this today in ObjC with one caveat - default protocol implementations. This is a feature that is new with Swift 2.0 and apparently wasn’t worth bringing back to ObjC.

[…]

I think the important takeaway from the Swift talk is not really about a “new paradigm” of programming, but rather showing a better way to compose software using techniques that we already use day-to-day. It makes it easier to do the better thing (get rid of accidental data sharing between types) and reducing the boiler-plate code required to do it.

There is one thing I’m worried about though: the class extension seems to be creating a very similar problem in that we are getting rid of unintentional data sharing between type hierarchies and replacing it with potentially unintentional functional changes in our programs.

Alexandros Salazar:

I haven’t had a chance to play with it too much, but watching the Protocol-Oriented Programming in Swift session, a particular construct struck me as the most likely source of arcane, incomprehensible bugs in the future. I expect it to be the novice’s crucible, similar to the way deallocated delegates would lead to crashes in the days before the weak attribute was introduced. I’m not yet sure what the searches will look like, but the fundamental question will be a variation of:

“Why does the method that I wrote overriding protocol extension X never get called?”

[…]

By always calling the value in the type’s implementation, then, we forever hide the default implementation of the extension, even in cases where it would be expected. The solution Swift 2 adopted is to call the default implementation when the protocol is explicitly specified.

[…]

The rules for dispatch for protocol extensions, then, are:

  • IF the inferred type of a variable is the protocol:
    • AND the method is defined in the original protocol
      • THEN the runtime type’s implementation is called, irrespective of whether there is a default implementation in the extension.
    • AND the method is not defined in the original protocol,
      • THEN the default implementation is called.
  • ELSE IF the inferred type of the variable is the type
    • THEN the type’s implementation is called.

Omar Abdelhafith:

If you are like me and you prefer reading decisions from a flow chart, the above reasoning can summarised in the following flow chart[…]

David Owens II:

This behavior is unsettling to me. For one, it makes some sense that you cannot change the functionality of another module with extensions to types belonging to that module. On the other hand, if I provide an extension for Sheep in my module, I’ll be able to use the new functionality just fine there, but anytime the type gets used in another module, the functionality will fall-back to the original behavior.

This just sounds like a scary source of bugs waiting to happen. I think the solution might be to simply disallow extensions to protocols that are not defined within the same module. I rather lose out on potential functionality to maintain certain guarantees in my program.

Soroush Khanlou:

With Swift 2, however, while we could continue to use decoration to wrap our data with new functionality, we’ve been given a new power with protocol extensions. Protocol extensions let us add concrete methods to a protocol that are dependent on the abstract methods in that protocol. It’s a form of the template method pattern, but one that doesn’t rely on inheritance.

[…]

Fortunately, we’re saved by protocol extensions here. We can give a default implementation for these properties in an extension, and we can leave it out of the individual request structs.

David Owens II:

To put it another way, if your protocol really only has meaning within your type hierarchy, ask yourself if it really makes sense to make it a protocol. I don’t think an answer of, “well, I want my type to be a struct so I need to use a protocol here instead” is a good reason. Decompose it and make it more applicable if that’s really the case.

[…]

Hopefully this is a just a point-in-time problem, but as soon as you make your protocols generic, you lose the ability have typed collection of hetergenous instances of protocols. I consider this a serious design limitation. For instance, all of the non-Self constrained functionality of a protocol should be safely callable from any place that protocol wants to be used.

This also applies to having your protocol adhere to generic protocols, such as Equatable. Generics are infectious.

Matthew “Canis” Rosenfeld:

Working with plain C structures is frequently a massive pain, so people often write “object oriented” wrappers around them to make them easier to work with. But then you run into leaky abstractions or impedance mismatch. In Swift, you can make the original raw C structs as easy to use as native Swift classes, and get the best of both worlds. Protocol conformance is a part of that.

So, yes, you can work with old-school BSD sockets code (this is a hypothetical example, don’t bug me about its utility) and throw sockaddrs into arrays, let Swift worry about managing their memory, diff those arrays to see what’s changed, and so on, and it all Just Works™.

I see this as one cornerstone of Swift’s “Grand Unified Theory” approach, where (however excited people might get by certain presentations) instead of saying Here Is The One New Way To Do Things, Swift instead allows you to mix and match whatever is appropriate to the task, whether that’s getting all functional, deeply dynamic, protocol-oriented, and more.

[…]

What you can’t do — and this is mostly where people are getting into trouble — is work with collections of arbitrary heterogenous generic protocols.

[…]

when you have an object of protocol type, that is actually a special object instance of about 40 bytes in size.

This is in turn due to that useful fact that anything, from an Int to a C struct to an Obj-C class can confirm to a protocol. You can’t simply cast an array of all those different types, to an array of the protocol, because the underlying data is completely different.

[…]

So, that’s why it stores these special Protocol instances instead, they’re adapters for the underlying types. And that’s why you can’t just cast arbitrary arrays to them. And why you can’t simply dispatch everything dynamically: some of those things just aren’t dynamic-able, because they might be C structs, Ints, native IEEE floating point values, or whatever, not Objective-C objects.

Brent Simmons:

Something like this ought to come naturally and easily to a language, or else that language is not helping me write apps.

This isn’t some weird, made-up situation. It’s super-common. Look at Mail’s sidebar, for instance — there are a bunch of different things. (Or look at Xcode’s sidebar.)

Yes. There are ways to deal with this in Swift, including using @objc protocols and collections. Or proxy objects or base classes (ugh) or whatever.

Andrew Bancroft:

Being a C# developer by day and a Swift developer by night has me constantly thinking about the similarities and differences between these two languages. I genuinely enjoy programming with each, and I love it when I can take a strategy that works well in one language, and see where that might cross over to the other. One of the areas I’ve been pondering as of late is the idea of how Swift and C# compare in terms of protocol extensions and abstract classes.

Previously: Swift Protocols, Arrays, and Casting, Swift Protocols Question, Swift Protocols and Generics.

Update (2015-09-04): Matthew Palmer:

This weekend, I rewrote most of Locksmith, my library for using the iOS keychain, to be protocol-oriented. This was a fascinating process, and one that isn’t yet finished.

[…]

Protocol oriented programming is the best approach I can think of to deal with this complexity and configurability.

Milen Dzhumerov:

Protocols in Swift can be generic via abstract type members rather than parameterisation. Consequently, the protocol itself can no longer be used as a type but only as a generic constraint.

[…]

If you’re interested in the tradeoffs between type parameterisation and abstract type members, check out the discussion on the dev forums and the article on how the issue affects Scala.

Update (2016-06-06): Ole Begemann:

I recently came across this post by Kevin Ballard on Swift Evolution that includes the best explanation I have seen for why method dispatch in protocols works the way it does […] So essentially, while protocols have a virtual function table, protocol extensions do not, and cannot easily have one because a type adopting the protocol won’t necessarily know about all extensions at compile time and therefore cannot add the extension methods to its own vtable.

Update (2017-03-15): Jonah Williams:

We’ve seen that subclasses cannot reliably override protocol methods they inherit from their parent class when those methods have default implementations in a protocol extension. This causes confusing behavior where a subclass can implement protocol methods only to discover that they are never called from behavior inherited from a superclass. This can be a source of confusing bugs and identifying the root cause requires inspecting the behavior of all our parent classes. Something that can be especially difficult if we were to subclass a framework provided class.

Update (2019-03-06): objc.io:

Swift Quiz

[…]

What’s the output?

Update (2024-12-10): Drew McCormack:

Hot take: been knee deep in Swift protocol-oriented programming all week, and have concluded that Swift’s compile-time protocol overloading is a nightmare. It’s so easy to accidentally erase type and call the wrong variant of a function. If any step in your call chain is not fully overloaded, you are in trouble. It’s just way too easy to make a mistake, and to get it “right” you have to introduce functions that do nothing but propagate type. Sorry folks — it’s bad.

How and Why We Designed Lucida

Bigelow & Holmes (via Hacker News):

First, a big x-height makes the typeface appear perceptually bigger, aiding legibility when text is viewed at greater than average reading distances or at small sizes, or both. Text on monitors was read at distances 50% greater than on paper, according to ergonomic recommendations of the 1980s. Second, the big x-height provides more pixels for better definition of features in the x-height region, which typically carries more information than ascenders and descenders, thus helping distinguish letter shapes for better recognition.

[…]

Beyond these global adjustments, generous spacing also prevented some local problems when errors in rasterization and fitting make adjacent letters accidentally merge, as often happened with a popular grotesque sans-serif in early laser printers, when ‘r’ touched a following ’n’ and made a spurious ‘m’, turning words like “fern” into “fem”.

[…]

At low resolutions, these differentiating details can be obscured, so, we lowered the arch join, cutting more deeply into the shape than in normal grotesque sans-serifs. This also tended to increase the thickness of the arch, further distinguishing ’n’ from ‘o’.

[…]

When we designed the first Lucida fonts, we chose a slightly dark weight to compensate for erosion around the edges of black letters on white background screens and on write-white laser printers, which visually reduce weight, making text look weak in small sizes. The slightly dark weight made Lucida well adapted to most screen displays for almost 30 years, but printing on 300 dot-per-inch write-black laser printers had a slightly darker tone than we desired.

What Publishers Should Know About iOS 9

Marko Karppinen:

Ad blocking apps on iOS will not be able to perform heuristic analysis of web content to recognize and block ads, which is what most advanced desktop blockers do; instead, the blocker must prepare explicit rules for the URLs and page element names Safari should block. This system makes it easy to target common trackers, beacons and ad networks, but blocking first-party ad serving will be much more difficult.

We see this feature affecting the mobile publishing landscape in two ways. Most importantly, widespread web ad blocking clearly bolsters the case for native apps over web sites: publishers will remain in complete control over the way content and ads appear in their native apps.

[…]

On the App Store side, Newsstand makes way for a new App Store category called Magazines & Newspapers. It will be just like any other App Store section, with one benefit remaining exclusive to periodicals: publications will continue to be able to change their app descriptions and screenshots at will, not just when uploading a new version of their app. These updates will have to be made manually, though: the Atom feeds that enabled automatic updates of issue descriptions and cover images will no longer be supported.

And, speaking of issue cover images, they are gone from the App Store and the devices, just like the rest of the Newsstand feature.

[…]

Apple News also raises the bar for news reading experiences on the platform. Most current newspaper and magazine apps are simply not as nice to use as Apple News will be. This is something publishers will have to address if they wish to convert Apple News readers to paying regulars in their own apps. In iOS 9, after all, the button back to Apple News will beckon them on the status bar.

Dave Hamilton:

Content blockers in iOS 9 (or, indeed, every other platform that will eventually adopt them in a similar way) don’t mean the end of ads on the web or the end of your favorite publishers. They just mean the end of massive third-party aggregators that rely on complex browser-run scripts to serve ads en masse to thousands of different web sites daily. If a website wants to take a direct sponsorship (as we do here at TMO), iOS 9’s content blockers won’t stop you from seeing that. If a website wants to run its own scriptless ad server engine and serve simple ad images (as we used to here at TMO), nothing will stop you from seeing those. There’s no reason for content blockers to stop you from seeing those because they’re delivered just like the text or an image in an article — and you certainly wouldn’t want a content blocker to stop you from getting that.

Frankly, I’m pretty bullish on the concept of iOS 9’s Content Blockers, and am looking forward to their mass adoption. Yes, it means we’ll need to abandon some of the easy/remnant methods of earning money here, but most of those methods have become worth less and less to us — and become more and more annoying to you, our readers.

GasBuddy’s New Privacy Policy

GasBuddy (via Slashdot):

In addition, if you access the Service through the Internet, your browser may allow you to adjust your browser settings so that “do not track” requests are sent to the websites that you visit. However, GasBuddy will not disable tracking technology that may be active on the Service in response to any “do not track” requests that we receive from your browser.

How to Use -updateConstraints

Ole Begemann (tweet):

So should you use updateConstraints() as suggested in the documentation? In this year’s Mysteries of Auto Layout (Part 2) WWDC session, Apple gives different advice:

Really, all this is is a way for views to have a chance to make changes to constraints just in time for the next layout pass, but it’s often not actually needed.

All of your initial constraint setup should ideally happen inside Interface Builder. Or if you really find that you need to allocate your constraints programmatically, some place like viewDidLoad is much better. updateConstraints is really just for work that needs to be repeated periodically.

Also, it’s pretty straightforward to just change constraints when you find the need to do that; whereas, if you take that logic apart from the other code that’s related to it and you move it into a separate method that gets executed at a later time, your code becomes a lot harder to follow, so it will be harder for you to maintain, it will be a lot harder for other people to understand.

So when would you need to use updateConstraints? Well, it boils down to performance. If you find that just changing your constraints in place is too slow, then update constraints might be able to help you out. It turns out that changing a constraint inside updateConstraints is actually faster than changing a constraint at other times. The reason for that is because the engine is able to treat all the constraint changes that happen in this pass as a batch.

Sony A7R II Focus Accuracy

Lloyd Chambers:

The DSLR is looking like not just a dinosaur, but a lame dinosaur, given these advances. How long will CaNikon watch Sony advance without responding? The optical viewfinder is great for some things, but I say get rid of it—it is a huge liability for most things. Mirrorless is now the leading technology on the market, solving real issues for real photography.

The Sony A7R II makes outstanding images with low noise and excellent dynamic range at 42 megapixels that are always in focus. Notwithstanding some file quality limitations and disappointing 12-bit behavior in certain situations, nothing else can touch this track record of ultra-high hit rate.

Marco Arment:

With the combination of fast phase-detect autofocus across the majority of the sensor, subject tracking, face- and eye-detection, an image-stabilized sensor, auto-ISO with programmable minimum shutter speed, very low noise at high ISOs, and incredible dynamic range, I’m finally breaking my long-held habit of taking three or five nearly identical photos at each opportunity to ensure that one of them is sharp and usable.