officehours/notes/bs.md

7.5 KiB
Raw Blame History

Note: "BS" stands for BrainStorming.

#Arivale Coding Problem

Problem description:

When clients sign up for the Arivale service, they develop a 1:1
relationship with a wellness coach over the course of a year. These
coaches help them interpret their personal health data as well as
make actionable recommendations to improve a clients overall
wellness. Clients need to schedule coaching calls on a monthly
basis. We want to create a web based experience that makes it easy
for clients to schedule a call. Clients should be able to see their
coachs availability and then book hour long coaching slot. Once a
slot is booked, other clients should not be able to book that slot
with the same coach.

Alternatives

Google Calendar offers an "office hours" appointment mechanism.  It
doesn't quite do what the problem requires; it's only available to
other members of the same school or corporate group account.

There's also a Django app, django-appointments, that probably does
most of what is asked of in this demo, but... I think I'd like to
take a crack at it with Flask (which I don't know), Psycopg2, and
doing most of the work (including a lot of the business logic) in
Postgres, just to see if I can.

What have other people done?

I wondered how other people solved the problem of constraint.
Google doesn't let you see more than a month at a time, but one of
its tasks is to assemble of view that may incorporate dozens of
underlying calendars.  On the other hand, assuming one person had
every half-hour booked with a unique task for a ten hour day, six
days a week without breaks, that's only 6240 individual items, well
within the performant range of a tool like Backbone or React.

Solution requirements:

* Data Store
* Middle Tier
* Front-End

Actors

* Staff
* Client

Tables

* Table of *Users* (flags "staff," "client," "staff_active," "client_active") [User]
  ** Is there redundant information in those flags?  Table-level
     constraints to prevent "client = false" "client_active = true"
     on the same object, for example?
* Table of *User/user relationships* [Staff_client_relationship]
  ** staff_user_id (constraint: staff flag must be TRUE, staff_active flag must be TRUE)
  ** client_user_id (constraint: user flag must be TRUE, user_active flag must be TRUE)

* Table of OfficeHours
  ** When the staff are available:
     *** staff_id
     *** availability: [(timestamp, timestamp)] defining TSRange: Availability

* Table of *Appointments*
  ** staff_client_relationship_id: ID
  ** reservation: (timestamp, timestamp) defining TSRANGE: Reservation

* Business rules -> rule values
  ** This could get ugly.  What are the limits?  One rule table per
     rule datatype?  Does Postgres have a union type, and how
     horrible is it to work with?

Accesses

* Client
  ** Retrieve: View upcoming appointments
  ** Create: Create a new appointment
  ** Update: Move an existing appointment
  ** Delete: Delete an existing appointment
  ** UNANSWERED QUESTIONS
      *** Recurring appointments?  Set/no set?  How do others handle this?

REST Documents:
    Appointment request: user, staff, time range
        * payload schema check
            User present and active?
            Staff present and active?
            Relationship present? (note: Never publish staff or relationship ID; user a slug for the customer if possible)
            Time range sane?
                * Positive length?
                  ** Assertion
                * Not in the past?
                  ** Assertion (review: "What programmers believe about time")
                  ** No, really: Timezones, Daylight Savings, all that jazz
                * Legitimate length
                  ** Business Rule
                * Not too far in the future?
                  ** Business Rule
                  ** Can the business rules be stored in the database?
                  ** If so, you'll need an admin page for them.
                * Assume attack:
                  ** Handle true fuzz.
                  ** Handle corruptions.
                  ** Handle crap.
                  ** WHITELIST RULES ONLY
            Time range available?
              ** OFFICE HOURS - for Coach only.
              ** Database can handle (Postgres has a RANGE operator now)
              ** Questions about performance, but don't care at this
                 point; just throw more metal at it.
        * Can the INSERT detect user/staff/relationship validity?
        * Can the INSERT deal with (some of) the time issues?
        * What happens on INSERT failure?
            ** How to report?


    Update request:
        * All of the above, plus:
        ** Existing appointment?
        ** Add-then-delete as a transaction, OR Update? Read pros/cons

    Retrieve:
        * Is about permissions and ranges
          ** What the user sees is what the database allows them to see
        * No further back in the past than (Business Rule) weeks
        * If as OPA (i.e. JSON), retrieve a couple weeks in advance,
          with scaling lookahead;   Like you did for Spiral's data
          sources list; the scaling rate can be found in Python List
          implementation, I think.  Or fibonacci with a limiter.
        * 300ms or twiddle.
            ** The above is front-end stuff.
            ** No Bad Ideas.  :-)

    Delete:
       * Appoinment exist?
       * This user?
       
Other:
    Non-REST issue
        * Progressive Enhancement.  If it doesn't work in Lynx, it
          doesn't work.
            ** Some kind of second-page form for a time range?
        * ARIA/Section 508 coverage?

Unit tests: Create: An appointment is a USER wanting a RANGE Logged in? Good/bad user? Good/bad range? Good/bad placement?

Delete:
    Logged in?
    Yours?

Update:
    Same as create plus:
        Yours?

Retrieve:
    Only the user ID and the start of the week matter.
    Constraint: No past views.  Not too far in the future
    ** Business Rule again

Secondary considerations: A staff member has a M:1 relationship with clients, but clients have only a 1:1 with staff. Encoding that into the Users table would make sense, only the staff's field would be Null. While I want to enforce NO-NULL idiom as much as possible, the separate table for that relationship [1] could be overkill; [2] permits the development of a M:M relationship where a user could have more than one coach, time and money permitting, but [2a] (probably) YAGNI.

Backend: Postgres, naturally. Leveraged as far as humanely possible. It's been a few years, but I'm genuinely impressed with what it does.

Middle Tier: What's the lightest Python application server there is? Flask?

Front End: HAML/Less/A script I don't know (Like Clojure, Pure, or Type? Something fun and different!)

What we don't care about (thus far):

Logging in.
Session management.

TODO VirtualEnv TODO Flask TODO PsychoPG2 TODO Flask skeleton TODO Postgres Database TODO Postgres retrieval example TODO Postgres range example TODO Deliver home page TODO Deliver retreivals


Quick thoughts:

Craft views or