> On Dec 25, 2015, at 12:02 AM, John McCall <rjmcc...@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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to