Best Practices

This section will highlight some feature-based best practices, including some single-source-of-truth principles.

Each of your feature implementations should strive to follow the single-source-of-truth principle. In doing this, a single line modification can propagate to many areas of your implementation.

This discussion is a guideline. It's up to you to implement these items because feature-u is not in control of this.

Our discussion will include the following items of interest:

Avoid Cross Feature Imports

A best practice is to treat each of your features as isolated implementations.

As a result, a given feature should never directly import resources from other features. This is tempting because typically the code is right there!

If one feature requires resources from other features, you should use the Cross Feature Communication mechanism, exposing a small set of characteristics as the Feature's Public API.

The reason for this is two fold:

  1. it is more controlled ... a feature can formally declare it's public interface points

  2. your features truly become plug-and-play

Feature Name

The featureName is a critical item that can be used throughout your feature implementation to promote a consistent feature identity.

A key aspect of the featureName is that feature-u guarantees it's uniqueness. As a result, it can be used to qualify the identity of several feature aspects. For example:

  • prefix action types with featureName, guaranteeing their uniqueness app-wide (see: feature-redux docs)

  • prefix logic module names with featureName, identifying where that module lives (see: feature-redux-logic docs)

  • depending on the context, the featureName can be used as the root of your feature state's shape (see: feature-redux docs)

While the featureName is part of the Feature object (emitted from createFeature(), there are race conditions where the Feature object will not be defined (during in-line code expansion).

As a result, a best practice is to expose the featureName as a constant, through a featureName.js mini-meta module that is "importable" in all use-cases (i.e. a single-source-of-truth).

src/feature/foo/featureName.js

/**
 * Expose our featureName through a mini-meta module that is
 * "importable" in all use-cases (a single-source-of-truth).
 */
export default 'foo';

Feature State Location

Because feature-u relies on slicedReducer() (in the feature-redux package), a best practice is to use the reducer's embellished selector to qualify your feature state root in all your selector definitions. As a result the slice definition is maintained in one spot.

Here is an example:

                             /** Our feature state root (a single-source-of-truth) */
const getFeatureState      = (appState) => reducer.getSlicedState(appState);

                             /** Is device ready to run app */
export const isDeviceReady = (appState) => getFeatureState(appState).status === 'READY';

... more selectors

For more information, please refer to the feature-redux docs.

results matching ""

    No results matching ""