Skip to content
This repository has been archived by the owner on Oct 14, 2024. It is now read-only.

Feature/action linker #98

Merged
merged 15 commits into from
Jan 13, 2017
Merged

Feature/action linker #98

merged 15 commits into from
Jan 13, 2017

Conversation

cipolleschi
Copy link
Contributor

@cipolleschi cipolleschi commented Jan 12, 2017

Why
Add the ActionLinker to dispatch a set of Actions that depends on another one

Changes
The Store require a links: [ActionLinks] new parameter to be initialized.
I keep the compatibility with the convenience empty init.

Tasks

  • Add relevant tests, if needed
  • Add documentation, if needed
  • Update README, if needed
  • Ensure that all the examples (as well as the demo) work properly

@lucaquerella
Copy link
Contributor

I suggest you show a snippet of how to use the linker here.

@cipolleschi
Copy link
Contributor Author

You want it here in the PR?

Copy link
Contributor

@bolismauro bolismauro left a comment

Choose a reason for hiding this comment

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

Beside the feedback, I'd like to have a snippet of code of usage as @lucaquerella asked because I'm not 100% sure about the additional struct that holds the array of tuples.
I'm not saying is wrong, it is just to me to picture it

Moreover Travis reports errors with the MacOS tests, can you take a look?

All the conversion between Action.Type and String is handled internally,
to leverage the type checking system.
*/
let links: [String : [LinkeableAction.Type]]
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't it be private?

The ActionLinker is responsible to check if there are actions that must be issued after a source actionis dispatched.
For each of this actions, it checks if the conditions are met: if yes, they are dispatched.
*/
struct ActionLinker {
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be public

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't agree.
A user should not know that there is an ActionLinker.
The store init it, you just have to pass the links

Copy link
Contributor

Choose a reason for hiding this comment

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

Right I didn't see it

var tmpLinks: [String: [LinkeableAction.Type]] = [:]

/// Create the dictionary for a fast and efficient access to the actions.
for tuple in links {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you can use reduce here

- parameter oldState: state of the application before the source action is applied
- parameter newState: state of the application after the source action is applied
*/
func dispatchLinkedActions(_ dispatch: (Action) -> Void, forAction source: AnyAction, oldState: State, newState: State) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It should be public

moreover I think that

dispatchActions(for State:oldState:dispatch)

is a better name

You always have to think about the usage
so

linkedActions.dispatchActions(for newState, oldState: oldState, dispatch: self.dispatch)


/// Create the dictionary for a fast and efficient access to the actions.
for tuple in links {
let actionType = String(reflecting: tuple.source)
Copy link
Contributor

Choose a reason for hiding this comment

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

Since you use this in two places, I'd move it into a private method

func stringName(for action: Action) -> String

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought about it but it will change a line for a line so no code is saved... but i'll do that

Copy link
Contributor

Choose a reason for hiding this comment

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

It is not about saving lines of code. It is about avoid to update it somewhere and forget to update it in another place

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok, make sense.

func dispatchLinkedActions(_ dispatch: (Action) -> Void, forAction source: AnyAction, oldState: State, newState: State) {
let linkedActions = self.links[ String(reflecting:(type(of: source)))]

if let actions = linkedActions {
Copy link
Contributor

Choose a reason for hiding this comment

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

Use guard to avoid indentations

@@ -109,11 +112,12 @@ open class Store<StateType: State> {
- parameter dependencies: the dependencies to use in the actions side effects
- returns: An instance of store configured with the given properties
Copy link
Contributor

Choose a reason for hiding this comment

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

Update the documentation

self.dispatchFunction(action)

self.actionLinker.dispatchLinkedActions(self.dispatch, forAction: action, oldState: oldState, newState: self.state)
Copy link
Contributor

Choose a reason for hiding this comment

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

You should move this into performDispatch

func testCreationOneSourceActionOneLink() {
let actionLinker = ActionLinker(links: [ActionLinks(source: BaseAction.self, links: [LinkedAction1.self])])
XCTAssertEqual(actionLinker.links.count, 1)
XCTAssertEqual(actionLinker.links[String(reflecting:BaseAction.self)]!.count, 1)
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of String(reflecting) you should use the method provided by ActionLinker (which could be also static, btw).

You don't want to test how things are stored, but just that they are stored

}
}

struct LinkedAction4: LinkeableAction {
Copy link
Contributor

Choose a reason for hiding this comment

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

stub structs should be fileprivate

@bolismauro
Copy link
Contributor

@lucaquerella We have a AnyAction but I think we don't need it anymore.
When we are happy about this PR I think I will take a look to remove them.
I'm not changing the code right now to allow @cipolleschi to take care of the feedback

@lucaquerella
Copy link
Contributor

yes I meant here,
also: why isn't the actionliker a middleware?

@bolismauro @cipolleschi

@bolismauro
Copy link
Contributor

bolismauro commented Jan 12, 2017

It could be, yes. Maybe it is better since we don't add too many things to the store.
To be tested. it should be doable but I'm not 100% sure

let actionLinks: [ActionLinks] = ...
let middleware = LinkedActions.middleware(for: [actionLinks])

@cipolleschi
Copy link
Contributor Author

Yesterday, when we talked about it, we decided to avoid middlewares if possible to remove the possibilities to make black magic or mess up with the architecture... But maybe I'm missing something.

@bolismauro bolismauro changed the base branch from master to develop January 12, 2017 14:08
@bolismauro bolismauro merged commit dfc4768 into develop Jan 13, 2017
@bolismauro bolismauro deleted the feature/action-linker branch January 13, 2017 14:55
@bolismauro bolismauro mentioned this pull request Jan 13, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants