Bulletproof and Maintainable JS Applications

Scalable JavaScript applications that are easy to tests and maintain.

Speaker

Michał Załęcki, woumedia

Bulletproof and Maintainable JS Applications

13th July 2016

@MichalZalecki

What I'm going to talk about

What I'm not going to talk about

MVC

MVC

MVC-ish

MVC

MVC

MVVM

Flux

Flux

Flux

Redux

Redux

Redux

Redux: Root Reducer

Redux: Containers

Reducing side effects

Redux Saga

Redux Saga

Redux Saga

        
          export function* deliverShipmentSaga({ payload, meta: { token } }) {
            yield put(activateLoader());
            const { response, error } = yield call(api.deliverShipment, payload, token);
            if (response) {
              yield put(deliverShipmentSuccess(response));
              const toast = { content: "Shipment marked as delivered.", type: "success" };
              yield fork(addToastAndRemoveIn, toast, 3000);
            } else {
              yield put(deliverShipmentFailure(error));
              yield fork(handleError, "cannot mark shipment as delivered", error);
            }
            yield put(deactivateLoader());
          }
        
      

Reactive State

Reactive State

        
          import Rx from "rxjs";

          function createState(reducer$, initialState$ = Rx.Observable.of({})) {
            return initialState$
              .merge(reducer$)
              .scan((state, [scope, reducer]) =>
                ({ ...state, [scope]: reducer(state[scope]) }))
              .publishReplay(1)
              .refCount();
          }

          export default createState;
        
      

Reactive State: connect

        
          function connect(state$, selector = state => state) {
            return function wrapWithConnect(WrappedComponent) {
              return class Connect extends React.Component {
                componentWillMount() {
                  this.subscription = state$.map(selector).subscribe(::this.setState);
                }
                componentWillUnmount() {
                  this.subscription.unsubscribe();
                }
                render() { ... }
              };
            }
          }
        
      

Model-View-Intent

MVI

MVI

Use object mappers

mappet

        
          const schema = [
            ["firstName", "first_name", text => text.toUpperCase()],
            ["cardNumber", "card.number"],
          ];

          const mapper = mappet(schema);
          const source = { first_name: "Michal", age: 21, card: { number: "555..." } };
          const result = mapper(source);

          // {
          //   firstName: "MICHAL",
          //   cardNumber: "5555-5555-5555-4444"
          // }
        
      

Use TypeScript or Flow

Use ESLint

Build from modules

Name things correctly

Questions?