[swift-evolution] [Review] SE-0005 Better Translation of Objective-C APIs Into Swift

Radosław Pietruszewski radexpl at gmail.com
Tue Feb 2 16:00:53 CST 2016


>> Ah, interesting!
>> 
>> I definitely see the rationale for this. Calling a method like `tracks` seems a bit confusing, it doesn’t capture the intent at all. The ObjC-convention version, say, `tracksWithMediaType(…)`, though less clear, makes a better job at this.
>> 
>> I can see more methods of this kind in the diff, and they seem to benefit the most.
>> 
>> I mentioned this before, but the way I would prefer this named is `findTracks(…)`, and skip the “with” in the name. The intent is captured better than the original, we start with a verb, and the method name is separated from its parameters. But obviously this is unlikely to work as an automated translation.
>> 
>> Having said that, a lot of the changes seem like a step back:
>> 
>> 
>>>    func highlight(level val: CGFloat) -> NSColor?		   func highlight(level val: CGFloat) -> NSColor?
>>> -  func shadow(level val: CGFloat) -> NSColor?		+  func shadowWithLevel(val: CGFloat) -> NSColor?
>> 
>> Inconsistency. Highlight analyzed as as a verb, shadow as a noun, even though those are obviously related.
> 
> Yes, this is an inconsistency we would need to deal with via NS_SWIFT_NAME. “highlight” is acting as an adjective here, although it’s predominantly a verb in Cocoa APIs.

True, but it would seem preferable to me to choose an approach for which having to fix up a name with NS_SWIFT_NAME is a rare occurrence.

>> 
>>> -  func blendedColor(fraction fraction: CGFloat, of color: NSColor) -> NSColor?		+  func blendedColorWithFraction(fraction: CGFloat, of color: NSColor) -> NSColor?
>> 
>> This doesn’t seem like an improvement. “fraction” and “color” seem very much like parameters to be separated from the name.
> 
> Note that this is the intent of the change, however: blendedColor is a noun phrase describing the result, and “withFraction” is a characteristic of the resulting color.

I understand; I just find it a much less compelling example for Jordan’s approach than something like the previously mentioned “tracks”.

Perhaps the way to differentiate further cases where “with” in the name is useful is: methods that you can imagine being called “findFoo”, and take some argument as a search condition, but without it, only a single noun remains.

Looking through the diff, methods like these:

track(trackID trackID: CMPersistentTrackID) -> AVAssetTrack?
func tracks(mediaCharacteristic mediaCharacteristic: String) -> [AVFragmentedAssetTrack]
class func devices(mediaType mediaType: String!) -> [AnyObject]!
class func defaultDevice(mediaType mediaType: String!) -> AVCaptureDevice!
func connection(mediaType mediaType: String!) -> AVCaptureConnection!
func mutableTrack(compatibleWith track: AVAssetTrack) -> AVMutableCompositionTrack?	

Bother me the most. But a lot others, I feel like they’re worse off for having “with” back in the name

>>> -  class func availableColorSpaces(model model: NSColorSpaceModel) -> [NSColorSpace]		+  class func availableColorSpacesWith(model: NSColorSpaceModel) -> [NSColorSpace]
>>>  func indexOfItem(objectValue object: AnyObject) -> Int		+  func indexOfItemWithObjectValue(object: AnyObject) -> Int
>> 
>> Same…
> 
> With the same answer: both start with noun phrases describing the result, so the “with” is acting more like “having”, indicating that the parameter is describing the characteristics of the result.
> 
>> 
>> 
>>> -  func reviewUnsavedDocuments(alertTitle title: String?, cancellable: Bool, delegate: AnyObject?, didReviewAllSelector: Selector, contextInfo: UnsafeMutablePointer<Void>)		+  func reviewUnsavedDocumentsWithAlertTitle(title: String?, cancellable: Bool, delegate: AnyObject?, didReviewAllSelector: Selector, contextInfo: UnsafeMutablePointer<Void>)
>> 
>> This definitely seem like a step back, “reviewUnsavedDocuments” works really well as a name, without the sort of confusion that the “tracks” mentioned above has.
> 
> Somehow, “review” wasn’t in my list of verbs. I’ll fix this.

Another one:

func invalidateLayoutWith(context: NSCollectionViewLayoutInvalidationContext)
+  func swapWithMark(sender: AnyObject?)

> 
>>> -  class func mouseEvent(type type: NSEventType, location: Point, modifierFlags flags: NSEventModifierFlags, timestamp time: TimeInterval, windowNumber wNum: Int, context: NSGraphicsContext?, eventNumber eNum: Int, clickCount cNum: Int, pressure: Float) -> NSEvent?		
>>> +  class func mouseEventWith(type: NSEventType, location: Point, modifierFlags flags: NSEventModifierFlags, timestamp time: TimeInterval, windowNumber wNum: Int, context: NSGraphicsContext?, eventNumber eNum: Int, clickCount cNum: Int, pressure: Float) -> NSEvent?
>> 
>> This one’s weird. “With” was added, but without “type” in the name.
> 
> “type” is redundant with the type info, so it has been pruned.

But is “mouseEventWith” as a name actually desirable?

* * *

Another thing that bothers me is how this makes method families have different names:

> -  func indexOfItem(title aTitle: String) -> Int		+  func indexOfItemWithTitle(aTitle: String) -> Int
> -  func indexOfItem(tag aTag: Int) -> Int		+  func indexOfItemWithTag(aTag: Int) -> Int
> -  func indexOfItem(representedObject object: AnyObject) -> Int		+  func indexOfItemWithRepresentedObject(object: AnyObject) -> Int
> -  func indexOfItem(submenu submenu: NSMenu?) -> Int		+  func indexOfItemWithSubmenu(submenu: NSMenu?) -> Int
> -  func indexOfItem(target target: AnyObject?, andAction actionSelector: Selector) -> Int		+  func indexOfItemWithTarget(target: AnyObject?, andAction actionSelector: Selector) -> Int


I think it would be desirable for this, being essentially a few versions of the same method, just taking different arguments, to have a single name.

This also passes the “you could imagine the name starting with ‘find’” test.

* * *


>   func smartMagnify(event event: NSEvent)		+  func smartMagnifyWith(event: NSEvent)
>    @available(OSX 10.6, *)		   @available(OSX 10.6, *)
> -  func touchesBegan(event event: NSEvent)		+  func touchesBeganWith(event: NSEvent)
>    @available(OSX 10.6, *)		   @available(OSX 10.6, *)
> -  func touchesMoved(event event: NSEvent)		+  func touchesMovedWith(event: NSEvent)
>    @available(OSX 10.6, *)		   @available(OSX 10.6, *)
> -  func touchesEnded(event event: NSEvent)		+  func touchesEndedWith(event: NSEvent)
>    @available(OSX 10.6, *)		   @available(OSX 10.6, *)
> -  func touchesCancelled(event event: NSEvent)		+  func touchesCancelledWith(event: NSEvent)
>    @available(OSX 10.8, *)		   @available(OSX 10.8, *)
> -  func quickLook(event event: NSEvent)		+  func quickLookWith(event: NSEvent)
>    @available(OSX 10.10.3, *)		   @available(OSX 10.10.3, *)
> -  func pressureChange(event event: NSEvent)		+  func pressureChangeWith(event: NSEvent)

Not digging this either. Passing NSEvent here feels like passing “sender” — an idiom that seems in no need of adding a “With” suffix to the method name…


Best,
— Radek
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160202/5ae9b64d/attachment.html>


More information about the swift-evolution mailing list