feat(Store): add Store#receivePayload(payload: Payload) #160

Merged
merged 7 commits into from Apr 16, 2017

Conversation

Projects
None yet
1 participant
@azu
Member

azu commented Apr 16, 2017

We introduce a new API receivePayload(payload): void.
It provide write/update timing to Store.

Core concept of almin store is read-stack on CQRS.

Read-stack is usually consist of write-in-read and read-in-read.

Write in Read

write-in-read receive tha event(payload) from write-stack.
In the almin, UseCase(Write-stack) dispatch a payload.
When just time, Store receive the payload and update own state.
In other word, write stack update the view model in read stack.

Read in Read

read-in-read just return own state of the Store.
When View needed application states, StoreGroup call each Store#getState and merge it.
In other word, just return the view model in read stack.

Motivation of the change

We try to provide a Store implementation that is easy to understand.

Almin aim to resolve following issues:

    N: Command(write-stack)
    M: Query(read-stack)
  • Do two task by one model
    • Complexity is N × M
  • Do two task by two model
    • Complexity is N × M

Store#receivePayload is in read-stack, but update the state.
Is it in write-stak?

This antilogy is appeared in CQRS Journey
image

OrderViewModelGenerator in this picure, it is smilar with Store.
A Store is read-stack, but it is called from write-stack(UseCase).

Almin provide shorthand of read-stack as Store and StoreGroup.
Basally, we eventually realize correct read-stack.
But, correct read-stack includes unwanted things in client side architecutre.

The read repository is unwanted thing in read-stack.
Because, we permanently store the view model.
In other word, we use localStorage insteadof IndexedDB in the read-stack.

Conclusion

  • Store is a thing in read-stack
  • [Optional] Store will receive a payload and update own state.
  • Store return the state

azu added some commits Apr 14, 2017

feat(Store): add Store#receivePayload(payload: Payload)
We introduce a new API `receivePayload(payload): void`.
It provide write/update timing to Store.

Core concept of almin store is read-stack on CQRS.

Read-stack is usually consist of write-in-read and read-in-read.

write-in-read receive tha event(payload) from Write-stack.
In the almin, UseCase(Write-stack) dispatch a payload.
When just time, Store receive the payload and update own state.
In other word, write stack update the view model in read stack.

read-in-read just return own state of the Store.
When View needed application states, StoreGroup call each Store#getState and merge it.
In other word, just return the view model in read stack.
src/Store.ts
* You should be overwrite by Store subclass.
* Next, return state object of your store.
*/
- abstract getState<T>(prevState?: T, payload?: Payload): T;
+ abstract getState<T>(): T;

This comment has been minimized.

@azu

azu Apr 16, 2017

Member

Breaking Change: getState not require prevState

@azu

azu Apr 16, 2017

Member

Breaking Change: getState not require prevState

+ *
+ * You can update own state.
+ */
+ receivePayload?(payload: Payload): void;

This comment has been minimized.

@azu

azu Apr 16, 2017

Member

Add Store#receivePayload.
We want to make it more meaning name.

It is write phase in read-stack

@azu

azu Apr 16, 2017

Member

Add Store#receivePayload.
We want to make it more meaning name.

It is write phase in read-stack

src/UILayer/CQRSStoreGroup.ts
@@ -255,15 +144,15 @@ export class CQRSStoreGroup extends Store {
* // { a: "a value", b: "b value" }
* ```
*/
- constructor(stores: Array<Store> | StateStoreMapping) {
+ constructor(stores: StateStoreMapping) {

This comment has been minimized.

@azu

azu Apr 16, 2017

Member

CQRSStoreGroup only accept following syntax.
It make Store more simple.

class AStore extends Store {
    getState() {
        return "a value";
    }
}
class BStore extends Store {
    getState() {
        return "b value";
    }
}
const aStore = new AStore();
const bStore = new BStore();
const storeGroup = new CQRSStoreGroup({
    a: aStore, // stateName: store
    b: bStore
});
console.log(storeGroup.getState());
// { a: "a value", b: "b value" }
@azu

azu Apr 16, 2017

Member

CQRSStoreGroup only accept following syntax.
It make Store more simple.

class AStore extends Store {
    getState() {
        return "a value";
    }
}
class BStore extends Store {
    getState() {
        return "b value";
    }
}
const aStore = new AStore();
const bStore = new BStore();
const storeGroup = new CQRSStoreGroup({
    a: aStore, // stateName: store
    b: bStore
});
console.log(storeGroup.getState());
// { a: "a value", b: "b value" }
if (process.env.NODE_ENV !== "production") {
- assertStoreIsRegister(store, this._stateNameByStoreMap, this.isInitializedWithStateNameMap);
- assertStateShape(nextState, store, this._stateNameByStoreMap);

This comment has been minimized.

@azu

azu Apr 16, 2017

Member

the state of Store is any.
Should we strict this?

assert(the state is not undefined?)
@azu

azu Apr 16, 2017

Member

the state of Store is any.
Should we strict this?

assert(the state is not undefined?)
@azu

This comment has been minimized.

Show comment
Hide comment
@azu

azu Apr 16, 2017

Member

We can provide more easily implementation top the Store class:

// MIT © 2017 azu
import { Store, Payload } from "almin";
export interface State {
    reduce<T extends State>(payload: Payload): T |this;
}
export abstract class Reactor<T extends State> extends Store {
    abstract state: T;
    abstract reduce(prevState: T, payload: Payload): T;

    receivePayload(payload: Payload) {
        const newState = this.react(this.state, payload);
        if (this.shouldStateUpdate(this.state, newState)) {
            this.state = newState;
        }
    }

    getState() {
        return this.state;
    }
}
// The user implement this
class MyStore extends Reactor {
    reduce(prevState: T, payload: Payload): T;
}
Member

azu commented Apr 16, 2017

We can provide more easily implementation top the Store class:

// MIT © 2017 azu
import { Store, Payload } from "almin";
export interface State {
    reduce<T extends State>(payload: Payload): T |this;
}
export abstract class Reactor<T extends State> extends Store {
    abstract state: T;
    abstract reduce(prevState: T, payload: Payload): T;

    receivePayload(payload: Payload) {
        const newState = this.react(this.state, payload);
        if (this.shouldStateUpdate(this.state, newState)) {
            this.state = newState;
        }
    }

    getState() {
        return this.state;
    }
}
// The user implement this
class MyStore extends Reactor {
    reduce(prevState: T, payload: Payload): T;
}

@azu azu referenced this pull request Apr 16, 2017

Closed

Roadmap 0.12.0 #161

7 of 8 tasks complete
@azu

These should be fixed

test/CQRSStoreGroup-test.js
let isCalled = false;
// then
- storeGroup.onChange(() => {
+ storeGroup.onChange((s) => {

This comment has been minimized.

@azu

azu Apr 16, 2017

Member

s should be removed

@azu

azu Apr 16, 2017

Member

s should be removed

test/CQRSStoreGroup-test.js
@@ -633,4 +631,67 @@ describe("CQRSStoreGroup", function() {
assert(!isCalled);
});
});
+ describe("#receivePayload", () => {
+ it("should return getState -> receivePayload", () => {

This comment has been minimized.

@azu

azu Apr 16, 2017

Member

Make it meaningful...

@azu

azu Apr 16, 2017

Member

Make it meaningful...

azu added some commits Apr 16, 2017

src/UILayer/CQRSStoreGroup.ts
super();
- const stateNames = Array.isArray(stores) ? [] : Object.keys(stores);
+ const stateNames = Object.keys(stores);

This comment has been minimized.

@azu

azu Apr 16, 2017

Member

We should add validation to stores.

@azu

azu Apr 16, 2017

Member

We should add validation to stores.

azu added some commits Apr 16, 2017

@azu azu merged commit fe51765 into master Apr 16, 2017

2 checks passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
continuous-integration/travis-ci/push The Travis CI build passed
Details

@azu azu deleted the store-receive-payload branch Apr 16, 2017

@azu azu referenced this pull request May 11, 2017

Closed

docs: Make clear Store position #160 #186 #198

0 of 1 task complete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment