Skip to the content.

Classic MVC and Reactive Programming, part 5

This time, we’re going to add a new complex business logic. We’re going to calculate sum of all values!

In the classic MVC version, we’ll add a new property named sum to the Model, and add a new ModelListener in the controller to update the view. Of course, you can update both views in one listener, but I wanted to demonstrate that a model can have multiple listeners.

class Model {
    ...

    get sum() {
        return this._values.reduce((sum, value) => sum + value, 0);
    }

    ...
}
class Controller {
    constructor(...) {
        ...

        model.addListener({
            updated(event: ModelEvent): void {
                $sum.innerText = event.model.sum.toString();
            }
        });

        ...
    }
}

The important thing is that it’s a Model that runs this business logic. You shouldn’t do this in the controller.

In the RxJS version, we’ll update values$ to have both values and sum of the values. Its type becomes Observable<[number[], number]> instead of Observable<number>.

const values$ = fromEvent($add, 'click')
    .pipe(
        map(() => $value.value),
        filter(value => value.length > 0),
        map(value => Number(value)),
        filter(value => !isNaN(value)),
        scan((values, value) => [...values, value], [] as number[]),
        mergeWith(loadedValues$),
        map((values): [number[], number] => [values, values.reduce((sum, value) => sum + value, 0)]),
        share({
            connector: () => new BehaviorSubject([[], 0]),
        })
    );

Then, subscribe to it to update views.

values$.subscribe(([values, _]) => {
    $view.innerText = values.join(', ');
});

values$.subscribe(([_, sum]) => {
    $sum.innerText = sum.toString();
});

Just like it was important to run the business logic in the Model, it’s important to make values$ run the business logic instead of running it in each Observer.

You can find the complete code at snakamura/mvc_rx.

As you can see, values$ itself behaves as a model. Then, what shall we do if we have more complex business logics? We’ll look at it in the next post.