Synthesis : Scott Becker

Weekend Update 9/13/2020

This has been a rough week.

Fires – A rare weather event in Oregon combined dry conditions, heat, and very strong winds to become a perfect storm. This fueled explosive growth to wild fires brewing throughout the state, both natural and human caused. More than a million acres burned in a single week. More than double the previous record for the entire year. The fires grew shockingly fast. Conspiracy theories abound, but whatever the original cause of each of the fires, wind is why they grew so huge. The wind began to subside on Wednesday, allowing humanity to regain something resembling control over the situation. The fires caused immense devastation, took lives and livelihoods, and completely destroyed many smaller towns like Gates, Phoenix and Talent. It came within a half mile of Estacada and other larger towns very close to Portland and Salem. As of this moment, the march towards Oregon’s major population centers in the north west part of the state appears to have stopped, thanks to the milder weather. I’m really hoping for rain. If the forecast holds, we may get a bit as soon as Tuesday.

Bad Air Quality – After the fire came the smoke. Around Wednesday the air quality started getting bad, and by this weekend it was downright hazardous (AQI – Air Quality Index – readings of around 450-500 in Portland – current worst in the world). The visibility is low and the sky has been a grayish orange. This morning it was just gray and fog-like, but so thick we could barely see the house across the street.

Stuck Indoors – As of this moment on Sunday afternoon, because of the bad air, we’ve remained almost 100% indoors since Thursday, or 4 straight days. I’m anxiously awaiting a dip in the AQI readings so we can get out of the house. Some of our friends opted to drive to the coast today or book a hotel. We were tempted, but we are lucky to have two air purifiers in the house, and they’re running 24/7. I think staying here where we have all of our personal creature comforts is the best option for us right now.

It feels strange to write like this. These weekend review posts are usually much more mundane musings on my personal life, family, and work. This week we have been living through a literal firestorm.

We are some of the lucky ones – we are all alive and healthy. Our house, our neighborhood, and our city is still standing. For all of that I’m grateful, and I can live with being stuck inside for a bit. We’ll get through it.

Leave a comment

Weekend Update – 9/6/2020

Fall is coming. It’s not officially here yet; Tuesday September 22nd is the official start of Fall, but you can feel it and see it. It’s starting to feel a little cooler in the mornings and evenings, leaves are beginning to turn brown and fall off the trees, and the sun is setting a few minutes earlier each day. We even have pumpkins in our backyard this year, and they are getting bigger and more orange each day.

Father/Son Overnight – O went camping for one night with a couple of her girlfriends mid week, so A and I had a solo day. Nothing extreme, we just had fun hanging out in the neighborhood. I got Thai food delivered for dinner. A likes Pad See Ew noodles with tofu. Doordash is great for solo dad night. Then we went on one of our long solo bike/walks for the evening. The next morning we both biked together, to a part of the neighborhood school field we like to call “the canyon.” It’s sort of a dry drainage ditch that runs along one side the field. “The canyon” is much more fun to say. A also likes to say “I want to go on a road trip” which means he wants to ride from one end of the canyon to the other. We watched neighbors toss balls for their dogs, biked around and had snacks – a big component of a fun outing. It was nice to just be on our own, felt like no big deal, and something we should do more.

Cathedral Park Company Outing – Finally had a company outing since the start of coronavirus, meeting up in the park under the St. John’s Bridge. It was refreshing to see everyone in person, and be able to see and hear the people I work with every day in real time living technicolor, not just little boxes on video calls. I brought pizza for everyone, and we played croquet. It was the first time I’ve played that game since the year of my wedding when we bought sets for people to play in the park by our house. Turns out we have still have a cool vintage set at home, so we got it out for A to play around with in the back yard.

Swan Island Beach – We got out to the Willamette river via the small “beach” on Swan Island again this week. Our friends just got the same type of folding kayak as us, as well as an inflatable SUP. We’ve all been enjoying this new novel experience of paddling around on the water. We take turns paddling around and taking the kiddos out, then they spend the rest of the time playing in the sand and having snacks, until the sun sets. This is a really nice way to end a weekday after work.

Khan Academy Kids – I’ve been itching to try this app with A, and finally did this week. So far he seems to like it. I’ve kept it to about ten minutes each time so it stays interesting, then we go do some other non-phone activity. It’s neat to see what he understands (big vs small, more vs less, color distinctions, associating pictures with letters). I like most of the activities and characters I’ve seen so far. Some of the activities seem arbitrary free play with no real goal/reward, like: draw X and tap the green button when you’re done! It doesn’t matter what you draw, it doesn’t check – but this is probably similar to any kind of drawing activity in pre-k school. I think it’s to give them a fun break, get them thinking creatively, and possibly lay groundwork for later things. A couple small frustrating things – the character in the corner (Cody I think) constantly says “tap me if you ever need help!” so A tried it a couple times and it either didn’t do anything, or it just repeated what it just said again. Some non-app specific things are – taps sometimes don’t register with the app (little fingers and the subtle skill of tapping a phone with the part of your finger the phone will recognize), tapping/dragging near the edge of the screen can make the phone actually switch to another app, and random phone notifications popping up on top of the app. There may be a way to disable some of that using “Guided Access.” We’ll try that next time.

Leave a comment

Weekend Update – 8/23/2020

Things I’ve been into this week:

A course – Video Editing with Final Cut Pro X – From Beginner to YouTuber with Ali Abdaal – I recently discovered Ali on YouTube. His videos on productivity are pretty engaging thanks to his quick cut, polished editing style. Ali made a class on Skillshare giving away a lot of his video editing tips and tricks for faster workflow. I’ve made a video course once before, so I appreciate the difficulty in making a polished video of the same high quality we are accustomed to watching as viewers. I’ve been thinking of starting my own YouTube channel lately, so this is good prep.

Writing – I’ve been working on a long form blog post on how to get better sleep – a departure from the mostly technical topics I’ve posted about in the past. Branching out! I’ve now got a ton of content, but I have more work to do to edit it all into a nice flowing article. Ironically, while putting together the post, I was thinking – I’ve now got a good system going and I’m ready to speak to it with authority. Then I fell off the wagon this week and slipped into a pattern of staying up late again. I’m re-committing myself and hitting the reset button this weekend.

In other writing work, I published a new post on my software development company’s blog on saving money and time when building a mobile app. I’m working on a follow up post with more technical suggestions for faster and more efficient development.

Adventures – O and A are doing excellent at getting outdoors into nature, going on hikes and getting out on the water. We got an Oru Inlet folding kayak about a month ago. They are a bit pricey but super lightweight and convenient. It fits inside the car and is only 20 lbs, which makes it no big deal. This has opened up a new area of exploration for us – actually on the water and not just land locked on the shore at rivers and lakes.

Parenthood – The current work-from-home situation means I get to spend a lot more time together with A. I get to be a part of a lot more of his day than I would have otherwise. He has started to ask “why” about various things, and I love attempting to answer.

Leave a comment

Enumerated Types in TypeScript

Enumerated Types, also known as enums, are a feature common to many programming languages, that represent a finite set of possible values for a given type.

For example, in a typical 52 card deck of cards, there is four suits: Clubs, Diamonds, Hearts and Spades. All of the 52 cards are one of these suites.

In a typed programming language, we could have a “Card” type, with a “suit” property. In the most basic form, the type could be defined where the value of “suit” must be a string. We could then assign the value “Clubs”, “Diamonds”, “Hearts”, or “Spades” for each card.

Here’s how that might be represented in TypeScript, and for simplicity, we’re going to make every card have a number value for now and not worry so much about face cards.

interface Card {
  value: number // 2, 3, 4, etc...
  suit: string // either "Clubs", "Diamonds", "Hearts", or "Spades"
}

With this setup, we could assign suit to be “Diamonds”, “Hearts”, etc, but we could also assign it any other string, like “Squares” or “Harts”, and the compiler would not complain, because we said the value can be any string, and “Squares” is a string.

It would be nice if the computer could help us avoid errors like these. That’s one of the things enums can do, along with documenting what the valid values are.

So to lock things down a bit tighter, we can define an enum for Suit, with all possible expected values defined. Here’s how that looks in TypeScript:

enum Suit {
  Clubs,
  Diamonds,
  Hearts,
  Spades,
}

Unless you say otherwise, the value of each item in an Enum is numeric, and starts at 0. Clubs == 0, Diamonds == 1, etc. It can start at a different number, or you can specifically set the value of each item.

You can also make the values be strings, which is handy if you’re dealing with something like a REST API returning JSON data where the value of suit is a string, not a number.

// GET https://awesome.api/cards/32

// JSON Response:
{
  "value": 5,
  "suit": "Diamonds"
}

Here’s a string enum for Suit:

enum Suit {
  Clubs = "Clubs",
  Diamonds = "Diamonds",
  Hearts = "Hearts",
  Spades = "Spades",
}

Slightly redundant since we have to repeat each word twice, but it’s more convenient, and the values map better to the data.

Now you can define a card interface with the more exact Suit enum value defined.

interface Card {
  value: number
  suit: Suit
}

Then we can define a card:

const card1: Card = {
  value: 5,
  suit: Suit.Diamonds
}

This works, because we use the enum when setting the value. If we try to use a random string, it does not work:

const card2: Card = {
  value: 5,
  suit: "x" // compiler error 
}

// error details:
// Type '"x"' is not assignable to type 'Suit'.
// The expected type comes from property 'suit' which is declared here on type 'Card'

It also doesn’t work if we use the same string values as the enum.

const card3: Card = {
  value: 5,
  suit: "Diamonds" // compiler error 
}

// error details:
// Type '"Diamonds"' is not assignable to type 'Suit'.
// The expected type comes from property 'suit' which is declared here on type 'Card'

If value type is an enum, and you manually define a card at compile time, you must use the enum to set the value.

Sometimes numeric enums are desirable. A single integer takes up less space than a string. Sometimes the numeric values are meaningful – it could represent known id values, sort order, or ranking. One possible example is access roles. If all roles are ranked and one always supercedes the other, you could use a numeric enum where the values represent the ranking order:

enum Role {
  SuperAdmin = 0,
  CompanyAdmin = 1,
  Manager = 2,
  Employee = 3,
  Guest = 4,
}

Then let’s say a user can have multiple roles, like ["Employee", "Manager"] and we wanted to get that user’s highest privileged role.

First, if the data looks like that instead of numeric values, we can define a typed union with all possible value of a role string, with this handy keyof typeof syntax:

/**
 * This is equivalent to:
 * type RoleStrings = 'SuperAdmin' | 'TenantAdmin' | 'Provider' | 'Guest' | 'NoAccess';
 */
type RoleStrings = keyof typeof Role;

Then we can define a function that compares the values of each role and find the one with the lowest value:

function getHighestRole(roles: RoleStrings[]) {
  return roles.reduce((acc, role) => {
    // if role's number is lower than previous accumulator role's number, it now wins, return it
    if (Role[acc] > Role[role]) {
      return role

      // otherwise return existing accumulator role
    } else {
      return acc
    }
  }, "Guest") // default to lowest privileged "Guest" role string
}

Now we can define some data and call the function

const myRoles: RoleStrings[] = ["Manager", "Employee"]

getHighestRole(myRoles) // "Manager"

So, enums provide a way to concretely define and document the set of possible values that a specific variable or object property can be, help programmers avoid mistakes while writing code, and enable compilers to catch errors.

Alright, that’s probably enough about enums for now. By this point it’s either totally clear or you’re totally confused. 🙂

Comments Off on Enumerated Types in TypeScript

Google Sheets Macros

A macro in Google Sheets is a recording of a series of actions that can be repeated via the Macro menu or with a hotkey.

To start making a macro, click Tools > Macros > Record Macros.

A dialog box pops up showing the macro is currently recording, and lets you choose between absolute and relative references.

Once recording, you can perform some actions (such as formatting a header row), and click the “Save” button in the dialog box, give it a name and an optional hotkey.

The first time you try to use a recorded macro, you will be prompted to authorize it. Authorization cancels the action, so you’ll have to re-run it after you’ve authorized it for it to actually run.

Macros as Code

The really cool thing – is that your recorded actions are automatically translated into statements in a JavaScript function using the Apps Script APIs. After saving a macro, you can go to Tools > Script Editor to view the recorded macro as a script.

Here you’ll see the script editor with a function of the same name as your macro, containing the code statements to reproduce the actions. This macro “Header” changes the colors of the first header row and freezes it.

Here’s that code, with comments for each statement:

/** @OnlyCurrentDoc */
// ^ limit script permissions to current doc

function Header() {
  
  // get the active spreadsheet (the entire document)
  var spreadsheet = SpreadsheetApp.getActive();

  // get the currently selected sheet
  var sheet = spreadsheet.getActiveSheet();

  // select the entire row, relative to cursor starting point (equivalent of clicking number to left of a row)
  sheet.getRange(spreadsheet.getCurrentCell().getRow(), 1, 1, 
  sheet.getMaxColumns()).activate();

  // set background color, set foreground color, and bold it
  spreadsheet.getActiveRangeList()
    .setBackground('#4c1130')
    .setFontColor('#ffffff')
    .setFontWeight('bold');

  // freeze the first row
  spreadsheet.getActiveSheet().setFrozenRows(1);
}

Comments Off on Google Sheets Macros

Creating G Suite Add-ons with Apps Script.

I’ve been working on a project to build a G Suite Add-on. This category of software is written in JavaScript and runs within Google’s infrastructure. It’s essentially serverless – you write your scripts, Google runs them, and you don’t think about the compute.

It has it’s own flavor of JavaScript execution environment and a set of APIs for communicating with and extending G-Suite, collectively called Apps Script.

A couple interesting things about it:

CLASP (Command Line Apps Script Projects) is useful and recommended when you’re ready to “get serious” and not just write simple scripts. It lets you:

Interesting things about the Apps Script APIs and execution environment:

Maintaining State

In most business applications, you want to maintain some sort of state, such as a user’s auth token to a 3rd party service, their preferences, etc. Any add-on that talks to a 3rd party service might want this. Until today, I was using an additional “Meta” sheet within a Google Sheet to maintain some state. But I thought there must be a better way and found that there is – the Properties service. This lets you store key/value pairs in a few different contexts:

Comments Off on Creating G Suite Add-ons with Apps Script.

Forcing HTTPS on WordPress with Apache

This site lives on a long-lived Dreamhost account, and until a couple months ago, like many older sites, had been happily humming along without SSL setup.

That’s not really a big deal for a public-facing blog site, or so the old thinking went. But since I do login to update content once in a while, it makes sense to get it up to date with current security best practices and not send passwords in the clear, so…

There’s many options on how to do this, and I don’t reach for Dreamhost these days for new web projects, but since it ain’t broke… I went hunting on how to do that on Dreamhost. A couple months ago I did the first half of this project, and figured out how to set up Let’s Encrypt for a website in the Dreamhost admin panel – too easy. Worked right away… But one problem, no redirect of HTTP to HTTPS, so the old insecure site continued to work just fine. Also my custom web font wasn’t rendering correctly.

Then I just forgot all about it, until today. I’m planning to blog here again, so I took a look and fixed the issues.

First, my web font wasn’t rendering because I had a “http://” url referring to the web font, and the browser was refusing to load insecure content. A quick edit of the header php file for my theme to make that a “https://” url fixed that up.

Second, forcing HTTPS. From doing this many times, I know this means redirecting from HTTP to HTTPS. My WordPress site is hosted on Dreamhost and runs within Apache, so I was searching around (much of professional software development is having good internet search skills). First, I searched “wordpress redirect to https” and found “How to Redirect HTTP to HTTPS in WordPress“, which mentions how to do it on Kinsta (a different hosting provider, not applicable), Nginx (not applicable), Apache (applicable!), and via a WordPress plugin (applicable!). Since Apache is lower level than WordPress itself, this is more desirable (can’t get blown away by an update or conflict with other WordPress plugins.) Apache it is, which involves editing a .htaccess file. Then I searched “wordpress dreamhost .htaccess” and found “Force your site to load securely with an .htaccess file” on the Dreamhost knowledge base, which show how to find where on the server file system to find this file for a particular Dreamhost site, and what to put in it – same code as the Kinsta article.

The magical .htaccess incantation?

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]

Looks like it turns the rewrite engine on, runs a rule if the HTTPS condition is not on, and creates a rule to return a 301 (Moved Permanently) redirect for any request to the https:// equivalent.

Then I remembered I used to have SSH access to Dreamhost set up. Did it still work? Yes, it did! Was the file where the help article said it woud be? It was. Edited it. Tested it with curl:

$ curl -i http://synthesis.sbecker.net/

HTTP/1.1 301 Moved Permanently
Date: Tue, 14 Jul 2020 05:31:58 GMT
Server: Apache
Location: https://synthesis.sbecker.net/
Cache-Control: max-age=600
Expires: Tue, 14 Jul 2020 05:41:58 GMT
Content-Length: 238
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://synthesis.sbecker.net/">here</a>.</p>
</body></html>

Works!


Sidenote – The above is a first go at a new format I’m going to try for a bit. I needed a place to put this writing, and this old dusty blog already existed, so I’m reviving it.

I plan to write about / document something I learned once a day or so (with exceptions for trips, vacations, needed breaks, etc.). It can be the simplest, stupidest thing, as long as I learned anything at all.

I’m going to commit to this for at least one week.

Comments Off on Forcing HTTPS on WordPress with Apache

Exploring graph databases and Neo4j

Recently I started learning about graph databases and Neo4j specifically.

In a graph database, you have two main things:

Nodes and relationships can each have properties – pieces of data about them – what type of node or relationship it is, and any other data about it – like it’s name, when it was created, etc. In a relational SQL database, to store relationships you need to add columns in your tables to track foreign keys, indexes, etc. In other words, you need to pre-think things out and get your data into a shape that fits in tables of columns and rows, and define what kinds of things belong to or have many other things. In a graph database, you just start adding nodes, then add relationships from one thing to another. Just interconnected things.

I decided to play around with Neo4j and get a feel for how it works.

I used the instructions on Digital Ocean’s site for installing Neo4j on Ubuntu.

 wget -O - http://debian.neo4j.org/neotechnology.gpg.key | apt-key add -
 echo 'deb http://debian.neo4j.org/repo stable/' > /etc/apt/sources.list.d/neo4j.list
 apt-get update
 apt-get install neo4j

Now Neo4j is running. The HTTP api is available on port 7474.

We can send some requests to the api and see how it responds.

Some facts I’ve gathered:

Every request, when using curl, looks basically like this:

$ curl \
  -H "Accept: application/json; charset=UTF-8" \
  -H "Content-Type: application/json" \
  -X POST \
  http://localhost:7474/db/data/cypher \
  -d '{...some json...}'

That JSON generally follows this format:

{
  "query": "...SOME CYPHER HERE...",
  "params": {
    "key1": "value1",
    "key2": "value2",
  }
}

The values in the params key/value hash get substituted for names in the query. Name substitution is a nice built in feature.

The exception to this JSON format, atleast in the tutorial I followed, was when creating relationships. For that, you post to a different URL and use a slightly different syntax.

POST http://localhost:7474/db/data/node/0/relationships (url of first node’s relationships resource)

Request Body JSON:

{
  "to": "http://localhost:7474/db/data/node/1", // url to another node
  "type": "Comes Before" // name you've given this type of relationship
}

You can also create relationships with the Cypher query language.

Creating a node of type Person with a “name” attribute:

Cypher:

CREATE (n:Person { name : {name} }) RETURN n

Params:

name: "John"

Full on JSON:

{
  "query" : "CREATE (n:Person { name : {name} }) RETURN n",
  "params" : {
    "name" : "John"
  }
}

The API gives you a lot of data back:

{
  "columns": [
    "n"
  ],
  "data": [
    [
      {
        "outgoing_relationships": "http://localhost:7474/db/data/node/0/relationships/out",
        "labels": "http://localhost:7474/db/data/node/0/labels",
        "data": {
          "name": "John"
        },
        "traverse": "http://localhost:7474/db/data/node/0/traverse/{returnType}",
        "all_typed_relationships": "http://localhost:7474/db/data/node/0/relationships/all/{-list|&|types}",
        "self": "http://localhost:7474/db/data/node/0",
        "property": "http://localhost:7474/db/data/node/0/properties/{key}",
        "properties": "http://localhost:7474/db/data/node/0/properties",
        "outgoing_typed_relationships": "http://localhost:7474/db/data/node/0/relationships/out/{-list|&|types}",
        "incoming_relationships": "http://localhost:7474/db/data/node/0/relationships/in",
        "extensions": {},
        "create_relationship": "http://localhost:7474/db/data/node/0/relationships",
        "paged_traverse": "http://localhost:7474/db/data/node/0/paged/traverse/{returnType}{?pageSize,leaseTime}",
        "all_relationships": "http://localhost:7474/db/data/node/0/relationships/all",
        "incoming_typed_relationships": "http://localhost:7474/db/data/node/0/relationships/in/{-list|&|types}",
        "metadata": {
          "id": 0,
          "labels": [
            "Person"
          ]
        }
      }
    ]
  ]
}

Creating a second person:

{
  "query" : "CREATE (n:Person { name : {name} }) RETURN n",
  "params" : {
    "name" : "Susan"
  }
}

Create a relationship between them:

Assume the John node has a url of

http://localhost:7474/db/data/node/0

And the Susan node has a URL of

http://localhost:7474/db/data/node/1

We want to create a relationship between John and Susan. John loves Susan. That’s the relationship. In Neo4j, relationships have a direction. They go from one node to another. They also have a type. In this relationship, the from node is John, the to node is Susan, and the type is “Loves”. Each node has a set of relationships. This set or collection of relationships is mapped to a rest API.

http://{url-to-node}/relationships

For John’s node, which is node 0, this would be:
http://localhost:7474/db/data/node/0/relationships

Then, to create this relationship:

POST http://localhost:7474/db/data/node/0/relationships

{
  "to": "http://localhost:7474/db/data/node/1",
  "type": "Loves"
}

Neo4j returns a lot more data back:

{
  "extensions" : {
  },
  "start" : "http://localhost:7474/db/data/node/0",
  "property" : "http://localhost:7474/db/data/relationship/1/properties/{key}",
  "self" : "http://localhost:7474/db/data/relationship/1",
  "properties" : "http://localhost:7474/db/data/relationship/1/properties",
  "type" : "Loves",
  "end" : "http://localhost:7474/db/data/node/1",
  "metadata" : {
    "id" : 1,
    "type" : "Loves"
  },
  "data" : {
  }
}

It tells us where the relationship starts, where it ends, any metadata, any extensions, properties, and any other data.

Now, lets do a simple query to figure out who loves who (JSON enclosure left out, just the Cypher query):

MATCH (n)-[r:Loves]->(m) 
RETURN n.name AS from, type(r) AS `->`, m.name AS to

And we get back:

{
  "columns" : [ "FROM", "->", "to" ],
  "data" : [ [ "John", "Loves", "Susan" ] ]
}

Once you’ve got a lot of relationships set up, you can use Cypher to quickly query these. An immediate use case for graph databases is social networks. If you have all this data regarding who is friends with who, and you want to get some stats on that, like how many friends of my friends friends like pizza and live in Spain, and so forth, with a SQL database, this can be a real pain to write – loads of joins, nested queries, and very slow as the size of the network grows. A graph database is optimized for this, so it’s very fast to perform queries that traverse through many levels of relationships – at least it’s purported to be.

Although social networks are the first data structures to jump to mind, graph databases seem well suited to many other types of data as well, so long as the items are interrelated.

Another nice thing – graph databases seem to be more able to easily represent real life scenarios, where data doesn’t easily fit in a two dimensional grid. Have more data? Add nodes. Does that data relate? Add relationships. This includes one off items, special cases, and things which don’t fit into a traditional two-dimensional grid, or a hierarchical tree, or a flat set of key value pairs. Everything can be inter connected in a giant messy hairball of strange and wonderful relationships, just as it is in real life, and that’s ok – a graph database can easily represent that.

Comments Off on Exploring graph databases and Neo4j

Checklists and Habits

Lately I’ve become obsessed with checklists – a simple list of everything to complete a certain task. The book “The Checklist Manifesto” by Atul Gawande is a great introduction to the topic, on how checklists reduce defects in medicine, aviation, and architecture, with some dramatic medical stories thrown in for excitement. The basic idea is that humans are fallible, and a simple checklist can help us do things the right way every time, without overlooking something simple or skipping a step. This can be especially helpful in a stressful situation. It’s challenging to remember every step of a simple, mundane process when we don’t have a lot of time to think, if we’re distracted, or if we’re forced to multitask.

Although we’re drawn to stories of the brilliant creative genius, or the hero who reacted quickly under pressure, many times what really lies beneath these stories are established routines and engrained habits.

How Companies Learn Your Secrets“, an article by Charles Duhigg is a fascinating look at the analytics and marketing groups inside Target, and how, using existing data of their customer base, they determine within a degree of certainty, whether a female customer is likely to be pregnant. The statistical analysis behind that is interesting, but there’s another half of the same article which explores habit formation and how existing habits can be changed or manipulated. That’s because when a woman is pregnant, it is one of the main times in their lives when they are thrown into unfamiliar territory, and their shopping habits can dramatically change. If Target is there at this critical juncture, the thought is that they can be the new favored store for all kinds of things the expectant mother must buy.

This knowledge of habit manipulation is surely great for companies to use on their customer base in order to generate more sales, but it can also be useful to all of us at the individual level, in order to improve ourselves.

For most of our lives, when we’re not making major changes and just going about our day to day lives, we are operating mostly out of habit. When we operate out of habit, our brains go on autopilot. We’ve done this before, we’ve got it down, and we can do it blindfolded. This is true for everything from our morning shower routine to our commute to work. We don’t have to think much. This is our brain’s way of conserving energy.

A habit has a structure. The structure includes a “cue” – the thing that prompts us to begin the habit, a “routine” – the things we do to complete the habit, and a “reward” – the thing we get for completing the routine. Duhigg calls this “The Habit Loop”.

For example, take washing the dishes. The cue – seeing a pile of dirty dishes. This won’t do. The routine – clear the sink so you can work, start the hot water, put in some dish soap, soak the dirty dishes. Then clean something, rinse, repeat until all are done. The reward – a clean, empty sink, a strainer full of clean dishes. The second reward – if you do it daily, not that many dishes build up, so it gets done fairly quickly. All done until next time.

While washing dishes isn’t my favorite way to spend my time, at this point I do it out of habit, and I find it somewhat calming and relaxing. My brain gets to disengage from the task at hand and think about other things.

It can be very hard to change habits. By their nature, we do them without really thinking about it, and sometimes without even realizing it. One of the best ways the marketers have found to change a habit is to piggy back on to an existing habit.

In the article the example was Febreze. Initially, marketers originally sought to sell the product as an odor eliminator. The problem is, people become used to the smell of their own house and don’t realize it stinks. Ever been to a friends house and smelled an intense, overwhelming smell of dogs or cats and wonder how they stand it?

So, most people saw no need for a product like Febreze. Their houses were clean (or so they appeared) and of course they didn’t want to think of themselves as people whose houses stink.

The marketers found the solution by observing customers who actually used the product. A woman who loved it used it after cleaning every room in her house, as part of the reward – a little spritz of Febreze as the finishing touch. This was the key. Instead of trying to create a new behavior in customers – going around eliminating the odors in their stinky houses, the answer was to pitch Febreze as a product to incorporate into your existing cleaning routine as part of the reward.

How can we use this information to change and improve our personal habits and routines? Maybe there is something you want to start doing regularly, like writing, or exercising. Start by thinking about what existing habits you have, that you like to do or just do without thinking. What causes you to start? What is your reward for completing them? Here lies the answer. You can hijack your existing habits by planning to do a different routine or give yourself a different reward for an existing habit by figuring out the cue that triggers it.

For more info, see “How Habits Work” by the author of the article mentioned above, and the book “The Power of Habit“.

Comments Off on Checklists and Habits

End of July

Today and tomorrow we’re going camping at Jedediah Smith Redwoods State Park. Since I may be out of network range I’m posting this early. This will be the last post of the July blog-every-day challenge. In August I’m going to back off and try posting 2-3 times a week. Hopefully a bit more developed and longer form. Writing every day has been tough at times, and not always up to my own standards, but was certainly good for me to get into a regular habit.

I also managed to run 13 times so far this month, for a total of 33.56 miles. Definitely a record! I’m going to try to get atleast one more in today or tomorrow.

Comments Off on End of July