Skip to content
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

Overhaul and deprotocolize Network 🛰 #218

Merged
merged 9 commits into from
Sep 30, 2020

Conversation

p4checo
Copy link
Member

@p4checo p4checo commented Jun 1, 2020

Checklist

Motivation and Context

As it was, our NetworkStack and it's main conforming type URLSessionNetworkStack were not straightforward to use, mostly because of the many different Resource protocols and respective
associated types. All these Resource protocols, while being broken into simple, focused and composable units, created lots of complexity due to the generic constraints they impose.

While initially designed for allowing diverse NetworkStack's to be modeled, we have observed that most of the times users are simply interested in using a URLSessionNetworkStack.

The NetworkStore suffered from similar issues, by being tied to our huge Resource protocol family, while its main idea (and sole implementation) was a store that orchestrated both a network and persistence stacks.

Finally, PersistenceStack received a minor clean up and improvement to make it more flexible and powerful.

With all these things in mind, our Resource "family" was rethought to be composed of multiple witnesses, instead of multiple protocols. Witnesses provide the same abstraction of modeling behavior, without some of the limitations and complexities of protocols. By being generic
concrete types, they also allow creating default implementations via static properties and functions, making code reuse very simple.

The NetworkStack protocol was kept but greatly simplified and the NetworkStore protocol was discontinuated in favor of a StackOrchestratorStore, also simplified while making its purpose clearer.

Some concepts discussed on the amazing pointfree's videos were used, in particular protocol witnesses. Feel free to check this talk or their video series over at pointfree.co. 🤓🙏

Description

  • Deprecate all Resource protocols, and replace most relevant ones with witnesses:

    • Create new BaseRequestMaking witness to replace BaseRequestResource.

    • Create new ModelDecoding witness to replace DecodableResource.

    • Create new ErrorDecoding witness to replace ExternalErrorDecoderResource.

  • Deprecate RequestAuthenticator in favor of URLRequestAuthenticator, providing a simpler API.

  • Deprecate RequestInterceptor in favour of a more powerful URLSessionResourceInterceptor defined at a Resource level, allowing much more flexibility and control. Add default conformances to URLRequestAuthenticator, Network.URLSessionRetryPolicy.

  • Improve Retry infrastructure via new Retry.State, Retry.Action.CompareClosure and Retry.Action.mostPrioritary helper static function. Rename Retry.Policy.retries to maxRetries, Retry.Policy.Backoff.Truncation.retries to maxRetries and Retry.Policy.Backoff.Truncation.delay to maxDelay.

  • Improve HTTPResourceEndpoint:

    • Convert body property into a throwable function, to allow handling encoding errors.

    • Convert request computed property into a throwable function, to propagate body encoding errors.

  • Rename Network.URLSessionNetworkStack.Error to Network.URLSessionError and refine it by removing unnecessary URLResponse and using new Retry.State.

  • Update NetworkStack to require just a Resource and FetchError associated types, and add protocol extension to perform decoding after a network fetch.

  • Update Network playground with recent changes.

  • Improve PersistenceStack to have a new Key: Hashable associatedtype instead of the hardcoded Persistence.Key, and renamed existing Remote to Payload.

  • Deprecate NetworkStore in favor of StackOrchestratorStore, which requires a NetworkStack and `PersistenceStack associated types. Add a protocol extension to perform decoding after a fetch.

  • Create new StackOrchestrator namespace.

  • Rename NetworkPersistableStore to StackOrchestrator.Store, plus some internal adjustments.

  • Rename NetworkStorePerformanceMetricsTracker to StackOrchestratorPerformanceMetricsTracker.

  • Update podspec.

  • Add some new rule exceptions on .swiftlint.yml

@diogoeiras diogoeiras self-requested a review June 3, 2020 09:39
@beloso
Copy link
Collaborator

beloso commented Jun 4, 2020

I like these changes. It reduces complexity on the network stack implementation.
Thanks for this.

Copy link
Contributor

@ivopintodasilva ivopintodasilva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing work 💪
Thanks for the spring/summer cleaning on the network layer 🥇

Sources/Network/Network+BaseRequestMaking.swift Outdated Show resolved Hide resolved
Sources/StackOrchestrator/StackOrchestrator+Store.swift Outdated Show resolved Hide resolved
As it was, our `NetworkStack` and it's main conforming type
`URLSessionNetworkStack` were not straightforward to use, mostly
because of the many different `Resource` protocols and respective
associated types. All these `Resource` protocols, while being broken
into simple, focused and composable units, created lots of complexity
due to the generic constraints they impose.

While initially designed for allowing diverse `NetworkStack`'s to be
modeled, we have observed that most of the times users are simply
interested in using a `URLSessionNetworkStack`.

The `NetworkStore` suffered from similar issues, by being tied to our
huge `Resource` protocol family, while its main idea (and sole
implementation) was a store that orchestrated both a network and
persistence stacks.

Finally, `PersistenceStack` received a minor clean up and improvement
to make it more flexible and powerful.

With all these things in mind, our `Resource` "family" was rethought
to be composed of multiple witnesses, instead of multiple protocols.
Witnesses provide the same abstraction of modeling behavior, without
some of the limitations and complexities of protocols. By being generic
concrete types, they also allow creating default implementations via
static properties and functions, making code reuse very simple.

The `NetworkStack` protocol was kept but greatly simplified and the
`NetworkStore` protocol was discontinuated in favor of a
`StackOrchestratorStore`, also simplified while making its purpose
clearer.

## Changes

- Deprecate all `Resource` protocols.

- Create new `BaseRequestMaking` witness to replace
`BaseRequestResource`.

- Create new `ModelDecoding` witness to replace `DecodableResource`.

- Create new `ErrorDecoding` witness to replace
`ExternalErrorDecoderResource`.

- Deprecate `RequestAuthenticator` in favor of
`URLRequestAuthenticator`, providing a simpler API.

- Deprecate `RequestInterceptor` in favour of a more powerful
`URLSessionResourceInterceptor` defined at a Resource level, allowing
much more flexibility and control. Add default conformances to
`URLRequestAuthenticator`, `Network.URLSessionRetryPolicy`.

- Improve `Retry` infrastructure:

  + Create new `Retry.State` to model the retry state of an arbitrary
operation, update `Policy.shouldRetry()` to use it.

  + Create `Retry.Action.CompareClosure` to compare actions.

  + Create `Retry.Action.mostPrioritary` helper static function, with
the default logic to pick the most prioritary action between two.

  + Rename `Retry.Policy.retries` to `maxRetries`.

  + Rename `Retry.Policy.Backoff.Truncation.retries` to `maxRetries`.

  + Rename `Retry.Policy.Backoff.Truncation.delay` to `maxDelay`.

- Improve `HTTPResourceEndpoint`:

  + Convert `body` property into a throwable function, to allow
handling enconding errors.

  + Convert `request` computed property into a throwable function, to
propagate body encoding errors.

- Rename `Network.URLSessionNetworkStack.Error` to
`Network.URLSessionError` and improve it:

  + Remove `URLResponse` associated value from `.url` and `.retry`

  + Use new `Retry.State`

- Update `NetworkStack` to require just a `Resource` and `FetchError`
associated types, and add protocol extension to perform decoding after a
network fetch.

- Update Network playground with recent changes.

- Improve `PersistenceStack` to have a new `Key: Hashable`
`associatedtype` instead of the hardcoded `Persistence.Key`, and
renamed existing `Remote` to `Payload`.

- Deprecate `NetworkStore` in favor of `StackOrchestratorStore`, which
requires a `NetworkStack` and `PersistenceStack associated types. Add a
protocol extension to perform decoding after a fetch.

- Create new `StackOrchestrator` namespace.

- Rename `NetworkPersistableStore` to `StackOrchestrator.Store`, plus
some internal adjustments.

- Rename `NetworkStorePerformanceMetricsTracker` to
`StackOrchestratorPerformanceMetricsTracker`.

- Update `podspec`.

- Add some new rule exceptions on `.swiftlint.yml`
- Remove `Network.URLSessionNetworkStack.Configuration`

- Create `FetchAndDecodeError`.

- Move `ModelDecoding` out of `Network` namespace.

- Improve default decoding witnesses helpers.
@p4checo p4checo force-pushed the feature/overhaul-and-deprotocolize-network branch from 3d0856a to fecb2ea Compare September 18, 2020 13:54
@p4checo p4checo marked this pull request as ready for review September 18, 2020 14:01
@codecov
Copy link

codecov bot commented Sep 18, 2020

Codecov Report

Merging #218 into master will increase coverage by 0.12%.
The diff coverage is 97.49%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #218      +/-   ##
==========================================
+ Coverage   94.81%   94.94%   +0.12%     
==========================================
  Files         100      102       +2     
  Lines        3243     3345     +102     
==========================================
+ Hits         3075     3176     +101     
- Misses        168      169       +1     
Impacted Files Coverage Δ
...urces/Persistence/DiskMemoryPersistenceStack.swift 88.09% <ø> (ø)
...r/StackOrchestratorPerformanceMetricsTracker.swift 91.66% <91.66%> (ø)
...ces/StackOrchestrator/StackOrchestratorStore.swift 91.89% <91.89%> (ø)
...urces/Network/Network+URLSessionNetworkStack.swift 96.15% <96.15%> (ø)
Sources/Network/Network+URLSessionResource.swift 97.61% <97.61%> (ø)
...es/StackOrchestrator/StackOrchestrator+Store.swift 98.64% <98.64%> (ø)
Sources/Network/HTTPResourceEndpoint.swift 80.00% <100.00%> (ø)
Sources/Network/Network+BaseRequestMaking.swift 100.00% <100.00%> (ø)
Sources/Network/Network+ErrorDecoding.swift 100.00% <100.00%> (ø)
Sources/Network/Network+URLSessionError.swift 100.00% <100.00%> (ø)
... and 18 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 538f770...b016735. Read the comment docs.

Documentation/Network.md Outdated Show resolved Hide resolved
Sources/StackOrchestrator/StackOrchestrator+Store.swift Outdated Show resolved Hide resolved
Copy link
Collaborator

@filipe-lemos filipe-lemos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏 Great work! These changes should simplify the use of this lib. Left just some very minor comments

Documentation/Network.md Outdated Show resolved Hide resolved
Documentation/Network.md Outdated Show resolved Hide resolved
Documentation/Network.md Outdated Show resolved Hide resolved
Documentation/Network.md Outdated Show resolved Hide resolved
Documentation/Network.md Outdated Show resolved Hide resolved
Sources/Network/Network+URLSessionResource.swift Outdated Show resolved Hide resolved
@p4checo p4checo merged commit 812a8ab into master Sep 30, 2020
@p4checo p4checo deleted the feature/overhaul-and-deprotocolize-network branch September 30, 2020 13:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants