Skip to content

Commit

Permalink
Merge pull request #24 from twittemb/improve/update-readme
Browse files Browse the repository at this point in the history
readme: updates
  • Loading branch information
twittemb authored Jan 24, 2021
2 parents 5d2c368 + 7159a2e commit 4a80aff
Showing 1 changed file with 13 additions and 13 deletions.
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ Here is the state machine described in the aforementioned System.
<img src="./Resources/state_machine.png" height="250" style="border-radius: 20px;"/>
</div>

On the one hand, defining transitions is about describing what is immutable in an application, what cannot change depending on external conditions, what is highly predictable and testable.
On the one hand, defining transitions is about describing what is immutable in an application, what cannot change depending on external conditions, and what is highly predictable and testable.

On the other hand, an application often needs to access data from the network or a database, which depends on conditions that are outside the System (filesystem, data availability, ...). Those side effects can be defined inside Feedbacks.

Expand All @@ -92,13 +92,13 @@ On the other hand, an application often needs to access data from the network or

In the "speaker volume example", at some point we need to access an external property: the targeted volume. It is external to the System because it is something variable that can be set and stored independently from the System. Its access has to be segregated inside a side effect.

A side effect is a function that reacts to an input state by producing on event that might trigger a transition. As a side effect can be asynchronous (fetching the network for instance), it should return a Publisher of events.
A side effect is a function that reacts to an input state by producing an event that might trigger a transition. As a side effect can be asynchronous (fetching the network for instance), it should return a Publisher of events.

In our example, one feedback takes care of increasing the volume and the other one is responsible for decreasing it. They both are executed everytime a new state is generated by a transition.
In our example, one feedback takes care of increasing the volume and the other is responsible for decreasing it. They are both executed everytime a new state is generated by a transition.

## Scheduling

Threading is very important to make a nice, responsive application. A Scheduler is the Combine way of handling threading by switching portions of reactive streams on dispatch queues, or operation queues or RunLoops.
Threading is very important to make a nice responsive application. A Scheduler is the Combine way of handling threading by switching portions of reactive streams on dispatch queues, or operation queues or RunLoops.

The declarative syntax of Feedbacks allows to alter the behavior of side effects by simply applying modifiers (like you would do with SwiftUI to change the frame for instance). Modifying the scheduling of a side effect is as simple as calling the `.execute(on:)` modifier.

Expand Down Expand Up @@ -234,7 +234,7 @@ Everytime the RefreshEvent is received, this transition will produce a LoadingSt

## The different ways of instantiating a Feedback

A Feedback is built from a side effect. A side effect is a function that takes a state as a parameter. There are two way to build a Feedback:
A Feedback is built from a side effect. A side effect is a function that takes a state as a parameter. There are two ways to build a Feedback:

```swift
Feedback(strategy: .continueOnNewState) { (state: State) in
Expand All @@ -244,7 +244,7 @@ Feedback(strategy: .continueOnNewState) { (state: State) in
}
```

This feedback will execute the side effect whatever the state is. It could be useful if you want to perform a side effect each time a new state is generated, no matter what is the type of State.
This feedback will execute the side effect for any type of state. It could be useful if you want to perform a side effect each time a new state is generated, regardless of the type of State.

```swift
Feedback(strategy: .continueOnNewState) { (state: LoadingState) in
Expand All @@ -257,7 +257,7 @@ This Feedback will execute the side effect only when it is of type LoadingState.

## Composing Transitions

The more complex a System is, the more transitions will have to be described. It is a good practice to split them into logical units:
The more complex a System, the more description required for the transitions. It's a good practice to split them into logical units:

```swift
let transitions = Transitions {
Expand Down Expand Up @@ -296,7 +296,7 @@ Systems should be self contained and limited to their business. We should pay at

There is a pattern for that in OOP: Mediator. A Mediator acts as a communication bus between independent components in order to garantee their decoupling.

Feedbacks comes eith two types of Mediator: `CurrentValueMediator` and `PassthroughMediator`. They are basically typealises on `CurrentValueSubject` and `PassthroughSubject`.
Feedbacks come with two types of Mediators: `CurrentValueMediator` and `PassthroughMediator`. They are basically typealises of `CurrentValueSubject` and `PassthroughSubject`.

To attach two Systems together:

Expand Down Expand Up @@ -336,17 +336,17 @@ systemA.attach(
)
```

When the systemA will encounter the state: `LoadedState`, the systemB will trigger a `LoadedEvent` event.
When systemA encounters the state `LoadedState`, systemB will trigger a `LoadedEvent` event.

# Using Feedbacks with SwiftUI and UIKit

Although a System can exist by itself without any visualization, it makes more sense in our developer world to use it as a way to produce a State that will be rendered on screen and to handle events emitted by the users.
Although a System can exist by itself without a view, it makes sense in our developer world to treat it as a way to produce a State that will be rendered on screen and expect events emitted by a user.

Fortunately, taking a State as an input for rendering and returning a stream of events from the user interactions looks A LOT like the definition of a side effect, we know how to handle them 😁, with a System of course. `UISystem` is a decoration of a traditionnal `System` dedicated to UI interactions.
Fortunately, taking a State as an input for rendering and returning a stream of events from user interactions looks A LOT like the definition of a side effect; and we know how to handle them 😁 -- with a System of course. `UISystem` is a decoration of a traditionnal `System` dedicated to UI interactions.

`UISystem` has some specificities:
`UISystem` has some specifics:

* it takes a function as a parameter to map a State to a View State, adapted to rendering
* it takes a function as a parameter to map a State to a View State adapted for rendering
* as it is an ObservableObject, it publishes a `View State` we can listen to in SwiftUI views or UIKit ViewControllers
* it ensures the `View State` is published on the main thread
* it offers an `emit(event:)` function to propagate user events in the System
Expand Down

0 comments on commit 4a80aff

Please sign in to comment.