Playful Features Kevin Bridges Applied Software Technologies - - PowerPoint PPT Presentation

playful features
SMART_READER_LITE
LIVE PREVIEW

Playful Features Kevin Bridges Applied Software Technologies - - PowerPoint PPT Presentation

Playful Features Kevin Bridges Applied Software Technologies kevin@wiiBridges.com @kevinast https://bit.ly/feature-u-pres slides, syllabus, articles, docs, and repo! Kevin Bridges Married, Father, Grandfather Applied Software


slide-1
SLIDE 1

Playful Features

Kevin Bridges Applied Software Technologies kevin@wiiBridges.com @kevinast https://bit.ly/feature-u-pres

slides, syllabus, articles, docs, and repo!

slide-2
SLIDE 2
  • Married, Father, Grandfather
  • 40 yrs in software (20 yrs consulting)
  • Retired
  • Be nice to the old guy :-)

Kevin Bridges Applied Software Technologies kevin@wiiBridges.com @kevinast

https://bit.ly/feature-u-pres

slides, syllabus, articles, docs, and repo!

slide-3
SLIDE 3

Playful Features

https://bit.ly/feature-u-pres

slides, syllabus, articles, docs, and repo!

Feature-Based Development that "Plugs and Plays"

slide-4
SLIDE 4

Sid ideBar: feature-u u docs

https://feature-u.js.org/

slide-5
SLIDE 5
slide-6
SLIDE 6

Goals

  • Requirements based
  • Encapsulation
  • Self Sufficient
  • Plug-and-Play

Hurdles

  • Isolation vs. Collaboration
  • Start-Up Initialization
  • Framework Configuration
  • UI Composition
  • Feature Enablement

In short, how do we achieve a running application from these isolated features?

slide-7
SLIDE 7

Two Primary Tenets needed to Achieve

  • ur

Goals

  • 1. Feature Runtime Consolidation
  • 2. Feature Collaboration
slide-8
SLIDE 8

1.

slide-9
SLIDE 9

2.

slide-10
SLIDE 10
slide-11
SLIDE 11

How is Cross Feature Communication achieved in a way that doesn't break encapsulation?

2.

slide-12
SLIDE 12

The feature-u Solution

slide-13
SLIDE 13

The feature-u Solution

Covered in this Session:

  • 1. Simplified App Startup
  • a. App-Specific Initialization in Features
  • b. Auto-Configuration of Frameworks
  • 2. Feature Enablement
  • 3. Cross-Feature Collaboration
  • a. Cross-Feature Sharing
  • b. Cross-Feature UI Composition
  • 4. A/B Feature Swap
  • 5. Plug-and-Play
slide-14
SLIDE 14

eatery-nod-w

https://github.com/KevinAst/eatery-nod-w

slide-15
SLIDE 15
  • 1. Simplified App Startup

I can start your app in 1,577 lines of code!

1

slide-16
SLIDE 16
  • 2. Plug-and-Play

Feature Enablement

slide-17
SLIDE 17
  • 3. A/B Swap

Mock Services

slide-18
SLIDE 18
slide-19
SLIDE 19
slide-20
SLIDE 20
slide-21
SLIDE 21
slide-22
SLIDE 22

How doe

  • es

feature-u ac accommodate:

  • 1. Feature

Runtime Consolidation

APP INITIALIZATION FRAMEWORK CONFIGURATION

slide-23
SLIDE 23

appWillStart({fassets, curRootAppElm}): rootAppElm|void

invoked early in the app startup process … supports accumulative static root DOM injection

appDidStart({fassets, [appState, dispatch]}): void

invoked immediately after app starts … triggers “app is running” processes

Feature Encapsulation

  • f

App Startup

appInit({showStatus, fassets, [appState, dispatch]}): promise|void

invoked later in the app startup process … supports blocking async initialization

  • 1. Feature Runtime Consolidation

Application Lif ife Cycle Hooks

slide-24
SLIDE 24
  • 1. Feature Runtime Consolidation

Ext xtendable Aspect Plu lugins

feature-u is extendable!

Framework Configuration Goal

slide-25
SLIDE 25
  • 1. Feature Runtime Consolidation

Ext xtendable Aspect Plu lugins

slide-26
SLIDE 26

1. . Feature Runtime Consolidation

eatery-nod-w

https://github.com/KevinAst/eatery-nod-w

slide-27
SLIDE 27

1. . Feature Runtime Consolidation

import React from 'react'; import Expo from 'expo'; import {LayoutAnimation} from 'react-native'; import {launchApp} from 'feature-u'; import {createReducerAspect} from 'feature-redux'; import {createLogicAspect} from 'feature-redux-logic'; import {createRouteAspect} from 'feature-router'; import features from './feature'; import SplashScreen from './util/comp/SplashScreen'; // launch our application, exposing the feature-u Fassets object // ... facilitating cross-feature-communication! export default launchApp({ aspects: appAspects(), features, registerRootAppElm(rootAppElm) { Expo.registerRootComponent(()=>rootAppElm); // convert rootAppElm to a React Component } }); // accumulate/configure the Aspect plugins matching our app's run-time stack function appAspects() { // define our framework run-time stack const reducerAspect = createReducerAspect(); const logicAspect = createLogicAspect(); const routeAspect = createRouteAspect(); const aspects = [ reducerAspect, // redux ... extending: Feature.reducer logicAspect, // redux-logic ... extending: Feature.logic routeAspect, // Feature Routes ... extending: Feature.route ]; // configure Aspects (as needed) // ... StateRouter fallback screen (when no routes are in effect) routeAspect.config.fallbackElm$ = <SplashScreen msg="I'm trying to think but it hurts!"/>; // beam me up Scotty :-) return aspects; }

src/app.js

src/ │ app.js ... our mainline - launches app via launchApp() │ ├──feature/ │ │ index.js ... accumulate/promote all app Feature objects │ │ │ ├──auth/ ... the app's authorization feature │ │ │ actions.js │ │ │ fassets.js │ │ │ feature.js ... expose aspects of interest to feature-u │ │ │ featureName.js │ │ │ index.js │ │ │ logic.js │ │ │ route.js │ │ │ signInFormMeta.js │ │ │ state.js │ │ └──comp/ │ │ SignInScreen.js │ │ SignInVerifyScreen.js │ │ │ ├──currentView/ ... more features │ │ │ ├──device/ ... feature to initialize the device │ │ │ actions.js │ │ │ api.js │ │ │ appDidStart.js │ │ │ appWillStart.js │ │ │ fassets.js │ │ │ feature.js ... expose aspects of interest to feature-u │ │ │ featureName.js │ │ │ index.js │ │ │ logic.js │ │ │ route.js │ │ │ state.js │ │ └──init/ │ │ platformSetup.android.js │ │ platformSetup.ios.js │ │ │ ├──discovery/ ... more features │ ├──eateries/ │ ├──firebase/ │ ├──leftNav/ │ ├──logActions/ │ └──sandbox/ │ └──util/ ... common utilities used across all features

directory structure

import React from 'react'; import platformSetup from './init/platformSetup'; import Notify from '../../util/notify'; /** * An app-level life-cycle hook, initializing our feature by: * - performing platform-specific setup (iOS/Android) * - inject our notify utility in the root DOM */ export default function appWillStart({fassets, curRootAppElm}) { // platform-specific setup (iOS/Android) platformSetup(); // initialize notify utility, by injecting it in our App root return [React.Children.toArray(curRootAppElm), <Notify key="Notify"/>]; } src/feature/device/appWillStart.js import {createFeature} from 'feature-u'; import initFireBase from './init/initFireBase'; /** * The **'firebase'** feature initializes the google firebase service, * and provides a placeholder for future API abstractions. */ export default createFeature({ name: 'firebase', appWillStart({fassets, curRootAppElm}) { initFireBase(); // initialize FireBase }, }); src/feature/firebase/feature.js

redux auto configured by feature-redux Aspect Plugin

import React from 'react'; import {Drawer} from 'native-base'; import SideBar, {registerDrawer, closeSideBar} from './comp/SideBar'; /** * Inject our Drawer/SideBar component at the root of our app */ export default function appWillStart({fassets, curRootAppElm}) { return ( <Drawer ref={ ref => registerDrawer(ref) } content={<SideBar/>}
  • nClose={closeSideBar}>
{curRootAppElm} </Drawer> ); } src/feature/leftNav/appWillStart.js export default launchApp({ aspects: appAspects(), features, registerRootAppElm(rootAppElm) { Expo.registerRootComponent(()=>rootAppElm); } });

src/app.js

import actions from './actions'; /** * An app-level life-cycle hook that dispatches our bootstrap action * that gets the ball rolling! */ export default function appDidStart({fassets, appState, dispatch}) { dispatch( actions.bootstrap() ); } src/feature/device/appDidStart.js

Feature Encapsulation

  • f

App Startup

  • App Initialization (Application Life Cycle Hooks)
  • Framework Configuration (Extendable Aspect Plugins)

Made possible because feature-u starts the app!

slide-28
SLIDE 28

feature-u so solu lutio ion

Feature Enablement

slide-29
SLIDE 29

Feature Enablement

export default createFeature({ name: 'sandbox’, enabled: inDevelopmentMode(), ... snip snip }); src/feature/sandbox/feature.js

  • by default all Features are active
  • can be disable via enabled Feature directive

Feature Enablement

Made possible because feature-u starts the app!

slide-30
SLIDE 30

How does fea eatu ture-u accommodate:

  • 2. Feature

Collaboration

Cross Feature Communication Feature Based UI Composition

slide-31
SLIDE 31
  • 2. Feature Collaboration

Cross Feature Communication fassets

  • fassets facilitate Cross Feature Communication
  • accommodates all Cross Feature Sharing
  • "Public Face" of a feature
  • Open
  • SideBar: fasset (not facet)

fassets – Feature Assets

slide-32
SLIDE 32
  • 2. Feature Collaboration

Cross Feature Communication fassets

Made possible because feature-u starts the app!

slide-33
SLIDE 33
  • 2. Feature Collaboration

Cross Feature Communication fassets

export default createFeature({ name: 'featureA', fassets: { define: { 'actions.openView': actions.view.open, // openView(viewName): Action 'sel.currentView': selector.currentView, // currentView(state): viewName 'sel.isDeviceReady': selector.isDeviceReady, // isDeviceReady(state): boolean }, }, ... }); defining fassets if (fassets.sel.isDeviceReady(appState)) { ... } using fassets

NOTE: This uses a push philosophy

code snippet ...

slide-34
SLIDE 34
  • 2. Feature Collaboration

Feature Based UI I Composition wit ithFassets()

export default createFeature({ name: 'common', fassets: { define: { 'company.logo': () => <img src="logo.png"/>, // a react component }, }, ... }); defining logo

code snippet ...

function MyComponent({Logo}) { return ( <div> <Logo/> </div> ... snip snip ); } export default withFassets({ component: MyComponent, mapFassetsToProps: { Logo: 'company.logo', } }); injecting fasset component properties

HoC Higher-order Components

slide-35
SLIDE 35
  • 2. Feature Collaboration

Feature Based UI I Composition useFassets() ()

export default createFeature({ name: 'common', fassets: { define: { 'company.logo': () => <img src="logo.png"/>, // a react component }, }, ... });

defining logo

code snippet ...

function MyComponent({Logo}) { return ( <div> <Logo/> </div> ... snip snip ); } export default withFassets({ component: MyComponent, mapFassetsToProps: { Logo: 'company.logo', } });

injecting fasset component properties

export default function MyComponent() { const Logo = useFassets('company.logo'); return ( <div> <Logo/> </div> ... snip snip ); } useFassets()

feature-u V2 supports React Hooks

slide-36
SLIDE 36
  • 2. Feature Collaboration

Feature Based UI I Composition Resource Contracts

  • Supported by additional fasset directives
  • fassets.use: specify a series of injection needs
  • fassets.defineUse: supply this content
  • Wildcards (*) provide additional dynamics
  • allowing content to be injected autonomously

UI Composition can be a "contract"

slide-37
SLIDE 37
  • 2. Feature Collaboration

Feature Based UI I Composition Resource Contracts

createFeature({ name: 'main', fassets: { use: [ 'MainPage.*.link', ], }, });

src/features/main/feature.js

code snippet ...

export default function MainPage() { const mainLinks = useFassets('MainPage.*.link'); return ( <div> {/* links section */} {mainLinks.map( (MainLink, indx) => <MainLink key={indx}/>)} </div> ); }

src/features/main/comp/MainPage.js

createFeature({ name: 'cart', fassets: { defineUse: { 'MainPage.cart.link': () => <Link to="/cart">Cart</Link>, }, }, });

src/features/cart/feature.js

createFeature({ name: 'search', fassets: { defineUse: { 'MainPage.search.link': () => <Link to="/search">Search</Link>, }, }, });

src/features/search/feature.js

We have switched to a pull philosophy with autonomous injection!!

  • 2. Feature Collaboration

Feature Based UI I Composition Resource Contracts

slide-38
SLIDE 38
  • 2. Feature Collaboration

UI Composition

Resource Contracts

eatery-nod-w

https://github.com/KevinAst/eatery-nod-w LeftNav menu

in baseUI feature

eatery screens discovery screens

slide-39
SLIDE 39

A/B Swap

change a feature to a new version

  • r swap out to a mock service
  • r turn on a new feature in it's entirety
slide-40
SLIDE 40

A/B /B Swap

Services tailor a generalized solution into an app-specific domain greatly simplifying business logic

Services

promoted by features

slide-41
SLIDE 41

A/B /B Swap

service-based features through

Usage Contracts

Services are promoted through Usage Contracts

  • authService is a required fasset (use)
  • that conforms to an abstract AuthServiceAPI
  • two implementations are provided (defineUse):
  • Real/Mock
  • both implement AuthServiceAPI
  • enablement is mutually exclusive

feature-u wires everything together

slide-42
SLIDE 42

In In Summary

slide-43
SLIDE 43

A fin final word about Feature-Based Development

Features should mirror requirements Features are a different abstraction

  • because they contain other programming paradigms
  • features are more about a “logical packaging”

so they plug-and-play

What does this mean in terms of feature-u?

Question: "How does feature-u impact my design constructs?" Answer: It doesn't!

feature-u is NON Intrusive!

  • you employ same constructs and styles
  • you use same frameworks in the same way
  • nly diff: your scope is smaller (i.e. a feature)

feature-u frees you up to focus your attention

  • n the "business end" of your features!
slide-44
SLIDE 44
slide-45
SLIDE 45

feature-u Benefits

slide-46
SLIDE 46

Kevin Bridges Applied Software Technologies kevin@wiiBridges.com @kevinast https://bit.ly/feature-u-pres

slides, syllabus, articles, docs, and repo!