The art of explicit
User interfaces

Farzad Yousefzadeh

@FARZAD_YZ

@FARZAD_YZ

✈️   ENGINEER

💻   ENGINNER

Living in

🇫🇮

@

User interface is

Challenging

Command line

Direct manipulation ui

Why User Interface is hard?

Run on different platforms

Platforms are different

Partial standards

Styling challenges

SOurces of Data

Unpredictable consumers

Accessibility

internationalization

State management

Renderer         = View

(State)

Renderer         = View

(State)

Behavior?

Explicitness

Predictable

Explicit state

Renderer         = View

(State)

Explicit UI

Own mistakes in state management

IMplicit states

before fetching

after fetching

isFetching: true

Booleans don't inherent any meaning.

Jeremy Fairbank elm-conf 2017

Use booleans when you need both of the sides

Use multiple booleans when you need all of the permutations

type FetchingState =
  | BeforeFetching
  | Fetching
  | FetchedValidData
  | FetchedCorruptedData
  | FetchedError

Missing states

Error

Empty

First class edge cases

Conflicting states

type LayoutProps = {
  main?: boolean;
  header?: boolean;
  right?: boolean;
}
type LayoutProps = {
  main?: boolean;
  header?: boolean;
  right?: boolean;
}
<Layout main />
<Layout header />
<Layout right />

8

3

type LayoutType =
    | Main
    | Header
    | Right
<MainLayout />
<HeaderLayout />
<RightLayout />

optional

Boolean

type LayoutProps = {
  main?: boolean;
  header?: boolean;
  right?: boolean;
}
const layoutProps = {
  isMain: false,
  isHeader: false,
  isRight: false
}

Mutually Exclusive

Mutually exclusive props

Guards

Unnecessary tests

Uncertainty

Limited values

Complexity growth

Priority will matter

isLoading: boolean
2 ^ N
isMain: true;
isHeader: true;

derived states

const ArticleList = ({list}) => {
  return (
    {list.length === 0 ? <p>Empty list</p> : null}
  )
}

const Article = ({ article }) => (
  <div>
    {article.pictures.length ? (
      <>
        <Picture src={article.pictures[0].url} />
        <PictureCaption>{article.pictures[0].caption}</PictureCaption>
      </>
    ) : null}
  </div>
);
switch(event.type) {
  case "SET_CHECKING":
    return {
      ...state,
      checking: true,
      error: undefined
    }
  case "CHECK_SUCCESS":
    return {
      ...state,
      checking: false,
      status: event.payload
    }
  case "CHECK_FAILURE":
    return {
      ...state,
      checking: false,
      error: event.payload
    }
  default:
    return state;
}
{
  status: undefined,
  checking: false,
  error: undefined
}
type HealthCheckState
  =
  | Idle
  | Checking
  | Success status
  | Failure error
{
  status: undefined,
  checking: false,
  error: undefined
}

Grouping relevant data

Event Driven

I'm sorry that I long ago coined the term "objects" for this topic because it gets many people to focus on the lesser idea.

The big idea is "messaging"

Problematic
conventions

Event, Action

document.getElementById("button")
  .addEventListener("click", e => {
  // Run side effects
})
dispatch({ type: "authorize_session" });

function authorizeHandler(state) {
  if (state.session.isLoggedIn) {
    dispatch({ type: "session_authorized" });
  } else {
    if (isSessionValidForRefreshing(state.session.lastLoggedIn))
    {
      dispatch({ type: "retry_session" });
    } else {
      if (state.session !== undefined) {
        dispatch({ type: "session_logout" });
      }
    }
  }
}

High cyclomatic complexity

hard to detect and separate "similar states".

Event handlers

renderers

login()

logout()

checkout()

addToCart()

LoginView

LogoutView

CheckoutView

CartView

Separately modeled

As HUMANS...

FSM
& Statecharts

FSM(State + Event) => NextState + SideEffects

Purity vs Idempotence

Reducing logic

Finite state machines

Guarding vs Not Allowing

Event->Action

Event+State->Action

Travel To Past
vs
Travel to Past & Future

Idiomatic reducing logic

Idempotence

Treat UI as a whole entity

Still keep logic idempotent

+

FSM + Actor model

MAKE IMPOSSIBLE STATES IMPOSSIBLE

Making Impossible States Impossible by Richard Feldman

MAKE IRRELEVANT DATA UNAVAILABLE

DO NOT TEST SOMETHING THAT IS NOT SUPPOSED TO HAPPEN

TESTING IS GOOD.

IMPOSSIBLE IS JUST BETTER.

Making Impossible States Impossible by Richard Feldman

simple user interfaces are easy to construct, it is the complx ones that need to be designed.

Constructing the user interface with statecharts / Ian Harrocks

THANK YOU!

Farzad Yousefzadeh

@FARZAD_YZ