<?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: Anthony D. Mays</title>
    <description>The latest articles on DEV Community by Anthony D. Mays (@anthonydmays).</description>
    <link>https://dev.to/anthonydmays</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%2F148563%2Fe17ed6ad-617e-4d79-b7db-1754f161cced.jpeg</url>
      <title>DEV Community: Anthony D. Mays</title>
      <link>https://dev.to/anthonydmays</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anthonydmays"/>
    <language>en</language>
    <item>
      <title>Coding Interview Preparation: Building a Plan for Success</title>
      <dc:creator>Anthony D. Mays</dc:creator>
      <pubDate>Fri, 08 Sep 2023 21:36:22 +0000</pubDate>
      <link>https://dev.to/anthonydmays/coding-interview-preparation-building-a-plan-for-success-boc</link>
      <guid>https://dev.to/anthonydmays/coding-interview-preparation-building-a-plan-for-success-boc</guid>
      <description>&lt;p&gt;Coding interview preparation can seem like an incredibly daunting task. This is especially true if you’ve never done one before, if you are a self-taught developer or bootcamp grad, or if you don’t have much industry experience. Unlocking the coding interview opens the door to top pay, benefits, and perks at premier tech companies. &lt;/p&gt;

&lt;p&gt;The key to preparing well for a coding interview is having a great preparation plan. A structured coding interview preparation plan can bolster your confidence and readiness. It also ensures that you will spend your time optimally without getting overwhelmed.&lt;/p&gt;

&lt;p&gt;Though we’ll be focusing primarily on coding interview prep, the strategies we’ll discuss here apply to other interview types as well, both technical and non-technical.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coding interview prep starts with the job description
&lt;/h2&gt;

&lt;p&gt;Crafting a great coding interview preparation plan begins with the job description. It is likely the first official documentation you’ll read regarding the job. Hiring managers and recruiters will take hours and even days to define and refine a good job description. It describes the ideal candidate they hope to attract. It will also serve as the source of truth for skills you’re expected to display in the interview process.&lt;/p&gt;

&lt;p&gt;Make sure to read the job description between three to five times at minimum. As you read, keep a pen and paper handy and have a dictionary available to look up unfamiliar words. Having a search engine is also useful for looking up concepts that aren’t immediately clear.&lt;/p&gt;

&lt;p&gt;The aim of reading the job description is to establish an initial study list. Here’s how I recommend you study the job description for coding interview prep:&lt;/p&gt;

&lt;h2&gt;
  
  
  A step-by-step process for reading the job description
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;On the first couple of passes, read through the content passively noting the overall structure and tone. Resist the temptation to dig into details just yet. Try not to even take notes. At this point, this is more about the forest than the trees. Focus on absorbing the whole job description as a unit. Get a sense of how everything fits and flows together. At this stage, you’ll begin to start unconsciously memorizing words and phrases. This will help you later in the process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the next phase, read through the job description starting again from the beginning. Highlight any words, phrases, or concepts that stand out. Focus especially on things that are repeated multiple times. Repetition is often used to imply emphasis and importance. These are the things that you should prioritize in your preparation plan.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the last iterations, write out a list of topics that will form the foundation of your study list. Organize your list into three categories: 1) technical skills, 2) soft skills, and 3) key values. For your coding interview preparation plan, the technical skills category will matter the most.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Research the interview process
&lt;/h2&gt;

&lt;p&gt;Now, with a solid understanding of the job description, it’s time to research the interviews. Your research should reveal the types of interviews you will encounter. It will also help you to nail down even more specific topics you should know. If you are reading this article, I assume you already know that a coding interview will be involved. But there are other types of interviews you will also need to anticipate in your interview preparation plan.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where to research the interview process
&lt;/h3&gt;

&lt;p&gt;Here are some places you should look for details on the interview process (in order):&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Your recruiter
&lt;/h4&gt;

&lt;p&gt;For top tech companies, you will almost certainly be assigned a recruiter who will discuss the role with you. They will be a fountain of pivotal information upon which you would do well to rely. Use your recruiter to tease out the nuance in the job description and get more details around interview specifics. They can also give you up-to-date information that the job description may not yet present. They may even tell you what things you can safely ignore.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. The company website
&lt;/h4&gt;

&lt;p&gt;Many companies in recent years have built their own interview preparation resources designed to help you understand their unique process. No two companies interview exactly alike, so understanding the process for a specific company is important. My favorite so far is Google’s own &lt;a href="https://techdevguide.withgoogle.com/"&gt;Tech Dev Guide&lt;/a&gt;. It contains example problems, links to free courses, and practice assessments. Amazon also has some &lt;a href="https://www.amazon.jobs/en/landing_pages/interviewing-at-amazon"&gt;useful resources&lt;/a&gt; that you should read if you’re interviewing there.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Third-party review sites
&lt;/h4&gt;

&lt;p&gt;Third-party sites can provide a wealth of information about the interview process. My favorites are &lt;a href="http://glassdoor.com/"&gt;Glassdoor&lt;/a&gt; and &lt;a href="http://teamblind.com/"&gt;Blind&lt;/a&gt;. However, you need to carefully consider that any reviews on these sites are non-authoritative. They may not apply to your specific interview process. Like other review sites, people are most likely to leave reviews when they are unhappy. Be wary of bias.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Employee or ex-employee blogs
&lt;/h4&gt;

&lt;p&gt;It is not too hard to find people who work at your target company using tools like LinkedIn or Medium. Sometimes, you’ll find that these individuals have blogs and that they write about their interview experience in way more detail than you’ll find in other places.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare for the recruiter screen
&lt;/h2&gt;

&lt;p&gt;Apart from the coding interview, one of the first ones to prepare for is the recruiter screen. Early in my career, I didn’t even realize that I was in a recruiter screen interview until after the fact. Now, I treat every conversation with a prospective company as an interview and do my best to prepare accordingly.&lt;/p&gt;

&lt;p&gt;You won’t get to do the coding interview if you don’t pass muster with the recruiter. This won’t be a difficult assessment. Rather, the recruiter screen is a pretty straightforward check of your skills and your interest. You could be asked about programming languages, frameworks, and projects you’ve worked on in the past. The recruiter will also assess your interest in the role and determine how active your job search is.&lt;/p&gt;

&lt;p&gt;You can prepare for the recruiter screen by reviewing your resume, familiarizing yourself with basic behavioral interview questions, and understanding the job description.&lt;/p&gt;

&lt;p&gt;In addition to preparing for recruiter questions, make sure that you have a couple of questions ready to ask. Get all the information you can around the interview process and the position you’re interviewing to fill. You might even learn about the specific team that’s hiring and the kind of work you may be doing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Review design principles for your coding interview prep
&lt;/h2&gt;

&lt;p&gt;Now if you’ve been wondering when I was going to get to the coding part of the coding interview preparation process, don’t worry! We’ll get there soon. But first, we need to talk about design principles.&lt;/p&gt;

&lt;p&gt;You need to write good, clean code that is idiomatic for your programming language. It also needs to be largely bug free and syntactically correct as well. If you’re going well under a stress-inducing live coding interview, make sure you are solid on code design.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strategies for reviewing design principles
&lt;/h3&gt;

&lt;p&gt;Write code everyday. This is easier to do if you already have a full-time coding job. If you aren’t employed, make your own opportunities so that you are building muscle in your programming languages and tools.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Review good code construction practices. The goal is to know how to define good variable names, clear functions, and well-structured classes. There are good books on writing high-quality code like Robert C. Martin’s “Clean Code” or Steve McConnell’s “Code Complete.” You don’t have to agree with everything that they recommend. However, their insights will help you to think about how to write code for clarity, extensibility, and easier maintainability. Style guides are also great. I really like &lt;a href="https://google.github.io/styleguide/"&gt;Google’s style guidelines&lt;/a&gt; and &lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/identifier-names"&gt;Microsoft’s as well&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once you understand how to write well organized functions and classes, it’s time to think about code design patterns. Start off by reviewing &lt;a href="https://www.freecodecamp.org/news/solid-design-principles-in-software-development/"&gt;SOLID design principles&lt;/a&gt; and understand the differences and tradeoffs between object-oriented programming (OOP) and functional programming. Also, lock in the essential Gang of Four design patterns. I grew up learning these from the book &lt;a href="https://www.amazon.com/Head-First-Design-Patterns-Brain-Friendly/dp/0596007124"&gt;Head First Design Patterns&lt;/a&gt;. There are also YouTube videos and websites like &lt;a href="https://refactoring.guru/design-patterns"&gt;Refactoring Guru&lt;/a&gt; or &lt;a href="https://www.geeksforgeeks.org/"&gt;GeeksforGeeks&lt;/a&gt; that are pretty great too.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lastly, make it a practice to read good code regularly. It’s not hard to find decent repos on GitHub, maybe even from your prospective company. If you’re doing coding interviews with companies that have rigorous style guides and conventions, read examples of their code. This is especially useful for FAANG company interview prep. Make it a point to do your best to mimic that style. It’s about looking like you’re already an engineer who would fit right in with their engineering culture.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Figure out your priority list
&lt;/h2&gt;

&lt;p&gt;You’re almost ready to build your coding interview preparation plan. You should already be aware of what you need to know for your interview. There is just one more thing that you need in order to proceed: a priority list.&lt;/p&gt;

&lt;p&gt;Building a prioritized list of topics helps you to organize your preparation. It will help you tackle the most important things early on and save the easier stuff for later. But how do you know what should go first, second, and third on your list? You might already have an intuition about this. However, I recommend that you validate by benchmarking yourself using sample questions and problems by topic area. You can use a stopwatch to measure how long it takes you to provide an optimal answer. The slower you are, the more work you need to do to get faster over time.&lt;/p&gt;

&lt;p&gt;The hardest part of this step will be figuring out what your benchmark assessment will look like. If you’re going to have behavioral, live coding, and knowledge interviews, then you’ll want questions for each type. For FAANG style coding interviews, I picked a couple of questions from each section of &lt;a href="https://www.crackingthecodinginterview.com/"&gt;Cracking the Coding Interview&lt;/a&gt;, a few &lt;a href="https://www.techinterviewhandbook.org/behavioral-interview-questions/"&gt;behavioral questions&lt;/a&gt;, and some random Java language quiz I found. That could easily have you working through 40 problems and questions before you’ve even started studying!&lt;/p&gt;

&lt;p&gt;After you have worked through sample problems, you should have a good idea of what your strengths and weaknesses are. You will have a well-informed, data-driven priority list tailored to your skill set and the role for which you’re applying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build your coding interview preparation plan
&lt;/h2&gt;

&lt;p&gt;At this point, you should have all of the necessary inputs to build a good coding interview preparation plan. You now need to combine all your data into a cohesive preparation strategy. Your plan will largely dictate what you need to study and when you should study it. Now is the time to put on your project manager hat!&lt;/p&gt;

&lt;p&gt;Time is going to play a big factor in how you arrange your plan, so starting early is key. It probably won’t be realistic to expect that you’ll spend 10 hours a day studying. Some of you reading this may be able to. However, most people cannot just start from zero and suddenly sustain a rigorous work ethic without getting crushed. It’s usually better to work up to this.&lt;/p&gt;

&lt;p&gt;Figure out how many hours you can commit per day and on what days of the week. Then, extrapolate how long it will take you to cover everything on your list. Alternatively, work backwards from your interview date. Determine how many topics you can reasonably cover with the time you have, then set a schedule. If you think you need to push your interview date to give yourself more time, talk to your recruiter ASAP.&lt;/p&gt;

&lt;p&gt;Here are the elements that should be included in your preparation regimen:&lt;/p&gt;

&lt;h3&gt;
  
  
  Coding problems
&lt;/h3&gt;

&lt;p&gt;This one is pretty obvious. You’re going to be working through LeetCode and HackerRank style coding problems to build up muscle in this area. You should select your problems based upon your priority list and occasionally mix in random easy and medium level problems. I recommend working through pre-organized lists of problems that help you focus on specific patterns. And remember, your goal isn’t to memorize solutions. It’s to memorize and feel comfortable with patterns and common paradigms.&lt;/p&gt;

&lt;p&gt;Do keep in mind that not every interview features data structure and algorithms style interview questions. Make sure to find coding questions appropriate to the interview type you expect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Memorization exercises
&lt;/h3&gt;

&lt;p&gt;I recommend to my clients that they memorize several algorithms and data structures and write out the code by hand. Not only does this give you something to code each day, but it helps you understand these algorithms better.&lt;/p&gt;

&lt;h3&gt;
  
  
  Knowledge tests and quizzes
&lt;/h3&gt;

&lt;p&gt;Your coding interview may feature fast-fire knowledge questions about programming languages and principles. Make it a habit to quiz yourself regularly on key terms and design principles so that the information stays fresh.&lt;/p&gt;

&lt;h3&gt;
  
  
  Behavioral questions and STAR responses
&lt;/h3&gt;

&lt;p&gt;Make sure to pre-craft responses to the most common behavioral questions and rehearse them. Rehearsing responses will help you answer questions fluidly and succinctly in an interview situation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mock interviews
&lt;/h3&gt;

&lt;p&gt;Although you will spend much time studying on your own, you must also practice being interviewed by another human being. I have come to believe that mock interviews are the cornerstone of a good coding interview preparation strategy. Sure, you can also watch sample mock interviews on YouTube and on other platforms. But there’s nothing like sitting in the hot seat yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reading articles and blogs
&lt;/h3&gt;

&lt;p&gt;You should have a reading list that you can work through covering some of the things we discussed earlier. This includes reading news about the company for which you’re applying, books on good code design and design patterns, and blog articles about system design. You might even continue reading interview stories from individuals who have gone through the interview process for which you are preparing. And, if nothing else, keep reading good code so that you become more comfortable with best practices and patterns.&lt;/p&gt;

&lt;h2&gt;
  
  
  A note to the overwhelmed
&lt;/h2&gt;

&lt;p&gt;I know that we’ve covered a lot of information in this article. This all might have you feeling some kind of way (as my wife likes to say). It took me 15 years to figure out everything that I’m sharing with you. Trust me, this isn’t even half of it. There’s even more I could teach you.&lt;/p&gt;

&lt;p&gt;If the thought of all this preparation has you feeling overwhelmed, don’t worry. Give yourself time and permission to work though this content at a pace that makes sense for you. Read this article a few times. Let it soak in. Then do a little bit at a time. Not everybody will need to do everything that I’ve spelled out exactly as I’ve written it here. &lt;/p&gt;

&lt;p&gt;If you need help crafting your plan, you can &lt;a href="https://morganlatimer.com/"&gt;book a complimentary consultation&lt;/a&gt; with me. I’ll be glad to discuss your unique situation. I’ve also got a &lt;a href="https://morganlatimer.com/webinar"&gt;free upcoming live webinar&lt;/a&gt; on technical interviewing that you can join. I’ll teach you even more stuff about succeeding at technical interviews to help you win.&lt;/p&gt;

</description>
      <category>interview</category>
      <category>career</category>
      <category>productivity</category>
    </item>
    <item>
      <title>gRPC vs REST: Comparing API Styles in Practice</title>
      <dc:creator>Anthony D. Mays</dc:creator>
      <pubDate>Tue, 21 Feb 2023 22:39:22 +0000</pubDate>
      <link>https://dev.to/anthonydmays/grpc-vs-rest-comparing-api-styles-in-practice-4bl</link>
      <guid>https://dev.to/anthonydmays/grpc-vs-rest-comparing-api-styles-in-practice-4bl</guid>
      <description>&lt;p&gt;In this article, we'll explore APIs created using both the REST architecture and a fairly new player called gRPC. Our goal is to understand how to use these architectural styles to build APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is REST?
&lt;/h2&gt;

&lt;p&gt;In 2000, Roy Fielding wrote his dissertation and introduced the world to an architecture for distributed systems called "Representational State Transfer," or REST for short. He outlined several constraints for system architecture rooted in the principles that drive the web itself. The goal was to leverage decades of wisdom around building distributed systems that helped to ensure good separation of concerns and scalability.&lt;/p&gt;

&lt;p&gt;Central to the REST philosophy is the concept of hypermedia and hypertext (like the "H" in HTTP). A RESTful API allows users to interact with resources identified by URLs and encoded in a variety of hypermedia representations (such as JSON, XML, or HTML). Modifying these resources changes the application state. Typically, clients use HTTP as the protocol of choice for building and interacting with RESTful service.&lt;/p&gt;

&lt;p&gt;An oft neglected but critical concept to REST is the idea of hypermedia as the engine of application state (HATEOAS). Simply put, instead of clients choosing what methods to invoke to change an application's state, it's the hypermedia itself that determines what resources a client can interact with and at what time. This is similar to how users interact with web pages today. Users only need to visit a single URL and links provided on the resulting page inform the user where they can browse.&lt;/p&gt;

&lt;p&gt;REST is designed to leverage all of the existing technologies that make the web work, especially HTTP, TCP, URLs, and hypermedia types like JSON, XML, and HTML. To that end, no special software is required in order to build or use RESTful APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is gRPC?
&lt;/h2&gt;

&lt;p&gt;The distributed client-server communication style known as "Remote Procedure Call" (RPC) is nothing new, dating back to at least the early 80s. However, Google's implementation known as gRPC was invented in 2015 as a performance-centric framework for enabling web communication between systems. Built to leverage the newer HTTP/2 protocol under the hood, gRPC supports bidirectional communication between clients and servers in addition to streaming capabilities that enable multiple messages per request or response. This makes it very efficient for building high-performance, high-throughput applications. &lt;em&gt;Performance&lt;/em&gt; is the killer feature of gRPC.&lt;/p&gt;

&lt;p&gt;Unlike RESTful APIs, RPC-based APIs define procedures (or methods) using an Interface Definition Language (IDL). Tools are required to generate server and client stub classes from the interface definition that can be used in a variety of programming languages. For gRPC, Google chose to develop its own format called "Protocol Buffers" (or "protobufs" for short) which benefit from a very efficient wire serialization format designed for speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demonstrating an address book using REST and gRPC
&lt;/h2&gt;

&lt;p&gt;Let's take a look at some sample projects that demonstrate the distinctions between the REST and gRPC architectural styles. All of the projects we'll examine are implemented as a full-stack address book apps with a simple front-end UI built on &lt;a href="https://svelte.dev/" rel="noopener noreferrer"&gt;Svelte&lt;/a&gt; and a &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;NodeJS&lt;/a&gt; back-end API. You can find the sample project monorepos on GitHub at &lt;a href="https://github.com/anthonydmays/grpc-vs-rest" rel="noopener noreferrer"&gt;anthonydmays/grpc-vs-rest&lt;/a&gt;.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anthonydmays" rel="noopener noreferrer"&gt;
        anthonydmays
      &lt;/a&gt; / &lt;a href="https://github.com/anthonydmays/grpc-vs-rest" rel="noopener noreferrer"&gt;
        grpc-vs-rest
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Demo projects for the "gRPC vs REST" session at Hacking With The Homies Developers Conference 2023.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;gRPC vs REST Demos&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Description&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;This repo contains three full-stack monorepos demonstrating the REST and gRPC API architectural styles. See the README in each of the subprojects for instructions on how to run each demo.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Author&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Anthony D. Mays (&lt;a class="mentioned-user" href="https://dev.to/anthonydmays"&gt;@anthonydmays&lt;/a&gt;) - &lt;a href="https://twitter.com/anthonydmays" rel="nofollow noopener noreferrer"&gt;Twitter&lt;/a&gt; | &lt;a href="https://linkedin.com/in/anthonydmays" rel="nofollow noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | &lt;a href="https://github.com/anthonydmays" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Projects&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;The following is a description of the projects you can demo.&lt;/p&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Project&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://github.com/anthonydmays/grpc-vs-restrest-api-app/" rel="noopener noreferrer"&gt;rest-api-app&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Address book app built using a REST API built on Express and a Svelte fronted.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://github.com/anthonydmays/grpc-vs-restgrpc-api-app/" rel="noopener noreferrer"&gt;grpc-api-app&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Address book app built using a gRPC API.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://github.com/anthonydmays/grpc-vs-restgrpc-rest-app/" rel="noopener noreferrer"&gt;grpc-rest-app&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Address book app built using a gRPC API with a REST endpoint using an Envoy reverse proxy.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Resources&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/anthonydmays/grpc-vs-rest-comparing-api-styles-in-practice-4bl" rel="nofollow"&gt;gRPC vs REST: Comparing API Styles in Practice&lt;/a&gt; by Anthony D. Mays&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://cloud.google.com/blog/products/api-management/understanding-grpc-openapi-and-rest-and-when-to-use-them" rel="nofollow noopener noreferrer"&gt;gRPC vs REST: Understanding gRPC, OpenAPI and REST and when to use them in API design&lt;/a&gt; by Martin Nally&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm" rel="nofollow noopener noreferrer"&gt;Architectural Styles and the Design of Network-based Software Architectures&lt;/a&gt; by Roy Fielding&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/devaddict/use-grpc-with-node-js-and-typescript-3c58" rel="nofollow"&gt;Use gRPC with&lt;/a&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/anthonydmays/grpc-vs-rest" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;To keep things simple, I only have a few features I've implemented along with several key constraints.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Implement basic CRUD operations&lt;/strong&gt;. Nothing special here in the way of functional requirements. We just want to be able to list all of our contacts and create, update, or delete a single contact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full-stack type safety&lt;/strong&gt;. We should be able to ensure that our entire codebase is type-safe and supports modern IDE niceties like autocomplete.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Browser-consumable API&lt;/strong&gt;. We want to allow any clients to use our API from the browser environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unit-testable code&lt;/strong&gt;. It should be fairly trivial to write unit tests for our API to ensure that we have the behavior we expect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal diffs&lt;/strong&gt;. In order to highlight the differences when moving between styles, I've done my best to minimize differences between the sample projects at the expense of some best practices. These demos are not designed to show you how to write production-ready systems, but rather to help you understand each style sufficiently.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Examining the REST API app
&lt;/h2&gt;

&lt;p&gt;First, let's get the API and client up and running. Clone the &lt;a href="https://github.com/anthonydmays/grpc-vs-rest" rel="noopener noreferrer"&gt;anthonydmays/grpc-vs-rest&lt;/a&gt; repo to your machine, open a terminal, and change into the &lt;a href="https://github.com/anthonydmays/grpc-vs-rest/tree/main/rest-api-app" rel="noopener noreferrer"&gt;rest-api-app&lt;/a&gt; directory. Follow the README instructions to install dependencies and build the &lt;code&gt;apiTypes&lt;/code&gt; package. The commands are shown below for your convenience:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://github.com/anthonydmays/grpc-vs-rest
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;rest-api-app
&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;npm run build:apiTypes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In separate terminal windows, run the server by executing the &lt;code&gt;npm run dev:api&lt;/code&gt; command and the client using &lt;code&gt;npm run dev:client&lt;/code&gt;. You should be able to now browse to &lt;code&gt;http://localhost:5173&lt;/code&gt; to see the basic UI.&lt;/p&gt;

&lt;p&gt;Let's turn our attention to the API for a moment. I'll use &lt;code&gt;curl&lt;/code&gt; to retrieve a single contact in order to demonstrate what makes our API conformant with REST principles. We'll see from the response how our API satisfies REST architectural constraints.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-iX&lt;/span&gt; GET http://localhost:9090/v1/contacts/1
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: &lt;span class="k"&gt;*&lt;/span&gt;
Content-Type: application/json&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;utf-8
Content-Length: 349
ETag: W/&lt;span class="s2"&gt;"15d-bXqO1UHKOU8wml7G/sca1xVRseU"&lt;/span&gt;
Date: Mon, 20 Feb 2023 22:54:24 GMT
Connection: keep-alive
Keep-Alive: &lt;span class="nb"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5

&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"resource"&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"uri"&lt;/span&gt;:&lt;span class="s2"&gt;"contacts/1"&lt;/span&gt;,&lt;span class="s2"&gt;"firstName"&lt;/span&gt;:&lt;span class="s2"&gt;"Hedda"&lt;/span&gt;,&lt;span class="s2"&gt;"lastName"&lt;/span&gt;:&lt;span class="s2"&gt;"Ready"&lt;/span&gt;,&lt;span class="s2"&gt;"email"&lt;/span&gt;:&lt;span class="s2"&gt;"hready0@ftc.gov"&lt;/span&gt;,&lt;span class="s2"&gt;"phoneNumber"&lt;/span&gt;:&lt;span class="s2"&gt;"919-521-1661"&lt;/span&gt;,&lt;span class="s2"&gt;"_links"&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"self"&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;:&lt;span class="s2"&gt;"http://localhost:9090/v1/contacts/1"&lt;/span&gt;,&lt;span class="s2"&gt;"type"&lt;/span&gt;:&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="s2"&gt;"allContacts"&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;:&lt;span class="s2"&gt;"http://localhost:9090/v1/contacts"&lt;/span&gt;,&lt;span class="s2"&gt;"type"&lt;/span&gt;:&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="s2"&gt;"delete"&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;:&lt;span class="s2"&gt;"http://localhost:9090/v1/contacts/1"&lt;/span&gt;,&lt;span class="s2"&gt;"type"&lt;/span&gt;:&lt;span class="s2"&gt;"DELETE"&lt;/span&gt;&lt;span class="o"&gt;}}}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Consistent identification of resources&lt;/strong&gt;: Our API identifies resources by URL. For any resource available to us via the API, there is a unique URL that we can use to access or act upon it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manipulation of resources through representation&lt;/strong&gt;: We can see a list of contacts by issuing an HTTP GET request to &lt;code&gt;http://localhost:9090/v1/contacts&lt;/code&gt;. If we issue an OPTIONS request, we'll see that we can also &lt;code&gt;POST&lt;/code&gt; to this resource to create a new contact if we wish. By sending the JSON-representation of a contact, we'll be able to update properties of that contact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-descriptive messages&lt;/strong&gt;: The &lt;code&gt;contacts&lt;/code&gt; resource is represented using the &lt;code&gt;application/json&lt;/code&gt; hypermedia format. We can see exactly the fields available to us and their basic types (string, numeric, array, and anything else JSON supports).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hypermedia as the engine of application state (HATEOAS)&lt;/strong&gt;: Importantly, the resource also provides us with links that tell us what other operations we can perform on this resource or other related resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cacheability&lt;/strong&gt;: Since we're just using HTTP, we already have all the mechanisms we need to indicate whether a resource can be cached or not. We can also use ETags to convey this same information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stateless&lt;/strong&gt;: Interactions between the client and our API server are stateless. Everything needed for the server to understand a request is provided in the request itself. The server does not store any state about previous requests or responses in order to fulfill new requests. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now if we look at our client app, we'll see something a bit unusual about the front-end implementation. Since our aim is to abide by RESTful constraints, we are required to use the links provided by our hypermedia resource in order to do anything with the API. It's important to note that there is no URL construction happening in our client. We are simply using whatever we're given from the API.&lt;/p&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funb8blhdwc7ocxj67g34.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funb8blhdwc7ocxj67g34.png" alt="Address book UI screenshot showing paging controls"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- packages/client/src/routes/+page.svelte --&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Paging controls for navigating our list of contacts --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;
  {#if data._links?.firstPage}
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"?url={encodeURIComponent(data._links.firstPage.href)}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{'&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;'}&amp;lt;/&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; |
  {/if}
  {#if data._links?.previousPage}
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"?url={encodeURIComponent(data._links.previousPage.href)}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{'&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;'}&amp;lt;/&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    |
  {/if}
  {#if data._links?.nextPage}
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"?url={encodeURIComponent(data._links.nextPage.href)}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{'&amp;gt;'}&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt; |
  {/if}
  {#if data._links?.lastPage}
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"?url={encodeURIComponent(data._links.lastPage.href)}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{'&amp;gt;&amp;gt;'}&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  {/if}
&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** file: packages/client/src/routes/+page.ts */&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$env/dynamic/public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ListContactsResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@grpc-vs-rest/api-types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PageLoad&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./$types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/** Handles loading data for the page. */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;load&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Anchor links in the UI configure the URL parameter based &lt;/span&gt;
  &lt;span class="c1"&gt;// on whatever is provided by the API.  &lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apiEndpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PUBLIC_API_ENDPOINT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:9090/v1/contacts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;apiEndpoint&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ListContactsResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="nx"&gt;satisfies&lt;/span&gt; &lt;span class="nx"&gt;PageLoad&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Taking a look at gRPC
&lt;/h2&gt;

&lt;p&gt;Switching it up a bit, let's now examine the gRPC API implementation which you'll find in the &lt;a href="https://github.com/anthonydmays/grpc-vs-rest/tree/main/grpc-api-app" rel="noopener noreferrer"&gt;grpc-api-app&lt;/a&gt; directory. The structure of this project is identical to our rest app, so I'll just focus on the essential bits that have changed. Let's start with the &lt;code&gt;apiTypes&lt;/code&gt; project.&lt;/p&gt;

&lt;p&gt;In order to define the contract by which the server and client will communicate with one another, we define a proto with the services, functions, parameters, and model definitions we need. We have a single proto defined in our &lt;code&gt;apiTypes&lt;/code&gt; project under the namespace &lt;code&gt;proto.contacts.v1&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** file: packages/apiTypes/proto/contacts/v1/contacts.proto */&lt;/span&gt;

&lt;span class="c1"&gt;// An API for managing a collection of contacts.&lt;/span&gt;
&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;ContactsService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// List all available contacts.&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;ListContacts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListContactsRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListContactsResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Retrieves a specific contact.&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;GetContact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetContactRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetContactResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Updates a contact with the provided information.&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;UpdateContact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UpdateContactRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UpdateContactResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Deletes a contact with the provided id.&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;DeleteContact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeleteContactRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;google.protobuf.Empty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Creates a contact.&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;CreateContact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateContactRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateContactResponse&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;The second big difference is that we now have auto-generated client and server stubs. For this task, I chose to use &lt;a href="https://github.com/bufbuild/buf" rel="noopener noreferrer"&gt;buf&lt;/a&gt; and the &lt;a href="https://github.com/timostamm/protobuf-ts" rel="noopener noreferrer"&gt;protobuf-ts&lt;/a&gt; plugin in order to generate idiomatic Typescript classes and objects. Not only do these classes describe the types we'll use in the server and client, but also includes the actual gRPC implementations used to serialize and send messages back and forth across the wire.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# /proto/buf.gen.yaml&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ts&lt;/span&gt;
    &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;src/&lt;/span&gt;
    &lt;span class="na"&gt;opt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;generate_dependencies,long_type_string,server_generic,client_generic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next comes the server. The implementation is fairly trivial, thanks to the straightforward service interface produced by &lt;code&gt;protobuf-ts&lt;/code&gt;. Note that, for this demo, we've ditched &lt;code&gt;Express&lt;/code&gt; as the server and will instead host our service via the built-in &lt;code&gt;node:http2&lt;/code&gt; module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** file: packages/api/src/index.ts */&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@grpc-vs-rest/api-types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ServerCredentials&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@grpc/grpc-js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;adaptService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@protobuf-ts/grpc-backend&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ServerCallContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@protobuf-ts/runtime-rpc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;createContact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;deleteContact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;getContact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;getContacts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;getContactsCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;updateContact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./contacts.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContactsService&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;IContactsService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;listContacts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ListContactsRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ServerCallContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ListContactsResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;pageNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;orderBy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;pageSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pageSize&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;pageNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pageNumber&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contacts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getContacts&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;pageNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;orderBy&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;pageNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;totalCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;getContactsCount&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="c1"&gt;// Implement remaining server methods.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;9090&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bindAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s2"&gt;`0.0.0.0:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;ServerCredentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createInsecure&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;adaptService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ContactsService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ContactsService&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`server is running on 0.0.0.0:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we now run our client and inspect requests to the API using a packet sniffer such as Wireshark, you'll see that the response for the same contact retrieval method we implemented in REST is substantially smaller in size at 132 bytes compared to 349 bytes of JSON that was delivered previously.&lt;/p&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foir0wefmet7rlltk0n9x.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foir0wefmet7rlltk0n9x.png" alt="Inspecting gRPC response using Wireshark "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is one more significant change to note. What might not be obvious is that the gRPC client code is required to run server-side (note that the load function for the main page is named &lt;code&gt;+page.server.ts&lt;/code&gt; to denote a server-side rendered page). That's because the base gRPC client library for JavaScript (&lt;a href="https://github.com/grpc/grpc-node" rel="noopener noreferrer"&gt;grpc/grpc-node&lt;/a&gt;) used by &lt;code&gt;protobuf-ts&lt;/code&gt; needs to run on NodeJS. &lt;/p&gt;

&lt;p&gt;Browser support for HTTP/2 is still limited at the moment. That means that, unfortunately, our API is not browser-accessible as we set out to design it initially.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combining the gRPC and REST styles
&lt;/h2&gt;

&lt;p&gt;But what if we could make some changes to enable clients to interact with our gRPC API as though it were a REST service? Our service won't be RESTful since it will still be RPC under the covers, but we will get to access it via HTTP/1.1, URLs, and JSON. Thankfully, we can use an &lt;a href="https://envoyproxy.io" rel="noopener noreferrer"&gt;Envoy&lt;/a&gt; proxy server to easily accomplish this feat without having to write our own code manually!&lt;/p&gt;

&lt;p&gt;All the required changes can be viewed in our last demo, the &lt;a href="https://github.com/anthonydmays/grpc-vs-rest/tree/main/grpc-rest-app" rel="noopener noreferrer"&gt;grpc-rest-app&lt;/a&gt; implementation. First, we need to update our proto service interface to help the proxy service make our gRPC service methods available at the right URLs and for the correct HTTP operations. To do this, the &lt;a href="https://github.com/googleapis/googleapis/blob/master/google/api/http.proto" rel="noopener noreferrer"&gt;Google API HTTP&lt;/a&gt; library provides annotations we can add to our proto to describe the correct mappings. The &lt;code&gt;buf&lt;/code&gt; tool allows us to include the &lt;code&gt;googleapis&lt;/code&gt; dependency as a plugin in our &lt;a href="https://github.com/anthonydmays/grpc-vs-rest/blob/main/grpc-rest-app/packages/apiTypes/buf.yaml" rel="noopener noreferrer"&gt;buf.yaml&lt;/a&gt; file).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** file: packages/apiTypes/proto/contacts/v1/contacts.proto */&lt;/span&gt;

&lt;span class="c1"&gt;// An API for managing a collection of contacts.&lt;/span&gt;
&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;ContactsService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// List all available contacts.&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;ListContacts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListContactsRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListContactsResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;option&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;google.api.http&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"/v1/contacts"&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Updates a contact with the provided information.&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;UpdateContact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UpdateContactRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UpdateContactResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;option&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;google.api.http&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"/v1/contacts/{id}"&lt;/span&gt;
      &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"contact"&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Deletes a contact with the provided id.&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;DeleteContact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeleteContactRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;google.protobuf.Empty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;option&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;google.api.http&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"/v1/contacts/{id}"&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Other methods excluded for brevity.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see in the example, we use the &lt;code&gt;google.api.http&lt;/code&gt; annotation to indicate for each method what HTTP verb and URL path we want to make it accessible under.&lt;/p&gt;

&lt;p&gt;We can now stand up an &lt;code&gt;Envoy&lt;/code&gt; reverse proxy server instance that will be able to read these bindings and generate a service endpoint that will accept requests using the specified URIs. You'll find the implementation in the &lt;a href="https://github.com/anthonydmays/grpc-vs-rest/tree/main/grpc-rest-app/packages/proxy" rel="noopener noreferrer"&gt;packages/proxy&lt;/a&gt; subfolder complete with a fully configured Docker Compose image. We'll require three things for this to work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.envoyproxy.io/" rel="noopener noreferrer"&gt;Envoy&lt;/a&gt;&lt;/strong&gt;. I chose to use the Docker image for simplicity, but you can also install via your favorite package manager and run the provided yaml on your own with a one-line change to the config (see &lt;a href="https://github.com/anthonydmays/grpc-vs-rest/blob/c4729ca7a7db2e0f5bdba2c81713175ad9bc3cf9/grpc-rest-app/packages/proxy/envoy.yaml#L63" rel="noopener noreferrer"&gt;file comments&lt;/a&gt; for details).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;gRPC-JSON transcoder plugin&lt;/strong&gt;. We need to configure this plugin as a filter in Envoy in order to intercept HTTP requests with JSON payloads and transform them into gRPC encoded messages in binary proto format. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The proto descriptor file for our service&lt;/strong&gt;. Using the &lt;code&gt;buf build&lt;/code&gt; command line option in our &lt;code&gt;apiTypes&lt;/code&gt; package script, we're able to generate a proto descriptor file that will be used by the transcoder plugin to understand what services and operations are available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to starting our API and client servers as before, we'll now need to run our proxy server using the &lt;code&gt;docker compose up&lt;/code&gt; command. The client code is also updated to send fetch requests to our proxy service instead of to our backend API directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** file: packages/client/src/routes/+page.ts */&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$env/dynamic/public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ListContactsResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@grpc-vs-rest/api-types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PageLoad&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./$types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/** Handles loading data for the page. */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;load&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PUBLIC_API_ENDPOINT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:8080&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pageNumber&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orderBy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;orderBy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apiUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/v1/contacts?pageSize=25&amp;amp;pageNumber=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pageNumber&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;orderBy=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apiUrl&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ListContactsResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="nx"&gt;satisfies&lt;/span&gt; &lt;span class="nx"&gt;PageLoad&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The flexibility of this new approach is that services that want to speak to our API using native gRPC are free to do so, while clients that need to communicate via JSON and HTTP/1.1 won't be left out in the cold.&lt;/p&gt;

&lt;p&gt;Since we're using Envoy, there's one more neat trick that we can employ. It turns out that Envoy also support &lt;a href="https://github.com/grpc/grpc-web" rel="noopener noreferrer"&gt;gRPC-Web&lt;/a&gt; out of the box, a JavaScript client designed to support gRPC communication from the browser! That means that we can send gRPC messages over HTTP/1.1 as base64 encoded strings or as binary protobufs. Messages will be sent through our proxy and on to our backend service. The advantage of this is smaller and more efficient wire communication which should lead to better performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We've covered a lot in this post. I encourage you to take a look at the GitHub repo a bit more and play around to see how everything fits together.&lt;/p&gt;

&lt;p&gt;Because things are still evolving in the gRPC ecosystem, new tools and capabilities are being added all the time to make things easier for devs. I recently discovered that &lt;code&gt;Buf&lt;/code&gt; has &lt;a href="https://buf.build/blog/connect-web-protobuf-grpc-in-the-browser" rel="noopener noreferrer"&gt;introduced a new library&lt;/a&gt; for supporting gRPC apps that includes browser support for gRPC, gRPC-Web, and their own Connect Protocol for RPC communication. Consider checking it out if you are looking to explore gRPC for your next API.&lt;/p&gt;

&lt;p&gt;Designing great APIs is hard. Hopefully, this article has presented you with some options for building APIs that scale well and support your use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://cloud.google.com/blog/products/api-management/understanding-grpc-openapi-and-rest-and-when-to-use-them" rel="noopener noreferrer"&gt;gRPC vs REST: Understanding gRPC, OpenAPI and REST and when to use them in API design&lt;/a&gt; by Martin Nally&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm" rel="noopener noreferrer"&gt;Architectural Styles and the Design of Network-based Software Architectures&lt;/a&gt; by Roy Fielding&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/devaddict/use-grpc-with-node-js-and-typescript-3c58"&gt;Use gRPC with Node.js and Typescript&lt;/a&gt; by Aria Azadi Pour&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;Hey there! I'm Anthony D. Mays, 20 year software engineer who spent 8 years at Google. Now, I'm a career coach and founder of &lt;a href="https://morganlatimer.com" rel="noopener noreferrer"&gt;Morgan Latimer Consulting&lt;/a&gt; and a senior advisor for &lt;a href="https://ml.tips/brilliant-black-minds" rel="noopener noreferrer"&gt;Brilliant Black Minds&lt;/a&gt;, offering free mock technical interviews to Black software engineers in the US. &lt;/p&gt;

&lt;p&gt;Learn about how I went from foster kid in Compton to software engineer at Google in &lt;a href="https://amays.me/buzzfeed" rel="noopener noreferrer"&gt;this short documentary on BuzzFeed&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;You can &lt;a href="https://twitter.com/anthonydmays" rel="noopener noreferrer"&gt;find me on Twitter&lt;/a&gt; and LinkedIn at &lt;a class="mentioned-user" href="https://dev.to/anthonydmays"&gt;@anthonydmays&lt;/a&gt;, or check me out as a speaker and blogger at anthonydmays.com.&lt;/p&gt;

</description>
      <category>api</category>
      <category>webdev</category>
      <category>programming</category>
      <category>typescript</category>
    </item>
    <item>
      <title>9 Things You Didn’t Know About Your Coding Interviewer</title>
      <dc:creator>Anthony D. Mays</dc:creator>
      <pubDate>Tue, 14 Jun 2022 15:47:54 +0000</pubDate>
      <link>https://dev.to/anthonydmays/9-things-you-didnt-know-about-your-coding-interviewer-54fc</link>
      <guid>https://dev.to/anthonydmays/9-things-you-didnt-know-about-your-coding-interviewer-54fc</guid>
      <description>&lt;p&gt;Preparing for technical interviews as an interviewee takes a lot of mental and emotional energy. But what is it like to be an interviewer? As a 20 year software engineer, interview coach, and former interviewer at Google, I’ve spent plenty of time on the other side of the interviewing table assessing talent. Allow me to share some insight on the interviewer’s mindset that can help you better prepare as an interviewee. Here are nine things that you probably didn’t know (or haven’t considered) about your coding interviewer.&lt;/p&gt;

&lt;h2&gt;
  
  
  1) They are human
&lt;/h2&gt;

&lt;p&gt;Many of you prepare for interviews forgetting your interviewer will be a human being. Not only will you need to collaborate with another human in the interview, but several other humans will also assess your work. Your job is to convince them you have qualities the organization is looking for. &lt;/p&gt;

&lt;p&gt;If you’re only practicing alone (or against the CPU), you’re not doing it in a way that reflects the real experience. Understand that your interviewer is a human being. They can’t be inside your head figuring out what you’re thinking. Practice communicating well, articulating your thoughts out loud, and showing your work.&lt;/p&gt;

&lt;h2&gt;
  
  
  2) They might suffer from imposter syndrome
&lt;/h2&gt;

&lt;p&gt;Here’s something that may surprise you. Most FAANG software engineers I’ve asked feel like they barely passed the interviews themselves. They aren’t completely sure they’d be able to survive the interviews if they had to do it all over again. And they attribute at least some of their success to luck. &lt;/p&gt;

&lt;p&gt;I didn’t feel qualified to do coding interviews when I first started despite my training. I became comfortable over time as I got more interviews under my belt. Your interviewer might be very experienced or not very experienced at all. Don’t be surprised if they fumble the ball a bit.&lt;/p&gt;

&lt;p&gt;In fact, that leads me to my next point.&lt;/p&gt;

&lt;h2&gt;
  
  
  3) They get nervous
&lt;/h2&gt;

&lt;p&gt;The interview process can be very stressful for you as a candidate. But did you know that it can also be stressful for your interviewer? &lt;/p&gt;

&lt;p&gt;Here are some reasons for that. For one, they are likely meeting you for the first time. You are as much of a stranger to them as they are to you. Also, any number of things can go wrong in the interview. Anxiety-inducing events include communication issues, technical malfunctions, or having to switch interview questions.&lt;/p&gt;

&lt;p&gt;Nervousness is especially likely to occur for inexperienced interviewers. But introverted or socially awkward interviewers can also be prone to it as well. &lt;/p&gt;

&lt;p&gt;As a candidate, there may not be much you can do about it. Strive to communicate clearly. Be patient with your interviewer if they don’t seem to have it all together.&lt;/p&gt;

&lt;h2&gt;
  
  
  4) They’re being judged too
&lt;/h2&gt;

&lt;p&gt;Interviewers usually aren’t the ones who make hire/no hire decisions. Instead, they send detailed notes along with your code to a separate committee of peers. Those peers will not only assess your performance, but also assess how well the interviewer conducted your interview. They may send feedback to the interviewer to help them improve.&lt;/p&gt;

&lt;p&gt;Your interviewer doesn’t want to be that one person who messed up by not providing enough signal to the committee. And they definitely don’t want to get flagged for bias. They also don’t want to look too easy on candidates as compared to their peers. They may feel that their own reputation is on the line.&lt;/p&gt;

&lt;p&gt;The interview committee members aren’t the only ones judging your interviewer. You, the candidate, are judging them too. They know they are the face of the company, having a responsibility to represent the company well. Nobody wants to be accused of being a bad or unfair interviewer. And they certainly don’t want to be the subject of someone’s angry, mean spirited rant or tweet any more than you do.&lt;/p&gt;

&lt;h2&gt;
  
  
  5) They want you to succeed
&lt;/h2&gt;

&lt;p&gt;You may think that your interviewer exists to murder your hopes and dreams. You might believe they’re out to prove how superior they are to you. And as much as I hate to say it, I’m sure that is true for some small and problematic segment of the population. &lt;/p&gt;

&lt;p&gt;However, that has not been my experience. All the interviewers that I’ve known in tech want you to succeed in the interview for at least three reasons:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A bad interview experience feels awful for the interviewer almost as much as it does for you. It’s frustrating when a candidate can’t seem to get out of a rut or fails to ask the right questions. &lt;/li&gt;
&lt;li&gt;The best interviews are ones filled with lively discussion from engaged candidates. Poor candidate performance makes for a boring and uninteresting interview. &lt;/li&gt;
&lt;li&gt;Your interviewer knows what it’s like to sit in your seat. They are sympathetic to the fact that you want to do your best. Interviewers meet way more people who won’t succeed in the interview than those who will. It’s refreshing when a great candidate comes along and performs well. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember, interviewers are being judged too. They can get dinged in feedback for not providing timely guidance or for giving you bad information. And unless they’re on a power trip, they gain nothing from seeing you fail. That is, unless you’re being a jerk. In that case, they are doing their colleagues a favor by exposing your bad behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  6) They might feel underappreciated or overworked
&lt;/h2&gt;

&lt;p&gt;For most tech interviewers, interviewing is part of the job. However, they may not receive much recognition for the effort they pour into being decent. Your interviewer is an engineer like you. They are primarily rewarded for delivering impact to the business. That means spending more time building things and less time conducting interviews.&lt;/p&gt;

&lt;p&gt;Interviewing is a time-consuming process. It can take two or three hours to prep, conduct, and write up feedback for an interview depending on how well they did. Many candidates end up being mediocre or near misses, and they take the longest time to assess.&lt;/p&gt;

&lt;p&gt;This matters to you because you may run into a cranky interviewer who’d rather be coding than interviewing you. If you are combative, argumentative, discourteous, or late, then you will likely make the interview unpleasant for them and for you. This is not in your best interest. &lt;/p&gt;

&lt;p&gt;A word to the wise. Do your best to show up on time, wear a smile, be respectful, and thank your interviewer for their time. Avoid doing anything that will distract your interviewer from fairly assessing your technical performance. &lt;/p&gt;

&lt;h2&gt;
  
  
  7) They can’t pull questions from LeetCode
&lt;/h2&gt;

&lt;p&gt;I’ve never worked for a company that used coding questions from a public online repository like LeetCode. Instead, interviewers rely on proprietary question databases or make them up themselves. When a question appears on a public forum, it generally isn’t supposed to be used for a real interview.&lt;/p&gt;

&lt;p&gt;This matters to you because no matter how many LeetCode questions you do, you are likely not going to get the exact same question in the interview. Granted, you may get something similar sounding. But there will likely be some element that you may not have encountered.  &lt;/p&gt;

&lt;p&gt;Trying to memorize as many solutions as possible isn’t going to cut it. It is more important to study the patterns across questions and solutions. Be aware of when certain tools should be used in certain situations. It is essential to understand Big-O so that you know how to apply the right algorithm or data structure to achieve the optimal solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  8) They can tell if you already know the answer
&lt;/h2&gt;

&lt;p&gt;But let’s say that your interviewer does ask you a question you’ve heard before. Should you pretend like you haven’t heard it and go with the flow? Not at all. Not only is this dishonest, but your interviewer can probably tell. They’ve likely asked that interview question plenty of times and can spot anomalies in performance that suggest prior knowledge of the question.&lt;/p&gt;

&lt;p&gt;Unfortunately, I’ve sat on hiring committees and witnessed candidates getting the same question twice during an interview loop. In my experience, the candidate usually will have to take an additional interview to make up for the duplicate. Worst case, candidates get a no-hire decision. This is either because they outright lied or because they didn’t do better on the second attempt.&lt;/p&gt;

&lt;p&gt;If you get a question you’ve heard before, tell your interviewer. Explain what you think the solution is and allow them to decide what to do. They may propose a more advanced version of the question or pivot to something different. You’ll be seen as honest and responsible, not to mention saving you time in the process as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  9) They don’t know your previous performance
&lt;/h2&gt;

&lt;p&gt;You may not know this, but your interviewer generally has no awareness of your past interview performance. At most, they may view your resume and previous questions that you’ve tackled in the past, but that’s about it. Whether you bomb your last interview or knocked it out of the park, you are starting from square one with them. They won’t know anything unless you tell them yourself.&lt;/p&gt;

&lt;p&gt;What does that mean for you? “Be a goldfish” as Ted Lasso once said. Once you’re in the next interview, forget all about your performance in your previous ones. Don’t let past mistakes, failures, or successes distract you from focusing on the problem you’re solving in the moment.&lt;/p&gt;

&lt;p&gt;===&lt;/p&gt;

&lt;p&gt;Are you a current or aspiring black software engineer in the US? You can get up to four free mock interviews with feedback from trained, professional interviewers and workshops through &lt;a href="https://ml.tips/brilliant-black-minds"&gt;Brilliant Black Minds&lt;/a&gt;. No tip required! &lt;a href="https://ml.tips/brilliant-black-minds"&gt;Sign-up using this link&lt;/a&gt; to get started!&lt;/p&gt;

</description>
      <category>career</category>
      <category>leetcode</category>
      <category>beginners</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>How to Practice LeetCode Problems (The Right Way)</title>
      <dc:creator>Anthony D. Mays</dc:creator>
      <pubDate>Tue, 10 May 2022 04:51:59 +0000</pubDate>
      <link>https://dev.to/anthonydmays/how-to-practice-leetcode-questions-the-right-way-35c1</link>
      <guid>https://dev.to/anthonydmays/how-to-practice-leetcode-questions-the-right-way-35c1</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;tl;dr:&lt;/strong&gt; You're doing it wrong. Use &lt;a href="https://ml.tips/six-steps"&gt;"The Six Steps"&lt;/a&gt; any time you practice LeetCode questions, preferably with another person. Keep an interview prep journal to track your progress.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The struggle is real
&lt;/h2&gt;

&lt;p&gt;Have you been tackling LeetCode problems but don't feel like you're actually getting better in interviews? Feel like you're able to come up with solutions but never make it to the optimal one? Do you keep running out of time before you can finish the question? Are you constantly having a tough time making it through difficult questions?&lt;/p&gt;

&lt;p&gt;As a former Google software engineer and now career and interview coach, many of my clients have had this problem over the years. And if you were my client, I'd tell you that the problem isn't that you're not smart enough. Nor is it that you're not working hard enough.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You're probably practicing wrong.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Maybe you've been  working through the &lt;a href="https://www.teamblind.com/post/New-Year-Gift---Curated-List-of-Top-75-LeetCode-Questions-to-Save-Your-Time-OaM1orEU"&gt;Blind 75&lt;/a&gt;. Or maybe you're just using example problems from &lt;a href="https://smile.amazon.com/Cracking-Data-Science-Interview-Questions/dp/171068013X"&gt;Cracking the Coding Interview&lt;/a&gt;. You can pull questions from wherever you want, I don't care. If you're using the wrong strategy, &lt;strong&gt;it's not gonna help you very much, no matter how many questions you practice.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Anyone who's done weightlifting in the gym knows that good form and flexibility are essential. Those elements are necessary for getting the most out of your workout. Similarly, you need to practice good problem solving techniques when you're doing LeetCode questions so that you're maximizing the time you spend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping the real interview in mind
&lt;/h2&gt;

&lt;p&gt;Many of you practice LeetCode questions incorrectly because you may be unfamiliar with how technical interviews work in real life. Let's break that down real quick.&lt;/p&gt;

&lt;p&gt;More than anything else, you need to understand that technical interviewing is a &lt;strong&gt;collaborative problem-solving exercise.&lt;/strong&gt; The real interview won't be you working through a LeetCode question by yourself. You're going to be talking to a real human being. That's important to state because, if you're practicing by yourself, you probably aren't thinking about the fact that you need to communicate out loud to another person and ask questions.&lt;/p&gt;

&lt;p&gt;The biggest weakness with LeetCode problems is that there's no human involved outside of yourself. The question needs to provide every detail necessary for you to solve the problem up front. In a real interview, your interviewer is probably going to hold back some information to see how you deal with ambiguity. In other words, they want to know if you're going to ask questions or not.&lt;/p&gt;

&lt;p&gt;Also, a LeetCode question can't give you hints if you're headed in the wrong direction. It can't give you feedback on whether your approach is sound or not. All of this matters because your interviewer is going to assess how you handle feedback. If I, as your interviewer, ask you about whether you can optimize your solution, I'm going to expect something better than "I don't know."&lt;/p&gt;

&lt;p&gt;Oh, and by the way, your interviewer isn't obligated to provide you with examples or test cases. Some may do it to be helpful, and that's great. But if you're used to having all of that provided for you in your LeetCode questions, then you're going to have a hard time in the real interview coming up with good examples and test cases.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/5gDYpypPQQo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  A better way
&lt;/h2&gt;

&lt;p&gt;With the necessary context established, let's talk about how I think you should properly study example questions. The following strategy is what I used to ensure I got the most mileage out of every interview question. These steps will show how I applied my own problem solving framework (I call them &lt;a href="https://ml.tips/six-steps"&gt;"The Six Steps"&lt;/a&gt;) to practice interview questions.&lt;/p&gt;

&lt;h3&gt;
  
  
  1) Grab something to code on (not an IDE)
&lt;/h3&gt;

&lt;p&gt;Before you begin, make sure that you are set up correctly for your mock interview. You may choose to write out code using a whiteboard, pencil and paper, or using a computer and a text editor or lightweight code editor like Notepad++ or TextPad. Try to avoid using a full-on IDE since they will often include features that you're not likely to get in a real coding interview.&lt;/p&gt;

&lt;p&gt;If you're working with a mock interviewer, make sure to choose something that they'll also be able to see and edit.&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Decide whether to practice with a mock interviewer (strongly recommended) or by yourself
&lt;/h3&gt;

&lt;p&gt;The best way to practice a LeetCode question is with another person who will assess you as an interviewer. Now this is going to come as a shock, but they don't necessarily need to be a coder! Having a fellow software engineer or developer is ideal of course, but the important thing is finding someone that you can talk to and that can give you feedback. When studying for the Google interview, I relied on my wife who is definitely not technical but provided great feedback on my presence and demeanor.&lt;/p&gt;

&lt;p&gt;Of course, there will be times when you will need to study alone and that's fine. It will be essential for you to keep yourself accountable by not giving yourself more than a mock interviewer would in a real interview.&lt;/p&gt;

&lt;p&gt;Oh, and whoever you work with, show them some thanks and appreciation. There's always something you can do to compensate them for their time, whether with money, coffee, a public acknowledgement, or a gift card.&lt;/p&gt;

&lt;h3&gt;
  
  
  3) Start the clock
&lt;/h3&gt;

&lt;p&gt;Most interviews are timed for 45-60 minutes. Decide what length of time you're going to spend doing your mock interview based upon what you can expect for the real thing. Remember, you want to keep things as realistic as possible. Once your time is up, stop working. It's important to train yourself to work well within time constraints.&lt;/p&gt;

&lt;p&gt;One caveat here is that if you're early into your interview prep journey, you may want to just benchmark yourself a few times to see how well you perform. You'll still want to time yourself, but don't stop by a specific time. Keep going until you reach an optimal solution or can't think of anything else to do.&lt;/p&gt;

&lt;h3&gt;
  
  
  4) Articulate the problem
&lt;/h3&gt;

&lt;p&gt;Your mock interviewer will begin by reading the question out loud. Under no circumstances during the whole interview are you to look at the sample question, examples, or constraints. Depend completely on your mock interviewer for any information you will need to solve the problem. This is why it is absolutely essential that you take notes as your interviewer is speaking so that you don't have to ask them repeatedly for information they've already revealed.&lt;/p&gt;

&lt;p&gt;To ensure you've heard the question correctly and that you've captured all the details, repeat the question back to your interviewer in your own words. If you've missed any details or added something unnecessary, your mock interviewer should let you know before proceeding.&lt;/p&gt;

&lt;p&gt;If you're practicing on your own, read the question out loud exactly one time along with the example. Once done, hide the question from view and then repeat the question in your own words as though you were actually talking to a real person. Take notes, but avoid writing the full problem statement out. Focus on short statements that help you remember the key parts of the problem you're solving.&lt;/p&gt;

&lt;h3&gt;
  
  
  5) Ask questions and confirm assumptions
&lt;/h3&gt;

&lt;p&gt;Here's a handy tip for any interview. Always ask questions as the interviewee. Even if you think you know everything about how to solve a problem, and even if you've solved it before—still ask questions. Here are some questions you can ask for nearly any technical question:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What's the data type of the input and range of valid data?&lt;/li&gt;
&lt;li&gt;Does the input fit in memory?&lt;/li&gt;
&lt;li&gt;Can I expect to receive invalid data?&lt;/li&gt;
&lt;li&gt;How will input data be provided?&lt;/li&gt;
&lt;li&gt;Is the input data sorted already?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember, you should avoid asking questions that already have answers in the problem statement itself. It is important and encouraged, however, to re-state your assumptions in the hearing of your interviewer based on your understanding of the problem. For instance, if the problem mentions sorting whole numbers, you might assume that you're going to be sorting 32-bit signed integers. State that assumption clearly or ask if that's the case. The problem might actually require you to sort values that fit in a short integer, thus allowing you to save space (or a long 64-bit integer, which would obviously require more).&lt;/p&gt;

&lt;p&gt;If you're practicing alone or if  you're working with someone non-technical, you won't have someone to answer your questions. Once you've documented all your questions and assumptions, you can peek at the LeetCode constraints at this point and write down the answers. &lt;/p&gt;

&lt;p&gt;Again, try not to do a lot of writing. Prefer the least number of words needed to capture the essentials so you don't have to keep details in your head.&lt;/p&gt;

&lt;h3&gt;
  
  
  6) Come up with example inputs and their outputs
&lt;/h3&gt;

&lt;p&gt;At this point, you should begin working through examples. Two things are important at this step. One, look through any examples provided for you and reverse engineer them to figure out what details they reveal about the problem or its constraints. Two, add a couple of your own examples to demonstrate your understanding of those constraints or to prompt more questions. A way to think of examples is to treat them like test cases. Read up on test driven development (TDD) and unit testing as part of your interview prep if you habitually struggle to come up with good test cases.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A note to the mock interviewer. If the interviewee comes up with an example that violates constraints, let them know immediately. You are obligated to inform or remind them of the constraints in this case since this information may be critical to their being able to solve the problem.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Again, if you're studying alone then you won't have someone who can give you feedback on your examples. That's OK. Still come up with examples and make best-guess assumptions to any unanswered questions you may generate at this step. LeetCode questions are generally specific enough that this shouldn't be hard to do.&lt;/p&gt;

&lt;h3&gt;
  
  
  7) Brainstorm solutions and estimate their Big-O
&lt;/h3&gt;

&lt;p&gt;You should now have enough information to start coming up with solutions to the problem. This is where the rubber meets the road. All of your studying of algorithms and data structures should amply prepare you for generating two or three viable ways to solve the problem. If you struggle a lot at this step, hit the books. You've got more learning to do.&lt;/p&gt;

&lt;p&gt;The first step to good brainstorming is making a good guess about what the optimal solution looks like as expressed in Big-O. Is it possible that a constant time and constant space solution could exist? Why not? How about a logarithmic solution that 's O(lg n)? Remember, you're always driving towards an optimal solution. &lt;/p&gt;

&lt;p&gt;As an example, if I need to sort an array, I'm pretty sure that I can't do any better than a O(n) time complexity and O(1) space complexity in the worst case. I claim linear time complexity because I'll probably have to look at every element of input at least once, and I claim constant space because some sorts move elements in place so that I don't need to use a separate data structure.&lt;/p&gt;

&lt;p&gt;Once you think you know the ideal, the next step to good brainstorming is coming up with solutions and predicting their time and space complexity. Note that your first solution is probably going to be a brute force approach that is less than ideal. It also might also be the only solution you can come up with quickly. That's OK! If that's all you are able to come up with after a couple of minutes, just move on and go with it. But take the time to try to think about what you can do to get closer to the ideal, optimal solution.&lt;/p&gt;

&lt;p&gt;A couple of principles can be helpful here: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You usually have to use more space (memory) to make something go faster (and vice-versa), so if you're optimizing for speed, you probably need to use a data structure.&lt;/li&gt;
&lt;li&gt;If your task is to build a new data structure, you are likely going to need to put two data structures together that complement each other. That means that, in your studying, you should strive to know the strengths and weaknesses of each data structure and what problems they are designed to solve.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again, take only short notes of your approach along with the expected time and space complexity. Do the estimation up front, even if you aren't exactly sure! This can help you navigate your way through potential optimizations before you write the first line of code. You might find that a more optimal solution is just as easy, if not easier, to implement than the initial one you devised. &lt;/p&gt;

&lt;p&gt;One last thing. You're going to have to choose a solution to start implementing in the next step. It is OK for you to get input from your interviewer about which one they'd prefer to see you implement. It's also fine for you to implement the easiest one first and then write an optimal version after that. Hopefully, you can find a great mock interviewer who will provide you with good guidance here.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/hwwxGE7yJiM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  8) Implement a solution
&lt;/h3&gt;

&lt;p&gt;Now comes the easiest part of the experience. If you don't find this to be the easiest, then you need to spend more time practicing writing out code. There's a practical reason why I say this. You want to spend the least amount of time in this step so that you can devote more time to the others. It's like the old proverb says: "measure twice, cut once."&lt;/p&gt;

&lt;p&gt;Because you are on an artificially constrained, time-boxed schedule, you should also avoid writing in pseudocode. In real life interviews, pseudocode generally doesn't count. That means you'll have to turn all your fake code into real code for it to be assessed properly. Instead of pseudocoding, I suggest you make small notes about your proposed algorithm instead of writing out fake code since that will probably be faster and provide the same utility.&lt;/p&gt;

&lt;p&gt;Again, we're talking about coding interviews primarily used by the big tech companies. If you can pseudocode on a take home assignment and make the deadline, go for it! But at the big tech level, I assure you that writing code will be the easiest part of the job. Understanding the work you need to do and vetting your design will probably be the bulk of what makes your job challenging.&lt;/p&gt;

&lt;p&gt;Some tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Say what you're going to do before you write the code, then write the code. Don't write code without explaining what you're writing first. This ensures that the interviewer knows what you are thinking and has the opportunity to interrupt you if you're going down the wrong path.&lt;/li&gt;
&lt;li&gt;Use good, clear variable names. Prefer to be verbose (e.g. indexCount instead of idxCnt). In a real interview, your interviewer won't be the only one looking at your code. Readability matters a lot and is one of the reasons why code reviews are practiced in any major software shop.&lt;/li&gt;
&lt;li&gt;Don't be afraid to use common APIs, syntactic sugar, and common idiomatic style for your language. If you have doubts, just ask your interviewer whether you can use something or not. And even more importantly, understand what is happening under the covers so that you're aware of any performance penalty. For instance, calling the sort method on your collection costs between O(n lg n) or O(n2) depending on your language. Just calling that method won't magically turn your code into a constant time solution.&lt;/li&gt;
&lt;li&gt;As part of your &lt;a href="https://ml.tips/how-to-prepare"&gt;practice regimen&lt;/a&gt;, writing algorithms from memory can help you both get stronger in your programming language while also strengthening your comprehension of the algorithm itself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember, I strongly advise against using an IDE for coding up your solution to practice problems. And if you decide to use the LeetCode editor, don't compile and run the tests. In most cases, you're not actually going to get that in a real interview and even if you do, you will be tempted to use it as a crutch instead of properly walking through your code and testing it. Use a real compiler and unit tests after your time is up!&lt;/p&gt;

&lt;p&gt;If you find yourself getting stuck during the implementation, use an example and work out the steps on paper to get from input to output. Try to visualize what you need to do on paper so that you can see what your code needs to do and then implement it.&lt;/p&gt;

&lt;h3&gt;
  
  
  9) Test your code
&lt;/h3&gt;

&lt;p&gt;After you've typed the last semicolon or curly brace, you are still not done. You probably have at least one bug, typo, or missing variable that you need to fix. Walk through your code line by line, and check that each line is doing what you designed it to do. You should have a mental checklist of a few things to watch out for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Undeclared variables&lt;/li&gt;
&lt;li&gt;Off-by-one errors&lt;/li&gt;
&lt;li&gt;Reversed conditionals (e.g. "&amp;lt;" instead of "&amp;gt;=")&lt;/li&gt;
&lt;li&gt;Bad variable names&lt;/li&gt;
&lt;li&gt;Null pointer exceptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is one of the big reasons why it's essential to work out examples early in the problem solving process. You can easily use one of those examples to mentally run through the code and test that things work well, using paper and pencil or the text editor to track variable state.&lt;/p&gt;

&lt;h3&gt;
  
  
  10) Optimize
&lt;/h3&gt;

&lt;p&gt;If you haven't reached an optimal solution yet, either go back to brainstorming or implement a more optimal solution you've already devised. Until the timer hits zero, you've still got more work to do. Keep going!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up your mock interview
&lt;/h2&gt;

&lt;p&gt;Regardless of whether you practice with a partner or on your own, make sure to document feedback on your performance. Keeping a journal or notebook with all your learnings is a very useful way of organizing tips, resources, and your own progress. I still have my mock interview journal that reflects just some of the work I poured into being successful.&lt;/p&gt;

&lt;p&gt;If you worked with a mock interviewer, there are two questions you should answer: 1) how do you feel about your own performance, and 2) how would your interviewer rate you between hire, no hire, or on the fence. The key to these two questions is figuring out whether your self-assignment aligns with that of your interviewer. This will help you to shape the right expectations as you prepare so that you can build confidence and gain a good sense for yourself about whether you're headed in the right direction.&lt;/p&gt;

&lt;p&gt;Allow your interviewer space to critique you on non-technical things as well. Did you stumble a lot in your speech or use non-sequiturs? Were you making any annoying noises that should be avoided? Did you go quiet for long stretches of the interview? This feedback might not help you code better, but it will help you to communicate better and that's half the challenge of doing well on technical interviews.&lt;/p&gt;

&lt;p&gt;Lastly, now that your interview is over, feel free to copy your code into the LeetCode tool and make sure that it compiles and that the tests pass. If they don't take note of any edge cases you missed. I'd actually recommend copying into an IDE so that you can get more detail about compilation errors or use a debugger to step through your code. Take note of failures or missed edge cases so that you can add them to your implementation checklist on the next coding question you tackle.&lt;/p&gt;

&lt;p&gt;===&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Are you a current or aspiring black software engineer in the US? You can get up to four free mock interviews with feedback from trained, professional interviewers and workshops through &lt;a href="https://ml.tips/brilliant-black-minds"&gt;Brilliant Black Minds&lt;/a&gt;. No tip required! &lt;a href="https://ml.tips/brilliant-black-minds"&gt;Sign-up using this link&lt;/a&gt; to get started!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>tutorial</category>
      <category>career</category>
      <category>programming</category>
    </item>
    <item>
      <title>'King Richard': Reflections of a Black Software Engineer</title>
      <dc:creator>Anthony D. Mays</dc:creator>
      <pubDate>Mon, 02 May 2022 16:21:19 +0000</pubDate>
      <link>https://dev.to/anthonydmays/king-richard-reflections-of-a-black-software-engineer-58dh</link>
      <guid>https://dev.to/anthonydmays/king-richard-reflections-of-a-black-software-engineer-58dh</guid>
      <description>&lt;p&gt;Something magical happens when black people put in work.&lt;/p&gt;

&lt;p&gt;This fact should surprise no one. Hard work has always been the required wage demanded to justify the existence of the African American, lest the black tax go unpaid. It is common knowledge amongst black folks that we must work, at minimum, twice as hard as our non-black counterparts to achieve an equitable level of recognition and respect. Intriguingly, the fateful marriage of scarcity and struggle wrought from centuries of injustice and inequality have, out of sheer necessity, birthed a culture of innovativeness that has transformed everything that black people touch; from sports, to fashion, to tech, and beyond.&lt;/p&gt;

&lt;p&gt;Still, knowing all of this, I watched the inspiring story about the upbringing of Venus and Serena Williams by their father Richard Williams and found that it struck a chord with me. One that continues to resonate in my very soul for several reasons.&lt;/p&gt;

&lt;p&gt;For one, I was moved by the actions of a man determined to propel his daughters into greatness in the face of inestimable odds, defying skeptics and critics in pursuit of a singular vision. I was also inspired anew by the tenacity of two young girls from Compton working with skill and precision to hone their craft with relentless persistence and grit. I even watched with wonder as an entire family upended their lives to risk everything on a hope and a prayer, trusting that their heritage would be nothing short of greatness.&lt;/p&gt;

&lt;p&gt;And more than any other moment in the film, I was completely captured by Serena's response to a tennis coach when asked who she wanted to resemble most as a tennis player. With an all too familiar air of Muhammed Ali like confidence, she lays bare her audacious goal: "I want other people to be like me."&lt;/p&gt;

&lt;h2&gt;
  
  
  A shared narrative of greatness
&lt;/h2&gt;

&lt;p&gt;Beholding the greatness of champions like Venus and Serena (and any of the other highly successful athletes, artists, and musicians from Compton), we laud them for the success they've attained. And I mostly believe it appropriate for us to do so. There's nothing like a good 'ole American underdog story. But this acknowledgement of greatness also belongs to so many others from Compton who aren't said athletes, artists, and musicians.&lt;/p&gt;

&lt;p&gt;It also belongs to people like me and so many others.&lt;/p&gt;

&lt;p&gt;And what is my claim to this narrative? After surviving physical and sexual abuse as a 4-year-old kid and being abandoned to the foster care system, I taught myself how to code at age 8 as a means of reclaiming some of the agency and control I felt I had lost. I learned to code nearly a decade before I ever met a programmer in real life. And I was not just content with merely being good—I wanted to be the best. That, in my mind, was no less than what seemed required of me. I learned that from black history, for I taught that this too was the price demanded of the innovators and engineers who long preceded me.&lt;/p&gt;

&lt;p&gt;Though I did not exactly have a Richard Williams of my own per se, I had foster parents who believed that I would be somebody. They stopped at nothing to unlock as many opportunities as they could for me. Even when opportunities were scarce. Even when they couldn't afford it. Even when my father was laid off from his job two years before retirement and cheated out of his pension.&lt;/p&gt;

&lt;p&gt;Like the Williams sisters who themselves knew what it meant to be the only black person in white spaces, I also knew what it was like to be that only one in the computer science lecture halls, on teams at work, or in the whole office.&lt;/p&gt;

&lt;p&gt;I worked my butt off to succeed at the infamously hard Google interview that not even I thought I could pass. I actually failed it on my first attempt. Nonetheless, that fact didn't stop me from studying 4 hours a day for over a month to eventually find my pathway to success. My career has always required the same relentless persistence, grit, determination, practice, and work ethic that the Williams sisters harnessed in their own journey.&lt;/p&gt;

&lt;p&gt;Well, almost. I never had to write code outdoors in the rain. But I would have, had such been required.&lt;/p&gt;

&lt;h2&gt;
  
  
  In the pursuit of excellence
&lt;/h2&gt;

&lt;p&gt;Let me share with you a little secret. For many black folks pursuing pathways in tech, they are not merely fighting for a job. They are fighting for both their excellence and the recognition of their brilliance. They are striving to be still first in many unfamiliar spaces. In fact, being just 5% of all software engineers in the US, black tech talent has continued to endure a myriad of challenges and yet remains undeterred in the pursuit of not only succeeding in the tech game, but also changing it.&lt;/p&gt;

&lt;p&gt;People like &lt;a href="https://www.invent.org/inductees/marian-croak"&gt;Marian Croak&lt;/a&gt;, a living legend who pioneered Voice-over-IP technology and has over 200 patents to her name. People like &lt;a href="https://twitter.com/thugdebugger"&gt;Justin "Thug Debugger" Samuels&lt;/a&gt;, founder of the largest black software engineering conference, Render ATL, whose stated mission is to drape the whole of tech culture in unapologetic blackness. People like &lt;a href="https://www.youtube.com/watch?v=64yYnvviG8c"&gt;Bria Sullivan&lt;/a&gt;, a software engineer who left a cushy job at Google to start her own game company and serve as a startup advisor. People like &lt;a href="https://www.theverge.com/22910624/career-karma-ceo-ruben-harris-interview-startup-tech-linkedin-decoder"&gt;Ruben Harris&lt;/a&gt;, opening doors for underrepresented folk through the Career Karma platform that provides support, community, and mentorship to those embarking on untraditional journeys into tech.&lt;/p&gt;

&lt;p&gt;And now, Serena Williams joins this noble work. Her recent financial investment as a Champion of Brilliance for Karat's &lt;a href="https://ml.tips/brilliant-black-minds"&gt;Brilliant Black Minds&lt;/a&gt; initiative is nothing short of awe inspiring. Providing participants with free practice interviews, feedback, and guidance, the program is the start of a new movement to increase the number of black engineers in tech.&lt;/p&gt;

&lt;p&gt;The blessing of my fellow Compton alum Serena Williams is profoundly significant to me. We are now standing at the intersection of so much black excellence—and Compton excellence—that I believe this work will move the needle of tech diversity in a way never before anticipated. Its significance can scarcely be contained. Indeed, it cannot.&lt;/p&gt;

&lt;p&gt;I hope the day will come when society recognizes the brilliance of moments like this with the same vigor shown when black folks make moves in sports and entertainment. On that day, the true significance of this moment may perhaps be more fully apprehended. Until then, the work continues.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Anthony D. Mays is senior advisor for &lt;a href="https://ml.tips/brilliant-black-minds"&gt;Brilliant Black Minds&lt;/a&gt; at Karat, founder and career coach at &lt;a href="https://morganlatimer.com"&gt;Morgan Latimer Consulting&lt;/a&gt;, speaker at the &lt;a href="https://wsb.com/speakers/anthony-mays"&gt;Washington Speaker's Bureau&lt;/a&gt;, and a former software engineer at Google. You can follow him at &lt;a href="https://twitter.com/anthonydmays"&gt;@anthonydmays&lt;/a&gt; on Twitter. Originally posted at &lt;a href="https://anthonydmays.com/blog/2022/04/19/king-richard-reflections-of-a-black-software-engineer/"&gt;anthonydmays.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devjournal</category>
      <category>motivation</category>
      <category>inclusion</category>
    </item>
    <item>
      <title>Learning from My Tech Career Failures as a Software Engineer</title>
      <dc:creator>Anthony D. Mays</dc:creator>
      <pubDate>Tue, 05 Oct 2021 15:13:41 +0000</pubDate>
      <link>https://dev.to/anthonydmays/learning-from-my-tech-career-failures-as-a-software-engineer-493f</link>
      <guid>https://dev.to/anthonydmays/learning-from-my-tech-career-failures-as-a-software-engineer-493f</guid>
      <description>&lt;p&gt;There aren’t many things I regret in my tech career. Of course, there are things I’ve lived through that shouldn’t happen in a perfect world. For instance, the abuse I suffered as a kid. Or my laziness in college. Or my overdeveloped fear of failure.&lt;/p&gt;

&lt;p&gt;Yet I’m grateful for &lt;a href="https://amays.me/buzzfeedtweet"&gt;every step of my journey&lt;/a&gt;. The complex tapestry of struggles, failures, and learnings I’ve experienced has led me down the path of tech career success I enjoy today.&lt;/p&gt;

&lt;p&gt;But what if I had to do it all over again today? Follow along as I walk you through this interesting thought exercise. Hopefully, you can take something from these learnings to apply them to your own unique situation.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Applied more of my computer science (CS) knowledge
&lt;/h2&gt;

&lt;p&gt;It is quite possible to be successful career in tech without having a computer science degree. However, applying CS fundamentals to your work empowers you as a developer in ways that being a mere tool or framework user does not.&lt;/p&gt;

&lt;p&gt;My first job in tech was as an intern for a bank. What I did not understand at the time is that there is a huge difference between developing software for a company that makes its money from the software it builds and one that does not.&lt;/p&gt;

&lt;p&gt;Back then, the value of software was determined by how well it saved the organization time over manual, paper-based tasks. It didn’t matter if it was fast, usable, or laughably, even correct at times. The worst applications still saved a non-trivial number of hours per year of time compared to doing tasks using paper based systems.&lt;/p&gt;

&lt;p&gt;Graduating from a CS program that prioritized preparing students for cutting-edge software companies solving problems at scale, my education seemed somewhat useless given my situation at the time. The IT department could just build or buy software, no matter how awful, and force the tens of people who needed it to use it. The game was simply to provide the least amount of quality for the cheapest sum of money possible.&lt;/p&gt;

&lt;p&gt;Consequently, I was dubious about the value of my classroom learning as it pertained to my real world career. Had I known what I know today, I would have done one of two things: 1) asserted my knowledge more confidently to help lead the team into better software patterns and practices, or 2) left the company sooner to pursue opportunities in my career where I could apply my knowledge more usefully and honed my skills more quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Attempted the Google interview sooner
&lt;/h2&gt;

&lt;p&gt;As fate would have it, I attempted my journey to Google five years after graduating from college and landed my dream job on my second attempt three years after that. The growth I experienced between those attempts were critical. I wish I had experienced that sooner in my career.&lt;/p&gt;

&lt;p&gt;In college, almost a decade before I actually got the job, I met a Google recruiter at a career fair. They handed me a brochure and told me to apply for an internship. I trashed it. In my mind, there was no conceivable path &lt;a href="https://anthonydmays.com/blog/2015/06/08/google-would-never-hire-a-person-like-me/"&gt;for a black kid from Compton to get to Google&lt;/a&gt;. That’s the stuff of Hallmark movies.&lt;/p&gt;

&lt;p&gt;I didn’t have a single soul in my poor network of connections who had ever attempted this unfathomable feat. No context. No experience. No vision. And because I had not yet valued the virtue of learning from failure, I did not see interviewing as an opportunity to accelerate my learning. No, it was like asking me to drive a car off a cliff. There was only one way that could end. Having no eagerness to discover the ceiling that I knew had to exist all along for someone like me, I preferred not to even try. I was a black man pursuing a career in tech in the early 2000’s.&lt;/p&gt;

&lt;p&gt;Had I known that Silicon Valley is the place where taking risks is not only celebrated but glorified, I would’ve taken the dive way sooner and been all the better for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Networked 500% more in college
&lt;/h2&gt;

&lt;p&gt;With some regularity, I get an email at work from a recruiter wanting to know if I am familiar with some candidate. Over 95% of those emails pertain to someone who attended my alma mater while I was there.&lt;/p&gt;

&lt;p&gt;I confessed earlier that I was network poor in my college days (I was money poor too, but I digress). The thought had not occurred to me to make an effort to build one myself. If I had not isolated myself, I might have built doorways into better career opportunities. At least I would’ve learned some names that I could’ve referred to Google later in life. That could have been easy referral bonus money.&lt;/p&gt;

&lt;p&gt;While I might not have had as many opportunities handed to me like some of my colleagues did, I also didn’t leverage what opportunities I did have very well. And with the platforms for networking that now exist, I would not make that same mistake today if I had the chance to start over again.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Practiced unit testing and code reviews
&lt;/h2&gt;

&lt;p&gt;For the majority of time in tech before Silicon Valley, I often relied on a QA team to validate the results of my work. This fostered a mindset of shifting the responsibility of ensuring the quality of my work to someone else. School taught me that unit testing is an effective tool for building robust, higher quality software. But in my early days, most enterprise organizations didn’t have the stomach for it.&lt;/p&gt;

&lt;p&gt;Not only that, but I could write as much code as I wanted with impunity. This meant that I made a lot of bad decisions regularly, developing horrible habits that went unchecked for years. And I was good at producing boat loads of code.&lt;/p&gt;

&lt;p&gt;I faced a rude awakening when, during my first year at Google, I found myself having to redo work many times during code reviews. I saw my productivity dive bomb like a bent paper plane. You can only imagine how that fed my already severe feelings of imposter syndrome. The code review process exposed a lot of weaknesses in my coding practices. That suffering was both necessary, humbling, and useful. I also could have saved myself some embarrassment too.&lt;/p&gt;

&lt;p&gt;What could I have changed? Even when in an environment where not practiced, I would have made unit testing an integral part of my workflow. I would eagerly invite others to review my code. Finally, I would insist on finding roles that value unit testing and code reviewing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I’m sure there’s more that I could say, but I hope this honest take is helpful to you. Have a thought about something I mentioned here? Did I leave something out? Leave a comment and let me know.&lt;/p&gt;

</description>
      <category>career</category>
      <category>testing</category>
      <category>codequality</category>
    </item>
    <item>
      <title>How should I prepare for my Google interview if I have 1 month left?</title>
      <dc:creator>Anthony D. Mays</dc:creator>
      <pubDate>Wed, 04 Sep 2019 17:30:07 +0000</pubDate>
      <link>https://dev.to/anthonydmays/how-should-i-prepare-for-my-google-interview-if-i-have-1-month-left-3nlh</link>
      <guid>https://dev.to/anthonydmays/how-should-i-prepare-for-my-google-interview-if-i-have-1-month-left-3nlh</guid>
      <description>&lt;p&gt;&lt;em&gt;The following is my answer to the question “How should I prepare for my Google interview if I have 1 month left?” Originally posted on &lt;a href="https://www.quora.com/How-should-I-prepare-for-my-Google-interview-if-I-have-1-month-left/answer/Anthony-D-Mays"&gt;Quora&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With over ten years of programming experience and a CS degree, it took me about a month and a half of daily practice to get ready for the interview. “Ready,” for me, is ambitiously defined as the ability to tackle almost any technical interview question in 30 minutes or less and reach an optimal solution. The following is based upon what I did to prepare—your mileage may vary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ingredients:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;About two years of solid coding experience&lt;/li&gt;
&lt;li&gt;Pencil and paper&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/gp/product/0984782850"&gt;Cracking the Coding Interview (CTCI)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Your favorite algorithms book

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.amazon.com/gp/product/0070131511/"&gt;Introduction to Algorithms&lt;/a&gt; , &lt;a href="https://www.amazon.com/gp/product/1849967202/"&gt;The Algorithm Design Manual&lt;/a&gt;, and &lt;a href="https://www.amazon.com/gp/product/0201657880/"&gt;Programming Pearls&lt;/a&gt; are a few good choices. Might I suggest you go low tech and buy physical copies?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Two or three hours a day&lt;/li&gt;
&lt;li&gt;Highly recommended: Whiteboard&lt;/li&gt;
&lt;li&gt;Highly recommended: CS degree&lt;/li&gt;
&lt;li&gt;Optional: MIT OpenCourseware or another learning site&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Directions:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) Learn as much as you can about the Google interview process (days 1–2)
&lt;/h3&gt;

&lt;p&gt;Just like an incomplete understanding of a technical question will ruin you in the actual interview, misinformation will derail your preparation leading up to it. I learned this the hard way when I failed at my first attempt after emphasizing brain teasers over studying algorithms and data structures.&lt;/p&gt;

&lt;p&gt;Start with the source—check out google.com/careers for info on how Google hires. Then watch this video from Google about what interviewers look for in the interview, and finally check out an example interview featuring real Google engineers.&lt;/p&gt;

&lt;p&gt;Once you have a solid foundation, I’d recommend following up by reading CTCI. Particularly focus on chapters 5 and 6 entitled Behavioral Questions and Technical Questions.&lt;/p&gt;

&lt;p&gt;By the time you finally read my short article about the six things you absolutely need to do during the actual interview, you should have a good grasp of what a well prepared candidate looks like.&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Benchmark yourself (days 3–5)
&lt;/h3&gt;

&lt;p&gt;Now that you know how prepared you need to be, figure out where you are right now. Use CTCI for this. Take a couple of questions from each section and solve them using the six steps I mentioned earlier. Keep track of how long it takes you to reach an optimal solution for each problem you solve.&lt;/p&gt;

&lt;p&gt;If and only if you’ve solved the problem yourself, take a look at the accompanying solution to assess how you did. Did you reach the optimal solution or at least progress beyond the naive/brute force answer? How long did it take you? Was your code written in the fewest lines possible?&lt;/p&gt;

&lt;p&gt;Do this for every section. When done, you can prioritize the sections that you didn’t do so well on up front in your practice regimen and leave the other sections for later. You should repeat this exercise just before your interview so that you know your weak spots going into the day of the interview.&lt;/p&gt;

&lt;h3&gt;
  
  
  3) Make a study list (days 3–5)
&lt;/h3&gt;

&lt;p&gt;Using the data you acquired from the previous step, make a prioritized list of things you need to study. This list should include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memorizing two good sorting algorithms and &lt;a href="http://bigocheatsheet.com/"&gt;their Big-O&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Memorizing binary search&lt;/li&gt;
&lt;li&gt;Memorizing how to implement basic data structures such as hashmap, linked list, stack, queue, and trees (n-ary, trie, heap) and &lt;a href="http://bigocheatsheet.com/"&gt;their Big-O complexities&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Memorizing graph traversal algorithms (BFS, DFS, and a shortest path algorithm like Dijkstra’s)&lt;/li&gt;
&lt;li&gt;Memorizing powers of 2&lt;/li&gt;
&lt;li&gt;Practice bit manipulation exercises (working with bit maps, bit shifting)&lt;/li&gt;
&lt;li&gt;Object-Oriented Programming terminology (abstraction, inheritance, cohesion, coupling)&lt;/li&gt;
&lt;li&gt;Know the collections and math APIs for your given programming language&lt;/li&gt;
&lt;li&gt;&lt;a href="https://loveforprogramming.quora.com/Backtracking-Memoization-Dynamic-Programming"&gt;Recursion, backtracking, and memoization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Review principles of basic discrete mathematics and statistics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is all covered in CTCI and your favorite algorithms book. Note: the point of the memorization is understanding! You will probably never be asked to write out an algorithm verbatim. Rather, you’ll be expected to know each well enough that you can use them creatively to solve a problem you’ve never seen.&lt;/p&gt;

&lt;h3&gt;
  
  
  4) Practice algorithms and data structures daily (days 6–30)
&lt;/h3&gt;

&lt;p&gt;Pick a two or three items from your list and commit about two or three hours each day working on these things (e.g. 1 hr before work, lunch break, 1 hr after work). As you memorize things, test yourself by writing out an algorithm or data structure on paper or on a whiteboard. Write down the worst case Big-O time and space complexities for the algorithm when you’re done. Always check your work, always!&lt;/p&gt;

&lt;p&gt;Now copy what you’ve written to your favorite IDE and compile. Take note of any compilation errors so that you can avoid them when you repeat the exercise again. You can and should also create unit tests to verify the correctness of your code.&lt;/p&gt;

&lt;p&gt;Keep doing this until you can transcribe and compile your code without logical or syntactical errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  5) Tackle as many programming questions as you can (days 16–30)
&lt;/h3&gt;

&lt;p&gt;By now, you should have a pretty good handle on the skills you need to succeed on interview question. Starting with CTCI, tackle every single programming problem you can, again using the six steps. Devote about half your study time to this while you spend the other half reviewing items from your study list.&lt;/p&gt;

&lt;p&gt;If you’re doing well, you’ll probably start to run out of questions in the book. You can find tons more of real samples online from sites like &lt;a href="https://careercup.com"&gt;CareerCup&lt;/a&gt; or &lt;a href="https://interviewcake.com"&gt;Interview Cake&lt;/a&gt;. Or, just use your favorite search engine. I know a &lt;a href="https://www.google.com/"&gt;pretty good one&lt;/a&gt; you can use ;).&lt;/p&gt;

&lt;p&gt;Practice a few times with another person, both with someone technical and someone non-technical. Ask them if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You looked and sounded relaxed&lt;/li&gt;
&lt;li&gt;You looked like a disciplined problem solver&lt;/li&gt;
&lt;li&gt;You kept thinking out loud throughout the entire exercise&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6) Relax and get some good sleep (day 30)
&lt;/h3&gt;

&lt;p&gt;Congratulations! You’ve worked really hard. There’s nothing else you can do. Relax and get into your good place. You’ve made it this far. That means you either really enjoy coding or that you will stop at nothing to get that job at Google. I think you will genuinely enjoy your interview experience. Make sure to have fun! I look forward to seeing you in the meeting room.&lt;/p&gt;

&lt;p&gt;Appreciate this article? &lt;a href="https://amays.me/youtube-subscribe"&gt;Subscribe to my newly revamped YouTube channel&lt;/a&gt; to see sample interviews and get even more useful tips. Want to do a mock coding interview with me? Visit &lt;a href="https://morganlatimer.com"&gt;morganlatimer.com&lt;/a&gt; to book time with me. Share and leave a comment below to keep the discussion going!&lt;/p&gt;

</description>
      <category>interview</category>
      <category>whiteboarding</category>
      <category>career</category>
      <category>coding</category>
    </item>
    <item>
      <title>Interviewing at Google? Here’s 6 Things You Absolutely Need To Do</title>
      <dc:creator>Anthony D. Mays</dc:creator>
      <pubDate>Sat, 23 Mar 2019 16:44:49 +0000</pubDate>
      <link>https://dev.to/anthonydmays/interviewing-at-google-heres-6-things-you-absolutely-need-to-do-22lo</link>
      <guid>https://dev.to/anthonydmays/interviewing-at-google-heres-6-things-you-absolutely-need-to-do-22lo</guid>
      <description>&lt;p&gt;Having interviewed, coached, and sat on hiring committees with many candidates during my three year tenure at Google, I’ve learned a lot about what works and what doesn’t. I conquered the interview process after failing once before and, even then, I thought it could’ve gone either way. With tons of stuff to study, it’s hard to figure out how to prepare. Even really smart people can fail if they don’t have a good plan for what to do when they get into the room with an actual software engineer and a whiteboard.&lt;/p&gt;

&lt;p&gt;So, I’m going to share six tips I believe you absolutely need to nail your interview. After you check these out, watch this &lt;a href="https://www.youtube.com/watch?v=XKu_SEDAykw"&gt;sample interview video&lt;/a&gt; conducted by Google engineers.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Repeat the question in your own words
&lt;/h1&gt;

&lt;p&gt;As soon as you hear it, repeat it out loud. Do this preferably in your own words to demonstrate your comprehension. Remember, your interviewer is there to assist you, so repeating the question aloud will only serve to make their job (and yours) easier.&lt;/p&gt;

&lt;p&gt;This will also buy you some time to think about what you’ve been asked and develop good questions or approaches. Plus, hearing yourself restate the problem might help you think through it more clearly.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Check assumptions
&lt;/h1&gt;

&lt;p&gt;Many candidates start writing code almost immediately after hearing the question. This is a big mistake. Most coding questions have some level of ambiguity built in. Have at least two or three questions ready so that you can confirm you have all the necessary detail to solve the problem. You can also write out confirmed assumptions on the whiteboard (do it in small print to save space). Questions like “does input fit in memory?” or “can I assume input is always valid?” are good candidates if you can’t think of any at first.&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Use real examples
&lt;/h1&gt;

&lt;p&gt;You’ve got a whiteboard—use it! Draw out an example array, a binary tree, a linked list, etc. Give it real data and write out the expected output of a working solution. You should practice coming up with good examples as part of your study regime (you do have one, right?). Using a visual example also gives you opportunity to think up more questions and your interviewer a chance to correct your assumptions. Don’t forget to keep thinking out loud as you work through it.&lt;/p&gt;

&lt;p&gt;If your interviewer provides examples, use those since they probably exist for a reason. This is also how interviewers will point you towards problems with your design or implementation.&lt;/p&gt;

&lt;h1&gt;
  
  
  4. Brainstorm solutions and their time/space complexity
&lt;/h1&gt;

&lt;p&gt;Stop and think about various approaches. If you’ve put in time studying algorithms and data structures, this is where it really starts to pay off (&lt;a href="https://www.amazon.com/Cracking-Coding-Interview-Programming-Questions/dp/0984782850"&gt;Cracking the Coding Interview&lt;/a&gt;, anyone?). Think about trade offs using &lt;a href="http://bigocheatsheet.com/"&gt;Big-O analysis&lt;/a&gt; and think out loud. Don’t stop with the first solution that comes to mind. Always ask yourself what’s the best you can do. Trust me, we always will!&lt;/p&gt;

&lt;p&gt;Tips: Don’t forget the &lt;a href="https://en.wikipedia.org/wiki/Space%E2%80%93time_tradeoff"&gt;space–time tradeoff&lt;/a&gt; principle. Wanna go fast? Use more space. Also, hash tables people! And learn how to &lt;a href="https://steve-yegge.blogspot.com/2008/03/get-that-job-at-google.html"&gt;think graphs&lt;/a&gt;—including trees. If all else fails, &lt;a href="https://loveforprogramming.quora.com/Backtracking-Memoization-Dynamic-Programming"&gt;recursion, backtracking, and memoization&lt;/a&gt; are useful tools on particularly difficult problems.&lt;/p&gt;

&lt;h1&gt;
  
  
  5. Write working code (no pseudo-code please!)
&lt;/h1&gt;

&lt;p&gt;You might normally use pseudo-code to design your code, but you don’t have time for that in a 45-minute interview. Choose your strongest language and turn your thoughts into working code as quickly as possible. This should be the easiest part of the interview assuming you’ve put time into practicing without an IDE (seriously, don’t use an IDE to practice for the interview unless you’re compiling code you’ve already written out). Make sure to practice using a whiteboard or just use pen and paper.&lt;/p&gt;

&lt;h1&gt;
  
  
  6. Test your code, always
&lt;/h1&gt;

&lt;p&gt;Now turn your brain into a compiler and execute each line of code to ensure you don’t have any logical bugs. Use the whiteboard to keep track of variable state as you iterate. Also, use the example(s) you created earlier and confirm that you get the expected output. Testing is crucial in software engineering, so never make the grave mistake of leaving this step out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practice makes perfect
&lt;/h2&gt;

&lt;p&gt;It took nearly an hour and a half to finish a coding question when I first started using these six steps. After a month and a half of daily practice, I could solve most questions in about half an hour. Nothing takes the place of putting in the time to prepare for the interview until you’ve developed the muscle memory to execute these six steps perfectly. Is it worth it? &lt;a href="https://www.youtube.com/watch?v=9ANgEo40VSE"&gt;I’d say so&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This post originally appeared on &lt;a href="https://www.linkedin.com/pulse/interviewing-google-heres-6-things-you-absolutely-need-anthony-mays/"&gt;LinkedIn&lt;/a&gt;. Find more tips at &lt;a href="https://amays.me/interview-tips"&gt;anthonydmays.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>interview</category>
      <category>whiteboarding</category>
      <category>career</category>
      <category>coding</category>
    </item>
  </channel>
</rss>
