Humanist, vegan, minimalist, programmer, collector of labels.
49971 words


In the United States, the general election is coming up in a couple weeks. While every election seems like "the most important ever", this one is particularly noteworthy. We're in the middle of a global pandemic, climate change is creeping closer, and economic inequality abounds.

American democracy is under attack. Voter participation has been incredibly low over the last couple decades, and blatant voter suppression tactics are deployed regularly, like limiting the number of ballot drop boxes or polling places to make it difficult to cast a ballot.

Despite our historic lack of participation, early voting levels are drastically outpacing past elections!

While our country faces a deep political divide, I do think we can all celebrate the fact that more citizens in this election are exercising their democratic right to vote. High levels of voter participation theoretically leads to representatives being elected who more closely mirror the desires of the populace. And it's my hope that high turnout will lead to many broadly popular policies (weed decriminalization, infrastructure and healthcare improvements, progressive taxation reform, etc.) finally being enacted by the politicians in D.C.

I know many people are unhappy with the choice for President. But there are far more elections on the ballot than a single office. Even if your favorite presidential choice doesn't win office, you can still have an impact on your local and state races, who are arguably more integral to making things happen that you'll notice in your day-to-day life.

So go get educated. Read voters guides, newspaper and union endorsements, the candidates platform, and any other reliable information you can find. Then cast your vote for the people who are closest to building the world you dream of.

The last four years have been a mess for me. Voting for Joe Biden, despite him being one of my last choices, was an incredible opportunity for me to be the change I wish to see in the world. I've felt a bit powerless following politics over the last few years. Submitting my ballot felt amazing. I did my bit for building a better world.

Please, do your bit too!

If you're new to voting or need a bit of help, is a fantastic resource to help you exercise your civic duty and one of the most important democratic rights you have!

Let's smash turnout records. Let's get the will of the people heard and give the next government (regardless of who wins) a clear mandate to enact their agenda and (ideally) make the world a better place.

Back in Seattle!

I'm all settled in my new apartment in the Ballard neighborhood of Seattle. I spent some time this morning walking around the neighborhood and seeing what kind of food, shops, and entertainment are nearby and I found some real gems! The neighborhood is quiet but alive, and it's got basically all the things I need to enjoy living in an area (movie theater, variety of resturaunts, rock climbing gym, good bus routes, and a Trader Joe's)!

I miss being with family in Utah, but I also enjoy the independence that comes from moving to the big city. I wish COVID were over so that life could be a bit more normal, but until then I'll make the most of what coronavirus-era Seattle has to offer.

Next step is getting some rugs and decorations to mute a bit of an echo in my apartment haha. Luckily there are lots of cute shops nearby with that kind of stuff that I can explore and make this place really feel like home. After moving for the third time in less than ayear, I'm ready to stay in one place for a while!

New Job!

I've got some exciting personal news: I recently accepted a position with the Allen Institute for Brain Science! I'll be working as a web developer to build out a scientific data sharing platform.

After six years in IT consulting, I've decided to make the jump to the non-profit sector. I've wanted to work for a non-profit organization for a while, and now is the time for me to make that dream come true.

I started my first job out of college with Pariveda Solutions, and I'm incredibly grateful to have been there for so long. It's a fantastic place to work and I'm glad I landed there to start my technology career. But my life has changed a lot in the six years I was with Pariveda, and it felt like it was time to move on.

So in August, I started my first job hunt in forever.

It was a strange experience. I literally had not looked for a job or touched my resume while I was with Pariveda since I had been very happy working there. So I brushed up my resume, sent it to some friends who gave great feedback, and then started sending out job applications like crazy!

Here are the stats regarding the applications I sent out:

  • 63 applications
  • 35 ghosted
  • 21 nos
  • 4 technical assessments
  • 2 "no positions available" responses
  • 2 post-assessment interviews
  • 1 offer

I applied for a lot of "pie-in-the-sky" jobs, like Discord, Reddit, Nintendo, and other companies whose products and services I enjoy. I also looked for some Rust-specific jobs since I really enjoy that programming language. And I applied for some that were building tools to address climate change.

Eventually I ran across the Allen Institute a couple weeks into my search. I knew about the organization because I walked by their building in Seattle every day for a couple years during my commute. I always thought it would be cool to work for them or another non-profit, but I never really looked into it because I thought it was just a bunch of scientists who didn't have a need for a web/cloud/backend software engineer. Thankfully I discovered that's not the case!

I got through the interview process, met a good portion of the team, and was literally dancing around when I received the offer. I'm super excited to work on web technologies to build out useful graphs, charts, tables, and other tools for exploring the data generated by the scientific teams at the Allen Institute. It's a fantastic opportunity for me and I'm really grateful that I get a chance to use my skills to further what humanity knows about the brain. If I can do anything to help solve issues like brain cancer or Alzheimer's disease, I will be ecstatic.

I'm moving back to Seattle right now to start the new job next week, which means I'll get to see my dog Kaladin again and many of my Seattle friends! I had a really good time living in Utah with my family, but it also feels nice to return to the Pacific Northwest.

I'm starting a new chapter in my life, and it's scary and exciting and new and terrifying. I can't wait to see how it goes!

I'm So Done With This Country

We're a bunch of racists who use police power to punish black people because we never got over losing our slaves.

Fuck the poverty to prison pipeline, the privatization of prisons, and the systemically racist police force and legislation that keeps it all running.


Tyranny of the Minority

The United States is democratic republic. That means that the people elect the representatives who make decisions on our behalf.

But the democratic part of our system has been under attack for decades. You can see it clearly with the Supreme Court nominees.

When Trump appoints a third SCOTUS judge, five of the nine serving justices will have been put in place by presidents who lost the popular vote and confirmed by Senators representing a minority of citizens.

That's hardly something you can call democratic.

While George W. Bush appointed both his nominees in his second term, where he won a majority of votes, that was arguably because of the wave of nationalism from the 9/11 attacks and his natural advantage as an incumbent. He should have never been in the position to nominate Supreme Court justices in the first place in a second term that likely would not have occurred had Gore won the presidency.

As for Trump, he lost the popular vote by almost 3 million ballots (a much wider margin than the 500,000 lead Gore had). The Electoral College once again paved the way for a minority president to be in place to appoint multiple SCOTUS judges, including the stolen seat of Merrick Garland.

The Electoral College is an inherently undemocratic institution, and that has benefited Republicans twice in the last 20 years.

As for the Senate, it becomes more unrepresentative each and every year as populations boom in urban areas, while rural states grow more slowly. A vote in Wyoming is over 50 times more effective than a vote in California, since both have only two Senators but California has 24 more million people.

When we look at the numbers for the Senates that approved each of the minority president's SCOTUS picks, the undemocratic nature of it all rears its ugly head.

The 109th US Congress approved two of Bush's selections with 55 Republican Senators, representing an estimated 49.54 percent of the US population in 2005 and 49.79 percent of the US population in 2006 (stats taken from

The 115th US Congress approved two of Trump's selections with 52 Republican Senators for the first pick and 51 for the second pick. This represents an estimated 44.74 and 44.12 percent of the US population in 2017 and 2018, respectively (stats taken from

The 116th US Congress is on the verge of approving a third Trump selection with 53 Republican Senators. Because the 2020 estimates are not provided, using the 2019 estimate gives 47.86 percent of the US population (stats taken from

This means that the third branch of government, which is supposedly set up to be non-partisan, will now be a 6-3 conservative majority that will inhibit progressive policies for decades to come.

Republicans have been playing this long game ever since the Southern Strategy. Their gerrymandering, voter suppression, and relentless focus on the judiciary has laid the groundwork for their minority rule.

Is it any wonder why democratic participation is so low? To gain a majority, liberals and progressives need to win far more than 50 percent of the vote. Our two party system has led to a shrinking of the Overton Window to the point where the choice is between two slightly different flavors of neo-liberalism, leading to even more feelings of hopelessness from the electorate.

We must put a stop to this pattern of minority rule. We need a blue tsunami in November, and the politicians elected need to have the willingness to put democratic rules in place to level the playing field and allow for a true democratic republic to emerge.

Here are a few of the things I'm hoping that a Democratic government will accomplish in 2021:

  1. New federal law requiring bi-partisan/non-partisan groups to draw district lines to combat gerrymandering
  2. Ranked-choice voting to stop negative partisanship
  3. An expansion of the House to match historical representation
  4. Add the US territories and Washington D.C. as states to give millions of Americans Senate representation
  5. Publicly fund elections and reverse the disastrous Citizens United decision that gave corporations and the rich an out-sized political influence
  6. Remove the filibuster to eliminate gridlock in Congress so that citizens can elect politicians based on their actions rather than rhetoric
  7. Eliminate the Electoral College to elect the President based on the popular vote

Those seven steps would drastically re-shape American politics and create a true democratic republic. The will of the people would finally be represented for the first time in the 200+ years of the American Experiment.

We spent so much time and energy to prevent the tyranny of the majority that we left a huge hole that the GOP and their minority views have exploited brilliantly. Their bad-faith gamesmanship has deeply damaged our democracy, and we really only have one election left until they permanently entrench their power.

We all must vote in this upcoming election. Another round of Republican leadership will only further minority rule in this country, since they will once again be in power to continue the gerrymandering and judicial appointments that will keep our country from making progress on the biggest issues of our time. Women's rights, climate change, worker's rights, and more are all in limbo. Without a progressive push-back, our country will continue its decline into a corporate oligarchy, and our standing as a world influencer will crumble to dust.

Bye Bye Twitter

I did it!

I deleted Twitter. I had wanted to do so earlier, but ever since the great Twitter hack of 2020, they had disabled the ability to export your data (which is a violation of the GDPR, by the way; what I wouldn't give for decent privacy laws in the US...).

It feels a bit weird. I've had a Twitter account since 2008. It's something I still got value out of in 2020, unlike Facebook, which I happily jettisoned a while back. But I don't trust Twitter with my data, and I don't trust myself on their platform. I used it in a reactionary way, which involved a lot of screaming into the void about how ridiculous our world is.

I'm planning on using Mastodon going forward, but the smaller community and lack of fucktards like Trump on the platform means I'll be able to truly use it as a micro-blogging platform. That will be much healthier for my brain and I'll be able to deliver more value to any followers I manage to gain since I'll be more thoughtful about what I post. In addition, Mastodon has much better data portability and is completely open source. I could (and maybe will) spin up my own instance and still be able to connect with the larger fediverse.

I'm sure I'll still pop onto Twitter occasionally when I see a link to something interesting on Reddit (one of the last major social media vices I still have), but no more random, reactionary tweeting for me!

It's toots from here on out.

Join the fediverse yourself and give me a follow!

One-on-Ones: How Regular Mentoring Can Boost Your Career Growth

When I started my first real job out of college, I had no idea how to operate in the real world. A university education does very little to prep you for the realities of the business world, even if you were like me and graduated with a business major.

My first year as an IT consultant was rocky. While I had 17 years of school under my belt, the skill I perfected most during that time was learning how to get good grades (as opposed to learning for learning's sake). I was proud of my grades and my test scores. I assumed I would jump into the business world and hit the ground running. But instead I ran headfirst into a brick wall. I had all this information in my head but no idea how to actually apply it!

I continued to struggle to the point where I had a mental breakdown at work, in front of some of my co-workers and the client. I didn’t know it at the time, but I was struggling with depression. And while I did know about my severe anxiety, I lacked the tools to properly manage it.

Throughout my whole life I ignored both my anxiety and depression, pushing it deeper and hoping it would just take care of itself. Impostor syndrome crippled me to the point where I would hide in my cubicle, paralyzed with fear because I couldn’t figure out how to get my work done.

I probably would’ve been placed on a performance improvement plan after much longer, but (as embarrassing as it was) I firmly believe that mental breakdown saved my job. After seeing my struggles boil over, my team realized that I needed help. While my team did many things to help me at that difficult time in my life, the biggest positive change was making a simple addition to my schedule:


Soon after my breakdown, I began to meet with a senior developer on my team. He is a great guy who truly cares about helping others, and he delicately helped me work through transitioning from school to work. We started meeting weekly to talk about how things were going on the project, where I was in my career development, and how I was doing with life in general. We made concrete plans to help me complete my work and grow my skills, and we developed a set of emergency protocols that I could use whenever I started feeling overwhelmed.

It worked brilliantly. A short 30 minute session every week was all it took to change my trajectory and turn me into a solid contributor. I still struggled for far longer than I’d like to admit, but simply knowing that somebody else had my back and cared about my development gave me the hope and energy I needed to improve my skills and finally learn to work in the “real world”.

After that, I made sure that one-on-ones were a part of every team I was on, and by doing that I was able to find the mentorship I needed to make it through the early stages of my career. Even six years into my career, I deeply value my regular one-on-ones, both from the mentor and mentee perspectives. They are an indispensable tool for personal and team growth!

While not all your co-workers will be dealing with problems as extreme as the ones I faced, my story is meant to show just how powerful one-on-ones can be. They can take your team to the next level by helping everyone improve themselves and their work.

If your team isn’t conducting regular one-on-one meetings, you’re missing out on an incredible enabler that will create a better workplace environment, increase your team’s performance, and help each individual reach their potential.

As a consultant I’ve been on a wide variety of teams. In my experience, the happiest, most productive teams all held regular one-on-one meetings. This article will cover (1) why one-on-ones are important to your team’s success, (2) what typically happens during a one-on-one, and (3) how to get one-on-ones started on your own team, whether you are managing others or not.

Why One-on-Ones?

One-on-ones strengthen bonds by increasing the amount of communication you and your teammates have with one another. In the normal flow of business, many of the conversations we have with our teammates are regarding the specific tasks we need to accomplish that day. While those conversations are important in their own ways, what’s typically lacking in the average person’s daily communications is a deliberate forum for praise, constructive criticism, and meaningful dialog.

Sitting face-to-face (or screen-to-screen for remote workers) and having an uninterrupted conversation with another person is a powerful experience. Group conversations are fun, but how often do you do a deep dive into your hopes and dreams in front of a crowd? In order to be vulnerable, we have to feel like we can trust the person we’re talking to. Establishing trust takes time, and it’s often easier to do in conversation with a single person. Regular one-on-ones are a deliberate practice crafted to create a space where truths can be spoken and where meaningful dialog can occur.

That’s not to say that every one-on-one is an intense, soul-searching endeavor where you pour your heart out to a co-worker. Most aren’t! But the regular practice of meeting with your teammates builds stronger relationships so that when the need for a deep conversation arises, it can take place in an environment of trust and support.

Once trust has been established, you can have candid conversations with your co-worker. You can go over your concerns with the direction of your project, give each other constructive criticism, and discuss career aspirations.

What Is a One-on-One?

While there are many different formats for one-on-ones, I personal strive to touch on these three areas:

  • How is the person feeling about their current work?
  • What are their career aspirations?
  • Who are they outside of work?

The first two topics allow people to discuss information about their past, present, and future work life. If their current work isn’t ultimately benefiting their desired career path, this is an opportunity to express that concern and make plans for change. It's also a great time to get help on immediate problems that are blocking your ability to finish your work in a timely manner.

The third topic helps build trust by getting to know them on a more personal level. It’s amazing how little you sometimes learn about a person even if you’ve sat next to them for years. Giving people space to share their passions helps them be seen as a whole person, not just a cog in the machine. In addition, sharing your whole self gives people more opportunities to find common ground and develop a deeper connection and friendship.

These meetings should be long enough to allow for substantial conversations. I typically schedule one-on-ones once a week for 30 minutes. The frequent cadence allows for quick turnaround with any questions and a shorter feedback loop for sharing constructive criticism. However, depending on the needs of your particular team, you could use a variety of schedules. I’ve been on teams where one-on-ones are every other week, once a sprint (if you’re working in an Agile environment), or even once a month. The further apart the meetings are, the longer each meeting should be. Don't let meetings slip any further than a month though, since they're more likely to completely disappear from the calendar and they won't become a habit.

One-on-ones are also opportunities to meet with people at different levels in the company. I've found it helpful to have less frequent — but still regular — one-on-ones with people a few levels above or below you in the organization. I meet with my manager’s manager about once every six weeks. This gives me time to ask higher-level questions about the overall direction of the project I’m working on and valuable face time with people I don’t necessarily work directly with on a day-to-day basis.

How to Start Having One-on-Ones in Your Own Team

If you’re a team lead, it’s pretty easy to start the practice of regular one-on-ones with your team. Send out a few calendar invites and you’re off and running! Make sure to set the context for why a new meeting has taken up their precious time. If you need inspiration, touch on some of the points in this article to help your team understand the importance of one-on-ones.

If you aren’t responsible for others on your team, it’s a little more difficult to start as a team-wide practice, but you can request meetings with your managers and start a personal practice. Encourage your teammates to do the same, and talk to your manager about making it a team practice!

Once you have regular meetings going, do your best to not let them slip off the calendar. Often, one-on-ones become the first meetings cancelled when things get busy, but always try to reschedule instead of completely cancelling them.

In addition, consider which person should own the invite. I like to own my one-on-one invites since they're some of my favorite work meetings so I make sure I never miss one! But if you're prone to ignoring your calendar, ask the person to keep track of it and pester you when you start missing them.

You should seek out one-on-ones with someone who has more experience than you, ideally your direct manager. This gives them a platform to coach you regularly, reducing the likelihood of any surprise feedback on your yearly review. If there are problems with your behavior or areas in which your teammates are hoping you’ll grow, you can receive that feedback here.

Being open to frequent feedback facilitates a culture of mentoring, as people begin to realize that hearing feedback is not an attack on one’s character. In fact, it’s a sign that your teammates care about your professional development. They want to see you grow and succeed!

Finally, look for ways to be both a mentor and a mentee, even if you're a junior member of the team. Everybody has things to learn from and to teach others, so one-on-ones with peers can also be a wonderful experience.


One-on-ones will dramatically change your team's dynamics. By regularly meeting with teammates to discuss current concerns, future career goals, and life in general, you'll forge deeper relationships that will help you work better together. These meetings will help you make friends, see new perspectives, become better at your job, and give you a little break from your day-to-day work.

If you have any other one-on-one strategies that I missed here, please reach out! I love learning new things and adding to my one-on-one toolbox.

This is the fourth of nine articles delving into the processes that every effective development team should use. Stay tuned for more!

Automated Testing Save Lives

Automated testing saves lives.

It's a fact. And not only for software engineers building rocket software for carrying folks to Mars or controlling nuclear reactors. By automating your testing, you will literally save yourself and your teammates precious hours in our short lives where we don't have to chase down regression bugs.

And if you're not testing, you shouldn't call yourself a software engineer.

One huge difference between programming and software engineering is the testing.

A "programmer" is someone that just needs the thing to work. Once it's working, they move on to shiny new problems (at least until something breaks). I am often in a programming mindset when I write software for fun, since nobody depends on what I write and I'll probably get bored of it in the next week or two. That's a programming mentality. And there's nothing wrong with that! There are tons of situations where programming is all that is needed, but when you're getting paid to develop software you need to be a software engineer.

And software engineers write tests.

Why Are Tests So Important?

Let's say you were a construction worker building a high-rise apartment, where you often dangled over ledges to get bolts and beams into place. If your company forgot to provide you with a harness, tether, and safety net (or even actively told you that you didn't need them), you would likely be scared to do your job. You'd play it safe, maybe leaving some of the far-reaching bolts a little loose since a proper tightening means climbing out to the edge with nothing to protect against a fall.

Tests are your harness, tether, and safety net. They give you an automated way to encode business rules, protocols, and other standards into your codebase and allow you to check that you haven't broken anything accidentally.

Having a suite of tests allows you to code with confidence. You can make improvements to the codebase when you see opportunities without the need to do extensive manual regression testing. You can try new programming patterns or technologies and refactor to your heart's content. The freedom to experiment and improve your existing codebase leads to growth in your technological prowess as you discover new ways of working.

In addition, testing saves money. Sure, they take "extra" time to implement and run, but the benefits far outweigh the costs. Computers are really good at doing the same thing over and over. That's a perfect fit for checking that the existing state of your application won't break with your new changes! Plus, once you have a test suite in place, it's incredibly cheap to run them many times a day. Compare that to the cost of manual testing, where a human takes longer and is less accurate in reporting the results or covering all cases.

That's not to say that humans shouldn't be testing your software. You absolutely need a great squad of folks that ensure the software quality remains high, but they are the last line of defense and should be focused on the higher-level concerns of usability, accessibility, perceived performance, and other "softer" metrics that can make a huge difference for the end user.

Testing allows for a more frequent release cadence, which gives your team a chance to quickly test your new code and make changes in response to new information and requirements. If you have a well-designed test suite and everything passes, the likelihood of catastrophic failure to release the new code drops substantially.

Finally, tests lead to better written code with clean interfaces. When your tests are a consumer of your code, you have to put a little extra thought into what those boundaries look like. You're able to decouple your codebase into stand-alone pieces that can be shared with others, which can easily be swapped out for better technology in the future. In addition,

Alright, now that I've ranted about why testing is important, let's get into some specific tools. This article covers the Jest and .NET testing tool sets, but the overall principles can be applied to pretty much any technology.

Unit Test Framework Examples

In general, tests follow this pattern:

  1. Arrange your test data
  2. Act on the function being tested
  3. Assert that the result matches the expected output


Jest is a widely used JavaScript/TypeScript testing tool and is built into the create-react-app tool.

By convention, test files in JS/TS projects are named like: [file_being_tested].test.ts

Here's a simple test from a router.test.ts that tests the addSearchParams in the router.ts file. The addSearchParams function builds a URL from the provided parameters and values.

describe('router tests', () => {
    test('addSearchParams adds param', () => {
        // arrange
        const testUrl = '';
        const testParams = 'Param1';
        const testValues = ['1'];

        // act
        const result = addSearchParams(testUrl, testParams, testValues);

        // assert

Let's break it down by the Jest-provided pieces:

  • describe - An optional function for labeling your test sections, displayed on the CLI when running tests
  • test - The actual test that will be run
  • expect and toBe - Jest helper functions that run the assertions for the test (there are tons more, like toBeTruthy, toMatchObject, etc.

The addSearchParams function is a good one to test because it has a single job and a clean interface. By writing a test like the one above, we can fearlessly refactor and improve the internals should the need arise!

In fact, the need to refactor the method did arise when I added this test:

test('addSearchParams adds param with list', () => {
    const testUrl = '';
    const testParam = 'Param1';
    const testValues = ['1', '2', '3', '4'];

    const result = addSearchParams(testUrl, testParam, testValues);

When I ran that test, it failed! For some reason, the result looked like ${testUrl}?{testParam}=1&2&3&4!

After taking a peek at the addSearchParams function, I noticed that the delimiter between parameter values was using an & instead of a ,. The & would signify an entirely new URL parameter, which is not how the function should behave.

This particular function had been around for a long time, but nobody had caught this bug. After a bit of searching the codebase, I did see that a few developers had been passing in an optional third parameter called delimiter using the ,, so they had seen the problem and solved it by fixing the inputs instead of addressing the root cause.

Before I went crazy with new code to fix up the function, I decided to add a few more tests that covered all the edge cases involved with building a URL that I could think of. Once those tests were in place, I confidently started refactoring the function until they all passed!

Once everything was passing, I could say with confidence that my changes had materially improved the codebase and the developer experience. I didn't need to boot up the application, spend five minutes getting to the specific web page that used the function, and then testing things manually. All of that ceremony was removed, and with the test suite in place I could quickly iterate on a solution instead!

I ended up adding 50+ tests over the next week and found even more bugs around edge cases. But now with the tests in place, it's easy to check that they will keep behaving far into the future!

Jest is a great tool. It just works and has fantastic documentation. If you're working with the create-react-app or really any other JavaScript/TypeScript project, I'd recommend you consider it for your testing framework. Give the official documentation an afternoon, and you'll be up and running writing all kinds of tests!

Microsoft Testing Tools

If you work with .NET, there are a ton of testing frameworks to choose from. The default tools from Microsoft are solid, so we'll take a quick peek at what that looks like:

public class BlobStorageServiceTests
    [TestCategory("PDF Tests")]
    public void GetSignedApplicationPdf_Test()
        IBlobStorageService svc = new BlobStorageService();
        byte[] bytes = null;

        string _samplePackageId = "3b2c8766-2706-40c7-b46c-911047996c2c";
        bytes = svc.GetSignedApplicationPdf("MyApplication", _samplePackageId);
        Assert.IsTrue(bytes.Length > 10000);

        string _sampleEnrollmentId = "01086456694P07302019";
        bytes = svc.GetSignedApplicationPdf("Medicare", _sampleEnrollmentId);
        Assert.IsTrue(bytes.Length > 10000);

The unit test pieces are:

  • [TestClass] - Indicates that the class is used for testing, and the testing tools will automatically find and include it
  • [TestCategory] - A human-readable tag to group multiple tests together
  • [TestMethod] - Marks a single test
  • Assert.IsTrue - One of the many Assert functions to check your test results. Others include Assert.Fail, Assert.Equals, Assert.IsNotNull, etc.

This particular function being tested returns a PDF from cloud storage. We're not touching on the technical details of mocking inputs in this article, so just assume that the BlobStorageService doesn't need to actually talk to the internet to fetch the PDF.

Notice how similar the process is compared to the Jest tests? It's the same process, just with a little more pomp and circumstance that a typed language like C# demands.

I don't have a story about successfully adding more tests and fixing bugs in this particular codebase, but that's because the 1000+ unit tests are currently broken. Those are thousands of tests represent dozens (if not hundreds) of hours put into building that impressive safety net. They could be helping check for errors when making changes to the code base today, but instead those tests have been left to decay over the years and are at a point that a major refactoring would be needed to fix them all and reintroduce them back into the build pipeline.

That's why you should never remove your tests from the automated pipeline. If you refuse to let broken tests get merged into your codebase in the first place, you'll never lose the hours of work that were put in to build the test suite in the first place!

How to Approach Your Work with a Testing Mentality

A test-first mentality leads to cleaner, reusable interfaces with your code. While you don't need to go full-on Test Driven Development to be effective, simply considering how your code will be tested leads in better outcomes.

When I need to write new code, I tend to do the following:

  1. Break the problem down into small, single-purpose functions (ideally ones that don't mutate state)
  2. Get those functions working, with unit tests proving it
  3. Compose those smaller functions together to solve the problem
  4. Write more tests demonstrating that the larger function works as expected
  5. Compose the larger function together with other pieces of the application
  6. Repeat until everything works

I've found it easiest to work from the backend out to the UI layer, following the pattern of smaller, easily verifiable functions that together solve a larger problem. Breaking things down into manageable chunks allows you to lessen your cognitive load as you move further up the stack (meaning, towards the user-facing interface). As you build each piece and test it, you can be more confident that the higher level solutions will work properly. Now, that's not to say you shouldn't be doing integration or end-to-end tests, but if you unit test and encapsulate your logic smartly, the odds of any one thing breaking too badly decreases.

I'm sure you'll find your own cadence regarding how much testing you need to work through problems and how you write your code. Just like writing in spoken languages, each person has their own style and approach when they talk to their machines through code! Experiment and find what works best for you!

How to Create a Culture of Testing on Your Team

Now the hard part. When I was on my very first project out of college in 2014, we spent about a month fixing hundreds of broken unit tests. They had previously been taken out of the build process (or potentially had never been part of it at all), so the tests got ignored and atrophied over time. It hadn't been a requirement to have a working test suite before moving on to the next feature, but our team was determined to change that. Five years later, I've found myself back on the same project again, only to discover there are over a thousand tests that no longer function.

As a consultant (i.e. an outsider) I can't just add tests and hope that they keep running in perpetuity. It takes buy-in from the developers and leaders who actually own the codebase, and without out it, those tests will be left to rot. You can't just say "unit testing is important" and expect a culture of testing to pop up overnight.

The best way I've found to get teams to care about testing:

  • Start small. Don't try to fix a 1000+ unit test repository in a Sprint
  • Integrate testing to any new initiatives from the very beginning
  • Add those working tests to the build process
  • Don't allow the test step in the build process to be bypassed for any reason
  • Encourage developers to add tests when reviewing their Pull Requests
  • Start a grassroots approach on your team and continually talk about the importance of tests
  • Ask your leadership to push the importance of testing from the top down
  • Track metrics on the types of bugs that come up (regressions vs new) to show that regressions go down as testing increases
  • Push for more sophisticated testing once you have a good unit test suite in place

What's Next?

There are many different dimensions to testing. This article has focused on the technical details of unit tests, but the general principles apply whether you're doing end-to-end, integration, UI, performance, accessibility, or any other kind of testing.

If you use JavaScript and want a fantastic overview of the different types of testing and when they're appropriate, check out (Disclosure: Kent is a friend of mine.)

As always, please reach out to me if I've completely bungled something or you have even better ideas to add! I'm always looking to learn and grow, so drop me a comment in my guestbook or find me online!

This is the fourth of nine articles delving into the processes that every effective development team should use. Stay tuned for more!

Git Hygiene

Git is an extremely powerful tool used to track changes in files, particularly source code. It's enabled software development to advance substantially over the last couple decades, and a majority of software developers use it on a daily basis.

That said, many developers don't have a good grasp of the tool. They understand the basics, like branching, merging, and committing, but when you start to reach deeper into the toolbox, git trips up many people. This leads to a sub-standard use of the tool, and it completely locks out some of the most useful features that we should be using to take care of our code bases.

This article is meant to provide some ideas on how to improve your git workflow, listed in an order that you can slowly introduce to your team without too much change at any one point:

  1. Standardize your commit messages
  2. Rebase locally instead of merging
  3. Version your software with tags
  4. Use a defined branch management methodology
  5. Squash broken or insignificant commits
  6. Use git hooks

I'm sure there are other ideas that aren't listed here, but I've found these to be extremely useful in both my personal and professional coding practices.

Let's get started!

Standardize Your Commit Messages

Let's face it. We've all written a poor commit message. I personally have a ton of "fixed bug", "arrrgh", "it's working!", "kill me now", and other useless commit messages in my past. When working on personal projects, this usually isn't a problem. But as soon as you start collaborating, all of those vague, frustrated messages do nothing to help your teammates understand the types of changes being added to the code base.

Since I don't like to reinvent the wheel, I have been using Conventional Commits as a personal standard for all my commits, and I've been working on introducing it to my teams at work. If you don't have a good sense of how you want to structure your team's messages, I'd recommend starting with Conventional Commits. It's used by a wide variety of teams and I have never felt at a loss for words in my commit messages based on the conventions it provides.

That said, the exact convention doesn't really matter. What's important is that you have a standard. You can keep it simple, or even get fancy and use emojis. Once you pick one, encourage your team to follow it!

A good commit message, combined with other steps in this article, will allow developers to look at the git history and grasp what types of changes have occurred. It provides useful historical data that can be extremely helpful when tracking down bugs, on-boarding new teammates, or automatically generating release notes.

Committing to a standard is an easy change to make on your team. It doesn't require any fancy technologies, just a conversation and commitment from your team!

Rebase Locally Instead of Merging

Once I pulled up the git history of a repository and 15 of the top 30 commits were all merges of the dev branch into various feature branches. This was a repository used by a large team, so every day we'd ship new features to the dev branch. All the developers would then merge those changes into their branches so they had the latest code.

Keeping your local repository up to date with the remote one is an excellent practice! But when your git tree becomes nothing but merge conflicts (which are themselves generally poor commit messages), it becomes impossible for developers on the team to read those excellent commit messages your team recently started writing!

Instead, encourage your teammates to pull new changes from the remote repository by doing a rebase.

rebase can be scary, especially for newer developers. I didn't dare touch them for the first few years into my career, because you can really screw things up compared to the simplicity of a merge. That said, rebase is a powerful tool for keeping your git history clean. If you need a primer on rebase, check out the official git documentation to get familiar.

Once everyone gets into the practice of using rebase, your commit history will be much cleaner, and the only merge commits you'll have are those involved in promoting one branch to another (depending on what type of branch management methodology you use), making it even easier to understand how code is moving through your branches or environments!

Version Your Software with Tags

Another powerful tool that I often see underused is tags. Tags are a simple way to describe a specific commit. You can use them to label your software versions, keep track of a problematic commit, automate your releases, and anything else you can come up with. They're extremely flexible and, most importantly, unchanging (unlike branches).

My favorite use is tagging software releases. SemVer, CalVer, build numbers, or even an incremental count will help you deploy and keep track of your releases. Versioning your software is a great way to reduce confusion on what versions your developers, testers, and users are using. You can even get tags set up as part of your build pipeline to make the release process less of a headache!

Use a Defined Branch Management Methodology

Everyone has a branch management methodology, whether you've put thought into it or not. Sometimes, these methodologies have carried over from previous version control software. Other times it's evolved over time to serve the needs of your team. Regardless of what methodology you use, you should make sure that it's written down and that your team understands the process. If you're having a tough time with merge conflicts, a proliferation of branches, or other issues with your git workflow, I'd recommend checking out at least the following methodologies:

Simply reading about other ways of organizing your branches will help you craft the best one for your team. Personally, I've been happy with both GitFlow and GitHub Flow on past teams, but GitLab Flow is intriguing and I'll likely give it a shot someday!

Once you've got your methodology in place and your team is actively working with it, you can pair it with your CI/CD pipeline (and tags) to further automate your release process!

Squash Broken or Insignificant Commits

A fantastic way to keep your git history clean is to use the squash command. squash allows you to mush multiple commits into a single one.

Good developers are in the habit of committing early and often. Those frequent commits save you from losing work if the crazy refactoring idea you had doesn't turn out to work so well. If you had made a commit to save your work before the refactor, it's easy to jump back to a working state without losing anything!

However, by the time you've finished writing a new feature or squashing that bug, your git history likely has a variety of commits, some which may break the build or your tests. Those commits are not very useful to you and your teammates won't care about them either.

That's where squash comes in! The big caveat when using squash is that it rewrites history. All those commits become one shiny new commit, complete with all the messages of each commit in the message body. The new history can really trip up your teammates if they happen to be working off the same feature branch as you. Ideally, sharing branches doesn't happen often, but sometimes you gotta do what you gotta do to ship that feature or bug fix.

If you know that nobody is using your branch, it's safe to push that new history and overwrite your long chain of commits. But be careful about it, otherwise you'll end up with some upset teammates.

My favorite way is to leave the squashing until the very end. Your CI/CD tools should be able to squash your PR on merge, which results in a single commit full of all that tasty goodness you finished being delivered to the main working branch for your teammates to enjoy!

squash and rebase together lead to a more readable history, as every remote commit has a deep level of meaning. Every commit either ends up delivering new functionality or is an easily identifiable merge to help you track code as it moves through your environments.

Next time you've got a new feature you're developing, give squash a try! It really is a life-changer.

Use Git Hooks

Finally, we arrive at hooks.

Hooks allow you to step into the git life-cycle and run arbitrary scripts. Those scripts live in the .git/hooks folder of your repository, and it's likely that there are some example ones sitting there for you to check out right now! The great part is, you can use whatever scripting language or tooling you want. While many of the hooks I've seen are bash scripts, you are free to choose whatever language fits the workflow and skill-set of your team.

One caution with hooks: these run locally, so your teammates could disable them easily if they get annoyed with the process. It takes strong buy-in from the team to successfully use hooks, but once everybody is on board they are an excellent tool.

There are a lot of great tutorials out there on how and why to use hooks, so I'd recommend you check them out, but the most useful ones I've seen or used are the following:

  • pre-commit
  • prepare-commit-msg
  • commit-msg
  • post-commit


The pre-commit hook is an excellent spot to run your tests, linters, and code analysis tools. If any of those fail, you won't be able to commit! This hook helps ensure that everything being pushed to the remote server at least doesn't break things or degrade the readability or quality of the code.


The prepare-commit-msg lets you modify the commit message, allowing you to use a standardized message format. We've already covered why good messages are important. This hook encourages teammates to stick to those standards.


The commit-msg hook runs after the commit message is provided. This is a great place to check that the story or bug number is included in the message, or that your teammates actually adhered to the standard template provided with the prepare-commit-msg.


The post-commit hook lets you decide what to do after a successful commit. You could automatically deploy the changes if the message contains release:, send a notification to the team notifying them new changes are available, or anything else you come up with.

There are even more hooks to explore! Go wild, and automate all the things!


I've thrown a lot at you in one article, especially if any of these git concepts are new to you. For a quick review, I've suggested that you consider introducing these practices into your team's workflow in the following order:

  1. Standardize your commit messages
  2. Rebase locally instead of merging
  3. Version your software with tags
  4. Use a defined branch management methodology
  5. Squash broken or insignificant commits
  6. Use git hooks

Your team may be more comfortable introducing some concepts sooner than others. Use this article as a guide, and choose the workflow that works best for your team! No team is the same, so no workflow will fit all use cases.

I'm sure there are some amazing ways to use git that I don't know about or completely ignored, so I encourage you to do your own learning and research when deciding how to set up your version control system. And if you find better ways of doing things, please let me know! I love learning about new features or ways of doing things, which is why I share them in the first place.

Good luck with wrangling your team's git workflow! It's well worth the effort.

More COVID Diaries

It's been about a month since I moved to Utah and wrote about the whole pandemic thing that's currently consuming the world.

Life is pretty good. I chill in my parent's basement most of the time, doing daily walks around the neighborhood and the occasional bike ride in the mostly bike-friendly city of South Jordan. I do miss the hustle and bustle of the city. I think I visibly see maybe 2.5 people on an average day out here in the suburbs, so it's lonely in a different way. I'm glad to not be in my apartment all by myself (and my dog), since I now have my mom and dad around, and my brothers pop in every week or so.

As for the state of the world, COVID still spreads unchecked in the United States. Arizona, Florida, Texas, and Georgia are particularly infected. And for whatever reason, we've started to test less, while still having many states in the 5 to 10+ percentage range for positive tests (a metric that indicates we don't have it under control).

While other countries have been able to open up a fair bit of their businesses and recreation, the US is still struggling mightily. I don't think we'll be "back to normal" until we get a vaccine, since nobody seems to be taking the precautions seriously. I've seen it first-hand. I've been to family events with 20+ people where I'm the only one wearing a mask and where everyone but me was hanging out inside. Utah isn't doing nearly enough to encourage its populace to wear masks, social distance, or reduce gathering sizes. The only thing saving Utah at the moment is that it's a sparsly populated state, so transmission rates are numerically low, (but just about average on a per capita basis).

On top of it all, the Post Office is under attack, with sorting machines being removed and delivery times increasing. Without universal mail in voting this November, people will have to literally risk their lives to exercise their human right to democratically elect their leaders. With every passing day, Trump slips further towards fascism as he attempts to keep hold of his power. It's scary shit.

So personally, things are good. Nationally, we're still pretending like we have things under control.

Again, I'm completely embarrassed to be an American. We're a world leader in stupidity, especially when it comes to COVID.

Here's hoping my next update contains a bit more good news.

RIP Mozilla

Mozilla, one of my favorite non-profits and a staunch defender of Internet freedom and privacy, has just gutted themselves.

Laying off 250 folks is a huge chunk of the company, and entire teams have been let go. From what I've seen from Mozilla employees on Twitter, that includes the following teams:

  • Servo - Their new web browser implementation that ultimately led to the Quantum update in 2017
  • MDN - One of the best web developer resources on the Internet
  • DevTools - My favorite tool for developing and debugging websites
  • Threat Management - Reviewing and preventing major security threats in the browser and add-ons will become almost impossible

I had always dreamed of working for Mozilla someday. The folks I follow on social media, blog posts, and other Mozilla-related spaces were some of the most forward thinking and intelligent individuals in the tech space. But with this change, I'm scared the Mozilla I knew and loved will never be the same.

We truly live in the darkest timeline. 2020 feels like whatever god-like being is playing their version of the Sims with our world decided it was time to increase the difficulty and see what happened. Mozilla is just one of the many, many casualties this year.

Fixing Install Errors for On Ubuntu

Every time I try to install on one of my Ubuntu machines, I run into the same error:

/usr/bin/ld: cannot find -lpq

It always takes a bit of time to remember how to fix it, so I'm throwing this on my blog for future reference.

👋 Hey future me, it looks like you're trying to do some Rust programming with Diesel again. Cool! At this point though, you might want to consider moving off of Ubuntu. These problems are annoying!

But, until that day, just do this:

apt-get install libpq-dev

You're welcome.

One Simple Thing: Stop Using So Much Air Conditioning

Holy hell people, tone it down with the AC.

After moving to Utah, I've been freezing every day, regardless of what building I'm in, despite the outside temperature being 10+ degrees hotter than Seattle on average. Seattle hardly has any AC, and while I sometimes complain about it, I'm so much happier without our stupid human construct of "room temperature".

People are addicted to 72 degrees.

While that's a nice temperature when you're in long pants or multiple layers, it's absolutely chilling when you wear normal summer close, like shorts, a t-shirt, and no socks.

I have to sit underneath a blanket in the middle of summer because of the dumb AC.

AC is energy intensive. Our energy is dirty. Trying to achieve a 20+ degree differential between the inside and outside of your home is absolutely insane.

If we tried to live with our environment instead of molding it to our every whim, we'd be able to save energy, feel more closely connected to where we live, and be able to wear summer clothing inside during, you know, the summer.

So run over to your AC unit and bump it up to 76 or even more. Get our your lightweight clothing, and enjoy feeling the warmth of summer. Pop open some windows and create a cross breeze. Get a nice fan and bring it around the house with you if you get too hot.

But don't try to make your entire home "room temperature". You're wasting money, contributing to the death of our Earth, and are totally missing out on the joy of never wearing socks for months at a time.

The One Thing: Stop Using So Much Air Conditioning

One Simple Thing: Build an Emergency Fund

If you're one of the zero people who avidly read my blog, you'll have noticed that I had to move in with my parents thanks to pay cuts from COVID-19 causing an economic downturn.

In one day, I had to pay my lease cancellation fee, book an expensive moving truck, and pay taxes.

Needless to say, it was an expensive day.

The only reason I got through it without loading up on credit card debt or taking a personal loan was thanks to my emergency fund! If you're not familiar, an "emergency fund" is a highly liquid and accessible pile of cash that is only to be used in the most dire of circumstances. Things like your car breaking down, a surprise trip to the vet, or even a pandemic that is ravaging our people and economies.

Most experts recommend having three to six months worth of your average monthly spending sitting in a savings account. That can be a daunting number to achieve, but it's possible! If you throw a small amount at it every single month, it will eventually begin to fill up and one day you'll look back and be amazed at the safety net you've built for yourself.

If seeing that pile of cash is too tempting, I would recommend making a account with a new bank or credit union, ideally one with a high interest on their savings account. That way, it's a little bit more difficult to get to, since you're not seeing the money mixed in with your regular accounts. But since it's in a savings account, the money is still available to be withdrawn at a moments notice when a true emergency hits.

I made the mistake of neglecting my emergency fund for years. I was focused on investing money, and a big pile of cash seemed totally counterproductive to wealth-building. I was lucky enough to not get hit by any emergencies during that time, and thankfully I started building up my fund a few months before COVID really took a chunk out of my finances.

Don't be like me. I got very lucky. If you're throwing money into investments without at least one to three to six months worth of spending in an emergency fund, you're on thin ice. You might end up in an okay situation. But the world is random, and you never know what will happen.

So, if you don't have one yet or your emergency fund is underfunded, start today! I use Ally for my fund, but there are lots of online banks out there with great rates. Grab an account, set up an automated transfer every couple weeks, fund it with any extra cash you might have, and start sleeping better at night!

The One Thing: Build an Emergency Fund

My Privacy-focused Apps

Over the last few years, I've made a concerted effort to find open-source tools that focus on protecting user privacy.

It's an ongoing journey. As you'll see, I'm still working through replacing some applications (and even operating systems).

This post lists out the tools I'm currently using, both so I can keep track of it for myself and help other privacy-conscious folks find software that values their privacy!

Cross Platform Applications

These apps work on all my devices, which is a big reason why I love them!

  • Firefox - Web browser, replaces Chrome, Safari, Edge, etc.
  • Signal - Messaging, replaces SMS, WhatsApp, Facebook Messenger, etc.
  • Standard Notes - Writing, replaces Microsoft Word, Evernote, OneNote, etc.
  • Bitwarden - Password manager, replaces LastPass, 1Password, Dashlane, etc.


  • Linux (Ubuntu) - Operating System, replaces Windows or MacOS
  • Thunderbird - Email Client, replaces Outlook and other email clients
  • VSCodium - Text editor, replaces VS Code, or any other developer-focused editors
  • Vim - Text editor, upgrades your ego, replaces all text editors (I'm still learning Vim so I rely on Codium a lot)
  • Krita - Drawing software, replaces Paint, etc.
  • GIMP - Image editor, replaces Photoshop, etc.
  • Inkscape - Vector software, replaces Illustrator, etc.
  • LibreOffice - Office software, replaces Microsoft Office, etc.
  • Audacity - Audio editing, replaces Garage Band, etc.


What's Left To Replace

  • Android - I like the Librem 5 phone, but it's still a little soon for me to grab one. In the meantime, I'm planning to install LineageOS.
  • Goodreads - I don't need Amazon tracking my every read, but I haven't found a good replacement yet. I like Calibre, so I'll move there eventually, but it's not open source so that's a mark against it.
  • Google Maps - I've downloaded OsmAnd, but I don't naturally reach for it yet.
  • Moodpath - Tracks my anxiety/depression. I haven't found a good replacement yet.
  • Google Keyboard - The swipe technology is just too good and I haven't found a good replacement yet. They only send telemetrics, but still. It's Google.
  • Strava - Exercise tracking. I've downloaded OpenTracks, but I don't naturally reach for it yet (and I haven't gone running in ages).
  • YNAB - Budgeting software. I pay for it, so according to their privacy policy I should be okay. I'd love to move to an open source app, but I haven't found a good replacement yet.
  • Prey - Phone location software. I need to look into their privacy policy, because this is one I haven't thought about in ages. I don't know of any open source apps that will let you find your phone when you lose it.
  • Todoist - My todo software. I pay for it, so I'm less inclined to look elsewhere, but I do want to find a good open source version, especially if I can pay them to support it and provide a syncing mechanism.