Re: [heycam/webidl] Add an informative section on overloads vs. unions/optional (#307)

> They make APIs much harder to understand.

That really depends on the API.

For example, let's look at `AudioNode`.  It has this IDL at <https://webaudio.github.io/web-audio-api/#idl-def-AudioNode>:

    AudioNode connect (AudioNode destination, 
                                       optional unsigned long output = 0,
                                       optional unsigned long input = 0);
    void connect (AudioParam destination, optional unsigned long output = 0);

How would you write this without overloads?  Right now you have to do:

    any connect((AudioNode or AudioParam) destination, 
                          optional unsigned long output = 0,
                          optional unsigned long input = 0);

plus prose to explain:

1.  The third argument is ignored if the first argument is an AudioParam.
2.  The return value is an AudioNode if the first argument is an AudioNode and void otherwise.

Note that both would still be issues even if we could write `(AudioNode or void)` for the return type.

As a result, you have to go read the prose to figure out what sort of thing a call will return, etc.

Now you could make the argument that these two methods should have been called `connectNode` and `connectParam` or something.  But _if_ this was the desired API, then overloads actually express it more clearly than unions plus optional arguments would have.

Or another example, from <https://drafts.csswg.org/css-conditional-3/#the-css-interface>:

    partial interface CSS {
      static boolean supports(DOMString property, DOMString value);
      static boolean supports(DOMString conditionText);
    };

Yes, you could rewrite this as:

    partial interface CSS {
      static boolean supports(DOMString propertyOrConditionText, optional DOMString value)
    };

with prose explaining that the first arg is treated as condition text if there is no second arg, otherwise treated as a property name.  But the actual IDL is a bit more confusing this way, in my opinion.  Oh, and this would have different semantics in the case when `undefined` is passed as a second arg, which may or may not be an improvement on the current behavior; it's hard to tell.  Again, maybe these should have been different function names...

Or canvas:

    void drawImage(CanvasImageSource image, double dx, double dy);
    void drawImage(CanvasImageSource image, double dx, double dy, double dw, double dh);
    void drawImage(CanvasImageSource image, double sx, double sy, double sw, double sh, double dx, double dy, double dw, double dh);

Yes, you could do this with optionals and explicitly disallowing cases in which dw is passed but dh is not passed in the second overload.  Oh, and all the args named appropriately so they make sense for both the second and third overload.  So really, you want to disallow cases when the fourth arg is passed but no more args are passed.   Do you really think that would make the API easier to understand?  And also, also, it would still have different semantics from what we have now.

Or how about this one from `CanvasDrawPath`:

    void fill(optional CanvasWindingRule winding = "nonzero");
    void fill(Path2D path, optional CanvasWindingRule winding = "nonzero");

Try writing that with unions and then showing someone the result and asking them whether it's easier to understand than the overload version....

I stopped here; these were three of the first 5 overloads I looked at in Gecko's IDL.


-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/heycam/webidl/issues/307#issuecomment-279466973

Received on Monday, 13 February 2017 17:48:39 UTC