<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Kumusta mundo! A blog by Adrienne Tacke]]></title><description><![CDATA[Tech tutorials and stories from a Filipina software engineer. 

✨ Featured on [tech-blogs.dev](https://tech-blogs.dev/)!]]></description><link>https://blog.adrienne.io</link><generator>RSS for Node</generator><lastBuildDate>Sat, 16 May 2026 01:29:46 GMT</lastBuildDate><atom:link href="https://blog.adrienne.io/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[I made a teleprompter using the <marquee> HTML tag]]></title><description><![CDATA[While filming the first episode of my $quickbytes series, I realized something: it was SUPER obvious when I would look away from the camera to read my script! I had it open on another monitor; just a Google Doc in a large font. I thought I could film...]]></description><link>https://blog.adrienne.io/i-made-a-teleprompter-using-marquee-html-tag</link><guid isPermaLink="true">https://blog.adrienne.io/i-made-a-teleprompter-using-marquee-html-tag</guid><category><![CDATA[HTML]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[creativity]]></category><category><![CDATA[HTML5]]></category><dc:creator><![CDATA[Adrienne Tacke]]></dc:creator><pubDate>Sat, 01 May 2021 19:23:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1619900719420/FbAW6m0p5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>While filming the <a target="_blank" href="https://youtu.be/G-6-1eCVmSA">first episode</a> of my $quickbytes series, I realized something: it was SUPER obvious when I would look away from the camera to read my script! I had it open on another monitor; just a Google Doc in a large font. I thought I could film while manually advancing my script; nope. That was way too complicated! </p>
<p>As I became more frustrated with not being able to read my script and keep my eyes on the camera, a genius idea came to my head: why not use the <code>&lt;marquee&gt;</code> HTML tag?!</p>
<p>I quickly opened up a W3schools TryIt Editor, adjusted the font and speed settings, and BAM! Instant Teleprompter!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619895450519/gzbr9_yyA.png" alt="Screenshot of a W3schools TryIt Editor showing marquee tag code on the left and a teleprompter on the right" /> 
<em>If you want to  <a target="_blank" href="https://www.w3schools.com/code/tryit.asp?filename=GPTDB6DAEJBQ">try it out yourself</a>, I encourage you to do so!</em></p>
<p>Here's all the code it takes (yes, really):</p>
<pre><code class="lang-HTML"><span class="hljs-tag">&lt;<span class="hljs-name">marquee</span> <span class="hljs-attr">direction</span>=<span class="hljs-string">"up"</span> <span class="hljs-attr">scrollamount</span>=<span class="hljs-string">"13"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"100%"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"100%"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"font-size: 100px;"</span> &gt;</span>
Here is a makeshift teleprompter. 
I've set it to be slow enough to read, but fast enough to keep pace with how I speak.
This helped me when I needed to record a video!
<span class="hljs-tag">&lt;/<span class="hljs-name">marquee</span>&gt;</span>
</code></pre>
<p><code>direction</code> sets the scroll direction of the marquee. I set it to <code>up</code>, which is the easiest for me to read, but you can also set it to <code>down</code>, <code>left</code>, or <code>right</code>.</p>
<p><code>scrollamount</code> sets the speed of the scroll. I had to experiment and find the right speed: fast enough so it sounds natural when filming, but slow enough that I don't get overwhelmed! For me, that number was <code>13</code>. I encourage you to play around and find the right speed for you!</p>
<p>That's really it in terms of <code>&lt;marquee&gt;</code>-specific attributes. The remaining <code>height</code>, <code>width</code>, and inline style was just to make my script legible to read on my other monitor! And between the <code>&lt;marquee&gt;</code> tags, I pasted in my script.</p>
<p>I got so excited about this silly solution, I shared it on twitter:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/AdrienneTacke/status/1385386687841198080?s=20">https://twitter.com/AdrienneTacke/status/1385386687841198080?s=20</a></div>
<p> </p>
<p>Of course, as some have brought up, please remember that the <code>&lt;marquee&gt;</code> tag has  <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/marquee">been deprecated</a> and is not recommended for use in production! But in the context of this sandbox and for this purpose, the <code>&lt;marquee&gt;</code> HTML tag saved me! </p>
<p>In case you're curious, this is the video I filmed using this teleprompter:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/G-6-1eCVmSA">https://youtu.be/G-6-1eCVmSA</a></div>
<p>What do you think? </p>
<p>Anyway, thanks for reading this quick post. Just wanted to share this silly, but genius solution that we as devs sometimes come up with every now and then!</p>
<hr />
<h2 id="thank-you">Thank you!</h2>
<p>Thank you so much for taking the time to read through my article. If you enjoyed it or have a question, please let me know in a comment below. Or even better, if you feel this article would be helpful to other devs, please share it/tweet it to spread the knowledge and love. ♥️</p>
<p>For more from me, be sure to follow <a target="_blank" href="https://blog.adrienne.io/">my blog</a>! And to see what I'm currently up to, follow me on <a target="_blank" href="https://twitter.com/AdrienneTacke">Twitter</a>!</p>
]]></content:encoded></item><item><title><![CDATA[Terminal, Console, CLI, shell... Aren't they all the same thing?]]></title><description><![CDATA[Terminal, Console, CLI, shell... Aren't they all the same thing?
Yes and no (although, in the present day, we do use them interchangeably with the confidence that the other person knows what we're talking about)!
I get these terms mixed up quite a bi...]]></description><link>https://blog.adrienne.io/terminal-console-cli-shell-arent-they-all-the-same-thing</link><guid isPermaLink="true">https://blog.adrienne.io/terminal-console-cli-shell-arent-they-all-the-same-thing</guid><category><![CDATA[Beginner Developers]]></category><category><![CDATA[terminal]]></category><category><![CDATA[shell]]></category><category><![CDATA[cli]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Adrienne Tacke]]></dc:creator><pubDate>Fri, 12 Feb 2021 19:47:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1613159054286/z322fjYUB.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="terminal-console-cli-shell-arent-they-all-the-same-thing">Terminal, Console, CLI, shell... Aren't they all the same thing?</h1>
<p>Yes and no (although, in the present day, we do use them interchangeably with the confidence that the other person knows what we're talking about)!</p>
<p>I get these terms mixed up quite a bit, so I wanted to dive deeper into what they are, why we use them interchangeably, and what the true differences are (at least the ones that matter).‌
‌</p>
<h2 id="tldr-breakdown">TL;DR Breakdown:</h2>
<h3 id="what-is-a-terminal">What is a Terminal?</h3>
<p>At it's core, any input/output device. Our keyboards and mice are terminals. So are our ears and eyes. They are like terminals for sound.</p>
<h3 id="what-is-a-console">What is a console?</h3>
<p>A physical terminal; a physical mechanism by which input can be collected. Thinking about it this way, it's easy to see how we share this word across industries: video game consoles in gaming, mixing consoles in music, and command consoles in aviation/space.</p>
<h3 id="what-is-a-cli">What is a CLI?</h3>
<p>CLI stands for Command Line Interface. A CLI is a distinct type of interface that accepts input commands and then executes them once you hit the Return/Enter key.</p>
<h3 id="what-is-a-shell">What is a shell?</h3>
<p>A shell is a specialized command line interface; this is what actually recognizes the commands you enter and then tells the operating system to execute them. There are many flavors; cmd is the default shell on Windows, Bash is the default shell on most Linux distributions, and just recently, zsh became the default shell on macOS Catalina.</p>
<p>My mind's blown. Is yours? Mooncake's definitely is.</p>
<p><img src="https://media.giphy.com/media/pPiEbdVp2EemAZucWg/giphy.gif" alt="Mooncake from Final Space saying 'Whoaaaa' in its alien language" /></p>
<h2 id="terminal-console-cli-and-shell-the-quick-history-behind-the-words">Terminal, Console, CLI, and shell: The (Quick!) History Behind the Words</h2>
<p>Yes, in order to understand why these terms have morphed into an interchangeable mess, we need to go back to the beginning. Back to the days of mainframes...</p>
<div><img src="https://www.ibm.com/ibm/history/ibm100/images/icp/F592552V34460X75/us__en_us__ibm100__system_360__360_2__800x593.jpg" alt="This is an image of a woman sitting at a printing apparatus with IBM 360 (specifically Model 40) in the background" />
<p>IBM 360 Mainframe - Source: <a href="https://www.ibm.com/ibm/history/ibm100/us/en/icons/system360/impacts/">System 360 IBM's History</a></p>
</div>

<p>You've probably seen pictures of these things. They took up entire rooms. And they were usually found in large businesses or universities. In fact, I think my college still uses one (because if it still works, why replace it?!).</p>
<p>Mainframes were meant to be used among many different users. Today, we would achieve this by just handing everyone their own personal monitor, keyboard, and mouse. But back then, users shared access through a common endpoint: the terminal. These were specialized stations that had a display (usually a small cathode ray tube TV screen) and a built-in keyboard. They were connected to the mainframe by a cable or phone line.</p>
<div><img src="https://images.computerhistory.org/timeline/timeline_networking.web_1964_sabre.jpg" alt="Woman sitting at Unimatic terminal for United Airline's competing system." />
<p>Woman sitting at Unimatic terminal for United Airline's competing system. Source: <a href="https://www.computerhistory.org/timeline/networking-the-web/">ComputerHistory.org</a></p>
</div>

<p>Speaking of connections, we get the term <code>console</code> from the actual console port on the mainframe that terminals would connect to. This is how users controlled the mainframe digitally, through these connected terminals scattered around the building.</p>
<p>Ok, so now we're connected. How did users actually interact with the mainframe? If you have seen any "hacker" scene in a movie, you usually see something like this:
‌
<img src="https://media.giphy.com/media/l46C6sdSa5DVSJnLG/giphy.gif" alt="Robotic and human hand fake typing on a terminal, with code appearing quickly on the screen" /></p>
<p>‌(And if you have a minute and 47 seconds to spare, watch this hilarious <a target="_blank" href="https://www.youtube.com/watch?v=Hcywf9mwF5U">Ode to Mainframes</a> 😂)</p>
<p>Notice how there are no fancy graphical interfaces just yet? That's because most interactions with mainframes were via simple commands, entered one at a time. And this is where the term and concept of the <code>command line interface</code> (CLI) comes from! Users would supply a command to the mainframe through a terminal. ‌</p>
<p>Alright, home stretch...‌
‌‌</p>
<p>‌It's important to note that the terminal has nothing to do with the actual processing or interpreting of the command. They are simply a means for the user to input commands (hence the hopefully antiquated term "dumb terminal"). It's actually the shell that accepts and recognizes these commands, sends them to the mainframe to execute, collects the results, and sends it back to the terminal!</p>
<p>Here's the kicker: the shell is really just a wrapper around the kernel. And in an operating system, the <code>kernel</code> is "a computer program that is the core of a computer's operating system, with complete control over everything in the system. On most systems, it is one of the first programs loaded on start-up..." <a target="_blank" href="https://en.wikipedia.org/wiki/Kernel_(operating_system)">^1</a></p>
<p>This is why we call the <code>shell</code> a "shell" as it acts similarly to the piece of material around a corn kernel! </p>
<p><strong>What happened?</strong></p>
<p>Today, most terminals and consoles are represented virtually through software, but as we've learned, they used to be physical, tangible objects. Pairing this history with the fact that they are heavily intertwined with the origins of the command line interface, it's easy to see how the terms "terminal" and "console" have become muddled together! And by the time we reach present day, the use of all of these terms "terminal", "console", "shell", "CLI" eventually became synonymous with the end goal we as developers are trying to achieve: to interact with an operating system and execute specific actions through commands!</p>
<p><span>Cover Photo by <a href="https://unsplash.com/@bertsz?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">bert brrr</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span></p>
<hr />
<p>Thank you so much for taking the time to read my blog post! Hopefully these terms aren't so confusing anymore!</p>
<p>If you enjoyed it, please let me know in a comment below. Or even better, if you feel this article was thorough in a good way, please share it/tweet it to spread the knowledge and love. ♥️</p>
<p>For more from me, be sure to follow  <a target="_blank" href="https://blog.adrienne.io/">my blog</a>!</p>
<p>To see what I'm up to, follow me on <a target="_blank" href="https://twitter.com/AdrienneTacke">Twitter</a>!</p>
]]></content:encoded></item><item><title><![CDATA[The CONS of Traveling for Tech Conferences]]></title><description><![CDATA[What's it like traveling the world to speak at tech conferences?

It's fascinating, extremely fun, and EXHAUSTING. You all know the perks of travel and how rewarding it can be to explore the world. I think we'd all much rather be doing more of it rig...]]></description><link>https://blog.adrienne.io/the-cons-of-traveling-for-tech-conferences</link><guid isPermaLink="true">https://blog.adrienne.io/the-cons-of-traveling-for-tech-conferences</guid><category><![CDATA[conference]]></category><category><![CDATA[DevLife]]></category><category><![CDATA[General Advice]]></category><category><![CDATA[developer relations]]></category><dc:creator><![CDATA[Adrienne Tacke]]></dc:creator><pubDate>Sun, 17 Jan 2021 00:49:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1610844162886/hS4xJKDKv.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>What's it like traveling the world to speak at tech conferences?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1609629886805/YoleC19Qj.jpeg" alt="Adrienne flying to another tech conference, pictured in a hangar with a jet in the background" /></p>
<p>It's fascinating, extremely fun, and EXHAUSTING. You all know the perks of travel and how rewarding it can be to explore the world. I think we'd all much rather be doing more of it right now! But until then, I'll tell you what most don't about traveling for tech conferences. Here are the major CONS of traveling this much:</p>
<h2 id="traveling-itself">Traveling itself</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1609630133350/FvdWg_NsR.jpeg" alt="Singapore Airlines airliner" /></p>
<p>Conferences usually pay in full for my airfare (or reimburse me afterward), but that doesn't mean I'm flying first-class! Conferences have budgets too, so when that's the case, especially if it's a community-run, non-profit conference, I'm usually flying economy. That may not be so bad for domestic flights, but anything longer than 6 hours or flying to Europe is real tiring. Add onto that the usual annoyances of airports, people with no travel etiquette, etc. and traveling so much is suddenly not so glamorous!</p>
<h2 id="dealing-with-jet-lag">Dealing with jet lag</h2>
<p>In-person conference season is on hold for a while, but phew! did it take a toll on my body when I was in full swing back then! Going back and forth between Europe and even the East Coast messes with my internal clocks so much, it takes a while to get over it! I stay up til 3 or 4am even though I need to sleep and I don't wake up until 11 or 12 the next day, effectively making me feel like I've wasted valuable time. Additionally, my appetite is all funky. </p>
<p>Depending on when I land at my destination, I either have an awesome selection of new food to try or am stuck with whatever the hotel can serve when everything else is closed. Many times, it's ordering pizza from room service 😂 See exhibit A:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1609630497890/Nl9XB-jKX.jpeg" alt="Adrienne eating a pizza in her hotel room." /></p>
<p>Once I get home, I eat A LOT (think normal local dining hours, but also every other hour in between) but feel like I haven't eaten anything at all. It takes a while for everything to sync back to normal and going through those effects are not much fun.</p>
<h2 id="living-out-of-a-suitcase">Living out of a suitcase</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608369756979/Djd_mk2WC.jpeg" alt="My open suitcase showcasing my travel essentials: a few outfits, my book, noise canceling headphones, a curling iron, and always a pair of killer black heels!" /></p>
<p>Despite learning what my TRUE essentials are (😂), it can get annoying to be living out of a suitcase. This is exacerbated if I don't have a free washer to make use of and I'm staying for longer than a week. At this point, it becomes a value proposition game. Do I pay more to check in an extra bag that's larger (with the disadvantage of having to wait for it and travel with it)? Do I spend the atrocious $4 a garment to use the hotel's laundering facilities? If I forgot something, do I buy another one? These are all issues that became more prominent for me as I started to travel to more tech conferences.</p>
<h2 id="mostly-exploring-alone">Mostly exploring alone</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1610841580554/jIgy6zNMd.jpeg" alt="Adrienne on the boat tour on the River Thames, London, England" /></p>
<p>This may not be a con for many of you (and I do enjoy exploring on my own every  now and then), but there's just something about exploring the world together <em>with someone</em>. In my case, that's my husband. I get to make memories with him, experience something new, and enjoy the hustle and bustle of exploring a place with someone I love. Traveling to lots of tech conferences means I don't get to do that. This also means I spend less time with him overall and I miss him a lot. </p>
<h2 id="exhaustion">Exhaustion</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1610842594604/25AKAwg-3.jpeg" alt="My cozy Airbnb in Finland." /></p>
<p>There are itineraries that have me jet setting from one place to another in a short span of time and that really burns me out. This happened with my conferences in Berlin, Germany and Richmond, Virginia; I had to visit both places within the span of a week! Sometimes, it's so bad that I end up skipping some speaker dinners or events because I just want to fall into my hotel bed and SLEEP! I hate this, though, because I miss out on meeting other speakers, enjoying exclusive events prepared especially for us, and just feel like I "waste" time in a new place instead of spending every second enjoying and exploring! </p>
<h2 id="and-theres-the-truth">And there's the <strong>truth</strong>!</h2>
<p>These rarely talked about cons make me yearn for weeks of just doing NOTHING...though, I am now painfully reminded to be careful what I wish for! 😂 While we wait for travel to become normal again, let these realities be a reminder that not everything is picture perfect!</p>
<hr />
<p>Thank you so much for taking the time to read my blog post! If you enjoyed it, please let me know in a comment below. Or even better, if you feel this article was thorough in a good way, please share it/tweet it to spread the knowledge and love. ♥️</p>
<p>For more from me, be sure to follow  <a target="_blank" href="https://blog.adrienne.io/">my blog</a>!</p>
<p>To see where I'm speaking next (virtually) and when I'll be living out of a suitcase again, follow me on <a target="_blank" href="https://twitter.com/AdrienneTacke">Twitter</a>!</p>
]]></content:encoded></item><item><title><![CDATA[Everything you need to know about Multi-Cloud Clusters on MongoDB Atlas]]></title><description><![CDATA[Multi-cloud clusters on MongoDB Atlas are now generally available! Just as you might distribute your data across various regions, you can now distribute across multiple cloud providers as well. This gives you a lot more freedom and flexibility to run...]]></description><link>https://blog.adrienne.io/everything-you-need-to-know-about-multi-cloud-clusters-on-mongodb-atlas</link><guid isPermaLink="true">https://blog.adrienne.io/everything-you-need-to-know-about-multi-cloud-clusters-on-mongodb-atlas</guid><category><![CDATA[NoSQL]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[MongoDB]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Adrienne Tacke]]></dc:creator><pubDate>Sat, 09 Jan 2021 01:07:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1609907041868/QqRkPsBh8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Multi-cloud clusters on MongoDB Atlas are now <a target="_blank" href="https://www.mongodb.com/blog/post/introducing-multicloud-clusters-on-mongodb-atlas">generally available</a>! Just as you might distribute your data across various regions, you can now distribute across multiple cloud providers as well. This gives you a lot more freedom and flexibility to run your application anywhere and move across any cloud without changing a single line of code.</p>
<p>Want to use Azure DevOps for continuous integration and continuous deployment but Google Cloud for Vision AI? Possible! Need higher availability in Canada but only have a single region available in your current cloud provider? Add additional nodes from another Canadian region on a different cloud provider! These kinds of scenarios are what multi-cloud was made for!</p>
<p><img src="https://webassets.mongodb.com/_com_assets/cms/Blog-asset-2-peidakk6r5.png" alt="Multi-Cloud on MongoDB Atlas" /></p>
<p>In this post, I won't be telling you why multi-cloud is useful; there are several articles (like <a target="_blank" href="https://diginomica.com/mongodb-forges-ahead-multi-cloud-agenda-announces-multi-cloud-clusters-atlas">this one</a> or <a target="_blank" href="https://www.mongodb.com/multicloud">that one</a>) and a <a target="_blank" href="https://youtu.be/eC1-16jpyEc">Twitch stream</a> that do a great job of that already! Rather, in this post, I'd like to:</p>
<ul>
<li>Show you how to set up a multi-cloud cluster in MongoDB Atlas.</li>
<li>Explain what each of the new multi-cloud options means.</li>
<li>Acknowledge some new considerations that come with multi-cloud capabilities.</li>
<li>Answer some common questions surrounding multi-cloud clusters.</li>
</ul>
<p>Let's get started!</p>
<h2 id="requirements">Requirements</h2>
<p>To go through this tutorial, be sure to have the following:</p>
<ul>
<li>A <a target="_blank" href="https://www.mongodb.com/cloud/atlas/register">MongoDB Cloud Account</a></li>
<li>To create an M10 cluster or higher (note that this isn't covered by the free tier)</li>
</ul>
<h2 id="quick-jump">Quick Jump</h2>
<ul>
<li><a class="post-section-overview" href="#how-to-set-up-a-multi-cloud-cluster">How to Set up a Multi-Cloud Cluster</a></li>
<li><a class="post-section-overview" href="#testing-a-primary-node-failover-to-a-different-cloud-provider">How to Test a Primary Node Failover to a Different Cloud Provider</a></li>
<li><a class="post-section-overview" href="#differences-between-electable-read-only-and-analytics-nodes">Differences Between Electable, Read-Only, and Analytics Nodes</a></li>
<li><a class="post-section-overview" href="#choosing-your-electable-node-distribution">Choosing Your Electable Node Distribution</a></li>
<li><a class="post-section-overview" href="#multi-cloud-considerations">Multi-Cloud Considerations</a></li>
<li><a class="post-section-overview" href="#multi-cloud-faqs">Multi-Cloud FAQs</a></li>
</ul>
<h2 id="how-to-set-up-a-multi-cloud-cluster">How to Set Up a Multi-Cloud Cluster</h2>
<ol>
<li><p>Log into your <a target="_blank" href="https://account.mongodb.com/account/login">MongoDB Cloud account</a>.</p>
</li>
<li><p>Select the organization and project you wish to create a multi-cloud cluster in. If you don't have either, first create an organization and project before proceeding.</p>
</li>
<li><p>Click "Build a Cluster". (Alternatively, click "Create a New Cluster" toward the top-right of the screen, visible if you have at least one other cluster.)</p>
</li>
<li><p>If this is the first cluster in your project, you'll be asked to choose what kind of cluster you'd like to create. Select "Create a cluster" for the "Dedicated Multi-Region Clusters" option.</p>
</li>
<li><p>You are brought to the "Create a Multi-Region Cluster" screen. If not already in the ON position, toggle the "Multi-Cloud, Multi-Region &amp; Workload Isolation" option:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1610135535864/IoFyenLLP.png" alt="Multi-Cloud, Multi-Region Cluster Toggle" /></p>
</li>
<li><p>This will expand several more options for you to configure. These options determine the type and distribution of nodes in your cluster:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1610135563926/v6C7FjuUj.png" alt="Overview of all multi-cloud cluster options" /></p>
</li>
</ol>
<blockquote>
<p>💡 <em>What's the difference between "Multi-Region" and "Multi-Cloud" Clusters?</em></p>
<p>The introduction of multi-cloud capabilities in Atlas changes how Atlas defines geographies for a cluster. Now, when referencing a <em>multi-region</em> cluster, this can be a cluster that is hosted in:</p>
<ul>
<li>more than one region within one cloud provider, or</li>
<li>more than one cloud provider. (A cluster that spans more than one cloud spans more than one region by design.)</li>
<li>multiple regions across multiple cloud providers.</li>
</ul>
<p>As each cloud provider has its own set of regions, multi-cloud clusters are also multi-region clusters.</p>
</blockquote>
<p>7 . Configure your cluster. In this step, you'll choose a combination of Electable, Read-Only, and Analytics nodes that will make up your cluster.  </p>
<p>💡 <em>Choosing Nodes for your Multi-Cloud Cluster</em></p>
<p><strong>Electable nodes</strong>: Additional candidate nodes (via region or cloud provider) and only nodes that can become the primary in case of a failure. Be sure to choose an odd number of total electable nodes (minimum of three); these recommended <a class="post-section-overview" href="#choosing-your-electable-node-distribution">node distributions</a> are a good place to start. </p>
<p><strong>Read-Only nodes</strong>: Great for local reads in specific areas.</p>
<p><strong>Analytics nodes</strong>: Great for isolating analytical workloads from your main, operational workloads.</p>
<p>🤔 <em>Still can't make a decision? Check out the <a class="post-section-overview" href="#differences-between-electable-read-only-and-analytics-nodes">detailed differences</a> between Electable, Read-Only, and Analytics nodes for more information!</em></p>
<p>As an example, here's my final configuration (West Coast-based, using a 2-2-1 electable node distribution):
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1610135718969/gDektxVzo.png" alt="Node configuration, based on a 2, 2, 1 node distribution and a west coast priority" /></p>
<p>I've set up five electable nodes in regions closest to me, with a GCP Las Vegas region as the highest priority as I'm based in Las Vegas. Since both Azure and AWS offer a California region, the next closest ones available to me, I've chosen them as the next eligible regions. To accommodate my other service areas on the East Coast, I've also configured two read-only nodes: one in Virginia and one in Illinois. Finally, to separate my reporting queries, I've configured a dedicated node as an analytics node. I chose the same GCP Las Vegas region to reduce latency and cost.</p>
<p>8 . Choose the remaining options for your cluster: </p>
<ul>
<li>Expand the "Cluster Tier" section and select the "M10" tier (or higher, depending on your needs).</li>
<li>Expand the "Additional Settings" section and select "MongoDB 4.4," which is the latest version as of this time.</li>
<li>Expand the "Cluster Name" section and choose a cluster name. This name can't be changed after the cluster is created, so choose wisely!</li>
</ul>
<p>9 . With all options set, click the "Create Cluster" button. After a short wait, your multi-cloud cluster will be created! When it's ready, click on your cluster name to see an overview of your nodes. Here's what mine looks like:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1610135775200/x82PTdd6D.png" alt="Multi-cloud cluster overview" /></p>
<p>As you can see, the GCP Las Vegas region has been set as my preferred region. Likewise, one of the nodes in that region is set as my primary. And as expected, the read-only and analytics nodes are set to the respective regions I've chosen:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1610135803262/TTHd8T5T6.png" alt="New node assignments for a 2, 2, 1 node distribution." /></p>
<p>Sweet! You've just set up your own multi-cloud cluster. 🎉 To test it out, you can continue onto the next section where you'll manually trigger an election and see your primary node restored to a different cloud provider!</p>
<blockquote>
<p>🌟 You've just set up a multi-cloud cluster! If you've found this tutorial helpful or just want to share your newfound knowledge, consider <a target="_blank" href="https://twitter.com/intent/tweet?url=https://developer.mongodb.com/how-to/setup-multi-cloud-cluster-mongodb-atlas&amp;text=How%20to%20Setup%20a%20Multi-Cloud%20Cluster%20with%20@MongoDB%20Atlas%20by%20@AdrienneTacke">sending a Tweet</a>!</p>
</blockquote>
<h2 id="testing-a-primary-node-failover-to-a-different-cloud-provider">Testing a Primary Node Failover to a Different Cloud Provider</h2>
<p>If you're creating a multi-cloud cluster for higher availability guarantees, you may be wondering how to test that it will actually work if one cloud provider goes down. Atlas offers self-healing clusters, powered by built-in automation tools, to ensure that in the case of a primary node outage, your cluster will still remain online as it elects a new primary node and reboots a new secondary node when possible. To test a primary being moved to a different cloud provider, you can follow these steps to manually trigger an election:</p>
<ol>
<li><p>From the main "Clusters" overview in Atlas, find the cluster you'd like to test. Select the three dots (...) to open the cluster's additional options, then click "Edit Configuration":
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1610135899287/v4WUl7Vq8.gif" alt="Gif showing how to navigate to the cluster configuration screen" /></p>
</li>
<li><p>You'll be brought to a similar configuration screen as when you created your cluster. Expand the "Cloud Provider &amp; Region" section.</p>
</li>
<li><p>Change your Highest priority region to one of your lower-priority regions. For example, my current highest priority region is GCP Las Vegas (us-west4). To change it, I'll drag my Azure California (westus) region to the top, making it the new highest priority region:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1609907493319/mdatsc5kB.gif" alt="Gif of Azure California (westus) region row being dragged to the top, making it the highest priority region for the multi-cloud cluster" /></p>
</li>
<li><p>Click the "Review Changes" button. You'll be brought to a summary page where you can double-check the changes you are about to make:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1610135958577/gRLLxb32S.png" alt="Confirmation screen to change cluster configuration" /></p>
</li>
<li><p>If everything looks good, click the "Apply Changes" button.</p>
</li>
<li><p>After a short wait to deploy these changes, you'll see that your primary has been set to a node from your newly prioritized region and cloud provider. As you can see for my cluster, my primary is now set to a node in my Azure (westus) region:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1610136001069/dAaq2djuS.png" alt=" New node assignments. Arrow pointing to new primary node located in Azure (westus) region. Azure (westus) region surrounded by black border." /></p>
</li>
</ol>
<p>💡 In the event of an actual outage, Atlas automatically handles this failover and election process for you! These steps are just here so that you can test a failover manually and visually inspect that your primary node has, indeed, been restored on a different cloud provider.</p>
<p>There you have it! You've created a multi-cloud cluster on MongoDB Atlas and have even tested a manual "failover" to a new cloud provider. You can now grab the connection string from your cluster's Connect wizard and use it with your application.</p>
<blockquote>
<p>⚡ Make sure you delete your cluster when finished with it to avoid any additional charges you may not want. To delete a cluster, click the three dots (...) on the cluster overview page of the cluster you want to delete, then click Terminate.
Similar to GitHub, MongoDB Atlas will ask you to type the name of your cluster to confirm that you want to delete it, including all data that is on the cluster!</p>
</blockquote>
<h2 id="differences-between-electable-read-only-and-analytics-nodes">Differences between Electable, Read-Only, and Analytics Nodes</h2>
<h3 id="electable-nodes">Electable Nodes</h3>
<p>These nodes fulfill your availability needs by providing additional candidate nodes and/or alternative locations for your primary node. When the primary fails, electable nodes reduce the impact by failing over to an alternative node. And when wider availability is needed for a region, to comply with specific data sovereignty requirements, for example, an electable node from another cloud provider and similar region can help fill in the gap.</p>
<p>💡 When configuring Electable nodes in a multi-cloud cluster, keep the following in mind:</p>
<ul>
<li>Electable nodes are the <em>only ones that participate in replica set elections</em>.</li>
<li>Any Electable node can become the primary while the majority of nodes in a replica set remain available.</li>
<li>Spreading your Electable nodes across large distances can lead to longer election times.</li>
</ul>
<p>As you select which cloud providers and regions will host your Electable nodes, also take note of the order you place them in. Atlas prioritizes nodes for primary eligibility based on their order in the Electable nodes table. This means the <em>first row of the Electable nodes table is set as the highest priority region</em>. Atlas lets you know this as you'll see the "HIGHEST" badge listed as the region's priority.</p>
<p>If there are multiple nodes configured for this region, they will also rank higher in primary eligibility over any other regions in the table. The remaining regions (other rows in the Electable nodes table) and their corresponding nodes rank in the order that they appear, with the last row being the lowest priority region.</p>
<p>As an example, take this 2-2-1 node configuration:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1610136084871/e7INedSPc.png" alt="Sample 2-2-1 node configuration" /></p>
<p>When Atlas prioritizes nodes for primary eligibility, it does so in this order:</p>
<p>Highest Priority =&gt; Nodes 1 &amp; 2 in Azure California (westus) region</p>
<p>Next Priority =&gt; Nodes 3 &amp; 4 in GCP Las Vegas (us-west4) region</p>
<p>Lowest Priority =&gt; Single node in AWS N. California (us-west-1) region</p>
<p>To change the priority order of your Electable nodes, you can grab (click and hold the three vertical lines of the row) the region you'd like to move and drag it to the order you'd prefer.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1610136154313/SrxkbVqbu.gif" alt="Gif showing how to reorder region priorities by dragging and dropping rows in the table." /></p>
<p>If you need to change the primary cloud provider for your cluster after its creation, don't worry! You can do so at any time through your Atlas dashboard.</p>
<h3 id="read-only-nodes">Read-Only Nodes</h3>
<p>To optimize local reads in specific areas, use read-only nodes. These nodes have distinct read-preference tags that allow you to direct queries to the regions you specify. So, you could configure a node for each of your serviceable regions, directing your users' queries to the node closest to them. This results in reduced latency for everyone! 🙌</p>
<p>💡 When configuring Read-only nodes in a multi-cloud cluster, keep the following in mind:</p>
<ul>
<li>Read-only nodes don't participate in elections.</li>
<li>Because they don't participate in elections, they don't provide high availability. </li>
<li>Read-only nodes can't become the primary for their cluster.</li>
</ul>
<p>To add a Read-only node to your cluster, click "+ Add a provider/region," then select the cloud provider, region, and number of nodes you'd like to add. If you want to remove a Read-only node from your cluster, click the garbage can icon to the right of each row.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1609907381811/P8rO5CskL.gif" alt="Gif showing how to add Read-only nodes to a multi-cloud cluster in MongoDB Atlas" /></p>
<h3 id="analytics-nodes">Analytics Nodes</h3>
<p>If you need to run analytical workloads and would rather separate those from your main, operational workloads, use Analytics nodes. These nodes are great for complex or long-running operations, like reporting queries and ETL jobs, that can take up a lot of cluster resources and compete with your other traffic. The benefit of analytics nodes is that you can isolate those queries completely.</p>
<p>Analytics nodes have the same considerations as read-only nodes. They can also be added and removed from your cluster in the same way as the other nodes.</p>
<h2 id="choosing-your-electable-node-distribution">Choosing Your Electable Node Distribution</h2>
<p>Deploying an odd number of electable nodes ensures reliable <a target="_blank" href="https://docs.mongodb.com/manual/core/replica-set-elections/">elections</a>. With this in mind, we require a minimum of three electable nodes to be configured. Depending on your scenario, these nodes can be divided in several different ways. We generally advise one of the following node distribution options:</p>
<h3 id="2-2-1-two-nodes-in-the-highest-priority-cloud-region-two-nodes-in-a-lower-priority-cloud-region-one-node-in-a-different-lower-priority-region"><strong>2-2-1</strong>: <em>Two nodes in the highest-priority cloud region, two nodes in a lower-priority cloud region, one node in a different lower-priority region</em></h3>
<p>To achieve continuous read <strong>and</strong> write availability across any cloud provider and region outage, a 2-2-1 node distribution is needed. By spreading across multiple cloud providers, you gain higher availability guarantees. However, as 2-2-1 node distributions need to continuously replicate data to five nodes, across different regions and cloud providers, this can be the more costly configuration. If cost is a concern, then the 1-1-1 node distribution can be an effective alternative.</p>
<h3 id="1-1-1-one-node-in-three-different-cloud-regions"><strong>1-1-1</strong>: <em>One node in three different cloud regions</em></h3>
<p>In this configuration, you'll be able to achieve similar (but not quite exact) read and write availability to the 2-2-1 distribution with three cloud providers. The biggest difference, however, is that when a cloud provider <em>does</em> go down, you may encounter higher write latency, especially if your writes have to temporarily shift to a region that's farther away.</p>
<h2 id="multi-cloud-considerations">Multi-Cloud Considerations</h2>
<p>With multi-cloud capabilities come new considerations to keep in mind. As you start creating more of your own multi-cloud clusters, be aware of the following:</p>
<h3 id="electionreplication-lag">Election/Replication Lag</h3>
<p>The larger the number of regions you have or the longer the physical distances are between your nodes, the <strong>longer your election times/replication</strong> lag will be. You may have already experienced this if you have multi-region clusters, but it can be exacerbated as nodes are potentially spread farther apart with multi-cloud clusters.</p>
<h3 id="connection-strings">Connection Strings</h3>
<p>If you use the <a target="_blank" href="https://docs.mongodb.com/manual/reference/connection-string/#connections-standard-connection-string-format">standard connection string format</a>, removing an entire region from an existing multi-region cluster <strong>may result in a new connection string</strong>. Instead, <strong>it is strongly recommended</strong> that you use the <a target="_blank" href="https://docs.mongodb.com/manual/reference/connection-string/#dns-seed-list-connection-format">DNS seedlist format</a> to avoid potential service loss for your applications.</p>
<h3 id="host-names">Host Names</h3>
<p>Atlas <strong>does not</strong> guarantee that host names remain consistent with respect to node types during topology changes. For example, in my cluster named "multi-cloud-demo", I had an Analytics node named <code>multi-cloud-demo-shard-00-05.opbdn.mongodb.net:27017</code>. When a topology change occurs, such as changing my selected regions or scaling the number of nodes in my cluster, Atlas does not guarantee that the specific host name <code>multi-cloud-demo-shard-00-05.opbdn.mongodb.net:27017</code> will still refer to an Analytics node. </p>
<h3 id="built-in-custom-write-concerns">Built-in Custom Write Concerns</h3>
<p>Atlas provides built-in custom <a target="_blank" href="https://docs.mongodb.com/manual/reference/write-concern/">write concerns</a> for multi-region clusters. These can help improve data consistency by ensuring operations are propagated to a set number of regions before an operation can succeed.</p>
<p><em>Custom Write Concerns for Multi-Region Clusters in MongoDB Atlas</em></p>
<table>
<thead>
<tr>
<td>Write Concern</td><td>Tags</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><code>twoRegions</code></td><td><code>{region: 2}</code></td><td>Write operations must be acknowledged by at least two regions in your cluster</td></tr>
<tr>
<td><code>threeRegions</code></td><td><code>{region: 3}</code></td><td>Write operations must be acknowledged by at least three regions in your cluster</td></tr>
<tr>
<td><code>twoProviders</code></td><td><code>{provider: 2}</code></td><td>Write operations must be acknowledged by at least two regions in your cluster with distinct cloud providers</td></tr>
</tbody>
</table>
<h2 id="multi-cloud-faqs">Multi-Cloud FAQs</h2>
<p><strong>Can existing clusters be modified to be multi-cloud clusters?</strong>
Yes. All clusters M10 or higher can be changed to a multi-cloud cluster through the cluster configuration settings in Atlas.</p>
<p><strong>Can I deploy a multi-cloud sharded cluster?</strong>
Yes. Both multi-cloud replica sets and multi-cloud sharded clusters are available to deploy on Atlas.</p>
<p><strong>Do multi-cloud clusters work the same way on all versions, cluster tiers, and clouds?</strong>
Yes. Multi-cloud clusters will behave very similarly to single-cloud multi-region clusters, which means it will also be subject to the same constraints.</p>
<p><strong>What happens to the config servers in a multi-cloud sharded cluster?</strong>
Config servers will behave in the same way they do for existing sharded clusters on MongoDB Atlas today. If a cluster has two electable regions, there will be two config servers in the highest priority region and one config server in the next highest region. If a cluster has three or more electable regions, there will be one config server in each of the three highest priority regions.</p>
<p><strong>Can I use a key management system for encryption at rest with a multi-cloud cluster?</strong>
Yes. Whichever KMS you prefer (Azure Key Vault, AWS KMS, or Google Cloud KMS) can be used, though only one KMS can be active at a time. Otherwise, key management for encryption at rest works in the same way as it does for single-cloud clusters.</p>
<p><strong>Can I pin data to certain cloud providers for compliance requirements?</strong>
Yes. With <a target="_blank" href="https://docs.atlas.mongodb.com/global-clusters">Global Clusters</a>, you can pin data to specific zones or regions to fulfill any data sovereignty requirements you may have.</p>
<hr />
<h2 id="thank-you">Thank you!</h2>
<p>Thank you so much for taking the time to read through my article. If you enjoyed it or have a question, please let me know in a comment below. Or even better, if you feel this article would be helpful to other devs, please share it/tweet it to spread the knowledge and love. ♥️</p>
<p>For more from me, be sure to follow <a target="_blank" href="https://blog.adrienne.io/">my blog</a>! And to see what I'm currently up to, follow me on <a target="_blank" href="https://twitter.com/AdrienneTacke">Twitter</a>!</p>
]]></content:encoded></item><item><title><![CDATA[A Countdown Timer in Pure JavaScript]]></title><description><![CDATA[Need a countdown timer without having to download third party libraries or install additional npm packages?
I did too.
Ideally, and essentially, all I needed was a function to accept a target end date and return the remaining time until that date. Th...]]></description><link>https://blog.adrienne.io/a-countdown-timer-in-pure-javascript</link><guid isPermaLink="true">https://blog.adrienne.io/a-countdown-timer-in-pure-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Adrienne Tacke]]></dc:creator><pubDate>Tue, 22 Dec 2020 20:46:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1608669172469/CE7_Oklfn.gif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Need a countdown timer without having to download third party libraries or install additional npm packages?</p>
<p>I did too.</p>
<p>Ideally, and essentially, all I needed was a function to accept a target end date and return the remaining time until that date. That’s exactly what I built using only pure (vanilla) JavaScript. I’ll show you the code and then explain, line-by-line. :)</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="f5a25c304f1b7b4a6fa42db70415bad2"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/adriennetacke/f5a25c304f1b7b4a6fa42db70415bad2" class="embed-card">https://gist.github.com/adriennetacke/f5a25c304f1b7b4a6fa42db70415bad2</a></div><p>Let’s explain what’s going on here:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">countdown</span>(<span class="hljs-params"><span class="hljs-string">`endDate`</span></span>) </span>{
</code></pre>
<p>Ok, softball line of code here right? We’re declaring our function <code>countdown</code> which accepts a parameter <code>endDate</code>. So far, so good, yeah?</p>
<p><img src="https://media.giphy.com/media/zcCGBRQshGdt6/giphy.gif" alt="That was easy from Office Space" /></p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> days, hours, minutes, seconds;
</code></pre>
<p>Now we’re declaring several variables that we’ll need. These will be the units of time that will be calculated and displayed. Note: These were the specific units I needed; You can add/remove other units of time as needed for your purposes.</p>
<p>Here, I chained two methods to transform <code>endDate</code> into a usable format that we can perform operations on.</p>
<p>First:</p>
<pre><code class="lang-js">endDate = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(endDate)
</code></pre>
<p>converts our passed in <code>endDate</code> parameter into a JavaScript Date object.</p>
<p>Second:</p>
<pre><code class="lang-js">.getTime();
</code></pre>
<p>returns our newly converted JavaScript date into milliseconds…Specifically, <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime">the number of milliseconds that have elapsed between 1 January 1970 00:00:00 UTC and the given date</a>.</p>
<p>Great! Now our <code>endDate</code> is in milliseconds and ready to be used in calculations. Before we start calculating though, I added a simple validation check:</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (<span class="hljs-built_in">isNaN</span>(endDate)) { 
    <span class="hljs-keyword">return</span>; 
}
</code></pre>
<p>After our conversions, we want to make sure the resulting number is, in fact a number. If not, we end the show right here.
Ok, now we’re done setting up the basics, now we can start having fun.</p>
<p><img src="https://media.giphy.com/media/3o6EhWeei7wsp2jc1G/giphy.gif" alt="Jared from Silicon Valley waving arms in excitement" /></p>
<pre><code class="lang-js"><span class="hljs-built_in">setInterval</span>(calculate, <span class="hljs-number">1000</span>);
</code></pre>
<p>Since we are evaluating how much time is remaining every second, we’ll use <code>setInterval</code> to repeatedly execute some function we decide to give it. So in the code above, we pass in our calculate function as the first argument and <code>1000</code> as the second argument to denote one second (1000 ms = 1 second).</p>
<p>Now we can declare our <code>calculate</code> function…</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculate</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-keyword">let</span> startDate = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime();
</code></pre>
<p>…and then grab the exact date as of this moment, converted into milliseconds, and place it in variable called <code>startDate</code>.</p>
<p>Then we can determine the time remaining between the current date and our end date:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> timeRemaining = <span class="hljs-built_in">parseInt</span>((endDate - startDate) / <span class="hljs-number">1000</span>);
</code></pre>
<p>To do this, we subtract <code>startDate</code> from <code>endDate</code> to get the remaining milliseconds between the two. Then we divide by <code>1000</code> to get seconds, which will be an easier unit to work with for calculating our other units of time. We store this in a variable called <code>timeRemaining</code>.</p>
<p>Now we check to see that there is, in fact, still time remaining between the current date and our end date:</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (timeRemaining &gt;= <span class="hljs-number">0</span>) {
</code></pre>
<p>If there is, we move into this block and calculate the unit specific measurements of time we want to display. Let’s start with remaining days:</p>
<pre><code class="lang-js">days = <span class="hljs-built_in">parseInt</span>(timeRemaining / <span class="hljs-number">86400</span>);
</code></pre>
<p>To calculate the days remaining, we divide our remaining time by <code>86400</code>, the number of seconds in a single day. This result is then parsed within the <code>parseInt()</code> function to ensure we work with whole numbers.</p>
<p>Before we continue calculating the other units, we need to subtract the days we’ve already calculated:</p>
<pre><code class="lang-js">timeRemaining = (timeRemaining % <span class="hljs-number">86400</span>);
</code></pre>
<p>Once we do this, we assign the remaining time to our <code>timeRemaining</code> variable.</p>
<p>We can now continue calculating the other units of time in the same manner:</p>
<pre><code class="lang-js">hours = <span class="hljs-built_in">parseInt</span>(timeRemaining / <span class="hljs-number">3600</span>); <span class="hljs-comment">// 3600 seconds in one hour</span>
timeRemaining = (timeRemaining % <span class="hljs-number">3600</span>);

minutes = <span class="hljs-built_in">parseInt</span>(timeRemaining / <span class="hljs-number">60</span>); <span class="hljs-comment">// 60 seconds in one minute</span>
timeRemaining = (timeRemaining % <span class="hljs-number">60</span>);

seconds = <span class="hljs-built_in">parseInt</span>(timeRemaining);
</code></pre>
<p>Almost done! We’re now ready to update our DOM elements with our newly calculated units of time!</p>
<p><img src="https://media.giphy.com/media/R2m2NzVxQ3pbG/giphy.gif" alt="Man turning around from computer signaling he is very close to being finished, motioning with two fingers slightly apart to denote how close" /></p>
<p>I made things easier for myself and created an element per unit of time I was going to display. For reference, check out my <a target="_blank" href="https://github.com/adriennetacke/maintenance-template">GitHub repo</a> to see the page I built utilizing this countdown timer. In essence, my timer would be displayed in a <code>div</code> that looked like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"countdown"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"timer"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"days"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> Day(s)
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"hours"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> Hour(s)
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"minutes"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> Minute(s)
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"seconds"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> Second(s)
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>With that in mind, I simply get the element I need and set its <code>innerHTML</code> to the appropriate unit:</p>
<pre><code class="lang-js"><span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"days"</span>).innerHTML = <span class="hljs-built_in">parseInt</span>(days, <span class="hljs-number">10</span>);
</code></pre>
<p>For remaining days, I parse my <code>days</code> variable and explicitly set the radix to <code>10</code> before assigning it to my element. This is to ensure the resulting display is set in the decimal numeral system.</p>
<p>Continuing on with the other units of time, I adjust the resulting calculations to display a leading zero before assigning it to its corresponding element:</p>
<pre><code class="lang-js"><span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"hours"</span>).innerHTML = hours &lt; <span class="hljs-number">10</span> ? <span class="hljs-string">"0"</span> + hours : hours;
</code></pre>
<p>First, I check if the remaining hours are below double-digits, which start at 10. If it is, I append a <code>"0"</code> before the remaining hours. Otherwise, I just return the remaining hours as-is.</p>
<p>For example, if <code>hours = 4</code>, the ternary operator would evaluate to <code>true</code> as it's less than 10. Adding the leading zero would return <code>"04"</code>.</p>
<p>Alternatively, if <code>hours = 23</code>, the ternary operator would evaluate to <code>false</code>, so adding the leading zero would be unnecessary. So, I just return the hours as-is.</p>
<p>I do the same thing for <code>minutes</code> and <code>seconds</code>:</p>
<pre><code class="lang-js"><span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"minutes"</span>).innerHTML = minutes &lt; <span class="hljs-number">10</span> ? <span class="hljs-string">"0"</span> + minutes : minutes;

<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"seconds"</span>).innerHTML = seconds &lt; <span class="hljs-number">10</span> ? <span class="hljs-string">"0"</span> + seconds : seconds;
</code></pre>
<p>Just need a few more closing curly bracket and remaining code to end function execution if there is no time remaining:</p>
<pre><code class="lang-js">        } <span class="hljs-keyword">else</span> {  
          <span class="hljs-keyword">return</span>;
        }
    }
}
</code></pre>
<p>And that’s it!</p>
<p><img src="https://media.giphy.com/media/XreQmk7ETCak0/giphy.gif" alt="90s kid nodding his head and giving a thumbs up" /></p>
<p>In the context of my <a target="_blank" href="https://github.com/adriennetacke/maintenance-template">maintenance page</a>, I wanted this countdown timer to start on page load. So I decided to place my <code>countdown</code> function within an iife, or <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/IIFE">immediately-invoked function expression</a>:</p>
<pre><code class="lang-js">(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{  
  countdown(<span class="hljs-string">'04/01/2018 05:00:00 PM'</span>);
}());
</code></pre>
<p>Our scheduled platform upgrade was slated to end on April 1st (no joke!) at 5PM, so this was the date I passed in.</p>
<p>This worked perfectly and was just what I needed. As promised, no external libraries or extra packages were used. JavaScript really is a wonderful language. :)</p>
<hr />
<p>Thanks for reading! If you enjoyed it, please let me know in a comment below. Or even better, if you feel this article was thorough in a good way, please share it/tweet it to spread the knowledge and love. ♥️</p>
<p>For more from me, be sure to follow <a target="_blank" href="https://blog.adrienne.io/">my blog</a>!
And to see what I'm currently up to, follow me on  <a target="_blank" href="https://twitter.com/AdrienneTacke">Twitter</a>  &amp;&amp;  <a target="_blank" href="https://www.instagram.com/adriennetacke/">Instagram</a>!</p>
]]></content:encoded></item><item><title><![CDATA[Three things I wish I knew before becoming a software developer]]></title><description><![CDATA[Especially as a woman in tech!
Kumusta! My name is Adrienne Tacke. After almost 8 years as a developer in the US, I have gathered some insightful advice that I’d like every developer to know, especially those who are just starting out.
Here’s to help...]]></description><link>https://blog.adrienne.io/three-things-i-wish-i-knew-before-becoming-a-software-developer</link><guid isPermaLink="true">https://blog.adrienne.io/three-things-i-wish-i-knew-before-becoming-a-software-developer</guid><category><![CDATA[womenwhocode]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Career]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Adrienne Tacke]]></dc:creator><pubDate>Wed, 16 Dec 2020 18:40:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1607553722776/ot92dxyP_.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Especially as a woman in tech!</p>
<p>Kumusta! My name is Adrienne Tacke. After almost 8 years as a developer in the US, I have gathered some insightful advice that I’d like every developer to know, especially those who are just starting out.</p>
<p>Here’s to helping the next wave of developers!</p>
<h1 id="insight-1-youll-need-to-fail-fast-and-fail-often-if-you-want-to-get-ahead">Insight 1: You’ll need to fail fast and fail often if you want to get ahead.</h1>
<p><img src="https://media.giphy.com/media/fbKaEClhBDqdW/giphy.gif" alt="Kitten trying to jump onto shelf, catches on, but ultimately falls off" />
<span><i>Failure is inevitable. Embrace it.</i></span></p>
<p>Failure is inevitable in a software development journey. Just look at how many concepts, frameworks, and tools there are to learn in web development alone! I’m willing to bet that most new web developers have gone through the agony of trying to set up Webpack for the first time or were deathly afraid to run a git command or two.</p>
<p><img src="https://media.giphy.com/media/xT0Gqr8S3sT5DQzHOM/giphy.gif" alt="Jared from Silicon Valley covering his eyes and rocking back and forth in a frustrated motion" />
<span><i>Learning web development in ${year}.</i></span></p>
<p>The point is, when something is overwhelming or new for someone, there is a great chance that person will make a mistake. And when that something is also ever-evolving and quickly changing (like software development!), you can be sure that the chances of making a mistake are guaranteed to increase.</p>
<p>The fear of failure is also something that hinders a lot of new developers. I remember when I was an intern for my university's software development department, I rarely asked questions and always tried to portray that I knew what I was doing. I didn’t.</p>
<p><img src="https://media.giphy.com/media/xUySTD7evBn33BMq3K/giphy.gif" alt="Buddy the Elf nodding and pretending to understand" />
<span><i>Not really. Not thoroughly.</i></span></p>
<p>By allowing this fear of failing and looking stupid consume me, I never asked how a certain piece of code worked or why we implemented a certain solution over another. I spent hours trying to piece together StackOverflow answers and other parts of our codebase to try and make sense of things instead of just asking for help or a pair programming session. These are the questions and learning opportunities that, had I encountered them sooner, would have made me a much better developer in a shorter amount of time. Instead, I spent an exaggerated amount of time learning things superficially rather than fully experiencing and building a solid foundation of core development concepts and best practices. Bummer.</p>
<p>So what do we do if all of this failure is inevitable?</p>
<p><strong>Embrace it.</strong></p>
<p>Don’t be fearful of it. Acknowledge it. Use it as a catapult in your journey, not as a ball and chain that drags you down. This is probably the <strong>most important piece of advice every new developer should know and is the reason I listed it first</strong>.</p>
<blockquote>
<p>By experiencing failure at a faster rate, you are inevitably catapulting yourself to the top of the steep learning curve that seems to discourage a lot of people.</p>
</blockquote>
<p>When you fail fast and fail often, it likely means you are learning things at a significantly faster rate than someone who does their best to <em>avoid</em> failure. The sooner you learn how to deal with merge conflicts, run into console errors while setting up Webpack, or experience what happens when you forget a <code>WHERE</code> clause in your SQL query, the greater your growth as a developer.</p>
<h1 id="insight-2-imposter-syndrome-is-normal-at-every-stage">Insight 2: Imposter Syndrome is normal at every stage.</h1>
<p>There will be points in your career where you’ll feel crippling doubt. It can come when you bomb a technical interview, are stuck on a bug for longer than a few days, or start several side projects that never get completed.</p>
<p>It can also creep in when you start comparing yourself to other developers who are in different fields, seem more accomplished, or generally seem like they know their shit. This happens to me sometimes. Even though I have eight years of experience, made key contributions to several production-level applications, and have a pretty accomplished career if I look at myself objectively, I suddenly feel irrelevant the moment I see another Boston Dynamics video.</p>
<p><img src="https://media.giphy.com/media/m6wBlE6mGJ1Ju/giphy.gif" alt="Boston Dynamics robot Atlas impressively doing a backflip" />
<span><i>Boston Dynamics, if you read this, I will quit my job and totally intern for you ❤</i></span></p>
<p>I mean, look at how much progress they are making in the field of robotics!</p>
<p><em>infatuated sigh</em></p>
<p>What you and I need to keep in mind, however, is that every example and moment of comparison I just mentioned can happen at ANY point in a developer’s career. From interns to architects and self-taught to formally educated, every developer I have ever met, including myself, has felt imposter syndrome at <strong>multiple</strong> points in their journey.</p>
<p>And you know what? <strong>That’s ok</strong>. What’s important to remember is that if you feel these pangs of imposter syndrome, it absolutely does not mean you are a bad developer. In fact, I like to think that it actually means one of the following things:</p>
<ul>
<li>You don’t understand some fundamental concept, a language’s syntax, or a new tool well enough yet</li>
<li>You don’t know or fully understand the scope of the problem/task that is before you</li>
<li>You don’t know the entire depth and breadth of hard work and circumstances the person you are comparing yourself to has faced to get to the point they are at now</li>
<li>You did not prepare || study || learn something new as well as you think you did</li>
<li>You may be lacking a good night's sleep or be under other stress.</li>
<li>You've set unreasonable expectations for yourself when it comes to learning and becoming skilled in something new.</li>
<li>You did not have enough || any coffee before starting your day.</li>
</ul>
<p>You know what’s awesome about all of these potential causes of Imposter Syndrome? They are all <em>actionable</em> things that you can <strong>control</strong>! Things you can work towards, improve upon, and change. Most importantly, they are all things that are hardly indicative of being intrinsically bad at software development.</p>
<p>So the next time you are banging your head on your desk because the same console error is appearing in DevTools for 4 hours, take a break and get some more coffee. Then remember that just because you are caught in a snag today DOES NOT mean you are a “fake” developer.</p>
<h1 id="insight-3-there-is-no-developer-uniform">Insight 3: There is no developer “uniform”.</h1>
<blockquote>
<p><em>The following insight and advice applies to everyone, but unfortunately feel it will be more relatable to women in tech.</em></p>
</blockquote>
<p>There is still a large misunderstanding regarding what a “real” developer is and what they’re “supposed” to look like.</p>
<p>Essentially, when asking an average person to describe a software developer, the stereotypical example of a white male that’s socially awkward, poorly dressed, and poorly groomed is usually brought up.</p>
<p><img src="https://media.giphy.com/media/RyXVu4ZW454IM/giphy.gif" alt="Kung Fury character hackerman slowly looking at the camera" /></p>
<p>Of course, most of us know this is fundamentally incorrect. <strong>Or do we</strong>?</p>
<p>If you follow my <a target="_blank" href="https://www.instagram.com/adriennetacke/">Instagram</a>, you’ll know that I like to wear what others consider feminine/body-conscious outfits. Nothing too drastic or revealing as my job requires a business-professional dress code. Unfortunately, with the internet being the predictable beast that it is, I found that  <a target="_blank" href="https://www.instagram.com/p/BcD2OrvjkFl/?taken-by=adrienne.tacke&amp;source=post_page---------------------------">one of my Instagram posts</a>  suddenly became a semi-popular meme on Facebook one day:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607550946732/Rl4d4OnLQ.png" alt="Cool, I’m a meme! Wait, what do the comments say?!" /> <span><i>Cool, I’m a meme! Wait, what do the comments say?!<i></i></i></span></p>
<p>That’s cool. Until you read the comments…</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607550996668/0gPC9Ag2Q.png" alt="&quot;Real&quot; developers, as described by some Facebook comments 🙄" /> <span><i>"Real" developers, as described by some Facebook comments 🙄</i></span></p>
<p>What was even more disheartening were the comments from other <strong>females</strong>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607551329301/buhyG6_K8.png" alt="Yay for women supporting women. :(" /> <span><i>Yay for women supporting women. :(</i></span></p>
<p>When we are already battling the same fear of failure as everyone else, trying to overcome regular Imposter Syndrome as well as Imposter Syndrome Because You Are A Woman ©, and constantly working a little bit harder to prove ourselves and our skills, is it really necessary to add “appropriate” attire to the list of things we need to worry about? <em>sigh</em></p>
<p>Now don’t get me wrong. This IS Facebook, and I’m not saying that everyone holds these prejudices. In fact, there were a few brave souls that were speaking out against the misogynistic comments and even defending my existence:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607551385930/nEK0L-ViK.jpeg" alt="Michael is awesome. Try to be like Michael." /> <span><i>Michael is awesome. Try to be like Michael.</i></span></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607551418211/Kv3vz5-sl.jpeg" alt="Esa is also awesome. Be like Esa too." /> <span><i>Esa is also awesome. Be like Esa too.</i></span></p>
<p>Someone even linked my Instagram profile, but that wasn’t enough. I was a unicorn:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607551446191/1NaZK3uTq.jpeg" alt="Nah, that can’t be a real profile! 🙄 (FYI, my IG handle is now @adriennetacke)" /> <span><i>Nah, that can’t be a real profile! 🙄 (FYI, my IG handle is now @adriennetacke)</i></span></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607551482236/47XI4tuPo.jpeg" alt="Salamat!" /> <span><i>Salamat!</i></span></p>
<p>Ultimately, I’m just trying to show that there is still a large majority of society that maintain this mentality and continue to perpetuate the stereotype; that, in my 8 years of experience thus far, there is still work to do in terms of women supporting other women instead of tearing each other down; that this exact post is a clear example of why so few women enter software development in the first place or continue to stay in it.</p>
<p>Despite all of these factors, what I want everyone to know and take away from this is that it truly doesn’t matter what a person looks like or chooses to wear. And it certainly plays no part in determining whether or not someone is a developer or is a good one for that matter. Typing that out and reading it sounds a bit silly, doesn’t it? A little too common sense? And yet, I take the time to dedicate my third insight of this article for it because it is still a stereotype we need to break.</p>
<p><img src="https://media.giphy.com/media/3osxYcUO6kJgwPkOBO/giphy.gif" alt="Silicon Valley female engineer saying 'I am not a *woman engineer*. I am an engineer." /></p>
<p>For me, a “real” developer is someone that likes building things and solving all kinds of problems. It’s someone that enjoys learning new things, constantly challenging themselves, and is inquisitive.
And that’s it.</p>
<p>There’s no dress code, official operating system, or master programming language that you need to have or use to be a developer.</p>
<p>So what does this mean and how do we deal with the existing situation? We do everything we can to break the stereotype. Wear what you want to wear. Reach out to fellow developers and learn things together. Support others who are more knowledgeable than you and mentor those who know less than you. And probably the most significant thing we can do is to keep sharing our individual stories so that we can see different perspectives and show society that developers are more than just white, male, and casually dressed.</p>
<p>That’s why it’s so important for me to continue sharing my journey on Instagram and to keep wearing the outfits I wear. I don’t need to dress down, switch to a MacBook, have 10K followers on Twitter, or post <em>every</em> line of code I write to prove my skill or worth as a developer. Why? Because these things don’t bear <strong>any weight</strong> in my skill as a developer! </p>
<p>Sharing my story inspires other women, and anyone else, to continue wearing what they want to wear and worry less about the things that don’t matter. Volunteering to speak to school children shows that jobs in tech aren’t limited to boys. And sharing my insights to you all hopefully provides the guidance I wish I had while navigating through my software development career.</p>
<hr />
<p>Thank you so much for taking the time to read through my article. If you enjoyed it, please let me know in a comment below. Or even better, if you feel this article would be helpful to other devs, please share it/tweet it to spread the knowledge and love. ♥️</p>
<p>For more from me, be sure to follow <a target="_blank" href="https://blog.adrienne.io/">my blog</a>!
And to see what I'm currently up to, follow me on  <a target="_blank" href="https://twitter.com/AdrienneTacke">Twitter</a>  &amp;&amp;  <a target="_blank" href="https://www.instagram.com/adriennetacke/">Instagram</a>!</p>
]]></content:encoded></item></channel></rss>