<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Logan McDonald</title>
    <description>The latest articles on DEV Community by Logan McDonald (@logan).</description>
    <link>https://dev.to/logan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F37522%2Ff145f4ed-d00e-49db-9305-a9ea00f96135.png</url>
      <title>DEV Community: Logan McDonald</title>
      <link>https://dev.to/logan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/logan"/>
    <language>en</language>
    <item>
      <title>Slack dorking for the win!</title>
      <dc:creator>Logan McDonald</dc:creator>
      <pubDate>Mon, 03 May 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/logan/slack-dorking-for-the-win-ko6</link>
      <guid>https://dev.to/logan/slack-dorking-for-the-win-ko6</guid>
      <description>&lt;p&gt;A while back I was on the &lt;a href="https://devpods.herokuapp.com/podcasts/devdiscuss/episodes/28"&gt;DevDiscuss podcast&lt;/a&gt; to talk about being an SRE. At some point I made a comment about a pet peeve of mine: When folks post screenshots of some error they are seeing to Slack. I wanted to take some time to expand on that and talk a little bit about how I use Slack to explain why.&lt;/p&gt;

&lt;p&gt;Slack is one of the most powerful logging systems I use. When investigating an error or incident, I’m probably using &lt;a href="https://slack.com/help/articles/202528808-Search-in-Slack"&gt;Slack search&lt;/a&gt; as a first move. Often I’ll find the error we’re seeing in the backlog of our chats and it often leads to valuable clues — “oh something similar happens every thrid Monday of the month???” When I find past mentions of the bug or error we’re currently seeing, I have a load of context to give me even more clues. Who worked on this last time? What was the content of the conversation? Even if I can’t figure out what’s happening from the previous chat, maybe I can contact the people involved previously.&lt;/p&gt;

&lt;p&gt;Slack search is hugely helpful even if there isn’t something I’m actively trying to debug. There are search modifiers Slack provides that can help us find information more easily. For example, say I’m looking for any documentation our team has on our Fastly SSO because I need to add a new user, and I know that historically my teammate Steven has owned our integration with Fastly. Before pinging him, I can search &lt;code&gt;from:@steven fastly login&lt;/code&gt; in Slack. I’ve now saved myself and Steven some time!&lt;/p&gt;

&lt;p&gt;Other modifiers, aka “dorks”, I’ve found useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Searching DMs for a message someone sent me but I don’t remember who: &lt;code&gt;to:logan that thing&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Narrow your search to a channel or DM using &lt;code&gt;in:&lt;/code&gt; — probably my most common dork.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;before:&lt;/code&gt;, &lt;code&gt;after:&lt;/code&gt;, &lt;code&gt;on:&lt;/code&gt;, or &lt;code&gt;during:&lt;/code&gt; to do time based searches. For example, if you remember an incident from March but don’t recall what: &lt;code&gt;during:March in:opsalerts feature flags outage&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;has:&lt;/code&gt; to retrieve messages that have a specific emoji reaction. This is especially helpful if you also have any automation that adds emoji reactions to particular messages. For example we tag deploy messages with &lt;code&gt;:rocket:&lt;/code&gt; so I could search: &lt;code&gt;has:rocket in:infra on:5/1/2021 rig_controller_api&lt;/code&gt; to find anything that deployed mentioning that service on May 1st.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Like many organizations, my work has embraced a lot of ChatOps for organizing teams, incidents, and work in general. We send all of our alerts to Slack, work on RFCs, and keep a ton of our context there. With all that in mind, do you understand why screenshotting (i.e. destroying) context frustrates me 😬 ? I’ve actually gotten in the habit of describing what is in the screenshot in a threaded comment response when I see them, so at least now it is tagged with searchable content.&lt;/p&gt;

&lt;p&gt;I hope this post inspires you to help an operations engineer out and copy and paste your errors, or at least add as much context as possible when posting screenshots. You are doing your team and your future self a huge favor.&lt;/p&gt;

</description>
      <category>observability</category>
      <category>slack</category>
      <category>chatops</category>
    </item>
    <item>
      <title>What's your dream technical interview process?</title>
      <dc:creator>Logan McDonald</dc:creator>
      <pubDate>Wed, 02 Oct 2019 21:28:18 +0000</pubDate>
      <link>https://dev.to/logan/what-s-your-dream-technical-interview-process-3pn8</link>
      <guid>https://dev.to/logan/what-s-your-dream-technical-interview-process-3pn8</guid>
      <description>&lt;p&gt;We all know that the interview processes in tech can be pretty broken. But what's your dream process? Besides just being handed the job, obviously. What do you think would show off talents and skills necessary for the job you'd want and would be a fun and informative process for you?&lt;/p&gt;

&lt;p&gt;I'll start. This would be for an infrastructure engineering position at a mid-to-senior level. My dream process would conversation with recruiter + manager to gauge fit for the team. Then, a time-boxed &lt;em&gt;small&lt;/em&gt; code challenge in a language of my choice, anonymized. Then, I'd like to have a series of short-answer questions, also anonymous, that have to do with my specific field. This would be things like "Explain load-balancing", "In your experience, what are pros and cons of microservices", "How does an identity aware proxy work?" If it could be tailored to be resume, that'd be great!&lt;/p&gt;

&lt;p&gt;If I passed those, then it'd be an "on site" half day of 4-5 interviews with the team. I want to meet people I'd be working directly with and mostly doing deep technical dives into my past work and comparing it to their specific challenges. I'd also like to meet with leader of the org, either CTO or VP to ask some questions about culture. I don't want to do any puzzles not related to the job. I don't want to whiteboard unless it is for either party to explain the architecture of a previous project better. I want to prove technical skills by thoroughly talking through problems I've solved in the past, though I'm willing to bring code from those projects if necessary.&lt;/p&gt;

&lt;p&gt;So, what's your dream process? &lt;/p&gt;

</description>
      <category>discuss</category>
      <category>career</category>
      <category>interviewing</category>
    </item>
    <item>
      <title>How BuzzFeed’s Tech Team Helps Journalists Report On Technology With Authority</title>
      <dc:creator>Logan McDonald</dc:creator>
      <pubDate>Wed, 25 Sep 2019 19:26:47 +0000</pubDate>
      <link>https://dev.to/buzzfeedtech/how-buzzfeed-s-tech-team-helps-journalists-report-on-technology-with-authority-3acl</link>
      <guid>https://dev.to/buzzfeedtech/how-buzzfeed-s-tech-team-helps-journalists-report-on-technology-with-authority-3acl</guid>
      <description>&lt;p&gt;&lt;em&gt;Reporter: Is anyone around to take a quick look at some code on codepen and help me understand what it does?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This question — and many, many others like it — arose from an initiative called “The Tech + News Working Group,” a BuzzFeed News collaboration between reporters and nearly every role across the Tech department — including SREs, SWEs, data scientists and product managers.&lt;br&gt;
The BuzzFeed Tech team is afforded “7% time,” or half a day each week, to learn something new. For those of us on the Tech side of the working group, that 7% time is dedicated to bringing our technical expertise to the newsroom.&lt;/p&gt;

&lt;p&gt;A primary value of BuzzFeed Tech is fostering an experimental and collaborative workplace; One way that’s come to life is through the Tech + News Working Group. The foundation for the group was laid by former BuzzFeed Tech SRE &lt;a href="https://medium.com/@sricola" rel="noopener noreferrer"&gt;Sri Ray&lt;/a&gt;, who provided countless &lt;a href="https://www.buzzfeednews.com/article/azeenghorayshi/grindr-hiv-status-privacy" rel="noopener noreferrer"&gt;acts of support&lt;/a&gt; to the newsroom throughout his time here. Reporters began reaching out to people on the tech and IT teams to help understand terminology, dig into tips, or verify the security of a file they had received from tipsters. The partnership allowed the Tech team to learn from reporters and consider the wider implications of our work. In turn, as insiders in the tech industry, the newsroom benefitted from our tools and perspective while reporting on technology, security, and business stories.&lt;/p&gt;

&lt;p&gt;Like other award-winning newsrooms, BuzzFeed News has a dedicated &lt;a href="https://github.com/BuzzFeedNews/everything" rel="noopener noreferrer"&gt;data journalism team&lt;/a&gt; that uses data and programming to aid in their reporting. But a year ago, we realized that there is a place for the Tech team to help with reporting, too.&lt;/p&gt;

&lt;p&gt;We decided to expand and formalize our collaboration, with an open Slack channel that includes members from both our Tech and News organizations to support day-to-day consulting on stories and work on larger ongoing projects, along with a new mission statement:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Our mission [for the Tech News Working Group] is to act as an elevating force for the newsroom’s work through guidance and assistance using our technical skills. Our News team at BuzzFeed strives to shine light on the most important issues facing us today. Currently, this means a growing focus on the impact of the internet and technology on a range of topics covered by News. As a team of technical experts, we are uniquely equipped to assist in this realm.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F3390%2F1%2A9n31gtXJT7nb9JtxbZs0nw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F3390%2F1%2A9n31gtXJT7nb9JtxbZs0nw.png" alt="Tubeviewer article"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since then, we’ve worked with the newsroom to develop reporting tools, including a project called Tubeviewer which took us &lt;a href="https://www.buzzfeednews.com/article/carolineodonovan/down-youtubes-recommendation-rabbithole" rel="noopener noreferrer"&gt;down the YouTube rabbit hole&lt;/a&gt;. Through Tubeviewer, we found that the Up Next algorithm occasionally pushes users toward hyperpartisan videos that include divisive, conspiratorial, and sometimes hateful content. Tubeviewer simulates the viewing experience of real humans watching YouTube videos given a certain set of search terms. Turn it on, walk away, and come back to a full picture of your viewing experience. We’ve used tools like this to audit algorithms across tech platforms. We’ve also developed bots that send digests of patent information to Slack or collect data from filing systems like NYSCEF. We’ve developed patterns for doing network analysis through Wireshark and done visualizations for articles with the data.&lt;/p&gt;

&lt;p&gt;We’ve received hundreds of requests ranging from assistance with finding data from a website to explaining how authentication tokens are used:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Reporter: working on a story about token based authentication vulnerability in a video game that uses google/fb sign on — and looking for someone to comment on the limits/risks of using token based authentication in general&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sometimes we get requests for help with something that would require a lot of manual labor, were it not for a quick and easy tech solution:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Reporter: this is a weird request&lt;br&gt;
that i apologize for&lt;br&gt;
but can someone count the number of stories under this tag&lt;br&gt;
if there is an easy way to do that…&lt;/p&gt;

&lt;p&gt;Engineer: can do with JS, count the number of item-list classes&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When we created the group, we didn’t know how popular the channel would be, but these requests are a fun break from our day to day “real” work. Sometimes the Tech team gets way more invested in the answer to a question posed by a reporter than the reporter intended. Once, we spent an embarrassing amount of time trying to determine what software Jessica Simpson used to create the graphic for this tweet (loads of EXIF digging later, we still couldn’t figure it out and the reporter had completely moved on). In the end, we’ve helped contribute to a bunch of stories and scoops, and in doing so created a bond of trust amongst reporters and technologists across our organization.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Reporter: I credit this scoop to asking the group here, so thank you&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The mentality of a good engineer is similar to that of a journalist; both need to ask good questions and seek out accurate answers with persistence even when there might be bugs in a system. Over the past year, it has been fun and rewarding to build a stronger bridge between the News and Tech teams at BuzzFeed, and we only expect this work to continue. Through the collaboration, both teams thrive: members of the Tech team have the privilege of working hand-in-hand with journalists, while the newsroom is able to report on technology with more authority.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Original post was published on &lt;a href="https://tech.buzzfeed.com/tech-and-news-working-group-7dabaaa38e45" rel="noopener noreferrer"&gt;Tech @ BuzzFeed publication on Medium, September 4, 2019&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>journalism</category>
      <category>datajournalism</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Working with journalists makes me a better engineer</title>
      <dc:creator>Logan McDonald</dc:creator>
      <pubDate>Wed, 04 Sep 2019 18:47:27 +0000</pubDate>
      <link>https://dev.to/logan/working-with-journalists-makes-me-a-better-engineer-5db9</link>
      <guid>https://dev.to/logan/working-with-journalists-makes-me-a-better-engineer-5db9</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: If you aren’t very familiar with my place of work, BuzzFeed, you may not know that our newsroom, BuzzFeed News, produces fantastic journalism. This isn’t a post about proving that point, so if you are thinking “Heh, BuzzFeed? News?” please first &lt;a href="https://www.buzzfeednews.com/article/maggieschultz/buzzfeed-news-biggest-stories-of-2018"&gt;check us out&lt;/a&gt; 💖. Ok, read on.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I've worked at BuzzFeed as an SRE for over a year and a half. In that time, I've also worked with our &lt;a href="https://tech.buzzfeed.com/tech-and-news-working-group-7dabaaa38e45"&gt;Tech + News Working Group (TNWG)&lt;/a&gt; with BuzzFeed News. At BuzzFeed Tech, we have "7% time" to spend on any learning activity we choose, and I spend that time working with our newsroom. &lt;/p&gt;

&lt;p&gt;We created the TNWG to pursue a mission:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Our mission is to act as an elevating force for the newsroom’s work through guidance and assistance using our technical skills. Our News team at BuzzFeed strives to shine light on the most important issues facing us. Currently, this means a growing focus on the impact of the internet and technology on a range of topics covered by News. As a team of technical experts, we are uniquely equipped to assist in this realm.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Over the last year, we've consulted with journalists on a variety of stories, and even built tools that made a few of those stories possible. In one instance, we built a bot that watches YouTube based on a set of search terms and returns a report on all the data with all the data from its trip &lt;a href="https://www.buzzfeednews.com/article/carolineodonovan/down-youtubes-recommendation-rabbithole"&gt;down the recommendations rabbit hole&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While our mission and work concentrates on what the tech org can offer the newsroom at BuzzFeed, this post is about the ways the newsroom has helped make me a better engineer. I have had the privilege of observing our reporters at work and many of those lessons carry over to my job as an SRE.&lt;/p&gt;

&lt;h2&gt;
  
  
  Communication communication communication
&lt;/h2&gt;

&lt;p&gt;When it comes to explaining complicated topics succinctly and clearly, no one has a harder and higher risk job than journalists. Often it takes our reporters just minutes to notice a breaking story and write a polished 200-word take. In these moments, they’re deploying years of hard won experience and skills. Furthermore, what’s impressive about these communication skills is that they’re balancing responsibilities among multiple reporting desks (breaking news, tech, politics, etc.) while also ensuring they meet a rigorous level of journalistic standards and ethics. The risks are far more acute than those we face on the engineering side, where colossal disasters do not generally ruin careers.&lt;/p&gt;

&lt;p&gt;As an SRE, I'm often in a similar situation, except we face time-sensitive issues across products. If an incident happens, we have to notify a host of interested parties and we have to do it in a consistent and responsive way. When facing an incident, journalists have taught me to: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear out extraneous noise &lt;/li&gt;
&lt;li&gt;Quickly identify the point people necessary to solve our problem, and &lt;/li&gt;
&lt;li&gt;Practice our communication skills and communication plans in advance &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Skills gleaned from my pals in news have helped make me and my team get better at communicating calmly, clearly, and efficiently. We work to maintain a shared language as a team, and an understanding of what we'll do if something unexpected happens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Research is a long game
&lt;/h2&gt;

&lt;p&gt;The best journalists are world-class researchers, and furthermore, expert open-source intelligence (OSINT) analysts. I've picked up lots of tips and tricks from talking to reporters about how they search for information online. When it comes to OSINT, engineers have tips and tricks of our own. Sharing these insights with one another has brought TNWG members great joy whether it’s explaining to reporters how they can run an OSINT software on their own through Docker or a journalist flagging a vulnerability in our system that they saw through their research.&lt;/p&gt;

&lt;p&gt;The main lesson I've learned from the newsroom is that research is a long game. Not every story is going to work out, and many of the leads I've seen our journalists pursue have turned out to be dead ends. Thankfully, our news team tends to be quite good at recognizing a dead end and avoiding the &lt;a href="https://www.behavioraleconomics.com/resources/mini-encyclopedia-of-be/sunk-cost-fallacy/"&gt;sunk cost fallacy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In my experience, we on the tech side of the TNWG seem to have a harder time halting effort in the face of unlikely returns. A reporter will come to us with a question and we'll run with it. We'll answer the question, get invested, and keep pursuing the angle. Soon after, the reporter will realize we’re at a dead end and move on to another question or story, but there are often engineers still doggedly looking at the question days later. I've learned from journalists that when a trail runs cold, it’s better to turn around than drive down the road of diminishing marginal returns. Document what you've learned and where the trail went cold, and move on.&lt;/p&gt;

&lt;p&gt;We struggle with this immensely in our software projects. You get really invested in a piece of technology or a certain solution that it feels like there is no way to move forward unless you are on that path. This is not true. There's always another solution, another technology, and learning how to admit the trail's run cold is an immensely valuable skill.&lt;/p&gt;

&lt;h2&gt;
  
  
  Just talk to people
&lt;/h2&gt;

&lt;p&gt;Possibly the hardest thing to imagine myself doing when I watch reporters work is that actually talking to people, like, on the phone. Reporters are constantly talking to contacts within governments and companies, keeping in touch with sources, or chatting with other reporters through text, in person, on the phone, etc. All the time. When digging into an issue with a reporter, the first time they said, "Well, why don't we just ask them if this is what's happening" I thought, "Wait, you can do that?"&lt;/p&gt;

&lt;p&gt;Working with journalists has helped me come out of my shell a little bit in terms of my willingness to talk to people. It has also impressed upon me the importance of maintaining good relationships with everyone I meet in the tech community. I try to be kind to everyone regardless, but I think this impressed upon me the value of networking, especially in open source communities. While reporters are often seen as antagonistic or single-minded, good reporters know how carefully they have to treat relationships with their contacts and potential sources. Similarly, in the software world someone is far more likely to help you fix a bug or solve an issue if they know you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Striving for truth isn't finding answers, it's asking questions
&lt;/h2&gt;

&lt;p&gt;This is by far the most important thing I've learned. When looking into any given lead or scoop or topic, it begins with asking questions and more questions and more questions. Often the best reporting is just putting questions out there – why is this technology monetized this way, who funds this campaign, why was person X here at this time, why is the court system set up this way in the first place? I've seen reporters ask questions that I would never think to ask. These questions don't always uncover surprises or elicit confessions, but sometimes they uncover something where no one thought to look.&lt;/p&gt;

&lt;p&gt;As a developer, a reorientation towards questioning is crucial. It often uncovers more bugs than a straightforward read of a pull request, for example. It leads to more creative solutions for tough problems. It pulls me out of biases towards certain technologies. It makes it easier for everyone in the room to understand what's going on. Focusing on the questions and coming up with the most creative questions makes your team more imaginative.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally, working with journalists gives you Range
&lt;/h2&gt;

&lt;p&gt;I recently read David Epstein's book Range: Why Generalists Triumph in a Specialized World. In the book Epstein argues that by generalizing and studying many different ways of working, we set ourselves up for success in our specialty. From the book:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Modern work demands knowledge transfer: the ability to apply knowledge to new situations and different domains. Our most fundamental thought processes have changed to accommodate increasing complexity and the need to derive new patterns rather than rely only on familiar ones. Our conceptual classification schemes provide a scaffolding for connecting knowledge, making it accessible and flexible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is why I love working as an engineer on a platform that supports non-engineers. I get to talk and work with people who do things very differently from me every day. There is so much we can learn and apply from fields apart from our own and I think that's been especially true of my time working with our newsroom. I get paid to write code, but coding itself is such a small part of my job. On the other hand, the ability to communicate what's happening in my code, the ability to research how to express something I've never done before in code, the ability to reach out to people who also write code, and the ability to ask good questions about code? These are all invaluable skills that make my work better. These are all skills I am still learning, and I'm grateful that I get to learn them from the best of the best: Journalists.&lt;/p&gt;

&lt;p&gt;Splash photo source: &lt;a href="https://unsplash.com/photos/cckf4TsHAuw"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>datajournalism</category>
      <category>journalism</category>
    </item>
    <item>
      <title>Automating delivery of US patent application alerts to Slack</title>
      <dc:creator>Logan McDonald</dc:creator>
      <pubDate>Tue, 05 Mar 2019 02:37:36 +0000</pubDate>
      <link>https://dev.to/logan/automating-delivery-of-us-patent-application-alerts-to-slack-3don</link>
      <guid>https://dev.to/logan/automating-delivery-of-us-patent-application-alerts-to-slack-3don</guid>
      <description>

&lt;p&gt;Recently, I've become obsessed with United States patent applications. Specifically, I'm interested in patent applications from large tech companies. I started reading about patents when I came across some patent applications from Microsoft in an article about facial recognition software. I found the dry and legalistic nature of the patent language fascinating, given the implications of the subject matter. So I googled "how do I find out what patent applications are released" and I found a glorious piece of software: The USPTO's &lt;a href="https://www.uspatentappalerts.com/"&gt;Patent Application Alert Service&lt;/a&gt;. Now, every week, I sit down with a cup of coffee and read through patent applications.&lt;/p&gt;

&lt;p&gt;In this post we'll cover why I do this, what this USPTO service does, what patent databases are available to the public, and what I've done to make the release of patent applications more accessible for my team.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are patent applications and why are they important?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Newsworthiness of patent applications
&lt;/h3&gt;

&lt;p&gt;When patent applications are released to the public, they often result in news stories. Here are just a handful I found while researching this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.cnet.com/news/apple-patent-hints-at-ar-headset-thatll-work-with-your-iphone/"&gt;"Apple patent hints at AR headset that'll work with your iPhone"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.businessinsider.com/apple-patent-filing-reveals-possible-design-for-foldable-iphone-2019-2"&gt;"An Apple patent filing reveals what a foldable iPhone might look like"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.buzzfeednews.com/article/daveyalba/amazon-filed-facial-recognition-patent-application"&gt;"Amazon Filed A Patent Application For Tech That Could Link You To Your Identity And Job"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://money.cnn.com/2016/01/28/technology/facebook-ridesharing/index.html"&gt;"Facebook is eying ridesharing"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://money.cnn.com/2018/06/07/technology/uber-patent-identify-drunks/index.html"&gt;"Uber wants to patent a way to use AI to identify drunk passengers"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cbinsights.com/research/palantir-patents-data-mining/"&gt;"Palantir’s New Patents Shed Rare Light On Its Data Methods"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.consumerwatchdog.org/sites/default/files/2017-12/Digital%20Assistants%20and%20Privacy.pdf"&gt;"Google, Amazon Patent Filings Reveal Digital Home Assistant Privacy Problems"&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As you can see, patent applications contain useful information for the public and reveal what companies consider to be innovation worth protecting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Importance of patent application alerts
&lt;/h3&gt;

&lt;p&gt;To persuade you that patent application &lt;em&gt;alerts&lt;/em&gt; are important, I need to talk a little bit about how patent applications work. When a company like Facebook or an individual person believes they have invented a novel "process" or "machine," among other things, they can apply for a patent to prevent another entity from making, using, or selling their invention without their consent. In order to obtain a patent, companies are forced to make a tradeoff. While they stand to make money by protecting their idea, they also have to disclose that idea to the public when they apply for a patent.&lt;/p&gt;

&lt;p&gt;By law, patent applications must be made public within 18 months of being filed. However, there are few exceptions. First, there is something called a "provisional" patent application. A provisional patent application allows an applicant to establish an early filing date, but the USPTO does not make it public or determine whether to grant a patent unless the applicant files a regular non-provisional patent application within one year. If the applicant doesn't file a non-provisional patent, the provisional application is never made public.&lt;/p&gt;

&lt;p&gt;There are two rarer examples of non-published applications and issued patents. First, there are those filed under foreign patent protection. Second, the USPTO may determine that an invention has implications for national security. Those examples aside, in general, after a US patent application is filed, it will be published by USPTO for the public to view (regardless of whether it has been granted yet).&lt;/p&gt;

&lt;h3&gt;
  
  
  USPTO databases
&lt;/h3&gt;

&lt;p&gt;So, you may be thinking that means the Patent Application Alert Service (PAAS) spits out an alert for &lt;em&gt;every&lt;/em&gt; non-foreign, non-provisional, and non-national-security related patent application before a patent is granted, but this isn't exactly true. Applications that come through the application database will result in alerts to PAAS. However, in some cases, a patent may be approved before the 18 month publication deadline.&lt;/p&gt;

&lt;p&gt;There are two major public databases for doing full-text searches for information related to patents: AppFT and PatFT, which contain information for patent &lt;em&gt;applications&lt;/em&gt; and patents that were approved.&lt;/p&gt;

&lt;p&gt;There are thus &lt;em&gt;applications&lt;/em&gt; that are published and indexed in AppFT that will eventually be granted, and those that may never be granted. However, all &lt;em&gt;patents&lt;/em&gt; are published and indexed into PatFT (except the ones with national security implications). Thus, those applications published prior to grant and then eventually granted live in both databases.&lt;/p&gt;

&lt;p&gt;Now you have enough background to evaluate what alerts coming through the &lt;em&gt;application&lt;/em&gt; alert service mean:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It doesn't mean that the application is granted (and it may never be granted)&lt;/li&gt;
&lt;li&gt;You're missing those patents whose applications were not published prior to being granted, and thus only exist in PatFT&lt;/li&gt;
&lt;li&gt;You're missing provisional patents, some foreign related patents, and those patents that have national security implications&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;However, dealing directly with AppFT still gives us a lot to work with. With that in mind, let's discuss the alert service.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Patent Application Alert Service (PAAS)
&lt;/h3&gt;

&lt;p&gt;PAAS is the system that provides customized email alerts when a patent application is published. It was created to allow the public to monitor the &lt;em&gt;latest&lt;/em&gt; patent application releases. You can use the service to add alerts for a variety of search terms.&lt;/p&gt;

&lt;p&gt;While these alerts definitely make it easier for reporters to report on companies' patent applications, the central reason for a patent alert system is to spur innovation. USPTO thinks that if people have easy access to patent-related information, they will file higher quality patent applications and pursue novel inventions. This is because patent filings require you to prove your patent is novel using "prior art". "Prior art" is &lt;em&gt;anything&lt;/em&gt; that can be used as evidence your invention is already known. USPTO thinks that if it can help you find "prior art" that shows your invention isn't novel, you won't apply for a patent. The more visible patent applications are, the more discoverable the "prior art".&lt;/p&gt;

&lt;p&gt;I signed up to start getting these alerts a couple months ago when I found out about PAAS. I included the top 10 tech companies in the US as well as some ones that were recommended to me like Palantir or Clear, just to see what they were like. This is the interface for adding a new company to your alerts:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0E43HzBE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/Q3qhohA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0E43HzBE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/Q3qhohA.png" alt="Adding an Alert"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I get the best luck with just searching for terms and selecting "Applicant". All the other categories will give you too much noise.&lt;/p&gt;

&lt;p&gt;I love reading the patent applications. To me, they seem like an unfiltered look into what these companies were working on in the language the engineers would use to describe it. Interestingly, there seems to be a disconnect between the engineering teams building these products and the PR teams who BuzzFeed reporters usually hear from. For example, while Amazon PR downplays the extent to which their facial recognition technology could be used by law enforcement, the language in their patents revels in those possibilities. This is because the incentives of the IP lawyers and the PR departments are misaligned. The lawyers' and engineers' goal is to get the patent approved, not to write the patent in such a way that hides a technology's dystopian features.&lt;/p&gt;

&lt;p&gt;If you are thinking of working at a large company, read their patent applications. It'll give you a great look into their work.&lt;/p&gt;

&lt;h2&gt;
  
  
  A patent application Slackbot
&lt;/h2&gt;

&lt;p&gt;I almost immediately started annoying my Twitter followers with patent-related tweets once I started getting these alerts.&lt;/p&gt;

&lt;blockquote class="twitter-tweet" data-lang="en"&gt;
&lt;p&gt;EYE TRACKING USING TIME MULTIPLEXING: "system implements time-multiplexing by configuring a source assembly comprising a plurality of light sources to project at least a first light pattern towards the user's eye over a first time period"&lt;br&gt;&lt;br&gt;again very cool but very creepy &lt;a href="https://t.co/4a40xToGe6"&gt;pic.twitter.com/4a40xToGe6&lt;/a&gt;&lt;/p&gt;— Logan McDonald (@_loganmcdonald) &lt;a href="https://twitter.com/_loganmcdonald/status/1093504704280252418?ref_src=twsrc%5Etfw"&gt;February 7, 2019&lt;/a&gt;
&lt;/blockquote&gt;

&lt;blockquote class="twitter-tweet" data-lang="en"&gt;
&lt;p&gt;Are they building Hunger Games???&lt;br&gt;&lt;br&gt;"The module may [...] analyze the metrics data to generate game inputs based on the participants' physical metrics, and provide the game inputs to the game system to affect game play" &lt;a href="https://t.co/BIBQkPWwOL"&gt;pic.twitter.com/BIBQkPWwOL&lt;/a&gt;&lt;/p&gt;— Logan McDonald (@_loganmcdonald) &lt;a href="https://twitter.com/_loganmcdonald/status/1096041820230991873?ref_src=twsrc%5Etfw"&gt;February 14, 2019&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;You may notice that the tweets above and the stories I linked earlier are all on Thursdays. PAAS releases all new patent applications to the public &lt;a href="http://appft.uspto.gov/netahtml/PTO/help/status.html"&gt;on Thursdays&lt;/a&gt; around 7am EST. Each Thursday, I get a new round of alerts from the companies to which I subscribe. This is what the looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jn9e89oK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/ro2cQ9r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jn9e89oK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/ro2cQ9r.png" alt="Imgur"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wasn't super happy with the formatting of the email. I'd have to go through and click on every link, and go out to its individual page to read about it. So I had a thought: What if I could turn this email into data that I could display the abstracts and titles only? What would that look like? My  goal was to make PAAS more accessible for people in a hurry to discover the most interesting applications right away.&lt;/p&gt;

&lt;p&gt;I looked to see if anyone had built something that accomplished this goal on Github, but could not find anything. Furthermore, while an API exists for searching the actual patent database, none exists for querying recently updated applications. Lastly, I recognize that patents are a big business. Proprietary software to parse new applications probably exists, but I don't have access to it.&lt;/p&gt;

&lt;p&gt;So I set out to make a new Slackbot. My general design of the Slackbot relies on incoming webhooks to Slack channels, sending the data to these webhooks when we receive the email from USPTO.&lt;/p&gt;

&lt;h3&gt;
  
  
  SES and SNS
&lt;/h3&gt;

&lt;p&gt;The first question is how we get the data from emails to our Slack webhooks/channels.&lt;/p&gt;

&lt;p&gt;I already have a DNS entry setup through Route53 so I thought it'd be fun to try out AWS's &lt;a href="https://aws.amazon.com/ses/"&gt;Simple Email Service (SES)&lt;/a&gt; to make an email for that entry that I could use to forward USPTO emails to. You have to set up &lt;a href="https://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-setting-up.html"&gt;email receiving&lt;/a&gt; by defining "rulesets" for emails within your account. I set it up to receive UTF8 emails to a &lt;code&gt;patents@mydomain.com&lt;/code&gt; email.&lt;/p&gt;

&lt;p&gt;Then, I hooked up that SES ruleset to a &lt;a href="https://aws.amazon.com/sns/"&gt;Simple Notification Service (SNS)&lt;/a&gt; action, which forwarded the emails to an SNS subscription called &lt;code&gt;patents&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then I went and signed up for PAAS using that email, and received the email on the AWS side through SNS and used the link they provided to confirm my email. Great! Now we had &lt;code&gt;SES -&amp;gt; SNS&lt;/code&gt; and then we just needed to hook SNS up to our Slackbot. So there are a couple ways we could go at this point. We can either use &lt;code&gt;https&lt;/code&gt; to forward the data to an endpoint as a &lt;code&gt;POST&lt;/code&gt; &lt;em&gt;or&lt;/em&gt; we could setup a lambda function that gets the forwarded data and forwards it to Slack. I decided to setup an endpoint because I didn't want to setup deploying the lambda but either would work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Slack applications
&lt;/h3&gt;

&lt;p&gt;Slack has great documentation on &lt;a href="https://get.Slack.help/hc/en-us/articles/115005265063-Incoming-WebHooks-for-Slack"&gt;setting up incoming webhooks&lt;/a&gt;. I created a Slackbot called "PatentsBot" and gave it permissions to post to channels through certain webhooks.&lt;/p&gt;

&lt;p&gt;I decided  to set up a different channel per company I wanted to follow so I have something like:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#patents-uber
#patents-amazon
#patents-facebook
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and expect my code to parse and understand where it should send any new applications that arrive for those companies and get them to the right channels.&lt;/p&gt;

&lt;p&gt;Now we just needed to receive it, parse it, and forward it to our existing webhooks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parsing emails
&lt;/h3&gt;

&lt;p&gt;Before this project, I didn't have experience with receiving and parsing emails with code so I was able to learn a lot about email encoding and the various options available for email parsing in python.&lt;/p&gt;

&lt;p&gt;If we look back at the email above, we can see that we are given a list of ids which are hyperlinks. The links don't make a ton of sense (i.e. aren't formatted with consistent routing):&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://appft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;amp;Sect2=HITOFF&amp;amp;d=PG01&amp;amp;p=1&amp;amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.html&amp;amp;r=1&amp;amp;f=G&amp;amp;l=50&amp;amp;s1=%2220190065445%22.PGNR.&amp;amp;OS=DN/20190065445&amp;amp;RS=DN/20190065445
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;... great, right? However, if you click through the link you'll find a nicely formatted HTML document that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--26Qaszi0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/XSS7SE5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--26Qaszi0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/XSS7SE5.png" alt="Patent application"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was enough information, formatted in &lt;del&gt;tolerable&lt;/del&gt; parsable XML. I decided to pull all the hyperlinks from the email, load their associated HTML, parse out the abstract, filing date, and company name, and then forward that data as a single Slack message, rather than trying to parse out meaningful information from the email alone.&lt;/p&gt;

&lt;p&gt;This is the code, a &lt;code&gt;build_slack_msgs&lt;/code&gt; method, that does the parsing to build messages we'll send on to Slack. This is receiving json objects from SNS, forwarded by SES, finding all the links that being with the AppFT URL signage, &lt;code&gt;http://appft.uspto.gov.&lt;/code&gt;, requesting data from each link, parsing that data, and returning some metadata.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'Message'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;json_file_parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="s"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;parsed_email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parsestr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_file_parsed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;links&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="c1"&gt;# Let's pull out all those nasty links and collect them
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;parsed_email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_payload&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;links&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r'\&amp;lt;(http://appft.uspto.gov.*)\&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;quopri&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decodestring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'utf8'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;message_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="c1"&gt;# Then we parse the information we can obtain from those links
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;html_tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lxml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;' '&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/html/body/font'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text_content&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="c1"&gt;# regarding the following line... I'm sorry, but it works
&lt;/span&gt;    &lt;span class="n"&gt;applicant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html_tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/html/body/table[3]/table/tr/td/table/tr[2]/td'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text_content&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;' '&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/html/body/table[3]/table/tr'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text_content&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;abstract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;' '&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/html/body/p[2]'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text_content&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;slack_webhook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;find_slack_webhook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;applicant&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# method to retrieve our Slack channel from secrets
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;slack_webhook&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;message_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s"&gt;'applicant'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;applicant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;'link'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;'date'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;'slack_webhook'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;slack_webhook&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;'abstract'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;abstract&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There are a couple more special packages I want to point out I'm using to parse the emails from PAAS.&lt;/p&gt;

&lt;p&gt;The first is &lt;code&gt;email&lt;/code&gt;'s &lt;a href="https://docs.python.org/3/library/email.parser.html"&gt;&lt;code&gt;parser&lt;/code&gt;&lt;/a&gt;. This package provides a standard parser that understands email document structures, including MIME documents. &lt;code&gt;parsestr&lt;/code&gt; takes a string object and then reads the data from the object given.&lt;/p&gt;

&lt;p&gt;The next package is &lt;a href="https://docs.python.org/2/library/quopri.html"&gt;&lt;code&gt;quopri&lt;/code&gt;&lt;/a&gt;. &lt;code&gt;quopri&lt;/code&gt; performs printable transport encoding and decoding for MIME (Multipurpose Internet Mail Extensions) documents, which is the encoding used in email. It takes the email object and decodes it.&lt;/p&gt;

&lt;p&gt;Finally, once we have our links list that we've parsed out from the email, we'll use &lt;a href="https://lxml.de/"&gt;&lt;code&gt;lxml&lt;/code&gt;&lt;/a&gt; to parse the html associated with those links. We give it our decoded string of html we get as a response from &lt;code&gt;requests&lt;/code&gt; and it returns a nicely formatted tree we can use to grep on html properties.&lt;/p&gt;

&lt;p&gt;After we've formed nicely formatted data blobs about our various patent applications in the email, we format the messages to deliver them to slack:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;msgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;build_slack_msgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;msgs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'slack_webhook'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;Slack_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"attachments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s"&gt;"fallback"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Patent filing."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"#d32600"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s"&gt;"pretext"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"New patent from {}"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'applicant'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
                    &lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
                    &lt;span class="s"&gt;"title_link"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'link'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="s"&gt;"fields"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                        &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Date filed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'date'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                        &lt;span class="p"&gt;},&lt;/span&gt;
                        &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Filing abstract"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'abstract'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
                            &lt;span class="s"&gt;"short"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="s"&gt;"footer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"PatentBot"&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'slack_webhook'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Slack_data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'application/json'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And that completes our design:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PAAS service -&amp;gt; SES email -&amp;gt; SNS subscription -&amp;gt; https endpoint POST -&amp;gt; Slack incoming webhook POST
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When we put this all together we get this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jBSc7z6J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/SFupcJz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jBSc7z6J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/SFupcJz.gif" alt="Patent scroll"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Easily readable, automated patent alerts sent directly to our team Slack channels! Users in Slack can now subscribe to exactly the channels they want. Then, there are three simple steps to extend this code to new companies to follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You add a company with USPTO alerts by &lt;a href="https://go.uspatentappalerts.com/login/login.php"&gt;logging in to USPTO&lt;/a&gt; and selecting "add an alert"&lt;/li&gt;
&lt;li&gt;Edit our secrets file to add another Slack webhook&lt;/li&gt;
&lt;li&gt;Add the logic to &lt;code&gt;find_slack_webhook&lt;/code&gt; to specify which keywords will identify the channel&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Currently I have about twenty channels setup in a test slack, while I only subject my coworkers to about six of them 😅.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Improvements
&lt;/h2&gt;

&lt;p&gt;We've been happy to get patent alerts for a variety of companies for the past month, but there are always ways to improve.&lt;/p&gt;

&lt;p&gt;We should look into incorporating any of &lt;a href="https://developer.uspto.gov/api-catalog"&gt;USPTO's APIs&lt;/a&gt;. I would like to query the PatFT database for information we might be missing about patents granted before the 18 month publication deadline. We could possibly use &lt;a href="https://github.com/USPTO/PatentPublicData"&gt;USPTO's PatentPublicData API&lt;/a&gt; for that.&lt;/p&gt;

&lt;p&gt;Another API, in beta, that I'm interested in is the &lt;a href="https://developer.uspto.gov/api-catalog/uspto-office-action-rejection-api-beta"&gt;USPTO action rejection API&lt;/a&gt;, which allows for retrieval of rejected applications. It would be great to keep track of those applications accepted or rejection as follow-ups.&lt;/p&gt;

&lt;p&gt;As always, I am open to suggestions for new avenues of research for getting updated patent information as fast as possible. Also, if there are any lawyer-devs out there, please let me know if I could expand on anything or got anything wrong. I have no legal background but am eager to learn!&lt;/p&gt;

&lt;p&gt;Shoutout to &lt;a href="https://github.com/frewsxcv/"&gt;@frewsxcv&lt;/a&gt; for reviewing the code here with me and debugging MINE decoding. Thanks to &lt;a href="https://github.com/mkaemingk"&gt;@mkaemingk&lt;/a&gt; for editing and &lt;a href="https://github.com/chrswng"&gt;@chrswng&lt;/a&gt; for chatting with me about patents.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;


</description>
      <category>legal</category>
      <category>slackbot</category>
      <category>civictech</category>
    </item>
    <item>
      <title>Questions I ask in SRE interviews</title>
      <dc:creator>Logan McDonald</dc:creator>
      <pubDate>Sun, 03 Mar 2019 14:07:38 +0000</pubDate>
      <link>https://dev.to/logan/questions-i-ask-in-sre-interviews-a9j</link>
      <guid>https://dev.to/logan/questions-i-ask-in-sre-interviews-a9j</guid>
      <description>&lt;p&gt;SRE, or Site Reliability Engineer{ing}, is a software discipline that applies software engineering to infrastructure and operations. Other SRE-like roles are Operations Engineering, Systems Engineering, or Infrastructure Engineering, but SRE tends to focus more on "resilience" of the operations of software systems. This post doesn't broadly cover SRE, but you can read more about it in my favorite SRE-intro post &lt;a href="https://hackernoon.com/so-you-want-to-be-an-sre-34e832357a8c?gi=52a662985557"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I was recently asked by a friend who has been interviewing for SRE jobs for good questions to ask at the end of the interview and was surprised to not find any infrastructure-specific posts on questions to ask interviewers. In writing the email back to them I realized I had lots of ideas and it might be worth it to share a short post for them, my future self and anyone else who is interested.&lt;/p&gt;

&lt;p&gt;These are the questions I make sure to ask when interviewing for positions on infrastructure or site reliability teams. Depending on the structure of your interviews, these may be appropriate for the recruiter, but are most likely questions for the hiring manager or other members of the team. Most of this centers around where the team is at with their tooling and how happy developers are. I'm also trying to get at the relationship between the operations engineering team and the rest of the team and org.&lt;/p&gt;

&lt;h2&gt;
  
  
  SRE related questions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is the tech stack?

&lt;ul&gt;
&lt;li&gt;I'm looking at the question from an operations perspective. Are they using a hodgepodge of languages or is the development flow opinionated? How many different technologies does the team have to support?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;What is the infrastructure stack?

&lt;ul&gt;
&lt;li&gt;Depending on what they say, we'll be talking about this for a while and will probably create a lot of other questions.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;What does your metrics &amp;amp; monitoring setup look like? How do you debug issues with the system?&lt;/li&gt;
&lt;li&gt;This may be a controversial one, but if the title is "SRE" I ask why the title is "SRE" and not something else (same for "DevOps"). I'm looking to see if they're being thoughtful about what the term means and how they are defining "resilience" for their systems.&lt;/li&gt;
&lt;li&gt;Walk me through the experience a developer has on-boarding to your development environment. How long do you think it takes?&lt;/li&gt;
&lt;li&gt;Walk me through the experience a developer has deploying with your pipeline. What would you say are the biggest pain points?

&lt;ul&gt;
&lt;li&gt;How would you rate test coverage and do you continue to measure that? What about test coverage is important to the team?&lt;/li&gt;
&lt;li&gt;Do you have blue-green deployments? Do you have canaries?&lt;/li&gt;
&lt;li&gt;How do engineers share their work with product teammates in the QA phase? How many environments do you have?&lt;/li&gt;
&lt;li&gt;These questions are incredibly important to me. It could both surface fun red flags for you to discuss with your interviewer and see how receptive they are to your opinions and give you an idea of things you might be working on for them.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;How would you describe the relationship between the operations team, IT, and the rest of the engineering team?&lt;/li&gt;
&lt;li&gt;How do you handle app security? How do you encourage developers to think about the security of their services?&lt;/li&gt;
&lt;li&gt;Do you have to be GDPR compliant? Did that process go smoothly for you?

&lt;ul&gt;
&lt;li&gt;This may not lead anywhere, but I'm looking for a discussion about what their data auditing procedures look like, and how easy it is to answer security questions about their data quickly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;What's your on-call set up look like?

&lt;ul&gt;
&lt;li&gt;How many times a month are you on-call?&lt;/li&gt;
&lt;li&gt;When you are on-call, how many times during that period are you getting paged?&lt;/li&gt;
&lt;li&gt;Would you say when you get paged, alerts are actionable?&lt;/li&gt;
&lt;li&gt;Are developers on-call for their services?&lt;/li&gt;
&lt;li&gt;How do you on-board people to on-call?&lt;/li&gt;
&lt;li&gt;How much time is spent on the team in "reactive" rather than "proactive" mode?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Are most things in the infrastructure stack self-service? Like, what's the process of setting up a new service with data stores?&lt;/li&gt;
&lt;li&gt;Which level of &lt;a href="https://landing.google.com/sre/sre-book/chapters/part3/"&gt;Dickerson's hierarchy of site reliability&lt;/a&gt; do you think needs the most work in your stack?&lt;/li&gt;
&lt;li&gt;Overall, how would you rate developer productivity?&lt;/li&gt;
&lt;li&gt;Do you have any open source projects? If not, are you interested in open sourcing anything?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Standard interview questions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Does your engineering team have a values statement? What's in it?&lt;/li&gt;
&lt;li&gt;What do you do to foster an environment of learning?&lt;/li&gt;
&lt;li&gt;What does success in this role look like? What sorts of projects or accomplishments could you see being completed 3 months, 6 months, and 1 year out?&lt;/li&gt;
&lt;li&gt;Is the working environment collaborative during work or do people mostly keep to themselves? How so? Is the office open? (I would also ask during on-sites that they show you where you'd be sitting. If you're sensitive to lots of noise while working this could be very important.)&lt;/li&gt;
&lt;li&gt;How much of the team is distributed? What is your "work from home" or "work from X" policy? Is it flexible or set?&lt;/li&gt;
&lt;li&gt;What is the thing you are most excited about working on or launching in the next year?&lt;/li&gt;
&lt;li&gt;What do you like best about working here?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I want to point out there are some things I didn't ask here and that doesn't mean that I don't value them. For example, I never ask directly about diversity on the team. I hope that's something that I see around the office and in my interviews. When I go to lunch with one of the developers, I'll ask questions that indirectly get to those issues. I don't really need the PR line about diversity.&lt;/p&gt;

&lt;p&gt;What are your questions you always make sure to ask in either general tech or SRE interviews? Let me know!&lt;/p&gt;

&lt;p&gt;Image used from &lt;a href="https://unsplash.com/photos/u3o7il8s1Fc"&gt;unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>interviewing</category>
    </item>
    <item>
      <title>Homographs, Attack!</title>
      <dc:creator>Logan McDonald</dc:creator>
      <pubDate>Fri, 16 Feb 2018 04:15:51 +0000</pubDate>
      <link>https://dev.to/logan/homographs-attack--5a1p</link>
      <guid>https://dev.to/logan/homographs-attack--5a1p</guid>
      <description>&lt;p&gt;We've known about Homograph attacks since the 1990s -- so you may be wondering why I'm writing about them in 2018. Don't worry, I'll get to that. In this post, we'll explore the history of homograph attacks, and why, like many of the internet’s problems that stem from path dependence, it seems like they just won’t ever go away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Origins of my Interest
&lt;/h2&gt;

&lt;p&gt;I first got interested in homograph attacks a few months back when I was working through tickets for Kickstarter's &lt;a href="https://hackerone.com" rel="noopener noreferrer"&gt;Hackerone&lt;/a&gt; program. HackerOne is a "bug bounty program", or, an invitation that hackers and security researchers find vulnerabilities in our site in exchange for money.&lt;/p&gt;

&lt;p&gt;When I was looking through the tickets, one caught my attention. It wasn't a particularly high risk vulnerability, but I didn't understand a lot of words in the ticket, so of course I was interested. The hacker was concerned about Kickstarter's profile pages. (We often get reports about our profile and project pages.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3lwggq0l9so5xobn6gno.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3lwggq0l9so5xobn6gno.png" alt="Example of Kickstarter's Profile Page" width="617" height="677"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Profile pages often create vulnerabilities for websites. Whenever you are in the position to “host” someone on your site, you are going to have to think about the ways they’ll abuse that legitimacy you give them. Our hacker was specifically concerned about a field that allows our users to add user-urls or "websites" to their profile.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F292ci8notxm1rzoyz39c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F292ci8notxm1rzoyz39c.png" alt="Example of Kickstarter's Profile Page Websites" width="492" height="130"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They thought this section could be used in a homograph attack. To which I was like, what the heck is a homograph attack? And that question lead me down a rabbit hole of international internet governance, handfuls of RFCs, and a decades-old debate about the global nature of the internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Internet Corporation for Names and Numbers (ICANN)
&lt;/h2&gt;

&lt;p&gt;We have to start with ICANN, the main international internet body in charge in this story. ICANN makes all the rules about what can and cannot be a domain name (along with performing the technical maintenance of the DNS root zone registries and maintaining the namespaces of the Internet).&lt;/p&gt;

&lt;p&gt;For example, say you go to Namecheap to register "loganisthemostawesome.com". Namecheap uses the &lt;a href="https://en.wikipedia.org/wiki/Extensible_Provisioning_Protocol" rel="noopener noreferrer"&gt;“extensible provisioning protocol”&lt;/a&gt; to verify your name with Verisign. Verisign is the organization that manages the registry for the “.com” gTLD. Versign checks the ICANN rules and regulations for your registration attempt, tells Namecheap the result, and Namecheap tells me if I can register "loganisthemostawesome.com". Spoilers: I can!&lt;/p&gt;

&lt;p&gt;This is great. But I primarily speak English and I use ASCII for all my awesome businesses on the internet. What happens to all those other languages that can’t be expressed in a script compatible with ASCII?&lt;/p&gt;

&lt;h3&gt;
  
  
  Version 1 of Internationalized Domain Names
&lt;/h3&gt;

&lt;p&gt;ICANN attempted to answer this question when they &lt;a href="https://www.icann.org/resources/pages/idn-guidelines-2003-06-20-en" rel="noopener noreferrer"&gt;proposed and implemented IDNs&lt;/a&gt; as a standard protocol for domain names in the late 90s. They wanted a more global internet so they opened up domains to a variety of unicode represented scripts.&lt;/p&gt;

&lt;p&gt;What's a script? A script is a collection of letters/signs for a single system. For example, Latin is a script that supports many languages, whereas a script like Kanji is one of the scripts supporting the Japanese language. Scripts can support many languages, and languages can be made of multiple scripts. ICANN keeps tables of all unicode character it associates with any given script.&lt;/p&gt;

&lt;p&gt;This is even better now! Through IDNs, ICANN has given us the ability to express internet communities across many scripts. However, there was one important requirement. &lt;a href="https://en.wikipedia.org/wiki/Domain_Name_System" rel="noopener noreferrer"&gt;ICANN’s Domain Name System&lt;/a&gt;, which performs a lookup service to translate user-friendly names into network addresses for locating Internet resources, is restricted in practice to the use of ASCII characters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Punycode
&lt;/h3&gt;

&lt;p&gt;Thus ICANN turned to Punycode. Punycode is just puny unicode. Bootstring is the algorithm  that translates names written in language-native scripts (unicode) into an ASCII text representation that is compatible with the Domain Name System (punycode).&lt;/p&gt;

&lt;p&gt;For example, take this fictional domain name (because we still can't have emojis in gTLDs 😭):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;hi👋friends💖🗣.com&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you put this in your browser, the real lookup against the Domain Name System would have to use the punycode equivalent:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;xn--hifriends-mq85h1xad5j.com&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, problems solved. We have a way to use domain names in unicode scripts that represent the full global reach of the internet and can start handing out IDNs. Great! What could go wrong?&lt;/p&gt;

&lt;h2&gt;
  
  
  Homographs
&lt;/h2&gt;

&lt;p&gt;Well, things aren’t always as they seem. And this is where homographs and homoglyphs come in.&lt;/p&gt;

&lt;p&gt;A homograph refers to multiple things that look or seem the same, but have different meanings. We have many of these in English, for example “lighter” could refer to the fire starter or the comparative adjective.&lt;/p&gt;

&lt;p&gt;The problem when it comes to IDNs is that homoglyphs exist between scripts as well, with many of the Latin letters having copies in other scripts, like Greek or Cyrillic.&lt;/p&gt;

&lt;p&gt;Example of lookalikes from homoglyphs.net:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe947vqto75vtb5pwqtrm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe947vqto75vtb5pwqtrm.png" alt="Homoglyphs.net Image of Example Homoglyphs" width="800" height="993"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's look at an example of a domain name.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;washingtonpost.com&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;vs&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;wаshingtonpost.com&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Can you tell the difference? Well, let's translate both of these to purely ASCII:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;washingtonpost.com&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;vs&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;xn--wshingtonpost-w1k.com&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Uh oh, these definitely aren't the same. However, user-agents would make them appear the same in a browser, in order to make the punycode user-friendly. But in reality, the first "a" in the fake-WaPo is really a Cyrillic character. When translated to punycode we can see the ASCII remaining characters, "wshingtonpost" and then a key signifying the Cyrillic a, "w1k".&lt;/p&gt;

&lt;p&gt;This presented ICANN with a big problem. You can clearly see how these may be used in phishing attacks when user-agents interpret both Washington Post's as homographs, making them look exactly same. So what was ICANN to do?&lt;/p&gt;

&lt;h2&gt;
  
  
  Internationalized Domain Names Version 2 &amp;amp; 3
&lt;/h2&gt;

&lt;p&gt;By 2005, ICANN had figured out a solution. They told gTLD registrars they had to restrict mix scripts. Every single registered domain had to have a "label" on it to indicate the single pure script that the domain name would use to support it's language. Today, if you went and tried to register our copy-cat Washington Post at &lt;code&gt;xn--wshingtonpost-w1k.com&lt;/code&gt;, you would get an error. Note: There were a few exceptions made, however, for languages that need to be mixed script, like Japanese.&lt;/p&gt;

&lt;p&gt;Problem fixed, right? Well, while mixed scripts are not allowed, pure scripts are still perfectly fine according to ICANN's guidelines. Thus, we still have a problem. What about pure scripts in Cyrillic or Greek alphabets that look like the Latin characters? How many of those could there be?&lt;/p&gt;

&lt;h2&gt;
  
  
  Proof of Concept
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fowde5hk63qz6n1ploowr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fowde5hk63qz6n1ploowr.gif" alt="Gif of POC" width="1024" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, when I was talking to my friend &lt;a href="https://github.com/frewsxcv" rel="noopener noreferrer"&gt;@frewsxcv&lt;/a&gt; about homograph attacks, he had the great idea to make a script to find susceptible urls for the attack. So I made a &lt;a href="https://github.com/loganmeetsworld/homographs-talk/tree/master/ha-finder" rel="noopener noreferrer"&gt;homograph attack detector&lt;/a&gt; that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Takes the top 1 million websites&lt;/li&gt;
&lt;li&gt;For each domain, checks if letters in each are confusable with latin or decimal&lt;/li&gt;
&lt;li&gt;Checks to see if the punycode url for that domain is registered through a WHOIS lookup&lt;/li&gt;
&lt;li&gt;Returns all the available domains we could register&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A lot of the URLs are a little off looking with the Cyrillic (also a lot of the top 1 million websites are porn), but we found some interesting ones you could register.&lt;/p&gt;

&lt;p&gt;For example, here's my personal favorite. In both &lt;em&gt;Firefox&lt;/em&gt; and &lt;em&gt;Chrome&lt;/em&gt;, visit:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://%D1%80%D0%B0%D1%83%D1%80%D0%B0%D3%8F.com/" rel="noopener noreferrer"&gt;https://раураӏ.com/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's what they look like in those Browsers.&lt;/p&gt;

&lt;p&gt;Firefox:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cuh6tplwhk9oarmfcat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cuh6tplwhk9oarmfcat.png" alt="Firefox IDN display algo" width="800" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chrome:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdgf5oerhatz013dhymp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdgf5oerhatz013dhymp.png" alt="Chrome IDN display algo" width="800" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pretty cool! In Firefox, it totally looks like the official PayPal in the address bar! However, in Chrome, it resolves to punycode. Why is that? 🤔&lt;/p&gt;

&lt;h2&gt;
  
  
  User-Agents &amp;amp; Their Internationalized Domain Names Display Algorithms
&lt;/h2&gt;

&lt;p&gt;It is because Chrome and Mozilla use different Internationalized Domain Name Display Algorithms. &lt;a href="https://www.chromium.org/developers/design-documents/idn-in-google-chrome" rel="noopener noreferrer"&gt;Chrome's algorithm&lt;/a&gt; is much stricter and more complex than Mozilla's, and includes special logic to protect against homograph attacks. Chrome checks to see if the domain name is on a gTLD and all the letters are confusable Cyrillic, then it shows punycode in the browser rather than the unicode characters. Chrome only changed this recently because of &lt;a href="https://www.xudongz.com/blog/2017/idn-phishing/" rel="noopener noreferrer"&gt;Xudong Zheng’s 2017 report&lt;/a&gt; using &lt;code&gt;www.xn--80ak6aa92e.com&lt;/code&gt; as a POC.&lt;/p&gt;

&lt;p&gt;Firefox, on the other hand, still shows the full URL in its intended script, even if it's confusable with Latin characters. I want to point out that Firefox allows you to change your settings to &lt;em&gt;always&lt;/em&gt; show punycode in the Browser, but if you often use sites that aren't ASCII domains, this can be pretty inaccessible.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, what's next?
&lt;/h2&gt;

&lt;p&gt;So what, now, is our responsibility as application developers and maintainers if we think someone might use our site to phish people using a homograph? I can see a couple paths forward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Advocate to Mozilla and other user-agents to make sure to change their algorithms to protect users.&lt;/li&gt;
&lt;li&gt;Advocate that ICANN changes its rules around registering domains with Latin confusable characters.&lt;/li&gt;
&lt;li&gt;Implement our own display algorithms. This is what we ended up doing at Kickstarter. We used Google's open-source algorithm and show a warning if it's possible that the url shown on the page is a homograph for another url.&lt;/li&gt;
&lt;li&gt;Finally, we could just register these domains like &lt;a href="https://github.com/frewsxcv" rel="noopener noreferrer"&gt;@frewsxcv&lt;/a&gt; and I did with PayPal so that they aren't able to be used maliciously. Possibly, if we are part of an organization with a susceptible domain, we should just register it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To summarize, this is a hard problem! That's why it's been around for two decades. And fundamentally what I find so interesting about the issues surfaced by this attack. I personally think ICANN did the right thing in allowing IDNs in various scripts. The internet should be more accessible to all.&lt;/p&gt;

&lt;p&gt;I like Chrome's statement in support of their display algorithm, however, which nicely summarizes the tradeoffs as play: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We want to prevent confusion, while ensuring that users across languages have a great experience in Chrome. Displaying either punycode or a visible security warning on too wide of a set of URLs would hurt web usability for people around the world.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The internet is full of these tradeoffs around accessibility versus security. As users and maintainers of this wonderful place, I find conversations like these to be one of the best parts of building our world together.&lt;/p&gt;

&lt;p&gt;Now, we just gotta get some emoji support.&lt;/p&gt;

&lt;p&gt;Thanks for reading! 🌍💖🎉🙌🌏&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Background
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/IDN_homograph_attack" rel="noopener noreferrer"&gt;Wikipedia on Homograph Attacks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Internationalized_domain_name" rel="noopener noreferrer"&gt;Wikipedia on IDNs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://eprints.whiterose.ac.uk/112665/1/paper_247v2.pdf" rel="noopener noreferrer"&gt;Plagiarism Detection in Texts Obfuscated with Homoglyphs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kaigi.org/jsai/webprogram/2013/pdf/960.pdf" rel="noopener noreferrer"&gt;A Collective Intelligence Approach to Detecting IDN Phishing by Shian-Shyong Tseng, Ai-Chin Lu, Ching-Heng Ku, and Guang-Gang Geng&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://slides.tips/exposing-homograph-obfuscation-intentions-by-coloring-unicode-strings.html" rel="noopener noreferrer"&gt;Exposing Homograph Obfuscation Intentions by Coloring Unicode Strings by Liu Wenyin, Anthony Y. Fu, and Xiaotie Deng&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.xudongz.com/blog/2017/idn-phishing/" rel="noopener noreferrer"&gt;Phishing with Unicode Domains by Xudong Zheng&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://evgeniy.gabrilovich.com/publications/papers/homograph_full.pdf" rel="noopener noreferrer"&gt;The Homograph Attack by Evgeniy Gabrilovich and Alex Gontmakher&lt;/a&gt; NOTE: The original paper!&lt;/li&gt;
&lt;li&gt;&lt;a href="http://static.usenix.org/events/usenix06/tech/full_papers/holgers/holgers_html/" rel="noopener noreferrer"&gt;Cutting through the Confusion: A Measurement Study of Homograph Attacks by Tobias Holgers, David E. Watson, and Steven D. Gribble&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ro.ecu.edu.au/cgi/viewcontent.cgi?article=1010&amp;amp;context=ism" rel="noopener noreferrer"&gt;Assessment of Internationalised Domain Name Homograph Attack Mitigation by Peter Hannay and Christopher Bolan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ieeexplore.ieee.org/abstract/document/5623562/?reload=true" rel="noopener noreferrer"&gt;Multilingual web sites: Internationalized Domain Name homograph attacks by Johnny Al Helou and Scott Tilley&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jsidrach/idn-homograph-attack" rel="noopener noreferrer"&gt;IDN Homograph Attack Potential Impact Analysis by @jsidrach&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Browser policies
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.chromium.org/developers/design-documents/idn-in-google-chrome" rel="noopener noreferrer"&gt;Chrome's IDN Display Algorithm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.mozilla.org/IDN_Display_Algorithm" rel="noopener noreferrer"&gt;Mozilla's IDN Display Algorithm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.unicode.org/reports/tr39/#Mixed_Script_Detection" rel="noopener noreferrer"&gt;UTC Mixed Script Detection Security Mechanisms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cs.chromium.org/chromium/src/components/url_formatter/idn_spoof_checker.cc" rel="noopener noreferrer"&gt;Chrome's IDN Spoof Checker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1332714#c79" rel="noopener noreferrer"&gt;Bugzilla Open Bug on IDNs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tools
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/UndeadSec/EvilURL" rel="noopener noreferrer"&gt;Homograph Attack Generator for Mixed Scripts&lt;/a&gt; NOTE: It is no longer possible to register mixed script domain names.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/frewsxcv/homograph-attack-finder/" rel="noopener noreferrer"&gt;Homograph Attack Finder for Pure Cyrillic Scripts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/loganmeetsworld/homographs-talk/tree/master/ha-finder" rel="noopener noreferrer"&gt;Homograph Attack Finder + WHOIS lookup for Pure Cyrillic Scripts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://homoglyphs.net/" rel="noopener noreferrer"&gt;Homoglyph Dictionary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.punycoder.com" rel="noopener noreferrer"&gt;Puncode converter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ICANN CFPs and Guidelines
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.icann.org/resources/unthemed-pages/idn-guidelines-2005-11-14-en" rel="noopener noreferrer"&gt;2005 IDN Version 2.0 Guidelines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.icann.org/news/announcement-2005-02-23-en" rel="noopener noreferrer"&gt;ICANN 2005 RFC Announcement for Version 2.0 of IDN Guidelines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.icann.org/en/system/files/files/idn-guidelines-26apr07-en.pdf" rel="noopener noreferrer"&gt;IDNA2008 Version 2.2 draft&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.icann.org/resources/pages/idn-guidelines-2011-09-02-en" rel="noopener noreferrer"&gt;2011 IDN Version 3.0 Guidelines&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ICANN, Verisign, and the Domain Registration Process
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains" rel="noopener noreferrer"&gt;Wikipedia for TLD&lt;/a&gt;. Each TLD has its own Registry that manages it and defines its IDN rules.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Domain_name_registry" rel="noopener noreferrer"&gt;Wikipedia for Domain Name Registry&lt;/a&gt;, like Verisign&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Domain_name_registrar" rel="noopener noreferrer"&gt;Wikipedia for Domain Name Registrar&lt;/a&gt;, like Namecheap, Godaddy, or Gandi.net&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.verisign.com/en_US/channel-resources/become-a-registrar/verisign-domain-registrar/index.xhtml" rel="noopener noreferrer"&gt;ICANN Accreditation and Verisign Certification&lt;/a&gt; for distributing .com domains&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Extensible_Provisioning_Protocol" rel="noopener noreferrer"&gt;Wikipedia for the Extensible Provisioning Protocol&lt;/a&gt;, which is used when a user on a registry requests a .com domain. The registry uses the EPP protocol to communicate with verisign to register the domain.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.verisign.com/en_US/channel-resources/domain-registry-products/idn/idn-policy/registration-rules/index.xhtml" rel="noopener noreferrer"&gt;Verisign's IDN Policy&lt;/a&gt;. Verisign requires you specify a three letter language tag associated with the domain upon registration. this tag determines which character scripts you can use in the domain. presumably the language tag for https://аррӏе.com/ (cyrillic) is 'RUS' or 'UKR'.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pir.org/products/org-domain/org-idns/" rel="noopener noreferrer"&gt;PIR, manager of .org TLDs, IDN rules&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Misc Security related to Domains
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stripe.ian.sh/" rel="noopener noreferrer"&gt;Extended Validation Is Broken by @iangcarroll&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Homograph Major Site Copy-cat Examples
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;http://аоӏ.com/&lt;/li&gt;
&lt;li&gt;https://раураӏ.com/&lt;/li&gt;
&lt;li&gt;https://аррӏе.com/&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.%D1%81%D0%BF%D0%BF.com/" rel="noopener noreferrer"&gt;http://www.спп.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>security</category>
    </item>
    <item>
      <title>How I Take Notes</title>
      <dc:creator>Logan McDonald</dc:creator>
      <pubDate>Sun, 12 Nov 2017 18:13:43 +0000</pubDate>
      <link>https://dev.to/logan/how-i-take-notes-ag1</link>
      <guid>https://dev.to/logan/how-i-take-notes-ag1</guid>
      <description>&lt;p&gt;Last month I was on jury duty in Brooklyn for two weeks. I learned a lot. However, jury duty is not being offered for the truth of the matter asserted, but merely to show what lead to this blog post. Apologies for the legalese, I was hanging out with lawyers too much!&lt;/p&gt;

&lt;p&gt;Anyway, at jury duty we had a lot of free time where we were trapped in a courtroom with no wifi just waiting around for instructions. I decided to take that time to learn something! I downloaded &lt;a href="https://doc.rust-lang.org/book/" rel="noopener noreferrer"&gt;The Rust Programming Language aka TRPL&lt;/a&gt; and grabbed my favorite notebook and took them with me to court every day for the last two weeks. On breaks I read chapters of the book and I took notes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Take Notes
&lt;/h2&gt;

&lt;p&gt;Taking notes doesn't work for everyone, but I find it absolutely necessary to retain knowledge. Notes can be taking in loads of different ways and it's important to find what works best for you. Particularly, I make a point to handwrite most of my notes. There is something visceral and tactile about indexing handwritten notes that helps me remember the topics better. My coworkers kid me about when I first interviewed at Kickstarter, I brought a big notebook and took copious notes during all the interviews. I take notes in lots of different situations, but namely when I'm learning something new at work, when I'm at a conference, or when I'm primarily paying attention to someone else talking/writing.&lt;/p&gt;

&lt;p&gt;I find several advantages to taking notes. First, it gives me a written record of everything I've learned. If I timestamp it well (and I usually put hours and minutes as well as dates!) I can get a log of my progress. Second, the act of taking notes &lt;em&gt;well&lt;/em&gt; helps me remember what I've learned.&lt;/p&gt;

&lt;p&gt;Now, let's discussing what taking notes "well" means.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cornell Method
&lt;/h2&gt;

&lt;p&gt;I think part of the reason we hate having to take notes is the many wasted hours being forced to take them throughout school. Personally, I always loved to handwrite notes. However, there are conflicting studies as to it's actual impact on memory retention. Regardless of if you take digital or handwritten notes, there are techniques you can use to make your notes more effective.&lt;/p&gt;

&lt;p&gt;One that I have loved over the years is &lt;a href="https://en.wikipedia.org/wiki/Cornell_Notes" rel="noopener noreferrer"&gt;The Cornell Method&lt;/a&gt;. The idea behind the Cornell notes is that you keep "cues" of the main body of the notes along one edge while you go through the materials. The reason I always loved Cornell notes is because you can make the cues whatever you find helps you remember the material the best, not necessarily keywords given in a textbook or by a lecturer. For example, I have a cues for my Rust notes that reference things in the Ruby API that are more familiar to me, so I can say things "like Bundler" for different Cargo commands, which cue me to remembering the context for the notes.&lt;/p&gt;

&lt;p&gt;Here are some cues on my notes from &lt;a href="https://twitter.com/megsa_" rel="noopener noreferrer"&gt;Megan Anctil's&lt;/a&gt; 2016 Monitorama talk, for example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5t5fkfb5du82t6z58lx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5t5fkfb5du82t6z58lx.jpg" alt="Notes from Monitorama 2016" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons from Learning Science
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Strengthening Recall
&lt;/h3&gt;

&lt;p&gt;A reason that I love Cornell notes' cueing method is it helps with a practice in learning science called recall. The idea behind recall is that rereading information from notes or a textbook are proven to have little effect on longterm memory of the concepts in that material. However, forcing yourself to &lt;a href="http://science.sciencemag.org/content/331/6018/772" rel="noopener noreferrer"&gt;recall information with flashcards or cues does help&lt;/a&gt;. Also, spacing out your study of this material has been shown to help. This is called "delayed retrieval". When we force our minds to stretch for past information with the help of cues, we strengthen those memories to the information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Low Stakes Testing
&lt;/h3&gt;

&lt;p&gt;Another concept connected with notetaking that's been proven to help learning is &lt;a href="http://insideteaching.grad.msu.edu/a-case-for-more-testing-the-benefits-of-frequent-low-stakes-assessments/" rel="noopener noreferrer"&gt;low stakes testing&lt;/a&gt;. Frequent, low stakes  testing allows us to practice remembering without the pressure of a live test. It gives us space to reflect on our mistakes and revist faulty places in our memory of certain content. If we take careful notes of our notes (i.e. cues) we can use these as a way of testing ourselves, which is pretty useful! All I do is go back to my Rust notes every couple of days and cover the side of the paper with the verbose notes and force myself to remember concept only from the cues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modeling
&lt;/h2&gt;

&lt;p&gt;Finally, I'm a huge fan of utilizing different sorts of patterns to model complex relationships amongst topics in my notes. Unfortunately for me, I'm not a great artist so usually these come out as squiggly blob drawings. I was inspired to start diagramming more in my notes (and pull requests!) by my coworker &lt;a href="https://twitter.com/superSGP" rel="noopener noreferrer"&gt;Sarah&lt;/a&gt;. She has this amazing talk on &lt;a href="https://www.youtube.com/watch?v=jHgrdiy4FnE" rel="noopener noreferrer"&gt;dev diagrams&lt;/a&gt;. Forcing yourself to make models of what you think the connections amongst different concepts are puts you on the road to constructing strong mental models to lean on for those concepts in the future.&lt;/p&gt;

&lt;p&gt;A good diagram is a beautiful thing, but in my opinion a series of bad diagrams are just as cool. I love to draw out how I think a system works in my notes only to find it later and be like, "Wow that's not it at all." That's what can also make taking notes wonderful. It's not only a log of your learning. It's a log of your past mistakes. It's powerful because not only is it a source of information. It's a source of your own journey to find that information.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's your note taking style?
&lt;/h2&gt;

&lt;p&gt;In conclusion, I know it's not for everyone, but learning how to take notes has helped me improve how I learn, which makes me a better developer. Do you take notes? I'd love to hear your note-taking style!&lt;/p&gt;

</description>
      <category>learning</category>
      <category>notes</category>
    </item>
    <item>
      <title>Using Bitwise Operators</title>
      <dc:creator>Logan McDonald</dc:creator>
      <pubDate>Sun, 12 Nov 2017 17:10:06 +0000</pubDate>
      <link>https://dev.to/logan/using-bitwise-operators-6c8</link>
      <guid>https://dev.to/logan/using-bitwise-operators-6c8</guid>
      <description>

&lt;p&gt;A cool thing I learned about a couple years ago in school is bitwise operators. I honestly mostly forgot about them until a coworker pointed out an implementation in our codebase the other day. I want to talk about a couple "practical" uses for them in that I've seen.&lt;/p&gt;

&lt;p&gt;Before we begin, let's do a quick math recap. An &lt;em&gt;operator&lt;/em&gt; is a tool that acts on the operands to produce another output. Famous operators are &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, etc. It is both the element or tool that acts upon operands, and what we call the thing that denotes the action. An &lt;em&gt;operand&lt;/em&gt; is the object of the mathematical operation. So in &lt;code&gt;2 + 2&lt;/code&gt;, the &lt;code&gt;2&lt;/code&gt;s are operands, the plus sign is the operator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to Bitwise Operators
&lt;/h2&gt;

&lt;p&gt;So what are Bitwise Operators? Well, an operator that operates on bits! Basically, they are operators that move around bits in patterns (like binary numerals) at the individual level. Because they operate at such a low level, they are general very speedy. Remember operators are just like &lt;code&gt;+&lt;/code&gt;/plus and &lt;code&gt;-&lt;/code&gt;/minus so they also have mathematical symbols &lt;em&gt;and&lt;/em&gt; english names. The programmatic or mathematical denotation is going to be different across languages.&lt;/p&gt;

&lt;p&gt;I'm going to go through and explain some really common ones. Sometimes I understand code better than English so I've also just coded out in ruby what the logic &lt;em&gt;means&lt;/em&gt;, but this is my own pseudocode, &lt;em&gt;not&lt;/em&gt; source code! Ok, here are the main bitwise operators:&lt;/p&gt;

&lt;h3&gt;
  
  
  NOT
&lt;/h3&gt;

&lt;p&gt;Also known as a complement, this operation performs negation on each bit so &lt;code&gt;1111&lt;/code&gt; would become &lt;code&gt;0000&lt;/code&gt;, &lt;code&gt;10101&lt;/code&gt; becomes &lt;code&gt;01010&lt;/code&gt;, etc. In code:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;NOT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
  &lt;span class="n"&gt;bit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_char&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'0'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;'1'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'0'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  AND
&lt;/h3&gt;

&lt;p&gt;This takes &lt;em&gt;two&lt;/em&gt; operands and multiplies each bit. So &lt;code&gt;1111 AND 0000&lt;/code&gt; is &lt;code&gt;0000&lt;/code&gt; (&lt;code&gt;1*0&lt;/code&gt; across all bits), &lt;code&gt;10101 AND 00111&lt;/code&gt; is &lt;code&gt;00101&lt;/code&gt;, etc. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;AND&lt;/code&gt; reminds me of a lot of languages Boolean &lt;code&gt;||&lt;/code&gt; operators when &lt;code&gt;false || true&lt;/code&gt;, &lt;code&gt;true || true&lt;/code&gt;, &lt;code&gt;false || false&lt;/code&gt;, the bitwise &lt;code&gt;AND&lt;/code&gt; acts in an identical way, but with binary. In code:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;AND&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bit_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bit_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
  &lt;span class="n"&gt;bit_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bit_2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  OR
&lt;/h3&gt;

&lt;p&gt;This also takes &lt;em&gt;two&lt;/em&gt; operands. The &lt;code&gt;OR&lt;/code&gt; takes two bit patterns and results in &lt;code&gt;0&lt;/code&gt; if both bits are &lt;code&gt;0&lt;/code&gt;, or else &lt;code&gt;1&lt;/code&gt;. So, &lt;code&gt;1111 AND 0000&lt;/code&gt; is &lt;code&gt;1111&lt;/code&gt;, &lt;code&gt;10101&lt;/code&gt; and &lt;code&gt;00011&lt;/code&gt; is &lt;code&gt;10111&lt;/code&gt;, etc.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;OR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bit_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bit_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
  &lt;span class="n"&gt;bit_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bit_2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'0'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'0'&lt;/span&gt;
      &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s1"&gt;'0'&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s1"&gt;'1'&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  XOR
&lt;/h3&gt;

&lt;p&gt;This is our most complicated one yet. &lt;code&gt;XOR&lt;/code&gt; also takes &lt;em&gt;two&lt;/em&gt; operands where the result in is 1 if only the &lt;em&gt;first&lt;/em&gt; bit is 1 &lt;em&gt;or&lt;/em&gt; only the second bit is 1, but is 0 if both are 0 or both are 1. Ah, confusing. Let's code this.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;XOR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bit_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bit_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
  &lt;span class="n"&gt;bit_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bit_2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s1"&gt;'0'&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s1"&gt;'1'&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ah, that's better.&lt;/p&gt;

&lt;p&gt;So these operators are pretty cool! They do simple math on binary and we can kind of see how they might be useful on a theoretical level. Just like we couldn't image life without multiplication, addition, subtraction, and division, bitwise operators are essential to a computer's life. From these simple building blocks, we can make some pretty powerful math.&lt;/p&gt;

&lt;p&gt;All programming languages I've seen have bitwise methods built it, but they look a little different than what we've defined here. For example, Ruby bitwise operators:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;NOT: ~
AND: &amp;amp;
OR : |
XOR: ^
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then there are also really cool bit shifters in ruby as well: &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; and &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;. These shift the integers bits to the left or right by a given number of positions like&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;a&lt;/code&gt; is a decimal, &lt;code&gt;to_s(2)&lt;/code&gt; means &lt;code&gt;to_binary&lt;/code&gt; basically, and &lt;code&gt;&amp;gt;&amp;gt; 2&lt;/code&gt; means, shift bits right 2 places. Example in &lt;code&gt;irb&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# the binary equivalent of a&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"1000000"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# the binary equivalent of a shifted to the right&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"10000"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Anyway, we could stay here all day talking about how cool shifting bits is but I  want to go into a couple cool use cases or examples I've seen of using these practically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tic Tac Toe
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Note: In researching for this post I found this brilliant description of using bitwise operators in tic-tac-toe by Joris Labie: &lt;a href="https://codepen.io/labiej/post/using-bit-logic-to-keep-track-of-a-tic-tac-toe-game"&gt;Using bit-logic to keep track of a tic-tac-toe game&lt;/a&gt;. Make sure to check it out for a more detailed description of how this works!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Building a game of tic-tac-toe is often one of the first intro level tasks a new programmer will be asked to do. It comes up often in interviews or code challenges. When I was in Ada Academy, our introduction to JavaScript was building a tic-tac-toe game in the browser. I enjoyed the project but I had a hard time formulated a good way to make the logic for winning a game. There are a lot of different possibilities for how to win across 9 different squares. Fortunately for me, I was also first learning about bitwise operators at the time, and got to thinking that &lt;code&gt;X&lt;/code&gt;s and &lt;code&gt;O&lt;/code&gt;s aren't all that different from &lt;code&gt;1&lt;/code&gt;s and &lt;code&gt;0&lt;/code&gt;s. Perhaps I could use bitwise operator logic to keep track of combinations across the board.&lt;/p&gt;

&lt;p&gt;I knew I needed to check every move for a winning score to judge the outcome, so I wrote a method &lt;code&gt;checkEnvironment&lt;/code&gt; that would call &lt;code&gt;winningScore&lt;/code&gt; each turn which would determine if the player that went last successful created a winning pattern of &lt;code&gt;X&lt;/code&gt;s or &lt;code&gt;O&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;So here's how the &lt;code&gt;winningScore&lt;/code&gt; logic worked. It relied on an array of &lt;code&gt;binaryWins&lt;/code&gt; or 8 unique ways to win (3 horizontal, 3 vertical, 2 diagonal). These are very special numbers and taking a look at them may help to figure out why.&lt;/p&gt;

&lt;p&gt;These are the winning combination numbers in binary:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;111, 111000, 111000000, 1001001, 10010010, 100100100, 100010001, 1010100]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and in decimal:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;7, 56, 448, 73, 146, 292, 273, 84]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And then let me express them one final way, again, in binary, but with some extraneous &lt;code&gt;0&lt;/code&gt;s:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;,
&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;,
&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;,
&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;,
&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;,
&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;,
&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;,
&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Look familiar? These binary numbers are an exact expression of the wins!&lt;/p&gt;

&lt;p&gt;It might help at this point to revisit our bitwise &lt;code&gt;AND&lt;/code&gt; operator, which takes two operands and returns multiplies each bit. This means if you compare any combination that a current player has across the board, with each of the binary wins, any &lt;code&gt;0&lt;/code&gt; bit in the players combinations, cancels out and becomes &lt;code&gt;0&lt;/code&gt;, but any place where the win's combination is &lt;code&gt;1&lt;/code&gt; and the player has that &lt;code&gt;1&lt;/code&gt; will register as a hit. For example, look at me winning diagonally on this board represented as a multi-dimensional array (I'm &lt;code&gt;X&lt;/code&gt;):&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;'X'&lt;/span&gt;, &lt;span class="s1"&gt;'O'&lt;/span&gt;, &lt;span class="s1"&gt;'X'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'O'&lt;/span&gt;, &lt;span class="s1"&gt;'X'&lt;/span&gt;, &lt;span class="s1"&gt;'O'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'X'&lt;/span&gt;, &lt;span class="s1"&gt;'O'&lt;/span&gt;, &lt;span class="s1"&gt;'X'&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And here's one of the binary wins:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'0'&lt;/span&gt;, &lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we represent each of the &lt;code&gt;X&lt;/code&gt;'s on the game board as a 1, even though there are more than the three winning &lt;code&gt;X&lt;/code&gt;s, they'll be canceled out by the &lt;code&gt;AND&lt;/code&gt; operator if compared with our binary win!&lt;/p&gt;

&lt;p&gt;This is pretty cool! Now that we have our logic figured out, the code is simple (excuse my javascript, it's not my primary language, but this works!):&lt;/p&gt;

&lt;p&gt;Early on, set our binary wins:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;binaryWins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;448&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;73&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;146&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;292&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;273&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Write our &lt;code&gt;winningScore&lt;/code&gt; logic:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;winningScore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;binaryWins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;binaryWins&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;binaryWins&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Each check we iterate through the possible wins, and use our &lt;code&gt;score&lt;/code&gt; and the &lt;code&gt;win&lt;/code&gt; as operands in the &lt;code&gt;AND&lt;/code&gt; operator, i.e.&lt;br&gt;
&lt;code&gt;score &amp;amp; self.binaryWins[i]&lt;/code&gt; and return a boolean for if a winning score has been found.&lt;/p&gt;

&lt;p&gt;So this is really neat. We've just used a bitwise operator for real! But tic-tac-toe is not business logic (unless you have a really cool tic-tac-toe business, please let me know if you do). Let's explore some other ways we could use these smooth operators.&lt;/p&gt;

&lt;h2&gt;
  
  
  Boolean or Bitwise Logic?
&lt;/h2&gt;

&lt;p&gt;So we often use boolean logic in conditionals, but bitwise logic is just as generally powerful! These conditionals are often used in assigning colors on the RGB spectrum, for example. We can also assign a range of random elements to different binary numbers and use bitwise operators to compare them. &lt;code&gt;&amp;amp;&lt;/code&gt; and &lt;code&gt;|&lt;/code&gt; do a good job comparing if two sets have an intersection. &lt;code&gt;^&lt;/code&gt; can be used to see what is different between two sets. Anytime we have sets of relationships, they can be compared using bitwise logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ruby's Secure Compare
&lt;/h2&gt;

&lt;p&gt;This is the &lt;code&gt;secure_compare&lt;/code&gt; method in Ruby:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;secure_compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bytesize&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bytesize&lt;/span&gt;
  &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unpack&lt;/span&gt; &lt;span class="s2"&gt;"C&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bytesize&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="n"&gt;byte&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;secure_compare&lt;/code&gt; is a super cool method that protects us from timing attacks, or attacks where an attacker can measure stuff about the response of a site by how long it takes to repsond. When string equality operators work left to right (i.e. &lt;code&gt;user_input == 'string'&lt;/code&gt;) and a user is inputting something that controls that logic, they can execute a timing attack.&lt;/p&gt;

&lt;p&gt;So to prevent this, &lt;code&gt;secure_compare&lt;/code&gt; takes hashes of the two strings and compares those instead like:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;secure_compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="no"&gt;Digest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SHA256&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hexigest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="no"&gt;Digest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SHA256&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hexigest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we look at the code about for &lt;code&gt;secure_compare&lt;/code&gt;, we can see that it steps through each letter, unpacking the byte size as it goes. It then iterates on those characters byte sizes and uses the &lt;code&gt;XOR&lt;/code&gt; operator to compare them. We can see that if two of the bytes in the corresponding hashes mismatch,&lt;code&gt;res&lt;/code&gt; is no longer zero and the compare returns &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Each hash pasted in is of an equal length and &lt;code&gt;XOR&lt;/code&gt; is used to compare and find any differences in their binary equivalents. This is not only more secure because it takes constant time to compare the hashes (no ability to measure the time differences with different inputs), but it's also really fast!&lt;/p&gt;

&lt;h2&gt;
  
  
  Rails bitfields gem
&lt;/h2&gt;

&lt;p&gt;Finally, I want to talk about a really cool gem, &lt;a href="https://github.com/grosser/bitfields"&gt;&lt;code&gt;bitfields&lt;/code&gt;&lt;/a&gt;. It's less directly related to the operators but it uses binary logic to store things in &lt;code&gt;ActiveRecord&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Say you have a table, &lt;code&gt;Puppy&lt;/code&gt; with multiples columns &lt;code&gt;has_chew_toy&lt;/code&gt;, &lt;code&gt;likes_pets&lt;/code&gt;, and &lt;code&gt;good_walker&lt;/code&gt;, which are all Boolean values. That's a lot of trues and falses for one table that seems primarily based around Booleans. What if we could save &lt;em&gt;one&lt;/em&gt; integer to represent all these fields? We can!&lt;/p&gt;

&lt;p&gt;The Boolean values are organized like:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;true false false =&amp;gt; 1 0 0 =&amp;gt; 1
false true false =&amp;gt; 0 1 0 =&amp;gt; 2
false false false =&amp;gt; 0 0 0 =&amp;gt; 0
true true true =&amp;gt; 1 1 1 =&amp;gt; 5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And when you instantiate a new dog, you just give it the values, like&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Puppy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Bitfields&lt;/span&gt;
  &lt;span class="n"&gt;bitfield&lt;/span&gt; &lt;span class="ss"&gt;:puppy_bits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:has_chew_toy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:good_walker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:likes_pets&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;puppy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Puppy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;has_chew_toy: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;good_walker: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;puppy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;likes_toys&lt;/span&gt; &lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="n"&gt;puppy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puppy_bits&lt;/span&gt; &lt;span class="c1"&gt;# 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is pretty cool use of binary logic! And under the surface it's using &lt;a href="https://github.com/grosser/bitfields/blob/master/lib/bitfields.rb#L171"&gt;bitwise operators&lt;/a&gt; to create the relationships.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Note
&lt;/h2&gt;

&lt;p&gt;I really love learning about bitwise operators because it takes something that seems really scary and illuminates it. Bitwise operators are just like the operators we learn in elementary school, but for a numeric system we aren't familiar with. While I love this implementations, for people less familiar with the operators, the syntax can be really confusing because it looks like Boolean logic but is really different. For that reason, I really like solutions that have comments and are well documented, at least recognizing the use of a bitwise operator in a codebase.&lt;/p&gt;

&lt;p&gt;I learned a lot writing this post! If you'd like to explore these operators more in depth I've left some resources below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;Here's a collection of some helpful resources I used in forming this blog post and some code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators"&gt;Mozilla's wiki on Bitwise operators&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.calleerlandsson.com/rubys-bitwise-operators/"&gt;Bitwise Operators in Ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/loganmeetsworld/js-tic-tac-toe/tree/lm/master"&gt;my javascript tic-tac-toe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://books.google.com/books?id=zsti09XFNbEC&amp;amp;pg=PA246&amp;amp;lpg=PA246&amp;amp;dq=tic+tac+toe+bitwise+operators&amp;amp;source=bl&amp;amp;ots=u5VzY_PCUx&amp;amp;sig=ekn1-fpmR33CnNSDD2z0xnRASOQ&amp;amp;hl=en&amp;amp;sa=X&amp;amp;ved=0ahUKEwjM1--yqvPWAhXH2SYKHZQ4C2QQ6AEIUjAH#v=onepage&amp;amp;q=tic%20tac%20toe%20bitwise%20operators&amp;amp;f=true"&gt;really random helpful passage on tic-tac-toe in "Using Macromedia Flash MX" by Michael Hurwicz, Laura McCabe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://api.rubyonrails.org/v5.1/classes/ActiveSupport/SecurityUtils.html"&gt;&lt;code&gt;secure_compare&lt;/code&gt; docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://thisdata.com/blog/timing-attacks-against-string-comparison/"&gt;Timing Attacks against String Comparison by Nick Malcolm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/grosser/bitfields"&gt;&lt;code&gt;bitfields&lt;/code&gt; rails gem&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


</description>
      <category>programming</category>
      <category>bitwiseoperators</category>
      <category>binary</category>
    </item>
    <item>
      <title>How to Learn</title>
      <dc:creator>Logan McDonald</dc:creator>
      <pubDate>Mon, 16 Oct 2017 20:42:19 +0000</pubDate>
      <link>https://dev.to/logan/how-to-learn-d8e</link>
      <guid>https://dev.to/logan/how-to-learn-d8e</guid>
      <description>&lt;p&gt;For the past several years, I've been thinking a lot about learning science, or the systematic investigation of how we learn. This was fueled by a switch in career trajectories after I graduated college towards software engineering.&lt;/p&gt;

&lt;p&gt;There's this really intimidating article that I often hesitantly send people looking to get into site reliability or ops work. It's &lt;a href="https://medium.freecodecamp.org/a-roadmap-to-becoming-a-web-developer-in-2017-b6ac3dddd0cf"&gt;A roadmap to becoming a web developer in 2017&lt;/a&gt; and lays out a list of topics that one can attempt to learn in various fields of web development when they're trying to break into a field. Here is the graph of things to know for the "devops" path:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xNRbC0pW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2AQc0PqmXenUZmRvnkMh9AoQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xNRbC0pW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2AQc0PqmXenUZmRvnkMh9AoQ.png" alt="devops topics graph"&gt;&lt;/a&gt;(&lt;a href="https://github.com/kamranahmedse/developer-roadmap"&gt;Diagram credit to Github user @kamranahmedse&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Wow, this is making me sweat just looking at it. Needless to say, there's a lot to learn.&lt;/p&gt;

&lt;p&gt;In May, I gave a lightning talk at Monitorama on learning and it's connections to my job as an ops engineer: "Optimizing for Learning". You can watch the talk &lt;a href="https://vimeo.com/221064922"&gt;here&lt;/a&gt; at 6m7s. The talk is an exploration of why memorization and learning are important whenever faced with a seeming abyss of knowledge.&lt;/p&gt;

&lt;p&gt;Software engineering is an incredibly broad field. There are a lot of topics to just &lt;em&gt;know&lt;/em&gt; about, before you can even get to mastering them. This is particularly true for systems and ops engineering. Entering this field really overwhelming. In the talk I have identified one source of this overwhelming feeling - Ops is based heavily on expert intuition and experience. Experience takes time, which we often cannot control. However, I decided in the last year to balance this disadvantage with something I have slightly more control over: My learning and memory. I decided to give that talk and write this post because I realized this is a challenge everyone faces. The faster you can learn new things and connect them to what you already know and the problems you’re facing, the more effective you are at your job or starting to build something useful.&lt;/p&gt;

&lt;p&gt;Now, learning is incredibly subjective and brains are complicated. No one learns quite the same. However, I have found some patterns that have made me better at it, and I'd love to share them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hierarchies of Learning
&lt;/h2&gt;

&lt;p&gt;I start theoretically with some conceptuals diagram that I learned all the way back in the 9th grade, &lt;a href="http://www2.rgu.ac.uk/celt/pgcerttlt/how/how4a.htm"&gt;Gagne's hierarchy of learning&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Bloom%27s_taxonomy"&gt;Bloom's taxonomy of learning&lt;/a&gt;. There have been many adaptations and addendums to these hierarchies since Robert Gagne and Benjamin Bloom came up with them in the 1950s, but I find the general path of learning to be an effective mental constructs for me.&lt;/p&gt;

&lt;p&gt;The idea is that learning increases in complexity up a hierarchy and learning can often be more successful when focusing on the lower rungs, listed here lowest to highest. Here's Gagne's hierarchy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Signal learning&lt;/li&gt;
&lt;li&gt;Stimulus-response learning&lt;/li&gt;
&lt;li&gt;Chaining&lt;/li&gt;
&lt;li&gt;Verbal association&lt;/li&gt;
&lt;li&gt;Discrimination learning&lt;/li&gt;
&lt;li&gt;Concept learning&lt;/li&gt;
&lt;li&gt;Rule learning&lt;/li&gt;
&lt;li&gt;Problem solving&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And Bloom's:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Remembering&lt;/li&gt;
&lt;li&gt;Comprehending&lt;/li&gt;
&lt;li&gt;Applying&lt;/li&gt;
&lt;li&gt;Analyzing&lt;/li&gt;
&lt;li&gt;Synthesizing&lt;/li&gt;
&lt;li&gt;Evaluating&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can see we start at the lower levels with stuff like route memorization and pattern matching. This is what I like to call the "copypasta code" level of learning. I want to be clear that I'm not knocking this type of learning or copypasta code. In fact, we'd better not call it "lower" at all -- it's foundational. And many experienced programmers or subject-matter experts will often have to relearn foundational tools to learn.&lt;/p&gt;

&lt;p&gt;In both these paradigms, longterm memory building is prized at the foundational level. Built upon these skills, pattern matching and chaining information is formed. Then learning what something is NOT (analyzing, discrimination learning) starts to become helpful. For example, when I started learning a functional programming language for the first time after programming only on object-oriented languages, I was surprised how much it strengthened my understanding of OOP. Finally, when we have a good grasp of the basics, we can start to form mental models or concepts generally applicable across different types of examples. Finally, we can create. Honestly, I think there should be a final item with both of these hierarchies -- opinions. They should be a thing you can hold at the highest rung. Unfortunately, many ranks these much lower in their learning calculus.&lt;/p&gt;

&lt;p&gt;While I definitely (and I assume most people do) interact with these hierarchies in very non-linear ways, they can be incredibly helpful when setting out to learn anything new. And they'll often help explain to me why, when learning Go for the first time for example, I couldn't right away start creating or solving complex problems in it.&lt;/p&gt;

&lt;p&gt;Over the last year, in order to inch closer towards the top of these hierarchies, I've become reacquainted with some old enemies: quizzes and flashcards.&lt;/p&gt;

&lt;p&gt;This is because I realized early on in my first year as an ops engineer that the more I knew about the tools as my disposal, the faster I could recognize the constraints of any given project I was assigned. This is because once you have knowledge (no expertise needed!) you can start to ask better questions. When you have good memory, it allows you to be more creative in solving problems.&lt;/p&gt;

&lt;p&gt;I found success learning about the things that inhabit the ops universe in a couple ways:&lt;/p&gt;

&lt;h2&gt;
  
  
  Practicing Retrieval
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Continuous development and testing for your brain!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Simply re-reading material has been proven to not work. However, practicing retrieval of that material can. Retrieval is just recalling something from memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Low stakes testing
&lt;/h3&gt;

&lt;p&gt;Try testing yourself after you read something. Retrieval is proven to force the brain to make strong connections to concepts. While short term memory kind of sucks, our longterm memory is incredibly plastic. But don’t test yourself on things right away. Difficult learning leads to stronger memory. By spacing out your retrieval you make your brain strain more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reflection
&lt;/h3&gt;

&lt;p&gt;Writing about something after you learn it. Reflection helps consolidate ideas into longterm memory because it links them to experience we already have. It’s as simple as asking yourself what went well, could have gone better, could do next time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory Palaces
&lt;/h2&gt;

&lt;p&gt;I’ve used memory palaces to remember concepts around networking, HTTP codes, linux features, and AWS services.&lt;/p&gt;

&lt;p&gt;Builds on a cool feature many humans have called imagination inflation. This is the ability for us to imagine things so strongly we trick our brains into believing they are real and saving them in memory as real.&lt;/p&gt;

&lt;p&gt;You just take a place you are already familiar with and place pieces of information throughout it while imagining something visceral or absurd in the place to make you remember. Like tarantulas passing notes in your living room to remind yourself about TCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Constructing Mental Models
&lt;/h2&gt;

&lt;p&gt;Mental models are the result of the extraction process where you take key concepts from new material and organize them. As we start to gather information about the ops universe, and monitoring systems for example, we are building up abstractions of those monitoring systems that will allow us to design other types of systems that aren’t exactly the same. Mental models, in other words, are what makes up expert intuition. &lt;/p&gt;

&lt;h2&gt;
  
  
  Having a Growth Mindset
&lt;/h2&gt;

&lt;p&gt;The final memory tool that has been essential in this year is having, and working with people who have, a growth mindset.&lt;/p&gt;

&lt;p&gt;There was a 2010 study done on 5th graders by the researcher Carol Dweck in New York where researchers gave them puzzles. After completing the puzzles, they told them either that they were very smart or that they worked very hard. They gave them another round of harder puzzles. The kids told that they worked hard did much better.&lt;/p&gt;

&lt;p&gt;Here's a quote from the study:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Emphasizing natural intelligence takes it out of the child’s control, and it provides no good recipe for responding to a failure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Learning requires failure. Ops engineering definitely requires failure.&lt;/p&gt;

&lt;p&gt;Surround yourself with people who believe this. I am lucky to work with a team the praises each other for working hard on difficult problems, not for being “smart” or naturally great engineers.&lt;/p&gt;

&lt;p&gt;If any of these strategies are interesting to you, I took a lot of suggestions from &lt;a href="https://www.amazon.com/Make-Stick-Science-Successful-Learning/dp/0674729013"&gt;Make it Stick&lt;/a&gt;, a book about learning science.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Note
&lt;/h2&gt;

&lt;p&gt;As a final note, I want to say that while learning how to learn can be a great way for people new to any topic to level-up, it's also a powerful thing for anyone in a technical leadership position to embrace as well. First, it'll allow you to mentor and train new engineers faster. Second, recognizing the fundamental importance of pattern matching and copying should force us to make code bases, runbooks, and documentation that is kind and considerate towards newcomers. We are all constantly learning across different levels of understanding. We are all trying to take our learning to the level of craft. Understanding how we learn can help not only ourselves learn faster, but be more empathetic in general.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I hope to share more learning tips and tricks as I come across them. Also, I'm using this blog as a sort of longform of reflection and retrieval, to help myself learn as well.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>learning</category>
      <category>career</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
