<?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: JTK</title>
    <description>The latest articles on DEV Community by JTK (@heyjtk).</description>
    <link>https://dev.to/heyjtk</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%2F113006%2F34a6244f-50f3-4950-9f7e-36cc3b7bdccb.png</url>
      <title>DEV Community: JTK</title>
      <link>https://dev.to/heyjtk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/heyjtk"/>
    <language>en</language>
    <item>
      <title>The dirty secrets of the IT Staffing industry</title>
      <dc:creator>JTK</dc:creator>
      <pubDate>Mon, 12 Dec 2022 20:12:47 +0000</pubDate>
      <link>https://dev.to/heyjtk/the-dirty-secrets-of-the-it-staffing-industry-19na</link>
      <guid>https://dev.to/heyjtk/the-dirty-secrets-of-the-it-staffing-industry-19na</guid>
      <description>&lt;p&gt;In 2013 during a relative low point of both my life and career, I got a job that I had no idea would alter the course of my entire life. It was an entry-level recruiting role paying $13 an hour with paltry benefits at a now-defunct IT Staffing firm in a small, nothing town in Maryland. &lt;/p&gt;

&lt;p&gt;I know many tech people hate recruiters, and if you are one of them, I will tell you the exact people you hate most are the kind created by this type of staffing agency. &lt;/p&gt;

&lt;p&gt;I was inspired to write this post after hearing a junior developer lament the unpredictable and confusing behavior of recruiters hounding her, then going silent. For anyone else new to the industry who may not be familiar with how these shops work, I'd like to pull back the curtain on how (some, many) IT staffing firms work and why I avoid them. &lt;/p&gt;

&lt;h2&gt;
  
  
  The basics
&lt;/h2&gt;

&lt;p&gt;Some of you may know this, but it is worth spelling out why staffing agencies exist and how they function. I'm going to be pretty critical in this post, so it may surprise you that I don't think all staffing agencies are necessarily evil or that they don't have a purpose. &lt;/p&gt;

&lt;p&gt;Some of the things I will criticize about staffing agencies are also more accurately laid at the feet of the companies that use staffing agencies to keep a perpetual underclass of lesser-paid contractors alongside their cushy salaried workers (looking at you FAANG). Staffing agencies react to what their customers profess to want, so in some ways their behavior is just a reflection of the state of the IT industry at large. &lt;/p&gt;

&lt;p&gt;But let's back up and take a 10000 foot view for a minute.&lt;/p&gt;

&lt;p&gt;In the most simple terms possible, staffing agencies exist to complement traditional in-house recruiters. If a business's own recruiting department is understaffed, sometimes they'll need help finding and vetting candidates and in theory a staffing agency is a great way to fill these fluid hiring demands. A company may not want to keep 10 in-house recruiters on staff if their demand is seasonal and half of them wouldn't have much work in non-peak season. Using that logic, it makes sense to partner with a staffing firm who can handle the more fluid and unpredictable surges in demand that a business may encounter in their hiring. &lt;/p&gt;

&lt;p&gt;In some cases, hiring IT talent is so hard that companies have indefinite agreements to work with a staffing agency. Again, on paper, it makes sense. An in-house recruiter may have to cover roles from HR, accounting, engineering, marketing, on and on. If you use an IT staffing firm where all the recruiters &lt;em&gt;specialize&lt;/em&gt; in tech talent, you ought to get better results, right? (Often no, but more on that later). &lt;/p&gt;

&lt;p&gt;In general, staffing agencies invest a lot of up-front work into calling candidates, vetting them, and then getting resumes to the business to review. The staffing agency will coach the candidate and confirm their interviews, and if the candidate does well they typically will be hired as a contractor under the staffing firm and receive any benefits the staffing firm offers. &lt;/p&gt;

&lt;p&gt;Usually, this work is structured as a contract or contract to hire vs permanent opportunity. Staffing agencies generally make their money in "billable hours", where they charge a surplus on top of whatever hourly rate the hired worker earns that goes to the staffing agency. It is sometimes called the &lt;em&gt;burden rate&lt;/em&gt;, the formula to determine how much the staffing agency has to charge on top of the hourly rate going back to the worker for that placement to be profitable to the staffing company. &lt;/p&gt;

&lt;p&gt;Adding a middleman between employee &amp;lt;&amp;gt; employer and giving someone else a cut of the budget for a certain job can have the effect of depressing the wages the worker/contractor receives. If you've ever noticed spammy recruiters talking about contract work at abysmal rates, eyyo. That's how that happens. &lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond the basics: System integrators
&lt;/h2&gt;

&lt;p&gt;It will sound ridiculous to say this, but on top of contract workers losing out on some wages because of the staffing agency middleman, there is often a SECOND middleman in the mix. If you have seen jobs from KForce, TEKsystems, Robert Half, etc etc - in general all the big guys like that as well as smaller staffing firms partner with something called &lt;em&gt;System Integrators&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The hugely popular one I dealt with in my staffing job was called &lt;a href="https://atos.net/en/" rel="noopener noreferrer"&gt;Atos&lt;/a&gt;, and their volume of business in the US was enormous. They covered Coca-Cola, Siemens (Atos used to be Siemens IT Services if I remember correctly), Nike, JP Morgan Chase, on and on. I have limited insight since I got out of agency recruiting as soon as I could, but they may be the big dog of all system integrators in the US, they seemed that large. &lt;/p&gt;

&lt;p&gt;How the flow of activity worked at my staffing agency (and many others) was that we actually did not deal directly with any company and instead were one of many dogs waiting for table scraps from Atos. Atos would receive a 'req' for the various businesses they served (Coca Cola, Nike) and redistribute those out to numerous staffing agencies simultaneously. &lt;/p&gt;

&lt;p&gt;If you have ever annoyingly gotten four different voicemails from recruiters for what sounds like the same job, guess what! It probably was. Recruiters would mad dash to call all the best candidates after receiving a req, since only the first company to submit a certain candidate could get credit for them. Atos would also give us a slap on the wrist if we ever accidentally submitted someone another agency had already sent. Sometimes candidates would get so inundated with recruiter phone calls that they'd legitimately not be able to keep track of what they were submitted for. &lt;strong&gt;Some&lt;/strong&gt; agencies try to scare candidates by saying if they don't reveal if they were already submitted they will get put on a &lt;em&gt;do not hire&lt;/em&gt; blocklist. In my experience, that is entirely made up and was not something I ever saw done. Maybe it happens elsewhere, but I never saw it. Candidates are the staffing agency's meal ticket, so you can see why they wouldn't want to "bite the hand that feeds", blocklist someone and miss out on future earnings. &lt;/p&gt;

&lt;p&gt;The last thing I'll say about Atos that leaves me with a very bad taste in my mouth about them is that the quality of their job descriptions was absolutely laughable. They were so bad that people would cuss me out for sending them something so useless. I remember it so vividly I was able to find what I'm confident is an Atos-related listing in about a second by searching "IT Support Specialist hardware software peripherals". I got this gem of a job listing: &lt;br&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%2Fvmyhwnymfy8syp7wxkxx.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%2Fvmyhwnymfy8syp7wxkxx.png" alt="Image of a highly generic IT support job ad"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Its a thumbs down, from me, on Atos. &lt;/p&gt;

&lt;h2&gt;
  
  
  Other foolishness within the agency day-to-day
&lt;/h2&gt;

&lt;p&gt;Moving away from Atos and back to life in the staffing agency, there are a number of things that I think result in the relatively poor candidate experience we see with agencies. &lt;/p&gt;

&lt;p&gt;Early into this role I asked my boss how to handle it when IT guys would be angry that I sent them our Atos job description that was little more than two lines about "support computer hardware, software and peripherals. Troubleshoot and debug end user issues". My boss confidently told me that it wasn't important, that our job was just sales. 90% of people were going to tell you to go to hell and that it just is what it is.&lt;/p&gt;

&lt;p&gt;I (of course) ignored him and set about learning more about technology so I could be a better recruiter. &lt;/p&gt;

&lt;p&gt;Other troubling things we were asked or forced to do included using a massive, primitive web scraping resume harvesting service called &lt;a href="https://jd.jobdiva.com/" rel="noopener noreferrer"&gt;JobDiva&lt;/a&gt;. We could set up harvesting jobs to run overnight using various keywords and search terms. When asked what to search, my boss told me &lt;code&gt;hardware AND software&lt;/code&gt;. I later went on to be certified in advanced boolean techniques but even without that background yet, it was obvious to me that those search terms were childishly inadequate. &lt;/p&gt;

&lt;p&gt;Job Diva would dutifully send "email merges" to the million, jillion, trillion people identified each night unlucky enough to have the words &lt;code&gt;hardware&lt;/code&gt; and &lt;code&gt;software&lt;/code&gt; in their resume, and each morning myself and the other recruiters would sift through the mountain of angry emails about how off base our outreach efforts were. &lt;/p&gt;

&lt;p&gt;Staffing agencies also have some of the most inane, useless metrics of any type of business I've ever seen. Recruiters are commonly judged on metrics for number of phone calls placed, number of candidates submitted, in addition to more meaningful metrics like number of interviews per week, time to fill a role, and number of placements made within a month. My staffing agency didn't have this but some have "lunch quotas", where recruiters have goals to take out a certain amount of candidates for lunch each month. A lot of it is utter nonsense. &lt;/p&gt;

&lt;p&gt;The incentives are aligned in such a way that you are so busy you can't follow up with candidates. The focus on placements means that staffing agency recruiters are really not incentivized to spend their time doing things like, updating candidates who weren't hired. The submittal metrics daily meant that we'd take half-qualified candidates and lob them over the fence just to hit our numbers, a waste of time for everyone involved. Alternately, we would have to edit and heavily wordsmith resumes for people, disguising gaps between jobs, generalizing titles, making people add keywords lest Atos reject the submission as "not qualified". &lt;/p&gt;

&lt;p&gt;All in all, I would describe staffing as a vehicle of enormous churn. Sure, it can generate a bunch of resumes for a company but when I think about all the waste involved in the process, it is hard to see it as a good investment. &lt;/p&gt;

&lt;h2&gt;
  
  
  Other miscellaneous bad behavior
&lt;/h2&gt;

&lt;p&gt;I know I've said a lot at this point bad about agencies, and I know there are some out there that are more boutique and don't do the things I describe. But for me honestly, it was clear very quickly that staffing was not the place for me. I was critiqued for caring too much about the technology, spending too much time doing research, spending too much time on the phone with each candidate. Basically, acting like a human being who cared about my job. &lt;/p&gt;

&lt;p&gt;The prevailing attitude was definitely in the vein of "it's all just sales, these people are all just numbers. Keep it brief and focus on throwing bodies at Atos". Although I generally met my metrics and wasn't under-performing, I was an office oddity for caring about candidate experience and trying to learn the technology to do better for the people I talked to. &lt;/p&gt;

&lt;p&gt;There ARE some things from this time that I am glad to have learned. &lt;/p&gt;

&lt;p&gt;Seeing how agencies work was enough for me to steer clear of them, for starters. I saw that agency recruiters had no pull or influence to get an excellent but slightly nontraditional candidate anywhere, so I realized me, without a degree was never going to have success getting jobs through staffing firms. &lt;/p&gt;

&lt;p&gt;I do stand by some of the resume edits I learned there, dropping months off resumes to disguise any gaps (you don't need to know that I took a month of funemployment in 2021 because I felt burnt out, Random Hiring Manager). Genericizing my title is something I've done and will continue to do if it serves me. But other than that? &lt;/p&gt;

&lt;p&gt;I left staffing as soon as I could, and entered the world of boutique, white-glove internal recruiting. I know a lot of y'all hate recruiters and have only encountered ones that are more of the staffing agency caliber, but I was different. My candidates used to compliment me with astonishment on how much technology I knew. I had printouts all over my office like an FBI agent on a manhunt except it was cross diagrams of programming languages and network engineering terms. I took tech certs, I started coding in my free time, I got certified in advanced boolean searches so I could find people more effectively, I wanted to be as surgical as a scalpel. &lt;/p&gt;

&lt;p&gt;Aaaaaand here I find myself, almost ten years since my stint in staffing, as a Senior Software Engineer. My quest to be a better recruiter took me too far over to the dark side, it seems. C'est la vie. &lt;/p&gt;

&lt;h2&gt;
  
  
  Filtering out the noise
&lt;/h2&gt;

&lt;p&gt;If you didn't already do this, it is possible to largely live out your tech career ignoring staffing agencies. I use a separate email while jobhunting and dutifully unsubscribe from all of the staffing agencies who find me. Their emails are normally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;contract for a client who won't be named (Atos won't allow it) &lt;/li&gt;
&lt;li&gt;extremely generic description&lt;/li&gt;
&lt;li&gt;pay, if listed, is bad &lt;/li&gt;
&lt;li&gt;despite offering little to no info, recruiter asks for your resume and has a heavy bias towards getting you on the phone&lt;/li&gt;
&lt;li&gt;(potentially) you get a string of similar emails at one time that all have identical bodies as all the various staffing firms scurry to submit people first &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are a somewhat traditional candidate and for whatever reason in a tough spot and need a job, no judgment of course if you take a contract through companies like these.&lt;/p&gt;

&lt;p&gt;If you have a LESS traditional background, I will tell you that your odds of getting anything meaningful from a staffing agency encounter are very low. &lt;/p&gt;

&lt;p&gt;If you are a person who gets one of these jobs, I would also focus on trying to get away from contract work as soon as you can. With great hypocrisy, Atos has a noted bias against serial contract workers. They were seen as inferior, the subtext being "why hasn't anyone wanted to bring you on full time?" What's worse is that in addition to the lower pay, lower level of security than a salaried employee, etc is that on the job contractors may be siloed and kept at arm's length from interesting work. In recessions, contractors are often the first let go. So in exchange for making it through the wringer that is staff agency hiring, it isn't like you get much in return. &lt;/p&gt;

&lt;p&gt;My advice if you really need a job and get what you &lt;em&gt;suspect&lt;/em&gt; is a staffing agency email is to try to reverse engineer the role from the location/description and apply to the job directly on the company website. It certainly won't hurt your chances and if you succeed, you're going to be getting a lot of benefits a contractor wouldn't. &lt;/p&gt;

&lt;h2&gt;
  
  
  In conclusion
&lt;/h2&gt;

&lt;p&gt;So that's it! That is the deep, dark, hidden dysfunction that goes on in staffing agencies and the reason I have never gotten a job through one since my own experience recruiting for that type of business. &lt;/p&gt;

&lt;p&gt;I was (luckily) able to get away from staffing fairly fast, and loved that in subsequent recruiting roles all the behaviors I got mocked for were appreciated. Learning the technology, being responsive to candidates, giving them a good experience: this stuff &lt;strong&gt;matters&lt;/strong&gt; in my opinion, even if staffing agencies act like it doesn't. &lt;/p&gt;

&lt;p&gt;If you have any questions I didn't address or your own experience with staffing agencies, feel free to share in the comments!  &lt;/p&gt;

</description>
      <category>career</category>
      <category>hiring</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>The road to staff engineer</title>
      <dc:creator>JTK</dc:creator>
      <pubDate>Thu, 01 Dec 2022 19:15:13 +0000</pubDate>
      <link>https://dev.to/heyjtk/the-road-to-staff-engineer-3keb</link>
      <guid>https://dev.to/heyjtk/the-road-to-staff-engineer-3keb</guid>
      <description>&lt;p&gt;I'm not qualified to write this post, &lt;em&gt;yet&lt;/em&gt;. I'm not a Staff Engineer yet. Although of the things I've ever really set my sights on, my track record is pretty impeccable, so I'd estimate my odds are good. I also hope to have another few decades in this field, so judging on my trajectory so far, I can't think of any reason it shouldn't happen. &lt;/p&gt;

&lt;p&gt;I wanted to write about this topic though, because I feel like it is shrouded in far more mystery than I would have expected. What is a Staff Engineer? What's the big deal about it? &lt;/p&gt;

&lt;p&gt;When I think of my current belief of "what's so special about Staff Engineers" I think if early-career me had heard it, I wouldn't even have understood what it meant. It is not always but &lt;em&gt;can&lt;/em&gt; be a lot more complicated than "just a super duper senior engineer". &lt;/p&gt;

&lt;h2&gt;
  
  
  What's so special about Staff Engineers?
&lt;/h2&gt;

&lt;p&gt;This is a complicated question to answer, and like any title different places it will mean different things. Like any job, different people have different strengths and weaknesses, and you could take two very successful Staff Engineers and find the reason for each of their success to be totally different attributes. &lt;/p&gt;

&lt;p&gt;Further complicating things, as my understanding of Staff Engineer grows, I see that it can but may not always share elements of other roles: leadership roles, technical lead, IC. All of these things make it harder than I would have imagined to pin down. &lt;/p&gt;

&lt;p&gt;Apparently I'm not alone. Will Larson (who has great content and a book out on this topic) identifies that there are, in fact, &lt;a href="https://staffeng.com/guides/staff-archetypes" rel="noopener noreferrer"&gt;staff archetypes&lt;/a&gt; people may tend to fall into, which can somewhat explain the disparity you see between person to person who may hold the title. Borrowed completely from the linked resource, they are:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The &lt;strong&gt;Tech Lead&lt;/strong&gt; guides the approach and execution of a particular team. They partner closely with a single manager, but sometimes they partner with two or three managers within a focused area. Some companies also have a Tech Lead Manager role, which is similar to the Tech Lead archetype but exists on the engineering manager ladder and includes people management responsibilities.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;The Architect&lt;/strong&gt; is responsible for the direction, quality, and approach within a critical area. They combine in-depth knowledge of technical constraints, user needs, and organization level leadership.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;The Solver&lt;/strong&gt; digs deep into arbitrarily complex problems and finds an appropriate path forward. Some focus on a given area for long periods. Others bounce from hotspot to hotspot as guided by organizational leadership.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;The Right Hand&lt;/strong&gt; extends an executive's attention, borrowing their scope and authority to operate particularly complex organizations. They provide additional leadership bandwidth to leaders of large-scale organizations.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So these descriptions advance me somewhat in my understanding. I have been called Tech Lead and Dev Lead before, so I can connect the dots and recognize what traits let me do that well. I've also situationally been my team's "Solver" or "Architect". Probably the least relevant to me is "The Right Hand Man" as I don't really like politics, although calling it "politics" grossly simplifies that archetype I realize.&lt;/p&gt;

&lt;p&gt;Although there is some overlap, my own understanding of Staff Engineer has been an evolving attempt to put words to people I've known but couldn't have described. There's one at my work who I started with before their promotion to Staff, and I remember just thinking "wow this guy is on another level". &lt;/p&gt;

&lt;p&gt;When I tried to articulate my goal of a Staff Eng promotion to my current work, I finally came up with at least a halfassed description of my newly-promoted colleague. "He sees the problem underneath the stated problem, he sees the solution no one was asking for but they actually desperately needed". In addition to being a solid coder, organized, and t-shaped, this person basically has x-ray vision, was I realized the heart of my compliment. &lt;/p&gt;

&lt;p&gt;I think the part junior-engineer me wouldn't have been able to conceptualize is how a Staff Engineer puts it all together. It's a mix of things, gravitas, communication skills, consensus building, deep as well as specialized technical knowledge, and the ability to transform all those elements into masterpieces of impact. It is hard to say that in a non-cheesy way that expresses the extent of it. I think as a junior dev, I also would not have understood how &lt;em&gt;deep&lt;/em&gt; "depth" can be. My impression of operating at the staff engineer level is that there is a depth borne of deep, deep experience that can't be faked or rushed. &lt;/p&gt;

&lt;h2&gt;
  
  
  What I want is not an easy path
&lt;/h2&gt;

&lt;p&gt;I was made Dev Lead with about three years of software engineering experience and at the time I remember feeling like it was an inflated title for my capabilities. Not wanting to miss out on any opportunities it netted me, I obviously didn't object to the title bump but inside it felt sort of meaningless.&lt;/p&gt;

&lt;p&gt;At that phase in my career, I was a solid communicator, obviously good coder, well-rounded in some ways although not in others, but I think mostly just working crazy hours was enough to get me to Lead. &lt;/p&gt;

&lt;p&gt;Since I've been in tech, it has not been unusual for me to see colleagues have a six year path to startup CTO (maybe title inflation, but its happening) or a two-year path to Senior Engineer. Not to detract from anyone else's achievement, but for me senior came too easy - it was meaningless. I didn't feel like I earned it and although I enjoyed the salary that came along I did not in my heart of hearts &lt;em&gt;feel&lt;/em&gt; senior. &lt;/p&gt;

&lt;p&gt;Staff Engineer is a different beast. While I think a lot of companies slotted people into senior roles in the past few years to make salaries work in a competitive hiring climate, Staff Engineer is a title that carries with it a weight that it isn't going to be given away like that.&lt;/p&gt;

&lt;p&gt;In fact, many to most engineers may never make it past a senior title. One resource I found but am now struggling to locate describes Senior Engineer as an often "terminal" title in the progression spectrum of a software engineering career. &lt;/p&gt;

&lt;h2&gt;
  
  
  Putting my own version of a roadmap together
&lt;/h2&gt;

&lt;p&gt;I'm still a work in progress. I write to you awaiting my first annual review at my job, so that in the event there are critical comments I can integrate them into my personal roadmap. If the comments are good, I'll have additional food for thought about what archetype I want to pursue.&lt;/p&gt;

&lt;p&gt;As always, I reach something of a fork in the road in relation to my natural talents versus my interests. People seem to find me likable, I get told I am articulate or a good communicator. Being organized, creating documentation and charts and guides, those are all things I was doing from childhood when I'd put together PowerPoint presentations lobbying my parents for different privileges. &lt;/p&gt;

&lt;p&gt;Maybe because it comes easier to me, or because they are skills I used in my past careers, I have always gravitated more towards the hardcore technical work since becoming an engineer. People probably would assume me to be an extrovert but I'm not. All that "likability" costs me, below the surface. The lack of control also fatigues me. &lt;/p&gt;

&lt;p&gt;In one of my appointments as Tech Lead we had an under-performing teammate and I was somewhat alarmed to have nebulous aims for that person's growth laid at my feet. Ultimately, I could help, I could coach, I would give them the tools to succeed but had no control over whether the struggling engineer improved. That kind of thing terrifies me, and is why I'm &lt;em&gt;not&lt;/em&gt; considering people management, although people sometimes tell me I'd be good at that. &lt;/p&gt;

&lt;p&gt;Adding another layer of complication, because Senior Engineer came too easy and didn't mean much to me, I have my own arbitrary thresholds of knowledge I want to conquer in the process of pursuing this title. For my entire dev career up until graduating this past March I have been a half-time to full-time student. Cranking out school assignments kept me so busy that there are many "fundamental" code areas I feel I never got to learn. I've never properly learned to do cool manipulations of tree data structures, if asked to do back of the napkin math about device storage capabilties I know almost none of that offhand. &lt;/p&gt;

&lt;p&gt;As someone working with high-level languages to be fair neither thing comes up all that often, but it has still been the voice in the back of my head saying &lt;em&gt;you aren't really senior, you got there through luck and likability&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;My managers asked me why I wanted a Staff promotion and I answered, "Not to sound like a real hippie but it's partly about the journey. I feel like its a chance to learn all these things I never got to to become my own idea of a deep, well-rounded engineer". &lt;/p&gt;

&lt;h2&gt;
  
  
  My plan from here
&lt;/h2&gt;

&lt;p&gt;I will never stop being surprised at the number of times in life being the so-called "squeaky wheel" or asking for what I want has netted me outrageous advantages. Since casually talking to folks about this a number of extremely lucky circumstances have fallen into my lap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I got to interview a talented Staff Engineer about their path to the title&lt;/li&gt;
&lt;li&gt;My old and new boss have &lt;strong&gt;both&lt;/strong&gt; been getting me involved in more database work, which I want to be the crux of my special area of knowledge &lt;/li&gt;
&lt;li&gt;I got invited to a recurring Staff Engineer working group where a mix of people who currently hold the title and want it chat together about what it means &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With all those things cooking, the next BIG thing I need to do is get my review from work and translate that into specific goals and milestones to attain the promotion in a year.&lt;/p&gt;

&lt;p&gt;The year timeline is to be honest with you, maybe a moon shot. I have six years of experience as of last month. I'm seeing people attaining Staff Engineer for the first time after 15 years of experience, some of it far more impressive than mine. &lt;/p&gt;

&lt;p&gt;Even so, all I can think is that having this focus so early might let me leapfrog a few years of just cruising at a senior title. The focus, the work, learning from others, can only help right? While a year may be crazy, I'd say my more honest goal would be to make Staff Eng before having ten years of experience. I would be perfectly happy with that outcome. &lt;/p&gt;

&lt;h2&gt;
  
  
  In closing
&lt;/h2&gt;

&lt;p&gt;While it is nerve-wracking, having this new goal is exciting. It is the first time I've really cared about my title in this field, and I feel like the journey to even trying to get it will be transformative. &lt;/p&gt;

&lt;p&gt;It IS about the journey, y'know? I wasn't just saying that. Even if I never get there, taking this road trip through all the topics I always felt I missed out on, developing leadership skills and impact, I'm looking forward to it all.&lt;/p&gt;

&lt;p&gt;Thanks for reading, and feel free to share any of your own thoughts on pursuing this title in the comments! &lt;/p&gt;

</description>
      <category>softwareengineer</category>
      <category>career</category>
    </item>
    <item>
      <title>Data modeling crash course</title>
      <dc:creator>JTK</dc:creator>
      <pubDate>Sun, 18 Sep 2022 19:42:41 +0000</pubDate>
      <link>https://dev.to/heyjtk/data-modeling-crash-course-1gai</link>
      <guid>https://dev.to/heyjtk/data-modeling-crash-course-1gai</guid>
      <description>&lt;h3&gt;
  
  
  Intro
&lt;/h3&gt;

&lt;p&gt;Data modeling questions are a fairly normal part of the interview process, and it is worth knowing some basic guidelines for how to organize data. Although in this piece I will primarily talk about this at the database level, it is good knowledge to have across the stack - knowing when a piece of logic should be broken out into a reusable component is something frontend engineers will frequently run into, and it gets into similar logical territory because we are thinking about how it makes sense to organize our information, what belongs together, and what should be broken up. &lt;/p&gt;

&lt;p&gt;Because it is the predominant type of database, we are mainly going to talk about relational databases and how to model data using good practices for relational databases specifically. But it is worth knowing that there are many other types of database out there, and what count as “good practices” can be different between different database systems. In addition to relational databases, there are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NoSQL&lt;/li&gt;
&lt;li&gt;Key/value stores&lt;/li&gt;
&lt;li&gt;Graph databases&lt;/li&gt;
&lt;li&gt;Network databases&lt;/li&gt;
&lt;li&gt;Object oriented databases&lt;/li&gt;
&lt;li&gt;Columnar databases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Among others. Before you feel pressure to learn all that, it is worth saying that I’ve been doing this a long time and have really only ever significantly dealt with relational databases, key value stores, and NoSQL. There is also some crossover in functionality between databases, at times. One of my favorite things about MongoDB is the ability to store data structures similar to JSON, but PostgreSQL, a relational database, also allows you to store JSON if you need to. Some NoSQL databases also support query languages like SQL (structured query language), the language of relational databases. &lt;/p&gt;

&lt;h3&gt;
  
  
  Basic ideas
&lt;/h3&gt;

&lt;p&gt;I feel like data modeling is one of those terms that can sound intimidating before you know what it is. I had several of these as a junior developer where when I would hear the term, for some reason my mind would go blank. (”Scripting language” was one of these, even though all I knew was scripting languages 🤷‍♀️). &lt;/p&gt;

&lt;p&gt;If hearing &lt;code&gt;data modeling&lt;/code&gt; makes you think of training AI models, or complex statistical models like they do for political elections, you can put that to the side. You should be happy to know, data modeling for relational databases more or less follows common sense. &lt;/p&gt;

&lt;p&gt;Relational databases and SQL have actually come to be a favorite technology of mine, &lt;em&gt;because&lt;/em&gt; the principles so closely echo common sense. It is also somewhat unique for a technology as old as relational databases to have survived the rapidly changing technological landscape since the theories behind them were created by by E.F. Codd between the 1960s-1980s. It is somewhat rare for a technology so old to still work so well and be so well liked by the people using it. The history behind this technology is interesting, and you can read more about it &lt;a href="https://www.techopedia.com/definition/25195/edgar-f-codd" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If I could summarize the “common sense” ideas that govern good data modeling for a relational database for someone with zero background, I’d probably highlight the following: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We want to follow separation of concerns by breaking up data as much as possible into distinct tables&lt;/li&gt;
&lt;li&gt;We want to avoid duplicating data, because this makes more work for us if we need to delete or update anything&lt;/li&gt;
&lt;li&gt;We want the components of our tables to be clear and independently meaningful (the value in column B should not change in meaning in relation to column A, it should stand on its own)&lt;/li&gt;
&lt;li&gt;We want to structure our data to have safeguards in place to avoid “junk data” - for instance, do we want to allow a user with a typo on a state abbreviation to send the value “NZ” instead of “NC” to the database? Probably not, because it may cause our application not to work as expected, and we may have to clean up bad data later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not too crazy, right? &lt;/p&gt;

&lt;h3&gt;
  
  
  Quick detour into SQL-specific lingo
&lt;/h3&gt;

&lt;p&gt;Some of the things in our toolkit to make the above guidelines happen are &lt;code&gt;indexes, keys&lt;/code&gt; and &lt;code&gt;constraints&lt;/code&gt;. You can think of these like rules. When you set up these rules, if data comes to your database that violates the rules, instead of writing that data an error will be thrown. This is actually what you want. Bad data can cause all kinds of headaches. &lt;/p&gt;

&lt;p&gt;Let’s quickly go into these concepts before we head into some examples and rules of thumb.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Primary&lt;/strong&gt; &lt;strong&gt;Keys&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Primary keys are a way for us to uniquely identify our records. This is typically done by creating a numeric ID field. Databases have logic around primary keys so that for each new record, the ID field is incremented by 1 for every new record. They also enforce logic so that you could not have two records with &lt;code&gt;id 2&lt;/code&gt;, for instance. This makes dealing with our data much easier, because it is far more convenient for your application to be built around &lt;code&gt;thing with ID 2&lt;/code&gt; than &lt;code&gt;thing with name x and address y and state z and…&lt;/code&gt; every time you need to pull up a record &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Foreign Keys&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It will be no surprise that in a relational database, we have representation of the &lt;em&gt;relationships&lt;/em&gt; between our data. In simplest possible terms, a foreign key is when one table references another. In addition to describing the relationships between tables, foreign keys can be used to enforce data quality. &lt;/p&gt;

&lt;p&gt;Lets consider that we have a table that collects address info, like the following:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Address&lt;/th&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;th&gt;Zip code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;123 tree street&lt;/td&gt;
&lt;td&gt;AZ&lt;/td&gt;
&lt;td&gt;87678&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4 Cary Ct&lt;/td&gt;
&lt;td&gt;NC&lt;/td&gt;
&lt;td&gt;27617&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;What happens if the user inputs a typo in their state? We would have bad data that might cause our application not to work as expected. However if we have an address table and a state table, we could use foreign keys to say that whenever we try to add a new address, we will check that the state exists in the &lt;code&gt;state&lt;/code&gt; table, indicating it is valid input. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Indexes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you create a &lt;code&gt;primary key&lt;/code&gt; field on a table, the database also creates what is called an &lt;code&gt;index&lt;/code&gt;. The idea is a little like an index in a book, and makes finding things easier. Indexes make searching faster for the database engine, the underlying logic that carries out SQL queries. If you have a table with ID fields like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;…&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And you are searching for record with ID &lt;code&gt;200&lt;/code&gt;, the database can use binary search to get to the correct record with great efficiency. How this works is the database might select the middle ID value of all the records, and see that it is &lt;code&gt;500,000&lt;/code&gt;. That’s way too high, so we can ignore the second half of those results, anything from &lt;code&gt;500001&lt;/code&gt; onwards. We can pick from the middle again, and get ID &lt;code&gt;250,000&lt;/code&gt;. Still way too high, so we can ignore the higher half of those results and pick from the middle again of the remaining lower half of ID numbers. So on and so forth. Binary search is a &lt;strong&gt;very efficient&lt;/strong&gt; algorithm, so database indexes are an important tool for fast searches and good database performance. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other constraints and keys&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We have other ways of applying rules to our database to ensure we have only good data, and no repeated data. We can use something called &lt;code&gt;UNIQUE&lt;/code&gt; constraints to create a rule that every record must have values in a certain column that don’t already exist in the database. If you had a database with usernames for instance, you could prevent someone registering with a username value that someone else had. (Side note, when you create a primary key, in addition to it automatically being indexed, it automatically also has a unique constraint out of the gate). &lt;/p&gt;

&lt;p&gt;Sometimes, we also have situations where a traditional number ID field does not fit our needs. So we can also make what is called a &lt;code&gt;composite key&lt;/code&gt;, and make a primary key that is the combination of two columns. &lt;/p&gt;

&lt;p&gt;There are many other types of keys, constraints, and indexes, but it is out of the scope of this article which is for beginners. &lt;/p&gt;

&lt;h3&gt;
  
  
  Data modeling interviews: brainstorming
&lt;/h3&gt;

&lt;p&gt;Data modeling is something that comes up from time to time in interviews. It may be part of some system design questions, or it may be an exercise of its own. In my experience, data modeling interview discussions are actually one of my favorites types of interviews. They are almost always common sense, straightforward, no trick questions, and I like data so I wind up enjoying them. They are also usually pretty collaborative. If you have gotten an interview like this, I don’t want to call something “easy” but I will say data modeling interviews are among the more pleasant interviews I’ve been part of, so go in with good vibes knowing you won’t be grilled on something random or asked some obscure factoid (ime). &lt;/p&gt;

&lt;p&gt;In my experience, brainstorming is an important stage of ALL interviews that ask you to approach a technical problem, and these are no different. With data modeling, there are some guiding questions that reflect good relational data modeling principles, and are good to move through to show that you understand this space and can reason about data and how data is related. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good brainstorming questions to ask yourself (and say out loud in interviews!)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What are the main &lt;em&gt;entities&lt;/em&gt; in this problem? (Often, what you would have as a model in backend code directly corresponds to what you would have as a table or “entity” in the database)&lt;/li&gt;
&lt;li&gt;When determining “data entities”, think about whether data is meaningful on its own, or only in the context of other data. It is generally good to split data up - good separation of concerns, a good way to keep tables smaller and more granular, good all around - but if data is not meaningful on its own, it may belong under the umbrella of another entity&lt;/li&gt;
&lt;li&gt;In school learning backend code, sometimes we learn to develop models thinking about “is a…” and “has a…”. We can say, a car &lt;em&gt;is a&lt;/em&gt; vehicle, and a motorcycle &lt;em&gt;is a&lt;/em&gt; vehicle. Maybe we build a &lt;code&gt;Vehicle&lt;/code&gt; class for that reason. We can say a motorcycle &lt;em&gt;has a&lt;/em&gt; engine, a car &lt;em&gt;has a&lt;/em&gt; engine. So maybe we need to track engine data and relate it back to our &lt;code&gt;Vehicles&lt;/code&gt;. These concepts translate to the database too, and are worth thinking about planning your models&lt;/li&gt;
&lt;li&gt;When you have related data, it is good to ask yourself what entity it is &lt;em&gt;most&lt;/em&gt; related to. Sometimes data is equally related to multiple entities. In those cases, sometime it is worth breaking out a separate table reflecting the relationship back to both of two equally related entities&lt;/li&gt;
&lt;li&gt;Relational databases deal with, you guessed it, relationships! Some relationships are hierarchical, like a boss with many reports. Some relationships are 1:1, like a website user would probably only have one account ID. Some relationships are many to many, like how a student can be in multiple classes and a class contains multiple students&lt;/li&gt;
&lt;li&gt;When you have your main entities figured out, it is worth thinking about the smallest appropriate data type you can use for your data. Booleans and integers generally take up less space than text and can be faster to search. You have to be careful though, since people can run into trouble using &lt;code&gt;INTEGER&lt;/code&gt; ID fields for databases with too many records, it is possible to hit the limit of integer values. For this reason sometimes there is another type, &lt;code&gt;BIGINT&lt;/code&gt; to allow greater flexibility. There are rarely trick questions here, but it is worth demonstrating you understand the tradeoffs of various data types&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Rules of thumb with examples
&lt;/h3&gt;

&lt;p&gt;One thing I’ll cover quickly is that in some of the examples I’ll show you next I borrow concepts from the rules of &lt;em&gt;database normalization&lt;/em&gt;. There are various “levels” of database normalization, and usually the higher the level your data conforms to, the more it is seen to follow good relational database practices. You can read more about normalization &lt;a href="https://www.lifewire.com/database-normalization-basics-1019735" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡Side note: I have &lt;strong&gt;never&lt;/strong&gt; been asked to remember the definition of a specific form of normalization in an interview, and probably couldn’t if asked. Since most of the rules are common sense, I apply them constantly, but it is intuitive rather than the result of memorization. While it &lt;em&gt;may&lt;/em&gt; come up in some rare, rare circumstance, I think it is worth mentioning that I have never been asked to regurgitate definitions of normalization. So if I were you, especially as a new coder, I would not worry about that tbh 🤷&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Rule 1: No multi-value records&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Consider we have an app like GoodReads where users can “favorite” books. What do you think if we have a table structured like what’s below? &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;user_id&lt;/th&gt;
&lt;th&gt;favorites&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;The Snow Child, Pride and Prejudice, Eleni, The Poisonwood Bible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;The Revenant, Ender’s Game, The Hobbit&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With SQL syntax, if the user “unfavorited” a book in this list, you would have to re-write the entire record to apply that update. There is also not an easy way to insert a new favorite without re-writing this entire comma-separated list. Searching also gets slower, since instead of looking for an exact match if you want to find users who favorited a certain book, you would have to essentially loop through all the favorites of each record and see if the book title is among them. &lt;/p&gt;

&lt;p&gt;The way to structure this data with better practices might involve splitting it up, and taking advantage of &lt;code&gt;foreign keys&lt;/code&gt; which we chatted about before.&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%2Fy1ip0uvi8fnuuhab8n4x.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%2Fy1ip0uvi8fnuuhab8n4x.png" alt="Each of three tables with relationships diagrammed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To summarize what we did here, and why it is good:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can now do a simple search for user favorites with logic like &lt;code&gt;where user = x and book = y&lt;/code&gt; on the user favorite table&lt;/li&gt;
&lt;li&gt;If a user adds a new favorite, we add a tiny new record to the user favorite table&lt;/li&gt;
&lt;li&gt;If there was a typo on the book title, instead of having to go through that giant list of favorites we had in the previous design and updating each record, we can simply update the &lt;code&gt;title&lt;/code&gt; field of one single row in the books table, which is much simpler, and the user favorite table remains completely correct&lt;/li&gt;
&lt;li&gt;Because we use foreign keys, we won’t have any “junk data” made for users that don’t exist or books that don’t exist as the result of application or user error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s also something cool you can do with SQL called &lt;code&gt;CASCADE ON DELETE&lt;/code&gt; which means that if a user is deleted or a book is deleted, all the records related to it in the user favorite table also get deleted. There is also something called &lt;code&gt;CASCADE ON UPDATE&lt;/code&gt;, so in the scenario of a typo potentially you could correct it in one place, and have it reflected everywhere. Cool, right!? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 2: Deduplicate data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You might see the example above and think, “I don’t really feel like querying three tables, why don’t I add more user info to the user favorite table because we need it all to display on the favorites page”. You might wind up with a table something like this: &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;user_id&lt;/th&gt;
&lt;th&gt;book_id&lt;/th&gt;
&lt;th&gt;user_name&lt;/th&gt;
&lt;th&gt;book_name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;jtkaufman737&lt;/td&gt;
&lt;td&gt;Homegoing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;jtkaufman737&lt;/td&gt;
&lt;td&gt;Shadow and Bone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;jtkaufman737&lt;/td&gt;
&lt;td&gt;The Ninth House&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;jtkaufman737&lt;/td&gt;
&lt;td&gt;Infidel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;jtkaufman737&lt;/td&gt;
&lt;td&gt;The Big Machine&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Look at how many records we have repeating that username! What happens if I want to update my username? What happens if there was a typo in the book name? &lt;/p&gt;

&lt;p&gt;The reason it is better to stick to the ID numbers and keep this table small are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;there is less to update&lt;/li&gt;
&lt;li&gt;IDs/key values don’t really change, ever, so we don’t care so much if they are repeated, its not as if it will ever lead to a bunch of updates&lt;/li&gt;
&lt;li&gt;Integers are a small data type, so it is better for storage and quicker for searching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, it is almost always the case that &lt;strong&gt;tables are not the correct place for combining your data into a convenient format&lt;/strong&gt;. Tables need to be a pure source of truth. (SQL does give you an option for combining your tables “virtually” though, with something called a &lt;em&gt;view&lt;/em&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Your data needs to be really, REALLY independent
&lt;/h3&gt;

&lt;p&gt;At the level of a single record, and the value of a single column, we really need our data to stand on its own two feet for good data modeling. If you make a change in column A, it should not change the meaning of column B. Nor should the meaning of columns be different if you were to change their order. Either of these things is a sign that your data is not structured properly. You should not need to worry about having to update &lt;code&gt;field a&lt;/code&gt; just because something was changed in &lt;code&gt;field b&lt;/code&gt;. In that case, those data are not truly independent, and some logical concession needs to be made so that they can be treated like the related pieces of data they are. &lt;/p&gt;

&lt;p&gt;Let’s look at another variant of our GoodReads data. Say we had a table like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;book_id&lt;/th&gt;
&lt;th&gt;genre_id&lt;/th&gt;
&lt;th&gt;genre_type&lt;/th&gt;
&lt;th&gt;author&lt;/th&gt;
&lt;th&gt;published&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Historical Fiction&lt;/td&gt;
&lt;td&gt;Jane Eyre&lt;/td&gt;
&lt;td&gt;1800&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Sci-Fi&lt;/td&gt;
&lt;td&gt;Bill Murray&lt;/td&gt;
&lt;td&gt;2001&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A change in the &lt;code&gt;genre_id&lt;/code&gt; would also require a change to &lt;code&gt;genre_type&lt;/code&gt;. These columns have a dependency, which means you cannot cleanly update one field, which in a perfect world you would be able to do no problem. For this reason, it is again, better to break up our data:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;book table&lt;/code&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;book_id&lt;/th&gt;
&lt;th&gt;genre_id&lt;/th&gt;
&lt;th&gt;author&lt;/th&gt;
&lt;th&gt;published&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Jane Eyre&lt;/td&gt;
&lt;td&gt;1800&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Bill Murray&lt;/td&gt;
&lt;td&gt;2001&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;genre table&lt;/code&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;genre_id&lt;/th&gt;
&lt;th&gt;genre_name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Historical Fiction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Sci-Fi&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Your data should be as regulated as possible
&lt;/h3&gt;

&lt;p&gt;This is something that bites me from time to time in application code. The database permits more values than I would expect, so we have unexpected &lt;em&gt;data variance&lt;/em&gt;. Maybe that means there are a mix of abbreviations and full state names in a table pertaining to addresses. Maybe the falsey value for a column can be either &lt;code&gt;{}&lt;/code&gt; or &lt;code&gt;NULL&lt;/code&gt;, so a condition I wrote looking for &lt;code&gt;NULL&lt;/code&gt; is not behaving as expected, since it was really supposed to catch all falsey values (that one happened to me recently). Good ways to keep your data quality high:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rely on lookup tables as much as possible to act as enums, forcing only data conforming to valid options to be created&lt;/li&gt;
&lt;li&gt;Pick column data types that enforce quality: should an email field ever allow &lt;code&gt;NULL&lt;/code&gt; values when users register for your site? Probably not. You can tell the database not to allow &lt;code&gt;NULL&lt;/code&gt; values. There’s also no reason to pick a data type that allows text characters if the column should only ever expect numeric input.&lt;/li&gt;
&lt;li&gt;You should use &lt;code&gt;CASCADE&lt;/code&gt; options so that there is never “orphan” data, child data to some parent entity left over after the parent entity is deleted&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  In closing
&lt;/h3&gt;

&lt;p&gt;There is much more to get into on this topic, but I sat down to write this for a newer frontend engineer with an upcoming data modeling interview and I wondered to myself “what are the bare basics that I’d want them to know?”&lt;/p&gt;

&lt;p&gt;Data modeling, database design, and performance are deep, fascinating subjects in their own right and if you liked this article, there is a ton more to read and learn. But for someone new in the field juggling learning on multiple fronts, what I’ve outlined here is a perfectly solid foundation for a data modeling discussion while interviewing. &lt;/p&gt;

&lt;p&gt;If you want to know more about the building blocks of SQL, I also gave a workshop which you can find &lt;a href="https://www.notion.so/Data-modeling-basics-b70b46b624e946d7ad42609d3a513764" rel="noopener noreferrer"&gt;here&lt;/a&gt; that discusses SQL basics and terminology more in depth, check it out! 🤓 I also highly recommend &lt;a href="https://sqlbolt.com/" rel="noopener noreferrer"&gt;this tutorial&lt;/a&gt; on SQL commands and syntax if you would like some practice learning structured query language.&lt;/p&gt;

</description>
      <category>sql</category>
      <category>interviewing</category>
      <category>career</category>
      <category>database</category>
    </item>
    <item>
      <title>Surviving live code interviews for newbies</title>
      <dc:creator>JTK</dc:creator>
      <pubDate>Fri, 02 Sep 2022 19:15:57 +0000</pubDate>
      <link>https://dev.to/heyjtk/surviving-live-code-interviews-for-newbies-5hn6</link>
      <guid>https://dev.to/heyjtk/surviving-live-code-interviews-for-newbies-5hn6</guid>
      <description>&lt;p&gt;One of the questions I get a lot is about live coding interviews. Like interviews, there is a HUGE variety in what you may be asked to do during live coding. Some of it is totally open-ended, no trick questions, just writing basic methods. Some of it is done in a live collaborative environment like repl.it. Others are the standard “is this string a palindrome” type riddles. &lt;/p&gt;

&lt;p&gt;There is good news and bad news in that, you can’t prepare perfectly for everything, so there is no point driving yourself crazy. However you can stick to some simple guidelines to make a good impression while live coding, even if you make mistakes, or don’t finish the exercise. &lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;While I personally avoided this topic for a long time out of being intimidated, I have done my best to come up with goofy, memorable, and painfully straightforward examples in this section below about Big O notation. Although optional reading, I hope you’ll give it a try and feedback is welcome 👇&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://dev.to/heyjtk/big-o-notation-basics-made-dead-simple-1c9m"&gt;A brief conversation about big O&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are not ready to dive into the big O conversation yet, I would summarize it (in terms of actionable things to focus on in coding interviews) with the following guidelines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hash data structures are superheroes (python dict, JS object, etc)&lt;/li&gt;
&lt;li&gt;Getting loop-requiring data structures (like arrays) into hashable data structures will be your friend&lt;/li&gt;
&lt;li&gt;Getting from nested loops to singular loops will also be your friend&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Part I: Getting started
&lt;/h3&gt;

&lt;p&gt;You are at an interview. You may or may not have known there was going to be live coding. In the first few minutes, I would say you have a few key priorities:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Take a minute to quietly read the problem to yourself&lt;/strong&gt; 📓&lt;/p&gt;

&lt;p&gt;Take a minute to read, then reread the problem to yourself. Don’t think of solutions yet, make sure you really understand it. I have definitely read too fast and gone off half-cocked with a  solution that missed edge cases before.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pick the language you are best with - seriously&lt;/strong&gt; 👨‍💻&lt;/p&gt;

&lt;p&gt;If given the option to pick a programming language, don’t worry about picking what the company uses or picking a language to make “a better impression”. It is already a high-stress scenario, pick what you are most comfortable with. If it isn’t what they use, in the past I’ve offered a breezy rationale like “I wind up doing most leetcode problems with x, so guess I’ll go with that”. If they offer the options, they intend to let people use them. Don’t worry about picking JS over Ruby looking bad or anything like that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make sure their code environment is working (run hello world)&lt;/strong&gt; 👋🏽&lt;/p&gt;

&lt;p&gt;Believe it or not, I have had the collaboration tool break! Check that you are in good shape by just running a quick log statement. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Set the tone with your interviewer for narration and conversation&lt;/strong&gt; 🗣️&lt;/p&gt;

&lt;p&gt;Let the interviewer know you plan to ask them for feedback and chat with them through your approach, like you would with a colleague in the real world. It feels much less like public speaking when there is back and forth. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have your interviewer collaborate on some test cases&lt;/strong&gt; 🏁&lt;/p&gt;

&lt;p&gt;It is easy to miss things in the heat of the moment, so this is a great area to get extra eyes. &lt;/p&gt;

&lt;p&gt;Bringing some of the above points together, this is something close to what I think I say at the beginning of code challenge interviews: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Me:&lt;/strong&gt; Great, so first I'm going to take a minute and read over the problem to &lt;br&gt;
myself if that's alright&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interviewer:&lt;/strong&gt; Of course! Have at it &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;... &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Me:&lt;/strong&gt; Great, so before I get too far into this I want to run a quick hello &lt;br&gt;
world from this function and make sure everything is cooperating. &lt;br&gt;
...&lt;br&gt;
Awesome, looks good. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Me:&lt;/strong&gt; So now to get started, I'm going to try to explain what I'm doing and my thinking to you as I go. Feel free to jump in as I'm coding, I think it will be great if this is collaborative and gives us a sense of how we'd pair &lt;br&gt;
together if I joined the team. I'll probably have questions for you as we go also. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interviewer:&lt;/strong&gt; Yeah that sounds great! And I will chime in periodically to remind us of where we are with time, so if we run out there's some room to discuss what you'd do next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Me:&lt;/strong&gt; Sure, sounds perfect. So to start with, I don't want to miss any edge cases. I was going to put together some test cases and whether they should pass or fail. If there is anything I miss as I'm doing these, please don't hesitate to &lt;br&gt;
let me know. Being on the spot for coding interviews, sometimes can be nerve-wracking and I don't want to accidentally miss anything.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(etc etc) &lt;/p&gt;

&lt;p&gt;Probably if you ask 10 people how they like to start code challenges, you’ll get ten different answers. Some people may not like my last comment, that I admit I’m on the spot and may miss something. In my experience interviewers have responded to that in a pretty human way, I even feel that it has been helpful? Sometimes they have supplied a test case I would not have thought of, and sometimes it does illustrate some aspect of the code challenge I hadn’t realized yet and would have wasted time dealing with later. &lt;/p&gt;

&lt;p&gt;Especially when you are new to code challenges and extra nervous, you can go quiet for a second thinking about your approach, and the seconds spiral into minutes, and you are just sitting there silently panicking. It is good to get the conversational rapport going early. For a junior coder, it is honestly pretty normal to get stuck on some aspect of a code challenge, but if you are already in a conversational rhythm with interviewer it is much easier to say “I feel a bit torn but think my approach should be this…” and open the door for feedback and direction. If you have been sitting there silently for several minutes, it feels way more awkward to suddenly ask for help. &lt;/p&gt;

&lt;p&gt;It varies place to place, but in many interviews the code working is ABSOLUTELY not the only outcome they are looking at. They are looking at collaboration (especially for juniors!) they are looking for how you deal with ambiguity, that you ask for help and don’t get stuck and spiral into panic. I would say almost always in code challenges, if you can convey what you are or were trying to do you can get “partial” credit for that alone, even if you were not close to a successful implementation. &lt;/p&gt;

&lt;h3&gt;
  
  
  Part II: In the thick of it
&lt;/h3&gt;

&lt;p&gt;So you have your test cases set out, you have the code running. The pleasantries and housekeeping items from the last step are sort of the “easy part” when I do code challenges, and when you are through all that just staring at the code that’s the moment where it is easy to lose your head. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡Listed below are the BIGGEST priorities while doing the main task.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Comment out the steps/phases of your solution immediately (”comment skeleton”)&lt;/strong&gt; 🦴&lt;/p&gt;

&lt;p&gt;For me, that looks something like this early into a code challenge:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// previously empty function where I did my hello world &lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;myCoolAlgo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sortedList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// first, I'm going to build a hash from my list items so that I can look&lt;/span&gt;
   &lt;span class="c1"&gt;// them up more efficiently &lt;/span&gt;

   &lt;span class="c1"&gt;// next, I want to build a separate validation method to check &amp;lt;blah&amp;gt;&lt;/span&gt;

   &lt;span class="c1"&gt;// third, I want to &amp;lt;blahblahblah&amp;gt; &lt;/span&gt;

   &lt;span class="c1"&gt;// next, I'll take the result indices and see if they are a prime number&lt;/span&gt;

   &lt;span class="c1"&gt;// last, I'll return the result * 23&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;^ by the way, the comment bodies are totally fictitious, no clue what kind of code challenge that would be. But that’s along the lines of stuff I would write. &lt;/p&gt;

&lt;p&gt;I like to comment out the stages of what I think I need to do early. A) to get feedback, and B) so if I get panicked and lose my train of thought, I have some reminders. For places that may save the code, it also provides a trail of bread crumbs into what your plans were if you had more time. &lt;/p&gt;

&lt;p&gt;Many places are more understanding than you might think about not finishing. Others, they have a laundry list of items that they would add on to the challenge indefinitely, so there is no real “end”, but you may be able to make an impression even on parts of the task you didn’t have time for by leaving some comments with your ideas. &lt;/p&gt;

&lt;p&gt;Giving my code a “comment skeleton” is maybe one of my more helpful habits ever in code challenges. I mean it, they do so much good. They keep you from losing your train of thought, for starters. It is also great to see a new coder comment their code, since sometimes junior software engineers do not write the most clear code anyway it is particularly needed for the work of an early career dev, and I know for me seeing an interview-ee has good comment practices would be a huge plus. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Talk about why and how you are making your decisions&lt;/strong&gt; 📰&lt;/p&gt;

&lt;p&gt;if you read the Big O thing linked earlier, or have performance considerations that led you to your solution, this is a great time to talk about your thinking on performance (so you get partial credit for that, even if you don’t finish getting them working). It is also a chance to reveal your knowledge passively outside of the specific code you are writing. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For each increment of new code, run some of your test cases&lt;/strong&gt; 🧪&lt;/p&gt;

&lt;p&gt;If you have commented your code out into “sections” sort of as I suggest, finishing each section is a great time to run some of your test cases and log what is happening so that you can guarantee you don’t go farther on nonworking code &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep the conversation going, solicit feedback&lt;/strong&gt; 💬&lt;/p&gt;

&lt;p&gt;It is also SO SO important to keep the conversation going here! You really can get “partial credit” for things you know but are not implementing. I know I’ve said things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I have a feeling I could get the performance better here, I’d like to get this working first and circle back to it at the end with time permitting&lt;/li&gt;
&lt;li&gt;For some reason I have a suspicion there might be edge cases that could bite us at this point, but I can’t put my finger on one…do you have any thoughts?&lt;/li&gt;
&lt;li&gt;I had hoped that I could keep this in a single loop for performance, but at this point am not seeing a way around adding a second. If I have time at the end, I would definitely come back and tighten up some things, just as I would with real code before submitting a PR&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The subtext, or literal commentary I sometimes have at those points is along the lines of “YOLO code interviews are stressful”. I find owning it relaxes me somehow? Just saying you know what, I have limited time here, some of it is setting off my spider senses and I’d like to revisit it, but out of respect for the time limit I’m going to move on for now. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Some other things to keep in mind&lt;/strong&gt; 🧠&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ctrl + f can be your friend, misremembering my own variable names is maybe my biggest cause of errors/debugging in code challenges 🥴 usually you can ctrl + f down a page to track something and at least rule that out&lt;/li&gt;
&lt;li&gt;When torn between a longer, descriptive name and a shorter, ambiguous one pick the longer one&lt;/li&gt;
&lt;li&gt;Even though you are in a rush, take time to make sure your code is reasonably formatted and your variables are named reasonable things&lt;/li&gt;
&lt;li&gt;Although often code challenges are in the scope of a single function, if your function gets too big it is worth either mentioning or implementing breaking the logic out into a separate function just to show you understand separation of concerns. If you are tight on time, its fine to just add that in running commentary “normally I would break this out” etc&lt;/li&gt;
&lt;li&gt;Sometimes the unexpected happens! I have had the collaboration tool fail on us unexpectedly. It is good to have a backup in mind. I think when that happened to me I recommend we switch to &lt;a href="http://repl.it" rel="noopener noreferrer"&gt;repl.it&lt;/a&gt; and screenshare, and I wound up getting that job haha&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Part III: Wrapping up
&lt;/h3&gt;

&lt;p&gt;I think every code challenge I have done has been a unique adventure. The first one I did was a train wreck and after that I avoided them for quite a while, I got so lost in my code that I was basically just rambling nonsense by the end. Others, I’ve felt I did nothing special and got job offers. Others, I’ve felt I nailed but got shot down. &lt;/p&gt;

&lt;p&gt;Code challenges are kind of a terrible way of assessing coders because of the fact that public speaking is one of the most common phobias people have, and even without a phobia there’s still plenty of other rational anxiety to have about them. &lt;/p&gt;

&lt;p&gt;Although they always feel stressful, I think I can count on one hand the live coding challenges I’ve felt were truly awful: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I asked them how to prepare, they said NOTHING about live coding, then sprung it on me before we even had done basic chitchat. I was totally flummoxed (this was that first one I mentioned). I couldn’t remember the difference between &lt;code&gt;slice&lt;/code&gt; and &lt;code&gt;splice&lt;/code&gt; in JavaScript and just absolutely spiralled over my inability to remember. It sucked monumentally in the moment, but I very quickly moved to finding it kind of hilarious. By the end I knew I bombed so bad I was just giving random database hot takes because it was like? Who cares &lt;/li&gt;
&lt;li&gt;They had one of those code editors where you couldn’t run the code. I probably would never even do an interview with those again. It is SO UNREALISTIC! It is not how we write code, and yeah it really did a number on me, I think I did very poorly with that premise &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Over time, I’ve kind of come to even &lt;em&gt;like&lt;/em&gt; coding challenges just because they are so relatively fast and over with so quickly. The more I did, I realized how much you get so-called “partial credit” for things you didn’t finish, so long as you are communicating. I realized people weren’t really watching me just looking out for any dumb mistake as I’d feared. It really is a lot about how you think, how you collaborate, and it seems like many that I’ve done have found finishing on time secondary. &lt;/p&gt;

&lt;p&gt;But as you are wrapping up your code challenge, here are my final pieces of advice for you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reiterate anything you would change/continue working on in the current code (this is a nice point to mention you would of course add tests to any functionality you write)&lt;/li&gt;
&lt;li&gt;Thank the interviewer for their time, and emphasize that you feel you can definitely thrive in a collaborative coding environment&lt;/li&gt;
&lt;li&gt;You can offer a brief defense or acknowledgement of anything that went wrong, and how/why it unfolded and either what you learned, or how you might avoid it in the future. But definitely thread the needle on keeping it positive/brief here&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And voila, that’s it! &lt;/p&gt;

&lt;p&gt;Optionally afterwards, you can send a follow-up note. It won’t hurt anything to add “I feel so silly that I did not think of this while on the spot, chalk it up to interview nerves, but realized immediately after the interview ended I could have used x to do y. I wish I would have thought of it during our session, but appreciate the opportunity and would look forward to any next steps” to whoever you paired with. In my experience, it is unlikely to hurt anything and shows some self-awareness, if you don’t feel you had time to address it in the interview already. &lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The biggest thing I would want anyone to know for live coding interviews is that you can’t perfectly prepare for them. Even doing this a long time now, some days I bomb. I’ve had recent interviews where for whatever reason, I could not sleep a wink the night before. My last interview cycle actually I had the bad luck to have this happen TWICE! I felt that I completely flubbed both, one resulted in an offer and the other a rejection. &lt;/p&gt;

&lt;p&gt;Live coding is inherently stressful. For me, it has become hugely more manageable over time, so maybe there is something to practicing. You can definitely arrange ways to practice with friends, alternating Leetcode problems while screensharing over Zoom or whatever.&lt;/p&gt;

&lt;p&gt;At this point in my life, I don’t know if I will ever stop being nervous to live code, but at this point it is much more like going to the dentist or some other mundane trial than the terrifying gauntlet I once found it to be. &lt;/p&gt;

&lt;p&gt;So at the end of the day, chin up, it isn’t the easiest thing in the world but the experience is helpful. You also never know when you will get lucky. I once live coded a problem where I had recently received the exact same on Leetcode and had a solution perfectly ready to go. &lt;/p&gt;

&lt;p&gt;There is always the unpleasant possibility that live coding is going to result in you feeling silly or even stupid for an hour, but over the years I’ve started to look at it like “Am I willing to feel stupid for an hour in exchange for a $50k raise?” because more than once, that’s been at stake and it has been secured through live coding. So at this point in my life, I say hell, sign me up to feel stupid for an hour, what’s the worst that can happen 😎&lt;/p&gt;

</description>
      <category>career</category>
      <category>jobhunt</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Big O notation basics made dead simple</title>
      <dc:creator>JTK</dc:creator>
      <pubDate>Fri, 02 Sep 2022 19:06:38 +0000</pubDate>
      <link>https://dev.to/heyjtk/big-o-notation-basics-made-dead-simple-1c9m</link>
      <guid>https://dev.to/heyjtk/big-o-notation-basics-made-dead-simple-1c9m</guid>
      <description>&lt;h1&gt;
  
  
  A brief conversation about big O
&lt;/h1&gt;

&lt;p&gt;To be honest with you, when I first got into programming I procrastinated learning Big O for quite a while out of intimidation, and this article is really for anyone out there who feels similar. I don’t know if it will help for me to say that most of it is common sense and the math doesn’t get much harder than multiplication. But just in case, I will add some visuals to make this as non-miserable as possible. The graphics are super silly, but honestly that helps me remember things. &lt;/p&gt;

&lt;p&gt;If I were to give you the simplest version possible of the idea behind Big O notation, or the time complexity of how your code runs, it would be something like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;basic operations are the most efficient&lt;/li&gt;
&lt;li&gt;repeated operations (loops) can be more of a worry for efficiency&lt;/li&gt;
&lt;li&gt;nested loops are among the biggest worries for efficiency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Honestly, that’s the basics. Not too terrible right? There’s also a whole category of things you never have to think about when figuring out the performance of your code. You can consider them “Freebies”. They include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;basic math, addition and subtraction&lt;/li&gt;
&lt;li&gt;assigning variables&lt;/li&gt;
&lt;li&gt;if/else conditions&lt;/li&gt;
&lt;li&gt;declaring a function&lt;/li&gt;
&lt;li&gt;calling a function (at face value)&lt;/li&gt;
&lt;li&gt;changing variables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If I had to sum the concept of Big O up in simplest terms imaginable, &lt;strong&gt;loops are pretty much all we are worried about&lt;/strong&gt;. I know when I realized that, I felt a lot less intimidated. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡A note before we begin: This is meant to be the absolute basics, for people who think Big O notation sounds like archaic rituals. There are more nuances, and more descriptors, than I’ve included here. Whenever there is a chance to take clarity vs greater detail, I have chosen clarity. This post is for folks a few months into programming who need basic, actionable info. This is part of a larger series I’m writing on live coding interviews so give that a read as well 🤓&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;To explain some of these, let’s pretend that in my free time, I like to go on scavenger hunts. My friends make the rules for these hunts and some are less challenging than others. (Sidebar, some people really do this! There is a hobby called geocaching that is pretty much real life treasure hunting. You can read about that &lt;a href="https://www.geocaching.com/play" rel="noopener noreferrer"&gt;here&lt;/a&gt; if you are curious. My examples are too silly to conform to really geocaching though so I’ll stick with the term scavenger hunt).  &lt;/p&gt;

&lt;h3&gt;
  
  
  Part I: Constant time or O(1)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;🏴‍☠️ Jamie sends me on a treasure hunt to retrieve a pen from a certain address on Chestnut street. I have one address so only need to go to one house, easy peasy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0kraf6qme6ka1wl56mg.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%2Fj0kraf6qme6ka1wl56mg.png" alt="Person icon with arrow to house icon"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is an example of what we would call “constant time”. Whether the scavenger hunt was for a pen or something else, I’m only knocking on one door in this scenario and it will not change. This is considered a &lt;em&gt;very positive&lt;/em&gt; state for algorithm performance, the most optimal actually. An example of a constant operation would be retrieving a value from a JavaScript object. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ann&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="na"&gt;hobbies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drawing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;programming&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
  &lt;span class="na"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dog&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Because JavaScript objects are an example of a hash, it is very performant to look up some value in an object. It is a perfect analog to having an exact address and being able to go straight to it without searching further. Regardless of what is inside, the step of retrieving the item is considered to run in constant time. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡For this reason, objects/hash data structures are often your friend in code challenges.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sometimes getting arrays into an object format can be hugely helpful for good performance in these types of challenges. We call this constant time O(1), in Big O notation. &lt;/p&gt;

&lt;h3&gt;
  
  
  Part 2: Logarithmic time, or O(log N)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;🎁 My friend Jake has set me on a trickier task. There is a new development being built near me but they have not added visible street signs. If I walk up to the houses though, They have notated the address on beams by the front door. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I don’t really want to have to walk up to each house individually, but after thinking about it I realize Jake has shared that the home address numbers increase as you progress down the street. &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%2Feaa5ue6v12z1nd4crgus.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%2Feaa5ue6v12z1nd4crgus.png" alt="Image of street with leftmost house labeled as lowest house number, rightmost house labeled as highest house number"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I don’t know the starting number as the road continues a ways past this cul de sac in the opposite direction, so I’m not sure what the lowest house number is. But I do know I’m looking for #22. I realize that if I start in the middle of the street, I’ll see if the address is lower or higher than what I’m looking for, and can knock out half the houses on the block, so I don’t have to search those. &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%2Facx1vjb39fda9iclcet3.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%2Facx1vjb39fda9iclcet3.png" alt="Image with arrow pointing to middle house and house number revealed to be 26"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I see the house in the middle is #26, so all the houses to the right of this one would have house numbers too high for what I’m looking for, #22. So I can cross off the house I walked up to, and all the houses to the right because they would have even higher numbers. &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%2Fbbzco2mdtryyexkrfvm8.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%2Fbbzco2mdtryyexkrfvm8.png" alt="Have put black circles over houses on the right half of the street now that I know their house numbers are too high"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now in a normal world, these houses would all be regular and I could just count my way to the correct one, but I see some empty dirt lots and can’t tell if those will also become homes or are for landscaping or parks. Because I’m not entirely sure what are lots, I am not sure just counting my way down the street to the correct house would work. &lt;/p&gt;

&lt;p&gt;So I decide to go with my “pick from the middle” approach again, and that way can at least cross of half of the remaining section of the street based on if the house is numbered too high or low. For this reason, I pick the middle house again of my remaining three houses. &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%2F0ltkv4s0g60bx9byqw5u.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%2F0ltkv4s0g60bx9byqw5u.png" alt="Arrow pointing to middle house of the three remaining houses, now circled in green because I have revealed it to be house number 22"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whaddya know! That’s the correct one. If you want to think of my “treasure hunt algorithm” the end result is pretty good. I wound up only having to walk up to two houses even though there were seven on the street. In terms of how much work I had to do to succeed at this task, my approach meant that the remaining houses to search would have been cut in half each time I walked up to one.&lt;/p&gt;

&lt;p&gt;We call the performance when you cut the result set each time &lt;em&gt;logarithmic performance&lt;/em&gt;, and after constant time (O(1)) it is as ideal as you can get. Even though you have a result set of 7, the operations you perform could be as low as 2. If you don’t remember much about logarithms from math, that’s honestly fine - all you need to know is that its a GREAT performance for an algorithm to have, because you are cutting your result set down significantly each time. &lt;/p&gt;

&lt;p&gt;In Big O language, we write logarithmic performance as O(log n). If you are worried about memorizing the big o descriptor, simply calling it “logarithmic time” in an interview is perfectly ok. And if all you need to know is that logarithmic time means that each pass you cut your results down potentially by half, it is pretty easy to recognize this when you are doing it. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As a side bar: my scavenger hunt example is an example of a &lt;strong&gt;binary search algorithm&lt;/strong&gt;. Not too bad, right? Just pick from the middle over and over. It is a great algorithm to use if you know your results are already in some type of order.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Part 3: Linear time, or O(n)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;🍬My friend Jess, on hearing how much work I’ve been putting into these scavenger hunts, takes pity on me. Lucky for me it happens to be October 31st and she assigns me the task of trick or treating! My treasure hunt is to get one piece of candy from every house on Sycamore street.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this somewhat deliberately messy graphic, you can see how much work this is compared to my last task. &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%2Foy6go63xer4jne7g0wm8.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%2Foy6go63xer4jne7g0wm8.png" alt="Image of a person with arrows pointing to each of many houses on a cul de sac"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is what we call in Big O “linear time”, aka a loop, aka simple multiplication. My task is multiplied by the number of houses. On a bigger street, that might be 50 trips. My work increases in a linear fashion based on what street I’m on and how many houses it has.&lt;/p&gt;

&lt;p&gt;For big O, linear time is a &lt;em&gt;good&lt;/em&gt; algorithm performance in many cases. Not as good as the first two we covered, but normally a code challenge you would receive in an interview is complex enough that there is a reasonable chance loops will be required. We write this as O(n), with “n” being basically what you are multiplying by, or how many loops you’d have to do. &lt;/p&gt;

&lt;h3&gt;
  
  
  Part 4: Quadratic and cubic time
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;👿 My last pal, Andrew, is really devious and sets me on the hardest treasure hunt yet.  He sets me off on main street and says that for every house on the street, I need to see if I can find an item at each house duplicated at each other house.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Filsw97f8gb5bpehdl9tl.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%2Filsw97f8gb5bpehdl9tl.png" alt="Picking a unique item from each house and seeing if it is in each other house"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Very quickly I’m up to 25 individual tasks, since I have five things to do for each of five houses. You can easily see if we put this to numbers I have 5 x 5 tasks, or 5^2. This is what we call &lt;strong&gt;quadratic time&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;In programming, this means one thing: nested loops! Each nested layer is adding an exponent. If my friend had said I want you to do this for more than one street, the math becomes something like neighborhood x houses x items, and could easily get into &lt;strong&gt;cubic time&lt;/strong&gt;, or O(n^3), often presented in a &lt;strong&gt;third nested loop&lt;/strong&gt; in real life. &lt;/p&gt;

&lt;p&gt;My example is pretty manageable still, but in real life programming we are looking at way larger numbers than this. See how the tasks balloon:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Base number&lt;/th&gt;
&lt;th&gt;Tasks ^2&lt;/th&gt;
&lt;th&gt;Tasks ^ 3&lt;/th&gt;
&lt;th&gt;Tasks ^ 4&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;1000000&lt;/td&gt;
&lt;td&gt;100000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;td&gt;1000000&lt;/td&gt;
&lt;td&gt;1000000000&lt;/td&gt;
&lt;td&gt;1000000000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100000&lt;/td&gt;
&lt;td&gt;10000000000&lt;/td&gt;
&lt;td&gt;1000000000000000&lt;/td&gt;
&lt;td&gt;100000000000000000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000000&lt;/td&gt;
&lt;td&gt;1000000000000&lt;/td&gt;
&lt;td&gt;1000000000000000000&lt;/td&gt;
&lt;td&gt;1000000000000000000000000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is maybe the &lt;strong&gt;most important area&lt;/strong&gt; I can talk to you about. It comes up the most in my job and the most programming. You can quickly see why it gets important fast. &lt;/p&gt;

&lt;p&gt;You will notice that that first row where your base number is 100 can quickly get into more operations than that last row, with a starting number of a million, if they are not careful about nested looping. Someone with a data set a million large can have a program doing less work than someone with that data set of 100 records, all depending on how careful they are with nested looping.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Most of the finer points that come up for me in code challenges are if I can get something from a loop to constant time, and then if I can get something from a nested loop to a single loop. (So from cubic time O(n^3) to quadratic time O(n^2)).&lt;/em&gt;* &lt;/p&gt;

&lt;p&gt;We also have a more general word to represent situations where the exponent is going to be to the power of n: *&lt;em&gt;exponential time (O(2^n))&lt;/em&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Part 5: What this may look like
&lt;/h3&gt;

&lt;p&gt;Let’s say we got the following code challenge. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;

Given an array of unique integers and a target number, determine if any two 
numbers in the array when added together would equal the target. If that 
condition is met, return the array position of the two numbers. You cannot 
reuse a number at a single index position (So array [4,2] could make
target number 6, but array [3] could not since it would require reusing the
array value at position array[0]).

Example: given array [1, 2, 3, 4, 5, 6] and target number 10, you would return 
an answer [3, 5] since at array[3] you have number 4, at array[5] you have 
number 6, and added together they make 10. 

Example: given array [1,2,4] and target number 50, you would return false 
because the condition can not be met. &lt;span class="sb"&gt;


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

&lt;/div&gt;

&lt;p&gt;This is a paraphrase of a Leetcode problem, where below it asks follow up question, “Can you get the time complexity below O(n^2)”. The fact that they ask is a good hint that we might. But for a very new programmer, the obvious way to solve this problem might be something like this. (You can also run the code yourself, &lt;a href="https://replit.com/@jtkaufman737/FlashyFlashyHexagons#index.js" rel="noopener noreferrer"&gt;here&lt;/a&gt;). &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%2Fl8s1mkui6g3aphuq2dt5.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%2Fl8s1mkui6g3aphuq2dt5.png" alt="Image of repl.it with javascript code containing a nested loop"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that very quickly, the exponential logic catches up with us and we have quite a few individual task calls in this method. &lt;/p&gt;

&lt;p&gt;Going back to what I said before about trying to get things into shape where you can take advantage of constant time and linear time, I’m going to use all the same test cases but rewrite this function in a way with better Big O. (BTW, this is illustrative, maybe not precisely how I would solve this problem so don't come for me in the comments lol). &lt;/p&gt;

&lt;p&gt;Hashes are really your friend in these kind of problems. So when I iterate over my list, I’m going to make a JavaScript object where each key is what the list item would need to be added with to reach the target number, and the value would be the index I found this item at.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;

Example: given target number 8 and list [1,2,3,4,9,6] my JS object would 
look like this:
{
   // first array item is 1, we'd need to find a 7 to make 8, its at index 0
   7: 0, 
   // second array item is 2, we'd need to find a 6 to make 8, its at index 1
   // so on and so forth
   6: 1, 
   5: 2, 
   4: 3,
   6: 5
}&lt;span class="sb"&gt;


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

&lt;/div&gt;

&lt;p&gt;So with this object, it means I don’t need to do a nested loop. I can do another regular loop (so linear time) and just check if the current list item is one of the keys for this Javascript object. If it is, I’ve found a matching pair whose sum is the target number. I have saved the index where the first number was located as the key value so I already have that handy, and then can just return the index of the list item I am on in my second loop. You can also play with this code &lt;a href="https://replit.com/@jtkaufman737/KnowingRequiredNumerators#index.js" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &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%2Fhqi34wxbm4vmyz42nci6.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%2Fhqi34wxbm4vmyz42nci6.png" alt="Image of problem with two separate instead of nested loops"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I used the same test cases, and you can see got the same results. But with my nested loop approach the worst performance we saw was &amp;gt; 200 operations, and by not nesting my loops it is only THIRTY! That’s pretty amazing. And it wasn’t too hard, once you get used to thinking this way, to extract the nested loop behavior and find another way. &lt;/p&gt;

&lt;h3&gt;
  
  
  Visualizing what we’ve learned
&lt;/h3&gt;

&lt;p&gt;One great way to drive home how these perform is to look at a graph of performance, I grabbed this one from &lt;a href="https://stackabuse.com/big-o-notation-and-algorithm-analysis-with-python-examples/" rel="noopener noreferrer"&gt;this website&lt;/a&gt;.&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%2Fixn1wl5puymyu61zfuwz.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%2Fixn1wl5puymyu61zfuwz.png" alt="Graph of Big O performance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Another fun note
&lt;/h3&gt;

&lt;p&gt;You may wonder when looking at the problem above, is the Big O notation O(2(n)) since we are looping twice? If a loop is O(n), we have done that twice: once to build the JavaScript object, and a second time to process the list again and see if we have two numbers that will sum to the target number.&lt;/p&gt;

&lt;p&gt;If you remember me saying that &lt;strong&gt;all we care about is loops&lt;/strong&gt;, mainly, add an asterisk here to say we care about the &lt;strong&gt;greatest magnitude of operation present&lt;/strong&gt; in the problem. What does that mean? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you have a loop in your program with performance O(n), and later in the code you have a nested loop with performance O(n^2), we call the big O simply O(n^2) - the exponent is the behavior of the highest order of magnitude in the program, aka the biggest worry. So we drop the lesser one&lt;/li&gt;
&lt;li&gt;If you have a nested loop running at O(n^2), and later on a triple-nested loop running O(n^3), we would simplify that to cubic time. That triple nested loop is the highest order of magnitude thing going on in the code so we simplify to call it O(n^3).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you think about it, it is more fair to do it this way. Almost everything you will write  will have some operations that are O(1), but it is almost never accurate to say the overall performance of a program is O(1). If it has a single loop, that statement will not be accurate. &lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;There are some other types of Big O notation we could cover, but these are the ones I see most commonly and they should get a new programmer pretty far in code challenges. Even if you don’t feel super into math concepts, remembering that loops are the biggest thing you need to worry about is I think easy enough advice that anyone can keep in mind, and it really does help you in keeping performance in mind no matter what level of coding expertise you have. &lt;/p&gt;

&lt;p&gt;Also, here are some other great resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://betterprogramming.pub/big-o-notation-a-simple-explanation-with-examples-a56347d1daca" rel="noopener noreferrer"&gt;Big O Notation with examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.freecodecamp.org/news/time-is-complex-but-priceless-f0abd015063c/" rel="noopener noreferrer"&gt;Algorithms in plain english, time complexity and Big O Notation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>softwareengineering</category>
      <category>algorithms</category>
      <category>coding</category>
    </item>
    <item>
      <title>Turbocharged Candidate Search With Algolia</title>
      <dc:creator>JTK</dc:creator>
      <pubDate>Tue, 26 Jul 2022 22:38:39 +0000</pubDate>
      <link>https://dev.to/heyjtk/turbocharged-candidate-search-with-algolia-3gka</link>
      <guid>https://dev.to/heyjtk/turbocharged-candidate-search-with-algolia-3gka</guid>
      <description>&lt;h3&gt;
  
  
  Thinking back to the stone ages of recruiting, before AI
&lt;/h3&gt;

&lt;p&gt;Something you all may or may not know about me is that I found my way to tech through a very unconventional route: recruiting! No, I wasn’t recruited, I was the recruiter.&lt;/p&gt;

&lt;p&gt;Back in the day, my claim to fame was that I was certified in Boolean logic searches. This came in handy when I used to work in government contracting. Very specific and rare combinations of a security clearance and one or many certifications were required for many of our hires. When I first heard about &lt;a href="https://www.algolia.com/about/" rel="noopener noreferrer"&gt;Algolia&lt;/a&gt;’s tools for AI-powered search, ranking, and recommendation, I thought back to those days I spent arduously searching for candidates. Naturally, I was curious to delve into what might be possible now that AI has the ability to superpower tasks that were once long and tedious.&lt;/p&gt;

&lt;p&gt;With that in mind, join me as I explore some of the capabilities of Algolia! I chose to do this with VueJS, but that was nearly at random considering the &lt;strong&gt;vast&lt;/strong&gt; number of language SDKs available, which you can see more &lt;a href="https://www.algolia.com/doc/guides/getting-started/how-algolia-works/in-depth/ecosystem/#using-the-api-clients" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Just a brief note before we begin: the team at Algolia is paying me to explore the tool and jot down my unbiased experiences, so all of the opinions below are my own.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Building out some candidate data
&lt;/h3&gt;

&lt;p&gt;Before taking a look at how Algolia tooling might facilitate a candidate search, I wanted to approximate some kind of candidate data. I came up with some logic that would represent a mix of skills and keywords that someone might search for. (I started this work with this &lt;a href="https://github.com/jtkaufman737/algolia-search" rel="noopener noreferrer"&gt;boilerplate Vue project&lt;/a&gt; if you would like to follow along). I almost expected there to already be something like tech-ipsum or professional-ipsum that I could lean on for this task, but sadly I didn’t really find anything!&lt;/p&gt;

&lt;p&gt;So to start with, at the root of my Vue project I created a small &lt;code&gt;seed.js&lt;/code&gt; file with the following logic to generate some “candidates” for us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// seed.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&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="s2"&gt;fs&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;seedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;frontend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fullstack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;termMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;back-end&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;python&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pytest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;django&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sql&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nosql&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;redis&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AWS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ci/cd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;fullstack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;full-stack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;python&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;javascript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sql&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;databases&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;typescript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;frontend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;front-end&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ux&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;design&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;accessibility&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tailwind&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;javascript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;typescript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;titles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;software engineer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;senior software engineer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;software developer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;programmer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;software development engineer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;randomAchievements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Led adoption of &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Increased throughput of systems using &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Introduced quality standards for &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enhanced testing of &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Coached more junior employees in &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Recognized subject matter expert for &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Led research effort on improvements to our &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Decreased bugs by 50 percent related to &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Created platform with &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Spearheaded workshops to train colleagues in &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;candidateList&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getRandomArrayItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;randomItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; 

    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;randomItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;randomItems&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateCandidateData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Silly little function to generate some candidate profiles &lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;candidates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&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;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getRandomArrayItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;seedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

      &lt;span class="nx"&gt;seedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;role&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;achievementList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getRandomArrayItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;seedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;randomAchievements&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
          &lt;span class="na"&gt;title&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;role&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="nf"&gt;getRandomArrayItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;seedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;titles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&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;let&lt;/span&gt; &lt;span class="nx"&gt;achievementsWithTechKeywords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

        &lt;span class="nx"&gt;achievementList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;achievement&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;achievementsWithTechKeywords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&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;achievement&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="nf"&gt;getRandomArrayItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;seedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;termMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resume&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;achievementsWithTechKeywords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;. &lt;/span&gt;&lt;span class="dl"&gt;"&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;candidates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile&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="nx"&gt;seedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;candidateList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;writeCandidateData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./candidates.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;seedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;candidateList&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="nf"&gt;generateCandidateData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;writeCandidateData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moving over to my terminal, I’m going to run this logic quickly to generate a file of JSON we can then use with Algolia by running &lt;code&gt;node seed.js&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;Looking over to my code editor, I now have a &lt;code&gt;candidates.json&lt;/code&gt; file full of slightly nonsensical but vaguely tech-resume-esque data, with a small sample pictured below. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3cleg329npuzpxzv178j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3cleg329npuzpxzv178j.png" alt="Candidate ipsum JSON" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not necessarily anyone I’m going to hire onto my team tomorrow but a fair enough approximation to start with. On to the star of our show, Algolia! &lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started with Algolia
&lt;/h3&gt;

&lt;p&gt;If following along, go ahead and &lt;a href="https://www.algolia.com/users/sign_up" rel="noopener noreferrer"&gt;create a free account&lt;/a&gt; with Algolia for what comes next. We’ll walk through their easy “getting started” wizard and first create an index called &lt;code&gt;candidates&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn0ndgimpaafia0p2xqt3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn0ndgimpaafia0p2xqt3.png" alt="Creating candidate index" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m going to plug in the JSON file we’d previously created, although Algolia also offers an API client that would make this task also super easy programmatically too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd78nrcqa1q0h1vivc3on.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd78nrcqa1q0h1vivc3on.png" alt="Uploading candidates" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On submitting, we are redirected to the dashboard where we can now see our data listed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4kdz5x8rc5u3ivibt1q7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4kdz5x8rc5u3ivibt1q7.png" alt="Candidate data" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Exploring some of the fun options we get with Algolia
&lt;/h3&gt;

&lt;p&gt;When you get to this point some getting-started-tips in an overlay will quickly prompt you to explore some of the cooler options that this tool makes available, including the customization options. To start with, we can choose to ignore or include attributes. For a start, I’m including both &lt;code&gt;resume&lt;/code&gt; and &lt;code&gt;title&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgh8wdowswdw50v9addxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgh8wdowswdw50v9addxg.png" alt="Selecting fields to hone in on" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why is this option cool? Well, I would definitely have benefited from the option to ignore &lt;code&gt;title&lt;/code&gt; on occasion in my candidate searches. In my first recruiting job we worked for this terrible client that had all of their IT support roles under an extremely bland title like &lt;code&gt;Support Services Technician&lt;/code&gt; or something equally nondescript. It didn’t take me long to learn that the resume keywords were going to be a much better proxy for fit than anything related to titles. This level of control would have helped me there. You also could potentially configure this type of search as part of an Applicant Tracking System (ATS) to assist with anonymizing parts of candidate profiles, to reduce any element of bias. One instance might be that if our data were structured to include fields for Education and Year Completed, you could ignore the year in to reduce the potential for ageism. Algolia explains more about the benefits of customized attributes &lt;a href="https://www.algolia.com/doc/api-reference/api-parameters/searchableAttributes/" rel="noopener noreferrer"&gt;here&lt;/a&gt;, if you’re curious! &lt;/p&gt;

&lt;p&gt;We also get the option to customize the fields most relevant in &lt;code&gt;ranking&lt;/code&gt;. Since I’m experimenting here, I’m going to set ranking to be exclusively tied to that resume field. My hypothetical scenario here is that I would be more interested in a match on Python skills than getting hung up on whether someone was a Software Developer vs Software Engineer. This side-steps the &lt;code&gt;title&lt;/code&gt; field we created for our data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ayltknxshxlneeu8jcg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ayltknxshxlneeu8jcg.png" alt="For ranking, we aren't including title" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One last option here that I would have KILLED for when I recruited is best understood through a little backstory.&lt;/p&gt;

&lt;p&gt;When I did government recruiting it was extremely common for people to have “synonymous” credentials, or certifications or status indicators that made a HUGE difference in their hirability but were not always expressed clearly. One example is the CompTIA certification Security +, which many people working in government contracting get trained for and certified in on the job through a Department of Defense directive (8750, specifically). Some of these people are so neck-deep in their world that they do &lt;em&gt;not&lt;/em&gt; optimize their resume for search, so you might only find them list the directive that required their certification. Algolia has the option to create a list of synonym keywords that could have saved me from long arduous searches like &lt;code&gt;security AND (engineer OR specialist OR analyst) and (8750 or "Security +" or "Security+)&lt;/code&gt; and so on and so forth. The synonym option is super easy to use, pictured below: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fja7sho7tck0rrzhdbp0o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fja7sho7tck0rrzhdbp0o.png" alt="Algolia allows you to set special synonyms" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A mini candidate search prototype
&lt;/h3&gt;

&lt;p&gt;To apply some of these cool options, I went through building a simple approximation of a candidate search page on that sparse skeleton of a Vue app I linked earlier. Feel free to skip this, but I hacked together a small amount of CSS to make this look reasonable, in the &lt;code&gt;&amp;lt;style&amp;gt;&amp;lt;/style&amp;gt;&lt;/code&gt; tags of our &lt;code&gt;App.vue&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.vue&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
button.ais-SearchBox-submit,
button.ais-SearchBox-reset &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

input &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

html &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;edeff5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

h3 &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;c4fe0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;letter&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;:.&lt;/span&gt;&lt;span class="mi"&gt;04&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

h5 &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Helvetica&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sans&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;letter&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;:.&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;a5e9a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

span#header &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;justify&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;space&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;between&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

span#header img &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

div.searchResults &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.ais-SearchBox-input &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* background-color: white; */&lt;/span&gt;
  &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.ais-InstantSearch &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.ais-Hits &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.ais-Hits-item p&lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.25&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="si"&gt;}&lt;/span&gt;

.ais-SearchBox-form &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the &lt;code&gt;&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&lt;/code&gt; section of our &lt;code&gt;public/index.html&lt;/code&gt;, linked this minimal CSS framework I like, Wing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/wingcss"&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding Algolia’s UI elements
&lt;/h3&gt;

&lt;p&gt;I wish I could make my effort on this part sound more interesting, but truly the options here made connecting this minimal UI to Algolia relatively effortless. For search, Algolia offers a number of UI libraries including one for Vue. You can check out some of the others &lt;a href="https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/vue/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🛑 ✋ &lt;strong&gt;A quick note:&lt;/strong&gt; We’re about to stick our Algolia API key in a &lt;code&gt;.env&lt;/code&gt; file. That’s completely alright if you’re confident that you haven’t given this particular API key any dangerous permissions. &lt;a href="https://www.algolia.com/doc/guides/security/api-keys/#rights-and-restrictions" rel="noopener noreferrer"&gt;It’s a good thing to check before we start&lt;/a&gt;, if you haven’t already.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With that said, to get these values, head to the main dashboard menu tab for &lt;code&gt;API Keys&lt;/code&gt;. Here, we’ll want to grab our application ID and search-only API key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2zdx8ibgdk2jjurp5y2n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2zdx8ibgdk2jjurp5y2n.png" alt="Grab our API key" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Heading back to the terminal, we’re going to run the following commands to install our needed Algolia packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="nx"&gt;algoliasearch&lt;/span&gt; &lt;span class="nx"&gt;vue&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;instantsearch&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then are going to bind that to our Vue instance, over in &lt;code&gt;main.js&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Vue&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;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&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;./App.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./registerServiceWorker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;InstantSearch&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;vue-instantsearch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// new import&lt;/span&gt;

&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;InstantSearch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// now bound to Vue&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&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="nf"&gt;$mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s introduce some changes to  &lt;code&gt;App.vue&lt;/code&gt; to accomplish a few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We are going to use are markdown section to use pre-made search widgets available through this library which are &lt;em&gt;super&lt;/em&gt; convenient&lt;/li&gt;
&lt;li&gt;We’re going to use the JavaScript logic to connect to our previously uploaded data and supply our records&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, let’s update the &lt;code&gt;&amp;lt;template&amp;gt;&amp;lt;/template&amp;gt;&lt;/code&gt; section of &lt;code&gt;App.vue&lt;/code&gt; to now include the search and display widget Algolia has handy for Vue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.vue &lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;center&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Turbocharged searches with Algolia&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;center&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ais&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;instant-search&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;search-client&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"searchClient"&lt;/span&gt; &lt;span class="na"&gt;index-name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"candidates"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ais&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;search-box&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"searchInput"&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;   
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ais&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt; &lt;span class="na"&gt;v-slot&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"{ items }"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; 
            &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"item.objectID"&lt;/span&gt;
            &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"searchResults"&lt;/span&gt; 
            &lt;span class="na"&gt;v-for&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"item in items"&lt;/span&gt; 
            &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"item.objectID"&lt;/span&gt;
          &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h5&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h5&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;  
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resume&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ais&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ais&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;instant-search&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, in the &lt;code&gt;&amp;lt;script&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt; section, let’s add the connection to our Algolia index.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
import algoliasearch from 'algoliasearch/lite';

export default &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;searchClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;algoliasearch&lt;/span&gt;&lt;span class="p"&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;VUE_APP_ALGOLIA_APPLICATION_ID&lt;/span&gt;&lt;span class="p"&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;VUE_APP_ALGOLIA_SEARCH_API_KEY&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="si"&gt;}&lt;/span&gt;;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then finally, back in the terminal, if you kick off &lt;code&gt;npm run serve&lt;/code&gt; and head to the browser, you should now get a simple search UI like seen below, tying all these pieces together:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdzmyjnap3djigeemgxy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdzmyjnap3djigeemgxy.png" alt="UI up and running" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can confirm the search and filtering capabilities are doing their thing by entering some criteria, you can see how mine changed when I typed “frontend”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9rtvnkgcs3ts6b24yhn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9rtvnkgcs3ts6b24yhn.png" alt="search in action" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that’s it! With truly, a few simple steps and maybe less than twenty minutes work, we have made a prototype which — simple as it looks — is leveraging the search configuration options we selected earlier &lt;em&gt;and&lt;/em&gt; the underlying artificial intelligence that comes baked in to the Algolia search product.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus: add event insights!
&lt;/h3&gt;

&lt;p&gt;If I imagine myself using this tool for this purpose, I realize that there also might be a scientific way to analyze the &lt;em&gt;usage&lt;/em&gt; of my fictitious candidate search engine. For that to work, we might want some kind of tracking related to what candidates a recruiter drills down into for further review, or many candidate search applications will also let you “favorite” candidates.&lt;/p&gt;

&lt;p&gt;To approximate that behavior, I decided to also make my search work with Algolia event insights. This area of functionality lets you track numerous events, be it clicks or favorites, that could further improve relevance of the search results shown to users. For more background on how to get started with events and Algolia, you can find that &lt;a href="https://www.algolia.com/doc/guides/sending-events/getting-started/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To start, we are going to make some updates in &lt;code&gt;App.vue&lt;/code&gt; which do a few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;import the event/insight library from Algolia&lt;/li&gt;
&lt;li&gt;connect the API client to our API credentials, so events will be sent back to the correct data respository, the one housing our candidate records&lt;/li&gt;
&lt;li&gt;attaches the insight client to our search widget from a previous step&lt;/li&gt;
&lt;li&gt;create simple logic to display icons, where clicking an icon “favorites” a candidate, and kicks off an event being sent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The revised sections of &lt;code&gt;App.vue&lt;/code&gt; are as seen below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.vue &lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;center&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Turbocharged searches with Algolia&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;center&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;!--&lt;/span&gt; &lt;span class="na"&gt;new&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;middlewares&lt;/span&gt; &lt;span class="na"&gt;argument&lt;/span&gt; &lt;span class="na"&gt;connects&lt;/span&gt; &lt;span class="na"&gt;the&lt;/span&gt; &lt;span class="na"&gt;insight&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt; &lt;span class="na"&gt;our&lt;/span&gt; &lt;span class="na"&gt;search&lt;/span&gt; &lt;span class="na"&gt;widget&lt;/span&gt; &lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ais&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;instant-search&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;search-client&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"searchClient"&lt;/span&gt; &lt;span class="na"&gt;index-name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"candidates"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"middlewares"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ais&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;search-box&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"searchInput"&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;   
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ais&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt; &lt;span class="na"&gt;v-slot&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"{ items, sendEvent }"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; 
            &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"item.objectID"&lt;/span&gt;
            &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"searchResults"&lt;/span&gt; 
            &lt;span class="na"&gt;v-for&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"item in items"&lt;/span&gt; 
            &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"item.objectID"&lt;/span&gt;
            &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"sendEvent('click', item, 'Item Starred')"&lt;/span&gt;
          &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h5&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h5&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; 
                &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"`img-${item.objectID}`"&lt;/span&gt; 
                &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://i.imgur.com/5Je2dmA.png"&lt;/span&gt; 
                &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"favorite(`img-${item.objectID}`)"&lt;/span&gt; 
                &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"thumbs up"&lt;/span&gt;
              &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;  
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resume&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ais&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ais&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;instant-search&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
import algoliasearch from 'algoliasearch/lite';
// new imports contain what we need to support sending events
import &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createInsightsMiddleware&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt; from 'instantsearch.js/es/middlewares';
import aa from 'search-insights';

// reconnecting to the API, so our events/insights go to the right place
aa('init', &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;appId&lt;/span&gt;&lt;span class="p"&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;VUE_APP_ALGOLIA_APPLICATION_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="p"&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;VUE_APP_ALGOLIA_SEARCH_API_KEY&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;);

// fictitious user token lets our "favorites" be tracked to me
aa('setUserToken', '32f32sfds94s032dfjskal')

const insightsMiddleware = createInsightsMiddleware(&lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;insightsClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;aa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;);

export default &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;searchClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;algoliasearch&lt;/span&gt;&lt;span class="p"&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;VUE_APP_ALGOLIA_APPLICATION_ID&lt;/span&gt;&lt;span class="p"&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;VUE_APP_ALGOLIA_SEARCH_API_KEY&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;insightsMiddleware&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="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;favorite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;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;// simple logic flips the icon, for a visual indicator of "favorited" candidates&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;icon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://i.imgur.com/j635pgy.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="si"&gt;}&lt;/span&gt;
};
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we return to our browser now, we see the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faritmydkmg837gs1ra54.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faritmydkmg837gs1ra54.png" alt="We have icons!" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we were to simulate doing a real search, and “favoriting” some results, we’d see hearts on our selected candidates (instead of the thumbs-up icon).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fek7j3p6oxmixwk96b7wb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fek7j3p6oxmixwk96b7wb.png" alt="We see the icon change and know our favoriting logic worked" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if we return to our Algolia dashboard (the URL is &lt;code&gt;https://www.algolia.com/apps/&amp;lt;your application id&amp;gt;/events/debugger&lt;/code&gt;) we can now see events being sent back! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uaav79nbcbcz9jfdyjt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uaav79nbcbcz9jfdyjt.png" alt="Events being sent back" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  In closing
&lt;/h3&gt;

&lt;p&gt;Honestly, between learning how to use web scrapers and now the knowledge of how easy it is to set up a robust, customizable search UI with Algolia, maybe some parallel-universe version of me is still in recruiting and specializes in building in-house candidate search tools. But the truth is, even out of the tiny niche of recruiting, I can think of limitless applications for search tools this convenient that come AI-powered by default. Thanks for making it this far, and I’d love to hear your ideas for applications of Algolia in the comments! 🤓&lt;/p&gt;

</description>
      <category>vue</category>
      <category>ai</category>
      <category>algolia</category>
    </item>
    <item>
      <title>The emotional gauntlet of learning to code</title>
      <dc:creator>JTK</dc:creator>
      <pubDate>Thu, 21 Jul 2022 22:30:51 +0000</pubDate>
      <link>https://dev.to/heyjtk/the-emotional-gauntlet-of-learning-to-code-k76</link>
      <guid>https://dev.to/heyjtk/the-emotional-gauntlet-of-learning-to-code-k76</guid>
      <description>&lt;p&gt;In a recent post I wrote about my long journey getting into programming, it made me remember some funny moments from the most intense period of my programming education which took place Spring/Summer 2016. &lt;/p&gt;

&lt;p&gt;I attended a coding bootcamp, and to say that it was a challenge would be an understatement. There was so much going on. I had just moved states, recently lost my dad, and kept getting really bad headaches (whoops, I needed glasses! Go figure). &lt;/p&gt;

&lt;p&gt;The specific memory that sticks out is, my anxiety during this period was through the roof. I didn't have a particularly fluid transition to coding, I wasn't great at it. To attempt to deal with my nerves/stress I remember trying at various points to meditate. Ultimately, if I could clear my mind at all I would immediately wind up stress-napping. What a mood, as they say. &lt;/p&gt;

&lt;p&gt;"Stress napping" I think is a response perfectly indicative of all the chaos involved with learning to code: it is mentally exhausting, emotionally bruising, and in my case an ego-shredding experience. So today I want to unpack a little bit of why that is, how it manifests, and most importantly some things I would recommend to help with it. (Help, not solve - ultimately this is a hard thing to do and in some ways there is no path but experiencing the difficulty). &lt;/p&gt;

&lt;h2&gt;
  
  
  What makes learning to code so grueling
&lt;/h2&gt;

&lt;p&gt;If I had to distil the difficulty of learning to code into main areas or themes, I'd probably organize them as follows: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mentally challenging&lt;/strong&gt;: I had always been a good student. Not just in one thing, across the board. A-B student, quick learner, and in some cases didn't need to try particularly hard to do well. Coding changed all of that. I could not let my focus drift a single bit. Applying every bit of determination and attention I could muster, still things were going over my head entirely. Things that looked "simple" as other people did them immediately became mystifying hieroglyphics the moment I was on my own. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distractions and conflicting information&lt;/strong&gt;: Learning to code alone is tough. Learning to code while learning Github while learning about IDEs while learning about the &lt;code&gt;inspect&lt;/code&gt; browser options while learning about Trello while also being a new Mac user was BANANAS. &lt;/p&gt;

&lt;p&gt;This gets arguably worse at the point when you have a working knowledge of what I listed above and think "ok now to get a job". &lt;/p&gt;

&lt;p&gt;One person tells you to focus on open source contributions on Github, which you still don't know well. One person tells you to focus on algorithms and data structures, which are bafflingly abstract. Another tells you to build a portfolio. Another tells you to do FreeCodeCamp or Codeacademy or Code Wars. Another tells you to practice Hackerrank. Someone recommends Eloquent JavaScript, someone else recommends a Youtuber, someone else recommends Cracking the Coding Interview. You are drowning in material. &lt;/p&gt;

&lt;p&gt;To be clear, none of these things will HURT you if you are able to work on them and make progress and through that progress gain experience and practice. These things &lt;em&gt;may&lt;/em&gt; hurt or hinder you if they are so overwhelming that you don't know what to do, or if you nervously rotate among them and are context switching so much that you aren't getting traction or practice with code. (More on that and approaches to manage it later). I don't know if this is a real term but I would like to coin it if not: &lt;strong&gt;panic-cycling&lt;/strong&gt;. I see a lot of new programmers panic-cycling through approaches and due to the churn, feeling stalled. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exhausting hits to self esteem&lt;/strong&gt;: Neither of the two previous points are particularly helpful to feeling good about yourself. People have told you five million different things you are supposed to do to become employed, and doing any of them feels like a herculean feat. The interview process is also bruising. If you are in dev communities, you may start to pick up on that developers can be dismissive and rude about beginners, Stack Overflow answers are downright hostile sometimes. Trying to use Stack Overflow literally the messaging you receive is often "This question is too dumb to ask" in the form of "this was asked elsewhere" or "this question doesn't meet our criteria". (More on this later too). &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weird industry cliqueyness&lt;/strong&gt;: In the background of all these other things, as you start coding you start to pick up on the social strata, which might seem bizarre to an outsider. Why is frontend or PHP perceived as less prestigious? Is this thing I'm about to learn "dead"!? (People loooove declaring various technologies "Dead!", its bizarre honestly). So although you are in a poor position to do so, most new coders I know feel immense pressure to pick the correct "path" before they realistically know what it should be, an added worry on everything else.&lt;/p&gt;

&lt;p&gt;Phew. I was exhausted just WRITING this list, just REMEMBERING these feelings even though they were six years ago! &lt;/p&gt;

&lt;h2&gt;
  
  
  How these stressors manifest
&lt;/h2&gt;

&lt;p&gt;Something I find funny that writing this post made me think of is related to travel, something I love. I started traveling solo when I was 17 and have been to sixteen other countries total. Would it surprise you to know, travel is so tiring that on almost every trip I take I have a moment in the first 24 hours where I think "this trip was a mistake". Whether it is a malfunctioning GPS in Iceland, getting stuck in a bathroom in France (door broke!), there is always some logistical mishap that makes me doubt all my life choices. &lt;/p&gt;

&lt;p&gt;Invariably, after my "freak out moment" I get a good night's sleep. Wake up the next day. And am a new person. I start to feel the vibe of the city, and stop feeling self conscious about my language barrier and start enjoying myself and just taking it all in. Even knowing this will happen to me, it happens every single time without fail. &lt;/p&gt;

&lt;p&gt;What does this have in common with learning to code? &lt;strong&gt;Exhaustion&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Ways that stress and exhaustion manifest learning to code: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Panic-cycling&lt;/strong&gt;: (talked about this a bit already). I'm no doctor but whenever I think of panic cycling that new devs do, I can't help but also think of &lt;a href="https://www.ama-assn.org/delivering-care/public-health/what-doctors-wish-patients-knew-about-decision-fatigue" rel="noopener noreferrer"&gt;decision fatigue&lt;/a&gt;. New devs feel pressured to make so many decisions that I think their thinking gets frenzied and they wind up trying to do it all and even more exhausted by context switching in a nasty cycle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Emotionally charged relationship with coding&lt;/strong&gt;: There was one person in my bootcamp who I will never forget who really struggled with this. In talking through debugging, you could hear the person's voice get noticeably emotional with frustration as they felt like they were trying everything and nothing was working. Debugging conversations would turn into frustration conversations, and it was obvious that the person would not be able to productively continue until they calmed down&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fatigue errors&lt;/strong&gt;: It has been &lt;a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1739867/" rel="noopener noreferrer"&gt;studied&lt;/a&gt; that being sleep deprived can have an impairment effect comparable to being actually drunk. For me, this is absolutely true. I get physically clumsy when sleep deprived very noticeably. I also miss things. Tired junior coders are very prone to making errors in my experience &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thought distortions&lt;/strong&gt;: If you haven't heard this term, a &lt;a href="https://www.healthline.com/health/cognitive-distortions" rel="noopener noreferrer"&gt;thought distortion&lt;/a&gt; is what happens when a logical thought becomes emotionally charged and then spirals. Learning to code, it is the difference between &lt;code&gt;I'm struggling with JavaScript&lt;/code&gt; and &lt;code&gt;I'm not cut out for this&lt;/code&gt;. One of those things is a logical thought. One of them is a projection spiral based on that thought. Other common ones in this vein: &lt;code&gt;I don't have what it takes&lt;/code&gt;, &lt;code&gt;I'll never be able to do this&lt;/code&gt;, &lt;code&gt;I'm not smart enough for this&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Procrastination/avoidance&lt;/strong&gt;: When I first learned to code, like many people out there, I initially assumed backend was out of reach for me. I thought my artistic skill could carry me through on frontend if I could pad my work with design related activities. I avoided exploring my options or trying to fairly evaluate my interests because I was operating from a place of fear and doubt. Which leads me to the next point --&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limiting beliefs&lt;/strong&gt;: These show up in a lot of ways. Delaying the job hunt because you think you aren't ready and no one will hire you. Blanket judgment of certain topics as "hard" and beyond you. Heck, in my bootcamp there was someone in the same area who wanted us to be friends. I initially avoided her because she was too good a coder and made me feel bad about myself. (Happy ending, I joke that she "bullied" me into us being friends, and here we are six years later good pals. She is a CTO!) &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  So what actually helps?
&lt;/h2&gt;

&lt;p&gt;So first of all, I discussed the fatigue thing. I will say one thing I did differently than the people in my program was, I never stayed up even close to 3am working on projects (some peers did!). I'm a person that needs my sleep, and I was self-aware enough to immediately see that coding tired just made me break my code even worse. Draw from that what you will. For me, I just &lt;em&gt;couldn't&lt;/em&gt;. I was getting killer headaches (needed glasses, lol) and was just very quickly like, no. I'm not going to do it. I'm not going to stay up all night. &lt;/p&gt;

&lt;p&gt;Second, I will address the context switching thing. Would it surprise you to know that I have never meaningfully learned code from a specific book or video series? I don't like videos and for whatever reason never got into O'Reilly books or anything else either. I've never done open source. I've done Hackerrank maybe 3-4 times ever for interviews. I don't have a presence answering questions on Stack Overflow. I didn't meaningfully network early in my dev career. I didn't bother trying to learn algorithms meaningfully until I was a couple years in. &lt;strong&gt;So take a deep breath&lt;/strong&gt;. This knowledge isn't going anywhere. If at some point you are unhappy with your learning materials, you always have room to change them. &lt;/p&gt;

&lt;p&gt;"Changing them" is different than panic-cycling or feeling like you HAVE to do them all, immediately, right away. When evaluating switching resources (let's assume you are in a program to learn to code or have a specific goal that means you have some basic learning resources as core materials).&lt;/p&gt;

&lt;p&gt;In picking your materials and practices, learning to code is a lot like developing a fitness regimen: what method is the best? &lt;strong&gt;Generally the one you are willing to keep doing on a daily basis&lt;/strong&gt;. Pick something you can deal with. Focus on being consistent. Focus on showing up. &lt;/p&gt;

&lt;p&gt;I also am a huge proponent of &lt;strong&gt;arguing with your limiting beliefs and thought distortions&lt;/strong&gt;. As I left bootcamp and prepared to get a coding job, I would often talk out loud to myself in the car preparing answers to imagined interview questions. Maybe since I was already talking to myself aloud more than normal, I started &lt;em&gt;also&lt;/em&gt; talking out loud against my negative thoughts:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Negative thought: You aren't cut out for this&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Me: Hey wait a minute, you just started! This isn't magic, people are learning this all around you. Why NOT you?&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Negative thought: You're not going to get this job&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Me: Fine, but I'm going to apply anyway. I have the interest, so if someone is going to say no its going to be them, not me.&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Negative thought: You can't hack it as a real dev, better be sure your portfolio at least looks pretty since that's all you are good for&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Me: Maybe I will, but maybe I'll try to learn some backend too. Maybe it isn't for me but it won't hurt to try to become more well rounded&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Negative thought: Everyone else is understanding this material faster than you&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Me: So what, I am enjoying what I'm learning and I can't stay bad at this forever. Who cares about everyone else&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Maybe it sounds kind of hokey, but as I told my therapist about how I interrupt my thoughts she pointed out that I'm essentially doing cognitive behavior therapy within my inner dialogue. Hokey or not, it helped! It helped with the rejection, the negative thoughts, and the hits to my self-esteem. &lt;/p&gt;

&lt;p&gt;I would love to give you a recommendation to deal with the last point I outlined, &lt;code&gt;cliqueyness&lt;/code&gt;, but for that one all I can tell you is that there are not some special social rules that mean the behavior is OK in tech where elsewhere in life we recognize that it's toxic. Cliqueyness is toxic everywhere. Early in, I realized I was never going to spend time in spaces with that vibe and I've been happier for it. Outside of occasional forays onto stack overflow, I rarely tangle with that side of the tech world. &lt;/p&gt;

&lt;h2&gt;
  
  
  In closing
&lt;/h2&gt;

&lt;p&gt;I wanted to write this to say, I truly get it: there are a confluence of factors that make it truly a marathon of emotional regulation to learn to code, on top of all the hard learning and the non-emotional challenges! &lt;/p&gt;

&lt;p&gt;I told you already, I was NOT a fluid coder. I felt like the ugly duckling of code for a good year or more. The one thing I did have going for me though were techniques to regulate my emotions and discipline my disappointments enough to continue on. &lt;/p&gt;

&lt;p&gt;I was telling someone the other day that I feel like my first year of coding was more challenging than all the other years combined and god if that isn't the truth. I never wanted to forget that feeling and it has made me passionate about mentoring and being part of a community that could make newer developers feel more supported than I did. Thanks for reading, and if you have any of your own tricks for staying grounded while learning to code, drop them in the comments! &lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>career</category>
      <category>mentalhealth</category>
    </item>
    <item>
      <title>Diving into ETL and CQRS — developing a secret message encoder with Serialized</title>
      <dc:creator>JTK</dc:creator>
      <pubDate>Mon, 04 Apr 2022 22:14:01 +0000</pubDate>
      <link>https://dev.to/heyjtk/diving-into-etl-and-cqrs-developing-a-secret-message-encoder-with-serialized-2655</link>
      <guid>https://dev.to/heyjtk/diving-into-etl-and-cqrs-developing-a-secret-message-encoder-with-serialized-2655</guid>
      <description>&lt;p&gt;Today we are going to embark on Part I of building a “secret” message board. In the course of creating this app — which is built just for fun — we are going to touch on the concepts of &lt;a href="https://www.ibm.com/cloud/learn/etl" rel="noopener noreferrer"&gt;ETL systems&lt;/a&gt;, &lt;a href="https://docs.microsoft.com/en-us/azure/architecture/patterns/cqrs" rel="noopener noreferrer"&gt;CQRS&lt;/a&gt;, and also explore &lt;a href="https://acloudguru.com/blog/engineering/what-is-go-an-intro-to-googles-go-programming-language-aka-golang" rel="noopener noreferrer"&gt;Golang&lt;/a&gt;, to which I am still a newcomer! With that said, let’s start with some background on those topics and get to coding later.&lt;/p&gt;

&lt;h2&gt;
  
  
  ETL (or Extract-Transform-Load)
&lt;/h2&gt;

&lt;p&gt;One of my favorite jobs I ever had was working on an ETL system. Before that point I had heard the term thrown around a lot, but the concept never stuck in my brain past “shuffling data around” — and to be honest, that is the gist! &lt;/p&gt;

&lt;p&gt;If it helps contextualize the use case where ETL systems are relevant, I’ll give you the tl;dr for project that ran one where I was Dev Lead. The company was paying something like $1,000,000 per year for some expensive software, so we were building out a replacement for it. But until my project was completely functional, we piped data from the old system into it and slowly migrated users over. The need to keep our new in-house learning software in lock step with the third-party system was the reason we needed to &lt;strong&gt;extract&lt;/strong&gt;, &lt;strong&gt;transform&lt;/strong&gt;, and &lt;strong&gt;load&lt;/strong&gt; data. Every minute, hour, or day various ETL jobs were running to capture the data, put it into the format our systems wanted, and then let it work seamlessly in our app. &lt;/p&gt;

&lt;p&gt;Today’s example is going to start off with a rough idea of these concepts to begin with, and then in later posts we will be exploring ETL functionality further.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One interesting note:&lt;/strong&gt; As you can imagine, people have all kinds of data transformation needs! That is why there are ETL variants like &lt;a href="https://rivery.io/blog/etl-vs-elt/" rel="noopener noreferrer"&gt;ELT&lt;/a&gt; (extract, load, transfer) and &lt;a href="https://www.integrate.io/blog/what-is-etlt/" rel="noopener noreferrer"&gt;ETLT&lt;/a&gt; (extract, transform, load, transform). In this article, we are going to focus on ETL, but we can look at some other data pipeline processes later.&lt;/p&gt;

&lt;h2&gt;
  
  
  CQRS (or Command and Query Responsibility Segregation)
&lt;/h2&gt;

&lt;p&gt;For anyone who has worked with a heftier traditional relational database, eventually you run into problems related to the fact that not all data is of the same nature. Some data is requested millions of times in a fraction of a second but rarely changed. Other data is write-heavy, frequently needing to be accessed and altered. As a result, usage patterns across tables can vary hugely, both in the number, and type of requests your database must handle.&lt;/p&gt;

&lt;p&gt;💡 Managing those different usage patterns in a database with a single set of tools and rules is a big ask.&lt;/p&gt;

&lt;p&gt;However, command and query responsibility segregation (CQRS from now on to save me some typing) says, &lt;strong&gt;“These are different animals! Let’s let an eagle be an eagle and a cheetah be a cheetah”.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;In that spirit, I’ll be using an excellent tool in this post called &lt;a href="https://app.serialized.io/" rel="noopener noreferrer"&gt;Serialized&lt;/a&gt;, which offers a comprehensive data management approach to both event driven data and CQRS. You can read more about them &lt;a href="https://serialized.io/blog" rel="noopener noreferrer"&gt;here&lt;/a&gt;, or very easily get &lt;a href="https://app.serialized.io/auth/signup" rel="noopener noreferrer"&gt;set up&lt;/a&gt; as a developer on their very handy free tier to play with all the cool functionality available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting set up with Go
&lt;/h2&gt;

&lt;p&gt;Last but not least, this will be my maiden voyage with &lt;a href="https://go.dev/" rel="noopener noreferrer"&gt;Golang&lt;/a&gt;, or Go! Go was developed at Google 10+ years ago and has exploded in popularity due to its performance, concurrency model, and keen developer interest. I had vowed that next time I got to build an ETL system I would do so in Go, so today it’s on! If you are set up with Go already, feel free to skip ahead to the next subheading, but I’m going to first get all the gears turning on my machine.&lt;/p&gt;

&lt;p&gt;Not being entirely sure this Mac was even set up with Go, I started with the basics before embarking on this voyage (for non-Mac users, various Go install options can be found &lt;a href="https://go.dev/doc/install" rel="noopener noreferrer"&gt;here&lt;/a&gt; if you want to follow along, and package manager aside most of these instructions should be fine for *nix users).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;go 
&lt;span class="nb"&gt;mkdir &lt;/span&gt;go_serialized &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;go_serialized
&lt;span class="nb"&gt;touch &lt;/span&gt;main.go 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my main.go file, I added a simple test just to get myself running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;package main 

import &lt;span class="s2"&gt;"fmt"&lt;/span&gt;

func main&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    fmt.Println&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Running!"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then I confirmed my Go setup was at least taken care of before moving on&lt;a href="http://Serialized.io" rel="noopener noreferrer"&gt;.&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜  go_serialized go build main.go
➜  go_serialized ./main
Running!
➜  go_serialized
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Getting set up with Serialized
&lt;/h2&gt;

&lt;p&gt;The sign up for a Serialized account is &lt;a href="https://app.serialized.io/auth/signup" rel="noopener noreferrer"&gt;here&lt;/a&gt;, and I’ll tell you two things I liked about the signup/auth process already. I used their authenticate-by-Google option (one less password to remember). Later on as I began looking for what URL I’d need to feed this app I noticed another nice touch, which is that account differentiation for Serialized is apparently done all by secrets/payload. No special URL to remember. &lt;/p&gt;

&lt;p&gt;If you’re new, go through the standard sign-up though. Make an account and a project if you are following along — for clarity my serialized project name is “go_serialized”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5b0p5xe6htpu31rnlptn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5b0p5xe6htpu31rnlptn.png" alt="Serialized login screen" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqaujkycyoka5uq9swen4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqaujkycyoka5uq9swen4.png" alt="Serialized create project pane" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And with that, we’re off! &lt;/p&gt;

&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;What we are going to eventually build is going to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Extract&lt;/strong&gt; a message from a local file&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transform&lt;/strong&gt; the message by encoding it with a passphrase&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load&lt;/strong&gt; it into &lt;a href="http://serialized.io" rel="noopener noreferrer"&gt;Serialized&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Query it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Being a Go newcomer and this being more of a proof-of-concept, I organized this project pretty simply. On completion, our structure will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;├── api
│   └── api.go
├── etl
│   └── etl.go
├── go.mod
├── go.sum
├── inputs
│   └── message_one.json
├── main
├── main.go
└── utils
    └── errors.go
    └── passphrase.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you may expect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The API code will wrap our network calls.&lt;/li&gt;
&lt;li&gt;The ETL module load and transform our data.&lt;/li&gt;
&lt;li&gt;The utils module contains logic to generate our passphrase and to give some generic error handling throughout our app.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;main.go&lt;/code&gt; in the root directory ties all of our logic together.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Keeping secrets secret
&lt;/h2&gt;

&lt;p&gt;Before we get too far, I’ll let you know that if you want to follow along you can head to this &lt;a href="https://github.com/jtkaufman737/go_serialized" rel="noopener noreferrer"&gt;repo&lt;/a&gt; and pull down from the &lt;code&gt;main&lt;/code&gt; branch to get our empty boilerplate structure. (A separate branch called &lt;code&gt;walkthrough&lt;/code&gt; will create our commit by commit progress and ultimately have the final project, so I’m going to switch branches).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; walkthrough

Switched to a new branch &lt;span class="s1"&gt;'walkthrough'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing we will want to do is build out the directories we mentioned earlier, and create an environment file. This will be where we store our credentials for Serialized.&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="nb"&gt;touch&lt;/span&gt; .env
&lt;span class="nb"&gt;mkdir &lt;/span&gt;api etl inputs utils
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;

&lt;span class="nb"&gt;.&lt;/span&gt;         ..        .env      .git      README.md api       etl       inputs    utils

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

&lt;/div&gt;



&lt;p&gt;We don’t want our &lt;code&gt;.env&lt;/code&gt; file to make it up anywhere public, because it will contain secrets soon. So let's quickly add a &lt;code&gt;.gitignore&lt;/code&gt; file and tell it to ignore &lt;code&gt;.env&lt;/code&gt; before anything else. We can then verify this worked with the &lt;code&gt;cat&lt;/code&gt; command, which should just return the contents of that file.&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="nb"&gt;touch&lt;/span&gt; .gitignore
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;".env"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitignore
&lt;span class="nb"&gt;cat&lt;/span&gt; .gitignore

.env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s commit our &lt;code&gt;.gitignore&lt;/code&gt; and &lt;code&gt;[README.md](http://README.md)&lt;/code&gt; before we move on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Create README, gitignore"&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;walkthrough aa1f032] Create README, gitignore
 2 files changed, 4 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;, 1 deletion&lt;span class="o"&gt;(&lt;/span&gt;-&lt;span class="o"&gt;)&lt;/span&gt;
 create mode 100644 .gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s navigate to &lt;a href="http://serialized.io" rel="noopener noreferrer"&gt;serialized.io&lt;/a&gt; and get both our access key and secret access key (my info blanked out for security). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flmi09lyg7yxxq5g9iqwo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flmi09lyg7yxxq5g9iqwo.png" alt="Serialized dashboard view of api credentials" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add to your &lt;code&gt;.env&lt;/code&gt; file the values we retrieved here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// .env

&lt;span class="nv"&gt;ACCESS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xxxxxxxx
&lt;span class="nv"&gt;SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xxxxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Awesome! Now we are set up to authenticate with Serialized.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jumping in with Go
&lt;/h2&gt;

&lt;p&gt;As we mentioned in the directory structure section, the core elements of this app are: the ETL, the API, and the main module tying it together. To begin a Go project, we’re going to run an initialization step for the project, and then re-run our &lt;code&gt;main.go&lt;/code&gt; from a previous step to confirm we are set up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
go mod init github.com/jtkaufman737/go_serialized
go: creating new go.mod: module github.com/jtkaufman737/go_serialized
go: to add module requirements and sums:
    go mod tidy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;main.go&lt;/code&gt; can just be a simple print test for now, since we’re just making sure it’s running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// main.go 
package main 

import &lt;span class="s2"&gt;"fmt"&lt;/span&gt;

func main&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    fmt.Println&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Running!"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running it once more before we begin, we see we are all set.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go
Running!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There’s one additional thing I recommend that made this project really nice to work on. For VS Code users, you may have already been or soon will be prompted to install a standard set of Go plugins for the editor. They included some really nice tooltips that helped me debug quite a bit as someone new to Go, but the nicest feature was that on save it will auto-import necessary packages for you and also automatically remove imports you aren’t using. I found this very handy, so if you have the opportunity, I say add the plugins. &lt;/p&gt;

&lt;h2&gt;
  
  
  Error Handling
&lt;/h2&gt;

&lt;p&gt;The first thing I’m going to do on this project is actually not at all exciting, but is more of a quality-of-life thing. You know I’m talking about error-handling. As I read through various Go tutorials, I kept seeing the following pattern repeated over and over:&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="k"&gt;*&lt;/span&gt; 
doing stuff &lt;span class="k"&gt;in &lt;/span&gt;go having a great &lt;span class="nb"&gt;time&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt;/ 
&lt;span class="k"&gt;if &lt;/span&gt;err &lt;span class="o"&gt;!=&lt;/span&gt; nil &lt;span class="o"&gt;{&lt;/span&gt;
  fmt.Print&lt;span class="o"&gt;(&lt;/span&gt;err.Error&lt;span class="o"&gt;())&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’m new, so maybe I’ll hear that people like repeating themselves that way for some reason, but it annoyed me to have those three lines of code some 20x repeated in this project by the end. For this reason my first order of business was creating a little utility function to deal with this and at least cut our three repeated lines of code down to one. Go ahead and make a &lt;code&gt;utils/errors.go&lt;/code&gt; file and we’ll add the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// utils/errors.go

package utils

import &lt;span class="s2"&gt;"fmt"&lt;/span&gt;

// LogErrors takes variadic, or multiple arguments &lt;span class="k"&gt;for &lt;/span&gt;errors and formats/prints them
func LogErrors&lt;span class="o"&gt;(&lt;/span&gt;errors ...error&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    // will check &lt;span class="k"&gt;if &lt;/span&gt;we ever receive no arguments
    &lt;span class="k"&gt;if &lt;/span&gt;len&lt;span class="o"&gt;(&lt;/span&gt;errors&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; 0 &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;_, err :&lt;span class="o"&gt;=&lt;/span&gt; range errors &lt;span class="o"&gt;{&lt;/span&gt;
        // &lt;span class="k"&gt;if &lt;/span&gt;we receive an argument list, &lt;span class="k"&gt;for &lt;/span&gt;each that is not nil &lt;span class="o"&gt;(&lt;/span&gt;falsey&lt;span class="o"&gt;)&lt;/span&gt; we will 
        // format and print them
        &lt;span class="k"&gt;if &lt;/span&gt;err &lt;span class="o"&gt;!=&lt;/span&gt; nil &lt;span class="o"&gt;{&lt;/span&gt;
            fmt.Print&lt;span class="o"&gt;(&lt;/span&gt;err.Error&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Golang newcomers, a couple of interesting tidbits here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go is one of a small number of languages I’ve worked with where &lt;code&gt;nil&lt;/code&gt; is our garden-variety falsey return value.&lt;/li&gt;
&lt;li&gt;We’ve seen a nice trick already which is that we can specify a varying number of function arguments with the use of ellipses &lt;code&gt;...&lt;/code&gt;. You can read more about that &lt;a href="https://gobyexample.com/variadic-functions" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Like some other languages, we see a package declaration up top that allows this function to be accessed in the future as part of the &lt;code&gt;utils&lt;/code&gt; package.&lt;/li&gt;
&lt;li&gt;You may also notice the naming convention as our function is uppercase. This signifies it is &lt;a href="https://stackoverflow.com/questions/20850047/public-private-upper-case-lower-case" rel="noopener noreferrer"&gt;public&lt;/a&gt; and can be imported by other files.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Information flow for our secret messages
&lt;/h2&gt;

&lt;p&gt;For the next sections, we are going to get into some cryptography utilities that Go has. I will be the first to admit to you that I borrowed the public work of others to figure out how to encrypt and decrypt messages, which we will talk about more soon. &lt;/p&gt;

&lt;p&gt;For this article though, I want to recap the application logical flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We read JSON in from a local file containing a “secret message” (extract)&lt;/li&gt;
&lt;li&gt;We will encrypt that message using a random passphrase (transform)&lt;/li&gt;
&lt;li&gt;We will then post a “new message” event to Serialized with the message, passphrase, and some metadata like an ID field. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the future, the idea for this application is that when you post a new message, the response gives you your “secret code” back. You then choose who to share it with, and only they can access the message. The message recipient, armed with the secret code, will be able to get the message back in plain text. The concept came to me as a high-tech version of passing notes in class as a kid, through the lens of ETL systems. We’re not going to fully implement it now — this article is already going to be quite long — but that’s the big picture we’re working towards.&lt;/p&gt;

&lt;p&gt;To start that process, let’s make a new file and set about reading it. Create &lt;code&gt;inputs/message_one.json&lt;/code&gt; and add to it a &lt;code&gt;body&lt;/code&gt; with some silly value. I went for &lt;code&gt;test test test&lt;/code&gt; but be creative with it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// inputs/message_one.json
&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"body"&lt;/span&gt;: &lt;span class="s2"&gt;"test test test"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  E is for Extract
&lt;/h2&gt;

&lt;p&gt;Let’s create a file called &lt;code&gt;etl/etl.go&lt;/code&gt; where our extraction logic can live.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// etl/etl.go
package etl

import &lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;"encoding/json"&lt;/span&gt;
    &lt;span class="s2"&gt;"io/ioutil"&lt;/span&gt;

    &lt;span class="s2"&gt;"github.com/jtkaufman737/go_serialized/utils"&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;

func ReadData&lt;span class="o"&gt;()&lt;/span&gt; map[string]string &lt;span class="o"&gt;{&lt;/span&gt;
    /&lt;span class="k"&gt;*&lt;/span&gt;
        going to create a default message structure
        as a map, which to me felt analgous to JSON-friendly structures
        &lt;span class="k"&gt;in &lt;/span&gt;other languages. It is similar to a JSON object or Python dict.
        In the future it might be more semantic to &lt;span class="k"&gt;do &lt;/span&gt;this
        with structs so I may revisit
    &lt;span class="k"&gt;*&lt;/span&gt;/
    message :&lt;span class="o"&gt;=&lt;/span&gt; make&lt;span class="o"&gt;(&lt;/span&gt;map[string]string&lt;span class="o"&gt;)&lt;/span&gt;

    // ioutil reads our JSON file into a variable and handles errors
    data, err :&lt;span class="o"&gt;=&lt;/span&gt; ioutil.ReadFile&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"./inputs/message_one.json"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    utils.LogErrors&lt;span class="o"&gt;(&lt;/span&gt;err&lt;span class="o"&gt;)&lt;/span&gt;

    // the json package translates this into the format we want
    json.Unmarshal&lt;span class="o"&gt;([]&lt;/span&gt;byte&lt;span class="o"&gt;(&lt;/span&gt;data&lt;span class="o"&gt;)&lt;/span&gt;, &amp;amp;message&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;message
&lt;span class="o"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you installed the VS Code plugins I mentioned earlier, you will notice that if you skipped the entire import section of the file above it will automagically generate ALL of the import statements for you, which is super nice.&lt;/p&gt;

&lt;p&gt;I’ll next add to our &lt;code&gt;main&lt;/code&gt; function in &lt;code&gt;main.go&lt;/code&gt; to test out the file reading capabilities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// main.go
package main

import &lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;"fmt"&lt;/span&gt;

    &lt;span class="s2"&gt;"github.com/jtkaufman737/go_serialized/etl"&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;

func main&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    fmt.Println&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Running!"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    // First we are going to &lt;span class="nb"&gt;read &lt;/span&gt;&lt;span class="k"&gt;in &lt;/span&gt;a JSON message
    rawMessage :&lt;span class="o"&gt;=&lt;/span&gt; etl.ReadData&lt;span class="o"&gt;()&lt;/span&gt;

    fmt.Println&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Message from filereader is:"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    fmt.Println&lt;span class="o"&gt;(&lt;/span&gt;rawMessage&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we run another &lt;code&gt;go run main.go&lt;/code&gt; we will see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go
Running!

Message from filereader is:
map[body:test &lt;span class="nb"&gt;test test&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect! We have confirmed our main function is running and capable of extracting our silly message from the JSON file.&lt;/p&gt;

&lt;h2&gt;
  
  
  T is for Transform
&lt;/h2&gt;

&lt;p&gt;Our next task, transforming our message, is actually the most interesting and complicated part of the app, at least for now. To be honest with you, I thought about trying to dig into the nitty-gritty of the encryption, but I realized that I had nothing special to contribute to warrant making an original version of it. Plus, the number one rule of encryption is “Thou shalt not roll thine own encryption”, and there’s good reason for that. I’d likely just end up creating vulnerabilities.&lt;/p&gt;

&lt;p&gt;I should note that Serialized, the platform we’ll be using to store this information in the Load step, actually has some neat options for &lt;strong&gt;real&lt;/strong&gt; encrypted data (unlike our pet project here, where we aren’t too worried about security). You can read more about the options available for encrypted data on Serialized by checking out &lt;a href="https://serialized.io/docs/advanced/event-encryption/" rel="noopener noreferrer"&gt;Serialized’s docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;During this step, we will also add a utility to generate a random password to use as encryption salt. This will be what lets the message recipient eventually retrieve and decode the message. Since that part is simpler, let’s start there. Create a &lt;code&gt;utils/passphrase.go&lt;/code&gt; file and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// utils/passphrase.go 
package utils

import &lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;"math/rand"&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;

var letters &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;rune&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"abcdefghijklmnopqrstuvwxyz!@#&lt;/span&gt;&lt;span class="nv"&gt;$%&lt;/span&gt;&lt;span class="s2"&gt;^"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

func MakePassphrase&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;byte &lt;span class="o"&gt;{&lt;/span&gt;
    /&lt;span class="k"&gt;*&lt;/span&gt;
        Answer informed by this SO answer
        https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-go
    &lt;span class="k"&gt;*&lt;/span&gt;/

  // rune is a go data &lt;span class="nb"&gt;type &lt;/span&gt;that aliases int32, you can &lt;span class="nb"&gt;read &lt;/span&gt;more about it here:
  // https://zetcode.com/golang/rune/
    b :&lt;span class="o"&gt;=&lt;/span&gt; make&lt;span class="o"&gt;([]&lt;/span&gt;rune, 32&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;i :&lt;span class="o"&gt;=&lt;/span&gt; range b &lt;span class="o"&gt;{&lt;/span&gt;
        b[i] &lt;span class="o"&gt;=&lt;/span&gt; letters[rand.Intn&lt;span class="o"&gt;(&lt;/span&gt;len&lt;span class="o"&gt;(&lt;/span&gt;letters&lt;span class="o"&gt;))]&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;byte&lt;span class="o"&gt;(&lt;/span&gt;string&lt;span class="o"&gt;(&lt;/span&gt;b&lt;span class="o"&gt;))&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;For me, coming from higher-level languages, this looks awfully fancy to solve the problem of “generate a random  of n length”, but it does the trick, so I’m happy. Let’s verify it works by adding a test to &lt;code&gt;main.go&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// main.go

...
func main&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  // ...previous code 

  // Custom passphrase to salt our encoded message with
  passphrase :&lt;span class="o"&gt;=&lt;/span&gt; utils.MakePassphrase&lt;span class="o"&gt;()&lt;/span&gt;
    fmt.Println&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Random passphrase is:"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    fmt.Println&lt;span class="o"&gt;(&lt;/span&gt;string&lt;span class="o"&gt;(&lt;/span&gt;passphrase&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s re-run &lt;code&gt;main.go&lt;/code&gt; and see our new result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go
Running!

Message from filereader is:
map[body:test &lt;span class="nb"&gt;test test&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
Random passphrase is:
bph@bgzmiegpcry!lvfcp!is^lpywxvy%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect! Now into the actual transformation. In &lt;code&gt;etl/etl.go&lt;/code&gt; under our &lt;code&gt;ReadData&lt;/code&gt; function from earlier, we are going to add some encryption logic. It isn’t necessary for what we’re building to get every nuance of the below code, although it is an interesting area and you can read some more about encryption topics &lt;a href="https://library.ahima.org/doc?oid=104090#.YkDMTt8pBhE" rel="noopener noreferrer"&gt;here&lt;/a&gt; if you wish. Ultimately, the important part is that we are using our randomly-generated passphrase in an encryption algorithm on the message text, and then we return both the result of the encryption and the passphrase.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// etl/etl.go&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;etl&lt;/span&gt; 

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"crypto/aes"&lt;/span&gt;
    &lt;span class="s"&gt;"crypto/cipher"&lt;/span&gt;
    &lt;span class="s"&gt;"crypto/rand"&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"io"&lt;/span&gt;
    &lt;span class="s"&gt;"io/ioutil"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/jtkaufman737/go_serialized/utils"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// ... previous code &lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;EncodeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;][]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// taken from https://tutorialedge.net/golang/go-encrypt-decrypt-aes-tutorial/&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;

    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;aes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCipher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// gcm or Galois/Counter Mode, is a mode of operation&lt;/span&gt;
    &lt;span class="c"&gt;// for symmetric key cryptographic block ciphers&lt;/span&gt;
    &lt;span class="c"&gt;// - https://en.wikipedia.org/wiki/Galois/Counter_Mode&lt;/span&gt;
    &lt;span class="n"&gt;gcm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewGCM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// creates a new byte array the size of the nonce&lt;/span&gt;
    &lt;span class="c"&gt;// which must be passed to Seal&lt;/span&gt;
    &lt;span class="n"&gt;nonce&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gcm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NonceSize&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c"&gt;// populates our nonce with a cryptographically secure&lt;/span&gt;
    &lt;span class="c"&gt;// random sequence&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadFull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// here we encrypt our text using the Seal function&lt;/span&gt;
    &lt;span class="c"&gt;// Seal encrypts and authenticates plaintext, authenticates the&lt;/span&gt;
    &lt;span class="c"&gt;// additional data and appends the result to dst, returning the updated&lt;/span&gt;
    &lt;span class="c"&gt;// slice. The nonce must be NonceSize() bytes long and unique for all&lt;/span&gt;
    &lt;span class="c"&gt;// time, for a given key.&lt;/span&gt;
    &lt;span class="n"&gt;finalText&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gcm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Seal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;][]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"passphrase"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;finalText&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;To test this encryption, let’s return to &lt;code&gt;main.go&lt;/code&gt; and call our new function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// main.go &lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt; 

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/jtkaufman737/go_serialized/etl"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/jtkaufman737/go_serialized/utils"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Running!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// ... earlier code&lt;/span&gt;

    &lt;span class="c"&gt;// Now we are going to encode it&lt;/span&gt;
    &lt;span class="n"&gt;encryptedMessage&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;etl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EncodeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rawMessage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;passphrase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Encrypted message and passphrase are:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encryptedMessage&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 re-run main, we will now see our encoded message logged as well!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;
&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;filereader&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Random&lt;/span&gt; &lt;span class="n"&gt;passphrase&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;bph&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;bgzmiegpcry&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;lvfcp&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;lpywxvy&lt;/span&gt;
&lt;span class="n"&gt;Encrypted&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;passphrase&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;bph&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;bgzmiegpcry&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;lvfcp&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;lpywxvy&lt;/span&gt; &lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;??&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;&lt;span class="s"&gt;"?S)c;????,?r?4$?4y??8o?w'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well that looks like a lot of hot nonsense but signifies success! &lt;/p&gt;

&lt;p&gt;Let’s now run a quick quality check to make sure we can demystify our data later on. In &lt;code&gt;etl/etl.go&lt;/code&gt;, add the following below our other code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// etl/etl.go &lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;DecodeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encryptedMessage&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;][]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// taken from https://tutorialedge.net/golang/go-encrypt-decrypt-aes-tutorial/&lt;/span&gt;

  &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;encryptedMessage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"passphrase"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;cipherText&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;encryptedMessage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;aes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCipher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;gcm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewGCM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;nonceSize&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gcm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NonceSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cipherText&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cipherText&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;nonceSize&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;cipherText&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;nonceSize&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gcm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cipherText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&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;Add the following to &lt;code&gt;main.go&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// main.go&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// ..previous code&lt;/span&gt;

  &lt;span class="c"&gt;// Lets check that we can decode it too&lt;/span&gt;
    &lt;span class="n"&gt;decryptedMessage&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;etl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DecodeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encryptedMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Decrypted message is:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decryptedMessage&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;By re-running &lt;code&gt;main.go&lt;/code&gt;, we confirm we’ll be able to decode this secret message when the time comes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;
&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;filereader&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Random&lt;/span&gt; &lt;span class="n"&gt;passphrase&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;bph&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;bgzmiegpcry&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;lvfcp&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;lpywxvy&lt;/span&gt;
&lt;span class="n"&gt;Encrypted&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;passphrase&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;bph&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;bgzmiegpcry&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;lvfcp&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;lpywxvy&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;&lt;span class="n"&gt;A_&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="err"&gt;\??&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;&lt;span class="n"&gt;ع4&lt;/span&gt;&lt;span class="err"&gt;???&lt;/span&gt;&lt;span class="n"&gt;SA&lt;/span&gt;&lt;span class="err"&gt;??&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="err"&gt;??&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;span class="err"&gt;????&lt;/span&gt;
&lt;span class="n"&gt;Decrypted&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  L is for Load
&lt;/h2&gt;

&lt;p&gt;The load step is going to connect us to Serialized and open the door for a lot of fun exploring this event sourcing platform and playing with all the functionality it offers later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick heads up:&lt;/strong&gt; In the next sections you may get a message about missing packages for our UUID package or others. You can run a quick &lt;code&gt;go get&lt;/code&gt; plus the link to the package repo to fix this. For me, it happened on two packages, so I ran &lt;code&gt;go get github.com/google/uuid&lt;/code&gt; and &lt;code&gt;go get http://github.com/joho/godotenv&lt;/code&gt;. The errors will prompt you and supply the exact command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;
&lt;span class="c"&gt;// api/api.go&lt;/span&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"bytes"&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"io/ioutil"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/joho/godotenv"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/jtkaufman737/go_serialized/utils"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// for each event, a `data` field will contain custom data, &lt;/span&gt;
&lt;span class="c"&gt;// or here the payload we care about &lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;PostData&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;EncryptedMessage&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"encryptedMessage"`&lt;/span&gt;
    &lt;span class="n"&gt;Passphrase&lt;/span&gt;       &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"passphrase"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// this is the larger `event` body with a subfield for data&lt;/span&gt;
&lt;span class="c"&gt;// defined in the previous struct&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;PostBody&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;EventID&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt;   &lt;span class="s"&gt;`json:"eventID"`&lt;/span&gt;
    &lt;span class="n"&gt;EventType&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;   &lt;span class="s"&gt;`json:"eventType"`&lt;/span&gt;
    &lt;span class="n"&gt;Data&lt;/span&gt;      &lt;span class="n"&gt;PostData&lt;/span&gt; &lt;span class="s"&gt;`json:"data"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="n"&gt;PostBody&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Step 1: Loading environment variables including our secret&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;godotenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;myEnv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;godotenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;/*
         Step 2: We need to build out a JSON body adhering to the following format
        {
            "events": [
                {
                    "eventID": UUID,
                    "eventType": string,
                    "data": {
                        "encryptedMessage": string
                        "passphrase": string
                    }
                }
            ]
        }
    */&lt;/span&gt;

    &lt;span class="c"&gt;// A bit MORE data wrangling: need a list of PostBody (events)&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;formattedData&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Events&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;PostBody&lt;/span&gt; &lt;span class="s"&gt;`json:"events"`&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;PostBody&lt;/span&gt;
    &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;finalData&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;formattedData&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Events&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// then can finally put the whole thing in JSON format&lt;/span&gt;
    &lt;span class="n"&gt;jsonData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;finalData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c"&gt;// set up our network client &amp;amp; error handling&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jsonData&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c"&gt;// add our headers so we can authenticate to serialize&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Accept"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Serialized-Access-Key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;myEnv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"ACCESS_KEY"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Serialized-Secret-Access-Key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;myEnv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"SECRET_ACCESS_KEY"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;bodyBytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ioutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// get it back into a format we like&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;responseObject&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bodyBytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;responseObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// and return it&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;responseObject&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There’s a lot going on here, but essentially our &lt;code&gt;Call&lt;/code&gt; method is a generic wrapper that we can feed a URL, HTTP method, and relevant data to communicate with Serialized and any other sites we plug into. We then use the HTTP package to make our calls, and do some data-wrangling to get things back into a manageable format.&lt;/p&gt;

&lt;p&gt;In our &lt;code&gt;main.go&lt;/code&gt; file, we need to add a few new things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we will use a &lt;code&gt;UUID&lt;/code&gt; package to generate IDs for our new “new_message” event, which will be part of the payload and the URL we hit on the Serialized API&lt;/li&gt;
&lt;li&gt;we will call our new API wrapper function to dispatch this logic&lt;/li&gt;
&lt;li&gt;we’ll then do one last print to confirm Serialized got our info
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// main.go&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// ... previous code &lt;/span&gt;

    &lt;span class="c"&gt;// We are going to generate a unique identifier for our event object&lt;/span&gt;
    &lt;span class="c"&gt;// and embed that into our URL&lt;/span&gt;
    &lt;span class="n"&gt;newUUID&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"https://api.serialized.io/aggregates/new_message/"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;newUUID&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"/events"&lt;/span&gt;

    &lt;span class="n"&gt;messageData&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PostData&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;EncryptedMessage&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encryptedMessage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
        &lt;span class="n"&gt;Passphrase&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encryptedMessage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"passPhrase"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;eventBody&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PostBody&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;EventID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;newUUID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;EventType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"new_message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;messageData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Next we are going to post this to serialized&lt;/span&gt;
    &lt;span class="n"&gt;responseObject&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;eventBody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Response object from Serialized is:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%+v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;responseObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And our final confirmation that the load step ran should look as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;
&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;filereader&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Random&lt;/span&gt; &lt;span class="n"&gt;passphrase&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;bph&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;bgzmiegpcry&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;lvfcp&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;lpywxvy&lt;/span&gt;
&lt;span class="n"&gt;Encrypted&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;passphrase&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;bph&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;bgzmiegpcry&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;lvfcp&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;lpywxvy&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="err"&gt;?̮?&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="err"&gt;?'&lt;/span&gt;&lt;span class="n"&gt;Ï&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;&lt;span class="n"&gt;ܧ_9&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;span class="err"&gt;??&lt;/span&gt;&lt;span class="n"&gt;yLC&lt;/span&gt;&lt;span class="err"&gt;????&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;
                                                             &lt;span class="err"&gt;?&lt;/span&gt;&lt;span class="n"&gt;GBw5&lt;/span&gt;
&lt;span class="n"&gt;Decrypted&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;
&lt;span class="n"&gt;Response&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;Serialized&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;aggregateVersion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SUCCESS&lt;/span&gt; &lt;span class="n"&gt;taskId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;51&lt;/span&gt;&lt;span class="n"&gt;ccba05&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;33&lt;/span&gt;&lt;span class="n"&gt;bf&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;4552&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;9539&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;9e9&lt;/span&gt;&lt;span class="n"&gt;a547dadf9&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Confirmation of our work
&lt;/h2&gt;

&lt;p&gt;Naturally we want to see a better signifier of what we did than this logging, so let’s head back over to Serialized’s dashboard. It’s the first thing you land on once you &lt;a href="https://app.serialized.io/auth/login" rel="noopener noreferrer"&gt;log in&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In my case I was testing this a few times so from our main dashboard we see a bevy of events. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F60zc3wj7elhhn1fhncwe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F60zc3wj7elhhn1fhncwe.png" alt="Serialized event list" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By clicking on the last event id in the chronologically descending list, we can check on the payload of what we sent over and confirm our data arrived. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7tmtn4imeog25mdijcf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7tmtn4imeog25mdijcf.png" alt="Specific event data in JSON" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;This was a fun one for me personally! Here’s a quick recap of some of the things I learned during the process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s nice to feel like a beginner again every once in a while. I just got promoted to Team Lead at work so honestly it seemed about right that I take a step back and take a crack at Go, which I’ve never used seriously before. Discovering how to work with it and get the first part of this project done was incredibly fun.&lt;/li&gt;
&lt;li&gt;Serialized was by far the easiest part of this work for me. We’re going to use it more when we continue this project in a future article, but it worked exactly how I expected it to going in.&lt;/li&gt;
&lt;li&gt;I also learned that being away from strongly typed languages for so long has really done a number on me. Particularly, I hadn’t realized how much I leaned on the loosey-goosey nature of high-level languages to deal with things like varying fields and unstructured data with JSON. I still don’t feel like I’ve fully hit my stride in elegantly dealing with JSON inside Go, so I’m going to go chat with some folks I know who use it regularly and see what I really should have been doing with all this logic 😅&lt;/li&gt;
&lt;li&gt;Despite the learning curve, I &lt;em&gt;generally&lt;/em&gt; found Golang pleasant enough to use, and the docs were fairly good considering its relatively young age. I also was impressed by its relative &lt;strong&gt;brevity&lt;/strong&gt; compared to Java, C#, or any of the other lower-level languages I’ve used in any significant way.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article was intended to be the first part of a short series, so I’m going to leave it here and get started on building out the other half of this application for Part 2! I am looking forward to exploring both more Go and more of Serialized’s capabilities in the next post, where the latter will feature more prominently. Thanks for reading!&lt;/p&gt;

</description>
      <category>go</category>
      <category>etl</category>
      <category>softwareengineering</category>
      <category>data</category>
    </item>
    <item>
      <title>What everyone's getting wrong about bootcamps vs degrees</title>
      <dc:creator>JTK</dc:creator>
      <pubDate>Sun, 03 Apr 2022 16:08:21 +0000</pubDate>
      <link>https://dev.to/heyjtk/what-everyones-getting-wrong-about-bootcamps-vs-degrees-521e</link>
      <guid>https://dev.to/heyjtk/what-everyones-getting-wrong-about-bootcamps-vs-degrees-521e</guid>
      <description>&lt;p&gt;Considering how much I tweet, bootcamps and degrees are something I haven't spent extensive energy on. Compared to the numbers of tweets about animals, hiking, food, or just making terrible jokes I've been next to silent on this matter (comparatively).&lt;/p&gt;

&lt;p&gt;But I did recently have this to say and I meant it.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1494010598023213057-620" src="https://platform.twitter.com/embed/Tweet.html?id=1494010598023213057"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1494010598023213057-620');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1494010598023213057&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;For the better part of a decade spent in tech, I've had to hear the endless choir of people pontificating about bootcamps and degrees and self-learning, each acting as if they were bringing down the word from the mountaintop. I've worked places where they assumed I had a degree and even repeatedly degraded people without them in front of me and I functioned as a “degreed engineer” with Schrodinger's credentials, you might say.&lt;/p&gt;

&lt;p&gt;But now I am done, I have the degree, and I'm ready to talk.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Part I: No Degree Days&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why I don't/didn't have a degree&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I'm writing this on February 21, 2022. Saying "I don't have a degree" will be accurate for about two more weeks, ish. I mean that's when my classes are done. I guess it gets conferred in May. But honestly, who gives a s@#$. The second that last assignment is turned in, in my mind it is done. (Updating this writing March 11th 2022 and I received two As, yay!)&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%2Fk7omzu3um8tw8zl3p3f4.gif" 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%2Fk7omzu3um8tw8zl3p3f4.gif" alt="https://media.giphy.com/media/3og0IuE1EjI5ZQzr3i/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For anyone wondering why I didn't manage to get a degree until now, there are many reasons. I didn't know for sure what I wanted to do. While in college, my dad got very sick and it became extremely difficult to manage his constant hospitalizations and keep up with the coursework. The teachers were not understanding. Also, &lt;strong&gt;I was poor&lt;/strong&gt; and it was not clear that I would make enough money even with a degree to pay back student loans, and thus was hesitant to take them out (my sister had just gone through finishing a degree that she couldn't find work in, and her example was informative to me).&lt;/p&gt;

&lt;p&gt;I'll pause here. &lt;strong&gt;For anyone whose thinking is so rigid that they don't understand that any one of those reasons by itself is good enough to not get a degree, you may as well stop reading&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is a fool's errand to pressure people into getting degrees when they don't know what they want to do. It is harmful that we make students feel like they must go on when they are facing life and death family crises. It is irresponsible, honestly, it is like a pyramid scheme that we bully people into taking on debt to buy their way into a middle-class life when &lt;a href="https://www.forbes.com/sites/camilomaldonado/2018/07/24/price-of-college-increasing-almost-8-times-faster-than-wages/?sh=152f4cf766c1" rel="noopener noreferrer"&gt;increasingly a degree does not guarantee it&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What it was like without a degree&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As a developer, I have led a surprisingly charmed life. I made senior rapidly. Dev Lead early too. Money, equity, and what now comes easy once seemed like a distant fantasy. Early into my life, it at one point seemed impossible that I'd ever be able to get an office job at all or anything out of service/manual work.&lt;/p&gt;

&lt;p&gt;It is not an exaggeration to say that doors were rudely slammed in my face, over and over and over again during that time of trying to find a first office job, over not having the degree. After the recession, there were enough job seekers that you could get rejected for $10/hr administrative jobs for not having a degree. (Nothing about that work requires one, for what it's worth).&lt;/p&gt;

&lt;p&gt;There's a study I came across about how &lt;a href="https://www.pbs.org/newshour/economy/making-sense/analysis-how-poverty-can-drive-down-intelligence" rel="noopener noreferrer"&gt;poverty lowers IQ&lt;/a&gt;, and I absolutely believe it. What I remember from this time were multiple prolonged cold wars waged between me and being poor and being an undesirable worker.&lt;/p&gt;

&lt;p&gt;So bleak was my path in getting into &lt;em&gt;any&lt;/em&gt; office role that I could leverage into a career that I found myself over and over again looking at online degree mills. When I say "degree mill" I do not mean some online college people turn their noses up at - I mean a &lt;strong&gt;literal degree mill&lt;/strong&gt; where you mail them a check for a fake diploma. It was made so crystal clear to me that the degree was the problem, I really almost did it even though it would certainly have been grounds to be fired if I did and it came to light, it might have counted as actual fraud. Things looked that grim. &lt;/p&gt;

&lt;p&gt;That's probably the most distinct memory I have of this time that I'll never forget: sitting in front of my computer with the degree mill website in front of me. I imagine if I could have looked at myself, I would have seen an eerie animation borne out of raw longing written all over my face. The lack of a degree was a black cloud trailing me, constantly.&lt;/p&gt;

&lt;p&gt;That, and my credit score. Simultaneously I schemed and stewed and plotted as if in a long, arduous chess match. &lt;em&gt;How do I get a job, any job where I'll build marketable skills? How do I budge my credit card up from 500-something?&lt;/em&gt; I can only imagine my IQ was lower. It felt like being haunted. I was always preoccupied.&lt;/p&gt;

&lt;p&gt;Whatever forward momentum I now enjoy as someone with assets, the opposite was true as someone without them. To clean up my credit I paid additional fees for a debt consolidation service and high-cost, high-fee credit cards to begin to have a history. It was pay to play. But still, a far lower entry fee than what it would take to attend school.&lt;/p&gt;

&lt;p&gt;I still feel strange sometimes saying that I was “poor” but I don't know what else to call it when they were at various points chasing me around trying to repossess my car, or that when living in Baltimore we kept the heat inside to 50 in the winter and used space heaters because me and my roommates were all broke. When I finally got a first office job, I volunteered at every opportunity to travel because I got a daily per-diem for it, but was constantly at risk of embarrassing myself on these trips with colleagues if we ever had to spend money because, with one wrong move, I would easily hit my credit limit or overdraw my bank account. I once volunteered for an extra two weeks away because I was too broke to pay rent and it gave me a pretext for the check to be late (ahh simpler times without Venmo). So, yeah. Plenty of people had it worse than me but I was pretty broke.&lt;/p&gt;

&lt;p&gt;And yeah, it was miserably hard to live that way. When eventually I got a low-paying job but where I was taught transferable skills, there were no limits to my tenacity (for those of you who think people don't finish degrees out of "laziness"). I was a recruiter, and so had no reason to get tech certs or a security clearance but I saw a pathway. I was opportunistic to the extreme.&lt;/p&gt;

&lt;p&gt;Anything I saw that would give me a foothold, give me legitimacy, give me something to propel me to a better life I grabbed on as hard as I could and didn't let go. I had no fixed plan of what I would be, I would have taken anything available to me that moved me forwards. &lt;strong&gt;The one exception to this remained school&lt;/strong&gt;, infuriatingly. As a white-collar worker, I began to have tuition benefits at work, up to $5000 or so dollars which is the limit the company can use it as a tax write-off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's the catch:&lt;/strong&gt; you typically had to pay up-front and then be reimbursed. I never had the money. You also had to repay the money if you left, and I was constantly expecting the sky to fall and to be laid off. It's amazing when you don't have money how much you have to worry about it, constantly, to not be caught off guard by the next disaster. The tech certs, though, the company paid up front. So that's what I did.&lt;/p&gt;

&lt;p&gt;Although this tenacity launched me out of being poor and into a stable enough career, the lack of degree continued to embarrass and dog me.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Fun things people have said to me about not having a degree&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I would be remiss to not give my mom a shoutout here. I’m not in touch with her anymore but at the point of me struggling so hard to get into any office role, I was. At the point that I told her how frustrated I was by my job search and how little luck I was having, I once said something like “I'm so disappointed I didn't get that one, I know I would have been great at it,” and she replied something to the effect of “You aren't qualified for it, you are qualified to work at Target”. I'd be lying if I said that line won't be burned onto my brain forever, although it's pretty funny in hindsight. (Maybe I SHOULD work at Target, I shop there enough – could use the discount). But at the time, I knew it would do nothing to advance me towards something where I could use my brain and actually build a career.&lt;/p&gt;

&lt;p&gt;Of course, there were other places where I got dinged over the lack of degree. In the screening call for what would wind up being my first programming job, they were so abjectly horrified when I answered that I didn't have a degree that I felt like an untouchable, like I might as well have had cartoon stink lines coming off of me. I finally just blurted out (having never done so before) that my dad had gotten very sick up until his death that year and I'd dropped out for family reasons but was trying to go back. After a stunned and uncomfortable silence, they apologized and moved on.&lt;/p&gt;

&lt;p&gt;When hired, it was clear that because of my lack of degree they perceived me only suited to be sort of a code plumber, an unrefined hand who could do basic tasks (unlike the music major they also hired at the same time with no experience, which makes sense how?). My boss made his disdain for my unfinished degree known, he brought it up in our 1:1s frequently. And with great, great irony that job was in the Education unit of a research institute. So, I had the dubious honor of being the least educated person IN THE EDUCATION GROUP. Fun times.&lt;/p&gt;

&lt;p&gt;It has actually been fun and funny at times to observe all the different reactions people have to the information. Stuff like, “But you are so smart!”, which.... thanks I guess?&lt;/p&gt;

&lt;p&gt;My all-time funniest/favorite is when I have been in situations and realized that even with a degree there was a higher level of arbitrary gatekeeping that would have kept me out anyway. If my life had gone differently in a couple of spots I would probably be the proud owner of a Graphic Design degree from a state school. I've been in a small number of interviews where they led with “Well, we hire engineers from &lt;strong&gt;&lt;em&gt;elite&lt;/em&gt;&lt;/strong&gt; colleges but someone from other schools could start in tech support and potentially work their way up but it isn't a guarantee”. Cool!&lt;/p&gt;

&lt;p&gt;At some point working in tech though, it stopped mattering. Actually, I guess I can pinpoint when: 2 years in. With two years of experience, it seems like no one gave a lick whether I went or not. Either that or people are exceptionally bad at reading. I put my field of study under a deliberately ambiguously titled &lt;em&gt;Education/Training&lt;/em&gt; section on my resume. I never lied. I listed the field of study with no degree or graduation date. Having been burned over and over and over again for not having the degree, I suppose at that point I decided “if you don't care enough to ask, I don't care enough to tell you”.&lt;/p&gt;

&lt;p&gt;It was always very hilariously clear when people assumed I had it and I didn't. A colleague once guffawed over me not knowing what Conway's Game of Life was and exclaimed “Did you even TAKE computer science!?”. In the moment I answered “Nope, they must have saved that for the fancy kids doing the Master's program” but internally I felt like shit. This colleague was a friend and I know only ribbed me that way because of the assumption that we were peers and it was in no way punching down. Little did they know, they had hit me where it hurt. Although having now finished a degree, I can tell you I STILL would never have learned about Conway's Game of Life! I have since of course looked it up. I do not feel as if it made me a better engineer to know it, lmao.&lt;/p&gt;

&lt;p&gt;The other truly, &lt;strong&gt;&lt;em&gt;truly funny&lt;/em&gt;&lt;/strong&gt; one was a boss I had. I forget what level of education he had but a degree for sure, and he definitely assumed I had mine as well. He used to say benevolently rude things like, “You know JT, we could hire someone with occupational training and they could string code together but they wouldn't be able to write algorithms like you or (other teammate).” &lt;/p&gt;

&lt;p&gt;Reader, I s@#$ you not, this man's code was THE WORST I'VE EVER SEEN. I WOULD GLADLY HAVE HIRED SOMEONE WHO “JUST STRUNG CODE TOGETHER” OVER HIM. He wrote API endpoints that were concatenated together in what sounds like a joke of a SQL-injection nightmare. He wrote all his joins in what would have been cartesian products/cross joins without the database engine cleaning up his misdeeds under the hood. He wrote a new-ass-application in Python 2 the year it was to be sunsetted when the maintainers had said they wouldn't even patch security bugs going forward, just because he didn't know about system python. He sure liked me though! He made me Tech Lead. I had an even more talented colleague at that job who switched teams to get away from this boss, and with great irony I later found out it was because the boss was giving him a hard time about having an unrelated Construction Management degree. (This dude was amazingly talented, and could code circles around the boss. Eeesh).&lt;/p&gt;

&lt;p&gt;A lot to unpack there but I'm going to throw away the whole suitcase.&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%2F3za6pry4dqnd1y10c8zs.gif" 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%2F3za6pry4dqnd1y10c8zs.gif" alt="https://media.giphy.com/media/S8Bnf6KByXDly5VCzq/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What someone without a degree would want you to know&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The only thing I will ever say no one can accuse me of is a lack of work ethic or ambition. Whatever you want to say about me not having a degree, you could chalk it up to just about anything in the world but there is no credible case to be made that laziness or lack of tenacity were in play. I'm not unique.&lt;/p&gt;

&lt;p&gt;I didn't write the first half of this post to be "woe is me", I'm obviously very lucky and have enjoyed a drastic change in circumstances. Honestly, it's been so drastic that for all I know I'm just part of a bubble about to pop and my fortunes will all reverse the next economic downturn. The reason I mention it is, that &lt;strong&gt;I was always the person capable of having the degree I'm about to earn&lt;/strong&gt;. I mean heck, I used to work harder without it, I had to exercise such a high level of showmanship and boldness to compensate, I was probably a better worker.&lt;/p&gt;

&lt;p&gt;So please take away from this that &lt;strong&gt;education != intelligence, education != work ethic&lt;/strong&gt;, and in many cases, it is just a reflection of someone's luck. When you judge people harshly on it, that is in fact what you are judging and it is frankly crappy.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Part II: Bootcamps&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What brought me to bootcamps&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When in 2015 my father died, he had some miscellaneous life insurance policies that resulted in me inheriting something like $40,000. That might have paid for school. Unfortunately, the price I had paid to get to the fringes of the middle class was to work jobs with ridiculous hours. I felt extreme concern that I could keep it up if I added school.&lt;/p&gt;

&lt;p&gt;At this point, my recruiting background had taken me into recruiting for technical roles in government contracting, most often for Network Engineers and Cybersecurity professionals. My claim to fame in recruiting was that I was very good at boolean searches, which was fortunate since government contracts often had roles with complex mixtures of security clearance and technical certification requirements.&lt;/p&gt;

&lt;p&gt;There is an entire DoD regulatory proviso code for the Security+ exam by CompTIA (DoD 8750), so invested are government agencies in these various tech certs. Some jobs had requirements with a complex mix of certification combinations, where you would need one or more certifications from group A, one or more certifications from group B, and then a security clearance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Point being, I come from a world where ongoing professional development was very respected and in-demand.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;(One thing it's funny to note here. Probably based on what I said about being so broke, you would think I got into tech for financial security. Nope! I took a 16k pay cut for my first programming job. My dad's death was really hard on me and I felt like I just couldn't talk to people for a living anymore. It felt unbearable. At the end of my recruiting career, I made 70k which was a fine living in 2016 and if I had liked it, could have pursued management if all I wanted was more money. Along the way of trying to be a good recruiter and learn tech terms, I crossed over to the dark side. It was so much more fascinating than having the same intro candidate call dozens of times a week. Although there is nothing wrong with getting into tech for money, I actually have done it out of love from day one. And that's the only reason someone with so little natural talent at coding became so successful. I just happily plugged away at it in most of my free moments until I got suddenly shockingly good). &lt;/p&gt;

&lt;p&gt;After my dad died and I debated using the inheritance for school vs getting more technical certifications, somehow strategically placed advertisements for bootcamps found their way to me. I immediately liked the idea. It sounded like a combination of instruction and apprenticeship, I would actually be BUILDING things not just memorizing and regurgitating things. I bought in completely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It is worth pointing out that although I wasn't recruiting developers heavily, I was in the tech industry and had no idea that bootcamps were widely criticized and considered by many totally illegitimate.&lt;/strong&gt; I want to pause on that.&lt;/p&gt;

&lt;p&gt;If me, a white-collar worker actually already working with these types of roles and around tech people, wouldn't know the baggage that came with that path, how do you expect someone working at Mcdonald's and dreaming of a better life to know it? Part of the hate on bootcamps honestly in effect s@#$s on people who risked a lot and put their neck on the line trying to do the really hard work of building a career. So, consider that.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The mixed bag that is bootcamps&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here's where it gets dicey. I just finished telling you that you need to show people who attend bootcamps some respect. I can't and don't necessarily say the same for the people running them.&lt;/p&gt;

&lt;p&gt;I attended General Assembly's first remote Web Development Immersive program in 2016 (since rebranded). I very clearly remember that the marketing was emphatic that the program could take you from zero to sixty, &lt;strong&gt;even with no experience&lt;/strong&gt;. I even had some experience! I had been doing Coursera, CodeAcademy, and technical certs, I thought I'd be coming in from a good starting position.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I was very wrong.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;About half the people in my bootcamp were technical. One did tech support, one had a CS degree and had freelanced, one was a graphic designer who did some code, on and on. By the end of the first unit, about half of the cohort's projects did not pass, a condition that could cause us to fail out of the program without a refund. As you may guess, the entire "almost failing half" were me and the other people not working in technical roles before joining the program. (I remember now and laugh that on the day we were supposed to present our projects I said something like “This is my project and spoiler alert it doesn’t work”).&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%2Fo3uvl8uvorhwvs0d7lvp.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%2Fo3uvl8uvorhwvs0d7lvp.png" alt="The Rocks shrugs saying this doesn't work"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With that large of a group failing, it was impossible to make us &lt;em&gt;individually&lt;/em&gt; shoulder the blame - it was too blatant. The bootcamp split us up into groups, with mine to repeat our first unit. As time went on, myself and one other woman in the program realized how screwed up it was that we were missing instruction and content that we paid for (at the time, on MEAN stack, all the rage). We raised hell. We made them agree to extra workshops after and other conciliatory measures.&lt;/p&gt;

&lt;p&gt;As a sidebar, I felt such stress and desperation that I had thrown all my eggs in this basket (quit my job, spent all that $) and then let down by the system I'd pinned all my hopes on, my brain got mean and focused and steely. After the first unit I moved, up-up-up towards the top of the pack in my group. I was stressed, I was angry, and I was scared but I channeled it and I liked code, even as bad as I was back then.&lt;/p&gt;

&lt;p&gt;Since then, bootcamps have arguably only gotten worse. &lt;a href="https://rbefored.com/dont-get-an-isa-and-what-to-do-if-you-have-one-a1a9217fd447" rel="noopener noreferrer"&gt;Parasitic income sharing agreements&lt;/a&gt; are a Faustian bargain. Bootcamps are functionally unregulated, and cherry-pick statistics to give the reporting body CIRR, or just &lt;a href="https://nymag.com/intelligencer/2020/02/lambda-schools-job-placement-rate-is-lower-than-claimed.html" rel="noopener noreferrer"&gt;stop doing so altogether&lt;/a&gt;. The inexperienced instructors and recycled recent graduate TAs don't know what they're doing. As the market is flooded with junior candidates many of whom are all trained in the same things, bootcamps have to pivot wildly and come up with new curriculum. &lt;strong&gt;I could go on and on and on&lt;/strong&gt;, and often do.&lt;/p&gt;

&lt;p&gt;Some of them have gotten better. I have seen B-Corps, free bootcamps, bootcamps to get former convicts into coding, schools free to disabled people. Some of the programs are now two years long. In response to critiques that bootcamp graduates don't know data structures well, some have added things like that. There are also orgs like &lt;a href="https://codethedream.org/" rel="noopener noreferrer"&gt;Code The Dream&lt;/a&gt; that give me a lot of hope in the nonprofit model, they follow the bootcamp with an apprenticeship period building sites for nonprofits to give the students real experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Least favorite takes on this topic and rebuttals&lt;/strong&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Bootcamp people are ok as programmers but will never be software engineers”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As someone who just finished four years of schooling largely debugging and learning alone, you can f@#$ right off with this. Nothing magical happened in my degree that transformed me. There was little new in my coursework and I could plow right through on code alone. Most of our books were open-source resources.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“People who join bootcamps need hand-holding and structure, but if you don't you can self-teach”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes, I hear this, not always this clear but I hear comments reeking of it often. You know why I wanted instructors? I had worked around software engineers and the field seemed hard. I wanted to do it right, I wanted to give it my all. I trusted that people in the field might have something to teach me. I trusted that learning these skills would be difficult and I wanted to give myself the best possible chance of success. Wanting instructors came from a place of humility. It was a lot of money and a lot of risk, but it was a representation of my commitment to choose active instruction – I wanted to do it right, I was giving this challenging material respect by wanting a guide.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What someone who attended a bootcamp would want you to know&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It is possible to be critical of bootcamps but still respect the people who attended them and treat them as people who took a huge risk out of willingness that they could build a better life for themselves and their family. Doing a bootcamp is PAYING to work extremely hard. These people don't deserve your scorn or your in-group out-group blanket dismissal.&lt;/p&gt;

&lt;p&gt;What does it say about you if you are someone that enjoys deriding people for trying to learn something? What did it ever do to hurt you? What makes you the authority on high to pass judgment on someone else just trying to be compensated for their labor and make a living? The more you unpack it, the more appalling it sounds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But the number one, super-duper incredibly important thing I need you to remember is this. Yes, you, you who secretly has a low opinion of bootcamp people: there is also a lot of bias at play here, and I don't mean credentialism.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is a known fact that bootcamp graduates are &lt;a href="https://www.cio.com/article/228301/want-a-more-diverse-workforce-hire-bootcamp-graduates.html" rel="noopener noreferrer"&gt;far more diverse across multiple categories&lt;/a&gt; than CS degree students. &lt;a href="https://thedecisionlab.com/biases/in-group-bias" rel="noopener noreferrer"&gt;In-group/out-group bias&lt;/a&gt; is a real thing and no matter how nice of a person you are, the human brain was built to categorize and we all must contend with that. It is not a coincidence that this group of people who is maybe queerer, browner, and more female than you and all your CS cohort peers show up and the initial brain reaction is mistrust or disbelief. As one study of in-group/out-group bias puts it, “Experiments […] have been repeated time and time again, demonstrating that the favoritism people show for their own group doesn’t need to founded in anything particularly meaningful.” The same linked article goes on to say:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Another basic truth about people: we have a need to feel positive about ourselves, and we are frequently &lt;/em&gt;&lt;em&gt;&lt;a href="https://thedecisionlab.com/biases/dunning-kruger-effect" rel="noopener noreferrer"&gt;overly optimistic&lt;/a&gt;&lt;/em&gt;&lt;em&gt; about how exceptional we are compared to other people. These processes of self-enhancement guide our categorizations of ourselves and others and lead us to rely on stereotypes that demean the out-group and favor our in-group. In short, because our identities are so heavily reliant on the groups we belong to, a simple way to enhance our image of ourselves is by giving a shiny veneer of goodness to our in-group—and doing the opposite for our out-group.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this sense, I feel for people with skepticism about bootcamps. Your brain is really not set up to like this concept. It is invalidating to people to have spent ~2 years of a Bachelor's Degree on Computer Science concepts and have someone who spent a fraction of that be competing at your level. &lt;/p&gt;

&lt;p&gt;I recently saw a tweet that was a pretty terrible take tbh but the comments were illuminating in one way.&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%2F3r6ec27l5iamejb9yqfm.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%2F3r6ec27l5iamejb9yqfm.png" alt="You went to a three month boot camp. I spent six and a half years getting my computer science degree. We are not the same"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Above ^ this the poster had a video of them saying “I took six years to get my degree, you went to a three month bootcamp. We are not the same”. I laughed a little at this because the “no one is better” at the end clearly is tacked on to avoid criticism. This person riffing on the “we are not the same” meme makes it clear they think one is better than the other. Some of the replies were:&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%2F6gg7relnu1h0maqrboa0.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%2F6gg7relnu1h0maqrboa0.png" alt="I did both and to be honest I learned more by myself. At school I had to follow the rules and do what the instructor wanted. Pretty old way to do things and the coding BootCamp care only about the money. To be honest it doesn’t make you any different."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And another, that most closely supports my point about in-group/out-group bias:&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%2Fbxdpj9t5zfze9r7ydv7d.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%2Fbxdpj9t5zfze9r7ydv7d.png" alt="I feel this way about design...when canva was released and everyone became a “designer” my feathers were ruffled as my degree and experience seemed invalidated overnight."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While I'm skeptical that anyone who knew Canva alone was off finding work as a designer, this person recognizes what's happening in their own cognition: they feel invalidated by people from other paths. It feels invalidating to the work they did and that's upsetting to them. I appreciate that they had the clarity to recognize it that way because at the end of the day I think that's part of what is going on with a lot of people.&lt;/p&gt;

&lt;p&gt;One final thought to leave you with: if like the poster above you find yourself thinking “a few months can't compare with years”, I want to reframe that a bit for you. An average college student goes two semesters a year with a 12-credit workload. The average semester is 15 weeks, with 2.5 hours of classroom time per course. So, 10 hours a week over 15 weeks, x2, or &lt;strong&gt;300 hours&lt;/strong&gt; of instruction time per year. Using General Assembly, my own bootcamp as an example, the schedule was 10-6 with an hour break at lunch. (That is not including time alone coding afterwards for homework). So that's 7 hours a day for 12 weeks, although I'm going to subtract that last week because I think we spend it on the final project. Let’s call it 11 weeks x 35 hours = &lt;strong&gt;385 hours&lt;/strong&gt; of instruction. Draw from that what you will.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Part III: The Degree&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What made me decide to finish the degree&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is a question I get asked A LOT by bootcamp people - “Why did you go back, did you feel like you needed it?” and it isn't that easy to answer. People in this field feel all the time like they are “imposters” regardless of background and experience, and I wasn't immune. Being a woman in a male-dominated field, it would be a lie to say that I never felt the need to be unimpeachable in my track record, credentials, and output. Having seen the fate of people without degrees in the last economic downturn, it also seemed like a way to protect myself. If the job market ever got bad again to where employers just needed to filter out some arbitrary number of people, degree requirements are a very easy way to do it.&lt;/p&gt;

&lt;p&gt;I also just wanted to &lt;em&gt;know&lt;/em&gt;. To know what it was exactly that I was missing by not going. What exact things I wasn't aware of that seemed to make this whole industry think people with my background were a joke (in the abstract anyway, individually people treated me well and I was obviously very successful even before finishing the degree). What exact topics a degree would cover that would take me from the fringe to being a Real Programmer :Tm:. You might say, I wanted the degree just so I could tell everyone to STFU up about this all. (That is literally what I tell people who want to talk about this topic, as I showed in the tweet included in Part I. There are a very very small number of topics where my mentality is “you can't tell me s@#$ about this”, but this is one of them. I have the complete perspective. At this point I have done a degree, done a bootcamp, and have professional certifications. I have tried it all).&lt;/p&gt;

&lt;p&gt;But was it worth it?&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The mixed bag that is degrees&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Ok so. You've already heard that I was not super impressed by my bootcamp and it would probably be more satisfying to end this arc by me saying the degree was far superior.&lt;/p&gt;

&lt;p&gt;Meh.&lt;/p&gt;

&lt;p&gt;Some of the stuff was pretty cool. I think my favorite courses included one where I got to use JavaScript and Flask to make demos of different software vulnerabilities. I came up with behavior with VueJS to imitate a bot doing a brute force attack on a login page for instance. By far the HARDEST courses I took were actually during a brief time when I was doing a Network Engineering major and had to do coursework aligned with the CompTIA A+ and Network+ certifications. I don't know how hard the certifications were, but the classes relied on all these virtual labs and they were incredibly time consuming and finicky, if you did things correctly but in the wrong order you wouldn't get points, that kind of thing.&lt;/p&gt;

&lt;p&gt;Most of the coding, I could just show up and code without much paying attention to anything else. Ironically, some of the things I was best at (SQL) were some of my worst grades, just because I would do things the “industry way” not the “textbook way” or use techniques that accomplished what was needed but weren't what the book was trying to highlight, etc. There were some more relevant things (like AWS) and some less relevant things, like assignments so old that they were dependent on Java tools that could no longer be installed on modern machines. At the end of it all, it was probably equal parts Python, Java, JavaScript (used in classes where I was allowed to pick), and SQL. Not a bad mix for employability.&lt;/p&gt;

&lt;p&gt;I will say that neither the types of tasks we were assigned nor the way content was presented were particularly engaging. A lot of “build a desktop Java app to do payroll”, “build a Java app to look up semester grades”, “build a Java calculator”. As someone who didn't like Java, I definitely had the realization that if college HAD been my first introduction to code, I would have abandoned it. I would have switched majors I'm almost certain. If I thought all coding was was building dull apps with Java, where it takes a bazillion lines of code to do the simplest thing, I would have noped out hard.&lt;/p&gt;

&lt;p&gt;The degree also pointedly side stepped a lot of extremely relevant industry concepts. There was one class where a classmate managed to bork his code irreparably and I was trying to help on the class forum. I was curious if anyone would tell this person about version control to save them from similar issues in the future. Knowing the professor would respond I said something like, “It would be great if there was a way to go back in time with code”, wondering if they would mention git at all. Nope!&lt;/p&gt;

&lt;p&gt;We also got assignments where to follow the instructions the cyclomatic complexity of the end result was horrendous. To get an A, you had to follow the arbitrary instructions even if the resultant code was poor. We also spent an honestly, somewhat embarrassing amount of time on things that are decidedly not industry standard anymore, like drag and drop UI builders in Java, incredibly old versions of Oracle, etc. Some of the more relevant things we learned were approached in very weird ways, like having to use spool files (???) for SQL, and topics like types of software testing or code efficiency were entirely skipped while instead, we spent a mind-numbing amount of time on things like the Software Development Lifecycle.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Least favorite takes related to this topic and rebuttals&lt;/strong&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Degrees are pointless”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Look, while ultimately mine may not be worth it you’ve seen from my experiences listed earlier how rudely the world may treat you for not having one. That’s not to mention that for groups that aren’t well-represented in tech there is often additional pressure to “prove” ourselves, and it is not always possible to be taken seriously without credentials. People might do it to advance themselves, just out of the curiosity to learn, or a multitude of other reasons. Same as we aren’t going to s@#$ on bootcampers for the act of learning, we are not going to s@#$ on people getting degrees. Why even would you? What is scorn worthy about someone wanting to work and learn?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“People who get degrees are fools, a bootcamp is enough”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Nothing is enough.&lt;/strong&gt; Truly.&lt;/p&gt;

&lt;p&gt;Our society has increasingly moved to requiring degrees even when they are only nominally of benefit for the role or even &lt;a href="https://www.bbc.com/worklife/article/20210126-degree-inflation-how-the-four-year-degree-became-required" rel="noopener noreferrer"&gt;irrelevant&lt;/a&gt;. Automated hiring is filtering people out in bizarre ways like screening nurses who need data entry skills for &lt;a href="https://www.vox.com/recode/22673353/unemployment-job-search-linkedin-indeed-algorithm" rel="noopener noreferrer"&gt;computer programming&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And yet...&lt;/p&gt;

&lt;p&gt;I don't know if I know ANYONE who walks onto their first programming job and doesn't feel kind of lost. In mine, I was able to immediately make contributions with bug fixes but even so was in way over my head on other things. Most schools still teach Java or C, most workplaces use a variety of things. If I extrapolate where I'd be starting from with the degree alone, my whole atrocious learning curve with git would have had to happen at work, I would have known little to nothing about CSS or HTML much less accessibility. It would still have been a steep, STEEP learning curve.&lt;/p&gt;

&lt;p&gt;If someone feels like going to college because they want to feel prepared for the workplace, good for them! Just as it doesn't invalidate people from college for bootcampers to exist, it is pretty iffy to completely disregard any time spent learning period.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Also: this statement is clearly wrong&lt;/strong&gt;, there is a reason people continue to find CS grads more prepared although it is not the reason people think and I'll elaborate in the next sections. Whenever I hear someone so self-satisfied with their conclusion, I can't help but think of the saying, &lt;em&gt;trust those who seek answers not those who claim to have found them&lt;/em&gt;. Anyone too gung-ho with no nuance, I do not trust your conclusions.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What someone with a degree would want you to know&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The reason I’m so sick of how people talk about this subject is the complete lack of nuance brought to it. And yes, you are hearing me correctly that my view that IMO does have sufficient nuance boils down to, people may be leaving degree programs slightly better prepared than bootcamps but there is also a lot of bias impacting how we evaluate people in these two groups, and the difference has absolutely nothing to do with degrees being superior or the people who get them being superior.&lt;/p&gt;

&lt;p&gt;At the end of the day, despite everything I've said, me with a degree may still be a little better than the version of me existing in some alternate universe without it. Not because the degree itself was special, but simply through the act of having to engage with the material and the extra hours put in. That didn't need to occur in school and I don't know that school was even the right place for it. ALL of the more advanced things I have learned or done in my career have been learned on the job, period. But attending school of course didn't make me any &lt;em&gt;worse&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;As time has gone on, as I've worked with people with and without degrees, as I'm now on a team that is made up largely of career changers with degrees (but unrelated) who are among the smartest colleagues I've ever had, my views on this entire thing remain hard to put into words. While I DON'T think the act of attending college is magical, I am comfortable roughly saying that college does seem to generally be producing more prepared entry-level programmers than bootcamps are.&lt;/p&gt;

&lt;p&gt;As time goes on, the more I see though, I am increasingly sure that it is not because these two forms of training are so fundamentally different or that one is inherently better. The longer I go on, I think the benefits of college are simply that it goes on &lt;em&gt;longer&lt;/em&gt;. There is &lt;a href="https://www.npr.org/sections/13.7/2018/02/01/581864513/would-college-students-retain-more-if-professors-dialed-back-the-pace" rel="noopener noreferrer"&gt;evidence&lt;/a&gt; that we retain more when concepts are explored slowly. Something called the &lt;a href="https://www.scotthyoung.com/blog/2016/05/31/learn-fast-or-slow/" rel="noopener noreferrer"&gt;spacing effect&lt;/a&gt; has studied that our brain holds on to more and benefits from superior long-term memory performance when the time spent learning is spread out. At the end of the day, &lt;strong&gt;I am of the opinion that that is the only difference that matters&lt;/strong&gt; in this debate.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Part IV: Where does this leave us?&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;If everything sucks, what's the point then? What's the solution?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Well, okay, so I know I was critical of my bootcamp and now critical of my degree. That being said, I wouldn't change either experience. When prospective career changers ask me which they should do, or ask what language they should learn, or how they should spend their time, I often tell them something like “any time spent learning will be valuable”. Pick what interests you, or what you think is the direction you want to take your career. It doesn't matter. I have a suspicion if you pick something enjoyable to you it will enable you to spend more time learning and overall have the biggest ROI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real takeaway I would like people to have from this post is that bootcamp vs degree training is not a valid premise for evaluating programmers. Period.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your brain has a sticky attachment to the idea of this hierarchy, ask yourself why. What benefit HAS ever really come from broadly profiling a huge group of people without any nuance? What benefit does it really give you?&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;An alternate framework&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;With that said, we reach a conundrum: if concrete credentials are not the way to evaluate programmers, how do we? We all know everyone hates whiteboarding and take-home projects. &lt;strong&gt;Although I will say, certainly me feeling stupid for an hour while live coding is less trouble than getting a whole ass degree.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At the end of the day if a company wants to have an entrance test and uses those in lieu of specific years of experience or degree requirements, I don't think that's the worst thing in the world. It at least would be something consistent. And while yes, it's a time commitment, again, less so of one than either a bootcamp or school to prove yourself.&lt;/p&gt;

&lt;p&gt;But really, I don't even think that's a necessary alternative if degree requirements were scrapped.&lt;/p&gt;

&lt;p&gt;One philosophy in hiring that I like is the competency-based approach, &lt;a href="https://www.shrm.org/hr-today/news/hr-magazine/pages/0315-competencies-hiring.aspx" rel="noopener noreferrer"&gt;described here&lt;/a&gt; as being the solution for hiring challenges where people were coming in with the right backgrounds, degrees, etc, and still having issues on the job. This approach relies on job profiles and structured interviews, and as discussed in the article above has also been linked with facilitating more diverse hires. It is also an excellent way to account for the fact that not all years of experience are equivalent and some people progress faster than others to the same level of mastery. &lt;a href="https://blog.imocha.io/competency-based-approach-to-identify-rock-star-software-developers/-during-talent-acquisition" rel="noopener noreferrer"&gt;This article&lt;/a&gt; goes on to say that naturally there are numerous ways of doing this for software engineers, whether it be assessments, technical questions, whiteboarding, etc.&lt;/p&gt;

&lt;p&gt;I think we'd be better off even with some combination of measures. Like a degree requirement OR you can do a take home OR you can whiteboard to demonstrate whatever level of mastery. Ultimately, my opinion is that you can assess an engineer without the whiteboarding but if it moves places away from arbitrary degree requirements then fine.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Also worth considering&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It is also worth noting that both bootcamps and colleges have numerous other issues I didn't even get to cover here. My personal opinion is that the bootcamp model is not worth throwing away despite the issues with poorly run and disorganized ones, but it is screaming for legislation. Some of the things I've heard go on are borderline fraudulent, like ISA repayment being triggered by jobs that are barely tech-adjacent.&lt;/p&gt;

&lt;p&gt;It is valid to have specific issues with the way bootcamps are run, but it is also valid to have extremely real concerns that stop you from wanting to go to college. When colleges shut down due to the COVID-19 crisis students were displaced from housing and meals that they were still &lt;a href="https://www.expertinstitute.com/resources/insights/universities-sued-for-covid-19-refunds-following-campus-closures/" rel="noopener noreferrer"&gt;on the hook for financially&lt;/a&gt;, and many are now suing. This excellent episode of &lt;a href="https://www.youtube.com/watch?v=YytF2v7Vvw0" rel="noopener noreferrer"&gt;Patriot Act&lt;/a&gt; addresses that increasingly schools cost is only half related to genuine fees, and schools are using atrociously paid adjunct professors to keep their own costs low while institution president salaries and investment trusts have exploded. The number of administrators at schools has increased in some cases 135% while adjunct pay has gone down 50% but executive level salaries are up 35%.&lt;/p&gt;

&lt;p&gt;That's not to mention, that for cases like mine with a sick parent, it isn't like in return for all that money you are getting any kind of understanding. Even in the recent invasion of Ukraine by Russia, students requesting deadlines to account for the fact that they are literally in a war zone are &lt;a href="https://ca.news.yahoo.com/ukrainian-canadian-students-send-love-232006339.html" rel="noopener noreferrer"&gt;being refused&lt;/a&gt;. I'm not even going to touch the ongoing embarrassment of &lt;a href="https://www.vox.com/2014/5/12/5703814/why-colleges-are-so-bad-at-handling-sexual-assault" rel="noopener noreferrer"&gt;sexual assault on college campuses&lt;/a&gt; and its abysmal handling. So with all that said: even if college might send you into the world SLIGHTLY more prepared for an entry level programming job, is it worth it? At the end of the day? For some people the answer is no, and for others it’s a moot point: they don’t have the money, they don’t have the time, and it was never in the cards for them.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;In closing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Where does this leave us? The prospect of learning challenging material with no direction is somewhat bleak.&lt;/p&gt;

&lt;p&gt;If I had it all to do again and had known about these options, I might have turned to something like the &lt;a href="https://github.com/ossu/computer-science" rel="noopener noreferrer"&gt;Open Source Software Degree&lt;/a&gt; or a new development, one I have my eye on as potentially the most promising revolution in software engineering education that I've heard of: the Free Code Camp accredited, &lt;a href="https://www.freecodecamp.org/news/free-accredited-bachelors-degrees-in-computer-science-how-do-we-get-there/" rel="noopener noreferrer"&gt;free(!) computer science degree&lt;/a&gt;. I think if supplemented with learning groups like I've found on Slack communities, an option like this when combined with community could likely do as good of a job as the path I wound up taking.&lt;/p&gt;

&lt;p&gt;If I can ask anything of anyone, after this absurdly long diatribe on this topic, it would be to realize that people's lives are messy and unpredictable. The same options are not realistically available to everyone. When compared side by side, the amount of instruction in a bootcamp vs a degree is not actually all that different, and there is nothing about degrees or the people who get them that is inherently superior. &lt;strong&gt;I truly believe that if CS grads are coming out slightly ahead, it is a function of the degree having a longer duration and nothing else.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Take a moment to examine why you might feel so strongly about someone else's educational background when it doesn't hurt you either way. And overall, realize that people's capabilities are not neatly assessable through the lens of bootcamp vs degree vs self-taught.&lt;/p&gt;

</description>
      <category>career</category>
      <category>bootcamps</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Negotiation Advice From a Former Recruiter</title>
      <dc:creator>JTK</dc:creator>
      <pubDate>Fri, 11 Feb 2022 21:39:15 +0000</pubDate>
      <link>https://dev.to/heyjtk/negotiation-advice-from-a-former-recruiter-83g</link>
      <guid>https://dev.to/heyjtk/negotiation-advice-from-a-former-recruiter-83g</guid>
      <description>&lt;p&gt;Something I enjoy - A LOT - is helping people negotiate, particularly for software engineering jobs, particularly if they are early-career or coming from a different background. To people in other fields, or new to this field, some of the stories I have from negotiating software engineering jobs sound made up. &lt;em&gt;You got &lt;strong&gt;what&lt;/strong&gt;!? They offer what kind of signing bonus!? They're paying &lt;strong&gt;what&lt;/strong&gt; to mid-level people!???&lt;/em&gt; I personally am of the belief that the boom times will not last forever, so I try to encourage people to seize the moment of the &lt;a href="https://www.forbes.com/sites/forbestechcouncil/2021/04/13/analyzing-the-software-engineer-shortage/?sh=5c1c2fbe321c" rel="noopener noreferrer"&gt;particularly competitive&lt;/a&gt; job market we find ourselves in. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;As a disclaimer, I live in the US and that's also where I recruited except for one weird assignment in the Kingdom of Bahrain. Other countries are of course, different with different markets/salaries than what I may mention.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part I: Get Your Mind Right
&lt;/h2&gt;

&lt;p&gt;Your &lt;strong&gt;negotiation stance&lt;/strong&gt; is &lt;strong&gt;a collection of beliefs, behaviors, and boundaries&lt;/strong&gt; that starts far before you have received a job offer. Sometimes I see new people say "I'm open ended on salary for my first job, I really just need the experience". &lt;/p&gt;

&lt;p&gt;They aren't wrong - a single year of experience in software engineering can be leveraged almost immediately into a 10, 20, 30k raise, perhaps more. But this approach is still slightly flawed.&lt;/p&gt;

&lt;p&gt;It is good to have some flexibility if the ends justify the means. But I encourage you not to limit yourself here. The biggest reason for that is that &lt;em&gt;you are negotiating not just for current you, but future you&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Scenario: you get offered a really great position at a very entry level salary. You join and it is everything you wanted, your skills grow phenomenally and you love the org and team. But within one year, that entry level salary adjusted 3% for cost of living is far beneath your skills. It is too irresistible to leave 20k plus on the table, so you leave after a year although you'd have liked to stay.&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Negotiating aggressively is betting on yourself, and how much your new job will be a great fit for you for a long time. You owe it to yourself to set the tone with a salary you'd be happy with for a long while.&lt;/p&gt;

&lt;p&gt;This is not limited to new people. I also see experienced people who have stayed with an employer say, the past five years vastly underestimate how much salaries have exploded over the past couple of years. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you go into the job hunt with an undefined sense of what you should aim for, someone else will try to define it for you.&lt;/strong&gt; What's worse, sometimes a sense of "sunk cost fallacy" will mean we go farther in interview processes than we should even though our spider-sense tells us this job may not be right. Defining your salary goal and your hard limits as part of your negotiation mindset up front can save you a lot of interviews, and who likes those! &lt;/p&gt;

&lt;h2&gt;
  
  
  Part II: Things to Figure Out Way Before the Offer
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Average and stretch goal salary:&lt;/strong&gt; anecdata, a lot of people I know job hunting in 2021 were starting from about 125 base, hoping for 150 and with a stretch goal of 180. The collective experience of people I know in that boat was that getting to 160 was surprisingly doable, and that everyone was giving out signing bonuses like candy. Some of these conversations happened in developer communities, and I have no doubt people on the sidelines at 125 that had been seeking 145 adjusted accordingly based on what they heard.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefit hard limits&lt;/strong&gt;: I fell into this trap at one point. Entertained a role with under three weeks PTO. The farther I got into the process, the more I realized that amount of PTO worried me, especially in the time of COVID. It wound up being a dealbreaker. I honestly wasted everyone's time and went through a lot of stressful interviews I could have skipped by not knowing that limit sooner&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tech stack hard limits&lt;/strong&gt;: Another one I speak from from experience. I would have not thought this mattered to me, but at a certain point I realized I didn't want to walk away from Python and start over with something else&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interview hard limits:&lt;/strong&gt; Is this related to negotiation? Technically yes. It makes perfect sense to be willing to do a &lt;em&gt;stupid&lt;/em&gt; amount of interviews to make Google money, but otherwise nope out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your &lt;em&gt;real&lt;/em&gt; current comp value&lt;/strong&gt;: Consider that imaginary tech workers Joe and Sarah both make 200k. Joe has three weeks vacation while Sarah has six. Sarah is actually in the grand scheme of things compensated annually ~$11,640 more than Joe for her time. Does your work have a tuition program? 401k match? Commuter benefits? &lt;em&gt;If you need a nudge to ask for a big scary number, sit down and consider EVERYTHING you currently have&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where the Job Lands:&lt;/strong&gt; Before you even get to the negotiation stage, you want a reasonable assurance that the negotiation could result in an offer you'd take. So that means getting baseline information on comp, benefits, and other hard-line items like (for example) remote work if that's important to you. &lt;/p&gt;

&lt;h2&gt;
  
  
  Part III: Negotiation Time
&lt;/h2&gt;

&lt;p&gt;Negotiation is not a one time event. If you think about it (not to get too meta) life is a series of negotiations. We are constantly negotiating the place we hold in the world and how people treat us. &lt;/p&gt;

&lt;p&gt;People are trained to think that a job is something you compete for, that employers have the power in the equation. Or if people don't think that, they think that power in negotiation comes from competing offers only, and otherwise they don't have much leverage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not true!&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;I once heard it said that in romantic relationships, whoever is more willing to leave has more power. The same is true for negotiation. So your power in negotiation can come from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Willingness to stay at your current job until the right thing comes along&lt;/li&gt;
&lt;li&gt;Willingness to leave a current job and job-hunt full time if you are underpaid and they won't approve a raise &lt;/li&gt;
&lt;li&gt;In demand skill set &lt;/li&gt;
&lt;li&gt;Knowledge that the market is tight &lt;/li&gt;
&lt;li&gt;Awareness that the role you are being offered has been unfilled for a while &lt;/li&gt;
&lt;li&gt;Niche domain knowledge &lt;/li&gt;
&lt;li&gt;Willingness to &lt;strong&gt;say no&lt;/strong&gt;, no matter what &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I encourage you to say no early and often. No to interview processes that are long and arduous if you don't know if the pay is worth it. No to recruiter conversations if they won't reveal the pay range or benefits. You are never obligated to finish an interview process just because you started it. &lt;/p&gt;

&lt;h3&gt;
  
  
  Talking Early Numbers
&lt;/h3&gt;

&lt;p&gt;Companies are all over the map in terms of talking salary. I've seen recruiters send me the range in the very first cold email, I've had people who would have me pry the information out of their cold dead fingers only after I'd signed my life away. It can be hard to develop a consistent system of salary boundaries when recruiters are so all over the place. Below is my advice for some common pit-stops in the early negotiation process.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Applicant system where salary is a required field:&lt;/strong&gt; Put 0 or n/a depending on what the form allows. Nice try recruiters! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First Call/Desired Salary:&lt;/strong&gt; Much like jobseekers are trained not to give away numbers, some recruiters are too. Some will say they are flexible for the right person, or pay "market rate", or that the pay depends on where you fall in the company leveling guide, which they can only tell you after more interviews. In &lt;em&gt;general&lt;/em&gt; it is worthwhile to play this game, using phrases like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"I can be a little flexible for the right role, but could I ask the general budget?" &lt;/li&gt;
&lt;li&gt;"I've honestly been seeing ranges all over the place in my current job search and it is going to depend a little bit on the total benefit and comp package. Can you tell me anything about that?" &lt;/li&gt;
&lt;li&gt;"You know, I just started my job hunt and haven't really had a chance to crunch the numbers on the going rate for my experience. If you have an idea for this role though I can work on that and get back to you with something firm" &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is possible to be completely likeable while denying the recruiter the information that they want. Don't feel bad, they're used to it. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First Call/Current Salary:&lt;/strong&gt; For starters, be aware if your state &lt;a href="https://www.smithhanley.com/2021/03/04/salary-history-questions-legal/" rel="noopener noreferrer"&gt;prevents this question&lt;/a&gt; being asked. But don't fret, even if you aren't in one of those states we aren't going to answer. My personal favorite is to say "I think that comp details are actually covered by my NDA" (Non-Disclosure Agreement). Totally out of your hands! Some people will share things like that they currently are underleveled and are changing roles to get a salary more in alignment with their expertise. To me, that's overkill, and shares that you may be in a vulnerable negotiating position as you are currently underpaid. My advice, is keep it simple, and make a third party (NDA) the bad guy in why you can't share the information. Others will advise you to answer "I'm not really comfortable discussing it". I like that answer less, because it's a job hunt - obviously money will come up. It seems disingenuous, and imo less like you are interested in cooperating with them. Maybe I'm splitting hairs, but that's my honest opinion. &lt;/p&gt;

&lt;h3&gt;
  
  
  Verbal Offer Stage
&lt;/h3&gt;

&lt;p&gt;A lot of companies do this thing where they will want to get a baseline agreement on the numbers before drafting up an offer &lt;em&gt;letter&lt;/em&gt;. As someone who has had to edit zillions of offer letters after negotiations changed the base pay, I sympathize with this impulse. &lt;/p&gt;

&lt;p&gt;That being said, if you are wondering when to start negotiating &lt;strong&gt;hard&lt;/strong&gt;, verbal offer is a great time! And also a dangerous one. &lt;/p&gt;

&lt;p&gt;Dangerous, because sometimes the details of the verbal offer miss critical information, or in your excitement it is hard to keep the details you are being told straight. Two examples from my own life of verbal negotiation misfires:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I once thought an offer included stock grants instead of stock options - one would have been &lt;em&gt;free&lt;/em&gt; stock, the other is just an agreement to let me &lt;em&gt;buy&lt;/em&gt; stock
&lt;/li&gt;
&lt;li&gt;I once named my asking salary as 1-1-5 (verbally) and I think the recruiter misheard because the offer came back at 1-5-5 (not kidding!) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Takeaway&lt;/strong&gt;: get the written offer as soon as you can. It is fine to say "So far this is sounding reasonable but I will want to see everything in writing". If there is one thing you read about negotiation (other than this post, of course) it should be this &lt;a href="https://haseebq.com/my-ten-rules-for-negotiating-a-job-offer/" rel="noopener noreferrer"&gt;fabulous article&lt;/a&gt;. The author, Haseeb Qureshi, says something to the effect of "not being the decision maker". I love this idea! I am single but I always borrow the line "let me run it all by my family". The recruiter just doesn't know that means my pitbull. &lt;/p&gt;

&lt;h3&gt;
  
  
  Written offer &amp;amp; getting to the finish line
&lt;/h3&gt;

&lt;p&gt;At this point, maybe you are sick of negotiation. You may have already negotiated several times just for this job! But hey, you're almost done. &lt;/p&gt;

&lt;p&gt;You might wonder, "How long/hard can I negotiate at the offer stage? Aren't things pretty final?" &lt;/p&gt;

&lt;p&gt;Well, let me tell you about a Project Manager candidate I was once responsible for recruiting. She managed to get something like 50k additional comp after negotiations were already down to the wire. (As the recruiter, it was SO STRESSFUL haha). So anything is possible. &lt;/p&gt;

&lt;p&gt;That said, to paraphrase the fabulous article I mentioned earlier, companies are motivated to negotiate by believing that you are &lt;em&gt;winnable&lt;/em&gt;. If you have too many "volleys" of back and forth, they may start to believe you are just leveraging them against another offer or not really interested in the role. &lt;strong&gt;If I had to give a completely random rule of thumb here, probably more than three volleys on the main stuff (base pay, stock, bonuses) may start to seem like you are not interested&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;You can save yourself some rounds of back and forth by making the first volley &lt;strong&gt;a significant ask&lt;/strong&gt;. There is something called the &lt;a href="https://www.pon.harvard.edu/daily/negotiation-skills-daily/the-drawbacks-of-goals/" rel="noopener noreferrer"&gt;anchoring effect&lt;/a&gt; which describes the phenomena that humans tend to be unduly influenced by early information. Basically in this scenario, it means that the point of reference becomes your negotiation point instead of theirs. They may be inclined to try to "split the difference". This is the most common response I saw in recruiting to negotiation. &lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We offer 85k, candidate asks for 100, we come back with 93 &lt;/li&gt;
&lt;li&gt;We offer 120k, candidates asks for 150, we come back with 135&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And on and on. So a big bold number here sets the stage for what "meeting in the middle" looks like. If you want a paraphrased version of what I usually say here, following the Habeeb article about being winnable, it is something like this:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;I'm incredibly excited about the idea of joining the team. I know that with my background in a and b, I can make an immediate impact on projects d, e and f. I'm confident that we can find something that works for everyone, but because I am looking at multiple offers I wanted to know if x is possible. If the pay could be x, I can sign on immediately.&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Why those elements? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Communicate that I'm winnable&lt;/li&gt;
&lt;li&gt;Remind them of the value they see in me&lt;/li&gt;
&lt;li&gt;Take the adversarial element of negotiation away by reminding them you are motivated to find something mutually beneficial ("works for everyone") &lt;/li&gt;
&lt;li&gt;Give them a specific end state ("could sign on immediately")&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And boom! That's it. Cradle to grave, that's how I approach negotiation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotchas and special cases
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q) What if the place has strict salary bands?&lt;br&gt;
A) Some places really do, some don't. Still negotiate.&lt;/strong&gt; Unfortunately, I have heard of numerous cases where people are told this to find out exceptions can be made but just weren't for them. Also, you can sometimes negotiate to be brought in at a higher title. I saw this happen &lt;strong&gt;all the time&lt;/strong&gt; as a recruiter. No joke.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q) What if the place says they don't negotiate? &lt;br&gt;
A) Same answer as above&lt;/strong&gt;, sometimes that is entirely made up. If they stick to it, it is your call whether it is worth proceeding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q) Can I negotiate other things than salary? &lt;br&gt;
A) YES!&lt;/strong&gt; You can also negotiate an earlier time to revisit your salary than annually if it is lower than you want. While you can negotiate things like conference budget, bonuses, etc there are certain things that are harder than others. Many companies I know do not vary on PTO. It is difficult to track if it is irregular between employees and could cause resentment if it came to light that someone got more. &lt;/p&gt;

&lt;p&gt;Another one I would get asked a lot by veterans was if salary could be increased if they don't need healthcare. Usually, the answer is no since if someone changed their mind at any time, the workplace still would be on the hook to provide healthcare.&lt;/p&gt;

&lt;p&gt;Aside from those two items, the sky is the limit though! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q) Can my offer be revoked for negotiating?&lt;br&gt;
A) Actually...yes.&lt;/strong&gt; There is actually a lot of bad information out there on this. People say "Oh that never happens!" as if it is that simple. &lt;/p&gt;

&lt;p&gt;It has happened - to me. After being a recruiter for years. So not someone approaching the negotiation in an insulting way, naturally. I know other people it has happened to. Most all of them were part underrepresented groups in tech.  &lt;/p&gt;

&lt;p&gt;The bottom line here is &lt;strong&gt;yes sometimes it happens although it is very rare&lt;/strong&gt;, but it is not something that you should let stop you from negotiating. As upsetting as it is when it happens, it is a blessing - it is the reddest of red flags about that org. Run, do not walk away from that place. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q) What if neither party budges in the game of don't-name-a-number chicken?&lt;br&gt;
A) I tend to throw out a ridiculous number to get them to talk&lt;/strong&gt;, bonus points for a bafflingly huge range. It usually gets a reaction out of them but also doesn't give much information away. Example: you expect the job to pay 60k, but the recruiter and you keep going back and forth in the won't-name-a-number dance. Eventually you give up and say "I'm seeing 80-120 for these types of roles". The recruiter will likely balk and blurt out something that tells you where they are out of surprise. &lt;/p&gt;

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

&lt;p&gt;So that's it! That's just about everything I would want someone to know when approaching negotiation. If I can encourage you to do anything it is to make yourself comfortable with the process, whether using any of my tips helps you feel prepared or reading from other sources does. It doesn't have to be adversarial, it can be something really positive, and it certainly shouldn't be built up to be this magical thing only certain people can do. Go forth and negotiate! &lt;/p&gt;

&lt;p&gt;And if I missed any Q &amp;amp; A topics you would like covered, feel free to drop them in the comments and I may add them to the post. &lt;/p&gt;

</description>
      <category>jobsearch</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Vue vs. Svelte vs. React</title>
      <dc:creator>JTK</dc:creator>
      <pubDate>Fri, 28 Jan 2022 21:25:31 +0000</pubDate>
      <link>https://dev.to/heyjtk/vue-vs-svelte-vs-react-3l31</link>
      <guid>https://dev.to/heyjtk/vue-vs-svelte-vs-react-3l31</guid>
      <description>&lt;p&gt;For those of us who don’t get to work with frontend technologies, it can be hard to stay up to speed on the latest &amp;amp; greatest developments with JavaScript frameworks. For this reason, today we are going to explore two very popular frameworks, Vue and React, as well as a newer one I’ve heard great things about: Svelte. &lt;/p&gt;

&lt;p&gt;In this post, I'm going to walk us through a side-by-side comparison of a Hello &lt;del&gt;World&lt;/del&gt; Fauna app, built in each React, Vue, and Svelte. By running through the same core tasks and building the same end product, we will get to examine these tools in contrast.&lt;/p&gt;

&lt;p&gt;In each, we’ll retrieve some data about Pokemon from Fauna and display it like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzxhsfl86d1rsvyl5awx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzxhsfl86d1rsvyl5awx.png" alt="Image of a pokemon gallery" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After building each, we’ll take a ten-thousand foot view of each framework’s developer experience and my observations on them as a Backend Engineer. Let’s get started!&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting set up with Fauna
&lt;/h3&gt;

&lt;p&gt;After playing with the Fauna GUI and CLI, I found the CLI a bit more to my taste, so that’s what I’ll be using here. You can get it on *nix machines with NodeJS/NPM installed by running &lt;code&gt;npm i -g fauna-shell&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt; &lt;span class="nx"&gt;fauna&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;shell&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;faunadb&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;4&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;4.1&lt;/span&gt; &lt;span class="nx"&gt;postinstall&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Cellar&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;17.3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;fauna&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;shell&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;faunadb&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;printReleaseNotes&lt;/span&gt;

&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;fauna&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;13.0&lt;/span&gt;
&lt;span class="nx"&gt;added&lt;/span&gt; &lt;span class="mi"&gt;325&lt;/span&gt; &lt;span class="nx"&gt;packages&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="mi"&gt;242&lt;/span&gt; &lt;span class="nx"&gt;contributors&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mf"&gt;27.304&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are following along it is at this point that you'd want to head to &lt;a href="https://fauna.com/" rel="noopener noreferrer"&gt;Fauna's site&lt;/a&gt; and make an account. Quick heads up: if you’re going to use the CLI, don’t use an SSO option when you make your account. The CLI isn't set up to work with that authentication. I also built us some &lt;a href="https://github.com/jtkaufman737/vue-faunadb/tree/boilerplate" rel="noopener noreferrer"&gt;boilerplate code&lt;/a&gt; for a Vue project, so if you want to follow along clone the repo and start with &lt;code&gt;origin/boilerplate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Returning to the command line, let's get into our Vue project and create our database, first by logging in with the Fauna CLI. You’ll go through a process a bit like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="err"&gt;➜&lt;/span&gt; &lt;span class="nx"&gt;fauna&lt;/span&gt; &lt;span class="nx"&gt;cloud&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;
&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt; &lt;span class="nx"&gt;alias&lt;/span&gt; &lt;span class="nf"&gt;prefix &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;combine&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;cloud&lt;/span&gt;
&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt; &lt;span class="nx"&gt;alias&lt;/span&gt; &lt;span class="nx"&gt;already&lt;/span&gt; &lt;span class="nx"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Overwrite&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Yes&lt;/span&gt;
&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;How&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;prefer&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Email&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;Password&lt;/span&gt;
&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Email&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jtkaufman737&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;gmail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;com&lt;/span&gt;
&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Endpoints&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Would&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;like&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nx"&gt;one&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;them&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Keep&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cloud-us&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;
&lt;span class="nx"&gt;Endpoint&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cloud-us&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, let’s create our database and an API key. &lt;strong&gt;Keep your secret key private&lt;/strong&gt; and be sure to mark it down somewhere as we will use it later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="nx"&gt;fauna&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt;
&lt;span class="nx"&gt;creating&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt;

  &lt;span class="nx"&gt;created&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt;

  &lt;span class="nx"&gt;To&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;shell&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;your&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

  &lt;span class="nx"&gt;fauna&lt;/span&gt; &lt;span class="nx"&gt;shell&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt;

  &lt;span class="nx"&gt;Or&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;application&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;your&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

  &lt;span class="nx"&gt;fauna&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt;

&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="nx"&gt;fauna&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt;
&lt;span class="nx"&gt;creating&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pokemon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

  &lt;span class="nx"&gt;created&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pokemon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
  &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;xxxx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;xxxxxx&lt;/span&gt;

  &lt;span class="nx"&gt;To&lt;/span&gt; &lt;span class="nx"&gt;access&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pokemon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="nx"&gt;using&lt;/span&gt;
  &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;driver&lt;/span&gt; &lt;span class="nx"&gt;library&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;your&lt;/span&gt; &lt;span class="nx"&gt;language&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;choice&lt;/span&gt; &lt;span class="nx"&gt;using&lt;/span&gt;
  &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;above&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  An important note before we move on
&lt;/h3&gt;

&lt;p&gt;This is a very simple &lt;code&gt;HelloWorld&lt;/code&gt; type exploration of three frameworks, and as such not how we would use any of these tools per se in the real world. We are going to let our JS code call the database directly, picking up credentials from local &lt;code&gt;.env&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;As such, if you follow along you should not &lt;strong&gt;deploy&lt;/strong&gt; this code, since the secret picked up will get built with the other static assets, making your secret visible if someone were to visit the web page. &lt;/p&gt;

&lt;p&gt;If you do want to turn any of these demos into a larger project, tools like &lt;a href="https://docs.netlify.com/configure-builds/environment-variables/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; and &lt;a href="https://vercel.com/docs/concepts/projects/environment-variables" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; have great options for how to deal with environment variables, or the database response could be returned through an API and server-side code. &lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started with Vue
&lt;/h3&gt;

&lt;p&gt;If you are familiar with modern single page apps, even if you haven’t worked with Vue, our project structure may seem somewhat familiar. You’ll notice that &lt;code&gt;src/&lt;/code&gt; contains the files we’d actively work on.&lt;/p&gt;

&lt;p&gt;A typical Vue project can contain elements that have been removed from the boilerplate code we’ll use here, which was done to keep things extremely simple and make comparison between Vue, Svelte, and React easier and clearer.&lt;/p&gt;

&lt;p&gt;With that in mind, our main active files are going to be &lt;code&gt;App.vue&lt;/code&gt; and &lt;code&gt;main.js&lt;/code&gt;. Let’s also add a &lt;code&gt;data.json&lt;/code&gt; file to seed our database with some records.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// data.json &lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bulbasaur&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://i.imgur.com/e7VtLbo.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pikachu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://i.imgur.com/fmMERCo.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Snorlax&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://i.imgur.com/TGf6qB8.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Caterpie&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://i.imgur.com/A21Gpql.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jigglypuff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://i.imgur.com/SU7yF1f.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Abra&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://i.imgur.com/f59APqT.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Weedle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://i.imgur.com/XDeqSAB.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dratini&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://i.imgur.com/K9DxFvF.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Charmander&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://i.imgur.com/KuZEzvo.png&lt;/span&gt;&lt;span class="dl"&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 Fauna CLI lets us easily import either JSON or CSV data to our new collection. Let’s import our new data.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="nx"&gt;fauna&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;pokemon&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;pokemon&lt;/span&gt;
&lt;span class="nx"&gt;Database&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pokemon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt; &lt;span class="nx"&gt;established&lt;/span&gt;
&lt;span class="nx"&gt;Start&lt;/span&gt; &lt;span class="nx"&gt;importing&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;
&lt;span class="nx"&gt;Average&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="mi"&gt;113&lt;/span&gt; &lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Imports&lt;/span&gt; &lt;span class="nx"&gt;running&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="nx"&gt;parallel&lt;/span&gt; &lt;span class="nx"&gt;requests&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="nx"&gt;documents&lt;/span&gt; &lt;span class="nx"&gt;imported&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt;
 &lt;span class="err"&gt;›&lt;/span&gt;   &lt;span class="nx"&gt;Success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Import&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt; &lt;span class="nx"&gt;completed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can confirm our records have made it up to the database by visiting our Fauna dashboard and drilling down into the right collection:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhl1y9yt6ogydanywvqvx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhl1y9yt6ogydanywvqvx.png" alt="FaunaDB dashboard lists out our collection records" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, let’s connect our Vue app to the database using Fauna’s JavaScript driver. We’ll take the API secret that we wrote down from earlier and add it to a &lt;code&gt;.env&lt;/code&gt; file - for Vue apps, anything prefixed with &lt;code&gt;VUE_APP&lt;/code&gt; gets seamlessly picked up by the application so our &lt;code&gt;.env&lt;/code&gt; file will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// .env &lt;/span&gt;
&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;VUE_APP_FAUNADB_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;xxxx&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ll then move over to &lt;code&gt;main.js&lt;/code&gt; and run through our main logic. Here are the general steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Import Fauna&lt;/li&gt;
&lt;li&gt;Use a constructor function to create a new database instance&lt;/li&gt;
&lt;li&gt;Bind that instance to the application
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.js &lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Vue&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;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&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;./App.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;faunadb&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;faunadb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// This constructor creates a new database instance, and supplying the secret&lt;/span&gt;
&lt;span class="c1"&gt;// authenticates us &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;faunadb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&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;VUE_APP_FAUNADB_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;db.us.fauna.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productionTip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="c1"&gt;// binding $db and $q means our database instance and query commands &lt;/span&gt;
&lt;span class="c1"&gt;// are easily accessible from here on out anywhere in our Vue code &lt;/span&gt;
&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;
&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;faunadb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&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="nf"&gt;$mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s the fun part: Vue’s basic unit of functionality is a Single File Component - split into a &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tag for our markup, a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag containing our JavaScript functions and logic, and optionally a &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tag for our CSS.&lt;/p&gt;

&lt;p&gt;Let’s start with our &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;. We are going to deal with a few handy tools Vue gives us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;data&lt;/code&gt; is an object for storing easily accessible values local to our component. We will start it with an empty array and fill it with Pokemon from Fauna.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;methods&lt;/code&gt; is an object whose properties can be functions for any behavior we want - here, we will call our database and get our records.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lifecycle methods&lt;/code&gt; are special events you can attach to behavior in Vue. I have arbitrarily chosen the moment our component is mounted to trigger the method call to Fauna. There are more lifecycle events than that, but let’s keep it simple today.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// App.vue 

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// data = our local component data, will be filled with  &lt;/span&gt;
  &lt;span class="c1"&gt;// pokemon later &lt;/span&gt;
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;pokemon&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="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// our fetchPokemon method calls fauna, then updates  &lt;/span&gt;
    &lt;span class="c1"&gt;// data.pokemon &lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;fetchPokemon&lt;/span&gt;&lt;span class="p"&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;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$q&lt;/span&gt; 
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Paginate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pokemon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt;
          &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Lambda&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt; 
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pokemon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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;// this lifecycle method is what kicks off the &lt;/span&gt;
  &lt;span class="c1"&gt;// fetchPokemon() function running&lt;/span&gt;
  &lt;span class="nf"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchPokemon&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="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My favorite part of Vue is the concise shorthand it offers to dynamically generate HTML based on component data. I’m going to make use of it here by leveraging a Vue construct called &lt;code&gt;v-for&lt;/code&gt; to iterate over our array of Pokemon. It’ll look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.vue &lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"home"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Pokemon&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"grid"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;!--&lt;/span&gt; 
             &lt;span class="na"&gt;v-for&lt;/span&gt; &lt;span class="na"&gt;iterates&lt;/span&gt; &lt;span class="na"&gt;over&lt;/span&gt; &lt;span class="na"&gt;pokemon&lt;/span&gt; &lt;span class="na"&gt;array&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt; &lt;span class="na"&gt;loads&lt;/span&gt; &lt;span class="na"&gt;the&lt;/span&gt; 
             &lt;span class="na"&gt;javascript&lt;/span&gt; &lt;span class="na"&gt;object&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;src&lt;/span&gt; &lt;span class="na"&gt;loads&lt;/span&gt; &lt;span class="na"&gt;the&lt;/span&gt;
             &lt;span class="na"&gt;Pokemon&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt; &lt;span class="na"&gt;each&lt;/span&gt;
             &lt;span class="na"&gt;array&lt;/span&gt; &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;so&lt;/span&gt; &lt;span class="na"&gt;on&lt;/span&gt; &lt;span class="na"&gt;and&lt;/span&gt; &lt;span class="na"&gt;so&lt;/span&gt; &lt;span class="na"&gt;forth&lt;/span&gt; 
          &lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt; &lt;span class="na"&gt;v-for&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"p in pokemon"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"p.id"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h6&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h6&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; 
             &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"p.imageUrl"&lt;/span&gt; 
             &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"p.name"&lt;/span&gt;  
             &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"pokemon"&lt;/span&gt;
           &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See the colon before a few of those HTML attributes? That lets Vue know that the attribute values aren’t strings, they’re dynamic JavaScript values based on the &lt;code&gt;p&lt;/code&gt; variable we defined in the &lt;code&gt;v-for&lt;/code&gt; shorthand. We also get to use those JavaScript values inside double brackets to interpolate into the content of the HTML tags — here that’s used to display the Pokemon names.&lt;/p&gt;

&lt;p&gt;Last but not least, I hacked together some CSS that will be used (with minor edits) throughout each demo app. It’s not absolutely necessary, but we want these components to look good, so here it is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.vue &lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Inter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sans&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;webkit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;smoothing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;antialiased&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;moz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;osx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;smoothing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;grayscale&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;c3e50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;h5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;h6&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;acumin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;pro&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;sans&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;h3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;h6&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.25&lt;/span&gt;&lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:.&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt; &lt;span class="nx"&gt;lightgray&lt;/span&gt; &lt;span class="nx"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;linear&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nf"&gt;gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="nx"&gt;deg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;F00A5&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;813&lt;/span&gt;&lt;span class="nx"&gt;EEF&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;justify&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;space&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;around&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;align&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;F00A5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nl"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;813&lt;/span&gt;&lt;span class="nx"&gt;EEF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;home&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;section&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;33.33&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mf"&gt;33.33&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mf"&gt;33.33&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pokemon&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With all that in place, let’s return to the command line and kick off a local build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="nx"&gt;serve&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;vue&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;faunadb&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="nx"&gt;serve&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;jkaufman&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Code&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;vue&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;faunadb&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;vue&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="nx"&gt;serveDONE&lt;/span&gt;  &lt;span class="nx"&gt;Compiled&lt;/span&gt; &lt;span class="nx"&gt;successfully&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;97&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;                                                                                            &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt; &lt;span class="nx"&gt;AM&lt;/span&gt;

  &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="nx"&gt;running&lt;/span&gt; &lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Local&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:8082/ &lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//192.168.58.105:8082/&lt;/span&gt;

  &lt;span class="nx"&gt;Note&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;development&lt;/span&gt; &lt;span class="nx"&gt;build&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;optimized&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
  &lt;span class="nx"&gt;To&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;production&lt;/span&gt; &lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="nx"&gt;yarn&lt;/span&gt; &lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voila! if you return to &lt;code&gt;localhost:8080&lt;/code&gt; you will be able to see our Vue app displaying the Pokemon gallery shown earlier in all its glory. With that out of the way, let’s do the same with some other tools! &lt;/p&gt;

&lt;h3&gt;
  
  
  Recreating the app in React
&lt;/h3&gt;

&lt;p&gt;React is the most popular web framework out there (or so it has seemed to me for a while), so it’s much more likely you’re familiar with how it works. Let’s try to reconstruct this application and see the differences between Vue and React. If you’re following along, pop over to &lt;a href="https://github.com/jtkaufman737/react-faunadb/tree/boilerplate" rel="noopener noreferrer"&gt;this repo&lt;/a&gt; and grab the latest from &lt;code&gt;origin/boilerplate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For those familiar with React, you will again notice that I’ve stripped out a lot - some of the files are outside the scope of this article and would just cloud the fundamental comparison of these frameworks.&lt;/p&gt;

&lt;p&gt;We’ll run through the same logic, although this time in &lt;code&gt;index.js&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Import Fauna&lt;/li&gt;
&lt;li&gt;Use a constructor function to create a new database instance&lt;/li&gt;
&lt;li&gt;Bind that instance to the application
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// index.js &lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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;react&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="nx"&gt;ReactDOM&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;react-dom&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="nx"&gt;App&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;./App&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="nx"&gt;faunadb&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;faunadb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// create database connection/instance through constructor &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;faunadb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&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;REACT_APP_FAUNADB_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;db.us.fauna.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; 
        &lt;span class="c1"&gt;// For react, we're going to bind the database instance &lt;/span&gt;
        &lt;span class="c1"&gt;// and query functionality as props &lt;/span&gt;
      &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;q&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;faunadb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&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;In our new React app, let’s go to &lt;code&gt;.env&lt;/code&gt; file and add our Fauna secret — this time using a React specific prefix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// .env &lt;/span&gt;
&lt;span class="nx"&gt;REACT_APP_FAUNADB_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;xxxxx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our last piece of business here will be some work in &lt;code&gt;App.js&lt;/code&gt;.  We will need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create methods to call Fauna and access our list of Pokemon.&lt;/li&gt;
&lt;li&gt;Iterate over the data and display it through dynamically generated markup.&lt;/li&gt;
&lt;li&gt;We will use &lt;code&gt;useEffect&lt;/code&gt; and &lt;code&gt;useState&lt;/code&gt; instead of lifecycle methods to trigger our API call. This is because React doesn’t have lifecycle methods, which is something I miss coming from Vue — more on that later.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.css&lt;/span&gt;&lt;span class="dl"&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;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPokemon&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;

  &lt;span class="c1"&gt;// use effect means this will fire on render&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&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;// this function uses our props for the database and Fauna query capabilities&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchPokemon&lt;/span&gt;&lt;span class="p"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Paginate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pokemon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt;
          &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Lambda&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;updatedPokemon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;

      &lt;span class="nf"&gt;setPokemon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedPokemon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;fetchPokemon&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;


  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"home"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Pokemon&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"grid"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// without v-for like in Vue, we instead use vanilla JS &lt;/span&gt;
            &lt;span class="c1"&gt;// to get the iteration over our data &lt;/span&gt;
            &lt;span class="nx"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="c1"&gt;// all dynamic JS values in React are expressed as {x}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h6&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h6&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"pokemon"&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
          &lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let it rip with an &lt;code&gt;npm run start&lt;/code&gt;, and you should see a perfect replica of the app we created with Vue running on &lt;code&gt;localhost:3000&lt;/code&gt;. Again, a pretty seamless experience to get a simple application prototype running. &lt;/p&gt;

&lt;p&gt;Last but not least, we are going to do the same again, with one final tool. &lt;/p&gt;

&lt;h3&gt;
  
  
  Recreating the app in Svelte
&lt;/h3&gt;

&lt;p&gt;I was honestly very excited for this one because I have been primarily a backend developer for quite a while, and as a result, I’ve had fewer opportunities than I’d like to play with the newest JavaScript stuff. Svelte has sounded interesting for a long time and I was happy to finally get to give it a whirl. &lt;/p&gt;

&lt;p&gt;As before, grab the &lt;a href="https://github.com/jtkaufman737/svelte-faunadb/tree/boilerplate" rel="noopener noreferrer"&gt;boilerplate code&lt;/a&gt; and checkout to &lt;code&gt;origin/boilerplate&lt;/code&gt; if you’re following along. You know the drill at this point: step one is sticking Fauna in our entry point JS file (which is &lt;code&gt;main.js&lt;/code&gt; here). Here’s how we tackle it in Svelte:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&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;./App.svelte&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="nx"&gt;faunadb&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;faunadb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// create db instance through constructor, secret for authentication&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;faunadb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&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;SVELTE_APP_FAUNADB_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;db.us.fauna.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;app&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;App&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// to make the db and query functionality available widely, we are &lt;/span&gt;
    &lt;span class="c1"&gt;// going to pass them as props in the main application instance&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;q&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faunadb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll want to remember to make an equivalent &lt;code&gt;.env&lt;/code&gt; file here too of course.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// .env &lt;/span&gt;

&lt;span class="nx"&gt;SVELTE_APP_FAUNADB_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;xxxx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main &lt;code&gt;App.svelte&lt;/code&gt; file reminds me a lot of Vue, sectioned out for different functional areas by default. Take a look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.svelte &lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s where it gets interesting. Svelte, like Vue, supports special shorthand iteration operations in its markup. For Svelte, these are denoted both with characters and keywords — for instance, &lt;code&gt;{#each /}&lt;/code&gt; will allow us to iterate over an array. We also get lifecycle methods back, and can tie our API call to component mounting. The expression of &lt;code&gt;{#each /}&lt;/code&gt; to me was particularly fascinating. It reminds me — visually speaking — more of templating methods in Rails or Django than the equivalent version of this functionality in React or Vue. There’s nothing wrong with that; it feels natural to me. &lt;/p&gt;

&lt;p&gt;In &lt;code&gt;App.svelte&lt;/code&gt;, next we’ll register the “on mount” behavior, a method containing our database call, and the iteration and display of the results in markup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.svelte &lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    import &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onMount&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt; from "svelte"; // Yay lifecycle methods! 

    let pokemon = [];
    // the double $$ is also visually interesting, maybe not what I'd expect
    // to signify accessing props, but nothing wrong with it either 
    const db = $$props.db; 
    const q = $$props.q;

    // method to grab our pokemon records 
    onMount(async () =&amp;gt; &lt;span class="si"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Paginate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pokemon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt;
                &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Lambda&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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="nx"&gt;pokemon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="si"&gt;}&lt;/span&gt;)
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"home"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Pokemon&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"grid"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;!--&lt;/span&gt; &lt;span class="na"&gt;here&lt;/span&gt; &lt;span class="na"&gt;starts&lt;/span&gt; &lt;span class="na"&gt;our&lt;/span&gt; &lt;span class="na"&gt;interesting&lt;/span&gt; &lt;span class="na"&gt;loop&lt;/span&gt; &lt;span class="na"&gt;block&lt;/span&gt; &lt;span class="na"&gt;syntax&lt;/span&gt; &lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 
           &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;!--&lt;/span&gt; &lt;span class="na"&gt;Like&lt;/span&gt; &lt;span class="na"&gt;React&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;dynamic&lt;/span&gt; &lt;span class="na"&gt;values&lt;/span&gt; &lt;span class="na"&gt;grabbed&lt;/span&gt; &lt;span class="na"&gt;and&lt;/span&gt; &lt;span class="na"&gt;expressed&lt;/span&gt; &lt;span class="na"&gt;with&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 
                  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h6&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h6&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"pokemon"&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/each&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/section&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, we can put the pedal to the medal with a &lt;code&gt;npm run dev&lt;/code&gt;. If you look at &lt;code&gt;localhost:5000&lt;/code&gt; you should again see a perfect replica of our Pokemon gallery, as pictured in the intro. &lt;/p&gt;

&lt;h3&gt;
  
  
  Comparison of these tools
&lt;/h3&gt;

&lt;p&gt;As someone who leans towards the backend but thoroughly understands frontend concepts, I think I have more of an objective wide-lens view of these JavaScript tools, which led to some interesting observations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All of these tools are simple enough for a backend developer like myself to jump in without much trouble. For example, I recall finding the class-based syntax React had at one point confusing to wade through. Being able to return to React and use functional components was great&lt;/li&gt;
&lt;li&gt;Svelte made a strong first impression on me as a long time Vue user. I liked it but could also imagine someone coming from React liking it. Having never touched it before, getting the markup and methods working took pretty much zero time for a rookie.&lt;/li&gt;
&lt;li&gt;The only area in which Svelte felt weak was in build configuration. Unlike Vue and React which by default utilize Webpack to build, bundle, and minimize code, Svelte uses another tool: &lt;a href="https://rollupjs.org/guide/en/" rel="noopener noreferrer"&gt;Rollup&lt;/a&gt;. Although I saved you from this experience in the tutorial, dealing with Rollup presented multiple hiccups that reminded me of the pre-Webpack-3 days of working with Single Page Apps, when extensive Webpack configuration was sometimes required. For anyone interested you can read more about these two tools &lt;a href="https://medium.com/webpack/webpack-and-rollup-the-same-but-different-a41ad427058c" rel="noopener noreferrer"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;On a related note, I did feel like the amount of time it took to figure out the standard method of passing Svelte environment variables felt surprisingly long. I would consider that an area to be improved upon - if a &lt;code&gt;.env&lt;/code&gt; file with &lt;code&gt;SVELTE_APP_VAR&lt;/code&gt; was plug and play (as it is for React or Vue) I would have been a much happier developer&lt;/li&gt;
&lt;li&gt;Both Svelte and React are by default stricter — I forgot that it is normal for your JavaScript build to scream at you about unused CSS classes. This is probably a positive, especially if you’re going to be building something for production in the long run&lt;/li&gt;
&lt;li&gt;Plenty of people prefer React because of fewer framework-isms, like Vue’s &lt;code&gt;v-for&lt;/code&gt; or Svelte’s &lt;code&gt;{#each /each}&lt;/code&gt; for dynamically generated markup. For me, they are intuitive enough that I like having the option, but I can see how they’d be confusing for many&lt;/li&gt;
&lt;li&gt;I also like Vue and Svelte’s component lifecycle methods. I find their names (&lt;code&gt;mounted&lt;/code&gt;, &lt;code&gt;onMounted&lt;/code&gt;) more intuitive than &lt;code&gt;useEffect&lt;/code&gt; in React. If I were new to JavaScript, I might expect something called &lt;code&gt;useEffect&lt;/code&gt; to be related to DOM behavior or something else&lt;/li&gt;
&lt;li&gt;If I had to make a decision for a personal project after this experience, I’d rank my favorites as Svelte first, then Vue, and lastly React. Svelte just gave me a warm and fuzzy feeling that puts it over the top for me, especially with all its potential&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The elephant in the room, of course, is that Svelte, uniquely, does not utilize a virtual DOM. &lt;a href="https://svelte.dev/blog/virtual-dom-is-pure-overhead" rel="noopener noreferrer"&gt;In their own words&lt;/a&gt;, Svelte cites the rationale for this as a way to get away from the overhead required to sync and compare the actual and virtual DOM. As someone with a utilitarian need for JS frameworks, I didn’t mind the virtual DOM when working with it, nor could I particularly think of ways I missed it playing with Svelte. Truthfully, that conversation doesn’t seem relevant until we’re building much larger apps with much more at stake if our performance starts to dip. I do find Svelte’s argument compelling, though, so I’ll definitely be following the large scale adoption of Svelte.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping Up
&lt;/h3&gt;

&lt;p&gt;I enjoyed building all three demo apps. React once felt very intimidating to me, but the move away from Redux and class based components has made it feel more intuitive. &lt;/p&gt;

&lt;p&gt;Vue is the only one of these technologies I have worked with significantly, ever since 2018. I continue to like it as a “mellow” tool, and it is a recurring comment I hear from other backend folks that Vue feels approachable to us. &lt;/p&gt;

&lt;p&gt;Svelte lived up to the hype, at least in this very minimal example! Although I have been a Vue person for years, I would strongly consider using Svelte instead on my next personal project based on my initial positive experience and wanting to learn more.&lt;/p&gt;

</description>
      <category>fauna</category>
      <category>svelte</category>
      <category>vue</category>
      <category>react</category>
    </item>
    <item>
      <title>Let's talk about Docker</title>
      <dc:creator>JTK</dc:creator>
      <pubDate>Sat, 15 Jan 2022 19:14:20 +0000</pubDate>
      <link>https://dev.to/heyjtk/lets-talk-about-docker-1fad</link>
      <guid>https://dev.to/heyjtk/lets-talk-about-docker-1fad</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is equal parts actually about Docker, and the hilarity of being a woman on the internet in tech.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Who knew anyone read my tweets
&lt;/h2&gt;

&lt;p&gt;It is funny to me that I would get any kind of attention on Twitter, I don't post for engagement, I barely write about tech, and I'm otherwise barely on social media at all. I post on FB every six or so months so my out of state relatives know I'm alive and that's about it.&lt;/p&gt;

&lt;p&gt;So I was certainly not expecting an offhand tweet complaining about Docker to get any kind of attention. &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1481652902913458184-963" src="https://platform.twitter.com/embed/Tweet.html?id=1481652902913458184"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1481652902913458184-963');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1481652902913458184&amp;amp;theme=dark"
  }



 &lt;/p&gt;
&lt;h2&gt;
  
  
  What are my qualifications to hate Docker
&lt;/h2&gt;

&lt;p&gt;I never knew that in order to have opinions about Docker I would need to announce my pedigree, but apparently I do. &lt;/p&gt;

&lt;p&gt;To my utter astonishment, someone on the Docker team found their way to my thread to call me a junior without the background to appreciate the problem set Docker addresses. And then asked to be unsubscribed like a &lt;em&gt;heeeelllllla&lt;/em&gt; boomer. That part made me laaaaaugh. &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1481893730684526592-557" src="https://platform.twitter.com/embed/Tweet.html?id=1481893730684526592"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1481893730684526592-557');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1481893730684526592&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Anyway here are my qualifications: Have been in this field for many years, made senior in two and a half, have worked on giant gnarly legacy code bases and alternately built multiple products out of nothing to be hugely successful. &lt;/p&gt;

&lt;p&gt;I am a code mentor and have volunteered teaching code, I am (as of recently) a paid guest writer for a database company, and managed to get straight As in senior year of a Software Engineering &amp;amp; Security degree while also working full time. My GPA was something like 3.8 and my major GPA was 3.9. Actually, I've been in school at least half time since 2019 so I have experienced a meteoric rise professionally with much less time on hand than equally qualified peers. &lt;/p&gt;

&lt;p&gt;In one past role, I was so brutally effective that I received an off-cycle promotion from Software Engineer, not to Senior Software Engineer but directly to Dev Lead. Within less than a year of working there.&lt;/p&gt;

&lt;p&gt;So...yeah. I am both educated and experienced, and as entitled to my opinion on Docker as anyone. (Although hot take, anyone can hate Docker for any time and for any reason, who cares lol). &lt;/p&gt;

&lt;p&gt;Most notably, I actually had to spend somewhat extensive time using a dockerized development environment when at a past job, we had dependencies with no good MacPorts option that did not run on Mac period. In that role, I was also responsible for software that dealt with tracing vulnerabilities through containerized environments which introduces a special, interesting set of challenges. &lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually think of Docker
&lt;/h2&gt;

&lt;p&gt;Surprise surprise, twitter is not a tool of nuance. There were more to my comments than "Docker is terrible", naturally. &lt;/p&gt;

&lt;p&gt;I made the mistake of wondering why this hit such a nerve with people and googled latest Docker tweets period, thinking surely I wasn't the only one with these issues. (Bad idea). Aaaaaaand that's when I found the subtweets. They centered on a few themes:&lt;/p&gt;

&lt;p&gt;Everyone in the discussion were junior engineers &lt;br&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%2Fkqr4fnlyvlamr9nluoij.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%2Fkqr4fnlyvlamr9nluoij.png" alt="Someone suggesting everyone in the discussion is junior"&gt;&lt;/a&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%2Fqx9zre9s046ekh7lo1fd.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%2Fqx9zre9s046ekh7lo1fd.png" alt="Guy erroneously concludes I'm a young engineer who doesn't know what it was like before Docker"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No one was providing any concrete reasons for disliking it (spoiler, I did and will again) &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%2F0513brnw7ti3tstwhd4t.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%2F0513brnw7ti3tstwhd4t.png" alt="Guy demands real reasons"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you aren't using Docker in x way/on y OS its your fault it is miserable (ok lol) &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%2Fnwxcbwk95cj96xe9ed6b.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%2Fnwxcbwk95cj96xe9ed6b.png" alt="Man asks if I'm using Docker directly"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;People goading me "what's your alternative then"&lt;br&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%2Fnus0844mk1ckfr8lm1lx.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%2Fnus0844mk1ckfr8lm1lx.png" alt="Guy asks what my alternative is"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The internet is a wild place lol. Imagine me tweeting "I don't like broccoli" and a bunch of nerds demanding I explain why or can't make that comment. Or saying I can only dislike broccoli if I mention that cauliflower is a valid alternative. Or say "it is your fault you don't like broccoli you should have been cooking it with this technique, DUH!" &lt;/p&gt;

&lt;p&gt;But as explained before, &lt;em&gt;I AM ACTUALLY PERFECTLY QUALIFIED TO HAVE BOTH THE OPINION, AND A RATIONALE BEHIND IT&lt;/em&gt;. The internet neckbeards I'm sure will be so relieved to hear it (not).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For starters, junior developers finding Docker un-intuitive and with iffy docs is also my problem, since what junior developers struggle with rolls downhill to me as their senior&lt;/li&gt;
&lt;li&gt;I have consistently found the cli poor, things I need to do regularly are not prefab commands or require large numbers of fiddly flags, I need to wind up making aliases for tasks I find common enough that they warrant a built-in command and it seems like something so easy to fix if you care about dx at all&lt;/li&gt;
&lt;li&gt;Resource consumption and old volumes hanging around remains annoying&lt;/li&gt;
&lt;li&gt;I find the docs very sparse, my particular criticism with them could probably be addressed by a 1-2 liner in various sections just showing one vanilla example of cli options. My experience in the docs is being redirected around like a pinball and eventually finding what I need outside of the official docs. If the rest of the internet is better than you are at explaining your product, imo that's an issue &lt;/li&gt;
&lt;li&gt;In light of I think, two Docker team members finding their way into my thread and being obnoxious, I now have a personal animus that I didn't even have originally so thanks guys lmao &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also have a criticism much more meta than Docker, and hate this opinion all you want but oh well:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Software is bad. Computers were a mistake&lt;/strong&gt;, (To quote an old coworker). The less software my app depends on, the happier I am - and that includes Docker.&lt;/p&gt;

&lt;p&gt;Particularly for my local dev setup, I tend to find that Docker wastes much more of my time than it saves. Tending to this tool and its various needs takes time I don't have. I'm busy, I'm sure if I had time to plumb the depths of the Docker documentation I could come up with a super cool setup that addresses every little thing about it that I don't like. For me personally, I have NEVER liked the "f@#$ you figure it out or you don't deserve the tool" mindset. &lt;/p&gt;

&lt;p&gt;Give me things that work seamlessly. I have s@#$ to do. &lt;/p&gt;

&lt;p&gt;I don't want to toil away customizing a linux box, give me an already usable computer. If you like that, great, but not everyone does. With more hours in the day I'm sure I could sit down with Docker and get into the weeds but I don't have time and for a tool so popular I don't feel like I should need to. Containerization is an area I have experience but not one I wish to specialize in, I'm hardly the best person around to come up with a complex Docker setup and feeling like I have to know it to do what used to be just running a flask app on localhost seems &lt;em&gt;extremely&lt;/em&gt; overwrought.   &lt;/p&gt;
&lt;h2&gt;
  
  
  Other criticisms I'll address
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;If you like Docker&lt;/strong&gt;, from the bottom of my heart I think that's awesome. My least favorite use case (local dev) emerged in the comments that equally frustrated and delighted people. I think its great that we all are so different and have different likes and I'm happy Docker works for some people &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Things were bad before Docker&lt;/strong&gt; - perhaps they were, some of it I wound up liking better for whatever reason. I've worked with Vagrant, VirtualBox, deploying to vms up on GCP, and whatever else. Maybe my preference just settled on those. I certainly miss local dev without Docker to mess with. It doesn't need to be how everyone feels &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker has its place&lt;/strong&gt; - I agree with you! Yeah, Twitter is not great for nuance but sometimes I have really enjoyed Docker being in the mix&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Come up with something better then&lt;/strong&gt; - well that's ridiculous. Returning to broccoli, clearly I can't invent a better vegetable. It is beyond absurd to imagine I can only have an opinion on Docker if I have a competing container solution's software ready to go. News flash, there are plenty of things made by people smarter than you or I that we still won't like for whatever reason. Also, the hilarious detachment from reality here - I have a mortgage and am in school full time? I don't have time to invent a better container solution if no one is paying me to do so, some of us have day jobs babe&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The hilarious thing about this experience
&lt;/h2&gt;

&lt;p&gt;No one expects the internet to be nice to them, let's be real. But in the negative commentary I will say, themes certainly emerged. &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1482076709927141380-894" src="https://platform.twitter.com/embed/Tweet.html?id=1482076709927141380"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1482076709927141380-894');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1482076709927141380&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;I'd love to never have to talk about this again, but &lt;strong&gt;it was hard not to see a sexist tilt to the replies&lt;/strong&gt;. For starters, seemed supremely random that so many people wanted to discredit me by calling me a junior and implying that that could completely explain me not liking Docker. &lt;/p&gt;

&lt;p&gt;It is not difficult to find the podcasts I've appeared on, my long held Senior or higher title has remained in my bio for years. Disagree with me all you want but you do not have a leg to stand on if you want to come at my seniority. Which is fortunate, because honestly as a newer and less secure dev maybe a zillion dudes telling me I have no idea what I'm doing would have bothered me. &lt;/p&gt;

&lt;p&gt;That critique is even sillier if you unpack it: if I were junior would I not have permission to dislike technology? The software I admire makes complex things simple, so the highest compliment I could give Docker would be that its a good tool for junior devs. Some of y'all really have it twisted on the topic of juniors not understanding software and how that reflects on the software. &lt;/p&gt;

&lt;p&gt;Lastly I'll say, a lot of bias is sub-optimal associations. People associate women with less expertise in tech, and these replies showed it. I think sometimes non-URM people think it is a security blanket, like somehow URM feel better if we can blame things on bias issues. I will assure you it is not the case, it just means for me that people are coming down hard on me regardless of the validity of my opinions and even if I respond in-depth, they are going to discount my expertise and conclusions. Makes it feel very futile to put effort into defending my views. &lt;/p&gt;

&lt;p&gt;Something about my personality, I have really always hated status symbols or things like pulling rank. I would normally never say "I'm a senior AF dev here's my credentials", I find it honestly very tacky and no one should feel like I'm cooler than them if they are less experienced. The fact that I have to trot out this litany of things to say I can have an opinion is honestly bizarre, but here we are. &lt;/p&gt;

&lt;p&gt;It is also not at all fun or a trump card to have to bring this up, frankly it sucks, but I feel like the kid in The Emperors New Clothes who speaks an unpopular truth. I am successful enough that I can take the flak for raising this issue so if something hits me as sexist you bet your ass I'm going to talk about it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways and positives
&lt;/h2&gt;

&lt;p&gt;Despite some annoying replies (admittedly tame for the internet at the end of the day) I actually got some cool takeaways from this experience.&lt;/p&gt;

&lt;p&gt;I had three people reach out to me about container tooling they want me to try, I'm going to set up three meetings next week for things I'd previously never heard of - considering my work uses Docker if any of them seem good I'd be thrilled to introduce them to our tech stack if they make Docker less of a headache. &lt;/p&gt;

&lt;p&gt;A ton of people also responded in earnest with cases they love Docker for, which made me happy! Trust me, no one is happier than I am that fewer people feel how I do on Docker. &lt;/p&gt;

&lt;p&gt;A lot of people just seemed relieved that anyone else struggled with this supremely popular tool that they hadn't gelled with. &lt;/p&gt;

&lt;p&gt;And finally, there were some good-faith replies by people who really like Docker that had suggestions on things to make the experience better, or with alternatives - many I'd never heard of and sound &lt;strong&gt;extremely&lt;/strong&gt; interesting and I'm really stoked to get into further. &lt;/p&gt;

&lt;p&gt;At the end of the day, willing to write it off as a funny fluke and move along. But did teach me a valuable lesson that sometimes when you yell into the void, the void yells back. &lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
