Feasgar Math!

Good afternoon!

I am thrilled to be here today.

My name is Cory and I am a senior web developer at Aumni.

and I am learning Scottish Gaelic. 😄

cory brown

why yes, we are hiring. thank you for asking

How to understand more by thinking less

or

5-ish best practices for managing complexity

Our subject

const getPageData = (endpoints, pageName, roles, featureFlags, done) => {
  fetch(endpoints.pageData[pageName])
    .then((response) => {
      if (response.ok) {
       response.json()
         .then((pageData) => {
           updateAppState(pageData)
           
           if (pageData.user.role === roles.admin) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = pageData.transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}

How to reduce complexity

  • Don't artificially entangle state
  • Pass only what is absolutely needed
  • Derive what can be derived
  • Push effects (error handling, fetching, etc) toward the edges
  • Dependency Injection

Don't artificially entangle state

const getPageData = (endpoints, pageName, roles, featureFlags, done) => {
  fetch(endpoints.pageData[pageName])
    .then((response) => {
      if (response.ok) {
       response.json()
         .then((pageData) => {
           updateAppState(pageData)
           
           if (pageData.user.role === roles.admin) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = pageData.transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        response.json()
          .then(errorMessage => {          
            globalErrorToast(`Oh noes! Couldn't get user.`)
            log(errorMessage)
            done(errorMessage)
          })
          .catch((error) => {      
            globalErrorToast(`Oh noes! Couldn't get user.`)
            log(error)
            done(error)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}

[My app] cannot be reconciled with the idea that [app state] should represent a reality in time and space, free from spooky action at a distance

~ Einstein the software developer

How not to artificially entangle state

combineReducers(userReducer, transactionsReducer)

...

dispatch({ type: 'user', paylaod: user })
dispatch({
  type: 'transactions',
  paylaod: transactions
})

combined reducers + dispatch

(props) => {
  const [user, setUser] = useState(null)
  const [
    transactions,
    setTransactions
  ] = useState(null)
  
  ...
  
  
}

distinct useState/Reducer calls

MyStore.getMyStuff()
MySore.on('change', handler)

YourStore.getYourStuff()
YourSore.on('change', handler)

separate data stores

How not to artificially entangle state

const getPageData = (endpoints, pageName, roles, featureFlags, done) => {
  fetch(endpoints.pageData[pageName])
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           
           if (pageData.user.role === roles.admin) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        response.json()
          .then(errorMessage => {          
            globalErrorToast(`Oh noes! Couldn't get user.`)
            log(errorMessage)
            done(errorMessage)
          })
          .catch((error) => {      
            globalErrorToast(`Oh noes! Couldn't get user.`)
            log(error)
            done(error)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}
const getPageData = (endpoints, pageName, roles, featureFlags, done) => {
  fetch(endpoints.pageData[pageName])
    .then((response) => {
      if (response.ok) {
       response.json()
         .then((pageData) => {
           updateAppState(pageData)
           
           if (pageData.user.role === roles.admin) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = pageData.transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        response.json()
          .then(errorMessage => {          
            globalErrorToast(`Oh noes! Couldn't get user.`)
            log(errorMessage)
            done(errorMessage)
          })
          .catch((error) => {      
            globalErrorToast(`Oh noes! Couldn't get user.`)
            log(error)
            done(error)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}

Pass only what is needed

const getPageData = (endpoints, pageName, roles, featureFlags, done) => {
  fetch(endpoints.pageData[pageName])
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           
           if (user.role === roles.admin) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}

Law of Demeter

(The principle of least knowledge)

A given object should assume as little as possible about the structure or properties of anything else (including its subcomponents).

Stuff goes in

Stuff comes out

?

Stuff goes in

Stuff comes out

Stuff goes in

Stuff comes out

?

global scope?

mutations?

Pass only what is needed

const getPageData = (endpoints, pageName, roles, featureFlags, done) => {
  fetch(endpoints.pageData[pageName])
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           
           if (user.role === roles.admin) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}
const hasError = (message: MESSAGE_TYPE): boolean => (
  message.status === UNKNOWN_ERROR ||
  message.status === UNKNOWN_STATUS ||
  message.status === ERROR
)
const hasError = (messageStatus: MESSAGE_STATUS_ENUM): boolean => (
  messageStatus === UNKNOWN_ERROR ||
  messageStatus === UNKNOWN_STATUS ||
  messageStatus === ERROR
)
const hasError = (messageStatus: MessageStatusEnum) =>
  [UNKNOWN_ERROR, UNKNOWN_STATUS, ERROR].includes(messageStatus)
const hasError = (message: MESSAGE_TYPE): boolean => (
  message.status === UNKNOWN_ERROR ||
  message.status === UNKNOWN_STATUS ||
  message.status === ERROR
)

Pass only what is needed

const getPageData = (endpoints, pageName, roles, featureFlags, done) => {
  fetch(endpoints.pageData[pageName])
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           
           if (user.role === roles.admin) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}
const getPageData = (pageDataEndpoints, adminRole, done) => {
  fetch(pageDataEndpoints[pageName])
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           
           if (user.role === adminRole) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           
           if (user.role === adminRole) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           
           if (isAdmin(user.role)) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           
           if (isAdmin(user)) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}

Pass only what is needed

const getPageData = (endpoints, pageName, roles, featureFlags, done) => {
  fetch(endpoints.pageData[pageName])
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           
           if (user.role === roles.admin) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           
           if (isAdmin(user.role)) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}

Derive what can be derived

To produce or obtain (a compound) from another substance

Derive what can be derived

What's a googol minus 1?

- my 7yr old

10^{100} - 1

😅

- Alexa

Derive what can be derived

What's a googol minus 1?

- my 7yr old

999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999

- the answer he was looking for

Derive what can be derived

const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           
           if (isAdmin(user.role)) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           
           if (isAdmin(user.role)) {
             setIsAdmin(true)
           }
           
           
           
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           
           
           
           
           
           
           
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}

Side Effects === complexity

A place for everything, and everything in its place

- Benjamin Franklin

Push effects toward the edge

\infty / 1

Pure.

Less pure.

Push effects toward the edge

const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}

Push effects toward the edge

Promise.resolve(
  Promise.resolve(
    Promise.resolve(
      Promise.resolve(
        Promise.resolve(
          Promise.resolve(5)
        )
      )
    )
  )
).then((val) => console.log(val))

// 5

Push effects toward the edge

const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}

Push effects toward the edge

const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => {
      if (response.ok) {
       response.json()
         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           done()
         })
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => response.ok ? response.json() : Promise.reject(response))


         .then(({ user, transactions }) => {
           updateUser(user)
           updateTransactions(transactions)
           done()
         })
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      .catch((error) => {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
        
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => response.ok ? response.json() : Promise.reject(response))
    .then(({ user, transactions }) => {
      updateUser(user)
      updateTransactions(transactions)
      done()
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't parse page data.`)
      log(error)
      done(error)
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get user.`)
      response.text()
      .then(errorMessage => {          
        log(errorMessage)
        done(errorMessage)
      })  
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
}

Push effects toward the edge

const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => response.ok ? response.json() : Promise.reject(response))
    .then(({ user, transactions }) => {
      updateUser(user)
      updateTransactions(transactions)
      done()
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't parse page data.`)
      log(error)
      done(error)
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get user.`)
      response.text()
      .then(errorMessage => {          
        log(errorMessage)
        done(errorMessage)
      })  
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => response.ok ? response.json() : Promise.reject(response))
    .then(({ user, transactions }) => {
      updateUser(user)
      updateTransactions(transactions)
      done()
    })
    
    
    
    
    
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get user.`)
      response.text()
      .then(errorMessage => {          
        log(errorMessage)
        done(errorMessage)
      })  
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => response.ok
      ? response.json()
      : Promise.reject(response.text()))
    .then(({ user, transactions }) => {
      updateUser(user)
      updateTransactions(transactions)
      done()
    })
    
    
    
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get user.`)
      response.text()
      .then(errorMessage => {          
        log(errorMessage)
        done(errorMessage)
      })  
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => response.ok
      ? response.json()
      : Promise.reject(response.text()))
    .then(({ user, transactions }) => {
      updateUser(user)
      updateTransactions(transactions)
      done()
    })
    
    
    
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get user.`)
      
      
        log(error)
        done(error)
      })  
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => response.ok
      ? response.json()
      : Promise.reject(response.text()))
    .then(({ user, transactions }) => {
      updateUser(user)
      updateTransactions(transactions)
      done()
    })
    
    
    
 
 
 
 
 
 
 
 
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => response.ok
      ? response.json()
      : Promise.reject(response.text()))
    .then(({ user, transactions }) => {
      updateUser(user)
      updateTransactions(transactions)
      done()
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
}

Before/After

const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => response.ok
      ? response.json()
      : Promise.reject(response.text()))
    .then(({ user, transactions }) => {
      updateUser(user)
      updateTransactions(transactions)
      done()
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
}
const getPageData = (endpoints, pageName, roles, featureFlags, done) => {
  fetch(endpoints.pageData[pageName])
    .then((response) => {
      if (response.ok) {
       response.json()
         .then((pageData) => {
           updateAppState(pageData)
           
           if (pageData.user.role === roles.admin) {
             setIsAdmin(true)
           }
           
           const transactionsPreview = pageData.transactions.slice(0, 3)
           setTransactionsPreview(transactionsPreview)
           done()
         .catch((error) => {
           globalErrorToast(`Oh noes! Couldn't parse page data.`)
           log(error)
           done(error)
         })
      } else {
        globalErrorToast(`Oh noes! Couldn't get user.`)
        response.text()
          .then(errorMessage => {          
            log(errorMessage)
            done(errorMessage)
          })
      }
    })
    .catch((error) => {
    	globalErrorToast(`Oh noes! Couldn't get page data.`)
        log(error)
        done(error)
    })
}

Dependency Injection

const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => response.ok
      ? response.json()
      : Promise.reject(response.text()))
    .then(({ user, transactions }) => {
      updateUser(user)
      updateTransactions(transactions)
      done()
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
}
const makeGetPageData = ({
  fetch,
  updateUser,
  updateTransactions,
  globalErrorToast,
  log
}) => (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => response.ok
      ? response.json()
      : Promise.reject(response.text()))
    .then(({ user, transactions }) => {
      updateUser(user)
      updateTransactions(transactions)
      done()
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
  }
}

Dependency Injection

const makeGetPageData = ({
  fetch,
  updateUser,
  updateTransactions,
  globalErrorToast,
  log
}) => (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => response.ok
      ? response.json()
      : Promise.reject(response.text()))
    .then(({ user, transactions }) => {
      updateUser(user)
      updateTransactions(transactions)
      done()
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
  }
}

Bonus: Prefer return values to callbacks

const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => response.ok
      ? response.json()
      : Promise.reject(response.text()))
    .then(({ user, transactions }) => {
      updateUser(user)
      updateTransactions(transactions)
      done()
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
}
const getPageData = (pageDataURI, done) => {
  fetch(pageDataURI)
    .then((response) => response.ok
      ? response.json()
      : Promise.reject(response.text()))
    .then(({ user, transactions }) => {
      updateUser(user)
      updateTransactions(transactions)
      done()
    })
    .catch((error) => {
      globalErrorToast(`Oh noes! Couldn't get page data.`)
      log(error)
      done(error)
    })
}
const getPageData = (pageDataURI) => fetch(pageDataURI)
  .then((response) => response.ok
    ? response.json()
    : Promise.reject(response.text()))
  .then(({ user, transactions, ...rest }) => {
    updateUser(user)
    updateTransactions(transactions)
    return { user, transactions, ...rest }
  })
  .catch((error) => {
    globalErrorToast(`Oh noes! Couldn't get page data.`)
    log(error)
  })

Super double bonus: tap

const tap = (fn) => (value) => {
  fn(value)
  return value
}

Super double bonus: tap

const getPageData = (pageDataURI) => fetch(pageDataURI)
  .then((response) => response.ok
    ? response.json()
    : Promise.reject(response.text()))
  .then(({ user, transactions, ...rest }) => {
    updateUser(user)
    updateTransactions(transactions)
    return { user, transactions, ...rest }
  })
  .catch((error) => {
    globalErrorToast(`Oh noes! Couldn't get page data.`)
    log(error)
  })
const getPageData = (pageDataURI) => fetch(pageDataURI)
  .then((response) => response.ok
    ? response.json()
    : Promise.reject(response.text()))
  .then(tap({ user, transactions }) => {
    updateUser(user)
    updateTransactions(transactions)
  })
  .catch((error) => {
    globalErrorToast(`Oh noes! Couldn't get page data.`)
    log(error)
  })

How to reduce complexity

  • Don't artificially entangle state
  • Pass only what is absolutely needed
  • Derive what can be derived
  • Push effects (error handling, fetching, etc) toward the edges
  • Dependency Injection
  • Prefer return values to callback
  • tap is cool

Are there any questions?

A bheil ceistean ann?

agus

thank you

Tapadh leibh

Beannach leibh uile

goodbye everyone

and