Howdy!
Today we’ll be talking about
We also have a solution to our last Microsoft interview question and a new question from Facebook.
Shopify is a tech company that helps businesses build e-commerce stores. If you want to build an e-commerce store to sell your handcrafted guitars, you could use Shopify to set up your website, manage customer information, handle payments/banking and more.
Jeremy Cobb is a software engineer at Shopify, where he works on the Contact Center team. They’re responsible for building the tooling that helps Shopify’s customer service team deal with all the support inquiries from businesses that use the platform.
He wrote a great blog post on how his team uses Terraform for configuration management. Terraform is an open source tool that lets you configure your infrastructure using code.
Here’s a summary
The Contact Center team builds the tooling that Shopify customer service agents use to handle support requests.
One tool the engineers rely on is Twilio’s TaskRouter service. Twilio is a company that builds programmable communication tools, so you can use Twilio’s API for sending emails, text messages, etc.
Shopify uses Twilio TaskRouter to handle routing communication tasks (voice, chat, etc.) to the most appropriate customer service agent based on a set of routing rules. For example, users in the US might get sent to a different customer service agent than users in Canada.
Previously, Shopify would configure these routing rules using Twilio’s website. However, the complexity of the rules grew and it became too much for a single person to manage.
Having multiple people manage the rules quickly became troublesome because the website doesn’t provide a clear history of changes or way to roll changes back.
In order to solve this, the Contact Center team decided to use Terraform to manage the configuration of Twilio Taskrouter.
Terraform is an open source tool that lets you write code to manage/configure your infrastructure/tooling. You can write the code in JSON or in a Terraform-specific language called HashiCorp Configuration Language (HCL).
In order to use Terraform to manage your infrastructure, you need 3 things.
So, Twilio TaskRouter provided a reliable API that the Shopify team could use to manage their rule configuration.
There was no TaskRouter Terraform Provider available at the time (Twilio has since developed their own) so the Shopify team built one themselves.
The Provider defines how Terraform should manage Twilio TaskRouter. It contains resource files for every type of resource in TaskRouter that Terraform has to manage; each resource file has CRUD instructions that tell Terraform how to manage it.
The Provider also has import instructions that let Terraform import existing infrastructure. This is useful if you already have infrastructure running and want to start using Terraform to manage it.
The Shopify team also built a client library that the Terraform Provider would use to make HTTP calls to Twilio’s API.
Using Terraform
With Terraform set up, Shopify could stop relying on Twilio’s website for configuring TaskRouter rules and instead write them using HCL (Terraform’s domain specific language).
This made seeing changes to the infrastructure much easier and allowed Shopify to integrate software engineering practices like pull requests, code reviews, etc for their TaskRouter rules.
It also allowed non-developers to start configuring rule changes themselves. Business and support teams could write rule changes in HCL and create PRs instead of making a request and waiting for a developer to log onto Twilio’s website and change the config manually.
For more details on how Shopify created the Provider and on how they use Terraform, you can read the full article here.
Quastor is a free Software Engineering newsletter that sends out deep dives on interesting tech, summaries of technical blog posts, and FAANG interview questions and solutions.
Deepu Sasidharan is a developer at Okta. He wrote a great blog post on programming safety and why it matters.
Here’s a summary
When you’re talking about safety in programming, you’re primarily talking about three things
When you access a variable/array in a memory-safe language, it will check to make sure that you are indeed accessing what you meant to access.
Memory-unsafe languages (like C and C++) do not provide built-in protections against access/overwriting data in other parts of memory.
This can lead to tons of different kinds of hairy bugs/exploits like
And many more.
Memory safety issues are the cause of most security vulnerabilities encountered.
If you look at the stats,
In a type-safe language, the compiler will validate types while compiling and throw an error if you try to assign the wrong type to a variable.
On the other hand, a language with poor type safety will not run these checks and will also do unintuitive things when you combine multiple types (JavaScript’s type coercion gives a ton of examples).
A lack of type safety can lead to tons of bugs at runtime that are hard to diagnose.
In a thread-safe language, you can access or modify the same memory from multiple threads simultaneously without worrying about data races (where the behavior of your program changes depending on which thread changes the memory first).
This is achieved using things like mutexes, thread synchronization and more.
Deepu then discusses how Rust addresses all of these safety issues.
Read the full blog post for more.
Write an algorithm that searches for a target value in an m x n integer matrix.
The matrix will have the following properties
As a refresher, here’s the previous question
You are given the root to a binary search tree.
Find the second largest node in the tree and return it.
Solution
The brute force solution there would be to just do an in-order traversal of the tree.
Then, when we have a list of all the ordered nodes in the tree, we can just return the second largest element in the list.
This solution takes O(n) time and space. Can we do better?
We can!
Let’s say the problem said find the second smallest node in the tree and return it. How would we do that? Well, we could just quit our in-order traversal once we’ve visited two nodes!
However, our problem statement is the second largest node in the tree. So, how can we modify our inorder traversal to solve this variant with the same approach?
We reverse our inorder traversal!
With inorder traversal, we
We’ll reverse it! In a reverse in-order traversal, we
In a Binary Search Tree, reverse in-order traversal will give us the nodes sorted in largest-to-smallest order!
Now, we can just quit once we’ve processed two nodes and return the second largest node in our tree.
Quastor is a free Software Engineering newsletter that sends out deep dives on interesting tech, summaries of technical blog posts, and FAANG interview questions and solutions.