• Were I the God-King of Twitter

    I don’t want to write this.

    I thought I could burn this draft once the Twitter acquisition was signed.

    …but Twitter is my favorite social media site. No where else can you interact with minor celebrities like you can on Twitter. I’ve gleaned more knowledge from random programmers I don’t follow on Twitter than I have from conferences.

    …and someone else’s bad opinions to monetize Twitter leaked from their drafts.

    First, Twitter needs to make more money off of their current user base. It’s been stuck at 300 million active users for as long as I can remember. They’re not growing their ad revenue anytime soon. One problem is most people are poor. Millenials haven’t recovered from the 2010 recession, and we’re already jumping into the next one. Twitter needs a way to monetize users while ensuring the experience mostly remains free.

    Every day I see public figures begging for a blue checkmark from Twitter support. People want something. It’s exclusive. It’s obvious. Charge for the blue checkmark. People give you proof of a government ID and $5 a month and they join the protected class. Twitter can still gift blue checks to journalists, politicians, and other users at-risk of impersonation.

    Give blue check users additional controls to limit how other users interact with their tweets and everyone will want to be a blue check. Imagine celebrities stopping harassment by only allowing blue checks to quote tweet, retweet, or reply to their tweets. Blocks mean something now: no more coordinated harassment campaigns chasing users off Twitter.

    A common form of spam is a blue check changing their username and profile picture to match a celebrity and then promote scams in their comments. I think most of these accounts are compromised. If they aren’t charging $5 and having a user’s government ID is a huge

    Twitter is the only social network that allows porn and nudity on the platform (RIP Tumblr). Gate nudity with the blue check mark. You get additional revenue from users making money on your platform and you get proof the user is of age.

    Next, segment your users.

    Celebrities and small businesses need multiple people to manage their account. Sell that. There are startups that offer that feature. Those startups should not exist. Account management should be part of your core product. I don’t know what’s reasonable, $30/month for five users to own an account?

    Do cable companies and airlines pay for their Twitter accounts? They should, at least $100k/year. If they’re using it as a support platform, they should pay. Add an Enterprise tier with everything they need, more users, a ticket queuing system, new APIs to connect it to Front, whatever they need.

    Lastly, the best innovations have come from outside the company. Give users better API access to Twitter and Twitter features. Let users generate their own API tokens and do whatever they want with it, as long as they’re paying for the blue checkmark. If they’re already paying you, do you care if they’re using a third-party Twitter client?

    I use a third party client. I wish I had polls and spaces, but the experience is too good to switch. Plus, I don’t see ads! Open up the API. Create a new version of the API every year. Developer momentum will not be slowed by supporting the last two years’ versions.

    So yeah, make me the god king of Twitter. I don’t want the job, but there’s no other tech company I care about this much.

  • Keep Ruby Weird 2018

    Programming (or writing or making art) is knowledge wealth building. Practicing your craft is compounding interest, and the best practice is to have a side project.

    Working on an application from inception to deployment teaches you so much more than you would learn at work. Your work projects are too big for you to master every part of the application. When the application is small, you can take the time to master every part from the authentication to the deployment.

    Keep Ruby Weird is a celebration of side projects that delight. None of these talks will make you a millionaire, but you’ll learn something. Maybe that something will help you on a future project. Maybe it will encourage you to start your own absurd side project.

    Opening Keynote - Yukihiro ‘Matz’ Matsumoto

    https://confreaks.tv/videos/keeprubyweird2018-opening-keynote

    2018 is the last Keep Ruby Weird, and they managed to get a talk from Matz. Did they have excess budget and need to spend every penny? Did they troll us by having a very normal conference talk at their weirdo conference? Who cares? You get to watch a talk from the creator of Ruby!

    Matz talks about how method hash arguments work in Ruby today and considers how they will work in the future. Nothing is set in stone, and they’re still taking comments/suggestions. If you want to learn about some weird edge cases for method hash arguments, this talk is for you.

    Distributed Fizz Buzz: Passing the Microservices Interview

    Skip it! This talk is an advertisement for the actual talk, which is a three day course on microservices.

    The Teenage Mutant Ninja Turtles Guide to Color Theory - Louisa Barrett

    https://confreaks.tv/videos/keeprubyweird2018-the-teenage-mutant-ninja-turtles-guide-to-color-theory

    Louisa explains the basics of color theory via Ninja Turtles. If you use colors but don’t know anything about color groups, what emotions are associated with which colors, how to get color groups from the color wheel, and what properties make up a color then this talk is for you.

    It’s a very introductory talk, but I still learned something. I had no idea how the properties of color worked.

    Game Show (Intermission)

    https://confreaks.tv/videos/keeprubyweird2018-game-show

    Skip it! The Game Show was fun in person, but it was filler. It’s not going to be as fun online.

    Using psql to \watch Star Wars And other silly things! - Will Leinweber

    https://confreaks.tv/videos/keeprubyweird2018-using-psql-to-watch-star-wars-and-other-silly-things

    Will uses the ascii version of Star Wars to explain the Postgresql \watch command. The \watch command is like a tail for your query. It reruns the query at some specified interval and displays the output. Combine \watch with a Postgresql function and a counter, and you’re watching Star Wars!

    Then comes the step up. Will uses ffmpeg to render Star Wars as emoji characters. He even hooks up his Mac’s webcam to ffmpeg to render live video of himself as emoji. It’s an utterly delightful moment.

    If you like Will’s talk, check out his talk from Keep Ruby Weird 2015. They’re both must sees.

    Cats, The Musical! Algorithmic Song Meow-ification - Beth Haubert

    https://confreaks.tv/videos/keeprubyweird2018-cats-the-musical-algorithmic-song-meow-ification

    Beth sets out to write an application that takes a song as input and returns the same melody but sung by cat meows.

    Extracting the melody from a song automatically is really hard, and she doesn’t get that part working. Instead she outsources the task to an online melody extractor. Even that extractor is terrible.

    This is a good talk to watch Beth encounter setbacks and work around them. There are compromises and work arounds, but she gets it working. The payoff? A cat rendition of the Game of Thrones theme.

    Using Ruby to build a modern Memex! - Andrew Louis

    https://confreaks.tv/videos/keeprubyweird2018-using-ruby-to-build-a-modern-memex

    Andrew obsessively catalogues every detail about his life. To categorize that information, he creates a Memex. The Memex was a thought experiment from the 1940’s by Vannevar Bush. He wanted to organize data by associations. For Andrew, that means being able to look up every podcast he listened to on a road trip three years ago.

    I want this. I want a personalized search engine for my life.

    The most impressive part is he’s using Ruby on Rails and Postgresql. I expected him to be using a Graph Database, which is almost a Memex. Graph Databases are super super new, meaning they’re all still pre-1.0 and unreliable. This is a friendly reminder that Rails and Postgresql are still incredibly powerful.

    Andrew wants to share his Memex but doesn’t know how. He’s unsure about opensourcing it. He never mentions it, but users of opensource have entitlement issues. There is an emotional cost to fielding support and feature requests. The DigitalOcean Marketplace would be perfect for his Memex. He could build a 1-click, only need to support one version of the OS, Rails, and Postgresql, and share it with people without outsourcing it.

    Transcendental Programming in Ruby - Yusuke Endoh

    https://confreaks.tv/videos/keeprubyweird2018-transcendental-programming-in-ruby

    Yusuke is an MRI contributor who’s side project is quines. A quine is program that prints its own sourcecode. If you can speak Japanese, Yusuke wrote a book about them.

    Quines are simple to write in Ruby. This example is from the wikipedia article on Quines. Represent your program as a string and eval that string.

    eval s="print 'eval s=';p s"

    Simple, right? Nope, nope, nope. Yusuke shows off some absurd quines.

    This talk was on the weirder side of Keep Ruby Weird. Definitely check it out.

    Closing Keynote - Avdi Grimm

    https://confreaks.tv/videos/keeprubyweird2018-closing-keynote

    Avdi Grimm, of Ruby Tapas fame, starts his keynote as a discussion about the roots of Object Oriented Programming and how the world misunderstood objects and methods in OOP. Alan Kay’s original description of OOP is more similar to the Actor model and Functional Programming than it is to modern OOP. Avdi iterates all of the problems with object messaging and how it’s broken.

    Avdi realizes that the same problems with OOP messaging apply to his life. He’s so laser focused on accomplishing a checklist of goals, that he postpones happiness and doesn’t enjoy the journey.

    The second half of his keynote is about being present and enjoying the moment. That focusing on the a goal at the expense of your day to day life isn’t healthy.

    Be content that your goals will take a decade to achieve. Savor the journey, especially with your family.

    Oh, and take more selfies.

    😎

  • Use Pointers in Golang Arrays

    In Go when I have an array, or slice, of structs, I prefer to always make that an array of pointers to the structs. You might want to do this so you’re not copying the entire struct every time you append to the slice. Using pointers is nanoseconds faster, but the real reason is developer ergonomics! It’s cumbersome to make changes to an array of structs.

    For example if you have the following struct.

    type Object struct {
    	Value int
    }
    
    func (o *Object) Double() {
    	o.Value *= 2
    }
    
    func (o *Object) String() string {
    	return fmt.Sprintf("{%d}", o.Value)
    }

    If you want to change the value of the contents of the array, you would instinctively write something like this.

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	array := []Object{
    		Object{
    			Value: 0,
    		},
    		Object{
    			Value: 1,
    		},
    		Object{
    			Value: 2,
    		},
    	}
    
    	fmt.Println(array)
    
    	for _, item := range array {
    		item.Double()
    	}
    
    	fmt.Println(array)
    }

    It won’t work. When you iterate over array, item is a copy of the struct that’s in the array. Any changes we make to it are scoped to our for loop.

    If you want to make changes to the array, you need to assign the updated struct to its index in the array.

    for i := 0; i < len(array); i++ {
    	item := array[i]
    	item.Double()
    	array[i] = item
    }
    
    fmt.Println(array)

    If you use pointers in your arrays, you don’t have this problem. The item variable is a pointer, and you can manipulate the struct directly.

    pointerArray := []*Object{
    	&Object{
    		Value: 0,
    	},
    	&Object{
    		Value: 1,
    	},
    	&Object{
    		Value: 2,
    	},
    }
    
    fmt.Println(pointerArray)
    
    for _, item := range pointerArray {
    	item.Double()
    }
    
    fmt.Println(pointerArray)

    Here’s a Go Playground to play around with it.

  • Better Golang Errors With errors.Wrap

    Libraries shouldn’t log. Logging takes resources and should occur as rarely as possible. If an error occurs deep in your program, you don’t want to immediately log it, bubble the error up the stack, and then log the same error again but with additional context. Thus, you should try to log as close to the UI as possible. If you’re writing a web service, only log in the handler before you send a response. The code for accessing the database is a dependency and should be in its own package. We treat it like a library and only concern ourselves with its API.

    But… having more context would be helpful. Even though it’s wasteful, logging an error twice reveals more about the current code path when the bug occurred.

    One way to provide more context is to have very specific messages for each log line that are never repeated. For example…

    const (
      UnauthorizedUserLogMsg                string = "Unauthorized request"
      UnmarshallingRequestErrorLogMsg       string = "Error unmarshalling request body"
      JSONMarshallingResponseErrorLogMsg    string = "Error marshalling json response body"
      JSONAPIMarshallingResponseErrorLogMsg string = "Error marshalling jsonapi response body"
      DatastoreErrorLogMsg                  string = "Error returned by the datastore"
    )
    
    func (handler *Handler) CompaniesGetAll(resp http.ResponseWriter, req *http.Request) {
      companies, err := handler.Datastore.CompaniesGetAll(limit, offset)
      if err != nil {
        handler.Logger.Error().Err(err).Msg(DatastoreErrorLogMsg)
        http.Error(rw, "Internal Server Error", http.StatusInternalServerError)
        return
      }
    
      // Handle a normal response
      // ...
    }

    If the Datastore package is returning a Postgresql error, that error could have come from any request to the database in CompaniesGetAll, and the error messages from the Go Postgresql adapter are especially obscure.

    Enter github.com/pkg/errors, a package that lets you wrap your errors with additional context. Calling errors.Wrap(err, message) returns a struct that conforms to the errors interface where message is prepended to the error. Everytime an error is returned, you can add context to that error message.

    My preferred way to use errors.Wrap is to keep it concise. The message added should have the format “verbing noun”.

    var count int
    err := db.DB.QueryRow("SELECT COUNT(*) FROM companies;").Scan(&count)
    if err != nil {
      return 0, errors.Wrap(err, "querying company count")
    }

    Now your errors have more context AND you are not logging in your packages.

    1. I will allow an exception for packages that start their go routines that run alongside your app. If your package needs to log information, please please please let the user pass in an io.Writer. Most loggers support the io.Writer interface, so your user's can use their logging library and format. If your logger writes JSON and you use Datadog's tracer, error messages from Datadog aren't going to match your pretty formatted logs
    2. I wish there was a standard interface for logging that gave you log levels.
    3. Secret trick: if your apps performance is degrading, disable logging. Verizon disables logging when new iPhones launch to prevent themselves from being DDoS'd by thirsty Apple users.
    4. Zerolog, my logger of choice, lets you use Diodes, a ring buffer, for writing logs. If logs are written to Diodes faster than stdout can read them, logs get dropped until stdout catches up.
  • Interviewing Like You're Dating

    Interviewing and dating are strangely similar. I assumed they’d magically work themselves out without additional effort on my part! I kid… I kid…

    Expect to Be Rejected a Lot

    It’s inevitable, but being rejected is the only way to build up a tolerance to rejection.

    The Best Leads Are Through Your Social Circle

    I’ve never lived Patrick McKenzie’s scenario where the company has decided they’re going to hire you and the interview is just a formality. Having someone who’s worked with you refer you to a company lets you skip some steps. Sometimes it’s only the HR screening. Sometimes you jump straight to an onsite interview.

    Be Legitimately Interested

    This should be obvious, but 2008 Jim needed to learn this. Don’t apply to a company unless you’re interested. Every interview process is going to ask you why you’re interested in [company]. You should know before you apply. If you have to practice it in the mirror, maybe you shouldn’t be applying.

    Sometimes this will come up when they ask you how you heard about [company]. Once I was able to honestly reply that I read their engineering blog and fell in love. They rejected me.

    Alternatively, it is very very hard to answer this question if the real answer is that [company] uses my favorite tech stach, pays above market, and the people are decent human beings.

    Ask Questions that Start Conversations

    One sided discussions are boring. Both you and the interviewer want to ask questions that start conversations.

    2008 Jim didn’t have questions to ask companies. At my early jobs developers had no input on the tech stack or build and deployment pipeline. I was less engaged in interviews, and interviewers probably mistook it for disinterest.

    My current favorite questions are about testing and build pipelines. Having automated builds and deployment is more and more common. It might be a very boring question in five years.

    My ideal interview would be talking shop about interesting bugs and what crazy ways [company] is dysfunctional (Every company is in some way). Alas, here are the questions I actually ask. I try to split them up and not ask every interviewer the same question.

    Questions for the recruiter

    • What is the role?
    • How many employees?
    • Type of funding? Bootstrapped? What series? (You should know if they’re public)

    Questions for engineers

    • What languages/frameworks do you use? Why does it fit your use case?
    • Where do you store code?
    • How do you deploy?
    • How is work planned?
    • How do you monitor your app?
    • Who responds to downtime? Is there a run book? Pager duty?
    • If you could change one thing at [company] what would it be? (A polite way to ask “What do you hate?”)

    Questions for Managers

    • How do you measure success? Six months to a year from now how do I know I’ve met my goals?
    • How does your team celebrate victories? (It’s bad if they never stop to appreciate what they’ve done)
    • What does the career path look like?
    • What does a bad sprint/project look like?

    Questions for Everybody

    • What are you looking for in a coworker/employee?

    Questions someone asked me that resulted in a good conversation but I would never ask

    • What’s your most controversial thought?
  • New Job

    As of August 14th, I have a new job!

    Oops!

    I didn’t plan to find a new job. I wanted to start my own company and was going to stay put until I could start my own thing. A friend talked me into applying for a tech lead position at his company. I had the qualifications, and it would have been a huge promotion. I applied for other jobs, but I didn’t think any of them could beat this.

    It was my first onsite interview, and I bombed it.

    Doh!

    My first onsite had only one technical interview. They asked me to model what happens when a user buys an SSL certificate. They didn’t say it explicitly, but they wanted a sequence diagram. I didn’t know what that was. I thought they wanted me to design a system, so I started mapping out services.

    My solution was way too complicated and confusing. I can blame my nerves, but I spent all of my prep-time reviewing Cracking the Coding Interview and working Leet Code’s interview questions. The question was new, so I was unprepared. Bombing this question helped me prepare for later interviews.

    I regret that my first choice was my first onsite.

    What Now?

    If I hadn’t applied to other companies, I would’ve mourned my lost free-time and given up on interviewing for another year. Instead, I doubled the number of applications I had, and continued studying in my free time.

    Job Hunt Stats

    95 days
    38 jobs applied for
    17 responses
    6 onsites
    14 rejections
    2 offers
    1 process ended once I accepted an offer
    

    Other Details

    Homework Is a Crapshoot

    Every company judges homework differently.

    I spent a week working on a homework assignment for [data metrics company] only to be rejected for doing the bare minimum. They purposefully left the scope vague to see if a candidate would go above and beyond.

    Another homework assignment I wrote in two hours and emailed it to the recruiter with notes on what I would improve if I had more time. It was good enough to skip a technical phone screen and jump straight to onsite.

    No One Thinks Twice About Your Interview

    I’d heard that interviews matter more to you than the company interviewing you. I didn’t expect to have hard proof. I ran into two people one to two weeks after they had interviewed me. Neither recognized me or remembered my interview once I brought it up.

    One exception was an interview I had with a CTO. He interviewed me when he was the VP of development at a different company. He remembered me. I should’ve asked if that was a good thing or a bad thing. 😅

    I Love My New Job

    It’s only been two weeks, but I love my new job. It’s 100% remote, and most of my team is remote. The team is brand new built to implement a killer new product. I couldn’t be more excited.

  • Fixing a Postgres Type Casting Bug With Regex

    Today I learned how to fix a type casting bug in our Postgresql script with regular expressions. This deserves celebration! Details below.

    The Problem

    We have a database table that matches data to other tables based on a specific column. The values for the column are provided by the user and stored as strings. Depending on the table being matched, the values can be strings or numbers. If the user submitted bad input for a number match, accidentally including characters in their match column, the query fails.

    The code handling the input was exactly the same for every match column type. I didn’t want to add a special case for this. The problem was in the query, so the fix should be in the query.

    The Solution

    Update: I subscribe to Andy Croll’s Ruby newsletter. He suggests using \A and \Z to match the beginning and ends of a string because ^ and $ will match the ends of a line. If your string has newlines in it, it will be accepted by the regex.

    Postgres has regular expression match operators. We can update our query to check that a value is a number.

    -- Example query
    SELECT *
      FROM list_of_things lot
      WHERE lot.value ~ '^[0-9]+$' AND lot.value::BIGINT = 12002;

    The ^ operator matches the regular expression to the start of the string and the $ matches to the end. By combining them with [0-9]+ we check that every character in the string is a digit.

  • The Little Things Make Me Love Apple

    My brother was visiting and wanted to connect his iPad to our wifi. Because he’s in my contacts, I didn’t have to tell him my password; I just hit a button on my Mac.

    It’s very inconvenient for my guests to type my super long wifi password. (All of my passwords are song lyrics with random characters.) I didn’t even know Apple had this feature, and it’s made my guests’ visits smoother.

  • Apple Has to Become GE

    Apple discontinued their wireless router. They absolutely should have, but it’s a shame. The Airport Express was terrible. If you used it for a Time Machine backup, everyone else’s internet connection would stall. Unplanned automatic backups would knock my roommate off of World of Worldcraft and cause Youtube videos to stutter. It was embarrassingly bad and missed the trend of having multiple access points. Eero should never have happened.

    Peak iPhone is going to be a thing. Even if Apple was successful enough to sell an iPhone to every person on earth, they would hit peak iPhone. Investors don’t want stable, consistent returns. They want growth! Apple needs to grow its product line. It’s going to turn into G.E.

    Ignore the Homepod, which is failing because Siri is terrible. Selling more products to your current customers is the best strategy.

    Wait. What the fuck am I talking about. The Homepod might be the best product no one buys. It costs $50 more than the Bose Soundlink I bought in 2013 and has reviews comparing it to a $50,000 speaker? I… want that. Hell, I want Apple to design the power cables and other boring parts of my home appliances.

    I want to live in a world where Apple is making my toaster oven.

    1. Apple will never sell everyone a phone. People's taste are too different, and some people don't like Apple for forcing its tastes on you.
    2. I love that a failed product for Apple would be a huge success for any other company.
    3. I don't own a toaster oven. They're all terrible.