Monday, September 04, 2017

NGRX Store and State Management 3

In previous articles I described the basic Store and Reducer layout of the pattern.

Reducers are the only way state is modified, and the modifications should be pure, meaning synchronous functions. Anything asynchronous should be handled elsewhere. Other desired side effects may be chaining of actions, where one action sets in motion a chain of changes and asynchronous calls.

The NGRX solution is Effects. These are essentially a subscription to the Action observable. Every action can be looked at, some side effect applied, and a new action mapped into the stream to be dispatched.

Here are the actions.

export const ARTICLES_LOAD = 'Load Articles';
export const ARTICLES = 'Article list';

export class ArticlesLoadAction: Action {
   type = ARTICLES_LOAD;
}

export class ArticlesAction: Action {
   type = ARTICLES;
   constructor(public payload: Articles[]) {}

export type Action 
   = ArticlesLoadAction
   | ArticlesAction;

The ARTICLES type action was handled in the articlesreducer, inserting the array of articles into the state. But the ARTICLES_LOAD action was not. It is a command action, and here is where Effects do their magic.

@Injectable()
export class ArticlesEffects {
   constructor(private actions$: Actions,
                      private http: Http
) {}

@Effect() loadarticles$ = this.actions$
   .ofType(ARTICLES_LOAD)
   .mergeMap(() => this.http.get(api)
      .map(response => response.json())
      .map(articlearray => new ArticlesAction(articlearray))
      .catch(err => Observable.of(new ErrorAction(err))
   );

Effects are an injectable service. Actions, the action observable stream is injected in the constructor, along with any services required. 

The effect is an observable chain, starting with ofType, which is similar to .filter. We are only interested in ARTICLES_LOAD. Multiple actions can be listed, 

.ofType(ARTICLES_LOAD, ARTICLES_RELOAD)

mergeMap calls a function that returns an observable, merging the results back into the actions$ stream. The response is mapped to an action with the array of articles as payload. The reducer is listening for this action, and the array will be inserted into the state.

Note the .catch is off the http.get observable? Effects in v2 of NGRX would complete if the .catch was off the actions$ observable. As well, if you .map the values off the http.get you can return a type that the actions$ observable likes.

If you want to dispatch multiple actions, replace the .map with
.mergeMap(data => [new Action1(data), new Action2(data)])

and each action will be merged into the stream for dispatch.

In some situations you may not want to dispatch a new action. 

@Effect({dispatch: false}) = ...

The possibilities are almost endless, and this is where much of the work of getting and posting data will occur.

To initialize the effects,

EffectsModule.forRoot([ArticlesEffects]),

in the import: [] section of the app.module.ts. It takes an array of injectable effect classes.



Sunday, September 03, 2017

NGRX Store and State Management 2

In the first post I described what application state is and how to use it in your components.

Here we will get into modifying the state.

If you remember, our application State looked like this.

export interface Article {
   author: string;
   title: string;
}

export interface ArticleState {

   articlelist: Article[];
}

export interface State {
    articles: ArticleState;
    auth: AuthState;
    preferences: PreferencesState;

}

And we defined the reducers.


export function articlesreducer(state: ArticleState = InitialArticleState, action: Action) {}

On startup of the application we want the State to be usable as is in components, otherwise we would need to jump through hoops to check the existence of properties etc. On initialization the reducers are called with an undefined state parameter, so we can pass it an initialization value, here called InitialArticleState.

export const InitialArticleState: ArticleState = {
   articlelist: []

};

The ngFor in our template can handle an empty array without error.

State is modified by dispatching an action. How you define your actions is how your application logic will be executed. Victor Savkin wrote a blog post describing the types of messages you will use in your application. As your application grows having an established pattern for naming your actions makes it much easier to use.

So what actions do we need for our articles? We need to get them from somewhere. So we need a command action. And the articles need to be inserted into the store by a document type action.

An Action looks like this.

export interface Action {
  type: string;
}

To define them.

export const ARTICLES_LOAD = 'Load Articles';
export const ARTICLES = 'Article list';

export class ArticlesLoadAction: Action {
   type = ARTICLES_LOAD;
}

export class ArticlesAction: Action {
   type = ARTICLES;
   constructor(public payload: Articles[]) {}

export type Action 
   = ArticlesLoadAction
   | ArticlesAction;

The Articles reducer function would respond to these actions.

export const articlesreducer(state: ArticleState = InitialArticleState, action: fromArticles.Action) {
   switch (action.type) {
      case ARTICLES:
         return Object.assign({}, state, {
               articles: action.payload;
            }
         });
      default: return state;
   }
}

The ARTICLES action is responded by assigning the articles property with the array of articles. Each reducer is called with every action, so return state as the default case or the state will disappear into undefined. I don't respond to ArticlesLoad here because the state isn't modified by that action. A loading indicator could watch for Load actions if desired.

How to dispatch an action? 

constructor(private store: Store<State>) {
    this.store.dispatch( new ArticlesLoadAction());
}

An important point. State should be immutable; don't modify the state slice, return a new instance. If you are working with items in an array, don't push or pop, return a new instance of the array with the changes.

Reducers are very easy to test. Pass it an object and a type, then see what it spits out.

How do we get the articles?
And how do we break up our state/reducers into modules?

NGRX Store and State Management

I have seen a couple of times experienced developers finding NGRX difficult to grasp. That was my experience as well. So I'll try to explain what it is about.

https://gitter.im/ngrx/platform

This is a great chat site for getting assistance. The angular/angular chat is active as well.

The best was to start is to lay out the problem that it solves. The Redux pattern implemented in NGRX is a way to maintain application state.

What is application state? All the data that the application requires to build and render the view over time.

Starting from the view, or Component level in Angular, here is how the data is presented by NGRX.

@Component({
   selector: 'article-view',
   template: `<div ngfor="let a of articlelist$ | async">
                  {{a.author}}{{a.title}}
              </div>`  
})
export class ArticleListView {
   articlelist$ = this.store.select(getArticles);

   constructor(private store: Store) {}
}

First you inject the store using the constructor.
Then you assign a value with a selector, in this example, getArticles.

Then in the template articlelist$, an observable is piped through async, returning an array, passed to ngFor which loops through each item and displays the author and title.

State is a list of articles each with a title and author.

export interface Article {
   author: string;
   title: string;
}

export interface ArticleState {
   articlelist: Article[];
}

Then define that application state

export interface State {
   articles: ArticleState;
}

You may hit the first objection to this pattern right here. All you have is a list of objects, why the excessive boilerplate? Believe me it will get worse. In fact for such a simple application, NGRX doesn't really make sense. But fill out this example into a full content display application with users, multiple data sources, complex content structures, multiple developers. Then the boilerplate, the very clear definition of everything in a way that is easy to read becomes very important. Embrace the Boilerplate!

Adding a second state slice will help illustrate the pattern.

export interface State {
    articles: ArticleState;
    auth: AuthState;
    preferences: PreferencesState;
}

Authentication and authorization, and a way to track preferences are added to the State. I won't define them here for brevity's sake, but it will help you understand the Store structure when it comes to initialization.

A basic rule of this pattern is that the state is changed in one way only, with a reducer function. The function that looks like this:

export function reducer(state, action) {}

It gets passed state and an action. Here are the reducer functions for the three state slices.

export function articlesreducer(state: ArticleState = InitialArticleState, action: Action) {}

export function authreducer(state: AuthState = InitialAuthState, action: Action) {}

export function preferencesreducer(state: PreferencesState = InitialPreferenceState, action: Action) {}

Here with types. As you can see, the articlesreducer doesn't get State as a parameter, but State.articles. How does that work? This is how you define your reducers.

export const reducers: ActionReducerMap<State> = {
   articles: articlesreducer,
   auth: authreducer,
   preferences: preferencesreducer
}

Then to initialize the state, in your app.module.ts file

imports: [
   StoreModule.forRoot(reducers),
]

The reducers object and the State interface properties match. When a reducer is called, the auth reducer is called with State.auth.

In the reducer function, if state is undefined it is assigned the value of the default. On initialization all reducers are called with an undefined state, initializing the state on startup.

What about that selector used in the component? Selectors are composed of a series of selectors that extract a specific property from the State.

export const getArticleState = (state: State) => state.articles;
export const getArticleList = (state: ArticleState) => state.articlelist;
export const getArticles = createSelector(getArticleState, getArticleList);

More boilerplate. Why not something like this?

export const getArticles = (state: State) => state.articles.articlelist;

Because every time any changes happen in State, the subscription in your component would fire.

This is one way of the two way data flows in the NGRX pattern. But it shows promise. A change in the state values will show up in the view. The data acquisition and handling is outside of the component. The Store structure is extensible, adding another state slice breaks nothing, making adding a feature to your app or component almost trivial.

How do you modify State? See here.
How do you break down the State into pieces that are modular?
How do you deal with api calls to get data from elsewhere? Here

For a suggestion on how to layout the files and folder structure, ngrx/example-app auth implementation


Thursday, July 27, 2017

NGRX pattern in a node server

I ran into the term CQRS twice in the last while. It means Command Query Responsibility Segregation

Essentially it means that the query, or getting data be segregated from the command, or posting data. It makes sense; the performance requirements for serving data is different from what is needed to write the data. Authentication requirements are very different as well. I suspect that many large scale implementations naturally have implemented this pattern, and an acronym formalises it.

I first read about the term in a Nestjs example. Nestjs is a server application framework using express, typescript, and a very nice dependency injection system. In an episode of Angular Air one of the guests mentioned Nestjs as a pick. My app has an Express backend, and I was getting horrified of the node callback mess without typescript, and was looking for a framework. It is quite impressive.

On another great podcast at NgHouston Brandon Roberts and Mike Ryan in response to a question whether Ngrx was useful on the server mentioned the CQRS pattern.

My dream would be to write the actions and reducers in Ngrx once and use the same code on the server. The action with payload would be the message passed between the client and the server. A Store subscription would serve the get requests, and effects would handle the post requests. The dependency injection system of Nestjs would make much of the initialization and structure of Ngrx portable.

And indeed that is the case. Getting a working store with selectors returning data, and effects posting the modifications was not that difficult.

https://github.com/derekkite/ngrx-nest is where the skeleton of the endeavor resides. Right now it isn't a working example, but more an illustration of how to do things. And there are things to fix.



NGRX Platform, redux

I have been using something similar undoables for an undo/redo function in my reducers. This implementation maintains the last array in memory, which would consume quite a few resources, so I rewrote it to keep the changed documents available for redo, and implemented effects to update the persistent storage. Worked fine in ngrx/store v2. And in ngrx/store v4 if I didn't use AOT. The feared ErrorError encountered resolving symbol values statically.

In my reducer definition I had code that looked like this:

export const reducers: ActionReducerMap = {
    connection: fromConnections.reducer,
    contactlist: undoable(fromContactList.reducer),
    contactemails: undoable(fromContactEmail.reducer),
    contactphones: undoable(fromContactPhone.reducer),
    contactwebsite: undoable(fromContactWebsite.reducer),
};

undoable gets a reducer as a parameter and returns it. AOT doesn't like it.

So there are two solutions.

You can provide the reducers.

export const REDUCER_TOKEN = new InjectionToken>('Registered Reducers');

export const reducerProvider = [
    { provide: REDUCER_TOKEN, useValue: reducers },
];

creates a token and provider, then in your module some magic.

// WORKAROUND HERE
Object.assign(REDUCER_TOKEN, reducers);
// WORKAROUND HERE

Then import the StoreModule

imports: [
        BrowserModule,
        CommonModule,
      ...
        StoreModule.forRoot(REDUCER_TOKEN),
],
providers: [
        reducerProvider,
]

The Object.assign hack is necessary, it won't work without it, at least in v 4.0.1.

The second way is to

export function undoableLayoutReducer(state: any, action: Action): fromLayout.State {
    return undoable(fromLayout.reducer)(state, action);
}

export const reducers: ActionReducerMap = {
    layout: undoableLayoutReducer,
};

which encapsulates the factory function in something that AOT likes. Right now this is required if you have a factory for your reducer in a feature store, as the forFeature doesn't as yet work with providers.




Saturday, July 22, 2017

Ngrx Platform

I've used ngrx/store and ngrx/effects for a while, and like the pattern. The new version has been released, and here are some of the changes I had to make in my code.

Pre v4 you built your reducers as follows, passing an object with

stateslice: reducerfunction.

const productionReducer = combineReducers(reducers);
export function reducers(state: any, action: any) {
    return productionReducer(state, action);}

With the new version, don't use combineReducers. I was running into the situation where the reducers weren't being initialized and the state was null.

Now you create your object of reducers:

export const reducer: ActionReducerMap = {
contactprimary: fromPrimary.reducer
contactselection: fromSelectionList.reducer
contactlist: undoable(fromContactList.reducer),
relations: relationUndoable(fromRelations.reducer),...

and in your app.module imports: [] section


StoreModule.forRoot(reducer),

The second big change is the Action type has been redefined.

export interface Action {
  type: string;
}

This breaks any of your code where you use action.payload. To fix it you have to define Action in each reducer. First define your action classes.

import {Action} from "@ngrx/store";
import {PrintItem} from "../../../models/print.model";


export const ADD_TO_QUEUE = '[Printing] Add to queue';
export const REMOVE_FROM_QUEUE = '[Printing] Remove from queue';
export const MARK_STATUS = '[Printing] mark status';

export class Print implements Action {
    type = ADD_TO_QUEUE;    
constructor(public payload: PrintItem) {}
}

export class PrintDone implements Action {
    type = REMOVE_FROM_QUEUE;    
constructor(public payload: PrintItem) {}
}

export class PrintStatus implements Action {
    type = MARK_STATUS;    
constructor(public payload: PrintItem) {}
}

export type Actions
    = Print
    | PrintStatus
    | PrintDone;


Note that the payload has a type in each one, and it is the same. You can call it whatever you like, or have multiple properties. The type Actions is exported.

Then in your reducer.

import {PrintState} from "../../../models/print.model";import {ActionReducer} from "@ngrx/store";import * as printingActionTypes from "../actions/printing.actions";

export type Action = printingActionTypes.Actions;
const initialState: PrintState = {
    queue: []
};
export const reducer: ActionReducer = (
    state = initialState, action: Action) => {
    switch (action.type) {
....


In this reducer, action is of the type defined in your action classes. The same action needs to be defined in the Effects as well.

This requires refactoring much of your reducers and effects. If you have different payloads for each of your defined action classes, lots of changes.

The advantage is strict typing of the data being passed around. It caught a couple minor flaws in my code, and I will be rewriting some reducers to take advantage of the added protection.

Otherwise it all works. The documentation is very helpful, especially with the specific initialization requirements.

I will update this blog after I have refactored the feature module reducers. There are also some improvements in the way selectors can be grouped.

Saturday, October 15, 2016

Angular 2 Things that Bite

Services.

Angular 2 services are classes that provide a service. They are an effective way of dealing with asynchronous data calls, for sharing data between components.

You set them up like this (using Typescript):

import {Injectable} from 'angular/core';

@Injectable()
export class MyService {
   
    public data : string;
    public getData() : string {
         return this.data;
   }

   public setData(newdata : string) {
        this.data = newdata;
   }

}

To use the service in your angular 2 app, you need to do two things.

1. Provide the service. This is where the service is instantiated and made available to the angular2 dependency injection system.

Each time you provide the service a new instance is created. Do you want one instance to exist? For example you may have an authentication service with a method isLoggedIn() that you check throughout your code. You want one instance, so you provide it once, only once. This is called a singleton.

You would provide this service in your app.module.

@NgModule({
  imports: [
    BrowserModule
  ],
  declarations: [
    AppComponent,
  ],
  providers: [
    MyService,
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }


And any time you want to use the service you need to inject it.
import {MyService} from './whereever/it/is';
@Component({
    selector: 'my-component',
    templateUrl: './my-component.html',
    providers: []    //   <=== if you put MyService here it creates a new instance!
})
export class MyComponent {
    constructor( private myservice: MyService) {
        ....
    }
}

You may have a service that is specific to a particular component, and each time this component is used you want a service to be created specifically for that component.

This example instantiates a new service instance each time the component is created.

import {MyService} from './whereever/it/is';
@Component({
    selector: 'my-component',
    templateUrl: './my-component.html',
    providers: [MyService]    //   <=== if you put MyService here it creates a new instance!
})
export class MyComponent {
    constructor( private myservice: MyService) {
        ....
    }
}

The Bite: The service is being initialized each time I use it. You are providing it more than once. It is working as designed.

https://angular.io/docs/ts/latest/guide/dependency-injection.html

Saturday, July 16, 2016

Herding Cats, or Managing Complexity

Determined to find a rational web based development environment, something stable, that works, has support and is flexible enough to deal with future demands, as well has minimal html involved, I ended up using Angular 2 on a Meteor base.

Yes it is alpha, now rc, not yet released. That hasn't caused many problems, as I'm early and still banging out the basic structure and development strategy.

A few things I've figured out.


  1. Javascript on browser has all the characteristics of multithreaded programming without the tools and api to deal with it. Once you get above a certain level of complexity it falls over a cliff, and your application can easily do the same. The frameworks such as Angular and React are an attempt, very good ones, at imposing order on the chaos. 
  2. Tracking down timing and essentially race conditions takes hours of time, time I don't have. Squiggly brackets nested deep are the devils work.
  3. Angular 2 is quite remarkable in it's power and simplicity. I have found that if I have something that requires figuring out some deep in the weeds function of the framework or platform, I'm making a mistake. Back out of the hole, and I find that there is a two line call that does exactly what I need. The paths are well trodden, almost all the issues I'm figuring out have been already, so learn the framework. There are bugs of course, and a few shortcomings, but each release candidate seems to sort a few of them out.
  4. ngrx/store and /effects is very interesting. It takes the ideas of Redux, adds Observables and ties it all to Angular 2. The idea of Redux, having the state defined and stored, changed by dispatching an event, having reducers which are pure functions to change the state, is brilliant in it's simplicity. It is similar to an event handler in gui application frameworks, but different. 
  5. It's power is in what it forces you as a developer to do. Start by defining any and all of the states your application will enter into. Each component will have different states, describing all the stages of fetching, waiting for, showing, editing the data. Each state gets set in a reducer function. This forces a level of simplicity, even the pure functions and the secondary effects get separated, again forcing you as the developer to break the process down into discrete steps that can be represented by a data structure containing the state. It seems repetitive; my mind is screaming at the almost identical functions, but keeping the simple structure makes it easier to find mistakes and bugs. And ngrx/store along with other redux implementations allow you to capture a step and return to it to sort out bugs.
  6. Observables are strange, confusing, wonderful and powerful. We tend to think of our applications as a point in time being represented on screen. Something happens, we react to it, getting to the state at another point in time. Observables describe a stream of data. The stream might have only one piece, or it may have many. My contact information for a customer streams forth from the data source, into an observable which is displayed. If there is a change from any source, the change flows the same way, showing the change on the display. That flow can be altered in many ways with the Observable methods. The flows go the other way as well; editing, keystrokes, selections, all the user input flows, is altered or used in some way leading to a change in some aspect of the state. 
  7. All this stacked up with discrete state reducers and observables exposing the state makes for traceable flows of events and data that can be debugged and fixed. One state of each component is when there is no data, gracefully handled it removes the source of lots of bugs. Each error state can be defined as well allowing for graceful failure.
I've set some parameters for the application. Everything is autosaved. It is a design parameter that in any and all situations the user could leave and come back without losing data and easily getting back to where they were. The well defined states are really helpful here. There are some instances where some distinct confirmation is required; an invoice posted, sending something. That is a different action from saving the state.

A second one is that data entry is a pain in the neck. Some of it needs doing, but it should be only for situations where the experience and thought of the user is required. Otherwise the idea is to present the user with decisions that need to be made, data that needs to be entered, and a place or slate where the experience and knowledge of the user gets applied.

A third one is to whenever possible have the data structured and entered in a way that doesn't require distinct fields. Sometimes it is necessary, but that should be determined by the data and it's use rather than the application structure. Something entered once with care and verified, then reused by selection or other methods reduces the scope for error. The characteristics of our business is that much of the time careful data entry is impossible or impractical, so the idea is to choose times or contexts where careful data entry is done, the rest of the time isn't necessary.

I'm enjoying Material design, which is in alpha development for Angular 2. It makes it trivial to construct nice looking and smooth operating applications, and it enforces a certain simplicity and elegance that makes an application useful.

Monday, December 28, 2015

Triggers

Why are almost all software projects structured around the data schema as opposed to the user and environment? This always ends up with the software defining your business as opposed to the business defining the software.

I run a service business, a small shop. We service a variety of commercial and residential customers. Refrigeration, air conditioning, heat pumps, air systems, etc. We deal with a number of client accounts payable and asset management systems. We have a variety of regulatory stuff, maintain some inventory, and turn over lots of jobs, usually having 20 balls in the air at the same time.

I'm maybe 80% there, but the complexity is staggering. I'll tell you what frustrates me about the software that we use.

The more capable it is the more it tries to tell me how to run the business.
The less capable it is the more difficult to set up specific requirements such as sales taxes and the like.
Mobile is terrible. It doesn't get used for good reason. My phone for data entry has a tiny screen by the time the keyboard is up.
I don't want modules, that is database centric. I want processes.
There is about 1/4 of an employee's time worth of housekeeping.
I know where I am, what I want, what data I need, it doesn't.
It is easier to build clutter, duplicate jobs, customers, invoices than searching.

A long time ago when I started in this business we had a notebook by the phone. Every call got a note; who, what about. That was the core of the business process; everything started there either in a conversation or voice message. This was before cell phones were accessible.

Why does service business software not start with that basic function?

I know why. Three reasons. There is someone answering calls and dispatching. It is difficult. The authors don't understand the business.

My goal is to put together an event based business process package that is configurable, knows where I and my technicians are, knows where the customers are, can nag us to do the things that really need to be done, can be set up by a smart business operator to gather data at the moment in time when it is easy and likely to be done.

I get a call from a customer. In time I show up at their site, am there for an hour or more. I make a call to one of my suppliers. Then leave. Next morning freight shows up, and the software asks me which parts are for that customer and job.

When I leave that site and am not moving (not driving), the phone pops something up asking if that was a job. Yes. Equipment worked on can be selected. A description entered. You phoned a supplier, did you order parts? Yes. Done.

The phone rings, another customer. We have a job in progress. One of my techs is close by. We converse and schedule something. I need to order something. No, in addition to the job in progress.

Another call, this time a drop everything emergency. I get to the site, do the repair. My phone beeps, deadline for ordering is 3pm, you have something to order. It remembers, and the next morning when there is a minute what can be entered. Phones come builtin with bar code reading capabilities. Three of these, two of those, yes one of each for both jobs.

I don't want to see a map, i know where I am. The next day, everyone has a log where they were, who they talked to. An email from a vendor with a pdf, estimate for which job? Click. I research some repair manual. Click, attached to this customer. You were at this location and you took photos. Yes, equipment. No time right now to enter details, but housekeeping knows and someone can clean it up when they have time.

Housekeeping. This email has a phone number in it, one that shows up in the log. Is that about this job? Yes, a contact is born with email, phone etc. All tied to a job.

Something old? Throw it out, a job was created based on a call but there was one already.

This is my day. Chaotic, manic, demanding and tiring. The software i use makes it moreso. 5 email accounts, multiple devices, a list a mile long to do every morning.

Some days it is quiet. Here is a list of stuff to clean up. Oops a call, drop everything and go. No problem, it will remind me again. Or a bunch of data entry stuff can be sent to someone else.

I want a solution. I am writing it.

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]