Does your company have crazy white boarding interviews where you’re expected to recite the curriculum of ivy league computer science programs? Your company probably has a deep existential fear of hiring someone who doesn’t know how to code.
Does your company spend most of the post-interview aghast that the candidate said he read trashy romance novels for fun? Your company is probably most afraid of hiring a bad culture fit.
What would it look like if your company was afraid of someone interviewing for the sole purpose of using your offer to get a raise?
I don’t know.
I had a weird interview experience, and this is the best explanation I have. The CTO and Director of Engineering both got really excited when I mentioned that my manager knew I was looking for a new job. I wish I had asked about it. It completely changed the tone of an interview that felt lukewarm.
Today I learned how to fix a type casting bug in our Postgresql script with regular expressions. This deserves celebration! Details below.
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.
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.
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.
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 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.
I was interviewing recently and we discussed ways to improve my TicTacToe code. Here’s version two!
A bunch of the improvements were insignificant. The entire diff can be viewed here.
I thought I knew about this when I first wrote TicTacToe. If the parent object of a case class is sealed, all match statements need to include every case. If every case isn’t covered, the match will throw a compile error.
We’ll never need an instance of the parent class, so we can make the Player a trait.
The player types, X and O, don’t need to hold a value, so we should use a case object instead of a case class. Case objects are singletons, so there is only ever one of them created.
When writing a library, you want to use the most generic type possible. We use an IndexedSeq instead of a Seq because the Range type inherits from IndexedSeq. For our TicTacToe board, no extra work is done to convert our board to an IndexedSeq.
Since we’re using an IndexedSeq instead of a List, we need to change how we check if a tile is empty or not. The syntax for decomposing a Seq is messy and I always forget it. We can use the isEmpty methods to check that the board space exists and that the board space is empty.
Rename nextPlayer to currentPlayer. I always confuse next Thursday and this coming Thursday. I don’t know why I thought nextPlayer was less confusing.
The old TicTacToe would calculate the game status every time Board.gameState was called. This is the most expensive part of TicTacToe. We definitely want to calculate the new status only once when we create a new state for the board.
One benefit of checking for victory when the user makes a moves is we only have to check the row, column, and diagonals for that move. We can ignore the entire rest of the board. We can split these checks into three different methods. Compare the new way of checking for a victory to the old way. The logic is simpler and we get to keep our immutable variables!
The TicTacToe game is recursive. We want it to be tail recursive, so it will reuse the same stack frame instead of indefinitely growing the stack. Our entire game logic is wrapped in a try catch block, but only the game.move method can throw an exception. Instead of using a lowercase try, we can use an uppercase Try, specifically a scala.util.Try. By wrapping our execution in a Try, we can assign it to a variable and use a match statement. Now our Try block has a clear execution path and always calls playGame in the tail position.
Today I learned that my broken dishwasher could have shown me the error codes. I would pay extra for a dishwasher that could connect to my phone just to see those codes. I don’t want to wait a week for the repair people. I want to order the part and fix it as soon as Amazon Prime delivers.
My first gen Automatic doesn’t reliably track my location anymore, but it’s worth keeping around for its error codes. There is no confidence like walking into a repair shop already knowing what’s wrong with your car.
People love when appliances are repairable. If smart appliances told you what was wrong and how to fix the wrong, they’d be loved too.
I really hate installing Java on my personal machines, but I still want to develop Scala. Part of the Docker promise is that you develop on the same environment as your production environment. Let’s actually set that up.
Add this alias to your $HOME/.bashrc file. Reload your bashrc, and the sbt command will run the docker image in your current directory.
What if you want to serve html from a random directory? Create another alias for the Apache docker image! This works great for any code coverage libraries that output to html.
There’s too much information to consume. We need to be tactical about advice we take. Why give any of your time to someone horrible?
“But, Jim”, you say. “If the person is giving good advice it doesn’t matter whether or not they’re a bad human being.”
Do you really want to be that person’s editor, searching for the good content in the bad? Whatever good advice you find is aligned with their philosophy. If you don’t agree with their philosophy, you’re going to need to hear that same advice from multiple people before you can trust it.
For instance, why is James still in the news? Who is taking his advice?
I don’t remember where I first heard of him, but I realized his advice wasn’t for me after reading a profile on him that I can’t find. (I’ll never find the original article. His SEO game is on point) There are two stories I distinctly remember. When James’s first child was born he would wake up early and go hide in a coffee shop. I can find some proof of this story in this Mixergy transcript. James is very proud of the second story. He secured a funding letter of intent for an idea without the implementation or the ability to ever implement it. He then negotiated a deal to buy a company in that idea-space and used that company as an asset to raise money.
All of his takeaways are wrong. In both stories the true moral is lost on him.
"Kids who play video games do better as adults"  summarizes the studies that show you should let kids play as many and as much video games as they can stomach 👍 https://t.co/DUNg0pJ7K4— DHH (@dhh) February 9, 2018
I agree that that play time limits are dumb, but Penelope Trunk isn’t the best person to take advice from…
At work I need to move an application to Kubernetes, but some of its logs are necessary for user usage data and tracking ad impressions. Setting up rolling logging from our container to AWS S3 looked more complicated and risky than our current setup, so we didn’t even investigate it. Other applications at the company use Amazon AWS Kinesis. It made sense to do the same. I wrote a code snippet to push log messages to Kinesis via an Akka Stream. I could get everything working in the REPL except for the part that pushes to Kinesis.
I tried to use kinesalite, an application which implements AWS Kinesis, but there aren’t any guides for getting it up and running. I assumed you would just start kinesalite, point your Kinesis endpoint at localhost with the right port, and it would just work. I did that, and nothing happened. No error messages, no kinesalite log messages, nothing.
It took way too long (two days) to figure out how to write to kinesalite by….
Below is my example code to write to Kinesis. It creates an Akka Stream to which you can send messages. I tested each part of the Akka Stream in the Scala REPL.
Either the AWS Java SDK requires credentials (my bet) or Kinesalite requires credentials even though it doesn’t care what those credentials are. Create a $HOME/.aws/credentials file with the below contents.
This was the last step I completed to get Kinesalite working. Neither the AWS Java SDK or Kinesalite showed a single error message when trying to connect to Kinesis without authentication credentials.
You need this to setup Kinesalite.
I didn’t know you had to do this. Ops created our staging and production streams. I expected Kinesalite to accept requests for any stream, but I guess it behaves exactly like AWS Kinesis.
Run the AWS CLI tool with the following parameters. It is super sensitive to typos. I copied and pasted from examples without any noticeable spelling errors. The only messages it will give is something like “–stream-name is requires”
The first command creates your stream. The second command lists all existing streams.
In your REPL, send something to Kinesis.
Two parts to reading what has been pushed to Kinesis. First you need to find the shard iterator to read data from the stream.
Once you have the shard iterator, you can read all of the records since that iterator. Replace the –shard-iterator with the one in your output.
Your record is a base64 encoded string. The following scala snippet will decode it back to what you pushed to Kinesis.
Sending a Kinesis request for every log message is inefficient. There’s an Akka Flow called groupedWithin that lets you batch your requests by either a number of elements or a timeout. If you don’t reach the element limit within your timeout, groupedWithin will flush your batch. Even better there is groupedWeightedWithin which lets you specify a weight. Kinesis has a 1MB limit for its payloads, so we can batch our requests until we get close to 1000000 bytes.
We can’t use groupedWeightedWithin. Our application is still running on the Spray web framework. The latest Akka it supports is 2.4. The groupedWeightedWithin function wasn’t introduced until Akka 2.5.1. We’ll have to wait until we upgrade our application to Akka HTTP before we can use it.
If we kept our libraries up to date, we would have access to groupedWeightedWithin.
Written while watching tv for Phoebe’s work’s secret Santa. Recorded for next year.