[swift-evolution] Proposal - Allow properties in Extensions

Paul Cantrell cantrell at pobox.com
Fri Jan 1 15:47:41 CST 2016


> On Dec 25, 2015, at 12:02 AM, John McCall <rjmccall at apple.com> wrote:
> 
>>>>>>>>> when you stuff a lot of functionality into a single class in most OO languages, there’s no real way to enforce its division into subsystems, because every method has direct access to every property and every other method.  In contrast, in Swift you can divide that class into distinct components with their own interface, state, and invariants, essentially making each component as good as its own type as far as encapsulation goes.
>>> …etc…
> 
> I feel like the strongest argument against allowing stored properties in extensions is the argument that it's poor design to have very complex types.  I have two responses to that; I apologize if this seems like straw-manning, because I know you haven’t raised this objection.
> 
> The first is that I’m always uncomfortable with abstract arguments against the complexity of other people’s code.
>> The second is that this is a valuable tool for incrementally reducing that complexity.

There’s a third good argument as well: it decouples API design from scoping of private state.

I find that readability at the point of API use often pulls against minimizing variable scope. A recent example: Siesta’s Resource class provides “latest best information” about the state of an HTTP resource, and lets you observe changes to that state. It’s nicest to work with the API when the same Resource class provides both of these things:

    activityIndicator.hidden = !resource.isLoading
    displayStuff(resource.latestData)
    
    resource.loadIfNeeded()

    resource.addObserver(self)

However, in the implementation, I would like to expose the set of observers only to the observer-related methods, i.e. the private observers property should be exposed to addObserver() but hidden from loadIfNeeded()).

Doing that using traditional methods gets ugly. I have to make a separate ResourceObservers type, and then … what? I can make it public, and force this API usage (which looks reasonable at first but rapidly gets awkward):

    resource.observers.add(self)

…or I can make the ResourceObservers type private and follow Demeter’s so-called law to its ugly conclusion, and have a bunch of forwarding methods on Resource.

Those API problems aside, I’m up a creek anyway: there’s _private_ state of Resource that both addObserver() and loadIfNeeded() need to see. Exposing that state to a separate ResourceObservers type is far messier than just letting the Resource class get a little bit bigger.

Some form of “properties in extensions” could help ease this problem, letting extension scope group methods with just the state they need, while still letting us design API based on what looks best from the outside.

This argument might even make the “extension properties” idea a little more compelling for structs.

Cheers,

Paul

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160101/5118dd73/attachment.html>


More information about the swift-evolution mailing list