My Process for Intentional Learning

Lately, I've been able to carve out dedicated to learning new skills. What I've learned has been random, from programming languages to how to build a tiny house. I've found a lot of joy in learning new skills, slowly becoming a generalist.

Over the last year, I've found you can optimize your "learning time" by thinking through the process of learning before you start. In my experience, picking a learning project, and creating a "learning log" for each skill is hugely helpful.

Identify a Learning Project

Learning in a vacuum doesn't work for me.

I love reading fiction, but reading a topic that I have no immediate need to understand makes it much harder to comprehend. When I'm motivated by a problem I'm trying to solve, I can plow through books and other information quickly. Without an immediate need, I'll read the same page many times or fall asleep with the book in my hand.

In other words, learning something Just in Case doesn't work for me. It has to be Just in Time.

This is why a 'learning project' is really important. A small, useful, and preferably time-bound project that requires new skills to complete. The project is a forcing function for learning new skills. You want a project where the pain of leaving it half-done is painful.

For example, when our second daughter was born, I knew she would need the room in our house that I was using as an office (I work remotely). I could move into a room in our basement, but I loved having a large window in the room and for some reason, I didn't want to work in a basement. So, I decided to build a tiny house to work in.

I'd never built any physical thing in my life before.

I knew I'd lose motivation once I started it (especially as the Colorado summer heat ramped up). I ordered a massive truckload of wood and dumped it in my driveway and built the initial foundation. I knew our new daughter would need my room at the end of the summer and it would become too cold to make real progress on it by October.

These factors created enough motivation to force me to finish the project when I didn't want to. I'm glad I did! By building a mini house I learned most of the handyman skills I've been wanting to learn for years—the perfect learning project.

Before jumping into learning something new, take some time in picking your learning project.

For instance, let's say you wanted to learn software programming. You could take a bunch of online courses or start reading random tutorials online. You could spend a bunch of money on a coding bootcamp, or join something like Lambda School.

However, you could also find a a simple job on UpWork that feels simple & small enough for you to figure out. This provides a context and specific application for your learnings and the extrinsic motivation to finish the work (there's someone on the internet trusting you to get this thing done for their business).

Structure Your Learning

After you've picked a project, I've found it to be helpful to structure your learning process by asking some questions (here's a post that roughly follows this structure):

What's your learning project? Example: build a tiny house or automatically mark RSS articles as read What does success look like? This prevents you from following rabbit holes and forces you to finish the project. Example: build an insulated tiny house (not painted, not drywalled) or a script which marks articles more than two weeks old as read. What 'open questions' do you have? What are the gaps in your knowledge that would prevent you from completing the project? Write these down at the top of the document. What tools are you missing? This won't be apparent to you at the outset, but as you start learning you'll find friction in your process that you'll want to eliminate. For instance, I found that the hammer I had was hard to use. I noted this down and found that $10 bought me a much better hammer. Or, in the context of programming, your IDE autocomplete may not be working in the language you are learning. What are some of the top books, tutorials, YouTube channels, etc that align most closely with what you are trying to do? What completed pieces of work are similar to what you are trying to do? For digital projects, this could be open source projects or raw asset files for a media project. Is there a community (online or otherwise) around the thing you are learning? Documenting the places where friendly people on the internet, who are obsessed with what you are learning, is super helpful. You'll remember to ask them a question when you get stuck!

With this information in place, I start working on the project. As questions come to mind I write them down in a "learning log"—bullets in a document. If there's a large piece of knowledge or tool that's missing I'll add it to the top of the document and handle it later.

I've found that this live-blogging style learning log helpful, even if no one reads it. By writing down questions and problems that are coming to mind as I'm learning, it forces me to clarify and refine my thinking. This often helps me solve a problem quickly. Writing down the question helps prompt my mind to provide better & unique answers.

As a meta-point, by writing down this little guide it helped me better structure my learning process for my next project!

Continue Reading

Securing and Backing Up Your Data

I'm sure you've had this experience: you flip open your laptop and it doesn't boot up. You drop your phone and it won't turn on.

You pause for a second... "is any of my stuff backed up?"

It wasn't until this happened to me (my hard drive almost fried) that I started taking backups seriously. Security and digital backups are one of those "important not urgent" things it's easy to forget about until it's too late.

Here's my take on how to think about backing up your digital world and making sure others can't get access to it.

Security & Privacy

Assume all of your private information—SSN, address, password, phone, etc—will be public at some point. It's only going to get easier to hack into large systems.

Why? Here's one example.

Each website requires 100s or 1,000s of software packages downloaded from across the internet in order to run. If just one of them gets hacked or has a vulnerability, it's relatively easy for a hacker to scan the internet for all websites using that package and attempt to break-in. This sort of hack happens often. 

Still think I'm crazy? Plug your email into this site.

The good news is, if you setup your digital world correctly you can easily be immune to these hacks:

Make sure any single password isn't that important Make it challenging or impossible for anyone to login with just a password Setup automated alerts when someone else is acting on your behalf Backing up Your Digital World

Thanks to Time Machine and WiFi iPhone backups, it's gotten much easier to backup your data. For most folks, a time machine backup against an external disk is probably enough. 

However, my computer contained everything to run my business for many years so I took my backup game up a notch.

Here's how I think about backups:

You should assume something bad is going to happen. Your computer will break, your external hard drives will die, a virus will wipe your disks, or someone will steal your computer. Hopefully, none of these things ever happen, but planning as if they will happen is the safest approach.  The time it would take to recreate a single important file is more costly than ~decade of storage costs. In other words, don't try to save a couple bucks by not backing up your files.  Disk space is cheap. Wether cloud or external drive space, it's worth paying another $100/year to have enough space to never worry or think about losing data. Eliminate a single point of failure. A time machine backup is great, but what if someone comes in to your house and steals your electronics? Or a baby spills water all over your laptop and hard drive? I want my data to be safe if my entire house burns down.  Make it easy and automated. I want to set my backup strategy up once and never think about it again. My Toolbox

So, how do we get this done? First, here are the tools you'll need:

1Password. This is, by far, the most important part of this toolbox. I've used 1Password for many years and it's awesome. Gets better without fail year. It's a paid product, but it's worth every penny. I store passwords, credit cards, personal data, etc in this. Yes, it's safe to store all of your data in your 1Password vault—lots of articles out there explaining why.  Arq. Backups data on your computer (and other attached devices) to cloud storage. Supports lots of different storage options, including Amazon Drive. It's a paid product, but it's not a subscription service. Amazon Drive. My prime membership has free photo storage, and their storage tiers beyond photos are very cheap ($60/year for 1TB). I don't use it for document storage/sharing, but it's great for backing up data. 1TB external hard drives for my wife and I's computer for Time Machine. Those that don't have an external power source are more convenient.  Google Drive. I use this for any non-media documents.  GitHub. For code. I store all of my projects in ~/Projects. For the technically inclined, documenting your configuration in a dotfiles repo is a great way to backup config or preferences that may be skipped by Arq. Building Your Backup System

Next, you'll want to setup your backup system:

Setup the Amazon Photos app on your phone. Setup the app to automatically backup all photos and movies.  Setup WiFi iCloud backups on your phone. Disable photo backups via iCloud to avoid running out of space super quickly.  Don't try to organize old files, and keep your workspace (i.e. Desktop, Download, Document, etc folders) organized. If you find old files are piling up, group them into a "May 2020 Documents" folder and throw them on an Archive folder on your external hard drive (if you need more space on your primary machine) Setup DropBox & Google Drive sync apps. If you have multiple Google Drives, use InSync to sync them to different folders. Setup Time Machine against an external hard drive.  Setup Arq: Add your Google Drive & DropBox folders. Add places you put files outside of cloud storage tools. For me, that's Desktop & Downloads. I put all of my GitHub code in ~/Projects. This approach works for any non-media "project" files—put them all in a common directly and back the whole thing up. Add any external drive folders that contain files that aren't on your machine's drive. Connect to a backup destination. I use Amazon Drive. Setup a daily automatic backup. 

Here's what my Arq configuration looks like:

 

Some notes & caveats:

I don't have any on-disk music or video files. This approach should still work if you have a lot of media, but you'll want to think about what videos & audio you really need to backup to Amazon Drive to limit your backup costs. Keeping an external drive connected to your computer isn't really practical. I haven't connected my external drive to my laptop in a couple months, which isn't great. The easy way around this is buying a drive that connects to the network. Securing Your Data

Now it's time to secure your data! Here's what to do:

Setup 1Password on your phone and computer. Store every password you ever use here. 1Password will magically identify passwords that are insecure or have been leaked out to hackers. This makes it really easy to incrementally eliminate insecure passwords.  Use a unique password for every login. Do not use the same password everywhere. 1Password will generate a beautifully random password for you automatically if you install the Chrome/Safari extensions (which you should do)! Setup Two Factor Authentication (2FA) on all important sites. This includes Google, Amazon, banks, investment accounts, etc. Yes, it takes a couple minutes to setup, but it makes it much more challenging for someone to hack your account. 1Password can actually be your 2FA device (as opposed to using your phone). If you add a "one time password" field to the 1Password entry, a scanner will pop-up on screen. You can put that scanner over the QR code and boom—your 2FA codes will exist in 1Password.  Review your Google, GitHub, DropBox, etc account connections each year (don't forget!). It's very easy to grant permissions to a 3rd party app which are larger in scope than you thought when you clicked "ok". Printout your 1Password password each year and put it somewhere super safe. This protects against 1Password going down, or something else horrible happening to your computer or the internet. Monitor & Lock Your Credit

It doesn't hurt to lock your credit and setup some simple monitoring. Here are the three credit unions where you'll need to lock your credit:

TransUnion Equifax Experian

I've found that CreditKarma is a great service for monitoring your credit score & activity.

As with most of these posts, they are mainly written so I can document and improve my thinking. If you have any critiques or ideas, I'd love to hear them.

Continue Reading

How to Block Distracting Websites on Your Laptop

"What exactly did I do the last 30 minutes?"

I'm sure you've been there, asking that same question, staring blankly into your computer screen.

I've written about how I'm working to minimized distraction. For me, a big component of that is blocking distraction on the device I spend the most time: my laptop.

Here's what I'm looking to do:

Automatically block distracting websites, but allow an easy way to temporarily unblock them. Example: I want to block Amazon by default, but sometimes I want to jump on and buy something quickly. I don't want to have to manage a schedule. Creating exceptions to schedules and then remembering to re-enable the schedule never works well. I don't want crappy software that is going to slow down my computer or cause weird networking issues. I want it to be hard, but not impossible, to disable. One or two clicks to disable is too easy. The Easy Way

For most folks, you'll want to use one of the couple apps out there that do this for you. Here are some that I've tried:

RescueTime Focus Freedom Cold Turkey

Focus is the best option I've found. It's a simple and nicely designed app. Check it out!

The Hard Way

If you like tinkering with your system setup, read on.

The pre-built applications always seemed to do strange things to the networking stack on my computer or hog lots of resources (GBs of memory in some cases). This is probably due to how much I customize my computer.

Also, I found that if I disabled my "blocking schedule" it didn't automatically re-enable. I would then find myself down the Twitter rabbit-hole with 20m wasted. That was a big issue for me.

Eventually, I got frustrated and built a solution which works surprisingly well:

Maintain a simple file listing every host is distracting. Run a script every time the computer wakes up. I used sleepwatcher for this. The script consumes a list of distracting hosts and adds them to /etc/hosts with a reference to a non-existent server. After trying a couple of tools, a node package hostile worked best. 1. Build a List of Distracting Websites

First, create a simple text file. Back it up on Gist or somewhere where it won't be lost. Version tracking the file allows you to view a history of what websites are distracting over time.

I keep this file in my dotfiles repo. Here's what it looks like:

facebook.com twitter.com smile.amazon.com

(yes, that's Amazon Smile since I have a browser extension to redirect me there)

Then you'll want to clean the file, add www variants of each host, and point them to 127.0.0.1:

sed '/^$/d' ./distracting_websites.txt | sed $'s/\(.*\)/127.0.0.1 \\1\\\n127.0.0.1 www.\\1/' > ~/distracting_sites.txt

I put this script in the setup process of my dotfiles for easy ad-hoc execution (you'll want to continually update your distracting_websites.txt as new things distract you).

2. Block all Distracting Websites with a Script

Below is a script that is run every time I wake my computer. Here's what it does:

Updates /etc/hosts using hostile and the distracting_sites.txt file Clears system DNS cache Clears Safari cache, which seems to have its own DNS cache. Chrome does not. # asdf is a node version management tool I use. Your exact execution paths will probably be different /Users/mike/.asdf/installs/nodejs/12.14.1/bin/node \ /Users/mike/.asdf/installs/nodejs/12.14.1/.npm/bin/hostile \ load /Users/mike/distracting_sites.txt # clear system cache # https://apple.stackexchange.com/questions/303110/flush-cache-of-dns-on-macos-sierra-high-sierra/303119#303119 sudo killall -HUP mDNSResponder # clear safari cache osascript << EOF tell application "Safari" activate end tell tell application "System Events" tell process "Safari" tell menu bar 1 to tell menu bar item "Develop" to tell menu 1 to tell menu item "Empty Caches" to click end tell end tell EOF

You can test this script by running it with sudo:

sudo /usr/local/sbin/sleepwatcher --verbose --wakeup .wakeup 3. Run Website Blocking Script When your Computer Wakes from Sleep

First, install sleepwatcher:

brew install sleepwatcher

Then, you'll want to find the location of the plist file which starts up sleepwatcher as a daemon process:

$ brew services Name Status User Plist sleepwatcher started root /Library/LaunchDaemons/homebrew.mxcl.sleepwatcher.plist

You'll want to edit this plist:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>homebrew.mxcl.sleepwatcher</string> <key>ProgramArguments</key> <array> <string>/usr/local/sbin/sleepwatcher</string> <string>-V</string> <string>-w /Users/mike/.wakeup</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/usr/local/var/log/sleepwatcher.log</string> <key>StandardErrorPath</key> <string>/usr/local/var/log/sleepwatcher.log</string> </dict> </plist>

Then, you'll want to ensure the process runs as root and the script you created is executable:

chmod + /Users/mike/.wakeup brew services stop sleepwatcher sudo brew services start sleepwatcher

And... you're done! Depending on your OS configuration you may need to grant some permissions on first run.

Was this overkill? Definitely. Does it prevent me from wasting any time on distracting websites? Absolutely.

Continue Reading

How I Broke My Phone Addiction

The launch of Neuralink started a conversation across the web about the "merge". The day when you can plug your brain into a computer and communicate with it through your thoughts. No keyboard, mouse, or touch screen. Something out of a sci-fi film.

I think Sam Altman has an interesting take:

I believe the merge has already started, and we are a few years in. Our phones control us and tell us what to do when; social media feeds determine how we feel; search engines decide what we think.

This resonated very strongly with me. My phone does control me to a certain extent and I feel uncomfortable if I hop in the car without it.

I've been on a kick this year of being intentional about how I use technology. A big part of that is my phone. It's the most distracting—and the most useful—thing I own.

"What's wrong with your phone? Is it broken?" has been a common refrain when I show a friend a photo or map on my phone. Friends often complain about how slow I am to respond to texts. My phone isn't broken and I know how to use the messages app, but I have taken some "extreme" measures to disconnect from my phone.

Below is the list of things I've done to disconnect from my phone. They work. Not that I'm close to perfect, but I can easily leave my phone in another room now and forget to check it for nearly a day. That's huge.

If they seem extreme, I encourage you try one or two and see what happens.

Turn off Text Notifications

Turn off all your text notifications. Settings > Notifications > Messages > Allow Notifications.

Yes, it's hard and annoying for a week. But man, it is amazing not to hear or see that ding from incoming messages. Once you get over the week or two of withdrawal you'll love it and never be able to go back. I've had my text notifications disabled for months at this point and it is the single biggest change you can make on your phone.

"Communication for work comes through text and I'm expected to respond instantly!"

You win. This won't work for you. Here are two ideas for you:

Can you block texts from non-work numbers? If your work will pay for a separate phone, you could setup that phone with text notifications and disable them on your device.

"What if you are meeting someone i person and need to communicate in real-time?"

This happens to me often. Just open up your message app.

"What if you miss an emergency text from your spouse/friend/whatever?"

Tell your spouse and close friends you've disabled text notifications. If they need you right away, they can call you.

1. Setup an Incoming Call Whitelist

The idea here is only allowing calls from people you know. Any other calls can go to voicemail. If it's important, they'll leave a message and you can listen to it later.

Here's how to setup this whitelist:

Navigate to Settings > Do Not Disturb. Setup a schedule and make it nearly the whole day. Allow Calls From: Favorites (or whatever list includes the people you need to be responsive to). This is your whitelist of people you want to hear from. Install Hiya. I've found this to be a helpful tool for identifying spam callers when reviewing my missed calls and voicemail.

"I may receive a callback from a customer service department or other unknown numbers"

Just disable do not disturb. Because you've setup a schedule, it'll automatically be enabled the next day.

2. Enable Grayscale Mode

This was a trick I pulled from Make Time. Makes your phone less addicting, but no less functional:

Settings > General > Accessibility >Display Accommodations >Color Filters. Switch Color Filters on and select Grayscale. 3. Remove Distracting Applications

Remove any apps which you find yourself pull-to-refresh'ing. Some examples:

Social: Twitter, Facebook, Pinterest, whatever Dedicated news apps Email. Truth be told, I still have this on my phone for work communication. Move any apps that you need to keep, but are distracting, off the home screen. 4. Block Nearly All Notifications

Go through every app on your phone (Settings > Notifications) and turn off notifications. Think hard about the couple apps you really need notifications from and enable them.

Here's my list:

Google Calendar FaceTime Phone Airline apps Google Maps Scooter apps, Lyft, Uber DMs on Slack within working hours Todoist 5. Block Distracting Websites

It's not intuitive but you can block distracting websites on chrome/safari on your phone.

Navigate to 'Screen Time > Content & Privacy Restrictions > Content Restrictions > Web Content > Limit Adult Websites' and enter in all distracting sites under "Never allow".

For example, here's some of my list:

facebook.com twitter.com news.ycombinator.com recode.net theverge.com techcrunch.com producthunt.com quora.com reddit.con

Setup a monthly reminder on your todo list to add any new distracting news sites that you've started looking at on your phone.

Other Tips & Tricks

If you've made it this far, I challenge you to stick with the setting changes for two weeks. That's about how long it took for me to stop being annoyed by the changes.

Below are some other configuration tips & tricks I've written down over the years for when I get a new iPhone.

Other Misc Tips & Tricks Move mail off of the home screen General > Display & Brightness > Night Shift. Enable, 9am-7pm General > Accessibility > Home Button > Reset Finger to Open Delete default apps I'll never use: Home, Books, iTunes Store, Watch, Tips, TV, Apple Mail, News, Stocks. Messages: Enable send as SMS, disable send read receipts, enable text message forwarding. iCloud: disable photos (use Amazon photos instead), enable contacts, disable calendar, enable Messages, disable Stocks, enable iCloud backup, disable Keychain (use 1Password instead) Phone > Call Blocking & Identification: Hiya Spam & Block Enable password autofill for 1Password. Password & Accounts > Autofill Passwords > 1Password. Disable keychain passwords. Amazon Music: download some music you like, enable automatic downloads of offline music, and disable cellular streaming. Download offline google maps for your local area. Automatic Backup Configuration If you have Amazon Prime. Install Prime Photos and use it to backup all of your photos. Settings > iCloud > Storage > Manage Storage > Backups > Disable Photo Backup . 5gb is not enough room for anything, and Amazon gives you unlimited photo storage for free. Plus, there additional storage tiers (if you take a lot of videos on your iphone) is really cheap. Settings > iCloud > Photos > Disable Photo Stream. Manually initiate a backup to ensure everything goes smoothly. Without photos + videos, your iPhone backup should be able to fit into the 5gb default iCloud storage. Warranty & Documentation

Some notes on warranty replacement:

An IMIE number is a unique identifier for your phone. Document this number in a 1Password note. Settings > General > About > IMIE Your ICC number is the unique identifier for your SIM card. Document this as well. If something is going wrong with your iPhone, try backing up the phone to iTunes and then doing a fresh restore. If that doesn't work it's a hardware issue. Try this before wasting your time with Apple/your cell provider. If you get an "Invalid SIM" error when switching cell phone providers or phones your IMIE and ICC numbers may not be "paired'. You can often pair these numbers yourself through the settings area of your cell provider. The support reps often do not check this or understand it fully.

Continue Reading

Learning Clojure by Automating an RSS Reader

I've been working on revamping how I consume information. Most of my information consumption has been moved to RSS feeds, but I can't keep up with the number of articles in my feeds. When I take a look at my reader I tend to get overwhelmed and spend more time than I'd like to trying to "catch up" on information I generally was consuming out of curiosity.

Not good.

I want articles to be automatically marked as read after they are a month old to eliminate the feeling of being "behind". This is a perfect little project to learn a programming language that's looked interesting for a while!

Building a small project in a new language or technology is the best way to learn. While I was building this tool, I documented what questions I was asking, answers to these questions, and what articles and resources I found helpful.

Posts like this have been interesting to me, hopefully this is a fun read for others!

What do I want to build?

I want to build a Clojure script for FeedBin that will:

Inspect all unread articles If the publish date is more than two weeks in the past, mark the article as unread Automatically run every day

Let's get started!

Resources

Here are some helpful blogs & tutorials I used while learning:

http://slipset.github.io/posts/Why-Clojure-is-my-favourite-language https://ltriant.github.io/2019/08/13/clojure-learning-functional-design.html https://learnxinyminutes.com/docs/clojure/ https://eli.thegreenplace.net/2017/notes-on-debugging-clojure-code/ https://clojure.org/guides/getting_started

Also, I always try to grab a couple of large open-source repos to look at when I'm learning a new language. Here are some places I searched:

https://github.com/trending/clojure https://clojars.org http://open-source.braveclojure.com

Some repos I found interesting:

https://github.com/metabase/metabase This is probably the largest full-blown open-source Clojure application out there. Most other projects I found were libraries, not applications. https://github.com/LightTable/LightTable https://github.com/clojars/clojars-web https://github.com/dakrone/clj-http Syntax & Structure

Now that I have some browser tabs open with documentation, let's start learning!

How do I install this thing? https://clojure.org/guides/getting_started => brew install clojure/tools/clojure Going through the "Learn X in Y" guide, some interesting takeaways: Clojure is built on the JVM and uses Java classes for things like arrays. Code in Clojure is essentially a list-of-lists. A list is how you execute code: the first element is the method name, and then arguments separated by spaces. This feels very weird at first, but it's a really powerful concept. Simple made Easy explains the philosophy behind this a bit. "Quoting" (prefacing a list with a single quote) prevents the list from executing. This is helpful for defining a list, passing code as a data structure that can be mutated later on. Sequences (Arrays/Lists) seem to have some important different properties from vectors. I need to understand this a bit more. When you define a function it doesn't get a name. You need to assign it (def) to a variable to give it a name. The [] in a function definition is the list of arguments. There are lots of ways to create functions: fn, defn, def ... #() multi-variadic function is a new word for me! It's a function with a variable number of arguments. Looks like you can define different execution paths depending on the arguments, kind-of like Elixir's pattern matching. [& args] is equivalent to (*args) in ruby The beginner (me!) can treat ArrayMap and HashMap as the same. Keywords == ruby symbols The language looks to execute from the inside out, and the composition of functions is done via spaces not commas, parens, etc. Looks like everything is immutable in Clojure. Everything is a function. So much so, that even basic control flow is managed the same way as a standard function. Looks like "STM" is an escape hatch if you need to store state. Similar to Elixir's process state. The Clojure community is big on "repl driven development", but what exactly do they mean? How is that different from binding.pry in a ruby process to play around with code? Looks like it's not that different. Some nice editor integrations make things a bit more clean, but more or less the same as opening up rails console with pry enabled. I've always disliked the ability to alias a module or function to a custom name. It makes it much harder for newcomers to the codebase to navigate what is going on. Looks like this is a pretty common pattern in Clojure, the require at the top of a file can setup custom aliases for all functions. "forms" have been mentioned a couple of times, but I still don't get it. What is a form? I've heard that Clojure is a Lisp. What is a "lisp"? https://en.wikipedia.org/wiki/Lisp_(programming_language) There was an original LISP programming language, but "a lisp" is a language patterned after the original LISP Seems like the unique property of a lisp-style language is code is essentially is a linked list data structure. Since all code is a data structure, you can define really interesting macros to modify your source code. Another property is the parentheses-based syntax. It's interesting to look at the different lisp styles available. I feel like the only language that is popular today is Clojure. Sounds like immutability is unique to Clojure and isn't a core structure other lisps.

I think I know just enough to start coding.

Coding in Clojure

Here's the learning process which generated the final source code:

Let's define the namespace and get a "Hello World" to make sure I have the runtime executing locally without an issue. 184408626bb41b87d53f9b0bb5485a8e9201d8d5 Ok, now let's outline the logic we'll need to implement. 7e018b05ff8ad925ef2bfe9c56c4a702dce4c3d0 Now, let's pick a HTTP library and figure out how to add it as a dependency. https://clojars.org looks like the most popular package repository. It doesn't seem like there's any download/popularity indicator that you can sort by. Bummer. Hard to figure out what sort of HTTP library I should use. Looks like project.clj is a gemspec type definition file. Metabase's http library is clj-http. Let's use that. We'll also need to figure out how to setup this dependency file. https://github.com/metabase/metabase/blob/master/project.clj#L63 https://github.com/technomancy/leiningen is linked in the project.clj files I've seen. It's listed as a dependency manager on the clj-http library: https://clojars.org/clj-http. Let's install it via brew install leiningen. lein new feedbin and mv ./feedbin./ ./ to setup the project structure. Looks like lein will help us with dependencies and deployment. b0b4022618abac840af6679f900584d04de510c1 There's this skip-aot thing in the main: definition which I don't understand. In any case, if I stuff a defn -main in the file for the namespace defined in main lein run works! 764d7a1e2a537d61b036df4229a2c96671725dd8 It looks like this ^: syntax is used often. What is it? Ok, let's copy our logic outline from the other file we were working on over to the src/feedbin/core.clj and try to add our HTTP dependency. Added [clj-http "3.10.0"] to the dependency list in project.clj, lein run seemed to pull down a bunch of files and run successfully. Now, let's pull the FeedBin variable from the ENV and store it to a var. Looks like you have to wrap let in parens, and include commands that rely on the var within the scope of the parens. I could see how this would force you to keep methods relatively short. 6f1f8099ffd0ed5f997be93685d18d1c574efb6b Let's hit the API and get all unread entries and store them in a var. Looks like cheshire is a popular JSON decoder, let's use that. It looks like let is only when you want temporary bindings within a specific scope. Otherwise, you should use def to setup a variable. 5b63cd289052d9fcebec2cb2965d598927b0616a Convention is - for word separation, not _ or camel case. Let's refactor the getenv to use def. Much better! a6a95a1e4703c07e76ecce32b56b6b0f1903acca Time to select entries that are two months old. A debugger is going to be helpful here to poke at the API responses. Looks like debugger is the pry equivalent. I had trouble getting this to work and deep-dived on this a bit: (pst) displays the stacktrace associated with the last exception. This is not dependent on clj-debugger Looking closer at clj-debugger it has ~no documentation and hasn't been updated in nearly two years. Is there a better option? Doesn't look like it (require 'feedbin.core :reload-all) seems like the best way to hot reload the code in a repl. Then you can rerun (feedbin.core/-main) Ah, figured it out! (break) on it's own won't do anything. It needs an input to debug. (break true) works. You need to run this in lien repl for it to work. As a side note, I've found the REPL/debugging aspect of learning a new programming language to be really important. Languages that don't have great tooling and accessible documentation around this make it much harder for newcomers to come up to speed. The REPL feedback loop is just so much faster and in developer tooling speed matters. I was able to extract the published date, now I just need to do some date comparison to figure out which entries are over a month old. ca16f54f66a39753933168c3f8deac636144ca47 Now to mark the entries as "read" (in feedbin this is deleting the entries). Should be able to just iterate through the ID list and POST to the delete endpoint. I started running into rate limiting errors as I was testing this. # turns a string into a regex, but appears to do much more. Looks like it's a shorthand for creating lambda. https://clojure.org/guides/weird_characters macroexpansion is an interesting command to help with debugging. With the rate limit errors gone, I can finally get this working for good. I tried passing in the article IDs as a comma-separated list as a query string and it didn't work. I need to send this data in as a JSON blob. 166ea49439ed690ff08c8fd987530b170b9bb80e Got the delete call working. You can pass a hash directly to clj-http and it'll convert it into JSON. Nice. 63ac8bf1d4fd969326fffa9ad7b50ad1f0a4b56d

Great! We have the script working. Now, let's deploy it.

Clojure Deployment Using AWS Serverless

I have a friend who is constantly talking about how awesome serverless is (i.e. AWS Lambda). I also remember hearing that you can setup cron-like jobs in AWS that hit a lambda. Let's see if that's the case and if we can get this script working on lambda.

Some things we'll need to figure out:

How/where do I specify that an endpoint should be hit every X hours? How do I specify where the entrypoint is for the lambda function? How do we specify environment variables?

Notes

I jumped into AWS lambda dashboard and created a function named "Mark-Feedbin-Entries-As-Read" with Java 11. It looks like the crazy AWS permission structure is generated for me. I added the com.amazonaws/aws-lambda-java-core package and it looks like I need to run gen-class to expose my handler. What is gen-class? It generates a .class file when compiling, which I vaguely remember is a file which is bundled into the .jar executable. Looks like aot compilation needs to be enabled as well. Still need to understand what aot is. I ran lein uberjar and specified feedbin.core::handler as my handler. Created a test event with "testing" as the input. Used the -standalone jar version that was generated. Looks like environment variables can be setup directly in the Lambda GUI. "Cron jobs" are setup via CloudWatch events. What is CloudWatch? It's AWS's monitoring stack. Strange that this is the recommended way to setup cron jobs. I would have thought there was a dedicated service for recurring job schedules. "Serverless" (looks like a CDK-like YML configuration syntax for AWS serverless) makes it look easy to deploy a lambda which executes on a schedule, but doesn't indicate how it's actually managed in AWS in the blog post. Aside: It's interesting the more you dig into AWS, the more it feels like a programming language. Each of the services is a library and the interface to configure them in yaml. It looks like "Amazon EventBridge" is the new "CloudWatch Events". Looks like we can setup a rule which triggers a lambda function at a particular rate. Neat, you can setup a rule directly with the AWS Lambda GUI. Use a EventBridge trigger with rate(1 day) to trigger the function every day. Really easy! I checked on it the next day and it's failing. How can we inspect the request? It's probably failing due to the input data being some sort of JSON object vs a simple string that I tested with. Here's what I found: you can inspect the logs, use CloudTrail to view an event, enable X-Ray tracing, and send failed events to a dead letter queue. I enabled all of this stuff: my end goal to inspect the event JSON passed the lambda to determine how to fix it. Ah! After a bit more digging, if you find the event in CloudTrail there's a "View event" button that will give you the JSON output. I can then copy the JSON into the test event in the configuration for the lambda and run it there to get helpful debugging information. Feels a bit primitive, but it works. I wonder how you would run the function and locally and write integration tests using example AWS JSON? Looks like the function signature for my handler is incorrect. When handling events, the handler accepts two arguments [Object com.amazonaws.services.lambda.runtime.Context]. This fixed the issue! 8520e8a319bd5d41a67a01f9517ce4cf559ab381

Resources:

https://bernhardwenzel.com/articles/using-clojure-with-aws-lambda/ https://aws.amazon.com/blogs/compute/clojure/ https://thenewstack.io/move-your-cron-jobs-to-serverless-in-3-steps/ https://serverless.com/blog/cron-jobs-on-aws/ https://docs.aws.amazon.com/lambda/latest/dg/with-scheduledevents-example-use-app-spec.html https://lumigo.io/blog/eventbridge-vs-cloudwatch-events-kinesis-and-sns/ https://docs.aws.amazon.com/eventbridge/latest/userguide/run-lambda-schedule.html https://d0nkrs.com/post/building-aws-lambda-functions-with-clojure https://github.com/aws/aws-cdk https://github.com/jebberjeb/lambda-sample Open Questions

Here's a list of questions that I wasn't able to answer during my learning process:

How can you parallelize operations in Clojure? How easy is deployment? How does interop with Java work? Is there a rails-like web stack? Is there a style guide?

Continue Reading

Reclaiming Your Mind: Creating an Information Diet

There's been a lot of areas of my life that I've been 'auditing' and attempting to tweak the habits that have intentionally or accidentally fallen into place. One of these is my information diet: how I find, consume, and process information.I've been tracking my time spent on reading/time on the internet and I'm not liking the trend. I've felt more addicted to information this year and I want to eliminate that feeling. Revamping my information intake is one way I'm going to do that. It's worth thinking about why it's worth spending time consuming information, how I consume information, and how I want to change my information consumption.

Categories Stories. I've been almost exclusively consuming non-fiction for the last decade and rarely read any non-fiction. At the suggestion of my ever-wise wife and the promptings of a great podcast on story I've reprioritized non-fiction as something worth spending time on. Great stories can change our perspective on our life and increase our creative thinking.Curiosity & Exploration. Investing in discovering new and interesting ideas has always paid off for me. For me, this generally looks like browsing community sites like hacker news, reading a random newsletter, of following interesting people on Twitter. Learning about random, interesting topics has always been really enjoyable for me—it sparks creativity (and joy) and is useful later Work. Learning specific to a work-related problem. Entertainment & Social. Twitter, Facebook, news, etc. When you look back at your time spent here you always feel like it was a waste. I've been convinced that keeping up with news is largely a waste of time (you'll hear anything worth knowing about through friends), and time spend communicating with friends over social is better spent with friends in person. This doesn't mean that there isn't a place for this category, but for me it means I need to bias towards eliminating any time spent on this category. Infrequent Personal-ish Updates. There's a group of organizations or people I follow that I want to keep tabs on, but don't send emails often. A friend running a non-profit, bands announcing a new album, etc. Deals/Promotions. Transaction/Service Emails. Mediums Podcasts.BooksBlogs.Community News. Hacker News, Lobsters, Reddit, Product Hunt.News Sites. Google News, Bloomberg, TechCrunch, etc. Social. Twitter, FaceBook.Movies. NetFlix, Amazon Prime, YouTube.Email.Personal communication. Texts, voicemails, etc.

Thoughts on Consumption.

Continually improve the system. Set aside time every month to quickly audit what I'm consuming and what tools I'm using. Make consumption a choice rather than a reaction. Right now, I randomly visit Hacker News or see an article come through my email. Instead I want to centralize information in one category into a single place that I can go. Optimize for pull vs push consumption. A great example here is email newsletters. They are push, not pull, and are often messy to read and pile up in my inbox. I want to separate "conversations with people" over "updates from companies/interesting news".Categorizing information is critical. Email newsletters can't be categorized easily. I want to put feeds into separate buckets that I can prioritize and triage separately. I should use RSS again. Way back when I read everything via NetNewsWire. Email newsletters took over seemingly overnight and I forgot that RSS existed. Most sites I care about still support RSS (even if it's not advertised explicitly).Use a RSS Reader. Specifically, one supported by paid subscriptions. Free is great, but most free things (without a huge market) die or have negative externalities over time. I don't want to have to mess with this part of my toolkit much and deal with a killed product. Paid subscriptions mean it's a real business that will continue to improve over time. Limit consumption. I want to enforce a limit on the numbers of things I'm consuming. I wonder if there is a way to automatically reset the read count of various feeds so it doesn't look like there are too many articles to read when I use a reader.Prefer books over articles. For most business/technology problems, blogs and Q&A sites are the main source of data, but work aside, books are generally higher-quality information compared to blogs. The time it took someone to create the content is a good indicator of the quality. Books > Blogs > Twitter. (this gets a bit tricky with low-cost kindle books: skip these). Optimize for highest impact & quality information at the beginning of the day. This means reading books and long-form articles at the beginning of the day while my mind is clear, instead of consuming blogs, tweets, texts, etc. Treat books like a blog archive. I really like this concept, can't remember where I first heard it. Reading books from cover to cover doesn't make a ton of sense, although it's definitely how I'm trained to read books. Skimming through a chapter (or skipping it entirely) if you find it boring or too verbose shouldn't feel 'wrong'. If the writer can't keep your attention, that's their fault. Additionally, books are generally longer than they need to be in order to hit page quotas.Don't switch contexts. If you are reading a book, don't stop and read a blog article. Cultivating sustained laser-focus attention on a single thing is critically important. I've found this to be more challenging as the years go by, and it's something I need to be even more intentional about.Focus on managing written internet media. I don't over-consume podcasts or books. I struggle most with interesting, distracting news sources like Hacker News or What I'm going to change Limit number of news feeds to 30. I suspect this number will change as I continue to slowly improve how I'm processing information, but this is a good start.Convert email newsletters to RSS. Most newsletters (like Ruby Weekly) have an RSS feed. For those that don't, FeedBin has a service to convert email newsletters into a feed, and I imagine there are standalone services that will do this for you automatically.Mass-unsubscribe from email newsletters. I've been using unroll.me for years (I don't love the privacy component, but it's a useful tool). It looks like their unsubscribe option will actually click through the unsubscribe links for me. I should go through my daily Unroll.me summary and remove newsletters I'm not interested in, and convert the others into a feed.Setup two aliases email+updates@gmail.com and email+promotions@gmail.com. Forward all updates to FeedBin and auto-archive. Auto-archive & tag all promotions.Subscribe to weekly summaries on community news site. Mass unfollow everyone on Twitter, and limit the people I follow to 50.Update my website blocking strategy, including blocking of all news & social sites. More on this in a separate post.Stop using Apple Podcasts. I find it hard to keep things organized and Apple seems to randomly reverse the listing of certain podcasts. I should trim which Podcasts I subscribe to and find another Podcast application. Categories: engineering, techReview all gmail filtersReview and trim all YouTube subscriptions. Review all Twitter app connectionsReview any compromised passwords via 1Password

After a bunch of investigation, I settled on using FeedBin.

https://reederapp.com/mac/#faq doesn't look like it is updated oftenhttps://github.com/mausba/rssheap went open source and hasn't been touched in over a yearhttps://github.com/getstream/winds podcast and RSS reader, open-source, commercially supported and recently updated.https://www.inoreader.com. Standalone paid product, has an API, doesn't look too complex. 64 feeds for free. Free and paid tiersFeedly.com is the most popular, but looks to be overdone. http://newsblur.com. Standalone paid product. Not updated frequently. Doesn't look like a great design. Free and paid tiers. I found this reader most commonly referenced by HN and Lobsters.https://readkitapp.com ties into various services to create a great reading experience. https://www.goldenhillsoftware.com/unread/ another macos reader.https://yoleoreader.com web-based reader with a low-cost paid subscription. https://feedbin.com well-designed feed reader. Supports podcasts and receiving email newsletters via a special email address. Also has a Twitter reader as well. Bootstrapped business. Also open source, very cool. https://github.com/feedbin/feedbinhttps://github.com/ViennaRSS/vienna-rss Pete Cooper is involved in this one. Open source. Looks like a zombie product.https://www.nooshub.com new reader from HN with some fancy "AI" grouping.https://ranchero.com/netnewswire/https://apps.apple.com/app/leaf/id576338668 Leaf. Looks dead. Hasn't been updated in two years.

Other interesting finds:

https://superfeedr.com RSS feed APIhttps://throttlehq.comhttps://news.ycombinator.com/item?id=20167143 and https://news.ycombinator.com/item?id=19909102

Continue Reading

2019 Goal Retrospective

I've been doing retrospective's on my yearly goals for a couple years now. Although it's a little late, I wouldn't want to break the habit (plus, I'm trying to open source my thinking).

Let's go!

What Worked Creating a distinction between habits and goals. I have a separate "habit document" where I document habits that are important to me. Setting a goal to kickstart a habit. Habit-goals shouldn't be all, or even most, of your goals for the year but having one or two habit-goals can be really effective at changing behavior. It was useful to commit to an action (like hiring a personal trainer) to force building momentum for a specific habit. If you've set a goal for the last couple years and haven't been able to make it happen, consider doing something drastic. How can you up the ante and put something on the line associated with the goal? Maybe it's hiring a coach, tying money to it, making a commitment that you can't back out of without causing issues for someone else, etc. Figuring out how to raise the stakes has been hugely helpful. Including a just-for-fun goal: vacation, hobbies, etc that you'll be really motivated to accomplish. This has helped me be excited about the year and maintain motivation for the important but not exciting goals. Setting aside project time as a married couple. It was fun to work on our goals together, and we got some important and run things done during this time. Looking forward to more of this. Joint goals or projects with my wife was really fun and motivating. For instance, we built a garden together this year. Zero-targets. Setting a non-action goal was a great way to break some behaviors I wanted to change. What Didn't Goals that weren't exciting or specific enough fell to wayside. We didn't do the quarterly review at all. This is the second year that this wasn't an effective practice. In the season of life that we are in (little kids), we just don't have the time to really set aside the time to do a proper quarterly review. We need to rethink this. This may be obvious, but having a kid is a goal in and of itself. We knew we were going to be growing our family, but I didn't account for this in my list of goals. Make sure to a in that year and you need to plan for that. We didn't create "project time" that often individually or as a couple. I wish we blocked off time for projects 2-3x more than we did. What Needs to Change? Remove the quarterly review. We haven't stuck to it for the last two years and with two young kids carving out that amount of time just isn't practical. Next iteration on this is adding reminders to our monthly review to ask a couple of the questions that we wanted to incorporate into the monthly review. More project time. This is super fun if you set goals at a couple and helps create focus around making progress on goals that are slipping.

Here are some other reflections I had about the year:

Many of the exciting life changes have come and gone (moving, buying a house, etc) and we are in a season where family (kids) take up the majority of our time. This means that most of our goals are less exciting, and that's ok. We have to remember that raising amazing kids and being present to them is our top priority. What that requires shifts and changes throughout the year. Some things in our life which need to change are hard to tie to a specific and measurable goal. Mostly because we don't know exactly what needs to change. With two young kids "improving our family balance" is a thing we need to improve, but what that exactly means isn't clear. What we decided to do was pick a specific thing that represented the best forcing function we could think of for improving on the vauge state that we are marching towards, and then adjust the specifics of that goal as we move through the year. Most of your goals shouldn't be actions that you naturally motivated to take. I tend towards this mode and need to think hard about what goals work against things I don't

Continue Reading

Life Categories for Your 2020 Goals

Each year my wife and I go through a review process where we set goals and habit targets. We've been doing it for five years and it's amazing to see the progress we've both made. It's also been powerful to set joint goals that we can work on together.

I've found it helpful to think over the "categories" of your life. A couple of years ago I wrote out my main life categories and it's time to update that list:

Spiritual Marriage Kids Health Intellectual Work Adventure, beauty, and fun. Intentionally pursuing outdoor adventure and just-for-fun activities with friends is a new thing for me. In the past the first thing to go with this sort of self-care, but I've found this to be more and more critical to achieving the life I want to have over the long-term. Financial Relationships

This list is stack ranked against what my long-term priorities are. For a season, one category will be more important than other aspects of my life but over the long term, I want to ensure I prioritize my life against this stack-ranked list.

It has served as a good gut check for me at the end of each year: is my time aligned against how I want my life to look?

 

Continue Reading

Archiving a QuickBooks Online Account to QuickBooks Desktop

If you run a small business, you probably use QuickBooks. I've been impressed with the product: the rate of improvement continues to stay constant over the last couple of years (one of the most important criteria in picking a software platform for your business!) and it's surprisingly pleasant to use.

If you close a company, you'll want to archive all of your QuickBooks data for at least a couple of years in case you get audited. However, QuickBooks Online does not have a low-cost "audit backup" option to access a read-only version of your data. If you cancel your subscription, you only have 90 days to reactivate your subscription and restore your data. There are some QuickBooks Online apps that claim to backup your data, but there are significant caveats with most of these cloud apps.

The best (and cheapest) option is to download a QuickBooks Desktop version of your data which can then be later used to create a new QuickBooks Online account if you ever need to. However, this is more complicated than it should be (most likely, by design).

Hopefully, this guide makes it a bit easier!

1. Get Access to Windows 7 with Internet Explorer 11

In order to actually export the QuickBooks Desktop file from QuickBooks Online, you need Windows + IE. User-agent spoofing won't work, there's some wacky ActiveX plugin you need to install in order to complete the export process.

Other versions of Windows and IE may work, but this is the 'official' version stated to work when you login to QuickBooks Online > Exports > "Moving to QuickBooks Desktop?" > "Download company data".

"How can I possibly get those exact versions, especially when I don't have a Microsoft computer anywhere in sight?!" you may ask. Great question.

Luckily, Microsoft has virtual machines with a bunch of different Microsoft and IE versions (designed to be used for website testing) you can download and use for 90 days for free. Download the virtual machine here.

2. Download VirtualBox

You'll need VirtualBox to run the virtual machine you downloaded from Microsoft. Download it here. You'll also want to set up a couple of configuration options by navigating to Machine > Settings once your virtual machine is running:

General > Advanced > Shared Clipboard > Bidirectional. Helpful for sharing passwords for QB. Shared Folder > Add New. Set up a folder and make sure to auto-mount it. General > Displays. Make sure video memory is at least 128mb. For some reason the default was 4mb. 3. Download QuickBooks Desktop Trial Version

In order to download the QuickBooks Desktop file, you'll need to have QuickBooks Desktop installed on your virtual machine. You can download a trial here.

4. Generate QuickBooks Desktop Download File

Follow these instructions to download your QuickBooks Online as a QuickBooks Desktop file. Here's another guide that's more simple (but won't be kept up to date).

5. Verify & Backup

After you generate the QuickBooks Download file you'll get a strange email with the subject "QuickBooks Online Simple Start: Company Data Ready for Download" asking you to "2. Click the task or to do item called 'Download the company file created on xx/yy/zzz'". This must be old email copy, because there is no such thing as a "task or to do item" in QuickBooks.

Here's what you need to do:

Navigate to QuickBooks Online > Exports > "Moving to QuickBooks Desktop?" > "Download company data". You'll be walked through a process to download the file and import it into QuickBooks Desktop. If things don't work, restart your computer and open up QuickBooks Desktop before opening up IE. After you've opened the file in QuickBooks desktop, run the P&L and Balance Sheet reports to ensure the numbers match up with QuickBooks Online. Create a backup from QuickBooks Desktop and store it in your shared folder Create a copy of the company for QuickBooks online. File > Utilities. Copy the backup to DropBox/Google Drive/whatever Recreate a new company in QuickBooks Desktop using your backup to ensure you can recreate it if you need it.

Continue Reading

Why You Should Open Source Your Thinking

Open source software (OSS) has transformed the technology landscape. I can't imagine any software company build without OSS at the core.

What makes OSS magical is the serendipity of how it's created. Someone throws an initial idea on the internet, and if others have the same problem, they join in and organically refine and improve the original idea. Others silently lurk into the project, start using it, and run into some bugs or edge cases which they report (and sometimes post a fix for). Before you know it, there's a robust piece of software that has been tested under a variety of circumstances by experts around the world.

Amazing.

Blogging has similar properties. Someone can post an idea, which is then improved upon or augmented by the community. Unlike software, the mechanics (i.e. GitHub) don't easily exist to collaboratively discuss a particular part of the idea or concept that is being written (what a cool product that would be! Holloway is doing something similar).

I think posts written as a breakdown of someone's thinking on a particular topic, without any hidden agenda, have the best chance of creating the OSS dynamic. For instance, by reading Stephen Wolfram's explanation of his productivity system, you'll probably end up tweaking your own working style or adopting some of his tricks. Reading how someone else learned a programming language may change how you approach learning. A packing list for a family with four kids may help augment your own travel strategy and inspire you to travel the world with your kids. Reading how someone manages their finances, consumes information, purchases insurance, will help you revise and improve your own processes.

I think of these posts as "open sourcing your thinking". Documenting how you approach a specific topic with enough detail and vulnerability helps you clarify your own ideas but more importantly allows your ideas to be critiqued and improved by the larger internet community (just like OSS).

I'm going to be doing more of this. And, selfishly, I hope you do the same so I can learn from you!

Continue Reading