You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
👋! I'm Brian, and I am a software guy. I like leading teams and building products.
Currently, I do this at the company I co-founded, Curri. We're revolutionizing that way supplies are brought to/from construction sites.
I used to spend my days building world-class e-commerce experiences amongst the best in the biz at Dollar Shave Club. I've also worked with brands like Sweetgreen, VMWare, Geni, MyHeritage, just to name a few.
I love writing code, especially Javascript. I also love thinking about how teams of software engineers can do their jobs more efficiently.
I adhere to the 80/20 principle. I listen to a lot of podcasts. I've read a fair amount of books (here are some of my favs). I've run 3 marathons. I have a masters degree from Norway (for free). I used to own a ‘72 and an '84 VW Bus, but now I am riding in my '14 Mercedes Sprinter. Fancy, I know. I currently reside in Ventura, CA.
Oh, and this whole blog was written with Gustavo – a blog platform atop Github Gists and Nuxt.
Alfred has become such an integral part of my workflow over the years.
One thing that always bugged me about OSX is that when I would receive a text message notification,
I could read the text, but would need to click on the notification or open Messages to respond.
I thought to myself: What if I could respond from Alfred directly?
With Script Debugger and Alfy in-hand,
I was able to whip up an Alfred plugin.
You certainly don't need everyone physically together to create a strong culture. The best cultures derive from actions people actually take, not the ones they write about in a mission statement. Newcomers to an organization arrive with their eyes open. They see how decisions are made, the care that's taken, the way problems are fixed, and so forth.
I often consider the concept of a "career" and think about how harmful it is. I know the term has various meanings, but I
often find it defined as "the running list of all job titles one has held over their working life". This usage seems
to be a more modern one.
A societal construct of the 20th and 21st centuries, career as we know it today can cause good people to act in odd, harmful ways.
We are conditioned to desire a "career trajectory" that trends upward. Accountant to Manager, Manager to Director,
Director to Sr. Director, Sr. Director to VP. Why does it matter? We even have a name for this ladder. The Career Ladder.
What happens to our career when we grow old and pass? Is it etched into our gravestone or recited in our eulogy? Nope. It's
ripped up and forgotten. What is remembered and talked about? What you did. What you made. Who you helped.
How you lived a life of humility and servitude.
If a move down the career ladder means a happier, fuller life, I hope we'd all make the right move.
The big issues facing us today are twofold: improving engineer autonomy while maintaining system security in the production infrastructure, and evolving a safety net for engineers to deploy quickly with confidence.
As your Ember app becomes more complex with user authentication, tricky redirect rules, error substates, etc., you'll often find yourself reaching for Ember's transitionTo method, but this may not always be the right tool for the job.
Maybe you need to redirect a user away from the login page if they have it bookmarked but are already logged in, or redirect them to the login page if the try to access their account but are authenticated.
Or perhaps you're running an A/B test and don't want users in a certain test to see a certain page.
What if the user is trying to access the sign-up page and they're already signed up? We'll redirect them as well.
This article will attempt to shed light on the tools you have at your disposal in Ember
transitionTo
intermediateTransitionTo
replaceWith
Transition#retry
Let's start with this high-level breakdown of each approach, then we'll walk through a few scenarios where you'd use one over the other.
State Management
History Operation
Controller Equivalent
transitionTo
Manual
Push
transitionToRoute
replaceWith
Manual
Replace
replaceRoute
intermediateTransitionTo
Manual
None
None
Transition#retry
Auto
Push
n/a
Scenario 1 - Redirecting away from an authenticated page
Take an unauthenticated user visiting /account, a route that requires user authentication. The desired UX is to kick them to /login, and once they login, to send them back to the account route:
The beauty of this approach is that the you don't break the user's back button as you send them to log in. If you blindly used transitionTo, the user's back button would likely break and they'd become trapped. No bueno.
Scenario 1 - API failure
Let's say your API intermittently fails or times out. The desired UX is to show the user some sane error messaging, and perhaps tell them to refresh shortly (or refresh the browser on their behalf). intermediateTransitionTo is the right tool for the job here.
Remember, intermediateTransitionTo does not modify the URL or the state of window.history. When the page is refreshed (or programmtically refreshes), the route the user intended to visit is preserved and will be reloaded.
When to use transitionTo
One mistake I often see young Ember developers make is overusing transitionTo.
This bit of markup with a corresponding action in one's route:
<button {{ action 'transitionToAccount' }}>
Take me to my account
</button>
...could be written more succinctly (no action!) as:
{{#link-to 'account' class='button'}}
Take me to my account
{{/link-to}}
So my advice is to use transitionTo when you want your app to behave as if the user had clicked on a link. But, don't use transitionTo when a simple link-to is more appropriate.
If you enjoyed this post, follow me on Twitter as I'll be writing more on Ember over the coming months.
Tim Ferriss uses the D.S.S.S method when he sets off to learn a new skill. Why? It's simple. This method frontloads the bulk of the learning (hello 80/20 principle), lowers the barrier to entry, tightens the feedback loop, and creates accountability.
The principle essentially breaks down learning into these four steps:
Deconstruct: identify the key characteristics
Selection: select the characteristics that will provide 80% of the benefit for 20% of the effort
Sequence: run small trials of learning to figure the best ordering of these characteristics
Stakes: add in an element of accountability to entice yourself to endure
Let's take this rubric for a spin on a passion of mine: surfing.
Deconstruct
Non-surfboard gear (wetsuit, roof rack, wax)
Surfboard
Understanding the tides
Paddling out
Catching the wave
Riding the wave
Turning
Selection
In this step, it's important to identify (a) what you can achieve quickly with your current
skillset (b) what might cause you to quit if not overcome shortly after starting. For me and surfing:
Get the right gear
Get the right surfboard
Paddle out frequently
Catch waves, no matter how small
Sequence
The one mistake I made during this phase was going out with a cheapo board. Did the board really matter? No. Was I
ready, skillwise, for a better board? No. However, my cheap foam Costco special made me feel like I didn't belong
out there.
I upgraded, to a mid-level board and instantly leveled up by paddling out much more frequently. Win.
Stakes
I never actually applied any "stakes", but I am considering making myself accountable in the following ways.
If I don't go out more than once a week, donate to anti-charity
If I don't go out more than once a week, surf foam surfboard the following week
To achieve this effect, I used a library called merge-img, which simply horizontally concatenates png files.
I used 10 number icons (png files), 0 through 9, and I create an image on the fly and set it as the icon.
This example below is Typescript, but you get the idea hopefully:
import*asmergeImgfrom'merge-img'// For example, the code argument below might be the string `123456`functionupdateTrayIconWithCode(code: string,tray: Tray): void{constnumberPaths=code.split('').map(n=>path.join(__dirname,`numbers/${n}.png`))mergeImg(numberPaths).then((img: any)=>{constnumericalIcon=path.join(__dirname,'numerical-icon.png')img.write(numericalIcon,()=>{tray.setImage(numericalIcon)})})}
The longest lived businesses in the world aren’t the ones that were biggest in their day. Many of them are family firms, or small to mid-sized enterprises content with steady evolvement of their niche. Content with enough.
A great read from DHH reminds me of what I've been thinking
about a lot myself. I've seen growth pull owners away from the "front lines" and ultimately away from what
excited them in the first place: rolling up their sleeves and making a broad-sweeping impact.
Why? Well earlier this year one of my best buds (Jeff W.) and I set out to build a blogging platform atop Nuxt and Github Gists. After a few iterations on names and architecture and a month or so, behold Gustavo, which now powers this very blog.
With a simple naming schema, pushing content out will be painless. I can simply pop into the Gist interface, create a new post or page, then publish. This was exactly the vision.
Great little video by Veritasium
on YouTube. I got a Bachelor's of Science in Electrical Engineering and still need a little refresher every now and then.
The commenter equates low-grade sexual harassment (what the OP is doing) with being asked for a dollar each day by a subset of all individuals. Regardless of who is and who isn't asking for the dollar, it's natural to treat everyone as if they want a dollar.
An excerpt from the comment:
A substantial portion of the population believes that they have a right to a woman's attention, and if they don't get it, they get offended, mean, and sometimes even violent. You're just one of many, many men who believe that any woman you like owes you something. It's exhausting and sometimes terrifying to be on the receiving end of that.
Interface types have many similarities to type aliases for object type literals,
but since interface types offer more capabilities they are generally preferred to type aliases.
But what are these capabilities? Well, interfaces can be extended in a very similar manner to classes
Lopp speaks of this cancerous Grapevine within a company. Do you feed it, or do you kill it? It's easy to feed it, because, as Lopp points out, "Being part of a secret feels powerful."
Without active prevention, the Grapevine can be stronger than any individual. While you can’t kill the Grapevine, you can dubiously stare at it when it shows up on your doorstep and simply ask the person delivering it, “Do you actually believe this nonsense? Do you believe the person who fed you this trash?”
Today, I'll run my third marathon, the LA marathon. I'll be running with my boy @ratherfancy. We begin at Dodgers Stadium and end on Ocean Avenue in Santa Monica.
This will be my first race where I wasn't on a special diet (2016, keto) nor training with an actual marathon regiment (2014).
I find pushing my body to its upper bounds fascinating. Wish me luck.
I read a Medium post called Lazy Leadership this weekend, and its points on delegation and building a team which operates like a machine resonated with me.
Some entrepreneurs never break through the delegation barrier and get stuck along the way. They try hiring someone, and when that person doesn’t behave exactly like they would, they jump in and take over.
Although I am not an entrepreneur, I lead a small team of developers and I like to think we operate like a small business within the company.
We have goals, accountability, consequences, deadlines, projects, etc. all baked into our humble little team.
Shielding
It’s often said that the best leaders shield their team. Think pressure, politics, and drama.
While I think this notion is a false one, I often find myself caught up in it and doing it.
Whether that be rolling up my sleeves when a last minute request comes in so the team doesn’t have to. Or protecting the team from deadline talk so they don’t get stressed out. Or commandeering tough interactions and relationships on their behalf.
Do they actually want this? Maybe, maybe not. Does this mean I should shield nonetheless? No.
Building the Machine
Once I started thinking about my business like a machine, I realized that there were people out there who relished the opportunity to travel for work and thrived doing the same thing.
I can think of at least 2 things which I could hire for or delegate off of my plate to make the team more efficient:
Scheduling
Project Management
I wonder what others on the team are doing outside of their wheelhouse.
Here's a small flow I like to use when learning a new technology. I follow these one-by-one,
moving from one to the next, skipping those which seem unnecessary.
google: <topic> ELI5
google: <topic> diagram
google: differences between <topic> and <something you already know well>
google/youtube: <topic> introduction
youtube: <topic> tutorial (sort by length, favor videos no longer than 9 min.)
google: <topic> best practices
google: <topic> documentation
Go off and build something super small in said technology. Limit yourself to 1-5 hours.
One of my favorite subreddits, LifeProTips, got me thinking that I might be able to contribute some of my own.
Here are just a few that bubbled to the top of my head that work for me:
K2R works wonders to remove grease spots from clothes.
If you pay for laundry in quarters, get $100 worth at a time from the bank.
1 load/wk. * ($1.50 wash + $ 1.25 dry)
$2.75 * 52 wks. = $143 per year
Keep your Amazon app handy and buy things the moment you think of them, and don't let them take up mental space. Especially useful when in the kitchen.
Can’t download something too big over data on your phone because you see the “100MB” limit? Tether to a friends device and trick your phone into thinking you’re on wifi.
Turn an old stereo into a wireless one using a cheap bluetooth receiver like this one.
Make a room feel instantly clean by dusting the largest surface. This will partially trick your brain into thinking the whole room is clean.
Surf or hike and don't want to lug your keys around? Get a lock box, put your key inside, and attach it to the door handle of your car. I recommend this one.
One of the key pieces of my development workflow is using iTerm with each of my project's commands running in its own pane. Some of my projects require 5+ commands - think vagrant up, ember build --watch, redis-server, rails s, etc.
Who has time to remember all this, much less manually configure iTerm with each of these commands
each time?
To that end, we've created a new tool, called mert, which
automates iTerm pane management. I previously used
termrc, but it was brittle and imcompatible with iTerm 3.
mert is built in node and uses Javascript for Automation (jxa) at its core.
My fingers work...I’d rather do a little more work with my fingers and less work with my brain because I want to be able to save my decision power for my actual business logic.
The idea is that, due to the contraints of a statically typed language like Elm, you’re forced into writing code that your future self has an easier time reasoning about. I get it.
It’s this very notion which has led to a lot of shaming of Javascript as of late.
I, however, think the conversation is more nuanced.
As someone who enjoys mentoring new developers, the utililty of opening literally any browser and pressing CMD + OPT + i to invoke a REPL and tinker and prototype and explore cannot be understated. Javascript is fast, expressive, and it runs everywhere.
I do believe maintainability is crucial. However, shortening the path to gratification, especially for new developers, is invaluable.
Your Speed
Consider the “Your Speed” traffic sign, which embodies the Evidence, Relevance, Consequences, and Action Feedback loop cycle concept – outlined here.
The driver is immediately shown evidence that they’re speeding
It’s put into perspective by contrasting the speed limit
The driver is reminded about consquences – tickets, citations, etc.
The driver slows down as a results.
Javascript is the “Your Speed” sign for young developers. With little ceremony – install steps, etc. – a developer is instantly injected into this feedback loop and they’re able to modify their behavior nearly real-time.
A classifier is a way to use math to identify something. For example, you see something on the playground that is red. It could be a playground ball, or maybe a rabbit, or a tennis ball - but it's probably not a rabbit or tennis ball because you've never seen a red one of those before.
A fellow named Thomas Bayes figured out that if you actually knew how often playground balls, rabbits, and tennis balls were red, you could use math to work out a number that says how often a red thing that you see is a playground ball, rabbit, or tennis ball. Pretty neat. Maybe you notice other things about what you see too: it's size, shape, whatever. Well, Bayes' rule works even when you have more than one way to describe what you're looking at.
A Bayes Classifer is, then, something that uses Bayes rules to figure out how often red things are playground balls, how often they are rabbits, and how often they are tennis balls and then picks the one that happens most often. If most playground balls are red, and most rabbits an tennis balls are not, then when you see something that's red, it's probably a playground ball.
A Naive Bayes Classifier is one where you have several things that describe what you are looking at, like it's color, size, whether it has eyes or not… and you assume that they have nothing to do with each other. The color of something has nothing to do with it's size or whether it has eyes or not. This might not be a good a assumption, for example, there are very few purple things with eyes. But we may not know that, so we'll just say that it is so because it makes the math much easier.
Here are a couple of modern ways to parallize requests. Disclaimer, this code has not been executed.
Using Promise.all (Bluebird)
constPromise=require('bluebird');constgetResponses=async(urls)=>{constrequests=urls.map(u=>fetch/* fetch is a newish builtin API */)constresponses=awaitPromise.all(requests)returnresponses}consturls=['https://foo.com/bar.json','https://foo.com/baz.json','https://foo.com/qux.json'](async()=>{constresponses=getResponses(urls)})()
Using async/await & for-of
constgetResponses=async(urls)=>{constrequests=urls.map(u=>fetch/* fetch is a newish builtin API */)constresponses=[]for(leturlofurls){constresponse=awaitfetch(url)responses.push(response)}returnresponses}consturls=['https://foo.com/bar.json','https://foo.com/baz.json','https://foo.com/qux.json'](async()=>{constresponses=getResponses(urls)})()
Polymorphism is a powerful concept which allows a developer to abstract common functionality into a base class. Consider the following example: a user with multiple payment methods. They could have a linked Paypal account, and a couple credit cards on file.
Note that, for polymorphism to work, Ember Data expects a "type" declaration polymorphic type via the reserved type property on the model. Confused? See the API response below.
When I am working on a node project, I am usually either working with some API (right now I am hacking on the Amazon API) or working with large sets of data. More often then not, I need to log some object to the console and inspect it.
The issue with logging an object using console.log in node is that each nested object is displayed as [Object]. Helpful right?
A little Googling around surfaces reccomendations of JSON.stringify(obj) or instead installing yet another npm module.
The truth is, node has this built in.
util.inspect
One of node's core libraries, util, has a method inspect which is the right tool for the job. Here's how to use it:
var util = require('util');
var obj = { a: { b: 'Hello, world!' } };
console.log(util.inspect(obj, false, null));
The second argument, showHidden, determines if the "non-enumerable" properties of an object will be logged.
The third argument is the depth level; setting it to false will recursive to the furthest depths of the object.
If you'd like to have some more node tools in your toolbelt, I reccomend learning the ins and outs of the util core library.
The Proxy object is a new feature of ES6 which is looks to be super useful and promising.
I was working on a new Javascript for Automation (JXA) project and came across the npm module called jxa. jxa uses the Proxy object to pipe commands to OSX's osascript executable. You should poke around the source, it's quite neat.
If you want to learn more about Proxy, check out this article from Mozilla and this article from MSDN.
Note, the Proxy object cannot be shimmed by Babel and browser support is not universal.
One of the main reasons I love typed languages like Typescript is that they allow a developer
to reveal how their code should be used through the use of interfaces.
For example, it's simple to reveal what arguments should be passed to a function,
the shape of those arguments, and, one oft overlooked feature, the ability to
mark properties of objects or even whole objects as read-only. The ability to mark objects
as read-only (or quasi immutable) is especially powerful when building functional
programs, eg. a React application.
Like all parts of programming, there's one way and then there's the right way.
First let's look at how not to mark an entire object as read-only:
A few caveats: if you need to mark only bits of your object as immutable,
dont use Readonly<T>. Also, Readonly<T> does not reach into nested objects, so you'll
need to wrap those objects in Readonly<{}> accordingly.
Update
As pointed out by reader schlenkster on Reddit, this method only marks a per-use instance as readonly. We can get around this nuance by extending Readonly<T> at definition time:
I've come to realize over the past 6 years the power of identifying a right and how it differs from an expectation.
Examples of rights:
Water
Food
Shelter
Access to internet and all of its data
Speech
Examples of expectations:
Well-paying job
A house
Having kids
Wealth
Why is it important to identify rights vs. expectations?
When we take inventory, identify, then name them, we are much more capable of dealing with the result of not receiving either the right or the expectation.
If we're not receiving something we have a right to, we should feel injustice and we should take action to fix that. If the right continues to not be given, we should continue the cycle of feeling injustice and acting.
Our relationship with expectations should look much different.
If we're not receiving something we expect to receive, we often become crippled by the inability to obtain said expectation. The power lies in identifying the expectation, being an active participant in achieving the expectation or not, then letting go of the results.
Stress is often avoided at all costs. But why? Some is good and some is bad. Let's explore how we can
reframe stress to separate the good from the bad.
There are two types of stress: eustress and distress.
Eustress brings joy and fulfillment. Like watching a huge wave approach, developing a little angst,
and not knowing whether or not you'll catch it or get pummeled. Or like that feeling that comes when your
big race approaches and butterflies of excitement develop within your stomache.
Distress brings anxiety and pain. Like a pending, arbitrary deadline with your boss and all stakeholders
hounding you to just get it done. Or, like an approaching commitment you said yes to but should have said
no to all along.
Don't throw the baby out with the bath water. Seek out eustress, and avoid distress.
Ever needed to hang your wetsuit in you shower but couldn't find a place for it? Grab one of these little guys and hang it wherever you please.
The Wetsuit Hanger
Instead of paying $5 for a proper wetsuit hanger, I just take 3 old hangers and little electrical page and fashion a hanger which is strong enough for a wetsuit.
My Sprinter van key fob is chock full of electronics, so tucking it away in my wetsuit while I surf is not an option. I attach this combo box to my door handle with my key inside while I surf. Simple.
This little lumber rack serves as a great way to tidy your boards. Slide some PVC pipe padded with some pipe insulation rover the rungs to add a little extra room for your board.
In our test file, it's important to import the whole object and name it using the import * as someName syntax.
import * as helloWorld from './hello-world'
import sinon from 'sinon'
test('it should say hello to compadres', function (assert) {
sinon.stub(helloWorld, 'whom', () => { return 'compadres' })
assert.equal(helloWorld.sayHello, 'Hello, compadres!')
})
Seth Godin illustrates a phenomenon that occurs when we set out to achieve something: start a business,
tackle a New Year's resolution, lose weight, for example. This phenomenon is called The Dip.
What is The Dip?
Well, consider gym memberships. 12% of new gym memberships come in January come by percentage,
but it actually represents about a 33-50% increase in volume (see this post).
I wanted to play around with Vue 2.0 and learn more about the Chrome extension API. @sifxtreme and I, because we often have a lot of open tabs for work, also had a desire to build a Chrome extension that:
would help us cleanup tabs to save computer memory and mental space
was pretty
So we did just that.
Introducing TidyTab. You can find the code on Github.
One of the neater technologies that powers Dollar Shave Club's member experience is our UI icons powered by ember-data. I wrote about that here, back in the day when we used gulp to build our ember app.
Within the past month, we updated our app to be ember-cli based. With that migration came the need to refactor away from some of our gulp dependencies. Luckily, one of those dependencies was one I wrote -- gulp-file-contents-to-json.
I am heading to the Way to Work Workshop tomorrow at Basecamp in Chicago.
I hope to glean valuable chunks of knowledge to bring back to my team and implement in practical ways.
Time is the single most valuable resource of the company. And pretty much every single Basecamp employee has their entire day free to work on the one project at hand. Literally everything they do at Basecamp is about safeguarding everyone’s time. Nobody’s time at Basecamp is more or less important than anyone else’s.
...there is an “epidemic of collaboration” amongst corporate spaces.
Try to remove as many dependencies as possible so there are no bottlenecks forcing people to wait to get work done until they finally hear back from someone else.
Basecamp has found that written communication skills are critical. Because with strong writing skills, it means you have employees who also have the ability to think critically and communicate their ideas.
There is no backlog of work at Basecamp. Every 6-week work cycle is a new cycle and there is no “plan” or “map” of what they’ll do next. There is only the project at hand.