<?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: Ryan Burmeister-Morrison</title>
    <description>The latest articles on DEV Community by Ryan Burmeister-Morrison (@rburmorrison).</description>
    <link>https://dev.to/rburmorrison</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%2F299326%2F9a293c9d-d4ff-48e7-b0fb-733e6f2ff223.jpg</url>
      <title>DEV Community: Ryan Burmeister-Morrison</title>
      <link>https://dev.to/rburmorrison</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rburmorrison"/>
    <language>en</language>
    <item>
      <title>How I Do More by Being Lazy, Impatient, and Over-Confident</title>
      <dc:creator>Ryan Burmeister-Morrison</dc:creator>
      <pubDate>Mon, 24 Feb 2020 04:02:58 +0000</pubDate>
      <link>https://dev.to/rburmorrison/how-i-do-more-by-being-lazy-impatient-and-over-confident-5gap</link>
      <guid>https://dev.to/rburmorrison/how-i-do-more-by-being-lazy-impatient-and-over-confident-5gap</guid>
      <description>&lt;p&gt;Laziness, impatience, and hubris. These are the three virtues of a great programmer written by Larry Wall (the creator of Perl) in his book, "Programming Perl".  More specifically, he wrote them as the "Virtues of the Perl Programmer", but they certainly span beyond Perl.&lt;/p&gt;

&lt;p&gt;This post is about how being lazy, impatient, and over-confident has improved my efficiency and the quality of my work. More importantly, though, it's about how these virtues allow me to enjoy my job while solving the problems at hand quicker, and how it can do the same for you.&lt;/p&gt;

&lt;h1&gt;
  
  
  Laziness
&lt;/h1&gt;

&lt;p&gt;I fell in love with programming when I was in high school. I had a fantastic teacher who had more to offer than most college professors I've encountered. I think what made her so effective was that she really focused on teaching the mindset that a programmer should have rather than the syntax of any particular language.  One thing that stuck with me more than anything else that she taught was &lt;strong&gt;laziness&lt;/strong&gt;. It's the first of the three virtues of a great programmer.  Here's the description of laziness, straight from "Programming Perl":&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Laziness sounds like the vice of the same name, but there’s a difference. The vice is about the avoidance of immediate work. The virtue is about the avoidance of future work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And &lt;em&gt;oh man&lt;/em&gt;, did I take that to heart. Laziness has become my core philosophy as a programmer, and it's a key ingredient to doing quality work. After all, it's the job of a programmer to do as much work now as they possibly can to ensure that they will do as little work as they possibly can later. A lazy programmer is a programmer that creates software that scales and source code that's maintainable. A lazy programmer is a magician that makes future problems disappear.&lt;/p&gt;

&lt;h2&gt;
  
  
  Organization
&lt;/h2&gt;

&lt;p&gt;So many frustrating problems can pop up when working on software. You get bugs, "it worked on my machine" syndrome, and things working when you have no idea how. Hours and hours are spent trying to solve these problems when they could all be prevented in the first place. They all stem from the same problem: &lt;strong&gt;a lack of organization&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Take this snippet of a file structure inspired by several projects I've seen before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── api.go
├── capMon.go
├── health.go
├── kubernetes.go
├── logs/
│   └── output.txt
├── processor.go
├── procMon.go
├── projectBinary
├── send.go
├── sync.go
└── yamlMon.go
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All I can say is &lt;strong&gt;&lt;em&gt;YIKES&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I'm only kidding, I can say more. I mean what is capMon? Are we playing Pokémon? Where is the main starting point? Turns out the answer is in &lt;code&gt;processor.go&lt;/code&gt;, right in the middle of the 1000 line file. What about &lt;code&gt;api.go&lt;/code&gt;?  That might make sense if it wasn't for the fact that &lt;code&gt;kubernetes.go&lt;/code&gt;, &lt;code&gt;health.go&lt;/code&gt;, &lt;code&gt;send.go&lt;/code&gt;, and &lt;code&gt;sync.go&lt;/code&gt; were all part of the API as well. You would never know that without looking through the code, which is buggy and unorganized as well. It's a tar pit - once you get in, you'll struggle, and the more you struggle, the deeper you sink.&lt;/p&gt;

&lt;p&gt;There are several other problems with a file structure like this, but I have to stop or I'll go on forever. &lt;strong&gt;Months&lt;/strong&gt; are wasted on code bases like this one, and unfortunately, this is more common than not.&lt;/p&gt;

&lt;p&gt;Here's a revised structure for the software:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── api/
│   ├── api.go
│   ├── health.go
│   ├── kubernetes.go
│   ├── send.go
│   └── sync.go
├── cmd/
│   └── program/
│       └── main.go
└── database/
    ├── capability.go
    ├── process.go
    └── yaml.go
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The code itself may not be fixed, but even a small change like this can save weeks worth of time, and the best part is that it's not much work at all to do this from the beginning.&lt;/p&gt;

&lt;p&gt;This goes beyond software structure, though. I can't count how many times I've tried to help somebody with a problem only to wade through a swamp of scattered files and directories just to find something simple. I get it, we're only human, but the mindset of "I can always fix it later" rarely does anybody any good. Yes, you can fix it later, but it'll be much more of a pain. Once I learned to save myself the pain and do it right from the start, I was surprised with how much time I saved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automation
&lt;/h2&gt;

&lt;p&gt;I currently go to an online school, but it wasn't too long ago that I was taking in-person classes on a campus. At that school, I had a particularly terrible class due to a particularly terrible professor. We were made to grade each other's homework, which he claimed was a "learning opportunity", and he had incredibly arbitrary rules that we were required to follow. Par for the course as far as college goes, but his biggest offense was that he had us create his quiz and test questions for him.&lt;/p&gt;

&lt;p&gt;We were separated into groups, and every week, for fifteen weeks, each team had to create five multiple choice questions, five short answer questions, and five code snippet questions. Every question we wrote had to be written in a very particular format, and the file's line endings had to be &lt;code&gt;\r\n&lt;/code&gt; since it worked in Windows notepad, which he was using. It was a lot of work on top of the work we were already given.&lt;/p&gt;

&lt;p&gt;For the first two weeks, we tried to do the work manually. It was a mess. Some of the team was doing work last minute, losing questions, and everybody was forgetting their secondary roles (editing, submitting, etc.). So what did I do to fix the problem? Well, I created an entire website from scratch in two weeks, of course. This is what it looked like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XwCHiHM7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tu05k76bcdzlqfws8ia7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XwCHiHM7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tu05k76bcdzlqfws8ia7.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was full with an in-built code editor, interactive multiple choice inputs, and progress statistics. Most importantly, it would keep track of who was doing what and format the questions exactly the way the requirements stated. I almost got to the point where the server would automatically email the professor when everybody voted to submit it, but the class ended before I was able to.&lt;/p&gt;

&lt;p&gt;The moral of the story is that you won't always be able to prevent frustrating work from presenting itself, as organized and prepared as you may be. Some things will be thrust upon you against you will. But never fret; you can always &lt;strong&gt;automate it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At work, I automate almost everything that takes me over a minute to do and I do often. I no longer set up my machines with my tool set, a script does it for me. I don't deploy my software to a test machine, I have another program that does it for me and live-streams the logs back to me. Automation can be easy, or it can be hard. It can be a simple script, or it can be a complex program.  When thinking about automating something, you have to assess how much time it saves you. Will the time to develop the script take longer than it would to do the task manually? Most of the time, you'll find that the answer is no, and you can completely automate those tasks away.&lt;/p&gt;

&lt;h1&gt;
  
  
  Impatience
&lt;/h1&gt;

&lt;p&gt;This is the second virtue of a great programmer. From the book:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Impatience is that nasty feeling you get when the computer is doing what it wants instead of what you want. Or, more correctly, when the programmer on the other side of the software chose the wrong default settings, made a poor GUI, or doesn’t give you access to this data. You’ve experienced it enough to not inflict the same pain on other programmers, turning your frustration with your wasted time into a benefit for other people.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Any programmer that has had to work with another has faced this problem. It's an innate annoyance of any inefficiency that disrupts the instant gratification we crave. Yet, the problem is common enough that I'm inclined to not believe a programmer who claims they have not dealt with this problem.&lt;/p&gt;

&lt;p&gt;But impatience doesn't always apply to working with others. A lot of time time, the one you find most difficult to work with is yourself. This section is about being impatient with yourself, and making it more tolerable for you to work with &lt;em&gt;you&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Right Tools
&lt;/h2&gt;

&lt;p&gt;You shouldn't have to create your own chainsaw from scratch to cut down a tree, yet I see people using vanilla JavaScript to build complex user interfaces instead of a framework &lt;em&gt;all the time&lt;/em&gt;. The time and resources that takes to do is ridiculous for the task at hand. Using the right tool for the job can quite literally make you go from taking months to finish a task, to weeks or even days.&lt;/p&gt;

&lt;p&gt;The biggest thing that clicked for me was realizing just how inefficiently we write text. Have you ever thought about how much time it takes to copy and paste something with your mouse over and over? Or how long it takes to use the arrow keys to move to another part of your document? All that time adds up, and it's not anything you'd ever notice until you don't do it anymore. And it's all because we use tools designed for ease-of-use, not efficiency. That's fine for the layfolk, but as tech professionals, it's downright unacceptable in my opinion.&lt;/p&gt;

&lt;p&gt;This changed for me after I learned Vim. If you're not aware of what Vim is, it's a text editor designed around using shortcuts exclusively. I mean, the mouse is disabled by default. It has a high learning curve, but the amount of time you save yourself in the long-term is unparalleled. After all, most of us write text all day, every day. Take the example of a group of lines that need their prefix changed. Here's how I'd do it in Vim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ucI3WBmI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/do9heys68y3dkbk464qa.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ucI3WBmI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/do9heys68y3dkbk464qa.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What might take the casual copy-paster 15 seconds to do, I've condensed into a maximum of two seconds. Not only that, but it's scalable. While it may not be practical, you can give me 1000 lines and I can do it at the same speed.&lt;/p&gt;

&lt;p&gt;Let's look at a more complex example. Say, perhaps, that you have a CSV file full of peoples' names, jobs, and cell phone numbers, and you need to convert it to JSON format. Here's what it looks like in Vim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xoVVkOx_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1fxe7l22iojhsult6vug.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xoVVkOx_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1fxe7l22iojhsult6vug.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's not something you can do in any other tool I know of. All it needed me to do was teach it how to format the text once (which I didn't include since it takes 15 seconds), and then I simply told it to repeat that work 15 times. I've had to do things similar to this countless times, and each time it comes up, I can't help but appreciate how much time I save. The alternative is to write a whole program that will format it for you, or go line by line and manually copy and paste the text for each one, which is something I see people do a lot.&lt;/p&gt;

&lt;p&gt;I focused on Vim a lot here because it's a perfect example of using the right tool for the job, but it's only an example. There are so many things you do on a day to day basis that you're probably using the wrong tool for. As a general rule of thumb: if a task feels like there's a better way to do it than the way you're using, there probably is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Side Note: Know Your Tools
&lt;/h2&gt;

&lt;p&gt;This might seems self-evident, but even if you are using the right tools, they won't help if you don't know how to use them. I can't count the number of times somebody has told me "I wish tool W did X, Y, and Z", just for me to point out that tool W does, in fact, do X, Y, and Z, if only they read the instructions they'd know about it.&lt;/p&gt;

&lt;p&gt;I get it, instructions are boring, but if you are using (and cussing at) a particular tool every day, you ought to know what it does. Take the time to read the five-page manual on what it does. It'll be boring, but it will save you frustration later on.&lt;/p&gt;

&lt;p&gt;As a special case, it particularly concerns me how many people are writing software in professional setting when they hardly know the language they're working with; how they download libraries with functionality that is already built into it and incur security risks. There is great value in learning in-depth about a tool such as a programming language that's used to make content for other people. This is a problem that's in more software than you know, and you can find it pretty easily by looking at open-source software on GitHub.&lt;/p&gt;

&lt;h1&gt;
  
  
  Over-Confidence
&lt;/h1&gt;

&lt;p&gt;Hubris, the last virtue has this description in "Programming Perl":&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hubris is the sense that, with the right tools, you can do just about anything. It’s all a Simple Matter of Programming, right? It’s also the thing that’s likely to make you fly too close to the Sun.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hubris is the over-confidence a programmer gets from winning and solving problems all the time. It's the yeast that inflates laziness and impatience and makes them relevant. Why be organized if you feel like it won't matter anyway?  Why learn your tools if you feel like it won't help? Over-confidence is the thing that makes a programmer move forward even when something seems impossible.&lt;/p&gt;

&lt;p&gt;Perhaps it's the hubris in me, but I'm not concerned with flying too close to the sun. In fact, I think it's entirely necessary. Tech is at the forefront of innovation. We are becoming a software-defined world, and somebody needs to test the boundaries. Somebody needs to see how far we can go.&lt;/p&gt;

&lt;p&gt;After all that I've learned so far - and I still have a ways to go - anything seems possible. Every problem is simply a matter of difficulty, not possibility, and it's that mindset that drives me to do more; it's that mindset that inspires me to be lazy and impatient so that I can focus on moving forward.&lt;/p&gt;

&lt;p&gt;So in conclusion, whether you're young or old, experienced or inexperienced, you should strive to be the laziest, most impatient, most stubborn person you can be. Your co-workers will respect you more for it, and so will you.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>codequality</category>
      <category>efficiency</category>
    </item>
    <item>
      <title>Language Review: Gophers Galore!</title>
      <dc:creator>Ryan Burmeister-Morrison</dc:creator>
      <pubDate>Thu, 16 Jan 2020 03:57:23 +0000</pubDate>
      <link>https://dev.to/rburmorrison/language-review-gophers-galore-53hi</link>
      <guid>https://dev.to/rburmorrison/language-review-gophers-galore-53hi</guid>
      <description>&lt;p&gt;For a relatively young language, Go's doing pretty well. Other than having the &lt;strong&gt;best mascot&lt;/strong&gt;, it has been used to create several very popular products, such as &lt;a href="https://github.com/docker/docker-ce" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;, &lt;a href="https://github.com/kubernetes/kubernetes" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt;, and &lt;a href="https://github.com/ethereum/go-ethereum" rel="noopener noreferrer"&gt;Ethereum's Geth&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Go's currently my favorite language for several reasons. Let's get to what's good, bad, and meh about Go.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Good:&lt;/strong&gt; Simple Syntax
&lt;/h1&gt;

&lt;p&gt;Go has only &lt;strong&gt;25 keywords&lt;/strong&gt;. For context, here's a graph of some of the most popular languages and the number of keywords they have.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fum7uy22mhfwe6li2ohhy.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fum7uy22mhfwe6li2ohhy.png" alt="# of Keywords"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's not a lot! And that's a good thing. There's not much magic in Go. That means that there's less to learn and more clarity by default. There's a post I love by Dave Cheney (a contributor to Golang itself) called &lt;a href="https://dave.cheney.net/2019/07/09/clear-is-better-than-clever" rel="noopener noreferrer"&gt;"Clear is better than clever"&lt;/a&gt;. It's a short post about the difference between readability in code and clarity, and the principles of effective Go code. It's &lt;em&gt;well worth&lt;/em&gt; the 5 or 10 minutes it takes to read.&lt;/p&gt;

&lt;p&gt;The lack of keywords makes it easy for new programmers to get started as well. I often hear about the ease of Python and its clarity. Take the following two snippets to compare them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# add.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// add.go&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To me, the Go code is more clear. That's not born out of familiarity; I've known Python far longer than I've known Go. For the most part, the code feels the same. But the addition of static typing in Go makes it very clear what my parameters must be in order to use &lt;code&gt;add()&lt;/code&gt;, and what I should expect back. I can't say the same about Python.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Good:&lt;/strong&gt; Static Typing and Type Inference
&lt;/h1&gt;

&lt;p&gt;Not everybody likes static typing, and I get it. It can feel like a hassle sometimes. Some things are just so obvious as to what they are that it feels like overkill to have to specify types for every variable, and in a lot of cases, it is! Fortunately, Go has type inference. Look at the following snippet:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;4.6&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In that snippet, &lt;code&gt;a&lt;/code&gt; is an &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt; is a &lt;code&gt;float64&lt;/code&gt;, and &lt;code&gt;c&lt;/code&gt; is a &lt;code&gt;string&lt;/code&gt;. I didn't have to specify the types, but they're defined. If I were to try to assign the value &lt;code&gt;3&lt;/code&gt; to &lt;code&gt;c&lt;/code&gt;, I'd get a type mismatch error. As a consequence, Go's typing system feels reasonable; the obvious stuff is taken care of for you, and the not-so-obvious stuff asks you to define the types. Surely that's not too much to ask to make your code easier to decode, right?&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Good:&lt;/strong&gt; Detailed Documentation
&lt;/h1&gt;

&lt;p&gt;Go has some very good documentation written by the official team. You can find it all in &lt;a href="https://golang.org/doc/" rel="noopener noreferrer"&gt;one location&lt;/a&gt;, and it's split up nicely. If you want an interactive taste of the language without committing fully, take &lt;a href="https://tour.golang.org/welcome/1" rel="noopener noreferrer"&gt;the tour&lt;/a&gt;. If you like what you saw in the tour, look at &lt;a href="https://golang.org/doc/code.html" rel="noopener noreferrer"&gt;How to Write Go Code&lt;/a&gt;. If you &lt;em&gt;really&lt;/em&gt; like Go, read the &lt;a href="https://golang.org/doc/effective_go.html" rel="noopener noreferrer"&gt;Effective Go&lt;/a&gt; document. It's all organized pretty well and well-written in my opinion.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Good:&lt;/strong&gt; Easy Documentation Tools
&lt;/h1&gt;

&lt;p&gt;Go puts a lot of emphasis on code documentation. If you use a tool like &lt;code&gt;golint&lt;/code&gt; which reports problems with your code style, you'll get several warnings if you don't add comments to exported functions. It might be annoying at first, but Go makes it easy to document your code properly and can generate a nice HTML document that maps out your code. It certainly helps that Go is statically typed, as it takes care of type definitions for you. All you need to do is add a short comment above the function you want to document, like so:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Add returns the result of adding one and two.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Of course, that's a simple and impractical example, but it really helps for large projects. If you want to see an example of what the generate documentation might look like, check out a package from Go's standard library: &lt;a href="https://golang.org/pkg/os/" rel="noopener noreferrer"&gt;https://golang.org/pkg/os/&lt;/a&gt;. Fair warning, it does get a little getting used to, but once you are, it's very nice.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Good:&lt;/strong&gt; A Large and Useful Standard Library
&lt;/h1&gt;

&lt;p&gt;I've written a lot of projects in Go, and in most of them, I only need one or two third-party dependencies &lt;em&gt;max&lt;/em&gt;. Compare that to NodeJS, where you typically need 20-30 for regular-sized projects &lt;em&gt;minimum&lt;/em&gt;. To me, that really speaks to the utility of Go's standard library and what's possible with it.&lt;/p&gt;

&lt;p&gt;I've written many servers and microservices in Go using only its standard library. Here's an interactive basic server implementation:&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@rburmorrison/SimpleServer?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;



&lt;p&gt;There's a lot of power in that little bit of code that isn't nearly as easy with the standard libraries of any other language I know. That's just a taste of all that Go's standard library can do. You can check out all the packages it has here: &lt;a href="https://golang.org/pkg/" rel="noopener noreferrer"&gt;https://golang.org/pkg/&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Good:&lt;/strong&gt; Verbose Error Handling
&lt;/h1&gt;

&lt;p&gt;Here's some code to open a file named &lt;code&gt;temp.txt&lt;/code&gt; for writing in Go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"temp.txt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;O_WRONLY&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;O_CREATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0755&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"There was an error opening your file"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A lot of people I've known that use Go &lt;em&gt;can't stand&lt;/em&gt; this level of verbosity. In Go, functions return errors like that all the time, and you have to manually check if the error is &lt;code&gt;nil&lt;/code&gt; or not (to determine whether an error actually occurred). I get it; it does seem very verbose, particularly when compared to other languages.&lt;/p&gt;

&lt;p&gt;I'd like to make a counter-argument, however. In other languages like Python and Java, if you're doing it right, your error handling will be just as verbose. Here's Python's equivalent code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;temp.txt&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;eprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;There was an error opening your file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To me, Go is the winner again.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Meh:&lt;/strong&gt; Package Management
&lt;/h1&gt;

&lt;p&gt;Go's package management has traditionally been very messy. Originally, packages were pulled straight from places like GitHub and had no versions. Each time you needed to download new dependencies, they'd pull the newest commit from the repo's master branch by default, which had the possibility of breaking your codebase. To combat it, projects would vendor their dependencies, meaning they would be re-downloaded and placed in a special &lt;code&gt;vendor/&lt;/code&gt; folder in your project's root. This made the codebase large and hard to keep up with.&lt;/p&gt;

&lt;p&gt;More recently, since Go v1.11, modules have been implemented. They still feel a bit wonky, but everything has versions, and the dependencies are managed automatically. It's also very easy to migrate old projects to the new module system, as it only needs to add one configuration file, &lt;code&gt;go.mod&lt;/code&gt;. It still needs work, but it's improving for sure.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Bad:&lt;/strong&gt; No Generics, Overloading, or Default Parameters
&lt;/h1&gt;

&lt;p&gt;When trying to get into Go's advanced concepts, or when trying to build large projects, Go can feel really inflexible. To an extent, that's part of its design, but it really hurts when you need to create a custom data structure and you have to do a lot of extra work to get it working properly. Here's a (very) minimal stack implementation in Go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Position&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;Items&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewStack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Position&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Items&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Position&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Position&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;

    &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NewStack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pop&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pop&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will work as expected, but for a language that prides itself in clear and readable code, all of the &lt;code&gt;interface{}&lt;/code&gt; types (which match any type in Go) are hard to look at. The only other option is to create a separate &lt;code&gt;Stack&lt;/code&gt; for each type, which is a problem because Go doesn't support overloading either! As a consequence, you'd have to name each one as &lt;code&gt;StackString&lt;/code&gt;, &lt;code&gt;StackInt&lt;/code&gt;, &lt;code&gt;StackFloat64&lt;/code&gt;, and so on, and that's pretty darn &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" rel="noopener noreferrer"&gt;WET&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In a lot of cases when you have &lt;code&gt;interface{}&lt;/code&gt; declarations everywhere, you end up having to do a lot of manual type assertions to verify that you're working with the proper type. It's just plain frustrating when you have to deal with it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Go really shines when working within a team. It is easy to learn while still enforcing well-defined standards that maintain clarity. Learning new languages can sometimes feel like a curse after learning Go due to its ease and utility. Most of the co-workers I work with daily have converted to Go as their primary language. I could go on and on about other things that I like about Go, such as its &lt;strong&gt;speed&lt;/strong&gt; and &lt;strong&gt;portability&lt;/strong&gt;, but I have to stop somewhere.&lt;/p&gt;

&lt;p&gt;I hope it's obvious that the "Good", "Bad", and "Meh" labels are my opinion; I'm not trying to pass those off as fact. If you disagree with anything, let me know! I'd enjoy discussing it. And if you noticed that I said anything that is objectively wrong, post a comment! I'm open to having my mind changed.&lt;/p&gt;

&lt;p&gt;If you're interested in learning Go, leave a commment! I have some resources that have worked well for both myself, co-workers, and people who have never programmed before.&lt;/p&gt;

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

</description>
      <category>go</category>
      <category>review</category>
      <category>analysis</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Language Review: Yikes! A Python!</title>
      <dc:creator>Ryan Burmeister-Morrison</dc:creator>
      <pubDate>Wed, 15 Jan 2020 04:06:30 +0000</pubDate>
      <link>https://dev.to/rburmorrison/language-review-yikes-a-python-4h9l</link>
      <guid>https://dev.to/rburmorrison/language-review-yikes-a-python-4h9l</guid>
      <description>&lt;p&gt;It's no doubt that Python is popular, but to me, it's too similar to the snake it shares a name with; cool to look at, but too unreliable to handle.&lt;/p&gt;

&lt;p&gt;Of course, there are exceptions to every rule, and some people are great at writing in Python. Take the team that created Ansible, for example. &lt;a href="https://github.com/ansible/ansible"&gt;Its code&lt;/a&gt; is well-organized and readable. Clearly, they have a set of defined standards that they follow. The way they use Python as a language is fantastic too. They take advantage of the fact that Python is deployed on most Linux systems to make Ansible agentless. If you're unsure of what that means, you should check out my &lt;a href="https://dev.to/rburmorrison/theoretically-ansible-2hde"&gt;Theoretically: Ansible&lt;/a&gt; post, but just know it's pretty cool!&lt;/p&gt;

&lt;p&gt;Alright, enough complementing Ansible. Let's get to the points.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Good:&lt;/strong&gt; Easy to Get Started With
&lt;/h1&gt;

&lt;p&gt;A lot of people are learning Python as their first language, and it's understandable. For one, it doesn't have all the symbols that other languages have. Look at the following two snippets from C++ and Python, respectively.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// age.cpp&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Welcome!"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Sorry, you must be at least 18 to enter."&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# age.py
&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Welcome!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sorry, you must be at least 18 to enter."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's obvious, but the C++ snippet is more verbose in several ways. For new programmers, it's just too much too fast.&lt;/p&gt;

&lt;p&gt;Another thing that makes Python easier to work with is the abstraction of pointers. In my experience, pointers are the hardest learning point for new programmers. In Python, everything is pass-by-reference, meaning that you can get around pointers. No need to worry about making references and dereferencing.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Good:&lt;/strong&gt; Healthy Standard Library
&lt;/h1&gt;

&lt;p&gt;Python's &lt;a href="https://docs.python.org/3/library/"&gt;standard library&lt;/a&gt; clearly ate its veggies as a kid, and that's great. It means that out of the box, you can do a lot with it. Anything from cryptography, to drawing in the terminal, to GUI applications, to database interfacing is at your fingertips, and that's something I love to see in a language.&lt;/p&gt;

&lt;p&gt;If you use Python a lot, seriously look into what's available. You may not need as many third-party packages as you think you do.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Good:&lt;/strong&gt; Strong Community
&lt;/h1&gt;

&lt;p&gt;Because Python's so popular, its community is huge. You can find a library to do just about anything. Here are the statistics for &lt;a href="https://pypi.org/"&gt;PyPi&lt;/a&gt; as of writing this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qkTawpmy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/of81x2jz727aqxdmx8ez.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qkTawpmy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/of81x2jz727aqxdmx8ez.PNG" alt="PyPi Stats"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's pretty good! They're not as high as something like Maven or NPM, but that can be a good thing. It means there's a lot less clutter to filter through when dealing with dependencies, but there are also enough options to look at.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Meh:&lt;/strong&gt; Slowness
&lt;/h1&gt;

&lt;p&gt;"But machine learning is done with Python all the time! It &lt;em&gt;must&lt;/em&gt; be fast!", I hear you say. That's actually false. Python wrappers are created that call compiled C libraries in the background, and the majority of the work is done in C. Python is really, really slow. I recently found a machine learning library written in pure Python that takes 3-4 days to finish! If that were written in something like C, it would take less than an hour. If you want metrics, check out either of the below resources. Whether you trust them or not is up to you, but the code is available to inspect for yourself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/python.html"&gt;https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/python.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kostya/benchmarks"&gt;https://github.com/kostya/benchmarks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reason this is only listed as "Meh" is because, in most modern applications, speed doesn't really matter. Most software tends to be "good enough", and if you need to do something fast, you can always write the C code to interface with it. But you're certainly not going to write a fast system monitor in pure Python.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Meh:&lt;/strong&gt; Everything's Public
&lt;/h1&gt;

&lt;p&gt;There's no access control in Python. Have a utility function that's only going to be used in your package? It doesn't matter, anybody can access it anyway. If you don't think this is a problem, you're probably not considering the documentation that will be generated for your code. For other developers that want to work with what you make, it won't be immediately clear what you intend for them to use as opposed to what you wrote for internal use only. You can get around this by using an underscore (&lt;code&gt;_&lt;/code&gt;) as a prefix to a private function like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_my_helper&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# do something
&lt;/span&gt;    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_worker&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# do something
&lt;/span&gt;    &lt;span class="n"&gt;_my_helper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is only a "Meh" because if you can make sure that everybody follows this simple rule, you can get around a lot of the issues that everything being public causes.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Bad:&lt;/strong&gt; Dynamic Typing
&lt;/h1&gt;

&lt;p&gt;Dynamic typing is another selling point for new developers. Why wouldn't it be? There's no need to worry about the extra overhead of variable types. When you assign a number to a variable, the variable contains a number. It's as simple as that. Here's another C++ vs. Python example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// add.cpp&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;addone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 1&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# add.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're a fan of that, I get it. And when working on your own project that's just for you, it's fine. But when you want to work with other people, it's &lt;strong&gt;very frustrating&lt;/strong&gt;. What's to stop me from doing this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# add.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# adding a string
&lt;/span&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; ERROR
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Absolutely nothing&lt;/em&gt;. There's no getting around the fact that, because of dynamic typing, anybody can pass anything to that function. If I were to try that with C++, I'd know that I made a mistake before the program even ran. There's are &lt;strong&gt;tons&lt;/strong&gt; of subtle errors that occur from accidentally using the wrong types in the wrong places; problems that would be solved with static typing.&lt;/p&gt;

&lt;p&gt;So how do you get around it? Documentation. You're expected to write good enough documentation to let users know what they should expect to work with your code. Let's re-write the function to include some.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# add.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;"""
    Add 1 to 'num'.

    @type int
    @param The number to add 1 to

    @return The result of adding 1 to 'num'
    """&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay, so we've documented it, and it's clear what should be expected now, right? Well, sure. At the same time, though, you had to do a lot more work than just adding the keyword &lt;code&gt;int&lt;/code&gt; like you could have done in C++, which takes care of what you needed the documentation for in the first place. The other problem is that &lt;strong&gt;you just can't trust most developers&lt;/strong&gt;. Most developers just won't bother writing documentation like that, and Python won't force them to. Static typing will, though. At the very least, even if a developer is bad at documenting, you'll know what the parameters need to be, and what you'll get back from it.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Bad:&lt;/strong&gt; Poor Default Documentation Tools
&lt;/h1&gt;

&lt;p&gt;Okay, okay. So you're willing to write the documentation for your code, and you want to do it right. Good! But also, good luck. Python's documentation tools are just about the &lt;strong&gt;worst&lt;/strong&gt; I've seen in any language I've worked with. Python's default documentation tool is PyDoc, and here's an example of what its output looks like, generated from the official &lt;code&gt;sys&lt;/code&gt; package of the standard library.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U_hZFzXY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/8oqj5adkdycg8t703qkx.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U_hZFzXY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/8oqj5adkdycg8t703qkx.PNG" alt="PyDoc"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm not going to bother discussing how ugly it is, because it's beside the point, but it's just so barebones. There are links to the functions and all, but that's about it. Let's compare that to Ruby's &lt;code&gt;yard&lt;/code&gt; gem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iJuCjqX_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ohpml1wu1qdabmhfxgc4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iJuCjqX_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ohpml1wu1qdabmhfxgc4.PNG" alt="Yard Example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To me, the difference is night and day. Ruby has dynamic typing as well, but the documentation tools are so good, with support like official typing notation and a side navbar tree, that it makes it so much easier to work with. That's a big deal when working with other people.&lt;/p&gt;

&lt;p&gt;To be clear, there may very well be better documentation tools for Python out there; in fact, I'm sure there are. But Python's default tools are what most people are going to use, and if the default tools are bad, the documentation is likely to be as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Edit [1/15/20]:&lt;/strong&gt; I recently played around with Doxygen, which was a lot better than the built-in tools, and can get the job done to a decent extent. Still, due to the dynamic typing, it's a lot more work than it would be with static typing.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Bad:&lt;/strong&gt; Poor Dependency Management
&lt;/h1&gt;

&lt;p&gt;I'm not a fan of the way Python handles dependencies at all. For whatever reason, "wheel files" were created, which is a format for Python dependencies. The problem with them is that they are sometimes tied to specific architectures or Python versions. For example, if I download a wheel file for Python 3.7, and you have Python 3.5, oh well, you can't use it! I get version compatibility, but this goes beyond that. You must have the exact specifications to install certain wheel files. For people working in an offline environment, this is very frustrating. They can't simply keep a folder of the dependencies they need for their offline machine since they could easily be useless if they update my Python version.&lt;/p&gt;

&lt;p&gt;The other option is to download the archived source code, and that tends to work pretty well. It doesn't require specific versions of Python or architectures. It works well enough that you may wonder why wheel files exist. From my perspective, it feels like somebody said: "Ya know, archived source files work great, but why don't we make it harder for the developers to work with dependencies instead?" Maybe I'm missing something, but no other language that I've dealt with has that problem.&lt;/p&gt;

&lt;p&gt;But what am I complaining about if I can just use the tar files, then? Well, it turns out that some package developers just don't offer them. Of course, you can always go to the GitHub repos where the source is, but you then run into issues with different directory structures and a lack of official releases like PyPi has.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Bad:&lt;/strong&gt; Not Very Portable
&lt;/h1&gt;

&lt;p&gt;Python is not alone in this problem since it's mostly just a problem with interpreted languages in general. The issue is that when you want to send your Python code to anybody else to use, it takes a few steps.&lt;/p&gt;

&lt;p&gt;For example, if you used any third-party dependencies, the other person will have to download them themselves too. You're not going to make something in Python and have your computer-illiterate friend use it like you would be able to do in a compiled language.&lt;/p&gt;

&lt;p&gt;Portability is a particular problem for folks in offline environments, where every dependency change and deployment is a huge deal. It'd be much more convenient to have the dependencies bundled with each other, which is possible through a process called "freezing", but I've had tough luck with freezing Python code in more cases then I care to talk about, where it either required internet connectivity where I had none, or the resulting executable just doesn't work.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;There was a time when I loved Python. When was that time? It was when I only knew C++. &lt;em&gt;Of course&lt;/em&gt; Python's going to look great if that's the only language you know. It was easy, and it did the work for you. But in a real, practical, everyday environment, it just doesn't fly for me. There are just too many better options for languages to start with that fix the problems Python has.&lt;/p&gt;

&lt;p&gt;I hope it's obvious that the "Good", "Bad", and "Meh" labels are my opinion; I'm not trying to pass those off as fact. If you disagree with anything, let me know! I'd enjoy discussing it. And if you noticed that I said anything that is objectively wrong, post a comment! I'm open to having my mind changed.&lt;/p&gt;

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

</description>
      <category>python</category>
      <category>review</category>
    </item>
    <item>
      <title>5 Reasons Why Nim Is Becoming My Favorite Language</title>
      <dc:creator>Ryan Burmeister-Morrison</dc:creator>
      <pubDate>Wed, 08 Jan 2020 03:04:59 +0000</pubDate>
      <link>https://dev.to/rburmorrison/5-reasons-why-nim-is-becoming-my-favorite-language-4oke</link>
      <guid>https://dev.to/rburmorrison/5-reasons-why-nim-is-becoming-my-favorite-language-4oke</guid>
      <description>&lt;p&gt;If you haven't heard of &lt;a href="https://nim-lang.org/"&gt;Nim&lt;/a&gt; yet, you're in the majority. It's a very young language that only hit &lt;a href="https://github.com/nim-lang/Nim/releases/tag/v1.0.0"&gt;version 1.0.0&lt;/a&gt; late last year. I've been looking at it for a while, however, and with its v1.0.0 milestone, I decided to give it a try. Here are 5 reasons why it might take the place of my favorite language.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. It's Fully Compiled
&lt;/h1&gt;

&lt;p&gt;The difference between a compiled and an interpreted language can be a thin line. Take Java, for example, in which the code is compiled to bytecode that is then interpreted by the JVM. Nim has no such confusion; it's a fully compiled language with no gimmicks. That makes software that's created in Nim faster and more portable than if it were interpreted. If you want performance metrics, check out this benchmarking repo: &lt;a href="https://github.com/kostya/benchmarks"&gt;https://github.com/kostya/benchmarks&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. It's "Pythonic"
&lt;/h1&gt;

&lt;p&gt;There's no doubt that Python is incredibly popular right now. Just take a look at its &lt;a href="https://www.tiobe.com/tiobe-index/python/"&gt;Tiobe index&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WHLElVlS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/c0uyzay1udduzyksngso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WHLElVlS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/c0uyzay1udduzyksngso.png" alt="Python Tiobe Index"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hear people talk about Python's easy syntax and the ability to prototype quickly with it. If you're one of those people: good news! Python is one of Nim's main inspirations, and it shares a lot of the same syntax. Take a look at the following two snippets.&lt;/p&gt;

&lt;p&gt;Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# conditional.py
&lt;/span&gt;
&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"More than 10!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Less than 10!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Nim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="c"&gt;# conditional.nim&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"More than 10!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Less than 10!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Not bad, huh? If you have experience with Python, you'll get Nim's basics quickly. There's also a great resource for Python developers that shows the conversions from Python concepts to Nim concepts. You can find that here: &lt;a href="https://github.com/nim-lang/Nim/wiki/Nim-for-Python-Programmers"&gt;https://github.com/nim-lang/Nim/wiki/Nim-for-Python-Programmers&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Cross-Platform GUIs
&lt;/h1&gt;

&lt;p&gt;Nowadays, if you want to create a cross-platform GUI, you don't have a whole lot of options. They are: &lt;a href="https://electronjs.org/"&gt;Electron&lt;/a&gt;, C libraries like (&lt;a href="https://wxwidgets.org/"&gt;https://wxwidgets.org/&lt;/a&gt;) and &lt;a href="https://www.qt.io/"&gt;QT&lt;/a&gt;, Java Swing or &lt;a href="https://openjfx.io/"&gt;JavaFX&lt;/a&gt;. Because Nim is built on C and it can use its libraries, it makes using its UI libraries that much easier. Even in Nim's standard library, there's &lt;a href="https://nim-lang.org/docs/iup.html"&gt;a wrapper&lt;/a&gt; for the &lt;a href="https://www.tecgraf.puc-rio.br/iup/"&gt;IUP toolkit&lt;/a&gt;, which provides an easy way to create native, cross-platform applications like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3IPeh43G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/z61ftnc15zxpn73grb7r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3IPeh43G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/z61ftnc15zxpn73grb7r.png" alt="IUP Example - Pulled From: https://metacpan.org/pod/distribution/IUP/lib/IUP.pod"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Nim team is also working on a separate &lt;a href="https://github.com/nim-lang/ui"&gt;UI package&lt;/a&gt; for the standard library based off of &lt;a href="https://github.com/andlabs/libui"&gt;libui&lt;/a&gt;. Combined with the &lt;a href="https://nimble.directory/search?query=gui"&gt;several other third-party libraries&lt;/a&gt; availaible on &lt;a href="https://nimble.directory/"&gt;https://nimble.directory/&lt;/a&gt;, you have options! People are already doing cool things in Nim, like making &lt;a href="https://github.com/def-/nimes"&gt;a NES emulator&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ipoodCzQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/c2fvwyrg25x8ow7iiuy3.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ipoodCzQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/c2fvwyrg25x8ow7iiuy3.PNG" alt="nimes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  4. A Great Package Manager (&lt;a href="https://github.com/nim-lang/nimble"&gt;Nimble&lt;/a&gt;)
&lt;/h1&gt;

&lt;p&gt;The fun name aside, Nimble does its job well. One of the first things you'll notice about it is the automation that it provides. When initializing a new Nimble application, it will walk users through about 6 quick questions needed to set everything up. Past that, you can just start coding! It makes posting packages to &lt;a href="https://nimble.directory/"&gt;https://nimble.directory/&lt;/a&gt; for the world to see easy and makes your project's dependencies consistent.&lt;/p&gt;

&lt;h1&gt;
  
  
  5. It Has a Macro System (Metaprogramming)
&lt;/h1&gt;

&lt;p&gt;If you're not familiar with metaprogramming, it can be boiled down to "code that reads and writes code". This means that the code you're writing can manipulate itself and write complex, tedious bits of other code for you that you would otherwise have to do manually. This may seem confusing at first but what if you wanted to create a function called &lt;code&gt;debugPrint&lt;/code&gt; that does this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="n"&gt;debugPrint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# output: 3 + 3 =&amp;gt; 6&lt;/span&gt;
&lt;span class="n"&gt;debugPrint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c"&gt;# output: pow(2, 2) =&amp;gt; 4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you can do this without metaprogramming, I'd be thoroughly impressed. In fact, as far as I'm aware, it can't be done. However, if you have a macro system, you can have those lines write themselves. Here's what &lt;code&gt;debugPrint&lt;/code&gt; would look like as a Nim macro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="k"&gt;macro&lt;/span&gt; &lt;span class="n"&gt;debugPrint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;untyped&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;untyped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newLit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repr&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="s"&gt;" =&amp;gt; "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;(`&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;`,&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;`)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Don't get hung up on the syntax. Nim has some &lt;a href="https://nim-lang.org/docs/tut3.html"&gt;good resources&lt;/a&gt; to learn how its macro system works, and it's an advanced concept anyway. What you might want to know is that with this macro, the previous example's code gets converted to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="c"&gt;# conditional.nim&lt;/span&gt;

&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"3 + 3 =&amp;gt; "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pow(2, 2) =&amp;gt; "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Even if you don't ever see yourself using macros, it allows other package developers to create them for you, making your life easier. Take this &lt;a href="https://github.com/Vindaar/shell"&gt;shell package&lt;/a&gt;, for example, which allows you to write shell commands directly in your source code, which then get converted to the appropriate Nim syntax &lt;em&gt;automagically&lt;/em&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;Look, I could keep going on about Nim's features. Things like &lt;strong&gt;easy C interop&lt;/strong&gt;, &lt;strong&gt;Python bridges&lt;/strong&gt;, &lt;strong&gt;machine learning&lt;/strong&gt;, &lt;strong&gt;multiple paradigms&lt;/strong&gt;, &lt;strong&gt;a sub-scripting language&lt;/strong&gt; and the possibility for &lt;strong&gt;&lt;a href="https://github.com/liquid600pgm/rapid"&gt;game engines&lt;/a&gt;&lt;/strong&gt; get me excited, but I have to stop somewhere! If you're interested in checking out Nim, look at their &lt;a href="https://nim-lang.org/docs/tut1.html"&gt;official tutorial&lt;/a&gt;. And if you have any questions, leave them in the comments.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

</description>
      <category>nim</category>
      <category>gui</category>
      <category>metaprogramming</category>
      <category>nimble</category>
    </item>
    <item>
      <title>Summary: Ansible</title>
      <dc:creator>Ryan Burmeister-Morrison</dc:creator>
      <pubDate>Mon, 06 Jan 2020 23:17:01 +0000</pubDate>
      <link>https://dev.to/rburmorrison/theoretically-ansible-2hde</link>
      <guid>https://dev.to/rburmorrison/theoretically-ansible-2hde</guid>
      <description>&lt;p&gt;Welcome to Summary, a series where I summarize a concept or tool for you so you can understand your coworkers when they talk about it. In this post, I cover Ansible: a smooth, powerful, and versatile automation tool.&lt;/p&gt;

&lt;h1&gt;
  
  
  Concept
&lt;/h1&gt;

&lt;p&gt;Ansible shines brightest in two fields. The first is &lt;strong&gt;configuration management&lt;/strong&gt;, which is the idea of keeping the configuration between a cluster of computing devices consistent and predictable. The other is &lt;strong&gt;automatic deployment&lt;/strong&gt;, which is the process of automatically and continuously deploying software to a target machine or machines, usually for testing or demonstrations. Your idea of Ansible should not be limited by these fields, however, as it is capable of much more.&lt;/p&gt;

&lt;p&gt;To manage any number of nodes (computational devices), Ansible requires a master node. A master node is a machine that has access to all other nodes and is where Ansible itself resides.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C50v0QCp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3sgr6jgql645dfbjxknt.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C50v0QCp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3sgr6jgql645dfbjxknt.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The master node must be running Linux; however, child nodes can run either Windows or Linux. Apart from installing Ansible on the master node, child nodes must have SSH and any recent version of Python. SSH is the mechanism that the Ansible master uses to remotely access child nodes, while Python is what it used to perform any tasks. Because of the use of both these tools, Ansible is &lt;strong&gt;agentless&lt;/strong&gt;, meaning that no additional Ansible-specific software is required to exist on child nodes.&lt;/p&gt;

&lt;h1&gt;
  
  
  Inventory
&lt;/h1&gt;

&lt;p&gt;Ansible isn't magic and doesn't know what its child nodes are until you configure it yourself. The inventory file is what Ansible provides to you to set them. It exists at &lt;code&gt;/etc/ansible/hosts&lt;/code&gt; and accepts either the INI or YAML formats. Here's an example of what one might look like (YAML):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;devgroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s"&gt;10.0.0.133&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s"&gt;10.0.0.209&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s"&gt;10.0.0.103&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;demogroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s"&gt;10.0.0.182&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s"&gt;10.0.0.114&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s"&gt;10.0.0.235&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There is a root level "all" group that can have any number of child groups.  Child groups can also recursively have children and can share nodes. Inventory allows for a high level of control and organization for your infrastructure that most small-scale environments may never need but is available nonetheless.&lt;/p&gt;

&lt;p&gt;When trying to perform any task in Ansible, you will need to provide the group of child nodes you would like to perform it on. It's important to note that if you improperly configure the inventory file, it is difficult to tell since Ansible isn't very straightforward with its error messages about it. Make sure to double-check your formatting after editing!&lt;/p&gt;

&lt;p&gt;For any host listed in your inventory file, Ansible expects that you have already set it up. As I mentioned before, each child of the master must have SSH and Python. Further, the SSH access to the child from the master must be passwordless through a tool such as &lt;code&gt;ssh-copy-id&lt;/code&gt;. If you can manually access the target machine with SSH without a password, so can Ansible.&lt;/p&gt;

&lt;h1&gt;
  
  
  Modules
&lt;/h1&gt;

&lt;p&gt;Ansible is designed to be easy for both beginners and professionals to use, and to accomplish this, the Ansible team created modules. Modules are at the core of Ansible and are the basic building block for any action. They are pre-defined functionality for almost any automation task that you can fathom.  There are modules for networking, cryptography, databases, files, and a ton more. There are many, and it would be more than impractical for me to list them all here. If you want to see a list of all of the modules provided by Ansible, click &lt;a href="https://docs.ansible.com/ansible/latest/modules/modules_by_category.html"&gt;this link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Modules are designed to be &lt;strong&gt;idempotent&lt;/strong&gt; when possible. That means if you run the same module multiple times in a row, the module will only do its job once. For example, if you try to transfer a file that already exists on a target, nothing will happen. This philosophy saves Ansible from being inefficient and allows you to be more liberal in terms of what modules you run. If you want to transfer a file to a group of nodes in which some already contain it, it doesn't hurt to run the module to make sure; Ansible will only perform the task for the nodes that don't.&lt;/p&gt;

&lt;p&gt;For small tasks like sending a file or restarting a service across a group of nodes, it is possible to run modules in isolation. To do this, you can run the &lt;code&gt;ansible&lt;/code&gt; command itself, specifying the inventory group, username on the machines (it must be shared amongst them all), and the module to run. For example, the "Hello World" of Ansible is to ping every child node to ensure the master can contact them with &lt;code&gt;ansible all -u username -m ping&lt;/code&gt;.  In most situations, however, modules need to run in groups.&lt;/p&gt;

&lt;h1&gt;
  
  
  Playbooks
&lt;/h1&gt;

&lt;p&gt;In a typical environment, when multiple modules must run in succession to accomplish a more significant overall task, playbooks can be leveraged. Ansible requires users to write playbooks in YAML, and the file can be stored anywhere.  A playbook must contain the target group from the Ansible inventory file, the username to use for all the machines, and a sequential list of modules to run called the task list. Here's an example playbook to install the "tmux" and "neovim" packages with &lt;code&gt;apt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;demogroup&lt;/span&gt;
  &lt;span class="na"&gt;remote_user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;username&lt;/span&gt;
  &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ensure tmux is installed&lt;/span&gt;
      &lt;span class="na"&gt;apt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tmux&lt;/span&gt;
        &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;present&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ensure neovim is installed&lt;/span&gt;
      &lt;span class="na"&gt;apt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;neovim&lt;/span&gt;
        &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;present&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ansible detects a lot of information about the target nodes, including what operating system they are running, and even what Linux distro it has if it's a Linux machine. Ansible stores these values in variables called "facts" that are available in playbooks. It's possible to use these variables to run tasks on nodes that require different tools selectively. For example, it's possible to use &lt;code&gt;apt&lt;/code&gt; for Debian systems and &lt;code&gt;dnf&lt;/code&gt;/&lt;code&gt;yum&lt;/code&gt; for RedHat systems.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ansible-playbook&lt;/code&gt; command is available to run an Ansible playbook. A playbook is executed by running &lt;code&gt;ansible-playbook X&lt;/code&gt;, where &lt;code&gt;X&lt;/code&gt; is the path of the playbook to run.&lt;/p&gt;

&lt;h1&gt;
  
  
  Roles
&lt;/h1&gt;

&lt;p&gt;Roles are a way to sequentially group a group of tasks that are reusable between multiple playbooks. Take compiling software from scratch, for example.  Software compilation takes several steps. It requires the transfer of many files to the target machine, the installation of several packages, and several other commands to perform their tasks. Multiple, unrelated playbooks may require the compiled software, and re-writing the tasks for each playbook would be inefficient. Instead, the tasks specific to the compilation can be separated and imported by each playbook that requires them.&lt;/p&gt;

&lt;p&gt;Roles require a concrete file structure to work, and they get into advanced Ansible. However, anybody that uses Ansible regularly should also be using roles.&lt;/p&gt;

&lt;h1&gt;
  
  
  Resources
&lt;/h1&gt;

&lt;p&gt;To learn Ansible, I would suggest looking at the &lt;a href="https://docs.ansible.com/"&gt;official documentation&lt;/a&gt;, as it's well-written. The &lt;a href="https://docs.ansible.com/ansible/latest/user_guide/intro_getting_started.html"&gt;"Getting Started" guide&lt;/a&gt; is an excellent place to start. Below are the concepts covered in this post, and the documentation links for them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inventory:&lt;/strong&gt; &lt;a href="https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#intro-inventory"&gt;https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#intro-inventory&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modules:&lt;/strong&gt; &lt;a href="https://docs.ansible.com/ansible/latest/modules/modules_by_category.html"&gt;https://docs.ansible.com/ansible/latest/modules/modules_by_category.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Playbooks:&lt;/strong&gt; &lt;a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks.html#working-with-playbooks"&gt;https://docs.ansible.com/ansible/latest/user_guide/playbooks.html#working-with-playbooks&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Roles:&lt;/strong&gt; &lt;a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html"&gt;https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Practices:&lt;/strong&gt;: &lt;a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html"&gt;https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ansible</category>
      <category>devops</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
