<font size=2 face="sans-serif">Thanks Ben. This is really useful.</font>
<br>
<br><font size=2 face="sans-serif">Its probably worth also adding some
information on the approach taken by Foundation today for URLRequest/Response.
</font>
<br>
<br><font size=2 face="sans-serif">For outbound requests, Foundation provides
both NSURLRequest (class) and URLRequest (struct). In the case of URLRequest
(struct), there is a mix of types as it contains a getter that returns
a stream class for the body - and the with a number of warnings commented
in the code:</font>
<br><font size=2 face="sans-serif">&nbsp; &nbsp; &nbsp; &nbsp; <i>&quot;The
stream is returned for examination only; it is not safe for the caller
to manipulate the stream in any way&quot;</i></font>
<br><font size=2 face="sans-serif">(</font><a href="https://github.com/apple/swift-corelibs-foundation/blob/5ab46791996cb65079d02f98115cef6562d4819b/Foundation/URLRequest.swift#L187"><font size=2 color=blue face="sans-serif">https://github.com/apple/swift-corelibs-foundation/blob/5ab46791996cb65079d02f98115cef6562d4819b/Foundation/URLRequest.swift#L187</font></a><font size=2 face="sans-serif">)</font>
<br><font size=2 face="sans-serif">This is presumably because you shouldn't
need to modify the stream for an outbound request</font>
<br>
<br><font size=2 face="sans-serif">For responses from outbound requests,
only NSURLResponse (class) is provided as the body is read from the stream.</font>
<br>
<br><font size=2 face="sans-serif">This effectively give us a model where:</font>
<br><font size=2 face="sans-serif">&nbsp; &nbsp; &nbsp; &nbsp; outbound
&nbsp; &nbsp; &nbsp; &nbsp;can be a struct (you shouldn't need
to touch the stream)</font>
<br><font size=2 face="sans-serif">&nbsp; &nbsp; &nbsp; &nbsp; inbound
&nbsp; &nbsp; &nbsp; &nbsp;class (reading from stream)</font>
<br><font size=2 face="sans-serif">For the server case, we need the mirror
opposite of this - with incoming requests being a class and the outgoing
response potentially being a struct. </font>
<br>
<br><font size=2 face="sans-serif">This leads to two questions:</font>
<br><font size=2 face="sans-serif">1. Do we think the Foundation model
is correct?</font>
<br><font size=2 face="sans-serif">2. Do we think it would be confusing
to switch been classes and structs when working with inbound vs. outbound
requests, or do we think it would enforce correct behaviour?</font>
<br>
<br><font size=2 face="sans-serif">Chris<br>
</font>
<br>
<br>
<br>
<br><font size=1 color=#5f5f5f face="sans-serif">From: &nbsp; &nbsp; &nbsp;
&nbsp;</font><font size=1 face="sans-serif">Ben Cohen via swift-server-dev
&lt;swift-server-dev@swift.org&gt;</font>
<br><font size=1 color=#5f5f5f face="sans-serif">To: &nbsp; &nbsp; &nbsp;
&nbsp;</font><font size=1 face="sans-serif">Dan Appel &lt;dan.appel00@gmail.com&gt;</font>
<br><font size=1 color=#5f5f5f face="sans-serif">Cc: &nbsp; &nbsp; &nbsp;
&nbsp;</font><font size=1 face="sans-serif">&quot;swift-server-dev@swift.org&quot;
&lt;swift-server-dev@swift.org&gt;</font>
<br><font size=1 color=#5f5f5f face="sans-serif">Date: &nbsp; &nbsp; &nbsp;
&nbsp;</font><font size=1 face="sans-serif">08/12/2016 02:04</font>
<br><font size=1 color=#5f5f5f face="sans-serif">Subject: &nbsp; &nbsp;
&nbsp; &nbsp;</font><font size=1 face="sans-serif">Re: [swift-server-dev]
[HTTP] Value vs Reference Types</font>
<br><font size=1 color=#5f5f5f face="sans-serif">Sent by: &nbsp; &nbsp;
&nbsp; &nbsp;</font><font size=1 face="sans-serif">swift-server-dev-bounces@swift.org</font>
<br>
<hr noshade>
<br>
<br>
<br><font size=3>Hi Dan,</font>
<br>
<br><font size=3>Thanks for spelling out these questions, I think they
are a great starting point for a discussion. A few comments inline.</font>
<br>
<br><font size=3>On Nov 23, 2016, at 1:19 PM, Dan Appel via swift-server-dev
&lt;</font><a href="mailto:swift-server-dev@swift.org"><font size=3 color=blue><u>swift-server-dev@swift.org</u></font></a><font size=3>&gt;
wrote:</font>
<br>
<br>
<br><font size=1 face="Helvetica">My own responses:</font>
<br>
<br>
<br><font size=1 face="Helvetica">&gt;1. Do we want to use concrete types
or protocols for Request/Response?</font>
<br>
<br>
<br><font size=1 face="Helvetica">When working on </font><a href="https://github.com/open-swift"><font size=1 color=blue face="Helvetica"><u>Open
Swift</u></font></a><font size=1 face="Helvetica">, this was a hot topic
since we believed that it would be unsafe to have a protocol that would
allow both value and reference types. </font>
<br>
<br><font size=3>Bear in mind that a protocol is more than just the methods
and types it declares – it is also its documentation. For example, a number
of protocols in the standard library state things like complexity requirements
in their documenting comments. The language has no way of enforcing these,
but your type does not truly “conform” to the protocol unless you adhere
to them. Value semantics are similar – you can document that it is invalid
to implement a protocol with reference semantics. So I don’t think this
is a blocker to wanting to use protocols.</font>
<br>
<br><font size=1 face="Helvetica">We arrived upon the `{Request|Response}Representable`
pattern which worked but was a bit of a mess. Because of this, I would
prefer concrete Request/Response types.</font>
<br>
<br>
<br><font size=3>You could think of there as being 3 purposes to using
protocols here, roughly in order of importance:</font>
<br>
<ul>
<li><font size=3>being able to write generic code</font>
<li><font size=3>allowing different frameworks to interoperate</font>
<li><font size=3>documenting what you need to implement</font></ul>
<br><font size=3>The first one is the only reason why a protocol must be
included in a library, and the key question to ask when considering defining
a protocol like this is “What common algorithms do you want to write across
multiple different conforming types in your program”? &nbsp;(such as generic
functions, including protocol extensions, or functions that take an existential
if the protocol has no associated types).</font>
<br>
<br><font size=3>This is distinct from wanting to be able to be able to
choose from different library implementations of Request. You might want
to choose between the Acme Inc Web Framework’s Request type, or some Swift-Server
“official&quot; Request type, but you never need to use both at once and
write code spanning them. You just want to make sure that one can serve
as a source-compatible “drop-in” replacement for the other in your code.
This doesn’t mean you can’t write your own extensions – but you would
extend the concrete Request not a RequestRepresentable protocol.</font>
<br>
<br><font size=3>Next, it’s possible that there might be a collection
of 3rd-party frameworks out there that don’t define Request, but want
to be able to write methods that take or extend multiple possible Request
implementations. This seems a bit unlikely in the case of these types,
more likely in other cases like networking, so it’s kind of a what-if
scenario where there are both multiple popular implementations of Request,
and various frameworks that want to interact with them. Anyone can add
a conformance to anything, so those frameworks can define a protocol of
their own with a subset of the functionality they need, and then just extend
the popular implementations to conform to it. If this gets really common,
at that point it might be worth creating an official protocol for everyone
to share – but this can be done later, doesn’t have to be done up-front.
</font>
<br>
<br><font size=3>Finally, if you do expect multiple implementations and
want people to be able to swap them in and out when they choose, the protocol
can serve to document what methods and properties you are expected to implement
to be “source compatible&quot;. This can be done in documentation instead,
the benefit of the protocol being it helps the library developer ensure
they’ve got all the signatures right etc. But this isn’t something you
expose to users, it’s something on the side to help implementors.</font>
<br>
<br><font size=3>Based on all the above, it seems like there isn’t a pressing
need for a protocol for these types right now and initial designs should
focus on a concrete implementation until one emerges, if only to avoid
premature generalization. Useful protocols tend to be discovered, rather
than designed, through a desire to share common operations on different
concrete types.</font>
<br>
<br><font size=1 face="Helvetica">&gt;2. If we use concrete types, do we
want value or reference semantics?</font>
<br>
<br>
<br><font size=1 face="Helvetica">What I think makes this easier is that
the &quot;big four&quot; have each taken a slightly different approach
that can be used as a reference.</font>
<br><a href=https://github.com/Zewo/Zewo/blob/master/Modules/HTTP/Sources/HTTP/Message/Request.swift#L3><font size=1 color=blue face="Helvetica"><u>Zewo</u></font></a><font size=1 face="Helvetica">
- struct, value semantics</font>
<br><a href=https://github.com/vapor/engine/blob/master/Sources/HTTP/Models/Request/Request.swift#L4><font size=1 color=blue face="Helvetica"><u>Vapor</u></font></a><font size=1 face="Helvetica">
- closed class, reference semantics</font>
<br><a href="https://github.com/IBM-Swift/Kitura/blob/master/Sources/Kitura/RouterRequest.swift#L26"><font size=1 color=blue face="Helvetica"><u>Kitura</u></font></a><font size=1 face="Helvetica">
- closed class + has-a pattern, reference semantics</font>
<br><a href="https://github.com/PerfectlySoft/Perfect-HTTP/blob/master/Sources/HTTPRequest.swift#L25"><font size=1 color=blue face="Helvetica"><u>Perfect</u></font></a><font size=1 face="Helvetica">
- class protocol, reference semantics</font>
<br>
<br><font size=1 face="Helvetica">Zewo is the outlier here, but I would
like to note as a contributor to Zewo that we have not ran into situations
where value semantics create an impassable roadblock. </font>
<br>
<br><font size=1 face="Helvetica">To me, it makes sense to pass them around
as values since they don't have any logic of their own. Requests/Responses
can't send themselves, they can only read and modified. It also gives me
as a user more safety to pass them around since I know that they won't
be modified implicitly.</font>
<br>
<br><font size=1 face="Helvetica">Take the following pseudo-code as an
example:</font>
<br>
<br><font size=1 face="Helvetica">HTTPServer.onRequest { request in</font>
<br><font size=1 face="Helvetica">&nbsp; &nbsp; print(request.sourceIp)</font>
<br><font size=1 face="Helvetica">&nbsp; &nbsp; HTTPClient.send(request)</font>
<br><font size=1 face="Helvetica">&nbsp; &nbsp; print(request.sourceIp)</font>
<br>
<br><font size=1 face="Helvetica">}</font>
<br>
<br><font size=1 face="Helvetica">With reference semantics, there is no
guarantee that sourceIp will be the same before and after sending off the
request. After all, it <i>could</i> make sense for the HTTPClient to modify
the sourceIp before sending off the request. This of course a contrived
example, but the point stands.</font>
<br>
<br>
<br><font size=3>Not contrived at all, this is a perfect illustration of
why reference semantics make it harder to reason about your code and identify
the cause of bugs.</font>
<br>
<br><font size=1 face="Helvetica">Anyway, I think it would be great if
we could have people talk about their own experiences.</font>
<br>
<br>
<br><font size=1 face="Helvetica">&gt;3. When is it more convenient to
have reference semantics?</font>
<br>
<br>
<br>
<br><font size=3>Convenience is a double-edged thing. Pointers with possibly-null
values, or integer indexes into Unicode strings, are often considered convenient.
But that convenience comes with a hidden cost to correctness – unexpected
nulls, accidentally indexing into the middle of a grapheme cluster etc.
When making a proper effort to handle these things correctly, code quickly
becomes less convenient, and less readable, compared to the alternatives.</font>
<br>
<br><font size=3>It’s generally the style in Swift that correctness shouldn't
be sacrificed for convenience, but when things work out well, convenience
and ergonomics can be mutually reinforcing – the code is nice to use correctly,
awkward to use incorrectly. For example, optionals that force you to handle
nil help with correctness, but they have sugar like ?? or optional chaining
to handle common patterns clearly and idiomatically, ! as a shorthand for
asserting something is non-nil etc.</font>
<br>
<br><font size=1 face="Helvetica">In the middleware chain architecture
that we decided on in Zewo (the other ones have something similar), it
can be convenient to modify requests in the responder and have that reflect
in the middleware. I think this problem is best solved with `inout` parameters
rather than reference types, but that is my personal opinion.</font>
<br>
<br>
<br><font size=3>FWIW, this design view is also strongly held by those
of us working on the Swift Standard Library. I also brought this up with
several members of the Core Team and they also strongly felt that inout
and value types was the general approach we should take with such types
in Swift. The consensus there was that reference types really should be
mostly used when identity of the value is important.</font>
<br>
<br>
<br><font size=1 face="Helvetica">&gt;4. Are there problems that can't
be solved with value semantics?</font>
<br>
<br>
<br><font size=1 face="Helvetica">I haven't found any, but I'm sure others
can bring something interesting to the table.</font>
<br>
<br>
<br>
<br><font size=3>Shared mutable state is one. With an unavoidably-shared
resource, like a network connection or a handle to a window on a screen,
reference semantics are often what you want.</font>
<br>
<br>
<br><font size=1 face="Helvetica">On Wed, Nov 23, 2016 at 1:07 PM Dan Appel
&lt;</font><a href=mailto:dan.appel00@gmail.com><font size=1 color=blue face="Helvetica"><u>dan.appel00@gmail.com</u></font></a><font size=1 face="Helvetica">&gt;
wrote:</font>
<br><font size=2 face="Helvetica">Hello everyone!</font>
<br>
<br><font size=2 face="Helvetica">I was unable to make the kick-off meeting
for the HTTP sub-team, but I looked over the </font><a href="https://docs.google.com/document/d/1SWK0qBDi-9DeLJwHlcXcPU7h22JU-DWW8HTVuHbTQiw/edit" target=_blank><font size=2 color=blue face="Helvetica"><u>meeting
notes</u></font></a><font size=2 face="Helvetica"> and found some topics
that I think could use some more on-the-record discussion.</font>
<br>
<br><font size=2 face="Helvetica">A few questions that I wanted to raise:</font>
<br>
<br><font size=2 face="Helvetica">1. Do we want to use concrete types or
protocols for Request/Response?</font>
<br><font size=2 face="Helvetica">2. If we use concrete types, do we want
value or reference semantics?</font>
<br><font size=2 face="Helvetica">3. When is it more convenient to have
reference semantics?</font>
<br><font size=2 face="Helvetica">4. Are there problems that can't be solved
with value semantics?</font>
<br>
<br><font size=2 face="Helvetica">I would like to avoid bike-shedding,
and I think this can be done by providing real examples rather than just
talking about the pros and cons.</font>
<br><font size=1 face="Helvetica">-- </font>
<br><font size=1 face="Helvetica">Dan Appel</font>
<br><font size=1 face="Helvetica">-- </font>
<br><font size=1 face="Helvetica">Dan Appel</font>
<br><font size=1 face="Helvetica">_______________________________________________<br>
swift-server-dev mailing list</font><font size=1 color=blue face="Helvetica"><u><br>
</u></font><a href="mailto:swift-server-dev@swift.org"><font size=1 color=blue face="Helvetica"><u>swift-server-dev@swift.org</u></font></a><font size=1 color=blue face="Helvetica"><u><br>
</u></font><a href="https://lists.swift.org/mailman/listinfo/swift-server-dev"><font size=1 color=blue face="Helvetica"><u>https://lists.swift.org/mailman/listinfo/swift-server-dev</u></font></a>
<br><tt><font size=2>_______________________________________________<br>
swift-server-dev mailing list<br>
swift-server-dev@swift.org<br>
</font></tt><a href="https://lists.swift.org/mailman/listinfo/swift-server-dev"><tt><font size=2>https://lists.swift.org/mailman/listinfo/swift-server-dev</font></tt></a><tt><font size=2><br>
</font></tt>
<br>
<br><font size=2 face="sans-serif"><br>
Unless stated otherwise above:<br>
IBM United Kingdom Limited - Registered in England and Wales with number
741598. <br>
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6
3AU<br>
</font>