-
-
Notifications
You must be signed in to change notification settings - Fork 7.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/swift result #2769
Feature/swift result #2769
Conversation
I thought this would be easy (ha), but I think it's revealed that some architectural/philosophical decisions need to be made by people closer to the project than I am. |
You'll need to merge master to fix the conflicts. (Fun!) If we can't namespace the extensions I would just get rid of them and use our |
I agree @jshier. I think we should remove public extensions on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really good overall. Certainly some things we'll probably need to work ourselves to get the extended APIs moved to internal or possibly eliminated. IMO we just need a rebase and then we can move it through. Then @jshier or I can work on getting things moved to be internal.
Ultimately I think we want to remove all extensions except those we use internally, those too if we can replace them with functionality from |
Add AFResult as a typealias to Result. Convert Result extensions to AFResult type. Update all code to use AFResult instead of Result.
… direction is to remove them. Add @testable to some unit tests that depend on functional extensions until they can be removed.
db8658b
to
5772d78
Compare
|
||
import Foundation | ||
|
||
public typealias AFResult<T> = Result<T, Error> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the Failure
case be changed to the more specific AFError
type?
I believe Alamofire always vends AFError
s currently masked behind Error
.
Which requires receivers to implicitly know that they should use the error.asAFError
extension to get the detailed error type.
The switch to explicitly specifying the Failure
case as AFError
would eliminate the need for the extension on Error
and the implicit knowledge of its existence
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really, no, as we don't convert underlying system errors to our error type in most situations. It would also require us to wrap all user errors as well, as we don't wrap things like serializer failures in our own error type either. And even if we did wrap everything in AFError
, the user would still need to extract the underlying associated error as an Error
and then cast to the type they need. So I'm not sure adding a layer of indirection through our error type would help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is something we do in our error system built on top of AF @jshier and it's actually super helpful. This way, you can easily categorize the error types you care about. We'd probably need to introduce something like .user
and .system
cases into AFError
that would wrap the underlying error. That would allow us to lock AFResult
to AFError
exclusively and would make it easier for clients, even though it makes it more difficult for us in AF.
Worth considering...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, thinking about it more, the doubly generic Result
does give us more flexibility here. I just need to think out all of the ramifications of encapsulating all errors.
I took a shot at namespacing the extensions under Commit d38c4e9 updates the Documentation to show how |
Ah sorry @ejensen, I should have posted here that I've been working on that as well. The current gameplan is to move all the APIs on The biggest question is whether we can to keep the |
Thanks for all the leg-work here @AtomicCat and @ejensen! I've pulled all these changes into #2774 while maintaining both of your attributions. Let's continue the discussion on that PR. I'm going to close this one out for now. |
For Review Only - See notes in Implementation Details
Issue Link 🔗
#2752
Goals ⚽
This PR removes the custom
Result<Value>
type and replaces it with a typealias to the new Swift 5 Result type:typealias AFResult<T> = Result<T, Error>
.The existing extensions on
Result
are also updated to work withAFResult
In addition, all internal references to
Result
have been replaced with references toAFResult
Implementation Details 🚧
The goal was to simply replace the existing
Result
type and retain the extended functionality as well; this would remove a now redundant type and keep the existing functionality that the code relied upon.However in the process of implementing the changes I've come to realize this may not be the best course of action.
Ideally the extensions on
AFResult
would be namespaced behind anaf
sub-struct as outlined in [Alamofire 5]: An Alamofire Namespace #2750. However, I was unable to come up with any Swift syntax that actually compiled as expected due to the generic nature ofResult
. Perhaps someone else will have better luck than I.In preserving the existing extensions which the Alamofire code depends on, there are impedance mismatches with the new Swift
Result
type. For example, both implementations have aflatMap
andflatMapError
functions, but the semantics and the signatures of the supplied closures differ. The AF implementations take a closure that yields theSuccess
orFailure
types and canthrow
, whereas the Swift variants yield a newResult
and cannot throw. There is existing code that relies on the old behaviors, so simplifying to the Swift versions is potentially non-trivial.A number of the existing
Result
extensions were explicit in the docstrings about returning an unmodifiedResult
(e.g.return self
), but it's not obvious why that was called out. I was unable to bridge the type mismatches with the new code and in many cases it now returns newAFResult
instance with the expected value.Given the lack of extension namespacing, it is unclear if publicly extending the Swift
Result
is a good idea. While, switching to aninternal
access level would allow the existing code to function as-is, it would break any client code relying on the old functionality.Testing Details 🔍
The unit tests for
AFResult
pass, though I have a lot of random failures on other unrelated tests. Themaster
branch also has a number of similar failures. The corporate network I'm on is pretty locked down, so that could be a factor.