<?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: Neil Chaudhuri</title>
    <description>The latest articles on DEV Community by Neil Chaudhuri (@realneilc).</description>
    <link>https://dev.to/realneilc</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%2F679011%2F8939b596-71dc-41d4-ad1a-2f18e11389b3.png</url>
      <title>DEV Community: Neil Chaudhuri</title>
      <link>https://dev.to/realneilc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/realneilc"/>
    <language>en</language>
    <item>
      <title>Why Coding Interviews are the Worst</title>
      <dc:creator>Neil Chaudhuri</dc:creator>
      <pubDate>Tue, 09 Aug 2022 14:51:02 +0000</pubDate>
      <link>https://dev.to/realneilc/why-coding-interviews-are-the-worst-3ogi</link>
      <guid>https://dev.to/realneilc/why-coding-interviews-are-the-worst-3ogi</guid>
      <description>&lt;p&gt;Tech interviews are broken. Much like with vegan cheese, we all agree there is a problem, but we all differ on how to fix it. How did we get here?&lt;/p&gt;

&lt;p&gt;Over the last several decades as tech became a dominant industry, the new personalities that became very rich very fast also became very &lt;a href="https://silicon-valley.fandom.com/wiki/Gavin_Belson"&gt;Gavin Belson from Silicon Valley&lt;/a&gt;—supremely convinced of their own outside-the-box cleverness not only at producing revolutionary technology but also at revolutionizing the way it's built. The media decided this was the beginning of a new era where the novel approaches tech companies took to everything should be a model for everyone else. Remember when open floor plans with foosball tables and Keurigs were the key to unleashing workplace productivity restrained too long by dehumanizing cubicles? After enough writeups in even mainstream outlets like &lt;a href="https://www.cbsnews.com/news/ditch-the-cubicles-for-better-collaboration/"&gt;CBS News&lt;/a&gt;, everyone was doing it.&lt;/p&gt;

&lt;p&gt;But we ended up just using headphones to fashion our own mental cubicles so we could work in some kind of awkward peace—&lt;a href="https://www.inc.com/betsy-mikel/new-study-open-offices-are-terrible-for-women.html"&gt;particularly awkward&lt;br&gt;
for women&lt;/a&gt;, people of color, introverts, and many others.&lt;/p&gt;

&lt;p&gt;A similar thing happened with tech interviews. After all, boring accounting firms ask about your resume but not us! The media were awestruck at&lt;br&gt;
profound interview questions like "&lt;em&gt;Why are manhole covers round?&lt;/em&gt;" or "&lt;em&gt;How would you calculate the number of cars passing through a busy bridge?&lt;/em&gt;"&lt;br&gt;
or the famous Elon Musk riddle "&lt;em&gt;You’re standing on the surface of the Earth. You walk one mile south, one mile west, and one mile north. You end up exactly where you started. Where are you?&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;This is all about getting deeper than any traditional interview could, you see, to reveal how candidates think!&lt;/p&gt;

&lt;p&gt;Yeah, OK.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coding interviews are the worst. How do we know?
&lt;/h2&gt;

&lt;p&gt;While the more absurd questions have lost some luster, one relic of our unconventional interview style that endures is the coding interview. You know it. A panel of dudes all vaguely reminiscent of &lt;a href="https://bigbangtheory.fandom.com/wiki/Howard_Wolowitz"&gt;Howard&lt;/a&gt; from &lt;em&gt;The Big Bang Theory&lt;/em&gt; asks candidates to go to the whiteboard or a laptop broadcasting to a screen and write code for something they've probably never seen (by design). It could be implementing a doubly-linked list or merge sort or a function that determines if a string is a palindrome. It could be performing a breadth-first search or converting a loop into a recursive function. And on and on.&lt;/p&gt;

&lt;p&gt;This is a problem—not only for job candidates but also for the companies considering them. It's an especially acute problem now with the shortage of software engineers and the popularity of remote work particularly in the aftermath of a global pandemic. Then there is all the uncertainty. Uncertainty tech companies feel in an era of inflation and &lt;a href="https://www.thestar.com/business/2022/07/26/i-got-this-wrong-shopify-ceo-announces-plan-to-layoff-10-per-cent-of-staff.html"&gt;evolving economic fundamentals&lt;/a&gt; and uncertainty candidates feel in an era of layoffs and evolving personal responsibilities and professional goals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coding interviews solve for the Computer Science Department valedictorian or the most short term knowledge. Not the best long term culture fit
&lt;/h3&gt;

&lt;p&gt;The biggest technical problem with coding interviews is the disconnect between what they measure and what actually adds value to the business. For 99% of you, hiring someone who understands Kruskal’s algorithm for finding a minimum spanning tree isn't relevant to making your UI accessible, scaling in the cloud, improving your engineering practices, or driving revenue. &lt;/p&gt;

&lt;p&gt;Even if you do better than silly college computer science questions and focus on the tech you use today, you focus on the wrong thing. It isn't what candidates know; it's how much they can learn. If you're a React shop, it's impressive if a candidate understands how &lt;code&gt;useEffect&lt;/code&gt; is about &lt;a href="https://dev.to/blog/dark-mode-nextjs-tailwindcss-react-hooks"&gt;syncing UI with state&lt;/a&gt; rather than a new spin on &lt;code&gt;componentDidMount&lt;/code&gt;, but what if you decide to move to &lt;a href="https://www.solidjs.com/"&gt;Solid&lt;/a&gt;? Or what if an important new initiative demands a different set of skills entirely and you don't have the resources to hire a subject-matter expert right away?&lt;/p&gt;

&lt;p&gt;Instead, you want to hire engineers who fit with your culture and make their teams better with hard and soft skills. They do this is many ways. They learn quickly because think in abstractions so they can translate prior knowledge into new skills that serve their professional growth and your bottom line. They aren't afraid to experiment and fail in order to learn new things. They listen. They are eager to help. They are patient and kind. They manage their time well. They can communicate with customers. They care about good code and write good documentation. Their teammates trust them to support them and to assume leadership when the moments calls for it.&lt;/p&gt;

&lt;p&gt;Your business needs &lt;a href="https://marvelcinematicuniverse.fandom.com/wiki/Vision"&gt;Vision&lt;/a&gt;. Coding interviews at best get you &lt;a href="https://marvelcinematicuniverse.fandom.com/wiki/Ultron"&gt;Ultron&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coding interviews further exclude systematically excluded communities
&lt;/h3&gt;

&lt;p&gt;I am a passionate advocate for diversity in tech. Prejudice against anyone on the basis of race, gender, ethnicity, nationality, religion, orientation, ability, or even academic background not only limits our individual growth but also &lt;br&gt;
limits the creative energy necessary to develop the best software. Sadly, there are countless institutional barriers to diversity in tech, and coding interviews are one of them.&lt;/p&gt;

&lt;p&gt;Don't believe me? Check out this &lt;a href="https://news.ncsu.edu/2020/07/tech-job-interviews-anxiety/"&gt;study by North Carolina State University and Microsoft&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;But the format may also serve as a barrier to entire classes of candidates. For example, in our study, all of the women who took the public interview failed, while all of the women who took the private interview passed. Our study was limited, and a larger sample size would be needed to draw firm conclusions, but the idea that the very design of the interview process may effectively exclude an entire class of job candidates is troubling.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Much as society writ large is convinced &lt;a href="https://www.youtube.com/watch?v=ScmJvmzDcG0"&gt;DNA evidence&lt;/a&gt; and &lt;a href="https://www.theguardian.com/technology/2016/mar/24/tay-microsofts-ai-chatbot-gets-a-crash-course-in-racism-from-twitter"&gt;AI&lt;/a&gt; are "objective," tech is at best convinced coding interviews are also free from bias or at worst happy to capitalize on their bias. Bias in coding interviews could be favoritism, intentional or otherwise, reflected in choice of coding problem or leniency in evaluation. They are also biased against realistic forms of working. In real life, we don't have people staring at us as we type to scrutinize our work and mannerisms. We have access to Google, Stack Overflow, and other resources. The discomfort produced by contrived awkwardness in coding interviews hurts otherwise talented candidates—particularly those in communities already systematically excluded in tech like the women in the study.&lt;/p&gt;

&lt;p&gt;But that's one study you say. OK, but consider anecdotal evidence from elite engineers. &lt;a href="https://twitter.com/gurlcode"&gt;Jenn Creighton&lt;/a&gt;, senior engineer at Netflix on the NodeJS team and host of the &lt;a href="https://twitter.com/single_threaded"&gt;single-threaded podcast&lt;/a&gt; exposed the problem on &lt;br&gt;
her premier episode with her guest &lt;a href="https://twitter.com/erinfoox"&gt;Erin Fox&lt;/a&gt;. Senior engineer, Apple whistleblower, and activist &lt;a href="https://twitter.com/cherthedev"&gt;Cher Scarlett&lt;/a&gt; described her own experience a few years ago:&lt;/p&gt;


&lt;blockquote&gt;
&lt;p&gt;not work, and wasn't what they were looking for. These same two pieces of code are now written about by two other individuals as best practice solutions to these problems. Do you think this coding interview was about code? No, it was an ego battle I'd never be allowed to win.&lt;/p&gt;— Cher Scarlett (@cherthedev) &lt;a href="https://twitter.com/cherthedev/status/998914080177115136?ref_src=twsrc%5Etfw"&gt;May 22, 2018&lt;/a&gt;
&lt;/blockquote&gt; 

&lt;p&gt;Of course if things can get so bad for cis white women in tech that coding interviews become a vanity exercise at their expense, just imagine how much worse it must be for women of color, trans people, anuerotypical people, even people who learned tech at boot camps instead of MIT or have degrees in psychology. And so many others.&lt;/p&gt;

&lt;p&gt;Let's use the interview process to welcome as many people as possible into tech because the challenges that lie ahead are too great to leave anyone behind.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coding interviews are the basis for an entire cottage industry dedicated to help candidates "ace" them
&lt;/h3&gt;

&lt;p&gt;Precisely because coding interviews are so divorced from the reality of our lives as software engineers, job candidates need time to prepare for the experience. It takes time to build composure as people stare at you at the front of the room or judge every keystroke. It takes time to remember, or learn for the first time, fundamental concepts of computer science or low-level implementation details typically abstracted from you by frameworks and open-source libraries. It takes time to memorize it all because you may not be allowed access to the resources you normally have at your disposal.&lt;/p&gt;

&lt;p&gt;Everyone knows it, so a cottage industry has emerged to get candidates through it. There are literally hundreds of books and online courses promising to help them "ace" the tech interview and get that prestigious, high-paying job so you can get that Cybertruck because you find its ugliness endearing.&lt;/p&gt;

&lt;p&gt;This is costly. At best, it takes time away from personal life. At worst, it costs serious dollars. Either way, this is another way coding interviews serve as a gatekeeper excluding communities from tech—software engineers who can't afford the costs of interview prep.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's the alternative?
&lt;/h2&gt;

&lt;p&gt;Coding interviews are bad for the business and bad for the candidate. Instead, you should conduct interviews that are inclusive, find the best long term fit for your business, and convey the joy of solving problems there.&lt;/p&gt;

&lt;p&gt;Make the interview a conversation. Share your business goals and details about your mission, the role you're hiring for, your expectations technically&lt;br&gt;
and culturally, and your values as an organization. Then consider questions like these.&lt;/p&gt;

&lt;h3&gt;
  
  
  "What are some examples of problems you solved at work? Take me through how you solved them."
&lt;/h3&gt;

&lt;p&gt;This question helps you understand the experiences candidates have had on the job. It helps you evaluate how these experiences apply to your business and, more importantly, how your candidates approach challenges. Feel free to explore the topic in depth and follow threads of conversation as candidates raise points you find particularly interesting. You don't have to be &lt;a href="https://www.youtube.com/watch?v=w-gkAM0XZMU"&gt;Oprah&lt;/a&gt;, but there is an art to navigating a conversation to elicit more information. You will get a good sense of candidates' technical knowledge, their creativity,&lt;br&gt;
amd their ability to gain new knowledge. &lt;/p&gt;

&lt;p&gt;After all, game recognizes game.&lt;/p&gt;

&lt;h3&gt;
  
  
  "Can you describe a situation at work where you were particularly proud of what you accomplished?"
&lt;/h3&gt;

&lt;p&gt;This question helps lighten the mood and bring positivity into a tense process. It gives candidates a chance to brag a little but in a way that lends value to you. You can glean if your own business offers the kinds of opportunities for joy the candidates want to experience, and you can again get some detail into their experience, expertise, and potential for growth.&lt;/p&gt;

&lt;h3&gt;
  
  
  "It's common to have differences of opinion on a team on how to solve problems. How have you worked through those?"
&lt;/h3&gt;

&lt;p&gt;This question addresses the reality of working on a team and the likelihood of a culture fit. Anyone who spends about three minutes on Tech Twitter knows we like to argue—often about the most trivial, self-serving things. Candidates have certainly had their share of disagreements at work, and it's important to understand how constructively they handle them and if their solutions fit with your company culture. You will also get a sense of what candidates think is important—tech or otherwise. The question is if your value system is compatible with theirs.&lt;/p&gt;

&lt;h3&gt;
  
  
  "If you had full control of the architecture and engineering of your current code base, what would you change about the code or the process?"
&lt;/h3&gt;

&lt;p&gt;This question again helps you learn about a candidate's expertise and room for growth but from a different angle. We all have regrets about technical debt, yearnings for different approaches, and other aspects of the product and process that stick in our craw. Give candidates a chance to vent. In the process, you will learn about what candidates value, their knowledge of the engineering and product delivery landscapes, the direction they want to go, and their tact with constructive criticism. Does their vision comport with yours for your business?&lt;/p&gt;

&lt;h3&gt;
  
  
  "What kinds of support do you need to do your best work?"
&lt;/h3&gt;

&lt;p&gt;This question addresses &lt;em&gt;your&lt;/em&gt; responsibility to your people to achieve the goals of the business and the support candidates can expect if they join. You might have an issue with this question because it implicitly undermines conventional wisdom that the best engineers do their best work of their own accord if they have "passion" for tech implied by a robust GitHub presence, lots of side projects, eagerness to work weekends, etc.&lt;/p&gt;

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

&lt;p&gt;For reasons why the responsibility is yours to provide "flow state" rather than candidates' responsibility to have passion, read&lt;a href="https://leaddev.com/culture-engagement-motivation/why-flow-matters-more-passion"&gt;this excellent post by Sarah Drasner&lt;/a&gt;, Director of Engineering, Core Developer Web at Google.&lt;/p&gt;

&lt;p&gt;The best engineering managers understand how to create flow state. Even if candidates are unfamiliar with management theory, this question informs them that you have their best interests at heart and recognize your own responsibility in making them successful. You can also evaluate whether their answers are aligned with your business values.&lt;/p&gt;

&lt;h3&gt;
  
  
  "Do you have any questions for us?"
&lt;/h3&gt;

&lt;p&gt;Hopefully you are asking this question anyway regardless of whether coding interviews are part of your hiring process. Give candidates a chance to ask you about the things that matter to them as they consider making the considerable, potentially life-changing commitment to your business. They should direct the conversation here. Expect questions about titles, commitment to and evidence of diversity, opportunities for advancement, remote work and tooling, and other aspects of business process and company culture.&lt;/p&gt;

&lt;p&gt;Be careful though not to interpret the absence of questions as apathy or really anything negative. This is their time, and if they don't need it, you shouldn't let that influence your decision one way or another.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As an aside, prefer diverse panels of interviewers. Also pay attention to the demeanor of candidates. Any toxic behavior like arrogance, abruptness, or something particularly awful like refusing to acknowledge female interviewers should make your decision easy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  But OK, if you must do coding interviews...
&lt;/h2&gt;

&lt;p&gt;Let's face it. Many of you will never accept that coding interviews are the worst. The idea is simply too entrenched in tech. You're convinced instant recall of computer science fundamentals is critical to bring value to your business. Besides, tech is full of imposters! You must expose them with cleverly chosen coding exercises they have never seen lest they compromise your business with their duplicity.&lt;/p&gt;

&lt;p&gt;There is no evidence any of that is true, but it sure &lt;a href="https://www.cc.com/video/63ite2/the-colbert-report-the-word-truthiness"&gt;feeeeeeels true&lt;/a&gt;! The funny thing is there are actually a lot of job candidates who also think it's true. They see coding interviews as a perfectly reasonable expectation and happily, if sometimes nervously, prepare accordingly.&lt;/p&gt;

&lt;p&gt;Fine. If you must, at least adapt your coding interviews like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Offer candidates the option either to live code or to do a short, paid(!) project to do at home.&lt;/li&gt;
&lt;li&gt;Have them solve a real but non-critical and non-sensitive problem you have at work.&lt;/li&gt;
&lt;li&gt;If it's a live coding exercise, collaborate with candidates rather than sit back and watch and give them access to resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have a lot of important work ahead of us as an industry. I hope you consider the lessons I've learned to help your business grow to meet the challenges ahead.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>career</category>
      <category>management</category>
      <category>leadership</category>
    </item>
    <item>
      <title>Which Programming Languages Should I Learn First?</title>
      <dc:creator>Neil Chaudhuri</dc:creator>
      <pubDate>Tue, 01 Feb 2022 00:12:09 +0000</pubDate>
      <link>https://dev.to/realneilc/which-programming-languages-should-i-learn-first-249k</link>
      <guid>https://dev.to/realneilc/which-programming-languages-should-i-learn-first-249k</guid>
      <description>&lt;p&gt;People who want to get into programming often ask me which languages to learn first, but as Dee tells Naomi on the series  premier of her &lt;a href="https://www.cwtv.com/shows/naomi/dont-believe-everything-you-think/?play=109fca5a-4aec-411d-90e6-19aa22eaedc6"&gt;eponymous TV show&lt;/a&gt;, "I can’t give you answers when you’re not asking the right questions."&lt;/p&gt;

&lt;p&gt;I think it's more helpful to identify which problems you want to solve first. Do you want to build a website to sell your mom's amazing ghee? Look at Shopify, Squarespace, or Wix for a low- or no-code approach or Next.js or Remix Run for a bespoke site. Do you want to build a data model that can help American football coaches decide whether they should go for it on 4th down? Look at Anaconda or Tensor Flow Lite.&lt;/p&gt;

&lt;p&gt;Don't let me stop you if you're jonesing to learn a particular programming language. But if you take my advice and come at the learning process from the point of view of providing a real business need (Your own business need counts!), figure out which tools, libraries, and frameworks make the most sense as you try to deliver for yourself and learn something along the way.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Secure Online Voting is Possible. This is How
</title>
      <dc:creator>Neil Chaudhuri</dc:creator>
      <pubDate>Tue, 25 Jan 2022 01:36:18 +0000</pubDate>
      <link>https://dev.to/realneilc/secure-online-voting-is-possible-this-is-how-2gda</link>
      <guid>https://dev.to/realneilc/secure-online-voting-is-possible-this-is-how-2gda</guid>
      <description>&lt;p&gt;The right to vote is sacred. It's essential to live in a free society and to pick a winner on [The Voice (&lt;a href="https://www.nbc.com/the-voice"&gt;https://www.nbc.com/the-voice&lt;/a&gt;). Unfortunately, the right to vote is under attack worldwide, and bad actors have used tech to do it. Russia &lt;a href="https://www.nytimes.com/2017/11/15/world/europe/russia-brexit-twitter-facebook.html"&gt;interfered with the Brexit referendum in the UK&lt;/a&gt; and with elections there, Ukraine, France, and famously here in the United States, even still as I write this, by hacking voting machines and voter registration databases and manipulating social media. &lt;a href="https://www.theverge.com/2020/9/11/21431990/russian-chinese-iranian-hackers-target-us-2020-elections-trump-biden-campaigns"&gt;Other foreign state actors are interfering in elections&lt;/a&gt; in similar if not quite as aggressive ways.&lt;/p&gt;

&lt;p&gt;Meanwhile, within our own borders here at home, the state legislature in North Carolina used data science with "&lt;a href="https://www.nbcnews.com/politics/politics-news/north-carolina-judges-toss-maps-slam-gerrymandering-stinging-ruling-n1049411"&gt;surgical precision&lt;/a&gt;" to rig state elections at the expense of voters' constitutional rights. North Carolina is hardly alone. In 2018 in Georgia, the Secretary of State, who was running for governor, had the authority to oversee his own election, and he orchestrated a complex web of corruption that actually &lt;a href="https://www.engadget.com/2018-11-09-how-brian-kemp-hacked-georgias-election.html"&gt;encouraged security vulnerabilities and culminated with his own breathtaking wipe of election servers and backups&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If accountability bothers these politicians so much, they should work in meteorology or sports talk radio. &lt;/p&gt;

&lt;p&gt;Even worse, the courts, including &lt;a href="https://dfw.cbslocal.com/2020/10/13/reinstates-texas-order-limiti-mail-in-ballot-drop-off-locations-1-county/"&gt;the Fifth Circuit Court of Appeals in Texas&lt;/a&gt; and the &lt;a href="https://www.cnn.com/2021/07/02/politics/john-roberts-voting-rights-act/index.html"&gt;Supreme Court&lt;/a&gt;, have refused to remain above politics as the judiciary should and have chosen instead to legitimize these bad actors.&lt;/p&gt;

&lt;p&gt;We can't forget criminal mercenaries either as we also saw when &lt;a href="https://blogs.microsoft.com/on-the-issues/2020/10/12/trickbot-ransomware-cyberthreat-us-elections/"&gt;Microsoft took down Trickbot&lt;/a&gt;, in their attempt to infect voting infrastructure with ransomware.&lt;/p&gt;

&lt;p&gt;The goals vary. To sow chaos. To sow mistrust of the electoral process. To override the will of voters. To preserve power structures. To change American policy objectives. To make money.&lt;/p&gt;

&lt;p&gt;Regardless of the purpose of these attacks on the right to vote, they're shameful, and systemic flaws make it all possible: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lack of transparency as manufacturers with troubling conflicts of interest produce closed, proprietary voting machines &lt;/li&gt;
&lt;li&gt;Lack of knowledge or interest in modern software architecture patterns, engineering best practices, UX strategies, modern technologies, accessibility, and good security hygiene&lt;/li&gt;
&lt;li&gt;Lack of training for staff in using and maintaining the available voting technology&lt;/li&gt;
&lt;li&gt;Lack of funding for officials acting in good faith to build robust voting infrastructure&lt;/li&gt;
&lt;li&gt;Lack of access controls to prevent officials acting in &lt;em&gt;bad&lt;/em&gt; faith from exercising undue influence over the infrastructure for nefarious purposes&lt;/li&gt;
&lt;li&gt;Lack of standards from NIST, DHS, and other government institutions for voting infrastructure &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And many others. You can &lt;a href="https://www.nap.edu/catalog/25120/securing-the-vote-protecting-american-democracy"&gt;read about the threats to and core values of a secure online voting platform&lt;/a&gt; defined by a panel of experts.&lt;/p&gt;

&lt;p&gt;Because of these systemic problems, the high stakes involved in electing officials who will be making life and death decisions in the era of COVID, the breathtaking incompetence and embarrassing failure of "modern" voting apps like the &lt;a href="https://www.vox.com/recode/2020/2/7/21125078/iowa-caucus-2016-mobile-app-2020"&gt;IowaReporterApp&lt;/a&gt;, and the fear of relentless attacks from around the nation and the world, we are in a place now where the consensus is that the only secure way to vote is with paper ballots. To say nothing of the vulnerabilities associated with paper ballots. Or the matter of voter access &lt;br&gt;
to those paper ballots, which itself is fraught with bad faith arguments and &lt;a href="https://dev.to/blog/black-lives-matter/"&gt;racism&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's easy, if profoundly disappointing, to see how we got here, but it really doesn't have to be this way.&lt;/p&gt;

&lt;h1&gt;
  
  
  Features of Modern Voting
&lt;/h1&gt;

&lt;p&gt;There is an old joke: &lt;/p&gt;

&lt;p&gt;&lt;em&gt;I told the doctor it hurts when I do that. He said "Then don't do that!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In order to build a modern voting solution, we need to look at the problems with existing voting solutions and "not do them."&lt;br&gt;
I believe secure online voting must have several critical features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Open Source (as much as possible)
&lt;/h3&gt;

&lt;p&gt;In a world of absurd conspiracy theories and legitimate conflicts of interest for voting machine vendors, the core of the solution must be open-source. Every line of code needs to be available for all stakeholders—media, elected officials, election attorneys, security analysts, and most importantly voters—to have confidence in the security and integrity of the software and therefore in the outcomes of elections. &lt;/p&gt;

&lt;p&gt;We will see shortly that it may be necessary to incorporate some commercial solutions that are closed-source, but those should be on the margins. There should be no core functionality that isn't available for all to see.&lt;/p&gt;

&lt;p&gt;Another reason to value open source is that a mission as important as this demands diverse experiences and perspectives—on voting experiences, past software failures, &lt;a href="https://dev.to/blog/vidya/technology/black-lives-matter/"&gt;biases&lt;/a&gt;, architectural patterns, tech stacks, potential vulnerabilities, and whatever else we need to understand to build the best online voting platform possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zero Trust
&lt;/h3&gt;

&lt;p&gt;Every state election system in America is perimeter-based. It's all about firewalls. Perimeter-based security is flawed because once intruders get in, which as we've seen time and time again isn't exactly impossible, there is no stopping them. Instead, we need a Zero Trust approach to security. I will let &lt;a href="https://www.scmagazine.com/home/opinion/executive-insight/what-is-the-zero-trust-framework-in-cybersecurity-and-5-considerations-for-building-a-zero-trust-it-environment/"&gt;Chris Gerritz&lt;/a&gt; explain what this means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Rather than defending only a single, enterprise-wide perimeter, the Zero Trust approach moves this perimeter to every network, system, user, and devices within and outside the organization. This movement is enabled by strong identities, multi-factor authentication, trusted endpoints, network segmentation, access controls, and user attribution to compartmentalize and regulate access to sensitive data and systems.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rather than try in vain to erect barriers to compromise, &lt;em&gt;Zero Trust assumes you have been compromised&lt;/em&gt;. This posture demands authentication and authorization at every point of interaction. It's more work, but it's necessary to minimize vulnerability to modern, sophisticated attacks.&lt;/p&gt;

&lt;p&gt;Think of Zero Trust like a secure hotel. You need your key to get in the building, to get through front desk security, to take the elevator to your floor and only your floor, and finally to enter your room or the gym or the pool. Even inside your room, you need to be authenticated to access WiFi or use the safe.&lt;/p&gt;

&lt;p&gt;Advancements in technology make Zero Trust possible, and a modern voting solution will enforce Zero Trust to ensure that every interaction with every component of the architecture demands authentication and a thorough vetting of privileges and integrity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transparent and Auditable
&lt;/h3&gt;

&lt;p&gt;While the source code will be fully transparent to give everyone confidence in the integrity and fairness of election outcomes, we also need that transparency to extend to the runtime operation of the software. We need to know the health of the system and to know every single thing that happens throughout the architecture—and who did it. This means continuous monitoring throughout the stack, elegant visualizations of the telemetry, and if we can manage it, anomaly detection through analytics. This level of auditability is necessary for Zero Trust, and it is also particularly valuable for &lt;a href="https://en.wikipedia.org/wiki/Risk-limiting_audit"&gt;risk-limiting audits&lt;/a&gt; conducted after elections to assess their integrity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Immutable and Append-Only
&lt;/h3&gt;

&lt;p&gt;I have &lt;a href="https://dev.to/blog/business-case-for-functional-programming/"&gt;written&lt;/a&gt; and &lt;a href="https://dev.to/blog/talking-trends-at-tech-talk-dc/"&gt;spoken&lt;/a&gt; a great deal about the value of immutable data, and I think it is essential for secure online voting. The software should not permit updates or deletes. Rather, any change to the data—a newly registered voter, a new address for an existing voter, and certainly every vote—should be represented in immutable, append-only fashion. As part of the auditability of the software, we should be able to replay every event to recreate state at any point in the process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Client Device and Application Deployment Agnostic
&lt;/h3&gt;

&lt;p&gt;A modern voting solution needs to give voters the freedom to access their ballots on a wide array of devices and to give state government officials the freedom to deploy on premise or in the cloud. The software needs to be agnostic to these possibilities, and this will force compromises in the implementation. It may not always be possible to apply the "coolest" solution if it couples the software too tightly to a particular vendor or feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  Usable
&lt;/h3&gt;

&lt;p&gt;This might seem obvious, but secure online voting demands all stakeholders consider it intuitive. This manifests in several ways. User interfaces need to reflect modern UX principles so that voters, poll workers, and state officials across age, education level, ability, and other factors find the software intuitive.&lt;/p&gt;

&lt;p&gt;I also believe giving voters the opportunity to cast their ballots from wherever they wish is a form of usability. It's not just about comfort either. Because of the relentless media obsession with conflict, everyone tends to focus on candidates, but what about referendums, state constitutional amendments, and bond issues? These can be complex. I know from experience that it's helpful to research these comfortably from your home rather than under pressure within the space and time constraints of a traditional voting booth. &lt;/p&gt;

&lt;p&gt;Part and parcel with usability is performance. Monitoring will help uncover issues with performance, but a modern online voting system needs to be architected for performance. Performance issues will not only be annoying, but they could also undermine confidence in the integrity of the vote. &lt;/p&gt;

&lt;h3&gt;
  
  
  Simple
&lt;/h3&gt;

&lt;p&gt;To achieve all of this, there will be a lot going on in a secure online voting platform—user interfaces, APIs, encryption, databases, multifactor authentication, monitoring. It will be tempting to add complexity to integrate it all, and we need to resist the temptation to overengineer. Otherwise, the application will become unsustainable for maintainers and, much worse, unusable for voters and others, which will bring us right back to the status quo of a voting platform that diminishes the confidence we have in the integrity of our elections.&lt;/p&gt;




&lt;p&gt;None of these are sufficient on their own. For example, merely being open source isn't enough to make this platform secure.&lt;/p&gt;

&lt;p&gt;This is a lot, and in order to achieve it, a secure voting platform needs to be engineered with a continuous deployment &lt;br&gt;
model that automates testing (for functionality, security, performance, accessibility), static analysis, and deployment. We need a process that solves for the key metrics for software delivery performance that Google describes in their &lt;a href="https://services.google.com/fh/files/misc/state-of-devops-2019.pdf"&gt;State of DevOps&lt;/a&gt; report: deployment frequency, lead time for changes, time to restore service, and change failure rate.&lt;/p&gt;

&lt;p&gt;The good news is that a secure online voting solution doesn't have steep demands for scalability or performance. It's not like there will be tens of thousands of votes per second. This isn't &lt;a href="https://www.fox.com/the-masked-singer/"&gt;The Masked Singer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Even if there were one instance of the platform for the entire United States, that's about 150 million voters. That's not a lot. And because in America every state runs its own platform, for better or worse, you'd have at most one instance of the platform for each &lt;a href="https://en.wikipedia.org/wiki/List_of_states_and_territories_of_the_United_States"&gt;state and inhabited territory&lt;/a&gt;. California is the largest state by population, and a statewide election there will have around 30 million voters. As software scale goes, 30 million over the course of several weeks (as the concept of "Election Day" thankfully grows more and more quaint) really isn't that much. Now maybe, hopefully even, great voting software will raise those numbers, but as it stands now, this makes things a lot easier. We can focus on user experience, data integrity, and platform security and worry a bit less about performance at scale.&lt;/p&gt;

&lt;p&gt;Another bit of good news? The UI is simple. It's just boring forms!&lt;/p&gt;

&lt;h2&gt;
  
  
  What Might the Tech Stack Look Like?
&lt;/h2&gt;

&lt;p&gt;I'm not exactly sure, and there are a lot of great options. But I do have some ideas I would like to run by you. &lt;/p&gt;

&lt;h3&gt;
  
  
  The user interface: Remix Run PWA
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://remix.run/"&gt;Remix Run&lt;/a&gt; is a new open source web framework from the creators of React Router that provides abstractions over core web fundamentals to build a resilient experience. In fact, it's that resiliency that makes Remix a compelling choice for a voting application. It's lightweight because it relies on core browser APIs and HTTP, and forms still work without any JavaScript because HTTP supports form submission on its own.&lt;/p&gt;

&lt;p&gt;Certainly a front end in Rails or another robust monolithic framework would be effective as would alternatives like &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt; or &lt;a href="https://kit.svelte.dev/"&gt;SvelteKit&lt;/a&gt;, but I find it hard to resist Remix's lean philosophy. As part of the trend towards more SSR at the edge, Remix Run even offers templates for a variety of deployment platforms like Cloudflare, Fly.io, Netlify, and Vercel, and that list will only grow. Although edge functionality isn't essential for voting software that applies across such little territory (a single state), the deployment flexibility is essential, and every millisecond helps. &lt;/p&gt;

&lt;p&gt;In addition, I think it is important that the front end is deployed as a &lt;a href="https://dev.to/blog/vidya-reloaded/"&gt;Progressive Web App&lt;/a&gt;. This offers a lot of benefits, but primarily for this purpose, it is critical that the front end is always available and as functional as possible regardless of connectivity, which absurdly remains a problem in the richest country in the world. &lt;/p&gt;

&lt;p&gt;This is orthogonal to the choice for UI or PWAs, but the voting application needs to have &lt;a href="https://owasp.org/www-community/attacks/csrf"&gt;Cross-Site Request Forgery&lt;/a&gt; protections and a strong&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP"&gt;Content Security Policy&lt;/a&gt; as well.&lt;/p&gt;

&lt;p&gt;By the way, it might be interesting down the road to think of voice interfaces allowing people to vote with Google Assistant, Alexa, or Siri if privacy concerns can be addressed. One challenge at a time though.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database: PostgreSQL. With a twist
&lt;/h3&gt;

&lt;p&gt;The backbone of this architecture is the &lt;a href="https://martinfowler.com/eaaDev/EventSourcing.html"&gt;event sourcing&lt;/a&gt; architecture based on an immutable, append-only data store representing every single mutation to the data on the platform in order to ensure full replayability and traceability for risk-limiting audits. How can we do this with PostgreSQL?&lt;/p&gt;

&lt;p&gt;Easy. Revoke UPDATE and DELETE privileges!&lt;/p&gt;

&lt;p&gt;Anything more than PostgreSQL, which is straightforward to deploy and agnostic of environment, would be overkill given the small scale—particularly if someone deploys the online voting platform for a small election below the state level with just a few thousand or even a few hundred voters.&lt;/p&gt;

&lt;p&gt;We could store votes in a single table where a simple &lt;a href="https://www.sqltutorial.org/sql-group-by/"&gt;GROUP BY&lt;/a&gt; will aggregate election results. That's easy. We can also store temporal and location data so we can run some basic secondary queries like measuring voter activity by precinct or time of day or day of week or whatever else you want to know. Changes to voter information, a popular action for bad actors, would also be tracked as immutable events, and voters would be notified as they happen.&lt;/p&gt;

&lt;p&gt;So immutable PostgreSQL it is. It's easy to connect to PostgreSQL from the UI with &lt;a href="https://www.prisma.io/"&gt;Prisma&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;By the way, what about blockchain? &lt;a href="https://dev.to/blog/pop-goes-the-blockchain/"&gt;No. Just. No.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment: Somewhere easy
&lt;/h3&gt;

&lt;p&gt;I have no particular preference for where we deploy this online voting platform, but it needs to be somewhere offering good DX and resiliency. To me, this implies any of the out-of-the-box deployment targets for Remix Run, but it could be AWS, Heroku, or many other cloud providers. There could also be a combination like Remix Run on Cloudflare and PostgreSQL, SMTP, and other infrastructure on Supabase. It all depends on what's simple, cost effective, and meets the needs of voters and staff.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitoring, Auditing, Disaster Recovery, and High Availability: It depends
&lt;/h3&gt;

&lt;p&gt;An online voting platform will come under attack from the most sophisticated hackers in the world, and its single most important requirement is that it always maintains the confidence of voters. In order to face these challenges, we need monitoring, auditing, disaster recovery, and high availability.&lt;/p&gt;

&lt;p&gt;These are cross-cutting concerns that apply to any non-trivial deployment, but they are undeniably essential here. It's hard to identify particular solutions because they are a function of the deployment platform, but suffice to say that any platform that cannot meet the needs of a mission-critical system like anomaly detection, alerting, and consistent backups is a nonstarter.&lt;/p&gt;

&lt;p&gt;In the end, we need to be able to understand who, what, where, when, and how for every single event on the platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication and Authorization: A blend of open-source and proprietary solutions
&lt;/h3&gt;

&lt;p&gt;It goes without saying that the most important piece of online voting is security. The challenge isn't just technical though:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It needs to be simple to implement and maintain yet all but impregnable&lt;/li&gt;
&lt;li&gt;It needs to be simple to use by all voters regardless their age, ability, tech savvy, and other factors&lt;/li&gt;
&lt;li&gt;It must withstand independent audit by a trusted partner&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where the top minds in infosec will be invaluable. I am nowhere near that class, but let me throw out some ideas.&lt;/p&gt;

&lt;p&gt;In the interest of Zero Trust, the connections to the server, the database, and any other infrastructure like SMTP servers and caches will be authenticated over TLS, and all data at rest will be encrypted. This of course implies encryption key storage like that provided by HashiCorp Vault and similar products.&lt;/p&gt;

&lt;p&gt;Voters would have a choice of authentication methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Username/password (12-64 characters with mixed case, numbers, and special characters required) and their choice of MFA methods (&lt;em&gt;e.g.&lt;/em&gt; authenticator app, physical key) along with the usual Forgot Password, Change Password flows&lt;/li&gt;
&lt;li&gt;OpenID integration with Google&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There will always be voters who feel comfortable voting in the traditional way—showing up to their local polling places on Election Day and casting ballots. Polling places would simply be equipped with computers from which voters cast their ballots by setting up accounts and logging in through the browser to our secure online voting platform, and staff would assist in the process. If it were up to me, the government would provide funding for physical keys, and every voter who shows up in person on Election Day who wants one would get one and would be shown how to use it.&lt;/p&gt;

&lt;p&gt;The database could associate random tokens to users, analogous to an access key for a cloud API, which for voters would have a quota limit of one for the duration of eligible voting. These tokens would be encrypted and rotated on a periodic basis, and they would represent voters in their interactions with the APIs to cast votes and staff in all other API calls.&lt;/p&gt;

&lt;p&gt;Finally, securing the entire DevSecOps pipeline means implementing a host of measures like keeping secrets out of code and configuration, managing access control and limiting permissions throughout the pipeline, signing changes to version control with PGP, using key management mechanisms appropriate for the deployment platform, and much more.&lt;/p&gt;

&lt;p&gt;And of course there are automated security tests in CI and full audits by security professionals to vet the entire &lt;br&gt;
architecture.&lt;/p&gt;




&lt;p&gt;This entire stack, and really the whole architecture, is just an idea. It is all subject to change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outstanding Questions
&lt;/h2&gt;

&lt;p&gt;Even if the architecture and technology stack are perfect, there are difficult questions that remain across not only technology but also law, finance, politics, and even philosophy. Here are some of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every state has its own election laws, technology infrastructure, and budget. What kinds of legal, privacy, and technical challenges are there to migrating voter registration data to a new system? Is there even a need if the application can represent registered voters some other way? &lt;/li&gt;
&lt;li&gt;Corrupt officials do not want anything that will make voting easier, but would even &lt;em&gt;honest&lt;/em&gt; officials consider it? &lt;/li&gt;
&lt;li&gt;What's to stop government officials who are authorized users acting in bad faith from compromising the platform in some way?&lt;/li&gt;
&lt;li&gt;While the platform would be built for resilience, what kinds of contingency plans would be in place just in case the platform went down for an extended period?&lt;/li&gt;
&lt;li&gt;If we use PostgreSQL as an immutable, append-only store to provide a replayable log of all data mutations, we will eventually hit its limits. What's the retention period for the data? If it is even necessary to retire the data to some kind of data lake after the retention period, where would that be? How would that work?&lt;/li&gt;
&lt;li&gt;To what extent can we preserve the notion of a "secret ballot" where only voters themselves know their selections? Or should a modern voting platform recognize the very concept of a secret ballot as an &lt;a href="https://www.washingtonpost.com/posteverything/wp/2017/01/06/want-to-improve-democracy-abolish-the-secret-ballot/"&gt;anachronism that is pointless at best and harmful at worst&lt;/a&gt; and function accordingly?&lt;/li&gt;
&lt;li&gt;Would machine learning serve a purpose here? If so, what's the simplest and most effective way to implement it?&lt;/li&gt;
&lt;li&gt;Would there be an audience for making non-PII data available via APIs for data analytics by independent organizations? If so, how would we do that?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The beauty of open source is the diversity of thought and creative energy that converges to solve interesting, hard problems like these. &lt;/p&gt;

&lt;p&gt;It will take a historical effort to build a secure online voting platform that allows all registered voters to make their voices heard and gives them the confidence that their votes count and that winners are legitimate. If you find improving access to voting, guaranteeing the integrity of elections, promoting social justice, and solving interesting problems as important and as compelling as I do, please &lt;a href="https://dev.to/contact"&gt;get in touch&lt;/a&gt; so we can collaborate on something that could transform society for the better.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What If...Marvel Built a Minimum Viable Product?</title>
      <dc:creator>Neil Chaudhuri</dc:creator>
      <pubDate>Thu, 11 Nov 2021 01:50:46 +0000</pubDate>
      <link>https://dev.to/realneilc/what-ifmarvel-built-a-minimum-viable-product-4fc0</link>
      <guid>https://dev.to/realneilc/what-ifmarvel-built-a-minimum-viable-product-4fc0</guid>
      <description>&lt;p&gt;In 2011, Eric Ries published &lt;em&gt;The Lean Startup&lt;/em&gt;, and it revolutionized software development. Lean principles had already &lt;a href="https://www.goodreads.com/book/show/194338.Lean_Software_Development"&gt;made it into agile software development&lt;/a&gt;, but &lt;em&gt;The Lean Startup&lt;/em&gt; fills in a lot of gaps to turn the abstract&lt;a href="https://agilemanifesto.org/principles.html"&gt;principles behind the Agile Manifesto&lt;/a&gt; into something real.&lt;/p&gt;

&lt;p&gt;For example, even if you nailed agile and built the thing right, how do you know you built the right thing? In other words, it's great to execute on your project and build exactly what you intend on time and on budget, but when you're done, how do you know people will actually buy it? Although the Agile Manifesto never answers this question because it assumes you are on the right track all along, Ries gives us an answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Minimum Viable Product
&lt;/h2&gt;

&lt;p&gt;Probably the most profound innovation in &lt;em&gt;The Lean Startup&lt;/em&gt; is the Minimum Viable Product (MVP).&lt;/p&gt;

&lt;p&gt;(You can &lt;a href="https://www.youtube.com/watch?v=E4ex0fejo8w"&gt;watch Ries himself talk about it&lt;/a&gt;, but I have to warn you that it looks like it was filmed by the director of &lt;a href="https://www.thenewsminute.com/article/how-blair-witch-project-manages-scare-without-showing-anything-supernatural-135492"&gt;The Blair Witch Project&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;The idea is really quite simple. Whether you are conscious of it or not, the product you have in mind is based on your assumptions about what your customers want and why, so the purpose of the MVP is to validate those assumptions with hard data around &lt;em&gt;a lightweight representation of your product&lt;/em&gt; before you commit your full resources to building it out in full. You give your early adopters access to the MVP and consider their feedback, which Ries calls "validated learning." Validated learning is crucial. For Ries, it's quantifiable feedback that is "the unit of progress for lean startups."&lt;/p&gt;

&lt;p&gt;Based on what you learned, you either "&lt;a href="https://www.youtube.com/watch?v=n67RYI_0sc0"&gt;pivot&lt;/a&gt;" to something else more aligned to what your customers want or "persevere" because you had it right all along. From this point on, you have quantifiable, proven demand for your product, and you can be confident that you will be investing in building the right thing.&lt;/p&gt;

&lt;p&gt;Like a lot of terms in tech that blow up, consultants often use MVP to mean something different from what Ries intended--most commonly to mean the first version of your product and/or a really scaled down version of it. In either case you've implicitly decided without any validated learning what you want to build. The fact it's in its earliest stages is irrelevant.&lt;/p&gt;

&lt;p&gt;So what does all of this have to do with Marvel?&lt;/p&gt;

&lt;h2&gt;
  
  
  The MCU Juggernaut
&lt;/h2&gt;

&lt;p&gt;Unless you have been living in the &lt;a href="https://marvelcinematicuniverse.fandom.com/wiki/Quantum_Realm"&gt;Quantum Realm&lt;/a&gt; for the last decade, you know the &lt;a href="https://www.marvel.com/movies"&gt;Marvel Cinematic Universe (MCU)&lt;/a&gt;. It's a monumental achievement in cinema  that has taken decades of Marvel comics and reformulated them into a multibillion dollar juggernaut movie franchise that has  raised once second-tier heroes like Iron-Man, Thor, and Black Widow to the stature of eternal favorites like Spider-Man, Captain America, and Hulk and put &lt;a href="https://marvel.fandom.com/wiki/Mjolnir"&gt;Mjolnirs&lt;/a&gt; and &lt;a href="https://marvelcinematicuniverse.fandom.com/wiki/Infinity_Gauntlet"&gt;Infinity Gauntlets&lt;/a&gt; into the homes of ardent fans worldwide.&lt;/p&gt;

&lt;p&gt;It may be hard to imagine now, but there was no guarantee of success at the beginning as Marvel was struggling as a business having sold off their most bankable assets. This forced Kevin Feige, the architect of the MCU, to get creative to and &lt;a href="https://www.vox.com/2016/5/9/11595344/marvel-cinematic-universe-captain-america-avengers"&gt;derive new ways to bring Marvel heroes to life&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;They succeeded spectacularly, and now they have to do it all over again.&lt;/p&gt;

&lt;p&gt;Firmly entrenched in global pop culture, the MCU now faces pressure to build on its foundation with new heroes and villains, many of whom like &lt;a href="https://marvel.fandom.com/wiki/Marc_Spector_(Earth-616)"&gt;Moon Knight&lt;/a&gt; and &lt;a href="https://www.marvel.com/characters/titania-mary-macpherran"&gt;Titania&lt;/a&gt; lack the star power of Captain America and Spider-Man and are all but unknown to mainstream audiences. And considering that the MCU has decided to go all in on the &lt;a href="https://marvelcinematicuniverse.fandom.com/wiki/Multiverse"&gt;Multiverse&lt;/a&gt;, there are literally infinite possibilities for stories.&lt;/p&gt;

&lt;p&gt;How can Marvel decide what direction to take with the MCU?&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;em&gt;What If?&lt;/em&gt; is Marvel's MVP
&lt;/h2&gt;

&lt;p&gt;There is no question Kevin Feige has sketched out the broad contours of the next iteration of the MCU. Still, as sterling as his record is, he's working from assumptions about what will make for great stories and what will thrill audiences going forward. If he followed &lt;em&gt;The Lean Startup&lt;/em&gt; model, he would build a lightweight MVP to test his hypotheses with passionate fans and measure their response for some validated learning.&lt;/p&gt;

&lt;p&gt;It turns out that is exactly what Marvel is doing with &lt;em&gt;What If?...&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What If?...&lt;/em&gt; is an &lt;a href="https://www.marvel.com/tv-shows/animation/what-if/1"&gt;animated show on Disney+&lt;/a&gt; that imagines the MCU heroes we know experiencing very different lives throughout the multiverse. For example, we see Peggy Carter receive the super soldier serum rather than Steve Rogers to become &lt;a href="https://www.marvel.com/articles/tv-shows/what-if-episode-1-multiverse-report-captain-carter"&gt;Captain Carter&lt;/a&gt;, and we watch somberly as T'Challa, voiced just as he is portrayed on screen by the legendary Chadwick Boseman in his final performance, &lt;a href="https://www.marvel.com/articles/tv-shows/what-if-new-images-episode-2"&gt;becomes Star-Lord&lt;/a&gt; rather than Peter Quill. It's heroes and villains we know so well from the MCU facing new challenges alongside other heroes and villains we've never seen them interact with before. &lt;/p&gt;

&lt;p&gt;The novel combinations are fun and exciting, but they're also an experiment. How will fans, primarily hardcore MCU fans (early adopters if you will) react? You can easily track this with viewership metrics on Disney+, mentions on Twitter, and the impressions of media influencers for validated learning. When a story doesn't click, Marvel can dismiss it as a fun idea for the fans and pivot to something else. On the other hand, when a story does click, Marvel can persevere and explore it further on a live-action series on Disney+ or even on the big screen within established MCU canon.&lt;/p&gt;

&lt;p&gt;Best of all, Marvel can test their hypotheses, engage in validated learning, and guide the future of the MCU accordingly at a low cost. &lt;em&gt;What If?...&lt;/em&gt; is high-quality animation, and most of the elite talent that portrays the characters on the big screen voices them on the show. Still, the cost of running these experiments in animation without any real commitment since the stories all happen outside the "prime" MCU universe is orders of magnitude less than it would be going all in with any of the &lt;em&gt;What If?...&lt;/em&gt; plots in live action.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Key Lesson
&lt;/h2&gt;

&lt;p&gt;One way or another, we are all in the business of product development. Too often we assume we have accurately gauged customer sentiment, and &lt;a href="https://www.youtube.com/watch?v=t-_PfdQ0DYo"&gt;we exude hubris that success is inevitable only to fail miserably&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Don't be afraid to test your assumptions before you go all in. Build a Minimum Viable Product--something more lightweight and less expensive that will nonetheless provide your early adopters something meaningful to evaluate. The validated learning you get from their feedback will either help you pivot to something more aligned with what people want or empower you to persevere with your original idea with legitimate confidence it  will sell. Once you start executing, then you can argue on Twitter about whether you need daily meetings and whether people should be allowed to sit down in them. &lt;/p&gt;

&lt;p&gt;Using an MVP to build confidence in your product direction is exactly what the Marvel Cinematic Universe has done with &lt;em&gt;What If?...&lt;/em&gt;, but you don't have to be Marvel to fly &lt;a href="https://www.youtube.com/watch?v=eKAvj9EjBmM"&gt;higher, further, faster, baby&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>agile</category>
      <category>leadership</category>
      <category>startup</category>
      <category>podcast</category>
    </item>
    <item>
      <title>Lessons Learned from Building a React Component Library with TypeScript</title>
      <dc:creator>Neil Chaudhuri</dc:creator>
      <pubDate>Tue, 19 Oct 2021 20:47:56 +0000</pubDate>
      <link>https://dev.to/realneilc/lessons-learned-from-building-a-react-component-library-with-typescript-3bkb</link>
      <guid>https://dev.to/realneilc/lessons-learned-from-building-a-react-component-library-with-typescript-3bkb</guid>
      <description>&lt;p&gt;Component libraries are all the rage. Shopify, Salesforce, IBM, and even the &lt;a href="https://designsystem.digital.gov/components/overview/" rel="noopener noreferrer"&gt;United States government&lt;/a&gt; have joined countless other organizations and businesses in building component libraries. They're the subject of blog posts, podcasts, and YouTube tutorials. All that's left is a &lt;a href="https://kenburns.com/the-films/" rel="noopener noreferrer"&gt;Ken Burns documentary&lt;/a&gt; on the subject.&lt;/p&gt;

&lt;p&gt;In fact, I am a software architect and senior engineer, and I currently lead the development of a React component library that will be the basis for the UIs for a prominent US government agency. I want to share with you my lessons learned in project management, communications, accessibility, engineering, and testing to build something that will impact the lives of millions. And the ups and downs of it all.&lt;/p&gt;

&lt;p&gt;So what's the big deal with component libraries?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Design System
&lt;/h2&gt;

&lt;p&gt;It doesn't start with a component library; it starts with a design system. The Nielsen Norman Group defines design systems &lt;a href="https://www.nngroup.com/articles/design-systems-101/" rel="noopener noreferrer"&gt;this way&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A design system is a complete set of standards intended to manage design at scale using reusable components and patterns.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A design system enumerates the standards and practices that comprise the premier UX for consumers of your brand. It expresses the nomenclature every team should use in communications to break down silos and avoid the impulse from &lt;a href="https://www.melconway.com/Home/Conways_Law.html" rel="noopener noreferrer"&gt;Conway's Law&lt;/a&gt;. There are basic rules about colors, typography, spacing, and so on. All of these core principles become the basis for larger components--explicit ones like buttons and date pickers and subtler ones like grid systems.&lt;/p&gt;

&lt;p&gt;Our UX team develops and maintains our design system. Like software, it evolves; it's versioned; and it's collaborative. There are conversations among the UX designers and with me and other architects and engineers on the program about what makes sense and what is feasible. Are nested dropdowns necessary? Do we have time to create our own perfect &lt;code&gt;Datepicker&lt;/code&gt;? Or do we try to customize something open source? How do we feel about disabled buttons, and if we think they make sense, how can we overcome common pitfalls like poor &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_WCAG/Perceivable/Color_contrast" rel="noopener noreferrer"&gt;contrast ratios&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;Stuff like that. We use the language of &lt;a href="https://bradfrost.com/blog/post/atomic-web-design/" rel="noopener noreferrer"&gt;Atomic Design&lt;/a&gt;, which deconstructs web interfaces into entities ranging from "atoms" to "pages," as a common nomenclature to describe the goals of the design system.&lt;/p&gt;

&lt;p&gt;The challenge, and probably the hardest part of building a component library for us, is the tooling. Partly because of the preferences of the UX team and partly because of constraints on our development environment due to the sensitive nature of our work, we have not been able to streamline automation for versioning UX wireframes or translating them into artifacts engineers can use to build. As a result, we work with wireframes that are cumbersome to understand. In order to even view them, we either need to install the tool on our machines, which costs more licenses and imposes a burden on developer experience (DX), or we need to wade through literally hundreds of static asset files with a custom browser plugin. Neither is an optimal experience. Beyond that, it's a manual process to track consistency between the design system and the component library as both evolve.&lt;/p&gt;

&lt;p&gt;I never said it was pretty, but it isn't all bad either.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Value of a Component Library
&lt;/h2&gt;

&lt;p&gt;The design system is a set of core principles independent of implementation details. You can choose to implement these principles and make them real for UI engineers with whatever technology you choose.&lt;/p&gt;

&lt;p&gt;For us, that's React. Our React components generate a lot of value for the program.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consistency
&lt;/h3&gt;

&lt;p&gt;Our component library enforces our design system across our development teams. Using the components all but guarantees a UI will be consistent with our brand and provide our users the best, most intuitive experience. Developers can feel confident they are using components vetted with the UX team, which frees them up to work on the specific use cases of their services rather than cross-cutting concerns like consistency with the design system.&lt;/p&gt;

&lt;p&gt;The library also maximizes the likelihood that our UIs pass visual testing by our UX team. This is important as violations slow down our delivery cadence and ability to get feedback.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessibility
&lt;/h3&gt;

&lt;p&gt;Related to consistency is accessibility, which is a first-class priority for our component library. Accessibility, commonly known as &lt;a href="https://www.a11yproject.com/" rel="noopener noreferrer"&gt;#a11y&lt;/a&gt;, is more than just empowering the visually impaired. It also means empowering people who experience difficulty with hearing, motion, dexterity, or anything else. It means empowering &lt;em&gt;everyone&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The program is required by contract and &lt;a href="https://www.access-board.gov/law/ra.html#section-508-federal-electronic-and-information-technology" rel="noopener noreferrer"&gt;by law&lt;/a&gt; to produce UIs that &lt;br&gt;
are accessible--specifically &lt;a href="https://www.section508.gov/tools/playbooks/technology-accessibility-playbook-intro/" rel="noopener noreferrer"&gt;508 compliance&lt;/a&gt;. That said, accessibility is far more than a professional obligation; it is my personal priority. It is very important to me that everything I build is intuitive for every user. &lt;/p&gt;

&lt;p&gt;I will elaborate on this shortly, but our component library is built for accessibility. Development teams can trust the accessibility of the individual components, and as I said before, focus on their own use cases. Of course you are probably thinking in terms of accessible dropdowns and autocompletes and datepickers, which we have, but we also provide helper &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Semantics#semantics_in_html" rel="noopener noreferrer"&gt;Semantic HTML&lt;/a&gt; components. For example, the library features &lt;code&gt;Section&lt;/code&gt;, which represents the &lt;code&gt;section&lt;/code&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section" rel="noopener noreferrer"&gt;HTML element&lt;/a&gt; as you would imagine, and &lt;code&gt;SectionGrid&lt;/code&gt;, which is a &lt;code&gt;section&lt;/code&gt; element endowed with our design system grid.&lt;/p&gt;

&lt;p&gt;Of course, the component library can only take developers part of the way to full accessibility, but it's nice not to have to start from 0.&lt;/p&gt;
&lt;h3&gt;
  
  
  Reusability
&lt;/h3&gt;

&lt;p&gt;We have worked very hard to provide intuitive APIs for our components, but the task is trickier than you might think. The APIs need to impose enough opinion so that consumers don't violate the design system but allow enough freedom for the components to support a wide range of use cases. For our &lt;code&gt;Button&lt;/code&gt; component, that is easy enough. For layout components like &lt;code&gt;Card&lt;/code&gt; and &lt;code&gt;Page&lt;/code&gt;, it's tougher. The reusability that results has made individual teams and the entire program so much more productive.&lt;/p&gt;

&lt;p&gt;We also go out of our way to endow our components with as little functionality as possible. Component APIs offer props that enable library consumers on the development teams to supply behavior. For an obvious example, developers supply &lt;code&gt;onClick&lt;/code&gt; behavior to the &lt;code&gt;Button&lt;/code&gt; component. We have more complex components that need to maintain their own state,&lt;br&gt;
but we try to minimize that where possible. This provides a clean separation of concerns, which makes testing our components much easier, and anyone who has been in the game long enough knows that strong testability makes for strong reusability.&lt;/p&gt;
&lt;h3&gt;
  
  
  Encapsulation
&lt;/h3&gt;

&lt;p&gt;There will be more about this shortly, but we do not build our components from scratch. Rather, we customize existing open source components and map our APIs to theirs. This abstracts the implementation details of the component from our development teams. For example, we use &lt;a href="https://github.com/Hacker0x01/react-datepicker" rel="noopener noreferrer"&gt;react-datepicker&lt;/a&gt; as the basis for our own &lt;code&gt;DatePicker&lt;/code&gt;, but if we decide to swap it out for a different one, our consumers will be none the wiser.&lt;/p&gt;
&lt;h2&gt;
  
  
  Component Stack
&lt;/h2&gt;

&lt;p&gt;As I mentioned, we build our component library with React, which is what we recommended but is also, for our risk-averse government customer, the safe choice given its backing by Facebook, &lt;a href="https://insights.stackoverflow.com/survey/2021#section-most-popular-technologies-web-frameworks" rel="noopener noreferrer"&gt;its market penetration&lt;/a&gt;, and &lt;a href="https://insights.stackoverflow.com/survey/2021#most-loved-dreaded-and-wanted-webframe-want" rel="noopener noreferrer"&gt;its popularity&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But React is the easy part. Let's look at other parts of the component stack.&lt;/p&gt;
&lt;h3&gt;
  
  
  TypeScript
&lt;/h3&gt;

&lt;p&gt;When we started building the component library, I considered TypeScript essential for two reasons. By enforcing type safety during development and at build time, we catch bugs much faster, which from a project management standpoint is much cheaper. More importantly, building our APIs in TypeScript is a huge help to library consumers on application development teams by facilitating code completion in their IDEs and type checking in &lt;em&gt;their&lt;/em&gt; builds.&lt;/p&gt;

&lt;p&gt;Let me also mention that some of our TypeScript APIs require &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA" rel="noopener noreferrer"&gt;ARIA&lt;/a&gt; values to promote accessibility if we can't derive them ourselves from other props.&lt;/p&gt;
&lt;h3&gt;
  
  
  Chakra UI
&lt;/h3&gt;

&lt;p&gt;I mentioned earlier that our components are built on open source components, and most of them are built on &lt;a href="https://chakra-ui.com/" rel="noopener noreferrer"&gt;Chakra UI&lt;/a&gt;. There are many other open source component libraries out there, but Chakra UI is my favorite by far. The primary reasons are its first-class commitment to accessibility and the intuitive APIs of its components built with TypeScript. As you can probably infer, Chakra UI is an inspiration to me when building our own &lt;br&gt;
component library on top of it.&lt;/p&gt;

&lt;p&gt;Chakra UI also offers a powerful &lt;a href="https://chakra-ui.com/docs/theming/customize-theme" rel="noopener noreferrer"&gt;theme customization API&lt;/a&gt; we leverage heavily to apply the principles of our design system to Chakra components via dedicated theme files that separate the styling from functionality. This separation of concerns makes it easier to reason about our code and makes the files themselves a lot lighter.&lt;/p&gt;

&lt;p&gt;Chakra UI also features with some helpful hooks like &lt;a href="https://chakra-ui.com/docs/hooks/use-disclosure" rel="noopener noreferrer"&gt;useDisclosure&lt;/a&gt; that come in handy. &lt;/p&gt;

&lt;p&gt;If you use Chakra UI for your own component library, you will probably need some alias imports to deal with name collisions. For example, we call our button components, to no one's surprise, &lt;code&gt;Button&lt;/code&gt;, but so does Chakra UI. So we do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Button as ChakraButton } from "@chakra-ui/react"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Engineering
&lt;/h2&gt;

&lt;p&gt;Of course the fun part is building a React component library. This post is long enough, so I can't get into every detail. But I do want to address some of the key aspects you might want to consider when you build your own.&lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow
&lt;/h3&gt;

&lt;p&gt;When we first began building the component library, we needed to move quickly because development teams were waiting on us &lt;br&gt;
to start building their UIs. Our management tasked me and several developers to get something done in a few sprints at nearly a full time commitment.&lt;/p&gt;

&lt;p&gt;We got the initial design system specification from the UX team and got to work. After those first few sprints, we had built enough components to allow teams to get going. The problem is that all of us resumed our normal duties with no time allocation for the library. This meant that whenever the UX team designed new components or developers found bugs in existing components, there was a bottleneck because no one was dedicated to upgrading the library. I and others got to it when we could, but the absence of a dedicated team was a problem.&lt;/p&gt;

&lt;p&gt;Another problem is the initial lack of communication within the UX team itself and among the UX team, developers, and me. In their creative zeal, far too often they provided wireframes to some developers inconsistent with wireframes provided to others, or they provided wireframes featuring components that weren't in the library. Development teams assumed they &lt;em&gt;were&lt;/em&gt; in the library and estimated accordingly. As you might expect, they were unhappy when they discovered the components didn't exist, which impacted their ability to deliver on schedule. They let me know it, and frankly they had every right to be unhappy. I knew we had to improve our process.&lt;/p&gt;

&lt;p&gt;To that end, we made some changes. We established a Microsoft Teams channel to encourage communication by eliminating the ceremony of meetings and even E-mails. We also decided that development teams will build new components initially, and if other teams will benefit, the library will absorb them, with tweaks as needed to APIs or implementations, to support broader applicability across the program. Then the team that built the component first will replace their implementation with the library's when ready. While this means teams have to devote more time to developing components, it's transparent, and there is no bottleneck. &lt;/p&gt;

&lt;p&gt;This is an evolving workflow. There is always room for improvement.&lt;/p&gt;
&lt;h3&gt;
  
  
  Component structure
&lt;/h3&gt;

&lt;p&gt;Our components in TypeScript take three forms.&lt;/p&gt;

&lt;p&gt;The simplest components look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const TimePicker = (p: TimePickerProps) =&amp;gt; {
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;TimePicker&lt;/code&gt; component has no children, so it's as straightforward as it gets. It's just a function!&lt;/p&gt;

&lt;p&gt;If the component has children, it still isn't too bad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const Card: React.FC&amp;lt;CardProps&amp;gt; = p =&amp;gt; {
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React's &lt;code&gt;FC&lt;/code&gt; type (for &lt;code&gt;FunctionComponent&lt;/code&gt;) includes a &lt;code&gt;children&lt;/code&gt; prop implicitly. We could also declare it just as we do &lt;code&gt;TimePicker&lt;/code&gt; but explicitly add a &lt;code&gt;children&lt;/code&gt; prop of type &lt;code&gt;ReactNode&lt;/code&gt; to &lt;code&gt;CardProps&lt;/code&gt;. I prefer &lt;code&gt;FC&lt;/code&gt; because it very clearly signifies the presence of &lt;code&gt;children&lt;/code&gt; to library consumers and because the type parameter lets me enjoy some type inference. Notice how I don't have to specify the type of &lt;code&gt;p&lt;/code&gt; because it's implicit from the type parameter &lt;code&gt;CardProps&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Still, not too bad, right?&lt;/p&gt;

&lt;p&gt;The last kind of component is a little complicated--form components. Our developers use &lt;a href="https://react-hook-form.com/" rel="noopener noreferrer"&gt;React Hook Form&lt;/a&gt;, and like every other form library I've used, it uses &lt;code&gt;ref&lt;/code&gt;s to maintain form state. This means our components need to provide a way to accept a &lt;code&gt;ref&lt;/code&gt; and delegate it to their children. &lt;/p&gt;

&lt;p&gt;Most React engineers don't know this because they don't have to, but React provides a function for exactly this purpose called &lt;code&gt;forwardRef&lt;/code&gt;, and we use it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const Button = React.forwardRef&amp;lt;HTMLButtonElement, ButtonProps&amp;gt;(function Button(p, ref) {
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me try to break this down.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://www.oreilly.com/library/view/functional-programming-in/9781492048633/ch04.html" rel="noopener noreferrer"&gt;higher-order function&lt;/a&gt; is a function that takes functions as parameters or returns a function. Here &lt;code&gt;forwardRef&lt;/code&gt; takes that &lt;code&gt;Button&lt;/code&gt; function that renders the component as a parameter. Thanks to &lt;code&gt;forwardRef&lt;/code&gt;, development teams can pass refs to the form components in our library, which we pass along though that function parameter to our rendered implementation. The type parameters to &lt;code&gt;forwardRef&lt;/code&gt; provide type safety and inference. The type of &lt;code&gt;p&lt;/code&gt; is &lt;code&gt;ButtonProps&lt;/code&gt;, and the &lt;code&gt;ref&lt;/code&gt; will be hooked onto a &lt;code&gt;HTMLButtonElement&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the end, it's a little complicated and a fair bit of ceremony, but the result is pretty simple--a form component that accepts a &lt;code&gt;ref&lt;/code&gt; from the caller so form libraries can work with it as needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Directory Structure
&lt;/h3&gt;

&lt;p&gt;When considering how to lay out your source code, it comes down to your team's preference, but as I tweeted recently:&lt;/p&gt;


&lt;blockquote&gt;
&lt;p&gt;There is a lot of commentary on how we should lay out source code in &lt;a href="https://twitter.com/hashtag/React?src=hash&amp;amp;ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;#React&lt;/a&gt;. If you take two "things" (functions, classes, &lt;a href="https://twitter.com/hashtag/TypeScript?src=hash&amp;amp;ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;#TypeScript&lt;/a&gt; interfaces, etc.), the higher the frequency that changing one changes the other, the closer they should be together&lt;/p&gt;— Neil Chaudhuri (&lt;a class="mentioned-user" href="https://dev.to/realneilc"&gt;@realneilc&lt;/a&gt;) &lt;a href="https://twitter.com/RealNeilC/status/1443309713584689154?ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;September 29, 2021&lt;/a&gt;
&lt;/blockquote&gt; 

&lt;p&gt;What does that really mean in practice?&lt;/p&gt;

&lt;p&gt;Simple. When it comes to our component library, this means organizing code dedicated to a particular component in the same directory and even in some cases the same file. This is how we do it at a high level.&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%2Fwicbqeb6ki290b7lmgm1.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%2Fwicbqeb6ki290b7lmgm1.png" alt="Button component directory layout"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;Button.tsx&lt;/code&gt; contains the &lt;code&gt;ButtonProps&lt;/code&gt; interface, related types, and of course the component itself. Meanwhile, I love how Chakra UI allows us to separate theming from behavior, so the colors, spacing, font family, icon sizes, focus behavior, and other button details defined by our design system are in &lt;code&gt;ButtonTheme.ts&lt;/code&gt;, a different file in the same directory.&lt;/p&gt;

&lt;p&gt;Finally, although we could keep our tests and stories (more on these later) in the same directory, we prefer organizing them in their own subdirectories. I guess I've seen too much Marie Kondo.&lt;/p&gt;
&lt;h3&gt;
  
  
  TypeScript Config
&lt;/h3&gt;

&lt;p&gt;I come from a background in &lt;a href="https://stackoverflow.com/questions/2690544/what-is-the-difference-between-a-strongly-typed-language-and-a-statically-typed" rel="noopener noreferrer"&gt;statically and strongly typed programming languages&lt;/a&gt; like Java and Scala. While I understand longtime JavaScript engineers balk at types, I find types make me extremely productive. As a result, our TypeScript config is very strict. In particular from our &lt;code&gt;tsconfig.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
...
  "compilerOptions": {
    ...
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitAny": true,
    ...
  },
...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As for building the library for application development teams, we scope our &lt;code&gt;tsconfig.json&lt;/code&gt; this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
...
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "**/__stories__/*",
    "**/__test__/*"
  ],
...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All our components, stories, and tests are in the &lt;code&gt;src&lt;/code&gt; directory, but we only want the components when we build the library. This is why we exclude the &lt;code&gt;__stories__&lt;/code&gt; and &lt;code&gt;__test__&lt;/code&gt; directories inside each component directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Static Analysis and Code Formatting
&lt;/h3&gt;

&lt;p&gt;Like everyone else, we rely on eslint and Prettier, and we don't do anything particularly special. Still, I do want to mention a couple of things.&lt;/p&gt;

&lt;p&gt;First is &lt;code&gt;eslint-plugin-jsx-a11y&lt;/code&gt;. We use &lt;a href="https://github.com/jsx-eslint/eslint-plugin-jsx-a11y" rel="noopener noreferrer"&gt;this eslint plugin&lt;/a&gt; to automate verification of the accessibility of our component library. It checks the JSX of our components for obvious violations. This is as far as we can go with automation, but we complement &lt;code&gt;eslint-plugin-jsx-a11y&lt;/code&gt; with manual auditing in Storybook I will discuss shortly.&lt;/p&gt;

&lt;p&gt;There might be something gnawing at the experienced engineers reading this. In the &lt;code&gt;tsconfig.json&lt;/code&gt; above, we exclude our stories and tests because they don't belong in the build. Still, you know we should apply the same quality standards to story code and test code as we do to production code. Code is code.&lt;/p&gt;

&lt;p&gt;To do this, we &lt;a href="https://www.typescriptlang.org/tsconfig#extends" rel="noopener noreferrer"&gt;extend&lt;/a&gt; &lt;code&gt;tsconfig.json&lt;/code&gt; in a file called &lt;code&gt;tsconfig.eslint.json&lt;/code&gt;,&lt;br&gt;
replacing the &lt;code&gt;exclude&lt;/code&gt; field with an empty array, and configure &lt;code&gt;eslint&lt;/code&gt; to use &lt;em&gt;that&lt;/em&gt;. This tells &lt;code&gt;eslint&lt;/code&gt; (and therefore Prettier) to include &lt;em&gt;everything&lt;/em&gt; in the &lt;code&gt;src&lt;/code&gt; folder in its analysis with identical TypeScript configuration. This means, for example, we can't cheat by using an implicit &lt;code&gt;any&lt;/code&gt; in our stories or tests either.&lt;/p&gt;
&lt;h3&gt;
  
  
  Builds
&lt;/h3&gt;

&lt;p&gt;We run our builds with &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt;. That may seem counterintuitive since Vite is the build tool for &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue&lt;/a&gt; while our library is built with React, but Vite is actually agnostic. In fact, it amazed me how little configuration we needed. It basically just worked. Our Vite config is almost identical to the &lt;a href="https://vitejs.dev/guide/build.html#library-mode" rel="noopener noreferrer"&gt;example in the documentation&lt;/a&gt;. Just like the example, our build produces two bundle formats--&lt;code&gt;es&lt;/code&gt; and &lt;code&gt;umd&lt;/code&gt;--and it works fast.&lt;/p&gt;

&lt;p&gt;As you may know, TypeScript builds feature two phases, type checking and transpilation to JavaScript. Type checking by &lt;code&gt;tsc&lt;/code&gt;, the TypeScript compiler, is &lt;em&gt;very&lt;/em&gt; slow, so while it is very important, you should do it rarely. We only do it via the IDE in real time as we code or when we build the library for production--and break the build if type checking fails.&lt;/p&gt;

&lt;p&gt;We have a dedicated &lt;code&gt;typecheck&lt;/code&gt; script in our &lt;code&gt;package.json&lt;/code&gt; that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "scripts": {
    ...
    "typecheck": "tsc --p tsconfig.eslint.json --skipLibCheck --sourceRoot src --noEmit",
    ...
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we use &lt;code&gt;tsconfig.eslint.json&lt;/code&gt; to typecheck everything.&lt;/p&gt;

&lt;p&gt;Meanwhile, transpiling your TypeScript source code to JavaScript is faster than type checking, but so is reading Tolstoy. Transpiling with &lt;code&gt;tsc&lt;/code&gt; or Babel is still not fast. However, the transpiler &lt;a href="https://esbuild.github.io/" rel="noopener noreferrer"&gt;esbuild&lt;/a&gt; is written in Go, a language &lt;a href="https://www.vidyasource.com/blog/scala-go" rel="noopener noreferrer"&gt;built for speed&lt;/a&gt;, and Vite uses it under the hood. Because we are transpiling constantly to see what's happening in Storybook, it's crucial that the process be fast. Thanks to esbuild, Vite does exactly what we need.&lt;/p&gt;

&lt;p&gt;Our production build, versioned with &lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;Semantic Versioning&lt;/a&gt;, includes &lt;a href="https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html" rel="noopener noreferrer"&gt;declaration files&lt;/a&gt; for each component and an &lt;code&gt;index.d.ts&lt;/code&gt; file enumerating all components. These improve DX by enabling developers' IDEs to perform fast code completion. We also provide the &lt;a href="https://chakra-ui.com/docs/theming/customize-theme" rel="noopener noreferrer"&gt;theme file&lt;/a&gt; we use for our own components so that developers can apply the same theme to theirs. Our CI/CD pipeline publishes the library to a private NPM registry, which allows appropriately configured &lt;code&gt;npm&lt;/code&gt; installations on developer machines to fetch the library with a conventional &lt;code&gt;npm install&lt;/code&gt;. The &lt;code&gt;package.json&lt;/code&gt; file accompanying the library contains all the peer dependencies they will need to use the library so &lt;code&gt;npm&lt;/code&gt; can grab them, and for convenience it also contains the version of the design system it is built with for developers to track.&lt;/p&gt;

&lt;p&gt;It also contains configurations to define which files to package in the library and how consumers can import modules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
...  
  "files": [
    "dist"
  ],
  "types": "./dist/index.d.ts",
  "main": "./dist/components.umd.js",
  "module": "./dist/components.es.js",
  "exports": {
    ".": {
      "import": "./dist/components.es.js",
      "require": "./dist/components.umd.js"
    }
  }
...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One last thing to note about the build. Although Vite of course provides minifying and other production readiness capabilities, we don't use them. We bundle the component library completely "raw." We find this helps developers debug their applications and report bugs (in those rare cases we make mistakes) with specificity. When they run their own builds, their tooling will apply minifying, tree shaking, and all other production processing to all their code and dependencies including the component library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;As I mentioned before, we limit the functionality of our components to the bare minimum necessary to add value. Still, components are code, and our consumers have expectations of our code. This means we need to test our components as much as we can and where it makes sense.&lt;/p&gt;

&lt;p&gt;Testing is a controversial topic. On Tech Twitter, engineers are more than happy to let you know why you are wrong to test your code in a different way than they do. I can only describe what works for us and why we think so while also stipulating that our methods are subject to change as we get better at this.&lt;/p&gt;

&lt;p&gt;Our approach is heavily inspired by this &lt;a href="https://storybook.js.org/blog/how-to-actually-test-uis/" rel="noopener noreferrer"&gt;Storybook blog post&lt;/a&gt;. In it, &lt;a href="https://twitter.com/winkerVSbecks" rel="noopener noreferrer"&gt;Varun Cachar&lt;/a&gt; describes different types of testing, when each is appropriate, and which tools make sense for which types based on the experiences of several large-scale engineering teams. &lt;/p&gt;

&lt;h3&gt;
  
  
  Storybook
&lt;/h3&gt;

&lt;p&gt;Storybook is crucial to the development and testing of the component library for us, and it's indispensable documentation for our users.&lt;/p&gt;

&lt;p&gt;During development, we use it in a couple of ways. If the component is simple, then it's nice to have your code and Storybook side by side and watch your changes render as you make them with hot reload. On the other hand, when we aren't clear on what the API for a component should be, it's nice to write a few &lt;a href="https://storybook.js.org/docs/react/get-started/whats-a-story" rel="noopener noreferrer"&gt;stories&lt;/a&gt; to work out the DX for it. Experienced engineers might recognize this approach as analogous to &lt;br&gt;
&lt;a href="https://www.agilealliance.org/glossary/tdd/" rel="noopener noreferrer"&gt;Test-Driven Development (TDD)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We apply our design system custom theme in Chakra UI to every story in &lt;code&gt;preview.jsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const decorators = [Story =&amp;gt; &amp;lt;ChakraProvider theme={theme}&amp;gt;{Story()}&amp;lt;/ChakraProvider&amp;gt;]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During testing, we also use Storybook in multiple ways. For example, because we take a mobile first approach to our components, which matters for &lt;a href="https://bradfrost.com/blog/post/atomic-web-design/#organisms" rel="noopener noreferrer"&gt;organisms&lt;/a&gt; in particular like modals, we configure custom breakpoints like this in &lt;code&gt;preview.jsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const parameters = {
    viewport: {
        viewports: {
            xs: {
                name: "XS",
                styles: {
                    height: "568px",
                    width: "320px",
                },
                type: "mobile",
            },
            sm: {
                name: "SM",
                styles: {
                    height: "896px",
                    width: "480px",
                },
                type: "mobile",
            },
            md: {...},
            lg: {...},
            xl: {...},
        defaultViewport: "xs",
    },
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I mentioned a CI/CD pipeline that builds the library and publishes it to a private registry. It turns out the pipeline also publishes our component Storybook to an &lt;a href="https://hub.docker.com/_/nginx" rel="noopener noreferrer"&gt;Nginx container&lt;/a&gt; so that the UX team can conduct visual testing on the components, and the ability to toggle among viewport sizes is extremely helpful. &lt;/p&gt;

&lt;p&gt;It's also helpful for development teams who use our components to interact with them. Thanks to &lt;a href="https://storybook.js.org/docs/react/essentials/controls" rel="noopener noreferrer"&gt;Storybook Controls&lt;/a&gt;, they can configure components themselves to see what happens. Thanks to &lt;a href="https://storybook.js.org/addons/@storybook/addon-docs" rel="noopener noreferrer"&gt;Storybook Docs&lt;/a&gt;, they can see the code and API props that generate each story. So Storybook provides a profound documentation benefit throughout the program.&lt;/p&gt;

&lt;p&gt;We also use Storybook for &lt;a href="https://storybook.js.org/blog/how-to-actually-test-uis/" rel="noopener noreferrer"&gt;composition testing&lt;/a&gt; occasionally though not as often as the Storybook team may prefer. For example, we have stories that demonstrate how to integrate our form components with React Hook Form, and this exposed issues we had with our &lt;code&gt;ref&lt;/code&gt;s. Generally though, we don't do a lot of composition testing until we need to &lt;a href="https://www.vidyasource.com/blog/code-coverage-is-killing-you" rel="noopener noreferrer"&gt;reproduce a scenario to fix a bug&lt;/a&gt; (and prove we've fixed it eventually).&lt;/p&gt;

&lt;p&gt;We make heavy use of &lt;a href="https://storybook.js.org/addons/@storybook/addon-a11y" rel="noopener noreferrer"&gt;storybook-addon-a11y&lt;/a&gt; to test for accessibility. As you can see from another post by &lt;a href="https://twitter.com/winkerVSbecks" rel="noopener noreferrer"&gt;Varun Cachar&lt;/a&gt;, who is definitely earning his paycheck, &lt;a href="https://storybook.js.org/blog/accessibility-testing-with-storybook/" rel="noopener noreferrer"&gt;Storybook offers a lot of features for accessibility testing&lt;/a&gt;. We make use of all of them. As I mentioned before, even though we do our best with &lt;code&gt;jsx-a11y&lt;/code&gt; in the build and Storybook visually to test for accessibility, it is still incumbent upon teams to add &lt;a href="https://www.npmjs.com/package/@axe-core/react" rel="noopener noreferrer"&gt;@axe-core/react&lt;/a&gt; to &lt;em&gt;their&lt;/em&gt; builds and perform their own visual tests in order to feel as confident as we can that we are providing the best possible experience to all our users.&lt;/p&gt;

&lt;p&gt;Finally, while Storybook has been invaluable for us and I recommend it strongly, I would be remiss if I didn't mention some gotchas. Storybook uses a lot of the same libraries we all use for theming, Markdown, and other things. When there are library conflicts between your version and theirs, bad things happen. For example, we got hit with the same conflict on &lt;a href="https://emotion.sh/docs/introduction" rel="noopener noreferrer"&gt;Emotion&lt;/a&gt; as this &lt;a href="https://github.com/storybookjs/storybook/issues/15879" rel="noopener noreferrer"&gt;issue on GitHub&lt;/a&gt;. To its credit, the Storybook team releases frequently. If nothing else, make sure you use identical versions of Storybook and all its addons and that you upgrade as soon as possible when updates are available. &lt;/p&gt;

&lt;p&gt;Storybook is also well aware of the "DivOps" revolution in JavaScript build tooling &lt;a href="https://storybook.js.org/blog/storybook-for-webpack-5/" rel="noopener noreferrer"&gt;and is positioning itself accordingly&lt;/a&gt;. This is exciting since Webpack had a good run but feels more and more like the past, and we wanted to use Vite with Storybook. We installed &lt;a href="https://storybook.js.org/blog/storybook-for-vite/" rel="noopener noreferrer"&gt;storybook-builder-vite&lt;/a&gt; knowing it's experimental to see how it would work for us. Overall, it makes our Storybook builds fast just as we hoped. Still, when you consider &lt;code&gt;storybook-builder-vite&lt;/code&gt; is raw, community-led by great engineers who have already given the community so much with their limited time and can't address every issue, and the general brittleness of Storybook I mentioned, your mileage may vary. Here is our Vite-related Storybook configuration 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 plaintext"&gt;&lt;code&gt;module.exports = {
    ...
    core: {
        builder: "storybook-builder-vite"
    },
    viteFinal: async config =&amp;gt; {
        return {
            ...config,
            plugins: ...,
            optimizeDeps: {
                ...config.optimizeDeps,
                entries: [`${path.relative(config.root, path.resolve(__dirname, "../src"))}/**/__stories__/*.stories.@(ts|tsx)`],
            },
        }
    },
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  React Testing Library
&lt;/h3&gt;

&lt;p&gt;If you have read any of my posts on testing, you know that I think our industry writ large gets testing wrong. We test some things too much. We test other things too little. We don't always know the purpose of our tests. And worst of all, because of perverse incentives, &lt;a href="https://www.vidyasource.com/blog/code-coverage-is-killing-you" rel="noopener noreferrer"&gt;we write tests to check a box&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I mentioned earlier that it has been a priority to endow our components with as little behavior as possible. Aside from the fact simpler code is easier to maintain and understand, this approach means fewer surprises for our consumers and less for us to test.&lt;/p&gt;

&lt;p&gt;Or so I thought.&lt;/p&gt;

&lt;p&gt;Our program has a mandatory minimum of 80% code coverage for our applications, and for reasons that don't make a lot of sense to me, that also applies to the component library. In my view, only components that maintain internal state offer the complexity that demands the ceremony of formal tests beyond Storybook, but alas, I don't make the rules.&lt;/p&gt;

&lt;p&gt;React Testing Library has become the &lt;em&gt;de facto&lt;/em&gt; standard for &lt;a href="https://storybook.js.org/blog/how-to-actually-test-uis/" rel="noopener noreferrer"&gt;interaction testing&lt;/a&gt; in React, and of course we use it for our own tests. But how could we write tests as quickly as possible to limit the impact of the code coverage standard?&lt;/p&gt;

&lt;p&gt;If you have written tests in any programming language, you understand the concept of "&lt;a href="https://stackoverflow.com/questions/12071344/what-are-fixtures-in-programming" rel="noopener noreferrer"&gt;test fixtures&lt;/a&gt;," the setup for your tests. For us, that means test fixtures are simply components configured with different props.&lt;/p&gt;

&lt;p&gt;But isn't that exactly what stories in Storybook are?&lt;/p&gt;

&lt;p&gt;Storybook offers a feature I love--the ability to import stories into tests written with React Testing Library as fixtures using&lt;br&gt;
&lt;a href="https://storybook.js.org/addons/@storybook/testing-react" rel="noopener noreferrer"&gt;@storybook/testing-react&lt;/a&gt;. Without it, we would need to duplicate &lt;br&gt;
the same code as stories in Storybook and fixtures in tests. The autocompletion is great too thanks to the TypeScript support built into &lt;code&gt;@storybook/testing-react&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One last thing I want to mention is, as you might guess given how much I have emphasized it in this post, accessibility. All of our tests in React Testing Library use &lt;code&gt;getByRole&lt;/code&gt; and &lt;code&gt;findByRole&lt;/code&gt; selectors. We do this because it is a way to build implicit accessibility testing into our interaction tests as &lt;a href="https://testing-library.com/docs/queries/about#priority" rel="noopener noreferrer"&gt;the documentation describes&lt;/a&gt;. After all, if we are unable to locate the component we wish to test by its ARIA role, that all but guarantees it isn't accessible. And if it isn't accessible, I don't care if it "works" because it doesn't work for everyone.&lt;/p&gt;

&lt;p&gt;Aside from all that, our tests work exactly as you would expect if you know React Testing Library. Here is an example of a simple test conveying everything I described:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
import {
    DefaultMediumPrimaryButton,
    ...
} from "../__stories__/Button.stories"

test("Button primary display works", () =&amp;gt; {
    const onClickMock = jest.fn()

    render(&amp;lt;DefaultMediumPrimaryButton onClick={onClickMock} /&amp;gt;)

    const button = screen.getByRole("button", { name: "Primary" })

    userEvent.click(button)
    expect(onClickMock).toHaveBeenCalledTimes(1)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;I know this is a lot, and it might have been slightly more entertaining as an audiobook. Still, I hope I conveyed the value in design systems and component libraries and the lessons we learned in project management, communications, accessibility, engineering, and testing to build something that will impact the lives of millions. I hope you can do the same...but better.&lt;/p&gt;

&lt;p&gt;Now go take a nap. You earned it.&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>a11y</category>
    </item>
    <item>
      <title>Scala or Go: Who Wore It Better?</title>
      <dc:creator>Neil Chaudhuri</dc:creator>
      <pubDate>Tue, 07 Sep 2021 02:49:32 +0000</pubDate>
      <link>https://dev.to/realneilc/scala-or-go-who-wore-it-better-38af</link>
      <guid>https://dev.to/realneilc/scala-or-go-who-wore-it-better-38af</guid>
      <description>&lt;p&gt;Scala and Go are two of the fastest growing leading-edge programming languages in the world. In the United States, they are also among the &lt;a href="https://adtmag.com/articles/2017/08/18/go-scala-salaries.aspx"&gt;most lucrative&lt;/a&gt;. Scala and Go are among a slew of programming languages that innovate in numerous ways to produce faster, more resilient, more secure applications for a multicore, cloud native, mobile world.   &lt;/p&gt;

&lt;p&gt;The thing is Scala and Go have &lt;em&gt;very&lt;/em&gt; different philosophies on what makes engineers most productive and what defines great applications. We are going to look at how Scala and Go solve five common programming tasks and how their contrasting approaches reflect their contrasting philosophies. Then you can decide for yourself which works best for your next application. This is a really long post, so here are the tasks we will consider so you can jump to the ones that interest you most:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Absent Values&lt;/li&gt;
&lt;li&gt;Error Handling&lt;/li&gt;
&lt;li&gt;Collections&lt;/li&gt;
&lt;li&gt;Concurrency and Parallelism&lt;/li&gt;
&lt;li&gt;Polymorphism&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or you can skip straight to my conclusion, which boils down to this: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Despite the strong possibility that this opinion will subject me to ritual humiliation on social media, I would use Scala (or a similarly featured language like Kotlin) for microservices or bigger but Go both to replace any bash or Python scripts that are part of my continuous delivery pipeline and to create lambda functions, which are supposed to be lightweight, fast, and focused.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With that, let me introduce you to Scala and Go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scala
&lt;/h2&gt;

&lt;p&gt;Scala is an object-oriented (OO) &lt;em&gt;and&lt;/em&gt; functional programming language built for the JVM (though &lt;a href="https://scala-native.readthedocs.io/en/latest/"&gt;Scala Native&lt;/a&gt; is in the works). It emerged from academia at the &lt;a href="https://scala.epfl.ch/"&gt;EPFL&lt;/a&gt; in Switzerland from the mind of Academic Director Martin Odersky, who sought to prove that the two paradigms--OO for representing your domain and functional for its &lt;a href="https://www.vidyasource.com/blog/business-case-for-functional-programming"&gt;mathematical guarantees for working programs&lt;/a&gt;--can blend seamlessly to yield the best of both worlds. Scala also has an exquisite static type system that can provide a powerful safety net.  &lt;/p&gt;

&lt;p&gt;Operationally, as you might expect from a language borne from academia, Scala tooling can be problematic and compilation can be slow--particularly if you are not yet using Scala 3, which only recently emerged and is very slowly percolating through the ecosystem (Remember the Python 2 to Python 3 transition?). But type inference, a vast standard library, and the time-tested reliability of the JVM make you very productive once you get the hang of them. Performance varies with the JVM you're running, but regardless you do have to contend with the size of compiled objects and the latency of garbage collection at runtime. When you want to experiment, you can skip the ceremony of writing a class or test and instead use a command-line REPL, an online REPL called &lt;a href="https://scastie.scala-lang.org/"&gt;Scastie&lt;/a&gt; you can share, or an outstanding third-party command-line REPL called &lt;a href="https://ammonite.io/#Ammonite-REPL"&gt;Ammonite&lt;/a&gt;. Dependency management is achieved with SBT typically but also more general JVM build tools like Gradle and Maven.&lt;/p&gt;

&lt;p&gt;Scala became really popular with the advent of "Big Data" because &lt;a href="https://www.vidyasource.com/blog/java-is-dysfunctional-with-big-data/"&gt;functional programming lends itself so naturally to analytics&lt;/a&gt;, and the learning curve for &lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/Lisp_(programming_language)#2000_to_present"&gt;modern LISPs like Haskell and Clojure&lt;/a&gt; is too high for too many. Apache Spark is built in Scala, and when it got big, Scala got big. Since then Scala has also become a popular language for other domains including &lt;a href="https://www.reactivemanifesto.org/"&gt;reactive web applications and microservices&lt;/a&gt; with &lt;a href="https://www.playframework.com/"&gt;Play Framework&lt;/a&gt; and &lt;a href="https://akka.io/"&gt;Akka&lt;/a&gt; and even the front end with &lt;a href="https://www.scala-js.org/"&gt;Scala.js&lt;/a&gt;.  &lt;/p&gt;
&lt;h2&gt;
  
  
  Go
&lt;/h2&gt;

&lt;p&gt;Go had an pragmatic mission from the start, so it was built with simplicity, minimalism, and performance in mind. Robert Griesemer, Rob Pike, and Ken Thompson created Go at Google as an &lt;a href="https://talks.golang.org/2015/gophercon-goevolution.slide#4"&gt;alternative to C++&lt;/a&gt; built for modern machines. Go is compiled to native machine code; no virtual machine. Go is statically typed like Scala but is imperative and procedural. It's not a functional language &lt;em&gt;per se&lt;/em&gt;, but &lt;a href="https://golangbot.com/first-class-functions/"&gt;functions are first-class&lt;/a&gt;. Where it &lt;br&gt;
truly shines is in its concurrency primitives: &lt;a href="https://medium.com/rungo/anatomy-of-channels-in-go-concurrency-in-go-1ec336086adb"&gt;channels and goroutines&lt;/a&gt;. Together, they enable you to leverage the full power of your multicore machine. &lt;/p&gt;

&lt;p&gt;Operationally, Go is really fast to compile and run. It too has a vast standard library for common tasks like &lt;a href="https://golang.org/pkg/net/http/"&gt;REST calls&lt;/a&gt; and &lt;a href="https://golang.org/pkg/encoding/json/"&gt;JSON de/serialization&lt;/a&gt;. When you want to experiment, you can use the &lt;a href="https://play.golang.org/"&gt;Go Playground&lt;/a&gt; or a scratch file in your IDE, but there is no command-line REPL. Unlike Scala, Go has by design a very lean feature set and simple constructs. This makes it relatively easy to learn. However, you have to add a lot of features yourself that you take for granted in other languages or explore what Go offers as &lt;a href="https://golang.org/doc/faq#Why_doesnt_Go_have_feature_X"&gt;potential workarounds&lt;/a&gt;. To get &lt;em&gt;really&lt;/em&gt; good at advanced features of Go like concurrency and polymorphism is still a challenge. Official dependency management is nonexistent, and you may find Go's unorthodox project setup based on Git repos &lt;a href="https://medium.com/rungo/working-in-go-workspace-3b0576e0534a"&gt;takes getting used to&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;After Go took off at Google and was released to the public, it got really popular as the language of concurrency, which helped in turn to make it the language of DevOps--particularly in concert with &lt;a href="https://rancher.com/using-kubernetes-api-go-kubecon-2017-session-recap/"&gt;Kubernetes&lt;/a&gt;, which also emerged from Google. Go has expanded into other domains as well with the CMS &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt; and the microservices framework &lt;a href="https://gokit.io/"&gt;Go kit&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Comparing Scala and Go
&lt;/h2&gt;

&lt;p&gt;Let's look at how Scala and Go handle the kinds of real-world problems you will encounter every day.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer:&lt;/em&gt; The sample code is not meant to showcase necessarily the "best" way to solve these problems--most performant, most elegant, or whatever. Instead it is meant to showcase reasonable, idiomatic solutions and, more importantly, how they reflect the design philosophies of the respective languages. Of course &lt;a href="https://www.vidyasource.com/contact"&gt;you are welcome to suggest improvements&lt;/a&gt; regardless. Also, the Scala code uses some of the revolutionary &lt;a href="https://docs.scala-lang.org/scala3/new-in-scala3.html"&gt;Scala 3&lt;/a&gt; syntax and constructs.&lt;/p&gt;
&lt;h3&gt;
  
  
  Absent values
&lt;/h3&gt;

&lt;p&gt;You have to deal with potentially absent values all the time like when database queries for single entities return no hits or when you are maintaining backwards-compatible microservices. Typically, absent values are represented with &lt;code&gt;null&lt;/code&gt;. Sir Tony Hoare called his invention of &lt;code&gt;null&lt;/code&gt; to represent the absence of a value his "&lt;a href="https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare"&gt;billion-dollar mistake&lt;/a&gt;." Handling absent values isn't glamorous, but if you do it poorly, you will suffer significant productivity loses. &lt;/p&gt;
&lt;h4&gt;
  
  
  Scala
&lt;/h4&gt;

&lt;p&gt;Although &lt;code&gt;null&lt;/code&gt; exists in Scala as a JVM language, you should (almost) never interact with it directly. Instead, you should work with &lt;code&gt;Option&lt;/code&gt;, a &lt;a href="https://stackoverflow.com/questions/44965/what-is-a-monad"&gt;monad&lt;/a&gt; designed specifically for this purpose. We describe &lt;code&gt;Option&lt;/code&gt; in more detail in &lt;a href="https://www.youtube.com/watch?v=rbZ6GzR8B7I"&gt;our tutorial&lt;/a&gt;, but essentially it compels you to account for the potential absence of a value at &lt;em&gt;compile&lt;/em&gt; time. This avoids the costly &lt;code&gt;NullPointerException&lt;/code&gt; at runtime that has sent thousands of Java developers to therapy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;case class Student(name: String, house: String)

def findStudent(key: Int): Option[Student] = {
  val students = Map(
    1 -&amp;gt; Student("Harry Potter", "Hogwarts"),
    3 -&amp;gt; Student("Draco Malfoy", "Slytherin")
  )
  students.get(key)
}

findStudent(3)
  .map(s =&amp;gt; s"The student's name is ${s.name}")
  .getOrElse("Back to Hogwarts")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;findStudent&lt;/code&gt; function returns an &lt;code&gt;Option[Student]&lt;/code&gt;. If the &lt;code&gt;Option&lt;/code&gt; contains a value, the client can transform it into a &lt;code&gt;String&lt;/code&gt; (&lt;em&gt;i.e.&lt;/em&gt; &lt;code&gt;Option[Student] =&amp;gt; Option[String]&lt;/code&gt;) with the &lt;code&gt;map&lt;/code&gt; function on &lt;code&gt;Option&lt;/code&gt;; otherwise, &lt;code&gt;getOrElse&lt;/code&gt; handles the absent value.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Option&lt;/code&gt; allows you to safely work with potentially absent values &lt;a href="https://marvel.fandom.com/wiki/Daredevil:_The_Man_Without_Fear_Vol_1_1"&gt;without fear&lt;/a&gt;. The compile-time safety makes you very productive. On the other hand, every transformation on the &lt;code&gt;Option&lt;/code&gt;--via &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, &lt;em&gt;etc.&lt;/em&gt;--produces a new value because of the functional programming bias towards &lt;a href="https://dev.to/blog/business-case-for-functional-programming"&gt;immutability&lt;/a&gt;. If memory is at a premium, maybe this is a concern.&lt;/p&gt;

&lt;h4&gt;
  
  
  Go
&lt;/h4&gt;

&lt;p&gt;Go handles potentially absent values through completely different idioms. Functions can return multiple return values. When a value is present, it's idiomatic to return the value and a &lt;code&gt;bool&lt;/code&gt; value (named &lt;code&gt;ok&lt;/code&gt; by convention) of &lt;code&gt;true&lt;/code&gt;; otherwise, it returns the &lt;a href="https://tour.golang.org/basics/12"&gt;"zero value" of the return type&lt;/a&gt; and &lt;code&gt;false&lt;/code&gt;. The client uses an imperative &lt;code&gt;if&lt;/code&gt; statement to distinguish.&lt;br&gt;
&lt;/p&gt;

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

import "fmt"

type Student struct {
    name string
    house string
}

func findStudent(key int) (Student, bool) {
    students := map[int]Student{
       1: Student{name: "Harry Potter", house: "Hogwarts"}, 
       3: Student{name: "Draco Malfoy", house: "Slytherin"}
    }
    student, ok := students[key]
    return student, ok
}

func main() {
    if student, ok := findStudent(3); ok {
        fmt.Printf("The student's name is %v\n", student.name)
    } else {
        fmt.Println("Back to Hogwarts")
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;findStudent&lt;/code&gt; function returns a &lt;code&gt;Student&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; a &lt;code&gt;bool&lt;/code&gt;. Go allows you to initialize and test conditions in one line, and that's what we see here. If &lt;code&gt;ok&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;, we know we got something and act accordingly; if &lt;code&gt;ok&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;, we know the value is absent and handle this contingency.&lt;/p&gt;

&lt;p&gt;For those uncomfortable with monad composition and higher-order functions, Go provides a very simple alternative in keeping with its mission. On the other hand, Go engineers need the knowledge and discipline to apply these language features and idioms. There is no dedicated type like &lt;code&gt;Option&lt;/code&gt; to help. Also, unlike with the composability afforded by monads like &lt;code&gt;Option&lt;/code&gt;, if you need to compose multiple potentially absent values, you need to write multiple &lt;code&gt;if&lt;/code&gt; conditions; that can feel verbose. The simplicity may well be worth it though.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error Handling
&lt;/h3&gt;

&lt;p&gt;This is another inglorious task that is critical to good software engineering. As programs become big and complex, proper error handling is critical to diagnose bugs and move builds to production as quickly as possible. &lt;/p&gt;

&lt;h4&gt;
  
  
  Scala
&lt;/h4&gt;

&lt;p&gt;As you might imagine from a language that prizes on immutability and composability, Scala offers another monad, &lt;code&gt;Try&lt;/code&gt;, for error handling. Analogous to &lt;code&gt;Option&lt;/code&gt;, it compels you to account for a possible error at compile time rather than the absence of a value. A &lt;code&gt;Try[Double]&lt;/code&gt;, for example, represents either a &lt;code&gt;Double&lt;/code&gt; if all is well or an error (or more precisely an instance of &lt;code&gt;Throwable&lt;/code&gt;) otherwise.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import scala.util.{Failure, Success, Try}

def squareRoot(value: Int): Try[Double] = {
  if (value &amp;gt;= 0) {
    Success(Math.sqrt(value))
  } else {
    Failure(new IllegalArgumentException("Value cannot be negative"))
  }
}
val sum = for
  a &amp;lt;- squareRoot(4)
  b &amp;lt;- squareRoot(16)
yield a + b
sum.map(s =&amp;gt; s"The result is $s") match {
  case Success(result) =&amp;gt; result
  case Failure(t) =&amp;gt; t.getMessage
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;squareRoot&lt;/code&gt; function returns &lt;code&gt;Try[Double]&lt;/code&gt;, and the client does something a bit more complicated than the prior example. It calls &lt;code&gt;squareRoot&lt;/code&gt; twice and uses a &lt;a href="https://docs.scala-lang.org/tour/for-comprehensions.html"&gt;for comprehension&lt;/a&gt;, which is syntactic sugar for otherwise cumbersome &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;flatMap&lt;/code&gt; transformations, to take advantage of the composability of monads to sum the results. If both calls work out, then the result is a &lt;code&gt;Try&lt;/code&gt; with the sum; if either fails, the error information is passed on. You can do similar with &lt;code&gt;Option&lt;/code&gt; too. This is why monad composability in Scala is so cool. The same pattern works on very different types as long as they follow the &lt;a href="https://miklos-martin.github.io/learn/fp/2016/03/10/monad-laws-for-regular-developers.html"&gt;monad laws&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As before though, keep in mind that you are generating new objects with each transformation. This means you're paying for the protection immutability affords you with memory.&lt;/p&gt;

&lt;h4&gt;
  
  
  Go
&lt;/h4&gt;

&lt;p&gt;Just as &lt;code&gt;Option&lt;/code&gt; and &lt;code&gt;Try&lt;/code&gt; in Scala are similar, handling absent values and handling errors in Go is similar. Here again Go takes advantage of multiple return values, but rather than a value accompanied by a &lt;code&gt;bool&lt;/code&gt;, idiomatic Go error handling features a value accompanied by an &lt;code&gt;Error&lt;/code&gt; (named &lt;code&gt;err&lt;/code&gt; by convention). If &lt;code&gt;err&lt;/code&gt; has the value of &lt;code&gt;nil&lt;/code&gt;, then you can work with the value because it's all good; otherwise, you handle the error and (probably) ignore the zero-value.&lt;br&gt;
&lt;/p&gt;

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

import "fmt"
import "math"

func squareRoot(value int) (float64, error) {
    if value &amp;gt;= 0 {
        return math.Sqrt(float64(value)), nil
    } else {
        return 0, fmt.Errorf("invalid input: %v", value)
    }
}

func sumRoots(v1, v2 int) (float64, error) {
    a, err := squareRoot(v1)
    if err != nil {
        return 0, err
    }
    b, err := squareRoot(v2)
    if err != nil {
        return 0, err
    }

    return a + b, nil
}

func main() {
    if sum, err := sumRoots(4, 16); err == nil {
        fmt.Printf("The sum is %v\n", sum)
        return
    } else {
        fmt.Println("Value cannot be negative")
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;sumRoots&lt;/code&gt; function, which is the client of &lt;code&gt;squareRoot&lt;/code&gt;, returns a value and an error. Those are saved from the first call to &lt;code&gt;squareRoot&lt;/code&gt;. If there is an error, the function returns immediately; otherwise, it does the same with the second call to &lt;code&gt;squareRoot&lt;/code&gt;. If the function makes it to the end, then it returns the sum and a &lt;code&gt;nil&lt;/code&gt; error. You will see a similar approach in &lt;code&gt;main&lt;/code&gt; with the call to &lt;code&gt;sumRoots&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are a few interesting things to note. First, once again the code reflects Go's bias toward simplicity. Furthermore, as immutability is not a priority, variable reuse is common in Go. In this case, &lt;code&gt;err&lt;/code&gt; is reused to store the error returned from &lt;code&gt;squareRoot&lt;/code&gt;. It doesn't happen here, but it isn't unheard of to reuse the value variable as well once its initial value has served its purpose. Finally, we see a common pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Call a function&lt;/li&gt;
&lt;li&gt;Test &lt;code&gt;err&lt;/code&gt; for &lt;code&gt;nil&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If an error is found, return&lt;/li&gt;
&lt;li&gt;Call the next function&lt;/li&gt;
&lt;li&gt;Test &lt;code&gt;err&lt;/code&gt; for &lt;code&gt;nil&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If an error is found, return&lt;/li&gt;
&lt;li&gt;Lather, rinse, repeat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Absent Scala's function composition, it's a fair bit of boilerplate--particularly when you are calling a lot of functions that may return errors. You can take advantage of language features to make it more elegant like &lt;br&gt;
&lt;a href="https://golang.org/doc/faq#exceptions"&gt;this pattern utilizing interfaces and pointers from Rob Pike&lt;/a&gt;, but this is one of the ways where Go's simplicity is a bit overrated. Building custom abstractions from Go's toolkit requires creativity, and you will have to do that often when you use Go to build mature applications. Still, it is almost certainly easier to master advanced patterns in Go than it is in Scala.&lt;/p&gt;

&lt;p&gt;Finally, even though it doesn't appear in this example, &lt;code&gt;defer&lt;/code&gt; &lt;a href="https://gobyexample.com/defer"&gt;is a simple but powerful construct&lt;/a&gt; in Go that executes a call at the end of a function no matter what happens--error or otherwise. You can use &lt;code&gt;defer&lt;/code&gt; to clean things up after an error in the same way you'd use &lt;code&gt;finally&lt;/code&gt; in other languages. &lt;/p&gt;
&lt;h3&gt;
  
  
  Collections
&lt;/h3&gt;

&lt;p&gt;I don't have to tell you that manipulating data from a database, a &lt;a href="https://medium.com/stream-processing/what-is-stream-processing-1eadfca11b97"&gt;stream&lt;/a&gt;, a REST request, or a host of other sources is a common task in application development. Languages that facilitate seamless transformation and aggregation of collections of data make your life a lot easier.&lt;/p&gt;
&lt;h4&gt;
  
  
  Scala
&lt;/h4&gt;

&lt;p&gt;Scala has a vast library of collections--both immutable and mutable though immutable is preferred--each of which offers in turn a vast collection of higher-order functions that let you manipulate the collection in numerous ways.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val words = List("Fear", "of", "a", "name", "only", "increases", "fear", "of", "the", "thing", "itself")

words
  .groupBy(_.toLowerCase)
  .mapValues(_.size)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, given a &lt;code&gt;List&lt;/code&gt; of words, the code uses &lt;code&gt;groupBy&lt;/code&gt; to convert it into a &lt;code&gt;Map&lt;/code&gt; of each word (lowercased to normalize them) to a list of occurrences of each word. Finally, those lists are transformed into their sizes, and the result is a &lt;code&gt;Map&lt;/code&gt; of each word to its count.&lt;/p&gt;

&lt;p&gt;There isn't much to see. This is a credit to Scala's powerful abstractions. Still, it is important to keep in mind that this code performs multiple &lt;em&gt;O(n)&lt;/em&gt; traversals and with each one consumes memory to produce an entirely new collection--all but the first and last of which are immediately thrown away. &lt;/p&gt;

&lt;h4&gt;
  
  
  Go
&lt;/h4&gt;

&lt;p&gt;Go naturally takes a far more lightweight approach to collections. You will essentially only deal with &lt;a href="https://blog.golang.org/go-maps-in-action"&gt;maps&lt;/a&gt; and &lt;a href="https://blog.golang.org/go-slices-usage-and-internals"&gt;slices&lt;/a&gt;, which are array views that enable memory-efficient operations on the backing arrays.&lt;br&gt;
&lt;/p&gt;

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

import "fmt"
import "strings"

func main() {
    dictionary := make(map[string]int)
    words := []string{"Fear", "of", "a", "name", "only", "increases", "fear", "of", "the", "thing", "itself"}
    for _, word := range words {
        word = strings.ToLower(word)
        if count, ok := dictionary[word]; ok {
            dictionary[word] = count + 1
        } else {
            dictionary[word] = 1
        }
    }

    fmt.Printf("The counts are %v\n", dictionary)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the code uses &lt;code&gt;make&lt;/code&gt; both to create an empty map (with values defaulting to the zero value, in this case literally 0) to hold the word counts and to create a slice containing the words. It simply iterates over the slice and builds the word count using the &lt;code&gt;ok&lt;/code&gt; idiom you saw before to check if there is an existing entry for the word in the map.&lt;/p&gt;

&lt;p&gt;The code is more verbose than its Scala counterpart, but it is significantly more efficient in time and space. There is a single &lt;em&gt;O(n)&lt;/em&gt; traversal with constant-time lookups in the map, and we maintain only two collections the entire time. The efficiency of Go collections and the simplicity of using them are among the best reasons to use Go in a project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Concurrency and Parallelism
&lt;/h3&gt;

&lt;p&gt;Modern software applications have a lot more to do in a lot less time, so it's important for your code to take advantage of every bit of power your machines have. Modern applications demand modern languages that enable you to leverage every core through abstractions that strike the right balance of power and intuitiveness. Perhaps most importantly, they need to provide mechanisms for handling errors because concurrent/parallel programming is notoriously hard to debug. It's a challenge to reproduce the conditions that generated the bug in the first place.&lt;/p&gt;

&lt;p&gt;By the way, as Rob Pike has taught us, &lt;a href="https://www.youtube.com/watch?v=cN_DpYBzKso"&gt;concurrency is not parallelism&lt;/a&gt;. Long story short, concurrency is about decomposing a problem into its components; each component might then run in parallel depending on available resources. Concurrency &lt;em&gt;manages&lt;/em&gt; a lot of things at once while &lt;em&gt;parallelism&lt;/em&gt; does a lot of things at once. &lt;/p&gt;

&lt;p&gt;Regardless, doing concurrency and parallelism well is a hard problem. Whatever path you choose, you need to understand the nature of your tasks to achieve peak performance. Are they IO- or CPU-intensive? Are they intrinsically parallel?&lt;/p&gt;

&lt;h4&gt;
  
  
  Scala
&lt;/h4&gt;

&lt;p&gt;As a core language in &lt;a href="https://www.reactivemanifesto.org/"&gt;reactive programming&lt;/a&gt;, Scala takes concurrency and parallelism very seriously. It offers &lt;code&gt;Future&lt;/code&gt; as its &lt;a href="https://docs.scala-lang.org/overviews/core/futures.html"&gt;core primitive&lt;/a&gt; to facilitate concurrency and parallelism--in concert with an &lt;code&gt;ExecutionContext&lt;/code&gt;, which is basically a &lt;a href="https://www.playframework.com/documentation/2.7.x/ThreadPools"&gt;thread pool&lt;/a&gt;. &lt;code&gt;Future&lt;/code&gt; abstracts the threads away from you, which is nice, but its association with &lt;code&gt;ExecutionContext&lt;/code&gt; can lead to some &lt;a href="https://stackoverflow.com/questions/27454798/is-future-in-scala-a-monad"&gt;complexity&lt;/a&gt; in understanding &lt;a href="http://www.beyondthelines.net/computing/scala-future-and-execution-context/"&gt;how they work&lt;/a&gt;. This is why notable &lt;a href="https://alvinalexander.com/scala/differences-scalaz-task-scala-future-referential-lazy"&gt;third-party libraries&lt;/a&gt; offer their own concurrency primitives. Still, &lt;code&gt;Future&lt;/code&gt; at least approximates a monad, and that means we can &lt;em&gt;mostly&lt;/em&gt; adhere to the familiar patterns we saw with &lt;code&gt;Option&lt;/code&gt; and &lt;code&gt;Try&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At a low level, each asynchronous call delegates to a different thread. This helps scale your application, but it's also a heavyweight operation as the operating system needs to schedule threads against physical processors and manage expensive context switching. The result is that for some problems parallelism with &lt;code&gt;Future&lt;/code&gt; in Scala may potentially consume a lot of resources for merely a modest increase in performance--or even slow you down. When performance is a major concern, you need to configure your &lt;code&gt;ExecutionContext&lt;/code&gt; smartly according to the capability of your machine(s) and the nature of your tasks.&lt;/p&gt;

&lt;p&gt;Bottom line? Reactive programming doesn't necessarily make your applications faster (except maybe in those cases where you can do expensive work in parallel), but it usually allows them to be more resilient. Reactive applications scale under load with limited threads and memory especially when you have latency from inconsistent network IO like database and REST calls.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import play.api.libs.ws._
import play.api.libs.ws.ahc._

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits._
import play.api.libs.json._

implicit val system = ActorSystem()
system.registerOnTermination {
  System.exit(0)
}
implicit val materializer = ActorMaterializer()
val ws = StandaloneAhcWSClient()

def getUuid: Future[String] = {
  ws.url("https://httpbin.org/uuid")
    .withHttpHeaders("Accept" -&amp;gt; "application/json")
    .get
    .map { response =&amp;gt;
      (response.body[JsValue] \ "uuid").as[String]
    }
}
val uuid1: Future[String] = getUuid
val uuid2: Future[String] = getUuid
val uuids = for
  u1 &amp;lt;- uuid1
  u2 &amp;lt;- uuid2
yield (u1, u2)
uuids
  .foreach {
    case (u1, u2) =&amp;gt; println(s"UUIDs: $u1, $u2")
  }
  .andThen { case _ =&amp;gt; ws.close() }
  .andThen { case _ =&amp;gt; system.terminate() }
  .recover {
    case t: Throwable =&amp;gt; println(s"There was a problem: $t")
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the code uses &lt;a href="https://github.com/playframework/play-ws"&gt;Play WS Standalone&lt;/a&gt; as a REST client to fetch JSON containing a &lt;a href="https://en.wikipedia.org/wiki/Universally_unique_identifier"&gt;UUID&lt;/a&gt;. Play WS has an asynchronous, non-blocking API based on &lt;code&gt;Future&lt;/code&gt;, so you need to provide an &lt;code&gt;ExecutionContext&lt;/code&gt; via &lt;a href="https://doc.akka.io/docs/akka/2.5/stream/"&gt;Akka&lt;/a&gt;. That's all the boilerplate at the beginning of this example. Sometimes it will be done for you as when you use Play WS in the context of &lt;a href="https://www.playframework.com/"&gt;Play Framework&lt;/a&gt;. Nonetheless, you should be aware it has to happen somewhere.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;getUuid&lt;/code&gt; function, the &lt;code&gt;get&lt;/code&gt; call to Play WS makes an asynchronous, non-blocking HTTP GET request and returns a &lt;code&gt;Future&lt;/code&gt; containing the response. You need to be careful and make sure you only work directly with the &lt;code&gt;Future&lt;/code&gt; itself lest you lose the eventual result--the response or an error. Otherwise anything you do next outside the realm of the asynchronous call will execute after the request is dispatched but completely independently from when the response returns. That's a common mistake for engineers new to &lt;code&gt;Future&lt;/code&gt;. This is why everything that happens after the call in &lt;code&gt;getUuid&lt;/code&gt; is dispatched is a method call on the &lt;code&gt;Future&lt;/code&gt; object that comes back.&lt;/p&gt;

&lt;p&gt;Like a typical monad, &lt;code&gt;Future&lt;/code&gt; offers &lt;code&gt;map&lt;/code&gt; to enable clients to transform results, and &lt;code&gt;getUuid&lt;/code&gt; does exactly that by parsing the JSON response into the UUID string and returning a &lt;code&gt;Future[String]&lt;/code&gt;. If the REST call returned an error, it remains preserved in the &lt;code&gt;Future.&lt;/code&gt; The client of &lt;code&gt;getUuid&lt;/code&gt; requires two calls to complete before moving forward, so it calls the function twice so the independent fetches can run in parallel and composes them as we saw with &lt;code&gt;Try&lt;/code&gt; via &lt;code&gt;for&lt;/code&gt; comprehension to produce a &lt;code&gt;Future[Tuple2[String, String]]&lt;/code&gt;. Finally, the code calls &lt;code&gt;map&lt;/code&gt; again to transform the tuple of strings into a printed result. If there is an error any step of the way, we handle it with &lt;code&gt;recover&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Future&lt;/code&gt; is a really nice concurrency primitive that offers the convenience of a monad, but it has its pitfalls. As mentioned, you need to supply a finely tuned &lt;code&gt;ExecutionContext&lt;/code&gt;, and everything you do once you make an asynchronous call better happen in the context of the &lt;code&gt;Future&lt;/code&gt; that returns. Otherwise, you will find very confusing results like silent failures. The &lt;a href="https://www.reddit.com/r/scala/comments/3zofjl/why_is_future_totally_unusable/"&gt;amorphous referential transparency&lt;/a&gt; of &lt;code&gt;Future&lt;/code&gt; can confuse you too. If the code made its calls to &lt;code&gt;getUuid&lt;/code&gt; inside the &lt;code&gt;for&lt;/code&gt; comprehension, they would have been sequential and not parallel. The result is likely the same, which &lt;em&gt;feels&lt;/em&gt; &lt;a href="https://alvinalexander.com/scala/how-to-create-scala-methods-no-side-effects-pure-functions#referential-transparency"&gt;referentially transparent&lt;/a&gt;, but the fact where you make the call impacts the desired parallelism definitely doesn't. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Future&lt;/code&gt; also consumes a lot of system resources because it transacts in full threads that have to managed by the operating system. It's important to profile your application to understand what's going on because there will almost be certainly occasions where things don't perform as you expect. You will need to diagnose if it is a code or resource problem.&lt;/p&gt;

&lt;h4&gt;
  
  
  Go
&lt;/h4&gt;

&lt;p&gt;Concurrency and parallelism lie at the heart of Go's mission as well, but of course it takes a totally different approach with primitives called &lt;a href="https://tour.golang.org/concurrency/1"&gt;goroutines&lt;/a&gt; and &lt;a href="https://gobyexample.com/channels"&gt;channels&lt;/a&gt;. The philosophy here is to break down your tasks into independent functions, and spin them off into goroutines. The key thing to remember is &lt;a href="https://golang.org/doc/faq#goroutines"&gt;goroutines are not threads&lt;/a&gt;; they are lightweight pieces of memory tracking thread usage. As a result, you can spin off literally hundreds of thousands of goroutines and use only a little memory on the stack while the Go scheduler, not you, uses clever algorithms to manage them in concert with the operating system and its actual threads.&lt;/p&gt;

&lt;p&gt;Goroutines use a paradigm called &lt;a href="https://en.wikipedia.org/wiki/Communicating_sequential_processes"&gt;communicating sequential processes&lt;/a&gt; (CSP) developed by Sir Tony Hoare, who despite being the &lt;code&gt;null&lt;/code&gt; guy is a pillar of computer science. CSP is a message-passing model. Goroutines pass their data over channels rather than synchronize data, which slows things down. If you are familiar with messaging patterns like &lt;a href="https://www.enterpriseintegrationpatterns.com/"&gt;Gregor Hohpe's Enterprise Integration Patterns&lt;/a&gt;, then you understand the power of this approach to manipulate message data as needed to produce the results you want--and at scale thanks to Go.&lt;br&gt;
&lt;/p&gt;

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

import (
    "encoding/json"
    "fmt"
    "net/http"
    "strings"
)

type Result struct {
    uuid string
    err error
}

func getUuid(rc chan&amp;lt;- Result) {
    r, err := http.Get("https://httpbin.org/uuid")
    if err != nil {
        rc &amp;lt;- Result{"", err}
        return
    }
    response := make(map[string]interface{})
    err = json.NewDecoder(r.Body).Decode(&amp;amp;response)
    if err != nil {
        rc &amp;lt;- Result{"", err}
        return
    }
    rc &amp;lt;- Result{response["uuid"].(string), nil}
}

func main() {
    n := 2
    rc := make(chan Result, n)
    uuids := make([]string, 0, n)
    for i := 0; i &amp;lt; n; i++ {
        go getUuid(rc)
    }
    for i := 0; i &amp;lt; n; i++ {
        r := &amp;lt;-rc
        if r.err != nil {
            fmt.Printf("There was a problem: %v\n", r.err)
            return
        } else {
            uuids = append(uuids, r.uuid)
        }
    }
    fmt.Printf("UUIDs: %v\n", strings.Join(uuids, ", "))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the code defines a type called &lt;code&gt;Result&lt;/code&gt; containing a UUID and an error to hold the result of a concurrent computation. Only one of those should be populated with a meaningful value, but there is no simple way to enforce that. Meanwhile, the &lt;code&gt;main&lt;/code&gt; function creates a &lt;a href="https://gobyexample.com/channel-buffering"&gt;buffered channel&lt;/a&gt; for communicating &lt;code&gt;Result&lt;/code&gt; values and spins off two goroutines for two concurrent &lt;code&gt;getUuid&lt;/code&gt; calls, which take the channel as a write-only parameter. That &lt;em&gt;is&lt;/em&gt; enforceable.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;getUuid&lt;/code&gt; function makes the REST call and unmarshals the JSON response. If an error occurs at either step, the code creates a &lt;code&gt;Result&lt;/code&gt; with the respective error (and the zero value, the empty string, for the UUID) and publishes it to the channel. If all goes well, the code creates a &lt;code&gt;Result&lt;/code&gt; with the UUID (and the zero value, &lt;code&gt;nil&lt;/code&gt;, for the error) and publishes it to the channel instead. The &lt;code&gt;main&lt;/code&gt; function knows in this case how many &lt;code&gt;Results&lt;/code&gt; to expect from the channel and consumes the right amount of data from the channel. It bails at the first error it finds, or it accumulates the data into a slice of UUIDs.&lt;/p&gt;

&lt;p&gt;Goroutines are lightweight and flexible--and straightforward if you have a good grasp on messaging. Still, there are subtleties that can make them more complicated than we might expect from Go. If you don't understand the difference between buffered and unbuffered channels, you may find &lt;a href="https://stackoverflow.com/questions/18660533/why-using-unbuffered-channel-in-the-same-goroutine-gives-a-deadlock"&gt;curious results&lt;/a&gt;. Error handling is also tricky because patterns aren't obvious. In this case we encapsulated success and error cases in a single struct, but some advise using &lt;a href="https://stackoverflow.com/a/42890750/1347281"&gt;dedicated error channels&lt;/a&gt;. This example is also as simple as it gets: You have one channel, and you know how many computations will transpire. In more complicated cases you will need to utilize other Go functionality from the &lt;a href="https://golang.org/pkg/sync/"&gt;sync&lt;/a&gt; package like &lt;code&gt;Mutex&lt;/code&gt;, &lt;code&gt;WaitGroup&lt;/code&gt;, &lt;code&gt;Pool&lt;/code&gt;. You might even need the &lt;a href="https://rodaine.com/2017/05/x-files-intro/"&gt;experimental&lt;/a&gt; &lt;code&gt;ErrGroup&lt;/code&gt;. Finally, you need to be very careful with &lt;a href="https://tour.golang.org/moretypes/1"&gt;pointers&lt;/a&gt; and mutability generally as always in concurrent programming. They save memory but you need to govern access carefully.&lt;/p&gt;

&lt;p&gt;Concurrency and parallelism are always hard. You have to decide which language offers primitives that comport with your mental model of how things should work.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Polymorphism
&lt;/h3&gt;

&lt;p&gt;You know polymorphism. Far beyond trite &lt;code&gt;Animal&lt;/code&gt;-&lt;code&gt;Dog&lt;/code&gt;-&lt;code&gt;Cat&lt;/code&gt; examples, the business value of polymorphism is to leverage abstractions to limit changes to your code even as the functionality of your application grows. By defining new behavior leveraged through old abstractions, you can build software efficiently, and you don't have to work weekends when your client demands new features immediately.&lt;/p&gt;

&lt;h4&gt;
  
  
  Scala
&lt;/h4&gt;

&lt;p&gt;As an OO language, Scala offers the familiar polymorphism that developers in Java, Ruby, and similar languages have loved for years, but because it is a functional language with a rich type system, it also offers &lt;br&gt;
&lt;a href="https://medium.com/@sinisalouc/ad-hoc-polymorphism-and-type-classes-442ae22e5342"&gt;typeclass polymorphism&lt;/a&gt;, which enables completely unrelated types to exhibit polymorphic behavior. You can think of it as functional programming's take on the &lt;a href="https://stackify.com/solid-design-open-closed-principle/"&gt;Open-Closed Principle&lt;/a&gt; from OO. Perhaps most striking of all&lt;br&gt;
in comparison to Go, Scala offers parametric polymorphism--what the kids call "generics." When &lt;a href="https://docs.oracle.com/javase/tutorial/extra/generics/index.html"&gt;Java 5 introduced generics&lt;/a&gt;, it was revolutionary, and Scala benefits as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Runtime polymorphism

trait Closeable:
  def name: String
  def close: String

case class Connection(override val name: String, database: String) extends Closeable:
  override def close: String = s"Closing connection $name"


case class File(override val name: String, opener: String) extends Closeable:
  override def close: String = s"Closing file $name"


def showClosing(c: Closeable): String = c.close

val w = Connection("MyConnection", "PostgreSQL")
val f = File("file.txt", "TextEdit")
showClosing(w)
showClosing(f)


// Parameteric polymorphism (generics) with List[T]

val numbers = List(1, 2, 3)
val firstNumber: Int = numbers.head

val strings = List("1", "2", "3")
val firstString: String = strings.head

def use[T &amp;lt;: File](t: T) = s"Using ${t.name}"

use(f)


// Typeclass polymorphism

case class Complex(real: Double, imaginary: Double)

object Complex:
  given Ordering[Complex] with
    def compare(a: Complex, b: Complex): Int = a.real.compare(b.real)


List(Complex(3, 5), Complex(10, 2), Complex(1, 6)).sorted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we really see three examples of polymorphism in Scala. The first is the kind of straightforward &lt;a href="https://stackoverflow.com/questions/28961957/example-of-runtime-polymorphism-in-java"&gt;runtime polymorphism&lt;/a&gt; familiar to Java developers--except with &lt;a href="https://stackoverflow.com/questions/16410298/what-are-the-differences-and-similarties-between-scala-traits-vs-java-8-interfa"&gt;Scala traits rather than Java interfaces&lt;/a&gt;. &lt;code&gt;Connection&lt;/code&gt; and &lt;code&gt;File&lt;/code&gt; are marked as instances of &lt;code&gt;Closeable&lt;/code&gt;, and the &lt;code&gt;showClosing&lt;/code&gt; function accepts a &lt;code&gt;Closeable&lt;/code&gt; parameter. Therefore either &lt;code&gt;Connection&lt;/code&gt; or &lt;code&gt;File&lt;/code&gt; is suitable to pass to &lt;code&gt;showClosing&lt;/code&gt; and the result of the function is dynamically and polymorphically resolved.&lt;/p&gt;

&lt;p&gt;The second example of polymorphism is also familiar to Java developers. It's generics. In Scala, you never have just &lt;code&gt;List&lt;/code&gt;; you have &lt;code&gt;List[T]&lt;/code&gt;, where &lt;code&gt;T&lt;/code&gt; is a type parameter indicating the type of item in the &lt;code&gt;List&lt;/code&gt;. Scala's type inference deduces that &lt;code&gt;numbers&lt;/code&gt; is an instance of &lt;code&gt;List[Int]&lt;/code&gt;; &lt;code&gt;strings&lt;/code&gt; is an instance of &lt;code&gt;List[String]&lt;/code&gt;. The &lt;code&gt;head&lt;/code&gt; method returns the first element of a &lt;code&gt;List&lt;/code&gt;, which is a &lt;code&gt;T&lt;/code&gt;. &lt;code&gt;T&lt;/code&gt; is &lt;code&gt;Int&lt;/code&gt; with &lt;code&gt;numbers&lt;/code&gt; and &lt;code&gt;String&lt;/code&gt; with &lt;code&gt;strings&lt;/code&gt;. Finally, just for demonstration purposes, the code defines a function &lt;code&gt;use&lt;/code&gt; that's not only type parameterized but type bounded. It only accepts a type that's &lt;code&gt;File&lt;/code&gt; or any subclass of &lt;code&gt;File&lt;/code&gt;. If you try passing a &lt;code&gt;Connection&lt;/code&gt; to it, the code won't compile.&lt;/p&gt;

&lt;p&gt;The last example is what I consider the coolest and most powerful form of polymorphism in Scala--typeclass polymorphism. &lt;code&gt;List&lt;/code&gt; has a &lt;code&gt;sorted&lt;/code&gt; method as you'd hope, but it requires an &lt;a href="https://www.scala-lang.org/api/current/scala/collection/immutable/List.html#sorted%5BB%3E:A%5D(implicitord:scala.math.Ordering%5BB%5D):Repr"&gt;implicit ordering&lt;/a&gt;. In other words, you have to tell &lt;code&gt;List[T]&lt;/code&gt; how to sort its elements by providing a function that &lt;a href="https://stackoverflow.com/questions/17965059/what-is-lifting-in-scala"&gt;lifts&lt;/a&gt; &lt;code&gt;T&lt;/code&gt; into an &lt;code&gt;Ordering[T]&lt;/code&gt;. This makes perfect sense, and it is enforced by Scala's type system. The code defines a type called &lt;code&gt;Complex&lt;/code&gt; and a way to lift &lt;code&gt;Complex&lt;/code&gt; to &lt;code&gt;Ordering[Complex]&lt;/code&gt; that defines how instances of &lt;code&gt;Complex&lt;/code&gt; should be sorted. Without this, &lt;code&gt;List[Complex]&lt;/code&gt; wouldn't know how to sort its contents, and that last line wouldn't compile. This means you can make any &lt;code&gt;T&lt;/code&gt; sortable by defining an &lt;code&gt;Ordering[T]&lt;/code&gt; typeclass. More broadly, it means you can use typeclasses to add polymorphic behavior to completely unrelated types, which includes types you don't control like legacy types and/or types found in imported dependencies. &lt;/p&gt;

&lt;p&gt;Polymorphism in Scala is powerful and flexible because of its sophisticated type system. It allows you not only to extend functionality in clever ways but also to constrain the solution space. In other words, you can limit the number of ways a problem can be solved, which makes it harder to write bugs.     &lt;/p&gt;

&lt;h4&gt;
  
  
  Go
&lt;/h4&gt;

&lt;p&gt;Go is not an OO language. Structs have no capacity for inheritance by design--only composition via "&lt;a href="https://golang.org/doc/effective_go.html#embedding"&gt;embedding&lt;/a&gt;". Go is not quite functional either. However, polymorphic behavior is not only possible but a fundamental part of the power of Go via &lt;a href="https://en.wikipedia.org/wiki/Structural_type_system"&gt;structural typing&lt;/a&gt;. You can take advantage by doing two things. First, you write &lt;a href="https://gobyexample.com/interfaces"&gt;interfaces&lt;/a&gt;, which as usual define the method signatures for a set of API calls. You can also compose interfaces via embedding. Second, you can endow any type--an existing Go type like &lt;code&gt;float64&lt;/code&gt; or your own custom structs--with behavior by defining functions and assigning them to the type. When you do this, the type is called a "&lt;a href="https://tour.golang.org/methods/8"&gt;receiver&lt;/a&gt;", and if the receiver has been assigned all the functions associated with a given interface, it is an implicit instance of that interface. You can then pass the type to any function expecting an instance of that interface, and it's resolved at compile time, which makes you more productive in stark contrast to the runtime resolution of &lt;a href="https://en.wikipedia.org/wiki/Duck_typing"&gt;duck typing&lt;/a&gt; in dynamic languages like Python.&lt;br&gt;
&lt;/p&gt;

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

import (
    "fmt"
)

type Named struct {
    name string
}

type Connection struct {
    Named
    database string
}

type Closeable interface {
    close() string
}

func (c Connection) close() string {
    return fmt.Sprintf("Closing connection %v", c.name)
}

type File struct {
    Named
    opener string
}

func (f File) close() string {
    return fmt.Sprintf("Closing %v", f.name)
}

func showClosing(c Closeable) string {
    return c.close()
}

func main() {
    connection := Connection{Named{name: "MyConnection"}, "PostgreSQL"}
    file := File{Named{name: "file.txt"}, "TextEdit"}
    fmt.Println(showClosing(connection))
    fmt.Println(showClosing(file))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, interface &lt;code&gt;Named&lt;/code&gt; is embedded in &lt;code&gt;Connection&lt;/code&gt; and &lt;code&gt;File&lt;/code&gt;. Note that this does not denote any relationship among them, but there is a tight coupling similar to inheritance in that any changes to &lt;code&gt;Named&lt;/code&gt; are reflected wherever it is embedded. Interface &lt;code&gt;Closeable&lt;/code&gt; is defined with a single function &lt;code&gt;close&lt;/code&gt; with no parameters and returning a &lt;code&gt;string&lt;/code&gt;. Any type with an identical function is resolved at compile time as an instance of &lt;code&gt;Closeable&lt;/code&gt;, and lucky for us, &lt;code&gt;Connection&lt;/code&gt; and &lt;code&gt;File&lt;/code&gt; qualify as they are both receivers of a &lt;code&gt;close&lt;/code&gt; function with the right signature. As a result, &lt;code&gt;showClosing&lt;/code&gt; works just fine when called on both kinds of structs.&lt;/p&gt;

&lt;p&gt;That's the extent of Go's polymorphism. Clearly it is not remotely as extensive as Scala's, but it promotes two important values--composition over inheritance and abstraction over implementation. Engineers coming from traditional OO backgrounds may find Go's polymorphism takes a little getting used to, but with some creativity you will find it &lt;br&gt;
&lt;a href="https://talks.golang.org/2015/json.slide#1"&gt;quite powerful&lt;/a&gt;. There is no question, however, that the absence of generics&lt;br&gt;
can be quite jarring for more complex applications. It's such a powerful and pervasive idiom that even front end languages like &lt;a href="https://www.typescriptlang.org/docs/handbook/generics.html"&gt;TypeScript&lt;/a&gt; and &lt;a href="https://elmprogramming.com/type-system.html"&gt;Elm&lt;/a&gt; have it. As it happens, there has been such demand for generics from the Go community that &lt;a href="https://go.googlesource.com/proposal/+/master/design/go2draft-generics-overview.md"&gt;the maintainers have begun considering it&lt;/a&gt;. As the debate rages on whether the benefits outweigh the costs--potentially the speed and simplicity fundamental to Go's mission--just recognize you won't have the benefit of generics for a while.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do You Decide?
&lt;/h2&gt;

&lt;p&gt;Scala and Go are two great languages with fundamentally different philosophies that offer distinct advantages and disadvantages. I've tried to lay those out as simply as I can so you can extrapolate which might be best suited to your situation. &lt;/p&gt;

&lt;p&gt;Having worked on complex applications with both languages, I can tell you Scala takes longer to grasp, and you will have a harder time finding Scala engineers--especially in the United States and especially if you require onsite work. But if you have senior staff who can mentor novices and who can build abstractions that utilize functional programming's strengths &lt;br&gt;
and the exquisite type system to constrain wayward novices, you will find the team growing very productive very quickly. Day-to-day tasks like compilation and continuous delivery are slower, and you will often find yourself exploring Scala's rich open-source community to enhance development.&lt;/p&gt;

&lt;p&gt;Meanwhile, anyone can learn Go. The constructs are simple and lightweight, and compiling and executing are just so fast. It's amazing. Mastering the more advanced concepts of Go, however, demands effort. You will also find yourself reinventing the wheel from other languages often--like writing your own &lt;code&gt;filter&lt;/code&gt; function, which is easy enough but is more plumbing than directly related to your business domain--and building creative workarounds for the limitations of Go by exploiting the powerful features Go &lt;em&gt;does&lt;/em&gt; offer. Dependency management and error handling could be better, and the absence of generics can be rather painful when dealing with unknown schemas like &lt;a href="https://stackoverflow.com/questions/28877512/taking-a-json-string-unmarshaling-it-into-a-mapstringinterface-editing-an"&gt;unmarshaling dynamic JSON&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So it all depends on if the priorities of your application and project align with the priorities of the language and ecosystem you choose. Despite the strong possibility that this opinion will subject me to ritual humiliation on social media, I would use Scala (or a similarly featured language like Kotlin for microservices or bigger but Go both to replace any &lt;a href="https://www.quora.com/Where-do-we-use-Python-or-shell-scripts-in-the-DevOps-project-life-cycle"&gt;bash or Python scripts&lt;/a&gt; &lt;br&gt;
that are part of my continuous delivery pipeline and &lt;br&gt;
to create &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/welcome.html"&gt;lambda functions&lt;/a&gt;, which are supposed to be lightweight, fast, and focused. This means you may not necessarily have to choose because nontrivial cloud native architectures will often blend both microservices and lambdas, and you should &lt;em&gt;always&lt;/em&gt; have a continuous delivery pipeline.&lt;/p&gt;

&lt;p&gt;I hope this helps. If you read the whole thing, you deserve a nap.&lt;/p&gt;

</description>
      <category>scala</category>
      <category>go</category>
      <category>functional</category>
      <category>programming</category>
    </item>
    <item>
      <title>Code Coverage Is Killing You</title>
      <dc:creator>Neil Chaudhuri</dc:creator>
      <pubDate>Sun, 15 Aug 2021 20:48:27 +0000</pubDate>
      <link>https://dev.to/realneilc/code-coverage-is-killing-you-30f3</link>
      <guid>https://dev.to/realneilc/code-coverage-is-killing-you-30f3</guid>
      <description>&lt;p&gt;If you are a software engineer or run software projects, &lt;a href="https://stackoverflow.com/questions/195008/what-is-code-coverage-and-how-do-you-measure-it"&gt;code coverage&lt;/a&gt; is probably very important to you. It's intuitive. Of course more tests produce better software! It's easy to calculate. Tools, automation, and stunning charts to impress the people who pay for the occasional pizza are all readily available. &lt;/p&gt;

&lt;p&gt;The problem is code coverage is killing you.&lt;/p&gt;

&lt;p&gt;Don't get me wrong. You deserve credit for your agile commitment to quality and your investment in continuous integration and continuous delivery. But why does just about everything out there say 100% code coverage is [at best unrealistic and at worst &lt;a href="https://softwareengineering.stackexchange.com/questions/1380/how-much-code-coverage-is-enough"&gt;dangerous&lt;/a&gt;? How can achieving a perfect score on a great metric be a bad thing? But OK. What's the optimal number then? There are a lot of heuristics, but &lt;a href="https://stackoverflow.com/questions/90002/what-is-a-reasonable-code-coverage-for-unit-tests-and-why"&gt;no one really knows&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;All of this uncertainty over an apparent no-brainer should give you pause, but it is important to understand the main reasons why code coverage is so flawed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code coverage assumes all your code is equally vulnerable
&lt;/h3&gt;

&lt;p&gt;Let's say your code includes a credit card validator. There &lt;br&gt;
is an infinite number of ways a string can fail credit card validation, but you only need a few tests to achieve 100% code coverage for it. Meanwhile other code may have far fewer failure scenarios. Ideally, that credit card validator should have hundreds of tests associated with it while other code has far fewer. Code coverage treats them all the same and only credits you for a small fraction of the tests necessary for your most vulnerable code, so you probably won't write any more than you have to. I believe that's what the kids call "perverse incentives."&lt;/p&gt;

&lt;h3&gt;
  
  
  Code coverage assumes all your code is equally valuable
&lt;/h3&gt;

&lt;p&gt;Let's say your application also offers payment via money order. Almost no one will use that option; the vast majority of customers will pay by credit card. Code coverage doesn't know the difference, so it considers credit card tests and money order tests equally important. That's bad. A bug with credit card payments will cost you orders of magnitude more profit than a bug with money orders, but code coverage will never account for that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code coverage demands ceremony that may not be necessary
&lt;/h3&gt;

&lt;p&gt;Let's not lose sight of the goal, which is to gain as much&lt;br&gt;
confidence as possible that your code works. Certainly that can come from tests, but it does not have to. For example, if you are building a component library in React that will be consumed by application developers, it could very well be &lt;a href="https://storybook.js.org/"&gt;Storybook&lt;/a&gt; is all you need. After all, a button in your component library will have no functionality on its own. Its functionality will come from the &lt;code&gt;onClick&lt;/code&gt; event handler passed as a prop by the library consumer. All you care about is that clicking the button does something. It's a waste of time to write a test for something so trivial just to check a coverage box when Storybook gives you that for basically free. Of course, if you insist, you can also &lt;br&gt;
&lt;a href="https://storybook.js.org/docs/react/workflows/unit-testing"&gt;use Storybook stories as fixtures for your tests&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Code coverage tells you how much but not how well
&lt;/h3&gt;

&lt;p&gt;This could be the worst of all. You are investing a lot of budget and schedule in building a test suite that should raise the quality of your software, lower costs, and improve customer satisfaction. But while code coverage tells you how much you tested, it doesn't tell you how &lt;em&gt;well&lt;/em&gt; you tested. You can write really poor tests (&lt;em&gt;e.g.&lt;/em&gt; tests that don't offer any challenging scenarios, tests that are flaky or slow, &lt;em&gt;etc.&lt;/em&gt;) that yield 100% coverage. In the end, those tests might actually be &lt;em&gt;counterproductive&lt;/em&gt; because the investment could have gone elsewhere and yielded some value. &lt;/p&gt;

&lt;p&gt;Frankly, none of these concerns are debatable. The only real argument for code coverage is that for all its flaws it is still the best we can do. Obviously I cannot speak to your specific project, but my extensive experience suggests that your best case scenario--if you have a team of talented, disciplined engineers who have faced no deadline pressures to get features out fast--is that your dedication to high code coverage has improved quality but not nearly enough given how much you've spent trying. Instead, what's most likely is all your spending has produced mostly useless tests that exist to check a box rather than to improve quality, and your code is only barely better than with no tests at all.&lt;/p&gt;

&lt;p&gt;The good news is we can do a lot better for a lot cheaper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Percentage Metrics
&lt;/h2&gt;

&lt;p&gt;Experience has shown me there are a lot better metrics than code coverage. Here is a good list of percentage metrics inspired by &lt;a href="http://blog.codepipes.com/testing/software-testing-antipatterns.html#anti-pattern-6---paying-excessive-attention-to-test-coverage"&gt;Kostis Kapelonis&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Percentage of Bugs Reproduced By Tests (Target: 100%)&lt;/em&gt;&lt;/strong&gt;. This is the best metric. Every bug reported by testers or users should have at least one test associated with it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Percentage of Tests That Change (Target: 0%)&lt;/em&gt;&lt;/strong&gt;. Too often tests are coupled to implementation, so updates to your implementation details--a new technology, updated algorithm, &lt;em&gt;etc.&lt;/em&gt;--lead to laborious updates to tests. That should stop. Shifting away from conventional, scenario-based testing to &lt;br&gt;
&lt;a href="https://www.vidyasource.com/blog/business-case-for-functional-programming"&gt;property-based testing&lt;/a&gt; where possible can help.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Percentage of Consistent Tests (Target: 100%)&lt;/em&gt;&lt;/strong&gt;. Have you ever seen the same tests pass some days and fail others? That's not consistent, and engineers typically respond by disabling or commenting out offending tests. Instead, rewrite these tests to be deterministic unit tests, or delete them entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Percentage of Developers Writing Tests (Target: 100%)&lt;/em&gt;&lt;/strong&gt;. Everyone who writes code should write tests, but it is important not to take this in a punitive direction. The purpose is not to uncover slackers; it's to grow a culture where all developers recognize test code deserves the same care as production code and to expose the entire team to the entire codebase to promote &lt;a href="https://martinfowler.com/bliki/CodeOwnership.html"&gt;collective code ownership&lt;/a&gt;. If command-and-control types do try to use this metric to identify what they consider "weak performers," then get rid of it. It does more harm than good.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trending Metrics
&lt;/h2&gt;

&lt;p&gt;There are also trends to watch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Low Code Quality in Tests&lt;/em&gt;&lt;/strong&gt;. Tests are code. Your test code should be a first-class citizen subject to the same quality checks as production code--limited duplication, reusable functions, design patterns where useful, &lt;em&gt;etc.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Time to Write Tests&lt;/em&gt;&lt;/strong&gt;. Maybe the quality of your tests is too low. Maybe the design is poor with too many dependencies to mock. Maybe it's hard to generate test data or scenarios. Taking too long to write tests will manifest in diminishing velocity and more bugs. Better design and again &lt;br&gt;
&lt;a href="https://dev.to/blog/2018/09/18/the-business-case-for-functional-programming/"&gt;property-based testing&lt;/a&gt; can help.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Time to Run Tests&lt;/em&gt;&lt;/strong&gt;. One of the core tenets of agile development is rapid feedback, which is impossible if your tests take forever. This might be controversial, but I would recommend favoring unit tests and functional tests over integration tests. Unit tests are fast (when written properly). Functional tests give you the most accurate view on quality, and modern tools like &lt;a href="https://www.cypress.io/"&gt;Cypress&lt;/a&gt; can overcome the slowness and flakiness of older tools like Selenium. You can also get a boost from your &lt;a href="https://engineering.linkedin.com/blog/2018/07/how-we-improved-build-time-by-400-percent"&gt;tooling&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Keep these trend lines as low and as level as possible.&lt;/p&gt;

&lt;p&gt;The best part about all of these metrics is that they are easily derived from your engineering tools. Nothing special is required of you. Of course you can always take the initiative to do some clever things specific to your domain like identifying particularly vulnerable and/or valuable parts of the codebase and ensuring there is a high level of coverage for that specific region of surface area.&lt;/p&gt;

&lt;p&gt;In the end you should be able to look at every test in your code base and recognize how it gives you confidence that your code will work in production and that no one will be working weekends. The siren song of code coverage is intoxicating, but you can do so much better.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>codequality</category>
      <category>codereview</category>
      <category>testing</category>
    </item>
    <item>
      <title>Dark Mode in Next.js Using Tailwind CSS and React Hooks</title>
      <dc:creator>Neil Chaudhuri</dc:creator>
      <pubDate>Tue, 03 Aug 2021 01:18:50 +0000</pubDate>
      <link>https://dev.to/realneilc/dark-mode-in-next-js-using-tailwind-css-and-react-hooks-1b3g</link>
      <guid>https://dev.to/realneilc/dark-mode-in-next-js-using-tailwind-css-and-react-hooks-1b3g</guid>
      <description>&lt;p&gt;It's quite possible that while waiting for the ads on Hulu to end you stumbled upon the &lt;a href="https://www.theverge.com/2019/3/22/18270975/how-to-dark-mode-iphone-android-mac-windows-xbox-ps4-nintendo-switch"&gt;option to set your phone's theme to Dark Mode&lt;/a&gt;. Dark Mode is becoming a staple of user interfaces on the web and mobile devices for &lt;a href="https://www.forbes.com/uk/advisor/mobile-phones/what-is-dark-mode-and-should-you-be-using-it/"&gt;several reasons&lt;/a&gt;--primarily to ease the strain on your eyes and to reduce battery consumption. &lt;/p&gt;

&lt;p&gt;At Vidya we pride ourselves on embracing emerging technologies and helping our clients leverage them to realize their potential. When it came time to give our website a fresh new look, we figured adding a toggle-able Dark Mode option would be consistent with that mission. &lt;/p&gt;

&lt;p&gt;The site is built in &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt; with &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt;, the most popular JavaScript library in the world, using &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt;, one of the most popular React frameworks in the world and the building block for full-stack "meta" frameworks like &lt;a href="https://redwoodjs.com/"&gt;RedwoodJS&lt;/a&gt; and &lt;a href="https://blitzjs.com/"&gt;Blitz&lt;/a&gt;. The user interface itself is crafted with the ever popular &lt;a href="https://tailwindcss.com/"&gt;Tailwind CSS&lt;/a&gt;, a powerful "utility-first" library that lets you compose your styles into higher-level abstractions that you apply across your user interface&lt;br&gt;
to give a consistent look and feel.&lt;/p&gt;

&lt;p&gt;If you would like to implement Dark Mode on a Next.js site using TailwindCSS, let me show you how. It involves three key pieces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tailwind's &lt;code&gt;dark&lt;/code&gt; class&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Script&lt;/code&gt; tag that we got in Next.js 11&lt;/li&gt;
&lt;li&gt;Understanding, like really understanding, React's &lt;code&gt;useEffect&lt;/code&gt; hook&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Activating Tailwind's Dark Mode Support
&lt;/h2&gt;

&lt;p&gt;Tailwind CSS offers &lt;a href="https://tailwindcss.com/docs/dark-mode"&gt;two ways to set Dark Mode&lt;/a&gt;. If you are content to default to system settings, then all you need to do is confirm your &lt;code&gt;tailwind.config.js&lt;/code&gt; file has the &lt;code&gt;media&lt;/code&gt; setting, which uses the &lt;code&gt;prefers-color-scheme&lt;/code&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme"&gt;CSS media feature&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// tailwind.config.js
module.exports = {
  darkMode: 'media',
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But since we want more control to let Vidya users decide which look they prefer, we need the &lt;code&gt;class&lt;/code&gt; setting instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// tailwind.config.js
module.exports = {
  darkMode: 'class',
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you need to handle variants like &lt;a href="https://www.gamesradar.com/loki-lady-loki-kid-loki-king-loki-disney-plus/"&gt;the TVA in Loki&lt;/a&gt;. &lt;a href="https://tailwindcss.com/docs/configuring-variants"&gt;Variants in Tailwind&lt;/a&gt; define the ways in which you want to apply different styles. For example, if we want to set a red background on a link hover, we apply the &lt;code&gt;hover&lt;/code&gt; variant on the &lt;code&gt;bg&lt;/code&gt; plugin: &lt;code&gt;&amp;lt;a className="hover:bg-red"&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As an aside, the CSS equivalent would be this for our shade of red:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a:hover {
  background-color: #9C4D61;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will do similar to apply &lt;code&gt;dark&lt;/code&gt; variants of our branding scheme throughout our interface. For example, here is a simplified version of our &lt;code&gt;contact-us&lt;/code&gt; class composing numerous Tailwind utilities in Next.js's &lt;code&gt;globals.css&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.contact-us {
        @apply dark:text-red dark:hover:text-blue bg-red dark:bg-red-light hover:bg-blue-dark dark:hover:bg-blue-light;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that you always put &lt;code&gt;dark&lt;/code&gt; first when you have multiple variants like &lt;code&gt;dark:hover:bg-blue-light&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is where you will spend most of your time. Mostly because you want to put together a Dark Mode color palette that is usable and accessible and consistent with your branding and because you want to be thorough in applying it throughout the site.&lt;/p&gt;

&lt;p&gt;Just remember to &lt;a href="https://tailwindcss.com/docs/extracting-components"&gt;extract components&lt;/a&gt; as we did above to keep things maintainable, consistent, and organized.&lt;/p&gt;

&lt;p&gt;Because we are relying on the Tailwind &lt;code&gt;class&lt;/code&gt; setting for Dark Mode, we need to figure out a way to hook the &lt;code&gt;dark&lt;/code&gt; class onto the root element of each page like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;html lang="en" class="dark"&amp;gt;
...
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we need to be able to do it on demand. This is where our code comes into play.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Script Tag
&lt;/h2&gt;

&lt;p&gt;If you've built a website with a lot of client side business functionality, GDPR or other consent management, Google Analytics, social media, or ads, you already know that managing JavaScript execution has always been awkward. Where do you put this script on the page relative to that one? Do you put this script at the top of the &lt;code&gt;head&lt;/code&gt; element or at the bottom of the &lt;code&gt;body&lt;/code&gt; element? It's actually easier figuring out where to seat everyone at your wedding.&lt;/p&gt;

&lt;p&gt;In v11.0.0, Next.js introduced the &lt;code&gt;Script&lt;/code&gt; &lt;a href="https://nextjs.org/docs/basic-features/script"&gt;tag&lt;/a&gt;, and it makes all this a lot better. You can put the &lt;code&gt;Script&lt;/code&gt; tag anywhere, and you apply one of three strategies to let Next.js know when it should execute.&lt;/p&gt;

&lt;p&gt;Before we specify which strategy should apply here, keep in mind our goal: to assess the user's Dark Mode preference and apply it immediately. For this script to work, it must execute &lt;em&gt;before&lt;/em&gt; the browser paints the page, so it has to block interactivity. This contradicts everything you've ever read about script optimization. Conventional guidance dictates scripts should run in an asynchronous, parallel fashion in order to maximize &lt;a href="https://web.dev/vitals/"&gt;Web Vitals&lt;/a&gt; and get the user up and running as soon as possible. That general guidance is accurate, but we need to make an exception for this particular script. Still, it must execute very quickly, or we will lose customers.&lt;/p&gt;

&lt;p&gt;Our strategy for implementing Dark Mode will factor in potential user preferences specific to the Vidya website set in &lt;code&gt;localStorage&lt;/code&gt;,a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage"&gt;key-value store available in modern browsers&lt;/a&gt;, and/or system settings that the browser will inform us with &lt;code&gt;prefers-color-scheme&lt;/code&gt;. The algorithm goes like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If the user previously visited the Vidya website and indicated a preference for Dark Mode OR if there is no preference established and system settings are set for Dark Mode, then activate Dark Mode by attaching the dark class attribute to the root. Otherwise, apply Light Mode by removing any dark class attribute.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is the &lt;code&gt;darkMode.js&lt;/code&gt; script that does exactly that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (localStorage.getItem('vidyaDarkMode') === 'true' || (!('vidyaDarkMode' in localStorage) &amp;amp;&amp;amp; window.matchMedia('(prefers-color-scheme: dark)').matches)) {
    document.documentElement.classList.add('dark')
} else {
    document.documentElement.classList.remove('dark')
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a straightforward conditional, which might even &lt;a href="https://medium.com/@amaliesmidth/javascript-short-circuit-conditionals-6606bdeaa30d"&gt;short-circuit&lt;/a&gt;, and DOM manipulation. That should be fast. Phew!&lt;/p&gt;

&lt;p&gt;And here is how we execute it before browser paint with Next.js's &lt;code&gt;Script&lt;/code&gt; tag inside our &lt;code&gt;_app.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Script from "next/script";
// ...
&amp;lt;Script strategy="beforeInteractive" src="/scripts/darkMode.js"/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;beforeInteractive&lt;/code&gt; strategy is the key. This tells Next.js to block everything until the script is finished. Again, you need to use this strategy very carefully, but it's &lt;a href="https://constitution.congress.gov/browse/essay/artI_S8_C18_1/#:~:text=C18.-,1%20The%20Necessary%20and%20Proper%20Clause%3A%20Overview,%2C%20Section%208%2C%20Clause%2018%3A&amp;amp;text=To%20make%20all%20Laws%20which,any%20Department%20or%20Officer%20thereof."&gt;necessary and proper&lt;/a&gt; in this instance.&lt;/p&gt;

&lt;p&gt;So thanks to Tailwind CSS and Next.js, we can successfully apply Dark Mode based on user preferences one way or another when the Vidya website loads. The last step is to give the user a chance to switch modes and to save that preference to &lt;code&gt;localStorage&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  With Great Effects Come Great Responsibility
&lt;/h2&gt;

&lt;p&gt;When Facebook revolutionized React with Hooks, it was a game changer, but even now, years later, they can be confusing. Let's see how we can use &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt; to complete our Dark Mode solution.&lt;/p&gt;

&lt;p&gt;The work we did with Tailwind CSS and the &lt;code&gt;Script&lt;/code&gt; tag presents our user interface exactly as it should look from what we know so far, but React needs to manage that preference to change it as the user dictates. There are two steps: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React needs to be made aware of the initial Dark Mode preference and keep an eye on it. &lt;/li&gt;
&lt;li&gt;If the user changes that preference, React needs to add or remove the &lt;code&gt;dark&lt;/code&gt; class from the root and persist the choice in &lt;code&gt;localStorage&lt;/code&gt; accordingly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are two different effects. We will localize them where they matter most, the &lt;code&gt;ThemeButton&lt;/code&gt; the user clicks to switch modes.&lt;/p&gt;

&lt;p&gt;Before we get into those, lets prepare to maintain state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [darkMode, setDarkMode] = useState&amp;lt;boolean | undefined&amp;gt;(undefined)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although we really want &lt;code&gt;darkMode&lt;/code&gt; to be &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;, we need to initialize it with &lt;code&gt;undefined&lt;/code&gt; because we don't know what it is until the first effect runs.&lt;/p&gt;

&lt;p&gt;Here it is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
        setDarkMode(document.documentElement.classList.contains("dark"))
}, [])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's simple but deceptively so. It's really &lt;a href="https://www.youtube.com/watch?v=ESrtX53Kc8Q"&gt;very very sneaky&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note the empty dependency array. Many React developers, especially the other old timers who remember the awkwardness of handling effects in component lifecycle events, think of this as the equivalent of the initial set up we did in &lt;code&gt;componentDidMount&lt;/code&gt;. That way of thinking can work for you, but it's imprecise and I would say counterproductive to understanding how React works. &lt;/p&gt;

&lt;p&gt;The purpose of &lt;code&gt;useEffect&lt;/code&gt; is to synchronize UI with the state represented in the dependency array. When that state changes, UI changes. However, the &lt;em&gt;absence of dependencies&lt;/em&gt; means that you want to synchronize your UI with the &lt;em&gt;absence of state&lt;/em&gt;, and state just happens to be absent when a component first mounts. So yeah, it works out the same as that &lt;code&gt;componentDidMount&lt;/code&gt; analogy, but they're really two different things. &lt;/p&gt;

&lt;p&gt;This is why math teachers make you show your work.&lt;/p&gt;

&lt;p&gt;As a result, this first &lt;code&gt;useEffect&lt;/code&gt; call runs when state is absent as the component initially mounts, and the current &lt;code&gt;darkMode&lt;/code&gt; value is saved to state. We can deduce the value from the root element because of the code we wrote earlier using the Next.js &lt;code&gt;Script&lt;/code&gt; tag, which we know has already executed because we used the &lt;code&gt;beforeInteractive&lt;/code&gt; strategy.&lt;/p&gt;

&lt;p&gt;See how it all fits together?&lt;/p&gt;

&lt;p&gt;Finally, there is the second hook that triggers and records a change to the theme when the user clicks the button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
        if (darkMode) {
            window.document.documentElement.classList.add('dark')
            localStorage.setItem("vidyaDarkMode", "true")
        } else {
            window.document.documentElement.classList.remove('dark')
            localStorage.setItem("vidyaDarkMode", "false")
        }
}, [darkMode])

const onClick = () =&amp;gt; {
        setDarkMode(!darkMode)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a more straightforward implementation of &lt;code&gt;useEffect&lt;/code&gt;. The &lt;code&gt;darkMode&lt;/code&gt; state value is in the dependency array of the effect, so when the user clicks the &lt;code&gt;ThemeButton&lt;/code&gt; and toggles the value with &lt;code&gt;setDarkMode&lt;/code&gt;, two effects execute. The code modifies the root element by adding or removing the &lt;code&gt;dark&lt;/code&gt; class as needed and persists the setting to &lt;code&gt;localStorage&lt;/code&gt; so our &lt;code&gt;Script&lt;/code&gt; from before will pick it up again when the user returns to the Vidya website.&lt;/p&gt;

&lt;p&gt;Let's wrap up by putting together all the relevant Dark Mode logic in &lt;code&gt;ThemeButton&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const ThemeButton = (p: ThemeButtonProps) =&amp;gt; {
    const [darkMode, setDarkMode] = useState&amp;lt;boolean | undefined&amp;gt;(undefined)
    useEffect(() =&amp;gt; {
        setDarkMode(document.documentElement.classList.contains("dark"))
    }, [])
    useEffect(() =&amp;gt; {
        if (darkMode) {
            window.document.documentElement.classList.add('dark')
            localStorage.setItem("vidyaDarkMode", "true")
        } else {
            window.document.documentElement.classList.remove('dark')
            localStorage.setItem("vidyaDarkMode", "false")
        }
    }, [darkMode])
    const onClick = () =&amp;gt; {
        setDarkMode(!darkMode)
    }

    return ( {/* ThemeButton UI goes here */} )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So that's it. I hope it's clear how the different components of our solution complement one another to bring Dark Mode to the Vidya website, but this is just one way of doing it. I can't wait to see how you apply the lessons learned here to build great Dark Mode experiences for your audience as well. If you come up with a better way of doing it, please &lt;a href="https://twitter.com/VidyaSource"&gt;let us know&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>tailwindcss</category>
      <category>react</category>
      <category>ux</category>
    </item>
  </channel>
</rss>
