<?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>Forem: Saif Sadiq</title>
    <description>The latest articles on Forem by Saif Sadiq (@saifsadiq1995).</description>
    <link>https://forem.com/saifsadiq1995</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%2F129235%2F4ec9e55b-033c-4466-be87-1381255d25fd.jpg</url>
      <title>Forem: Saif Sadiq</title>
      <link>https://forem.com/saifsadiq1995</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/saifsadiq1995"/>
    <language>en</language>
    <item>
      <title>JavaScript best practices to improve code quality</title>
      <dc:creator>Saif Sadiq</dc:creator>
      <pubDate>Mon, 19 Apr 2021 09:58:30 +0000</pubDate>
      <link>https://forem.com/deepsource/javascript-best-practices-to-improve-code-quality-5d33</link>
      <guid>https://forem.com/deepsource/javascript-best-practices-to-improve-code-quality-5d33</guid>
      <description>&lt;p&gt;If you write JavaScript today, it’s worth your time staying in the know of all the updates the language has seen in the past few years. Since 2015, with the release of ES6, a new version of the ECMAScript spec has been released each year. Each iteration adds new features, new syntax, and Quality of Life improvements to the language. JavaScript engines in most browsers and Node.js quickly catch up, and it’s only fair that your code should catch up as well. That’s because with each new iteration of JavaScript comes new idioms and new ways to express your code, and many a time, these changes may make the code more maintainable for you and your collaborators.&lt;/p&gt;

&lt;p&gt;Here are some of the latest ECMAScript features, and by induction, JavaScript and Node.js that you can make use of to write cleaner, more concise, and more readable code.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Block scored declarations
&lt;/h2&gt;

&lt;p&gt;Since the inception of the language, JavaScript developers have used &lt;code&gt;var&lt;/code&gt; to declare variables. The keyword &lt;code&gt;var&lt;/code&gt; has its quirks, the most problematic of those being the scope of the variables created by using it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="c1"&gt;// inner declaration overrides declaration in parent scope&lt;/span&gt;
 &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// prints 15&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// prints 15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since variables defined with &lt;code&gt;var&lt;/code&gt; are not block-scoped, redefining them in a narrower scope affects the value of the outer scope.&lt;/p&gt;

&lt;p&gt;Now we have two new keywords that replace &lt;code&gt;var&lt;/code&gt;, namely &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; that do not suffer from this drawback.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="c1"&gt;// inner declaration is scoped within the if block&lt;/span&gt;
 &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// prints 15&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// prints 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;const&lt;/code&gt; and &lt;code&gt;let&lt;/code&gt; differ in the semantics that variables declared with &lt;code&gt;const&lt;/code&gt; cannot be reassigned in their scope. This does not mean they are immutable, only that their references cannot be changed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="c1"&gt;// ["Hello", "World!"]&lt;/span&gt;

&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="c1"&gt;// TypeError: Attempted to assign to readonly property.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Arrow functions
&lt;/h2&gt;

&lt;p&gt;Arrow functions are another very important feature introduced recently to JavaScript. They come bearing many advantages. First and foremost, they make the functional aspects of JavaScript beautiful to look at and simpler to write.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// [2, 4, 6, 8]&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&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="c1"&gt;// [2, 4]&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In all of the above examples the arrow functions, named after the distinctive arrow &lt;code&gt;=&amp;gt;&lt;/code&gt;, replace traditional functions with a concise syntax.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If the function body is a single expression, the scope brackets &lt;code&gt;{}&lt;/code&gt; and &lt;code&gt;return&lt;/code&gt; keyword are implied and need not be written.&lt;/li&gt;
&lt;li&gt;If the function has a single argument, the argument parentheses &lt;code&gt;()&lt;/code&gt; are implied and need not be written.&lt;/li&gt;
&lt;li&gt;If the function body expression is a dictionary, it must be enclosed in parentheses &lt;code&gt;()&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Another significant advantage of arrow functions is that they do not define a scope but rather exist within the parent scope. This avoids a lot of pitfalls that can arise with the use of the &lt;code&gt;this&lt;/code&gt; keyword. Arrow functions have no bindings for &lt;code&gt;this&lt;/code&gt;. Inside the arrow function, the value of &lt;code&gt;this&lt;/code&gt; is the same as that in the parent scope. Consequently, arrow functions cannot be used as methods or constructors. Arrow functions don’t work with &lt;code&gt;apply&lt;/code&gt;, &lt;code&gt;bind&lt;/code&gt;, or &lt;code&gt;call&lt;/code&gt; and have no bindings for &lt;code&gt;super&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;They also have certain other limitations such as lack of the &lt;code&gt;arguments&lt;/code&gt; object which traditional functions can access and the inability to &lt;code&gt;yield&lt;/code&gt; from the function body.&lt;/p&gt;

&lt;p&gt;Thus arrow functions are not a 1:1 replacement for standard functions but welcome addition to JavaScript’s feature set.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Optional chaining
&lt;/h2&gt;

&lt;p&gt;Imagine a deeply nested data structure like this &lt;code&gt;person&lt;/code&gt; object here. Consider you wanted to access the first and last name of this person. You would write this in JavaScript like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;last&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="c1"&gt;// 'John'&lt;/span&gt;
&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="c1"&gt;// 'Doe'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine what would happen if the &lt;code&gt;person&lt;/code&gt; object did not contain a nested &lt;code&gt;name&lt;/code&gt; object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="c1"&gt;// TypeError: Cannot read property 'first' of undefined&lt;/span&gt;
&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="c1"&gt;// TypeError: Cannot read property 'last' of undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To avoid such errors, developers had to resort to code like the following, which is unnecessarily verbose, hard to read, and unpleasant to write — a very bad trio of adjectives.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Meet optional chaining, a new feature of JavaScript that does away with this monstrosity. Optional chaining short-circuits the digging process as soon as it encounters a &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt; value and returns &lt;code&gt;undefined&lt;/code&gt; without raising an error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resultant code is much concise and cleaner.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Null-ish coalescing
&lt;/h2&gt;

&lt;p&gt;Before introducing the null-ish coalescing operator, JavaScript developers used the OR operator &lt;code&gt;||&lt;/code&gt; to fall back to a default value if the input was absent. This came with a significant caveat that even legitimate but falsy values would result in a fallback to the defaults.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Missing&lt;/span&gt;&lt;span class="dl"&gt;'&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 'Missing'&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 'Missing'&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 'Missing'&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 'Missing'&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 'Missing'&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 'Missing'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JavaScript has now proposed the null coalescing operator &lt;code&gt;??&lt;/code&gt;, which offers a better alternative in that it only results in a fallback if the preceding expression is null-ish. Here null-ish refers to values that are &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Missing&lt;/span&gt;&lt;span class="dl"&gt;'&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 'Missing'&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 'Missing'&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ''&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, you can ensure that if your program accepts falsy values as legitimate inputs, you won’t end up replacing them with fallbacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Logical assignment
&lt;/h2&gt;

&lt;p&gt;Let’s say you want to assign a value to a variable if and only if the value is currently null-ish. A logical way to write this would be like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you knew about how short-circuiting works, you might want to replace those 3 lines of code with a more succinct version using the null-ish coalescing operator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// x = y if x is nullish, else no effect&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we use the short-circuiting feature of the null-ish coalescing operator to execute the second part &lt;code&gt;x = y&lt;/code&gt; if &lt;code&gt;x&lt;/code&gt; is null-ish. The code is pretty concise, but it still is not very easy to read or understand. The logical null-ish assignment does away with the need for such a workaround.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;??=&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="c1"&gt;// x = y if x is nullish, else no effect&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Along the same lines, JavaScript also introduces logical AND assignment &lt;code&gt;&amp;amp;&amp;amp;=&lt;/code&gt; and logical OR assignment &lt;code&gt;||=&lt;/code&gt; operators. These operators perform assignment only when the specific condition is met and have no effect otherwise.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="c1"&gt;// x = y if x is falsy, else no effect&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;=&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="c1"&gt;// x = y if x is truthy, else no effect&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pro-tip:&lt;/strong&gt; If you’ve written Ruby before, you’ve seen the &lt;code&gt;||=&lt;/code&gt; and &lt;code&gt;&amp;amp;&amp;amp;=&lt;/code&gt; operators, since Ruby does not have the concept of falsy values.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Named capture groups
&lt;/h2&gt;

&lt;p&gt;Let’s start with a quick recap of capture groups in regular expressions. A capture group is a part of the string that matches a portion of regex in parentheses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(\d{4})&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;(\d{2})&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;(\d{2})&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pi day this year falls on 2021-03-14!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// '2020-03-14', the complete match&lt;/span&gt;
&lt;span class="nx"&gt;result&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="c1"&gt;// '2020', the first capture group&lt;/span&gt;
&lt;span class="nx"&gt;result&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="c1"&gt;// '03', the second capture group&lt;/span&gt;
&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// '14', the third capture group&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Regular expressions have also supported named capture groups for quite some time, which is a way for the capture groups to be referenced by a name rather than an index. Now, with ES9, this feature has made its way to JavaScript. Now the result object contains a nested groups object where each capture group’s value is mapped to its name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(?&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;year&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\d{4})&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;(?&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;month&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\d{2})&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;(?&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;day&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\d{2})&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pi day this year falls on 2021-03-14!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt; &lt;span class="c1"&gt;// '2020', the group named 'year'&lt;/span&gt;
&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;month&lt;/span&gt; &lt;span class="c1"&gt;// '03', the group named 'month'&lt;/span&gt;
&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="c1"&gt;// '14', the group named 'day'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new API works beautifully with another new JavaScript feature, de-structured assignments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(?&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;year&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\d{4})&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;(?&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;month&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\d{2})&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;(?&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;day&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\d{2})&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pi day this year falls on 2021-03-14!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;groups&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt; &lt;span class="c1"&gt;// '2020'&lt;/span&gt;
&lt;span class="nx"&gt;month&lt;/span&gt; &lt;span class="c1"&gt;// '03'&lt;/span&gt;
&lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="c1"&gt;// '14'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. &lt;code&gt;async&lt;/code&gt; &amp;amp; &lt;code&gt;await&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;One of the powerful aspects of JavaScript is its asynchronicity. This means that many functions that may be long-running or time-consuming can return a Promise and not block execution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://the-one-api.dev/v2/book&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;prom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;prom&lt;/span&gt; &lt;span class="c1"&gt;// Promise {&amp;lt;pending&amp;gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// wait a bit&lt;/span&gt;
&lt;span class="nx"&gt;prom&lt;/span&gt; &lt;span class="c1"&gt;// Promise {&amp;lt;fullfilled&amp;gt;: Response}, if no errors&lt;/span&gt;
&lt;span class="c1"&gt;// or&lt;/span&gt;
&lt;span class="nx"&gt;prom&lt;/span&gt; &lt;span class="c1"&gt;// Promise {&amp;lt;rejected&amp;gt;: Error message}, if any error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the call to fetch returns a Promise that has the status ‘pending’ when created. Soon, when the API returns the response, it transitions into a ‘fulfilled’ state, and the Response that it wraps can be accessed. In the Promises world, you would do something like this to make an API call and parse the response as JSON.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://the-one-api.dev/v2/book&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;prom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;prom&lt;/span&gt; &lt;span class="c1"&gt;// Promise {&amp;lt;fullfilled&amp;gt;: Response}&lt;/span&gt;
 &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// prints response, if no errors&lt;/span&gt;
 &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// prints error message, if any error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In 2017, JavaScript announced two new keywords &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt;, that make handling and working with Promises easier and more fluent. They are not a replacement for Promises; they are merely syntactic sugar on top of the powerful Promises concepts.&lt;/p&gt;

&lt;p&gt;Instead of all the code happening inside a series of ‘then’ functions, &lt;code&gt;await&lt;/code&gt; makes it all look like synchronous JavaScript. As an added benefit, you can use &lt;code&gt;try...catch&lt;/code&gt; with &lt;code&gt;await&lt;/code&gt; instead of handling errors in ‘catch’ functions as you would have to if consuming Promises directly. The same code with &lt;code&gt;await&lt;/code&gt; would look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://the-one-api.dev/v2/book&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Promise {&amp;lt;fullfilled&amp;gt;: Response} -await-&amp;gt; Response&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// prints response, if no errors&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// prints error message, if any error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;async&lt;/code&gt; keyword is the other side of the same coin, in that it wraps any data to be sent within a Promise. Consider the following asynchronous function for adding several numbers. In the real world, your code would be doing something much more complicated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;agg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;agg&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Promise {&amp;lt;fulfilled&amp;gt;: 6}&lt;/span&gt;
 &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// prints 6&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Promise {&amp;lt;fulfilled&amp;gt;: 6} -await-&amp;gt; 6&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// prints 6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These new features just the tip of the iceberg. We have barely even scratched the surface. JavaScript is constantly evolving, and new features are added to the language every year. It’s tough to keep up with the constant barrage of new features and idioms introduced to the language manually.&lt;/p&gt;

&lt;p&gt;Wouldn’t it be nice if some tool could handle this for us? Fret not, there is. We’ve already talked in detail about &lt;a href="https://deepsource.io/blog/static-analysis-javascript/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=contentdistribution&amp;amp;utm_term=jscodequality" rel="noopener noreferrer"&gt;setting up static code analysis in your JavaScript repo&lt;/a&gt; using ESLint. It’s extremely useful and should be an indispensable tool of your toolchain. But to be honest, setting up ESLint auto-fix pipelines and processes takes time and effort. Unless you enjoy this sort of plumbing, you’d be better off if you wrote the code and outsourced the plumbing to…DeepSource!&lt;/p&gt;

&lt;p&gt;DeepSource can help you with &lt;a href="https://deepsource.io/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=contentdistribution&amp;amp;utm_term=jscodequality" rel="noopener noreferrer"&gt;automating the code reviews&lt;/a&gt; and save you a ton of time. Just add a &lt;code&gt;.deepsource.toml&lt;/code&gt; file in the root of the repository and DeepSource will pick it up for scanning right away. The scan will find scope for improvements across your code and help you fix them with helpful descriptions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://deepsource.io/signup?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=contentdistribution&amp;amp;utm_term=jscodequality" rel="noopener noreferrer"&gt;Sign up&lt;/a&gt; and see for yourself!&lt;/p&gt;

&lt;p&gt;Originally published on &lt;a href="https://deepsource.io/blog/javascript-code-quality-best-practices/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=contentdistribution&amp;amp;utm_term=jscodequality" rel="noopener noreferrer"&gt;DeepSource Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>codequality</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Guidelines for Java code reviews</title>
      <dc:creator>Saif Sadiq</dc:creator>
      <pubDate>Mon, 12 Apr 2021 05:57:10 +0000</pubDate>
      <link>https://forem.com/deepsource/guidelines-for-java-code-reviews-3096</link>
      <guid>https://forem.com/deepsource/guidelines-for-java-code-reviews-3096</guid>
      <description>&lt;p&gt;Having another pair of eyes scan your code is always useful and helps you spot mistakes before you break production. You need not be an expert to review someone’s code. Some experience with the programming language and a review checklist should help you get started. We’ve put together a list of things you should keep in mind when you’re reviewing Java code. Read on!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Follow Java code conventions
&lt;/h2&gt;

&lt;p&gt;Following language conventions helps quickly skim through the code and make sense of it, thereby improving readability. For instance, all package names in Java are written in lowercase, constants in all caps, variable names in CamelCase, etc. Find the complete list of conventions &lt;a href="https://www.oracle.com/technetwork/java/codeconventions-150003.pdf" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some teams develop their own conventions, so be flexible in such cases!&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Replace imperative code with lambdas and streams
&lt;/h2&gt;

&lt;p&gt;If you’re using Java 8+, replacing loops and extremely verbose methods with streams and lambdas makes the code look cleaner. Lambdas and streams allow you to write functional code in Java. The following snippet filters odd numbers in the traditional imperative way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;oddNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&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;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;oddNumbers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the functional way of filtering odd numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;oddNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&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;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;collect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collectors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Beware of the &lt;code&gt;NullPointerException&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;When writing new methods, try to avoid returning nulls if possible. It could lead to null pointer exceptions. In the snippet below, the highest method returns a null if the list has no integers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Items&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Items&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;items&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="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="nf"&gt;highest&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&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="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
      &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;highest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Integer&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;items&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if&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="na"&gt;indexOf&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="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;highest&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="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;highest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;highest&lt;/span&gt; &lt;span class="o"&gt;&amp;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;highest&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="o"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;highest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before directly calling a method on an object I recommend checking for nulls as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Items&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Items&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;emptyList&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="nc"&gt;Integer&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;items&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;highest&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;isEven&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="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// throws NullPointerException ❌&lt;/span&gt;
&lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;isEven&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="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can be pretty cumbersome to have null checks everywhere in your code though. If you are using Java 8+, consider using the &lt;code&gt;Optional&lt;/code&gt; class to represent values that may not have valid states. It allows you to easily define alternate behavior and is useful for chaining methods.&lt;/p&gt;

&lt;p&gt;In the snippet below, we are using Java Stream API to find the highest number with a method which returns an &lt;code&gt;Optional&lt;/code&gt;. Note that we are using &lt;code&gt;Stream.reduce&lt;/code&gt;, which returns an &lt;code&gt;Optional&lt;/code&gt; value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;highest&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reduce&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;integer2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
                            &lt;span class="n"&gt;integer&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;integer2&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;integer2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;Items&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Items&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;emptyList&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="na"&gt;highest&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;ifPresent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;             &lt;span class="c1"&gt;// ✅&lt;/span&gt;
    &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;isEven&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you could also use annotations such as &lt;code&gt;@Nullable&lt;/code&gt; or &lt;code&gt;@NonNull&lt;/code&gt; which will result in warnings if there is a null conflict while building the code. For instance, passing a &lt;code&gt;@Nullable&lt;/code&gt; argument to a method that accepts &lt;code&gt;@NonNull&lt;/code&gt; parameters.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Directly assigning references from client code to a field
&lt;/h2&gt;

&lt;p&gt;References exposed to the client code can be manipulated even if the field is final. Let’s understand this better with an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Items&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;items&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="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above snippet, we directly assign a reference from the client code to a field. The client can easily mutate the contents of the list and manipulate our code as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;span class="nc"&gt;Items&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Items&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// This will change how items behaves as well&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, consider cloning the reference or creating a new reference and then assigning it to the field as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Items&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same rule applies while returning references. You need to be cautious so as not to expose internal mutable state.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Handle exceptions with care
&lt;/h2&gt;

&lt;p&gt;While catching exceptions, if you have multiple catch blocks, ensure that the sequence of catch blocks is most specific to least. In the snippet below, the exception will never be caught in the second block since the &lt;code&gt;Exception&lt;/code&gt; class is the mother of all exceptions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pop&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// handle exception&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StackEmptyException&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// handle exception&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the situation is recoverable and can be handled by the client (the consumer of your library or code) then it is good to use checked exceptions. e. g. &lt;code&gt;IOException&lt;/code&gt; is a checked exception that forces the client to handle the scenario and in case the client chooses to re-throw the exception then it should be a conscious call to disregard the exception.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Ponder over the choice of data structures
&lt;/h2&gt;

&lt;p&gt;Java collections provide &lt;code&gt;ArrayList&lt;/code&gt;, &lt;code&gt;LinkedList&lt;/code&gt;, &lt;code&gt;Vector&lt;/code&gt;, &lt;code&gt;Stack&lt;/code&gt;, &lt;code&gt;HashSet&lt;/code&gt;, &lt;code&gt;HashMap&lt;/code&gt;, &lt;code&gt;Hashtable&lt;/code&gt;. It’s important to understand the pros and cons of each to use them in the correct context. A few hints to help you make the right choice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Map&lt;/code&gt;: Useful if you have unordered items in the form of key, value pairs and require efficient retrieval, insertion, and deletion operations. &lt;code&gt;HashMap&lt;/code&gt;, &lt;code&gt;Hashtable&lt;/code&gt;, &lt;code&gt;LinkedHashMap&lt;/code&gt; are all implementations of the &lt;code&gt;Map&lt;/code&gt; interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;List&lt;/code&gt;: Very commonly used to create an ordered list of items. This list may contain duplicates. &lt;code&gt;ArrayList&lt;/code&gt; is an implementation of the &lt;code&gt;List&lt;/code&gt; interface. A list can be made thread-safe using &lt;code&gt;Collections.synchronizedList&lt;/code&gt; thus removing the need for using &lt;code&gt;Vector&lt;/code&gt;. &lt;a href="https://javaconceptoftheday.com/not-use-vector-class-code/" rel="noopener noreferrer"&gt;Here&lt;/a&gt;’s some more info on why &lt;code&gt;Vector&lt;/code&gt; is essentially obsolete.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Set&lt;/code&gt;: Similar to list but does not allow duplicates. &lt;code&gt;HashSet&lt;/code&gt; implements the &lt;code&gt;Set&lt;/code&gt; interface.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. Think twice before you expose
&lt;/h2&gt;

&lt;p&gt;There are quite a few access modifiers to choose from in Java — &lt;code&gt;public&lt;/code&gt;, &lt;code&gt;protected&lt;/code&gt;, &lt;code&gt;private&lt;/code&gt;. Unless you want to expose a method to the client code, you might want to keep everything &lt;code&gt;private&lt;/code&gt; by default. Once you expose an API, there’s no going back.&lt;/p&gt;

&lt;p&gt;For instance, you have a class &lt;code&gt;Library&lt;/code&gt; that has the following method to checkout a book by name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;bookName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;searchByTitle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;availableBooks&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bookName&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;availableBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;checkedOutBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;searchByTitle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;availableBooks&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;bookName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you do not keep the &lt;code&gt;searchByTitle&lt;/code&gt; method private by default and it ends up being exposed, other classes could start using it and building logic on top of it that you may have wanted to be part of the &lt;code&gt;Library&lt;/code&gt; class. It could break the encapsulation of the &lt;code&gt;Library&lt;/code&gt; class or it may be impossible to revert/modify later without breaking someone else’s code. Expose consciously!&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Code to interfaces
&lt;/h2&gt;

&lt;p&gt;If you have concrete implementations of certain interfaces (e. g. &lt;code&gt;ArrayList&lt;/code&gt; or &lt;code&gt;LinkedList&lt;/code&gt;) and if you use them directly in your code, then it can lead to high coupling. Sticking with the &lt;code&gt;List&lt;/code&gt; interface enables you to switch over the implementation any time in the future without breaking any code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Bill&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Printer&lt;/span&gt; &lt;span class="n"&gt;printer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;printer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Bill&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ConsolePrinter&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Bill&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HTMLPrinter&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above snippet, using the &lt;code&gt;Printer&lt;/code&gt; interface allows the developer to move to another concrete class &lt;code&gt;HTMLPrinter&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Don’t force fit interfaces
&lt;/h2&gt;

&lt;p&gt;Take a look at the following interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;BookService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetchBooks&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;saveBooks&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;books&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderDetails&lt;/span&gt; &lt;span class="n"&gt;orderDetails&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;BookNotFoundException&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BookUnavailableException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;   
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookServiceImpl&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;BookService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Is there a benefit of creating such an interface? Is there a scope for this interface being implemented by another class? Is this interface generic enough to be implemented by another class? If the answer to all these questions is no, then I’d definitely recommend avoiding this unnecessary interface that you’ll have to maintain in the future. Martin Fowler explains this really well in his &lt;a href="https://martinfowler.com/bliki/InterfaceImplementationPair.html" rel="noopener noreferrer"&gt;blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Well then, what’s a good use case for an interface? Let’s say we have a &lt;code&gt;class Rectangle&lt;/code&gt; and a &lt;code&gt;class Circle&lt;/code&gt; that has behavior to calculate perimeter. If there is a requirement, to sum up, the perimeter of all shapes — a use case for polymorphism, then having the interface would make more sense, as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Shape&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="nf"&gt;perimeter&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Rectangle&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Shape&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;//data members and constructors&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="nf"&gt;perimeter&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;breadth&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Circle&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Shape&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;//data members and constructors&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="nf"&gt;perimeter&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;Math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;totalPerimeter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Shape&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;shapes&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;shapes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
               &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;Shape:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;perimeter&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
               &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reduce&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
               &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orElseGet&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  10. Override hashCode when overriding equals
&lt;/h2&gt;

&lt;p&gt;Objects that are equal because of their values are called &lt;a href="https://martinfowler.com/bliki/ValueObject.html" rel="noopener noreferrer"&gt;value objects&lt;/a&gt;. e. g. money, time. Such classes must override the &lt;code&gt;equals&lt;/code&gt; method to return true if the values are the same. The &lt;code&gt;equals&lt;/code&gt; method is usually used by other libraries for comparison and equality checks; hence overriding &lt;code&gt;equals&lt;/code&gt; is necessary. Each Java object also has a hash code value that differentiates it from another object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Coin&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;Coin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;getClass&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClass&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;Coin&lt;/span&gt; &lt;span class="n"&gt;coin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Coin&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;coin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, we have overridden only the &lt;code&gt;equals&lt;/code&gt; method of &lt;code&gt;Object&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Coin&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;coinCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Coin&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="o"&gt;{{&lt;/span&gt;
  &lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Coin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Coin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}};&lt;/span&gt;

&lt;span class="c1"&gt;//update count for 1 rupee coin&lt;/span&gt;
&lt;span class="n"&gt;coinCount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Coin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;coinCount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 3 🤯 why? &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We would expect &lt;code&gt;coinCount&lt;/code&gt; to update the number of 1 rupee coins to 7 since we override equals. But &lt;code&gt;HashMap&lt;/code&gt; internally checks if the hash code for 2 objects is equal and only then proceeds to test equality via the &lt;code&gt;equals&lt;/code&gt; method. Two different objects may or may not have the same hash code but two equal objects must always have the same hash code, as defined by the contract of the &lt;code&gt;hashCode&lt;/code&gt; method. So checking for hash code first is an early exit condition. This implies that both &lt;code&gt;equals&lt;/code&gt; and &lt;code&gt;hashCode&lt;/code&gt; methods must be overridden to express equality.&lt;/p&gt;

&lt;p&gt;If you write or review Java code, DeepSource can help you with &lt;a href="https://deepsource.io/blog/code-review-best-practices/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=contentdistribution&amp;amp;utm_term=javacodereview" rel="noopener noreferrer"&gt;automating the code reviews&lt;/a&gt; and save you a ton of time. Just add a &lt;code&gt;.deepsource.toml&lt;/code&gt; file in the root of the repository and DeepSource will pick it up for scanning right away. The scan will find scope for improvements across your code and help you fix them with helpful descriptions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://deepsource.io/signup/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=contentdistribution&amp;amp;utm_term=javacodereview" rel="noopener noreferrer"&gt;Sign up&lt;/a&gt; and see for yourself!&lt;/p&gt;

</description>
      <category>java</category>
      <category>codereview</category>
      <category>programming</category>
    </item>
    <item>
      <title>Python code review checklist</title>
      <dc:creator>Saif Sadiq</dc:creator>
      <pubDate>Tue, 30 Mar 2021 13:22:22 +0000</pubDate>
      <link>https://forem.com/deepsource/python-code-review-checklist-h30</link>
      <guid>https://forem.com/deepsource/python-code-review-checklist-h30</guid>
      <description>&lt;p&gt;As developers, we are all too familiar with code reviews. Having another pair of eyes take a look at our code can be wonderful; it shows us so many aspects of our code we would not have noticed otherwise. A code review can be informative, and it can be educational. I can confidently attribute most of what I know about good programming practices to code reviews.&lt;/p&gt;

&lt;p&gt;The amount of learning a reviewee takes away from a code review depends on how well the review is performed. It thus falls on the reviewer to make their review count by packing the most lessons into the review as possible.&lt;/p&gt;

&lt;p&gt;This is a guide on some vital aspects of the code you should be checking in your reviews, the expectations you should have from those checks, and some ideas on how tooling (such as linters, formatters, and test suites) can help streamline the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code review checklist
&lt;/h2&gt;

&lt;p&gt;We have formulated this guide in the form of a checklist. It lists a set of questions that you need to ask about the code. If the answer to any of them is not a ‘yes’, you should leave a remark on the PR.&lt;/p&gt;

&lt;p&gt;Do note that this list is only meant to serve as a guideline. Your codebase, like every codebase, has its own specific set of needs, so feel free to build upon this guide and override pieces of it that do not fit well for your use-cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Etiquettes
&lt;/h3&gt;

&lt;p&gt;The first and foremost thing to check during a review is how closely the PR adheres to basic etiquettes. Good PRs are composed of bite-sized changes and solve a single well-defined problem. They should be focused and purposefully narrow to have as few merge conflicts as possible. Put simply, a good PR facilitates being reviewed.&lt;/p&gt;

&lt;p&gt;For large-scale swooping changes, make a separate target branch and then make small incremental PRs to that target, finally merging the target with the main branch. Making one humongous PR makes it harder to review, and if it goes stale, many merge conflicts may pop up.&lt;/p&gt;

&lt;p&gt;When reviewing PRs from new developers, I also make it a point to ensure their commit messages are &lt;a href="https://www.git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines" rel="noopener noreferrer"&gt;well-written&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcig7dwlv1bp2jg6qkop2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcig7dwlv1bp2jg6qkop2.png" alt="Alt Text" width="439" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checklist:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the PR atomic?&lt;/li&gt;
&lt;li&gt;Does the PR follow the single concern principle?&lt;/li&gt;
&lt;li&gt;Are the commit messages well-written?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ideas:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Enforce a commit message format in the team. For example, you could try &lt;a href="https://gitmoji.dev" rel="noopener noreferrer"&gt;gitmoji&lt;/a&gt; wherein you use emoji in commit messages. For example, bugfixes should start with &lt;code&gt;[FIX]&lt;/code&gt;, or the 🐛 emoji and new features should start with &lt;code&gt;[FEAT]&lt;/code&gt; or the ✨ emoji. This makes the intention of the commit very clear.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functionality and syntax
&lt;/h3&gt;

&lt;p&gt;The next thing to check is whether the PR is effective in that it works. Code changed by the PR should work as expected. A bug fix should solve the bug it was supposed to fix. A feature should provide the additional functionality that was required without breaking something else.&lt;/p&gt;

&lt;p&gt;An important thing to keep in mind is that any new feature added by a PR is justified. A simple way to ensure this is to accept only the PRs that are associated with an already triaged issue. This practice minimizes &lt;a href="https://en.wikipedia.org/wiki/Feature_creep" rel="noopener noreferrer"&gt;feature-creep&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checklist:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the PR work?&lt;/li&gt;
&lt;li&gt;Does the new feature add value or is it a sign of feature-creep?&lt;/li&gt;
&lt;li&gt;Does the PR add test-cases for the modified code?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ideas:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Having comprehensive tests in the code makes it easier to check that new functionality works and harder for PRs to break existing stuff. The portion of the code covered should never go down in a PR. Any new code should come with complete coverage in unit/functional tests. Python comes with a robust &lt;a href="https://docs.python.org/3.9/library/unittest.html" rel="noopener noreferrer"&gt;unit testing framework&lt;/a&gt; built into the language itself. You should make use of it in your codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Design
&lt;/h3&gt;

&lt;p&gt;Once we’ve established that the code works, the next step is to check how well it integrates with the existing codebase. One key thing to inspect in this regard is duplication. Often, code added to a repo provides functionality that might already be a part of the code in a different location or something provided by the frameworks or Pip packages in use. This knowledge is something that one can only gain by experience. As a senior, it becomes your duty to point such duplication out to new developers contributing to your repo.&lt;/p&gt;

&lt;p&gt;Attention to paradigms is also essential. Many projects have pre-adopted design paradigms such as microservices, mono repo, or cloud-nativity. Any incoming code should be in line with these paradigms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checklist:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the code properly planned and designed?&lt;/li&gt;
&lt;li&gt;Will the code work well with the existing code and not increase duplication?&lt;/li&gt;
&lt;li&gt;Is the code well organised in terms of placement of components?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Patterns and idioms
&lt;/h3&gt;

&lt;p&gt;Python is a very mature language. It is driven based on certain philosophies, described as &lt;a href="https://www.python.org/dev/peps/pep-0020/" rel="noopener noreferrer"&gt;the Zen of Python&lt;/a&gt;. Those philosophies have given birth to many conventions and idioms that new code is expected to follow.&lt;/p&gt;

&lt;p&gt;The difference between idiomatic and non-idiomatic code is very subtle, and in most cases, can only be intuitively gauged. As with all things honed by experience, intuition must be transferred from experienced people, like yourself, to newbies like your reviewees.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checklist:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the code keep with the idioms and code patterns of the language?&lt;/li&gt;
&lt;li&gt;Does the code make use of the language features and standard libraries?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ideas:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most linters, popularly &lt;a href="https://www.pylint.org" rel="noopener noreferrer"&gt;PyLint&lt;/a&gt;, can help you identify deviations from the style guides and, in most cases, even automatically fix them. Linters work incredibly fast and can make corrections to the code in real-time, making them a valuable addition to your toolchain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Readability
&lt;/h3&gt;

&lt;p&gt;Python is widely regarded as a very readable language. Python’s simplicity of syntax and reduced usage of punctuation contribute heavily to its readability. It only makes sense for code written in the language to be readable as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checklist:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the code clear and concise?&lt;/li&gt;
&lt;li&gt;Does it comply with PEP-8?&lt;/li&gt;
&lt;li&gt;Are all language and project conventions followed?&lt;/li&gt;
&lt;li&gt;Are identifiers given meaningful and style guide-compliant names?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ideas:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A good code formatter like &lt;a href="https://black.readthedocs.io/en/stable/" rel="noopener noreferrer"&gt;Black&lt;/a&gt; can help a lot in formatting the code for consistency and readability. Black also offers minimal customization, which is good because it eliminates all forms of &lt;a href="https://en.wikipedia.org/wiki/Law_of_triviality" rel="noopener noreferrer"&gt;bikeshedding&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We’ve previously talked about &lt;a href="https://deepsource.io/blog/auto-code-formatting-python/?utm_source=devto&amp;amp;utm_term=pythoncodereview&amp;amp;utm_campaign=contentdistribution" rel="noopener noreferrer"&gt;integrating Black into your CI pipeline&lt;/a&gt; can work wonders during a code review.&lt;/p&gt;

&lt;h3&gt;
  
  
  Documentation and maintainability
&lt;/h3&gt;

&lt;p&gt;The next thing to check is the maintainability of the code. Any code added or changed by the PR should be written to facilitate someone other than the original author to maintain it.&lt;/p&gt;

&lt;p&gt;It should preferably be self-documenting, which means written in a way that anyone reading the code may be able to understand what it does. This is one of the hallmarks of good Python code. If the code has to be complex by design, it should be amply documented. In an ideal world, all classes and functions would have Python docstrings, complete with examples.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checklist:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the code self-documenting or well-documented?&lt;/li&gt;
&lt;li&gt;Is the code free of obfuscation and unnecessary complexity?&lt;/li&gt;
&lt;li&gt;Is the control flow and component relationship clear to understand?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ideas:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.sphinx-doc.org/en/master/" rel="noopener noreferrer"&gt;Sphinx&lt;/a&gt; is a documentation generator that exports beautiful documentation from Python docstrings. The exported documentation can then be uploaded to &lt;a href="https://rtfd.io" rel="noopener noreferrer"&gt;ReadTheDocs&lt;/a&gt;, a popular doc-hosting tool. Sphinx is one of the main reasons why I absolutely love writing documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;p&gt;Ensuring that the application remains secure is critical. The next thing to check is if the PR maintains or improves the security of the project. You need to ensure that the changes do not increase the attack surface area or expose vulnerabilities. If the PR adds new dependencies, they could potentially be unsafe, in which case you might need to check the version for known exploits and update the dependencies, if necessary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checklist:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the code free of implementation bugs that could be exploited?&lt;/li&gt;
&lt;li&gt;Have all the new dependencies been audited for vulnerabilities?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ideas:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the renowned security analyzers for Python is &lt;a href="https://github.com/PyCQA/bandit" rel="noopener noreferrer"&gt;Bandit&lt;/a&gt;. Also, if you use GitHub for hosting code, you should absolutely read &lt;a href="https://docs.github.com/en/github/managing-security-vulnerabilities" rel="noopener noreferrer"&gt;this guide&lt;/a&gt; about setting up vulnerability detection and Dependabot for your codebase.&lt;/p&gt;

&lt;p&gt;Once you set up vulnerability detection on GitHub, you’ll get notifications like this…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flx03nhs71gbxp8zyttk1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flx03nhs71gbxp8zyttk1.png" alt="Alt Text" width="800" height="28"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;… with details about the vulnerability and PRs in your repositories that you can merge to patch them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fesrdoe7w1pg9c8i8fc3u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fesrdoe7w1pg9c8i8fc3u.png" alt="Alt Text" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ve also recently talked about &lt;a href="https://deepsource.io/blog/python-security-pitfalls/?utm_source=devto&amp;amp;utm_term=pythoncodereview&amp;amp;utm_campaign=contentdistribution" rel="noopener noreferrer"&gt;common security pitfalls in Python&lt;/a&gt; development and how you can secure your projects against them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance, reliability and scalability
&lt;/h3&gt;

&lt;p&gt;The final things to check are the performance and reliability of the code at scale. While these are undoubtedly key metrics, I put them on the bottom of the checklist because I believe well-planned, well-designed, and well-written code generally works well too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checklist:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the code optimised for in terms of time and space complexity?&lt;/li&gt;
&lt;li&gt;Does it scale as per the need?&lt;/li&gt;
&lt;li&gt;Does it have instrumentation like reporting for metrics and alerting for failures?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ideas:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An excellent way to have add some reliability to Python is to use type hinting and static type checking that can provide hints into possible errors before runtime. Python new &lt;a href="https://www.python.org/dev/peps/pep-0484/" rel="noopener noreferrer"&gt;native support for type-hints&lt;/a&gt; is primarily inspired by the &lt;a href="http://www.mypy-lang.org" rel="noopener noreferrer"&gt;Mypy&lt;/a&gt; syntax, which can be incrementally adopted in existing projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  DeepSource
&lt;/h2&gt;

&lt;p&gt;DeepSource is an automated code review tool that manages the end-to-end code scanning process and automatically makes pull requests with fixes whenever new commits are pushed or new pull requests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://deepsource.io/docs/analyzer/python.html?utm_source=devto&amp;amp;utm_term=pythoncodereview&amp;amp;utm_campaign=contentdistribution" rel="noopener noreferrer"&gt;Setting up DeepSource for Python&lt;/a&gt; is a quick, easy, no-fuss process. Just add a &lt;code&gt;.deepsource.toml&lt;/code&gt; file in the root of the repo, and immediately DeepSource will pick it up for scanning. The scan will find scope for improvements across your codebase, make those improvements, and open pull requests for the changes it finds. I was blown away by the simplicity of the setup and the efficacy of their self-built code engine.&lt;/p&gt;

&lt;p&gt;🙋‍♂️ &lt;strong&gt;Trivia:&lt;/strong&gt; Did you know that DeepSource holds the distinction of being on &lt;a href="https://owasp.org/www-community/Source_Code_Analysis_Tools" rel="noopener noreferrer"&gt;OWASP’s curated list&lt;/a&gt; of source code analysis tools for Python?&lt;/p&gt;

&lt;h2&gt;
  
  
  The ideal code review
&lt;/h2&gt;

&lt;p&gt;Returning to my point about code reviews being educational and informative, I would also like to add that code reviews are time-consuming and resource-intensive. While each review takes time, the more in-depth and comprehensive ones consume even more.&lt;/p&gt;

&lt;p&gt;So each review must be as productive as possible. This is where all the tooling and automation efforts should be directed. By automating whatever can be automated, which is generally the mundane parts of the review, such as code style and formatting, we can allow devs to focus on the important stuff like architecture, design, and scalability.&lt;/p&gt;

&lt;p&gt;I’ll leave you with a profound thought my mentor shared with me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A good code review not only improves the code but the coder as well.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>python</category>
      <category>codereview</category>
      <category>codereviewchecklist</category>
      <category>automatedcodereview</category>
    </item>
    <item>
      <title>Common anti-patterns in Go</title>
      <dc:creator>Saif Sadiq</dc:creator>
      <pubDate>Wed, 24 Mar 2021 06:05:42 +0000</pubDate>
      <link>https://forem.com/deepsource/common-anti-patterns-in-go-fm7</link>
      <guid>https://forem.com/deepsource/common-anti-patterns-in-go-fm7</guid>
      <description>&lt;p&gt;It has been widely acknowledged that coding is an art, and like every artisan who crafts wonderful art and is proud of them, we as developers are also really proud of the code we write. In order to achieve the best results, artists constantly keep searching for ways and tools to improve their craft. Similarly, we as developers keep levelling up our skills and remain curious to know the answer to the single most important question - &lt;strong&gt;“How to write good code”.&lt;/strong&gt; 🤯&lt;/p&gt;

&lt;p&gt;Frederick P. Brooks in his book “ &lt;strong&gt;The Mythical Man Month: Essays on Software Engineering&lt;/strong&gt; ” wrote :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by exertion of the imagination. Few media of creation are so flexible, so easy to polish and rework, so readily capable of realizing grand conceptual structures.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fucarecdn.com%2F76f98acb-ecc5-4701-9a61-409dc9062b4d%2F" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fucarecdn.com%2F76f98acb-ecc5-4701-9a61-409dc9062b4d%2F" alt="how-to-write-good-code.png" width="455" height="695"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Image source: &lt;a href="https://xkcd.com/844/" rel="noopener noreferrer"&gt;https://xkcd.com/844/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post tries to explore answers to the big question mark in the comic above. The simplest way to write good code is to abstain from including &lt;strong&gt;anti-patterns&lt;/strong&gt; in the code we write.😇&lt;/p&gt;

&lt;h2&gt;
  
  
  What are anti-patterns? 🤔
&lt;/h2&gt;

&lt;p&gt;Anti-patterns occur when code is written without taking future considerations into account. Anti-patterns might initially appear to be an appropriate solution to the problem, but, in reality, as the codebase scales, these come out to be obscure and add ‘technical debt’ to our codebase.&lt;/p&gt;

&lt;p&gt;A simple example of an anti-pattern is to write an API without considering how the consumers of the API might use it, as explained in example 1 below. Being aware of anti-patterns and consciously avoid using them while programming is surely a major step towards a more readable and maintainable codebase. In this post, let’s take a look at a few commonly seen anti-patterns in Go.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Returning value of unexported type from an exported function
&lt;/h3&gt;

&lt;p&gt;In Go, to &lt;code&gt;export&lt;/code&gt; any &lt;code&gt;field&lt;/code&gt; or &lt;code&gt;variable&lt;/code&gt; we need to make sure that its name starts with an uppercase letter. The motivation behind exporting them is to make them visible to other packages. For example, if we want to use the &lt;code&gt;Pi&lt;/code&gt; function from &lt;code&gt;math&lt;/code&gt; package, we should address it as &lt;code&gt;math.Pi&lt;/code&gt; . Using &lt;code&gt;math.pi&lt;/code&gt; won’t work and will error out.&lt;/p&gt;

&lt;p&gt;Names (struct fields, functions, variables) that start with a lowercase letter are unexported, and are only visible inside the package they are defined in.&lt;/p&gt;

&lt;p&gt;An exported function or method returning a value of an unexported type may be frustrating to use since callers of that function from other packages will have to define a type again to use it.&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;// Bad practice&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;unexportedType&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ExportedFunc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;unexportedType&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;unexportedType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"some string"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;// Recommended&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ExportedType&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ExportedFunc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;ExportedType&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;ExportedType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"some string"&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;h3&gt;
  
  
  2. Unnecessary use of blank identifier
&lt;/h3&gt;

&lt;p&gt;In various cases, assigning value to a blank identifier is not needed and is unnecessary. In case of using the blank identifier in &lt;code&gt;for&lt;/code&gt; loop, the Go specification mentions :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the last iteration variable is the blank identifier, the range clause is equivalent to the same clause without that identifier.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Bad practice&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;sequence&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;someMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="c"&gt;// Recommended&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;someMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Using loop/multiple &lt;code&gt;append&lt;/code&gt;s to concatenate two slices
&lt;/h3&gt;

&lt;p&gt;When appending multiple slices into one, there is no need to iterate over the slice and append each element one by one. Rather, it is much better and efficient to do that in a single &lt;code&gt;append&lt;/code&gt; statement.&lt;/p&gt;

&lt;p&gt;As an example, the below snippet does concatenation by appending elements one by one through iterating over &lt;code&gt;sliceTwo&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;sliceTwo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;sliceOne&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;sliceOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&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;But, since we know that &lt;code&gt;append&lt;/code&gt; is a &lt;code&gt;variadic&lt;/code&gt; function and thus, it can be invoked with zero or more arguments. Therefore, the above example can be re-written in a much simpler way by using only one &lt;code&gt;append&lt;/code&gt; function call like this:&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="n"&gt;sliceOne&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;sliceOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sliceTwo&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Redundant arguments in &lt;code&gt;make&lt;/code&gt; calls
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;make&lt;/code&gt; function is a special built-in function used to allocate and initialize an object of type map, slice, or chan. For initializing a slice using &lt;code&gt;make&lt;/code&gt;, we have to supply the type of slice, the length of the slice, and the capacity of the slice as arguments. In the case of initializing a &lt;code&gt;map&lt;/code&gt; using &lt;code&gt;make&lt;/code&gt;, we need to pass the size of the &lt;code&gt;map&lt;/code&gt; as an argument.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;make&lt;/code&gt;, however, already has default values for those arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For channels, the buffer capacity defaults to zero (unbuffered).&lt;/li&gt;
&lt;li&gt;For maps, the size allocated defaults to a small starting size.&lt;/li&gt;
&lt;li&gt;For slices, the capacity defaults to the length if capacity is omitted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore,&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="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&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;sl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;int&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="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can be rewritten as:&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="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;int&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, using named constants with channels is not considered as an anti-pattern, for the purposes of debugging, or accommodating math, or platform-specific code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Not an anti-pattern&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Useless &lt;code&gt;return&lt;/code&gt; in functions
&lt;/h3&gt;

&lt;p&gt;It is not considered good practice to put a &lt;code&gt;return&lt;/code&gt; statement as the final statement in functions that do not have a value to return.&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;// Useless return, not recommended&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;alwaysPrintFoofoo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foofoo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;// Recommended&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;alwaysPrintFoo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foofoo"&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;Named returns should not be confused with useless returns, however. The return statement below really returns a value.&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;printAndReturnFoofoo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foofoo&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;foofoo&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"foofoo"&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;foofoo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Useless &lt;code&gt;break&lt;/code&gt; statements in &lt;code&gt;switch&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In Go, &lt;code&gt;switch&lt;/code&gt; statements do not have automatic &lt;code&gt;fallthrough&lt;/code&gt;. In programming languages like C, the execution falls into the next case if the previous case lacks the &lt;code&gt;break&lt;/code&gt; statement. But, it is commonly found that &lt;code&gt;fallthrough&lt;/code&gt; in &lt;code&gt;switch&lt;/code&gt;-case is used very rarely and mostly causes bugs. Thus, many modern programming languages, including Go, changed this logic to never &lt;code&gt;fallthrough&lt;/code&gt; the cases by default.&lt;/p&gt;

&lt;p&gt;Therefore, it is not required to have a &lt;code&gt;break&lt;/code&gt; statement as the final statement in a case block of &lt;code&gt;switch&lt;/code&gt; statements. Both the examples below act the same.&lt;/p&gt;

&lt;p&gt;Bad pattern:&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;switch&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"case one"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"case two"&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;Good pattern:&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;switch&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"case one"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"case two"&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;However, for implementing &lt;code&gt;fallthrough&lt;/code&gt; in &lt;code&gt;switch&lt;/code&gt; statements in Go, we can use the &lt;code&gt;fallthrough&lt;/code&gt; statement. As an example, the code snippet given below will print &lt;code&gt;23&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&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;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;fallthrough&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&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;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;fallthrough&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&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;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"3"&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;h3&gt;
  
  
  7. Not using helper functions for common tasks
&lt;/h3&gt;

&lt;p&gt;Certain functions, for a particular set of arguments, have shorthands that can be used instead to improve efficiency and better understanding/readability.&lt;/p&gt;

&lt;p&gt;For example, in Go, to wait for multiple goroutines to finish, we can use a &lt;code&gt;sync.WaitGroup&lt;/code&gt;. Instead of incrementing a &lt;code&gt;sync.WaitGroup&lt;/code&gt; counter by &lt;code&gt;1&lt;/code&gt; and then adding &lt;code&gt;-1&lt;/code&gt; to it in order to bring the value of the counter to &lt;code&gt;0&lt;/code&gt; and in order to signify that all the goroutines have been executed :&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="n"&gt;wg&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="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// ...some code&lt;/span&gt;
&lt;span class="n"&gt;wg&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="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is easier and more understandable to use &lt;code&gt;wg.Done()&lt;/code&gt; helper function which itself notifies the &lt;code&gt;sync.WaitGroup&lt;/code&gt; about the completion of all goroutines without our need to manually bring the counter to &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;wg&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="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// ...some code&lt;/span&gt;
&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  8. Redundant &lt;code&gt;nil&lt;/code&gt; checks on slices
&lt;/h3&gt;

&lt;p&gt;The length of a &lt;code&gt;nil&lt;/code&gt; slice evaluates to zero. Hence, there is no need to check whether a slice is &lt;code&gt;nil&lt;/code&gt; or not, before calculating its length.&lt;/p&gt;

&lt;p&gt;For example, the &lt;code&gt;nil&lt;/code&gt; check below is not necessary.&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;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;x&lt;/span&gt;&lt;span class="p"&gt;)&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="c"&gt;// do something&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code could omit the &lt;code&gt;nil&lt;/code&gt; check as shown below:&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;if&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;x&lt;/span&gt;&lt;span class="p"&gt;)&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="c"&gt;// do something&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9. Too complex function literals
&lt;/h3&gt;

&lt;p&gt;Function literals that only call a single function can be removed without making any other changes to the value of the inner function, as they are redundant. Instead, the inner function that is being called inside the outer function should be called.&lt;/p&gt;

&lt;p&gt;For example:&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="n"&gt;fn&lt;/span&gt; &lt;span class="o"&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;x&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&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;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&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;Can be simplified as:&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Using &lt;code&gt;select&lt;/code&gt; statement with a single case
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;select&lt;/code&gt; statement lets a goroutine wait on multiple communication operations. But, if there is only a single operation/case, we don’t actually require &lt;code&gt;select&lt;/code&gt; statement for that. A simple &lt;code&gt;send&lt;/code&gt; or &lt;code&gt;receive&lt;/code&gt; operation will help in that case. If we intend to handle the case to try a send or receive without blocking, it is recommended to add a &lt;code&gt;default&lt;/code&gt; case to make the &lt;code&gt;select&lt;/code&gt; statement non-blocking.&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;// Bad pattern&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="o"&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;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;// Recommended&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&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;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;default&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="o"&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;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"default"&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;h3&gt;
  
  
  11. context.Context should be the first param of the function
&lt;/h3&gt;

&lt;p&gt;The context.Context should be the first parameter, typically named ctx. ctx should be a (very) common argument for many functions in a Go code, and since it’s logically better to put the common arguments at the first or the last of the arguments list. Why? It helps us to remember to include that argument due to a uniform pattern of its usage. In Go, as the variadic variables may only be the last in the list of arguments, it is hence advised to keep context.Context as the first parameter. Various projects like even Node.js have some conventions like error first callback. Thus, it’s a convention that context.Context should always be the first parameter of a function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Bad practice&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;badPatternFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="n"&gt;favContextKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="c"&gt;// do something&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Recommended&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;goodPatternFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="n"&gt;favContextKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;    
    &lt;span class="c"&gt;// do something&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it comes to working in a team, reviewing other people’s code becomes important. DeepSource is an automated code review tool that manages the end-to-end code scanning process and automatically makes pull requests with fixes whenever new commits are pushed or new pull requests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://deepsource.io/docs/analyzer/go.html" rel="noopener noreferrer"&gt;Setting up DeepSource&lt;/a&gt; for Go is extremely easy. As soon as you have it set up, an initial scan will be performed on your entire codebase, find scope for improvements, fix them, and open pull requests for those changes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;go build&lt;/code&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Breaking builds, baseball bats, and the code quality DNA</title>
      <dc:creator>Saif Sadiq</dc:creator>
      <pubDate>Mon, 15 Mar 2021 13:07:43 +0000</pubDate>
      <link>https://forem.com/deepsource/breaking-builds-baseball-bats-and-the-code-quality-dna-278n</link>
      <guid>https://forem.com/deepsource/breaking-builds-baseball-bats-and-the-code-quality-dna-278n</guid>
      <description>&lt;p&gt;“What’s the biggest set of items in terms of tech debt. I can attack it, scope it into the code quality sprints and then start incrementally evolving” - Badri elaborated.&lt;/p&gt;

&lt;p&gt;In Good Code Podcast, we talk to experienced developers and technical leaders about the art and science of writing good code and building software. In episode 5, we talk to Badri Rajasekar, who has spent almost 20 years building software and is currently the founder and CEO of &lt;a href="https://jamm.app/en/download/" rel="noopener noreferrer"&gt;Jamm&lt;/a&gt; - a rapidly growing video collaboration app.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Microsoft executive who alarmed everyone with a baseball bat
&lt;/h3&gt;

&lt;p&gt;While speaking about code quality and code review processes, Badri shared an incident from his initial days at Microsoft, when somebody broke the Windows Build and had hundreds of developers waiting for it to get fixed. Soon enough, a Microsoft executive stormed into the office with a baseball bat shouting “Who broke the build?”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu1nyzq4vj6inj7459d37.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu1nyzq4vj6inj7459d37.gif" alt="Alt Text" width="1024" height="1024"&gt;&lt;/a&gt;&lt;br&gt;
With this hilarious (not at the time 😅) incident, Badri expounded on how code quality reviews have evolved over the past decade. Earlier, with strongly typed languages and no automation in place, errors could easily become blunders. Today, with the introduction of automated code reviews, various tooling, microservices, the concept of nightlies, and continuous integrations, there’s much more tolerance for both errors and blunders.&lt;/p&gt;

&lt;p&gt;Quick Read: &lt;a href="https://deepsource.io/blog/code-review-best-practices/?utm_source=devto&amp;amp;utm_term=talkwithbadri&amp;amp;utm_campaign=contentdistribution" rel="noopener noreferrer"&gt;Code Review Best Practices&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The flip side:&lt;/strong&gt; With the flexibility that these modern processes offer, it becomes even more critical to be careful in order to ensure code quality at every step of the way.&lt;/p&gt;

&lt;p&gt;In Badri’s words:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It’s just as possible for organizations in this era of continuous delivery to ship a lot of buggy code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The takeaway:&lt;/strong&gt; It’s extremely important to be structured around automation testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Slow down today and move 10X faster tomorrow onwards
&lt;/h3&gt;

&lt;p&gt;While talking about how inexperienced developers or new startups that don’t bother about integration testing for the sake of quick deployments, end up accumulating a lot of tech debt before they realize it, Badri shared another example of a rapidly growing startup that couldn’t slow down, hence making the problem worse for itself every day.&lt;/p&gt;

&lt;p&gt;Badri’s advice for situations like this - get as organized as possible, and try to not fix everything in one shot.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Have a strong process around all of your basic unit tests. Integration tests have to pass before a pull request gets merged in. Eg. Don’t submit a PR until the integration tests have passed. Be firm - either the tests have to pass or if they’re not passing, you’ve got to fix the test.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The key is to introduce code quality into the DNA of the company and encourage everyone on the team to think of it as an integral part of the process, and not rely on QA teams or site reliability engineers. Badri also shared his insights on how to do this — introducing quality sprints, having regular performance checks, taking care of the meta-questions, and maintaining documentation.&lt;/p&gt;

&lt;p&gt;He spoke about his time at TokBox and how they used to manage the code quality. They used to have a unified framework for instrumenting everything from platform health to analytics. They also made it fun by introducing the “Load Time Lama” - a fanciful creature who encouraged everyone to take care of the loading times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; Avoid premature optimization of architecture, as you’ll miss out on crucial problems that haven’t cropped up since you haven’t seen scale yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  The similarity between pilots and programmers
&lt;/h3&gt;

&lt;p&gt;Badri drew an analogy between pilots and programmers while explaining how to steer through massive amounts of data. When flying an airplane, a pilot majorly looks at a couple of indicators — the airspeed indicator, altimeter, heading indicator, etc. And when one of such indicators indicates a warning, only then he delves deeper into the issues.&lt;/p&gt;

&lt;p&gt;Similarly, while having analytics and continuous testing are critical, developers should not get lost in the data that accumulates over time. The way out is to simply stick to the basics. Have a “four-metric dashboard” that defines the code quality benchmarks for a team.&lt;/p&gt;

&lt;p&gt;At the same time, practicing causality where you reverse engineer the issues, rather than looking at a sea of graphs, makes it easier to figure out causal patterns.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5ytqicea6hpacojjw88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5ytqicea6hpacojjw88.png" alt="Alt Text" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The conversation wrapped up with golden advice:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Golden Advice: Keep your architecture simple!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Badri advocated the KISS (keep it simple silly) principle when it comes to architectures. This improves scalability and helps with faster resolution of unforeseen problems, because these are easy to reason about.&lt;/p&gt;

&lt;p&gt;After a lot of anecdotes, jokes, advisements, and laughter, the chat concluded.&lt;/p&gt;

&lt;p&gt;Interested in listening to the entire conversation?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Listen to the podcast &lt;a href="https://open.spotify.com/episode/1wrB1CljTNfBl2tiv9HoMn" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stay tuned for the next episode of the Good Code Podcast!&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>codereview</category>
      <category>technicaldebt</category>
      <category>automatedcodereview</category>
    </item>
    <item>
      <title>Automated Code Review Tools for Developers in 2021</title>
      <dc:creator>Saif Sadiq</dc:creator>
      <pubDate>Mon, 08 Mar 2021 13:02:30 +0000</pubDate>
      <link>https://forem.com/saifsadiq1995/automated-code-review-tools-for-developers-in-2021-1b78</link>
      <guid>https://forem.com/saifsadiq1995/automated-code-review-tools-for-developers-in-2021-1b78</guid>
      <description>&lt;p&gt;Code review is a technique that can improve the quality of a codebase by having multiple developers look for bugs and other problems before passing them on to others. Manual code reviews are costly and time-consuming, which is why many development teams use automated tools to do this work.&lt;/p&gt;

&lt;p&gt;Automated code review tools can help you automate the process, improve your code quality, and save valuable developer time. Developers want to focus on building their applications instead of reviewing other people’s code. Automated code review tools have been around for a while, but they’ve been evolving and getting better. They are now more efficient, accurate, and customizable than ever before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Automated Code Review Tools?
&lt;/h2&gt;

&lt;p&gt;Automated code review tools have been around for a while as static analysis and unit testing frameworks. However, as business needs require speed and agility, it’s necessary to &lt;a href="https://deepsource.io/blog/code-review-best-practices/?utm_source=dzone&amp;amp;utm_medium=automatedcodereviewtools&amp;amp;utm_campaign=organic" rel="noopener noreferrer"&gt;automate code review&lt;/a&gt;. It can lead to faster feedback, better code quality, and time to production.&lt;/p&gt;

&lt;p&gt;This blog will explore the top automated code review tools in 2021 and help you choose which one is best for your needs by looking at the pros and cons of each.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;CodeBeat&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://codebeat.co/" rel="noopener noreferrer"&gt;CodeBeat&lt;/a&gt; is a popular code review tool that provides automated code review and feedback. It displays a code grade on a &lt;strong&gt;‘4.0 scale’&lt;/strong&gt; system where the code gets reviewed on a scale of 1 to 4. CodeBeat supports various languages like Python, Ruby, Java, Javascript, Golang, Swift, and more.&lt;/p&gt;

&lt;p&gt;CodeBeat offers a &lt;a href="https://hub.codebeat.co/docs/how-is-codebeat-different" rel="noopener noreferrer"&gt;team management tool&lt;/a&gt; that makes it easy to analyze the code and move developers within a team while maintaining consistency. Integrating with many popular toolings like Github, Gitlab, Bitbucket, Slack, and Hipchat, developers and software teams use CodeBeat at scale.&lt;/p&gt;

&lt;p&gt;Some of the highlights of CodeBeat includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provides an integrated dashboard with project reviews&lt;/li&gt;
&lt;li&gt;Issues grouped into categories like complexity, code issues, and duplication&lt;/li&gt;
&lt;li&gt;Provides E-Mail updates for project and pull request quality continuously&lt;/li&gt;
&lt;li&gt;Provides immediate feedback to improve the codebase quality through “quick wins”&lt;/li&gt;
&lt;li&gt;Easy to integrate and use with minimal setup required&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of the drawbacks of CodeBeat are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lack of security analysis.&lt;/li&gt;
&lt;li&gt;Lack of support for open-source tools and linters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CodeBeat is entirely free for open-source, with enterprise support offered for large teams. CodeBeat provides a great degree of analysis for identifying cyclomatic complexity, thus identifying duplicated code.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;DeepSource&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://deepsource.io?utm_source=dzone&amp;amp;utm_medium=automatedcodereviewtools&amp;amp;utm_campaign=organic" rel="noopener noreferrer"&gt;DeepSource&lt;/a&gt; is an automated code review tool that provides automated code analysis against various popular general-purpose programming languages. DeepSource supports languages like Python, Javascript, Golang, Ruby, and Java. With its &lt;a href="https://deepsource.io/features/?utm_source=dzone&amp;amp;utm_medium=automatedcodereviewtools&amp;amp;utm_campaign=organic" rel="noopener noreferrer"&gt;single-file configuration&lt;/a&gt;, DeepSource makes continuous analysis easy with every commit and pull request.&lt;/p&gt;

&lt;p&gt;The code quality measures check for performance issues, type check issues, style issues, documentation issues, bug risks, and anti-patterns. It allows us to define clear and realistic goals for developers and maintainers to manage their codebases and make code review easier.&lt;/p&gt;

&lt;p&gt;Some of the highlights of DeepSource includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single-File Configuration for automated code analysis&lt;/li&gt;
&lt;li&gt;Integrates with continuous integration pipelines like Travis CI and Circle CI&lt;/li&gt;
&lt;li&gt;Supports code formatters like &lt;strong&gt;black, rubocop,&lt;/strong&gt; and &lt;strong&gt;gofmt&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Provides auto-fix for common issues across the codebase&lt;/li&gt;
&lt;li&gt;Provides analysis for every issue and pull request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of the drawbacks of DeepSource are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lack of support for PHP, C++, and Rust&lt;/li&gt;
&lt;li&gt;Lack of support for Azure DevOps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DeepSource is entirely free for open-source projects, with enterprise support for large teams. DeepSource analyzers work at file-level and repository-level and provide a low positive rate in comparison to other analyzers and code review tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;CodeClimate&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://codeclimate.com/" rel="noopener noreferrer"&gt;CodeClimate&lt;/a&gt; is a code review tool that aims to improve team productivity by bringing commit-to-deploy visibility. It aims to ease up continuous delivery with &lt;strong&gt;&lt;a href="https://codeclimate.com/velocity/trends" rel="noopener noreferrer"&gt;“&lt;/a&gt;&lt;/strong&gt;&lt;a href="https://codeclimate.com/velocity/trends" rel="noopener noreferrer"&gt;Velocity&lt;/a&gt;&lt;strong&gt;&lt;a href="https://codeclimate.com/velocity/trends" rel="noopener noreferrer"&gt;”&lt;/a&gt;&lt;/strong&gt;, which provides Engineering Intelligence, while &lt;strong&gt;&lt;a href="https://codeclimate.com/quality/" rel="noopener noreferrer"&gt;“&lt;/a&gt;&lt;/strong&gt;&lt;a href="https://codeclimate.com/quality/" rel="noopener noreferrer"&gt;Quality&lt;/a&gt;&lt;strong&gt;&lt;a href="https://codeclimate.com/quality/" rel="noopener noreferrer"&gt;”&lt;/a&gt;&lt;/strong&gt; provides automated code review on every commit and pull request.&lt;/p&gt;

&lt;p&gt;CodeClimate provides a maintainability score on a scale from A to F depending on various parameters, including code duplications, code smells, and more. It allows us to identify bottlenecks and provides trends like the change in test coverage or technical debt.&lt;/p&gt;

&lt;p&gt;Some of the highlights of CodeClimate includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy installation with automated Git updates.&lt;/li&gt;
&lt;li&gt;Identifies hotspots in the codebase to identify portions that need a refactor.&lt;/li&gt;
&lt;li&gt;Provides a security dashboard to identify application vulnerabilities.&lt;/li&gt;
&lt;li&gt;Provides an API to be used locally for automated code reviews.&lt;/li&gt;
&lt;li&gt;Provides alerts and instance notifications over Mail and RSS feeds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of the drawbacks of CodeClimate are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lack of issue description and search/filtering.&lt;/li&gt;
&lt;li&gt;Lack of customization capabilities and high pricing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CodeClimate suffers from a high rate and does not provide rules for identifying core complexities like file length and cognitive complexity. CodeClimate also integrates with Integrated Development Environments (IDE) like VS Code and Atom. It also features a library called &lt;a href="https://docs.codeclimate.com/docs/configuring-test-coverage" rel="noopener noreferrer"&gt;“cc-test-reporter”&lt;/a&gt; to test the coverage.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Codacy&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.codacy.com/" rel="noopener noreferrer"&gt;Codacy&lt;/a&gt; is one of the most popular automated code review tools used by individual developers and software development teams alike. Codacy supports various general-purpose programming languages like Python, Java, Javascript, C/C++, Ruby, Golang, and more.&lt;/p&gt;

&lt;p&gt;Codacy covers code complexity, error-prone, security, code style, compatibility, documentation, and performance issues.&lt;/p&gt;

&lt;p&gt;Some of the highlights of Codacy includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automated code reviews with minimal installation&lt;/li&gt;
&lt;li&gt;Integration with various services including GitHub, GitLab, GitHub Actions, CircleCI&lt;/li&gt;
&lt;li&gt;Help define particular goals for the Project and provides a recommendation to fulfill them&lt;/li&gt;
&lt;li&gt;Analyzes pull requests and commit individually&lt;/li&gt;
&lt;li&gt;Only new issues are taken into account to prevent noise and duplication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of the drawbacks of Codacy are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lack of issue search apart from a few filters&lt;/li&gt;
&lt;li&gt;Lacks support for exporting code patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Codacy provides an easy-to-use and intuitive user interface that can help developers to manage their code fluidly. It allows the developers to keep the code quality intact and the code review clean.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Veracode&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.veracode.com/" rel="noopener noreferrer"&gt;Veracode&lt;/a&gt; is an automated code review tool for code review, automated testing, and improving codebase efficiency. Supporting various general-purpose programming languages like Python, Java, Javascript, Golang, and more, Veracode provides two code review tools: &lt;a href="https://www.veracode.com/products/binary-static-analysis-sast" rel="noopener noreferrer"&gt;static analysis&lt;/a&gt; and &lt;a href="https://www.veracode.com/products/software-composition-analysis" rel="noopener noreferrer"&gt;software composition analysis&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The static analysis tool leverages static analysis, where developers can find bugs and anti-patterns and fix them before they land into production. The Software Composition Analysis allows identifying vulnerabilities while using third-party packages in the codebase.&lt;/p&gt;

&lt;p&gt;Some of the highlights of Veracode includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy to configure and quick to use.&lt;/li&gt;
&lt;li&gt;Provides binary scanning to have less false positives in the code.&lt;/li&gt;
&lt;li&gt;Pin-points to real vulnerabilities in the code and recommends solutions.&lt;/li&gt;
&lt;li&gt;Intuitive and friendly User-Interface with custom dashboards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of the drawbacks of Veracode are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lack of customization for analysis rules&lt;/li&gt;
&lt;li&gt;Lack of a well-defined user experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Veracode’s code analysis platform enables developers to review, analyze, and remediate code to find security vulnerabilities. Veracode also provides SDLC integration, which helps developers verify compliance with the OWASP Top 10 and other best practices.&lt;/p&gt;

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

&lt;p&gt;Automated code review tools are a boon for developers. There’s no shortage of options available, and this article explored 5 tools, each with its advantages and disadvantages. &lt;/p&gt;

</description>
      <category>codereview</category>
      <category>codequality</category>
    </item>
    <item>
      <title>5 Common mistakes in Go</title>
      <dc:creator>Saif Sadiq</dc:creator>
      <pubDate>Mon, 08 Mar 2021 06:49:22 +0000</pubDate>
      <link>https://forem.com/deepsource/5-common-mistakes-in-go-3e37</link>
      <guid>https://forem.com/deepsource/5-common-mistakes-in-go-3e37</guid>
      <description>&lt;p&gt;Bug-risks are issues in code that can cause errors and breakages in production. A bug is a flaw in the code that produces undesired or incorrect results. Code often has bug-risks due to poor coding practices, lack of version control, miscommunication of requirements, unrealistic time schedules for development, and buggy third-party tools. In this post, let’s take a look at a few commonly seen bug-risks in Go.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Infinite recursive call
&lt;/h3&gt;

&lt;p&gt;A function that calls itself recursively needs to have an exit condition. Otherwise, it will recurse forever until the system runs out of memory.&lt;/p&gt;

&lt;p&gt;This issue can be caused by common mistakes such as forgetting to add an exit condition. It can also happen “on purpose.” Some languages have tail-call optimization, which makes certain infinite recursive calls safe to use. Tail-call optimization allows you to avoid allocating a new stack frame for a function because the calling function will return the value that it gets from the called function. The most common use is tail-recursion, where a recursive function written to take advantage of tail-call optimization can use constant stack space. Go, however, does not implement tail-call optimization, and you will eventually run out of memory. However, this problem doesn’t apply to spawning new goroutines.&lt;/p&gt;

&lt;p&gt;Recommended reading: &lt;a href="https://dave.cheney.net/2013/06/02/why-is-a-goroutines-stack-infinite" rel="noopener noreferrer"&gt;Why is a Goroutine’s stack infinite ?&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Assignment to &lt;code&gt;nil&lt;/code&gt; map
&lt;/h3&gt;

&lt;p&gt;A map needs to be initialized using the &lt;code&gt;make&lt;/code&gt; function (or a &lt;code&gt;map&lt;/code&gt; literal) before you can add any elements. A new, empty map value is made using the built-in function &lt;code&gt;make&lt;/code&gt;, which takes the &lt;code&gt;map&lt;/code&gt; type and an optional capacity hint as arguments:&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="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The initial capacity does not bound its size: maps grow to accommodate the number of items stored in them, with the exception of &lt;code&gt;nil&lt;/code&gt; maps. A &lt;code&gt;nil&lt;/code&gt; map is equivalent to an empty map except that no elements may be added.&lt;/p&gt;

&lt;p&gt;Bad pattern:&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;var&lt;/span&gt; &lt;span class="n"&gt;countedData&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;][]&lt;/span&gt;&lt;span class="n"&gt;ChartElement&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good pattern:&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="n"&gt;countedData&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;][]&lt;/span&gt;&lt;span class="n"&gt;ChartElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recommended reading: &lt;a href="https://stackoverflow.com/questions/35379378/go-assignment-to-entry-in-nil-map?rq=1" rel="noopener noreferrer"&gt;Go: assignment to entry in nil map&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Method modifies receiver
&lt;/h3&gt;

&lt;p&gt;A method that modifies a non-pointer receiver value may have unwanted consequences. This is a bug risk because the method may change the value of the receiver inside the method, but it won’t reflect in the original value. To propagate the change, the receiver must be a pointer.&lt;/p&gt;

&lt;p&gt;For example:&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;data&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;num&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;bool&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;d&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;vmethod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;8&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;d&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vmethod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%+v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Output: {num:1 key:0xc0000961e0 items:map[1:true]}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;num&lt;/code&gt; must be modified:&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;data&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;num&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;bool&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;d&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;vmethod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;8&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;d&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vmethod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%+v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Output: &amp;amp;{num:8 key:0xc00010a040 items:map[1:true]}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Possibly undesired value being used in goroutine
&lt;/h3&gt;

&lt;p&gt;Range variables in a loop are reused at each iteration; therefore, a goroutine created in a loop will point to the range variable from the upper scope. This way, the goroutine could use the variable with an undesired value.&lt;/p&gt;

&lt;p&gt;In the example below, the value of index and value used in the goroutine are from the outer scope. Because the goroutines run asynchronously, the value of index and value could be (and usually are) different from the intended value.&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="n"&gt;mySlice&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;mySlice&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Index: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Value: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To overcome this problem, a local scope must be created, like in the example below.&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="n"&gt;mySlice&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;mySlice&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Index: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Value: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another way to handle this could be by passing the values as args to the goroutines.&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="n"&gt;mySlice&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;mySlice&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;go&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;index&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Index: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Value: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&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;Recommended reading: &lt;a href="https://golang.org/doc/faq#closures_and_goroutines" rel="noopener noreferrer"&gt;What happens with closures running as goroutines?&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Deferring &lt;code&gt;Close&lt;/code&gt; before checking for a possible error
&lt;/h3&gt;

&lt;p&gt;It’s a common pattern amongst Go developers, to &lt;code&gt;defer&lt;/code&gt; the &lt;code&gt;Close()&lt;/code&gt; method for a value that implements the &lt;code&gt;io.Closer&lt;/code&gt; interface. For example, when opening a file:&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="n"&gt;f&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;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tmp/file.md"&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;f&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this pattern is harmful for writable files because deferring a function call ignores its return value, and the &lt;code&gt;Close()&lt;/code&gt; method can return errors. For instance, if you wrote data to the file, it might have been cached in memory and not flushed to disk by the time you called &lt;code&gt;Close&lt;/code&gt;. This error should be explicitly handled.&lt;/p&gt;

&lt;p&gt;While you could go ahead without using &lt;code&gt;defer&lt;/code&gt; at all, you would need to remember to close the file everytime their job is done. A better way would be to &lt;code&gt;defer&lt;/code&gt; a wrapper function, like in the example below.&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="n"&gt;f&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;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tmp/file.md"&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;closeErr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;f&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;closeErr&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="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;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;closeErr&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;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error occured while closing the file :"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;closeErr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recommended reading: &lt;a href="https://www.joeshaw.org/dont-defer-close-on-writable-files/" rel="noopener noreferrer"&gt;Do not defer Close() on writable files&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When it comes to working in a team, reviewing other people’s code becomes important. &lt;a href="https://deepsource.io/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=contentdistribution&amp;amp;utm_term=gobugrisks" rel="noopener noreferrer"&gt;DeepSource&lt;/a&gt; is an &lt;a href="https://dzone.com/articles/automated-code-review-tools-for-developers-in-2021" rel="noopener noreferrer"&gt;automated code review tool&lt;/a&gt; that manages the end-to-end code scanning process and automatically makes pull requests with fixes whenever new commits are pushed or new pull requests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://deepsource.io/docs/analyzer/go.html?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=contentdistribution&amp;amp;utm_term=gobugrisks" rel="noopener noreferrer"&gt;Setting up DeepSource for Go&lt;/a&gt; is extremely easy. As soon as you have it set up, an initial scan will be performed on your entire codebase, find scope for improvements, fix them, and open PRs for those changes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;go build&lt;/code&gt;!&lt;/p&gt;

</description>
      <category>go</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Leveraging static code analysis in a Ruby CI pipeline</title>
      <dc:creator>Saif Sadiq</dc:creator>
      <pubDate>Tue, 02 Mar 2021 17:18:06 +0000</pubDate>
      <link>https://forem.com/deepsource/leveraging-static-code-analysis-in-a-ruby-ci-pipeline-31g3</link>
      <guid>https://forem.com/deepsource/leveraging-static-code-analysis-in-a-ruby-ci-pipeline-31g3</guid>
      <description>&lt;p&gt;Continuous integration, or CI, refers to the culture and the technologies that enable continuously merging features and bug fixes into the main branch of the codebase. Code changes are incorporated immediately after testing, rather than being bunched with other updates in a &lt;em&gt;waterfall&lt;/em&gt; release process.&lt;/p&gt;

&lt;p&gt;Similarly, continuous delivery, or CD, refers to automatically deploying the changed code to the target environment, such as pre-production branches to staging and master to production. CD picks up where CI left off, and as such, they often go hand in hand.&lt;/p&gt;

&lt;p&gt;Static code analysis typically falls under the CI aspect of a CI/CD pipeline. Taking the example of a small Ruby project, we’ll be setting up a CI workflow to analyze code quality using static analysis in the following areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistency, with the widely adopted &lt;a href="https://rubystyle.guide" rel="noopener noreferrer"&gt;Ruby style guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Layout, such as unjust spacing or misaligned indentation.&lt;/li&gt;
&lt;li&gt;Linting, such as inadequate permissions or redundant operations.&lt;/li&gt;
&lt;li&gt;Security analysis, such as the use of unsafe methods.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating a sandbox
&lt;/h3&gt;

&lt;p&gt;Let’s make a fresh new directory for our adventure today. Initialize a Git repository in the folder and check it into GitHub as we’ll be using GitHub Workflows as our CI tool (more on this later).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;mkdir&lt;/span&gt; &lt;span class="n"&gt;proj&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="n"&gt;proj&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;touch&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gitignore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting up Ruby and Bundler
&lt;/h3&gt;

&lt;p&gt;You probably already have Ruby installed on your computer. But I find it best not to use pre-installed Ruby for a couple of reasons. Reason the first, it’s generally much older than the latest stable version, and you don’t want to miss out on Ruby’s newest features, do you? Reason the second, it’s relatively easy to break your system by installing, removing, or updating a critical package.&lt;/p&gt;

&lt;p&gt;Don’t fret; there’s a solution — &lt;a href="http://rvm.io" rel="noopener noreferrer"&gt;RVM&lt;/a&gt;. I won’t get into details of RVM here, but using it, you can install and manage several versions of Ruby on a system, keeping the system Ruby pristine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;rvm&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;rvm&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we set up &lt;a href="https://bundler.io" rel="noopener noreferrer"&gt;Bundler&lt;/a&gt;, a fantastic package manager for Ruby. We need it to keep track of our projects dependencies. It’s extremely straightforward to install.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;bundler&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To ensure that our project gems remain localized to our project, we can set up Bundler to install Gems at a given path. Create a directory &lt;code&gt;.bundle/&lt;/code&gt; and a &lt;code&gt;config&lt;/code&gt; file within the directory with the following content.&lt;/p&gt;

&lt;p&gt;With this configuration, Bundler will install all gems inside a &lt;code&gt;.gems/&lt;/code&gt; folder inside the current project folder &lt;code&gt;proj/&lt;/code&gt;. Add both directories &lt;code&gt;.bundle/&lt;/code&gt; and &lt;code&gt;.gems/&lt;/code&gt; to your &lt;code&gt;.gitignore&lt;/code&gt; file so that they are not checked into VCS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting familiar with Rubocop
&lt;/h3&gt;

&lt;p&gt;For analyzing the code quality in all the areas we mentioned above, we will be using &lt;a href="https://rubocop.org" rel="noopener noreferrer"&gt;Rubocop&lt;/a&gt;, one of the finest linters available for Ruby. Rubocop comes with an extensive collection of rules, called ‘&lt;em&gt;cops&lt;/em&gt;’, organized in groups, called ‘&lt;em&gt;departments&lt;/em&gt;’, based on their functionality.&lt;/p&gt;

&lt;p&gt;To install, add the line to your Gemfile and run &lt;code&gt;bundle install&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# frozen_string_literal: true source 'https://rubygems.org' git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } + gem 'rubocop', '~&amp;gt; 1.9', require: false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To list all the offences in any given file or directory, just pass the names as arguments to &lt;code&gt;rubocop&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;rubocop&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;dir_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rubocop is also capable of autocorrecting most of the errors it reports, which is incredibly helpful. To enable autocorrection, pass the &lt;code&gt;-a&lt;/code&gt; flag. Passing &lt;code&gt;-A&lt;/code&gt; uses a more aggressive auto-correct mode, which is not advisable unless you are sure of what you are doing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;rubocop&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;dir_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# safe autocorrect, recommended&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;rubocop&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;dir_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# unsafe autocorrect, not recommended&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will need to prepend &lt;code&gt;bundle exec&lt;/code&gt; to these commands if Rubocop is not globally installed.&lt;/p&gt;

&lt;h3&gt;
  
  
  The code
&lt;/h3&gt;

&lt;p&gt;Now we get to the fun part, scripting in Ruby. Take this script, for example. It takes a file name as an argument and prints said file’s content to STDOUT, very similar to the &lt;code&gt;cat&lt;/code&gt; command (hence the name).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# cat.rb&lt;/span&gt;
&lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;
&lt;span class="n"&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="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is formatted poorly, violates many rules from the style guide, and even has a couple of gaping security flaws. We’ll fix those pretty soon but first, let’s do a preliminary scan with Rubocop and observe the output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;rubocop&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="no"&gt;Inspecting&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;
&lt;span class="no"&gt;W&lt;/span&gt; &lt;span class="no"&gt;Offenses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Correctable&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Style&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;FrozenStringLiteralComment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Missing&lt;/span&gt; &lt;span class="n"&gt;frozen&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;literal&lt;/span&gt; &lt;span class="n"&gt;comment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="c1"&gt;# cat.rb&lt;/span&gt;
&lt;span class="o"&gt;^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Security&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;The&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="no"&gt;Kernel&lt;/span&gt;&lt;span class="c1"&gt;#open is a serious security risk.&lt;/span&gt;
&lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^^^^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;W&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Correctable&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Lint&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;RedundantWithIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Remove&lt;/span&gt; &lt;span class="n"&gt;redundant&lt;/span&gt; &lt;span class="n"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;^^^^^^^^^^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Correctable&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Layout&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;SpaceBeforeBlockBraces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Space&lt;/span&gt; &lt;span class="n"&gt;missing&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="p"&gt;{.&lt;/span&gt;
&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Correctable&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Layout&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;SpaceInsideBlockBraces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Space&lt;/span&gt; &lt;span class="n"&gt;between&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;missing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;^^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Correctable&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Style&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;BlockDelimiters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Avoid&lt;/span&gt; &lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;multi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="n"&gt;blocks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10&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="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Correctable&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Layout&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;TrailingEmptyLines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Final&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt; &lt;span class="n"&gt;missing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="n"&gt;inspected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;offenses&lt;/span&gt; &lt;span class="n"&gt;detected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="n"&gt;offenses&lt;/span&gt; &lt;span class="n"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;correctable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rubocop found 7 offenses, of which 6 it can correct automatically, labeled as &lt;code&gt;[Correctable]&lt;/code&gt; in the output above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pipeline
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Picking the infrastructure
&lt;/h3&gt;

&lt;p&gt;Choices abound when it comes to picking a CI/CD infrastructure provider. From &lt;a href="https://travis-ci.com" rel="noopener noreferrer"&gt;Travis CI&lt;/a&gt;, a darling of open-source developers, to &lt;a href="https://www.jenkins.io" rel="noopener noreferrer"&gt;Jenkins&lt;/a&gt;, the tool of choice for enterprise teams who’d rather self-host their customized solution, dev-ops engineers are spoilt for choice.&lt;/p&gt;

&lt;p&gt;But the simplest of these in my experience has been &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub workflows&lt;/a&gt;, a GitHub-native solution allowing you to set up entire chains of jobs, described as YAML files, that can be initiated based on specific triggers. We can use them throughout the CI/CD pipeline, from running checks on PRs before merge to deploying the code after. There are hundreds of pre-built actions (many officially maintained) that take the effort out of setting up end-to-end pipelines.&lt;/p&gt;

&lt;p&gt;Naturally, we’ll be using GitHub workflows as our CI pipeline infrastructure. The end goal is to have linting as a check on our PRs and commits. Only PRs that pass the checks would be mergeable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding lint workflow
&lt;/h3&gt;

&lt;p&gt;Let’s see what the workflow file would look like in our case. Create a new directory &lt;code&gt;.github/&lt;/code&gt;, create another directory within this one named &lt;code&gt;workflows/&lt;/code&gt;, and in this directory, create a file named &lt;code&gt;lint.yml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/lint.yml&lt;/span&gt;
&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="no"&gt;Lint&lt;/span&gt;

&lt;span class="ss"&gt;on:
 push:
 branches:
 &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;master&lt;/span&gt;

&lt;span class="ss"&gt;jobs:
 lint:
 name: &lt;/span&gt;&lt;span class="no"&gt;Lint&lt;/span&gt;
 &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;on: &lt;/span&gt;&lt;span class="n"&gt;ubuntu&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;
 &lt;span class="ss"&gt;steps:
 &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="ss"&gt;uses: &lt;/span&gt;&lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="vi"&gt;@v2&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="ss"&gt;uses: &lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="vi"&gt;@v1&lt;/span&gt;
 &lt;span class="ss"&gt;with:
 &lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;version: &lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;
 &lt;span class="n"&gt;bundler&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;cache: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;# runs `bundle install`&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="ss"&gt;run: &lt;/span&gt;&lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;rubocop&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lint workflow consists of a single job. The job is fired on every push event to the &lt;code&gt;master&lt;/code&gt; branch and performs three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;actions/checkout&lt;/code&gt;: checks out the code repository&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ruby/setup-ruby&lt;/code&gt;:

&lt;ol&gt;
&lt;li&gt;sets up Ruby version 3.0 and the latest compatible version of Bundler&lt;/li&gt;
&lt;li&gt;uses Bundler to install all packages in the &lt;code&gt;Gemfile&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;run&lt;/code&gt;: runs Rubocop on the entire current working directory&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;Once the job completes, we get our outcome. In our case, it’s a big red cross. The workflow execution fails because Rubocop found issues in the code. The logs reveal the same message we had seen earlier, and lists offences identified by Rubocop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeepsource.io%2Fimages%2Fblog%2Fstatic-analysis-ci-ruby%2Fruby-ci-1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeepsource.io%2Fimages%2Fblog%2Fstatic-analysis-ci-ruby%2Fruby-ci-1.jpeg" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;😢 We’ll get there, eventually.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixing problems
&lt;/h3&gt;

&lt;p&gt;We want our check to pass. Nobody likes failing checks. Coming back to our local setup, let’s use Rubocop’s autofix feature to quickly resolve these issues. First, we should let Rubocop take care of the automatic stuff using the &lt;code&gt;-a&lt;/code&gt; flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;rubocop&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="no"&gt;Inspecting&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;
&lt;span class="no"&gt;W&lt;/span&gt; &lt;span class="no"&gt;Offenses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Correctable&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Style&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;FrozenStringLiteralComment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Missing&lt;/span&gt; &lt;span class="n"&gt;frozen&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;literal&lt;/span&gt; &lt;span class="n"&gt;comment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="c1"&gt;# cat.rb&lt;/span&gt;
&lt;span class="o"&gt;^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Security&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;The&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="no"&gt;Kernel&lt;/span&gt;&lt;span class="c1"&gt;#open is a serious security risk.&lt;/span&gt;
&lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^^^^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Corrected&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Layout&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;ExtraSpacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Unnecessary&lt;/span&gt; &lt;span class="n"&gt;spacing&lt;/span&gt; &lt;span class="n"&gt;detected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_line&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;W&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Corrected&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Lint&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;RedundantWithIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Remove&lt;/span&gt; &lt;span class="n"&gt;redundant&lt;/span&gt; &lt;span class="n"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;^^^^^^^^^^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Corrected&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Layout&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;SpaceBeforeBlockBraces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Space&lt;/span&gt; &lt;span class="n"&gt;missing&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="p"&gt;{.&lt;/span&gt;
&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Corrected&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Layout&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;SpaceInsideBlockBraces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Space&lt;/span&gt; &lt;span class="n"&gt;between&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;missing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;^^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Corrected&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Style&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;BlockDelimiters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Avoid&lt;/span&gt; &lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;multi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="n"&gt;blocks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10&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="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Corrected&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Layout&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;TrailingEmptyLines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Final&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt; &lt;span class="n"&gt;missing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="n"&gt;inspected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="n"&gt;offenses&lt;/span&gt; &lt;span class="n"&gt;detected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="n"&gt;offenses&lt;/span&gt; &lt;span class="n"&gt;corrected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;offense&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;corrected&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="sb"&gt;`rubocop -A`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rubocop solved most of the issues reported, including one issue introduced during the autofix process itself! With 6 of the 7 problems are already fixed, we’ve managed to shave off ~70% of our work with zero effort input.&lt;/p&gt;

&lt;p&gt;What’s left is one unsafe autofix and one security vulnerability that Rubocop cannot fix automatically. We can take care of those:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The frozen string literal comment is missing. That’s a reasonable thing to add to the file, so we’ll let Rubocop add it using the stronger autofix flag &lt;code&gt;-A&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;rubocop&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="no"&gt;Inspecting&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;
&lt;span class="no"&gt;C&lt;/span&gt; &lt;span class="no"&gt;Offenses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Corrected&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Style&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;FrozenStringLiteralComment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Missing&lt;/span&gt; &lt;span class="n"&gt;frozen&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;literal&lt;/span&gt; &lt;span class="n"&gt;comment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="c1"&gt;# cat.rb&lt;/span&gt;
&lt;span class="o"&gt;^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&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;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Corrected&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="no"&gt;Layout&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;EmptyLineAfterMagicComment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Add&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;empty&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="n"&gt;magic&lt;/span&gt; &lt;span class="n"&gt;comments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="c1"&gt;# cat.rb&lt;/span&gt;
&lt;span class="o"&gt;^&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Security&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;The&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="no"&gt;Kernel&lt;/span&gt;&lt;span class="c1"&gt;#open is a serious security risk.&lt;/span&gt;
&lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^^^^&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="n"&gt;inspected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="n"&gt;offenses&lt;/span&gt; &lt;span class="n"&gt;detected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;offenses&lt;/span&gt; &lt;span class="n"&gt;corrected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit and push. We’re green now! At this point, you should pat yourself on the back for a job well done.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeepsource.io%2Fimages%2Fblog%2Fstatic-analysis-ci-ruby%2Fruby-ci-2.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeepsource.io%2Fimages%2Fblog%2Fstatic-analysis-ci-ruby%2Fruby-ci-2.jpeg" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🥳 Yay!&lt;/p&gt;

&lt;h3&gt;
  
  
  Staying clean
&lt;/h3&gt;

&lt;p&gt;Now that you’re at peak code quality, we need to ensure it stays that way. This means that we need to ensure that no PR negatively affects our codebase quality. To run the check on every incoming PR, add the &lt;code&gt;pull_request&lt;/code&gt; event to our lint workflow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="ss"&gt;on: on: push: branches: &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;master&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="ss"&gt;pull_request:
&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="ss"&gt;branches:
&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;master&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, to test that our check is working as expected, we need to make a PR with some code that Rubocop would flag. Let’s refactor the lines in our script, that are concerned with reading the file, to use a block.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# cat.rb # frozen_string_literal: true filename = ARGV[0] - file = File.open(filename)&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&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="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_line&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out a new branch from &lt;code&gt;master&lt;/code&gt;. Commit and push to this branch and open a PR. You’ll see that the checks fail, and thus the PR cannot be merged unless overridden by an administrator.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeepsource.io%2Fimages%2Fblog%2Fstatic-analysis-ci-ruby%2Fruby-ci-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeepsource.io%2Fimages%2Fblog%2Fstatic-analysis-ci-ruby%2Fruby-ci-3.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🚧 Our check is working just fine!&lt;/p&gt;

&lt;p&gt;🧠 &lt;strong&gt;Brain-teaser:&lt;/strong&gt; Can you identify why the updated code, using a block, is being flagged by Rubocop?&lt;/p&gt;

&lt;p&gt;🤷‍♂️ &lt;strong&gt;Hint:&lt;/strong&gt; If you want a hint, here’s the Rubocop output for the PR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;rubocop&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="no"&gt;Inspecting&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;
&lt;span class="no"&gt;W&lt;/span&gt;

&lt;span class="no"&gt;Offenses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;W&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Lint&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;UselessAssignment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Useless&lt;/span&gt; &lt;span class="n"&gt;assignment&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;variable&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
  &lt;span class="nf"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;
  &lt;span class="o"&gt;^^^^&lt;/span&gt;

&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="n"&gt;inspected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;offense&lt;/span&gt; &lt;span class="n"&gt;detected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🧑‍💻 &lt;strong&gt;Answer:&lt;/strong&gt; Defining &lt;code&gt;list&lt;/code&gt; inside the block means that it is not accessible outside the block. This makes the assignment useless and will lead to a bug in the subsequent use of the variable.&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Lesson:&lt;/strong&gt; Though indirectly, code analysis can sometimes also help identify potential bugs!&lt;/p&gt;

&lt;h2&gt;
  
  
  DeepSource
&lt;/h2&gt;

&lt;p&gt;While we invested considerable time and effort, we now have checks and actions set up to monitor code quality in our repo. But what if we didn’t have time to spare or didn’t want to spend the effort? We’re busy developers, after all!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbojddazgf4gnjex4nq5j.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbojddazgf4gnjex4nq5j.gif" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Consider using &lt;a href="https://deepsource.io/" rel="noopener noreferrer"&gt;DeepSource&lt;/a&gt;. It continuously scans the code on every commit, and on every pull request, through various static code analyzers (including linters and security analyzers), and can automatically fix some of them. DeepSource also has its custom-built analyzers for most languages that are constantly improved and kept up-to-date.&lt;/p&gt;

&lt;p&gt;It’s &lt;a href="https://deepsource.io/docs/analyzer/ruby.html" rel="noopener noreferrer"&gt;incredibly easy to set up&lt;/a&gt;! You need only add a &lt;code&gt;.deepsource.toml&lt;/code&gt; file in your repository root, and DeepSource will pick it up. It takes much less effort and the end result is way more polished that setting up several workflows in GitHub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version = 1

[[analyzers]]
name = "ruby"
enabled = true

[[transformers]]
name = "rubocop"
enabled = true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Automate the tedium away
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwjiglypq97hdnjnfs8bh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwjiglypq97hdnjnfs8bh.gif" width="498" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CI/CD pipelines are quintessential to the agile development workflow. The ability to add features, squash bugs, and get the changes in production instantly can make a very significant difference. Startups live or die based on how often they iterate.&lt;/p&gt;

&lt;p&gt;Integrating static analysis into the CI pipeline ensures that only the cleanest and most compliant code makes its way into production. For something that takes very little time to set up, consumes a minuscule amount of resources, and does not significantly affect test/build timings, static analysis can add a lot of confidence to your build process.&lt;/p&gt;

&lt;p&gt;Confident iterations await. Till next time!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Automate code formatting in Python</title>
      <dc:creator>Saif Sadiq</dc:creator>
      <pubDate>Tue, 16 Feb 2021 08:06:53 +0000</pubDate>
      <link>https://forem.com/deepsource/automate-code-formatting-in-python-4d23</link>
      <guid>https://forem.com/deepsource/automate-code-formatting-in-python-4d23</guid>
      <description>&lt;p&gt;Right off the bat, let’s clarify an important distinction. Writing code that works and writing good code are two very different things. The former is a skill while the latter is an art form, and this difference distinguishes great programmers from the crowd.&lt;/p&gt;

&lt;p&gt;When we talk of good code, the word ‘good’ is vague by design. That’s because there are no rules set in stone about what makes code good or bad. All we have are some abstract guidelines such as readability:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Programs are meant to be read by humans and only incidentally for computers to execute.&lt;/p&gt;

&lt;p&gt;– Abelson &amp;amp; Sussman&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are two MIT professors with pretty solid credentials. Identifying the quality of code is an intuition that is honed over time, through practice and experience. Code reviews go a long way towards this goal.&lt;/p&gt;

&lt;p&gt;Code review is the process where developers more experienced than yourself read through your code and suggest improvements that could make it better. These suggestions can improve performance, incorporate new language features, patch security oversights, or correct code style.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyfspzf4n5yntzulqnj3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyfspzf4n5yntzulqnj3.gif" alt="Alt Text" width="498" height="206"&gt;&lt;/a&gt;&lt;em&gt;... when it comes to code review.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But manual code reviews are expensive. The time it takes someone to read your code is time they did not spend building awesome stuff. They are also error-prone and by no means comprehensive. There are human limits to knowledge and memory.&lt;br&gt;&lt;br&gt;
Enter automation. Automated code reviews are faster, less error-prone, and more in-depth than their manual counterparts.&lt;/p&gt;

&lt;p&gt;Let’s dive deep into the process with a sample project containing a single Python file. We’ll riddle the file with issues and then set up a workflow that automatically finds and fixes these problems.&lt;/p&gt;
&lt;h2&gt;
  
  
  Ingredients
&lt;/h2&gt;
&lt;h3&gt;
  
  
  A. Codebase with PEP-8 violations
&lt;/h3&gt;

&lt;p&gt;Before we automate code review, let’s first write some code to review. Here is a sample program that lists primes up to a given number. It might hurt to look at, which is good as it means your code-olfactory senses are working.&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;# list_primes.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_prime&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&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="n"&gt;number&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;number&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_primes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&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="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;is_prime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&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="sa"&gt;F&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; is prime&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;list_primes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a lot of problems with this script. Don’t get me wrong, it works, but it’s not good.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extraneous space before function parenthesis&lt;/li&gt;
&lt;li&gt;2-space indentation&lt;/li&gt;
&lt;li&gt;No spaces around operators&lt;/li&gt;
&lt;li&gt;Single line around functions&lt;/li&gt;
&lt;li&gt;Uppercase &lt;code&gt;F&lt;/code&gt; in f-strings&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  B. Black code formatter
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://black.readthedocs.io/en/stable/" rel="noopener noreferrer"&gt;Black&lt;/a&gt; is a popular code formatter for Python. It is capable of automatically reformatting your Python files, fixing all code style violations. What’s neat is that it is pretty opinionated and can’t be configured much, making it ideal for automation.&lt;/p&gt;

&lt;p&gt;So let’s install Black, while also taking the opportunity to set up some first-class dependency management with a tool I personally love, &lt;a href="https://pipenv.pypa.io/en/latest/" rel="noopener noreferrer"&gt;Pipenv&lt;/a&gt;. Running the following command creates two files, &lt;code&gt;Pipfile&lt;/code&gt; and &lt;code&gt;Pipfile.lock&lt;/code&gt;, in the root of the repo and installs Black as a dev dependency.&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="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;pipenv&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;pre&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; &lt;span class="n"&gt;black&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running Black without any args formats all files in the repo directly. Apart from reformatting your files, it has two less dangerous modes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--check&lt;/code&gt;: In this mode, Black purely checks if there are any code style violations. The return code is 0 if there are no violations and non-zero if there are any.&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="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;pipenv&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;black&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt; &lt;span class="n"&gt;list_primes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="n"&gt;would&lt;/span&gt; &lt;span class="n"&gt;reformat&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dhruvkb&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Documents&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;scratch&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;automata&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;list_primes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="n"&gt;Oh&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="err"&gt;💥&lt;/span&gt; &lt;span class="err"&gt;💔&lt;/span&gt; &lt;span class="err"&gt;💥&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="n"&gt;would&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;reformatted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--diff&lt;/code&gt;: In this mode, Black shows the changes it will make without actually making them. This mode is helpful if you want to inspect the changes before they are actually made.&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="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;pipenv&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;black&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt; &lt;span class="n"&gt;list_primes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="o"&gt;---&lt;/span&gt; &lt;span class="n"&gt;list_primes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;  &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.000000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;
&lt;span class="o"&gt;+++&lt;/span&gt; &lt;span class="n"&gt;list_primes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;  &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.000000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;
&lt;span class="o"&gt;@@&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="mi"&gt;17&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="mi"&gt;19&lt;/span&gt; &lt;span class="o"&gt;@@&lt;/span&gt;
 &lt;span class="c1"&gt;# list_primes.py
&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_prime&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_prime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&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="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&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="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;
 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_primes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;in&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;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;is_prime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;F&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; is prime&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; is prime&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;

 &lt;span class="nf"&gt;list_primes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Recipe
&lt;/h2&gt;

&lt;p&gt;Code review can be split in two parts: the interesting part where you solve big picture issues and the mundane parts where you identify non-idiomatic snippets and code style violations. Let’s automate the boring parts of the code review.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Set up Git hooks
&lt;/h3&gt;

&lt;p&gt;We just saw how incredible Black is. Wouldn’t it be awesome if Black ran automatically every time you were to commit your code? It’s possible, with Git hooks. Git hooks are programs that run on your codebase when you execute certain Git commands. The ‘pre-commit’ hook is of particular interest to us because we’d like the lint check to take place before the commit is created, and prevent the commit from being created if it fails.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/greenbone/autohooks" rel="noopener noreferrer"&gt;Autohooks&lt;/a&gt; is a Python package for managing these hooks via Python. It has a plugin system that enables integration with tools like Black. Let’s install both Autohooks and the Black-integration plugin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pipenv install --dev autohooks autohooks-plugin-black
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make a &lt;code&gt;pyproject.toml&lt;/code&gt; file in the root of your repo with the following content.&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="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;autohooks&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pipenv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;pre&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt; &lt;span class="o"&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;autohooks.plugins.black&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;autohooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;black&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;arguments&lt;/span&gt; &lt;span class="o"&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;--check&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Activate the hooks and run the check function to see if everything works fine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pipenv run autohooks activate
✓ autohooks pre-commit hook installed at /Users/hal/Documents/scratch/.git/hooks/pre-commit using pipenv mode.

$ pipenv run autohooks check
✓ autohooks pre-commit hook is active.
✓ autohooks pre-commit hook is up-to-date.
ℹ Using autohooks mode "pipenv".
✓ Plugin "autohooks.plugins.black" active and loadable.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try &lt;code&gt;git commit&lt;/code&gt;-ing the poorly written source code. Ha, gotcha! Here’s how things will go down:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The pre-commit hook will be initiated.&lt;/li&gt;
&lt;li&gt;The top-level hooks by Autohooks will be invoked.&lt;/li&gt;
&lt;li&gt;Autohooks will then execute Black with the &lt;code&gt;--check&lt;/code&gt; argument.&lt;/li&gt;
&lt;li&gt;Black will return a non-zero code because the file contains errors.&lt;/li&gt;
&lt;li&gt;Git will halt the commit operation.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git add . &amp;amp;&amp;amp; git commit -m "Add the source code to VCS"
ℹ autohooks =&amp;gt; pre-commit
ℹ Running autohooks.plugins.black
would reformat /Users/dhruvkb/Documents/scratch/automata/list_primes.py
Oh no! 💥 💔 💥
1 file would be reformatted.
×
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 &lt;strong&gt;Pro-tip:&lt;/strong&gt; You can bypass the hook with the &lt;code&gt;--no-verify&lt;/code&gt; flag on &lt;code&gt;git commit&lt;/code&gt;. It’s not recommended but we’re not the police, so do what you want.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 Pro-tip:&lt;/strong&gt; You can remove the &lt;code&gt;--check&lt;/code&gt; argument and then every time you commit, Black will reformat your files for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Lint check using GitHub Actions
&lt;/h3&gt;

&lt;p&gt;The main drawback of Git hooks is that they are local. In a project with multiple contributors, there might be people who might forget to activate the hook or actively try to bypass them. In such cases, the solution is to run the lint check on the remote repo itself. GitHub Actions provides an extremely versatile solution for running the lint.&lt;/p&gt;

&lt;p&gt;Create the file &lt;code&gt;lint.yml&lt;/code&gt; inside the &lt;code&gt;.github/workflows&lt;/code&gt; directory of the repo.&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;# .github/workflows/lint.yml
&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Lint&lt;/span&gt;

&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&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;pull_request&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="n"&gt;lint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ubuntu&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;
 &lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="nd"&gt;@v2&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="nd"&gt;@v2&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;psf&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;black&lt;/span&gt;&lt;span class="nd"&gt;@stable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow checks out the repository, sets up Python, installs Black and then lints the files. By default, this action runs Black with the &lt;code&gt;--check&lt;/code&gt; and &lt;code&gt;--diff&lt;/code&gt; arguments. Once you set up linting, all future commits and PRs will pass through Black.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwn9qq4g8q4n8jnmxyml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwn9qq4g8q4n8jnmxyml.png" alt="Alt Text" width="800" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;list_primes.py&lt;/code&gt; file will fail the test. The logs will show both the failing files as well as the diffs for those files (because of the &lt;code&gt;-diff&lt;/code&gt; argument). That’ll come in pretty handy when you’re fixing the violations.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Lint fixes using GitHub Workflows
&lt;/h3&gt;

&lt;p&gt;That brings us to the one aspect we still haven’t addressed yet. Black is capable of reformatting files, but so far, we have only used it to detect issues and present diffs. We’ve not tapped into Black’s full potential yet.&lt;/p&gt;

&lt;p&gt;How about we turn the automation up to 11 and update our GitHub workflow to automatically fix code style violations?&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;# .github/workflows/lint.yml
&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Lint&lt;/span&gt;

&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;workflow_dispatch&lt;/span&gt;

&lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="n"&gt;lint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ubuntu&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;
 &lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="nd"&gt;@v2&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="nd"&gt;@v2&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Install&lt;/span&gt; &lt;span class="n"&gt;Python&lt;/span&gt; &lt;span class="n"&gt;dependencies&lt;/span&gt;
 &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
 &lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;pipenv&lt;/span&gt;
 &lt;span class="n"&gt;pipenv&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;deploy&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wearerequired&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lint&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="nd"&gt;@v1&lt;/span&gt;
 &lt;span class="k"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="n"&gt;github_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="n"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GITHUB_TOKEN&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
 &lt;span class="n"&gt;black&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;
 &lt;span class="n"&gt;auto_fix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow uses the same two steps as the previous one, that is checking out the repo and setting up Python. Then we install Pipenv and use that to install Black on the system. The &lt;code&gt;lint-action&lt;/code&gt; &lt;a href="https://github.com/wearerequired/lint-action" rel="noopener noreferrer"&gt;action&lt;/a&gt; runs Black and then commits the changed files. This creates a new commit with the same changes that Black had shown in the diff!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 Pro-tip:&lt;/strong&gt; You can customize the author’s name and email and also the message of the commit. Just add the following to the &lt;code&gt;with&lt;/code&gt; key of the action. It’s an opportunity to be creative!&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="n"&gt;commit_message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Opening the pod-bay doors&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;git_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;HAL-9000&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;git_email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hal@hal.hal&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecmm8rldruluykofyej5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecmm8rldruluykofyej5.png" alt="Alt Text" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you can be assured that code pushed to the repo is free from style guide deviations, this frees up code reviewers to take a bigger picture look at the code and leave the minutiae to HAL.&lt;/p&gt;

&lt;h2&gt;
  
  
  End-to-end automation with DeepSource
&lt;/h2&gt;

&lt;p&gt;Phew! That was a lot of work, wasn’t it? But guess what, we only looked at style guide violations for now. Adding more features like looking for security gaps, finding possible bugs, and making complex refactors would make this a very long exercise. But it does not have to be.&lt;/p&gt;

&lt;p&gt;You could also consider automating this entire audit, review and refactor process with &lt;a href="https://deepsource.io/python-static-code-analysis/" rel="noopener noreferrer"&gt;DeepSource&lt;/a&gt; that can scan your code on every commit, and for every pull request, through several tools (including linters and security analyzers) and can automatically fix many issues. DeepSource also has its custom-built analyzers for most languages that are constantly improved and kept up-to-date.&lt;/p&gt;

&lt;p&gt;It’s &lt;a href="https://deepsource.io/docs/analyzer/python.html" rel="noopener noreferrer"&gt;incredibly easy to set up&lt;/a&gt;! You need only add a &lt;code&gt;.deepsource.toml&lt;/code&gt; file in your repository root, and DeepSource will pick it up. Much less effort than what we just went through.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version = 1

[[analyzers]]
name = "python"
enabled = true

  [analyzers.meta]
  runtime_version = "3.x.x"
  max_line_length = 80

[[transformers]]
name = "black"
enabled = true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Finis coronat opus
&lt;/h2&gt;

&lt;p&gt;Code reviews are a very important learning tool for new developers. It’s a way to transfer knowledge, experience, and convention from a senior developer to a junior, a way to understand how even the code that was deemed as final can be made better, cleaner, and more efficient.&lt;/p&gt;

&lt;p&gt;I’d venture so far as to say that code reviews are one of the best learning tools for developers, and they are wasted on mundane things like code style. Introduce a little automation and make every code review count.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;They know enough who know how to learn.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When done well, a code review can be a truly educational experience. Automation cannot replace that. What automation can do is take the mundane out of the process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://deepsource.io/blog/code-review-best-practices/" rel="noopener noreferrer"&gt;Here’s to better code reviews!&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Common Python security pitfalls, and how to avoid them</title>
      <dc:creator>Saif Sadiq</dc:creator>
      <pubDate>Wed, 10 Feb 2021 17:43:05 +0000</pubDate>
      <link>https://forem.com/deepsource/common-python-security-pitfalls-and-how-to-avoid-them-50gh</link>
      <guid>https://forem.com/deepsource/common-python-security-pitfalls-and-how-to-avoid-them-50gh</guid>
      <description>&lt;p&gt;Python is undoubtedly a popular language. It consistently ranks among the most popular and most loved languages &lt;a href="https://insights.stackoverflow.com/survey/2019" rel="noopener noreferrer"&gt;year&lt;/a&gt; after &lt;a href="https://insights.stackoverflow.com/survey/2018" rel="noopener noreferrer"&gt;year&lt;/a&gt;. That’s not hard to explain, considering how fluent and expressive it is. Its pseudocode-like syntax makes it extremely easy for beginners to pick it up as their first language, while its vast library of packages (including the likes of giants like Django and TensorFlow) ensure that it scales up for any task required of it.&lt;/p&gt;

&lt;p&gt;Being such a widely-used language makes Python a very attractive target for malicious hackers. Let’s see a few simple ways to secure your Python apps and keep the black-hats at bay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems and solutions
&lt;/h2&gt;

&lt;p&gt;Python places a lot of importance on zen, or developer happiness. The clearest evidence of that lies in the fact that the guiding principles of Python are summarized in a poem. Try &lt;code&gt;import this&lt;/code&gt; in a Python shell to read it. Here are some security concerns that might disturb your zen, along with solutions to restore it to a state of calm.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unsafe deserialization
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://owasp.org/www-project-top-ten/" rel="noopener noreferrer"&gt;OWASP Top Ten&lt;/a&gt;, a basic checklist for web security, mentions unsafe deserialization as one of the ten most common security flaws. While it’s common knowledge that executing anything coming from the user is a terrible idea, serializing and deserializing user input does not seem equally serious. After all, no code is being run, right? Wrong,&lt;/p&gt;

&lt;p&gt;PyYAML is the &lt;em&gt;de-facto&lt;/em&gt; standard for YAML serialization and deserialization in Python. The library supports serializing custom data types to YAML and deserializing them back to Python objects. See this serialization code here and the YAML produced by it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# serialize.py
import yaml class Person: def __init__ (self, name, age): self.name = name self.age = age def __str__ (self): return f'&amp;lt;Person: {self.name} - {self.age}&amp;gt;' def __repr__ (self): return str(self) person = Person('Dhruv', 24)
with open('person.yml', 'w') as output_file: yaml.dump(person, output_file)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!!python/object: __main__.Person
age: 24
name: Dhruv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deserializing this YAML gives back the original data type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# deserialize.py
import yaml # class Person needs to be present in the scope
with open('person.yml', 'r') as input_file: person = yaml.load(input_file, Loader = yaml.Loader) print(person)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ python deserialize.py ↵
&amp;lt;Person: Dhruv - 24&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the line &lt;code&gt;!!python/object: __main__.Person&lt;/code&gt; in the YAML describes how to re-instantiate objects from their text representations. But this opens up a &lt;a href="https://github.com/yaml/pyyaml/wiki/PyYAML-yaml.load%28input%29-Deprecation" rel="noopener noreferrer"&gt;slew of attack vectors, that can escalate to RCE&lt;/a&gt; when this instantiation can execute code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The solution, as trivial as it may seem, is to use safe-loading by swapping out the loader &lt;code&gt;yaml.Loader&lt;/code&gt; in favor of the &lt;code&gt;yaml.SafeLoader&lt;/code&gt; loader. This loader is safer because it completely blocks loading of custom classes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# deserialize.py
import yaml # class Person needs to be present in the scope
with open('person.yml', 'r') as input_file: person = yaml.load(input_file, Loader = yaml.SafeLoader) print(person)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ python deserialize.py ↵
ConstructorError: could not determine a constructor for the tag 'tag:yaml.org,2002:python/object: __main__.Person'
  in "person.yml", line 1, column 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Standard types like hashes and arrays can still be serialized to and deserialized from YAML documents just like before. Most people, probably including you, won’t even realize the difference.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;age: 24
name: Dhruv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ python deserialize.py ↵
{'age': 24, 'name': 'Dhruv'}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dynamic execution
&lt;/h3&gt;

&lt;p&gt;Python has a pair of very dangerous functions: &lt;code&gt;exec&lt;/code&gt; and &lt;code&gt;eval&lt;/code&gt;. Both are very similar in terms of what they do: process the strings passed to them as Python code. &lt;code&gt;exec&lt;/code&gt; expects the string to be a statement, which it will execute and not return a value. &lt;code&gt;eval&lt;/code&gt; expects the string to be an expression and will return the computed value of the expression.&lt;/p&gt;

&lt;p&gt;Here is an example of what both these functions in action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eval('2 + 5') # returns 7
exec('print("Hello")') # prints "Hello", no return
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You could in theory, pass a statement to &lt;code&gt;eval&lt;/code&gt; and get a similar effect as &lt;code&gt;exec&lt;/code&gt;, because in Python returning &lt;code&gt;None&lt;/code&gt; is virtually the same as not returning anything at all.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eval('print("Hello")') # prints "Hello", returns None
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The danger of these functions lies in the ability of these functions to execute virtually any code in the same Python process. Passing any input to the function that you cannot be 100% certain about, is akin to handing over your server keys to malicious hackers on a plate. This is the very definition of RCE.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are ways to mitigate the access that eval has. You can restrict access to globals and locals by passing dictionaries as the second and third arguments to &lt;code&gt;eval&lt;/code&gt; respectively. Remember that locals take priority over globals in case of conflict.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x = 3
eval('x + 5') # returns 8
eval('x + 5', { 'x': 2 }) # returns 7
eval('x + 5', { 'x': 2 }, { 'x': 1 }) # returns 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That makes the code safer yes. At least it somewhat prevents the data in the variables from being leaked.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9byl34355rwi5w61nqwj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9byl34355rwi5w61nqwj.png" width="538" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But it still doesn’t prevent the string from accessing any built-ins like &lt;code&gt;pow&lt;/code&gt;, or more dangerously, &lt;code&gt;__import__&lt;/code&gt;. To counter that, you need to override &lt;code&gt;__builtins__&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eval(" __import__ ('math').sqrt(5)", {}, {}) # returns 2.2360679774997898
eval( " __import__ ('math').sqrt(5)", { " __builtins__": None }, {} # restricts access to built-ins
) # error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Safe to expose now? Not quite. Because regardless of how secure you make &lt;code&gt;eval&lt;/code&gt;, it’s job is to evaluate an expression and nothing can stop the expression from taking too long and freezing the server for a long time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eval("2 ** 2147483647", { " __builtins__": None }, {}) # goodbye!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we Python developers like to say, “&lt;code&gt;eval&lt;/code&gt; &lt;strong&gt;is evil&lt;/strong&gt;.”&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependency management
&lt;/h3&gt;

&lt;p&gt;Python’s popularity draws the attention of white-hat security researchers just as much as it does that of hackers with malicious intent. As a result, new security vulnerabilities that are constantly discovered, disclosed, and patched. To keep the malicious hackers at bay, your software needs to keep all its dependencies up to date.&lt;/p&gt;

&lt;p&gt;A common technique for pinning packages in Python is the ubiquitous &lt;code&gt;requirements.txt&lt;/code&gt; file, a simple file that lists all the dependencies and exact versions needed by your project.&lt;/p&gt;

&lt;p&gt;Let’s say you install Django. As of writing, Django depends on three more packages. If you freeze your dependencies, you end up with the following requirements. Note that only one of these dependencies was installed by you, the other 3 are sub-dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pip freeze ↵
asgiref==3.3.1
Django==3.1.5
pytz==2020.5
sqlparse==0.4.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;pip freeze&lt;/code&gt; does not place dependencies in levels and that’s a problem. For smaller projects with a few dependencies that you can keep a track of mentally, this is not a big deal but as your projects grow, so will your top level dependencies. Conflicts arise when sub-dependencies overlap. Updating individual dependencies is a mess too, because the graph relationship of these dependencies is not clear from the plain text file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fla8p9alg8ifyrvu5el0l.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fla8p9alg8ifyrvu5el0l.jpg" width="500" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pipenv.pypa.io/en/latest/" rel="noopener noreferrer"&gt;Pipenv&lt;/a&gt; and &lt;a href="https://python-poetry.org" rel="noopener noreferrer"&gt;Poetry&lt;/a&gt; are two tools that help you manage dependencies better. I prefer Pipenv but Poetry is equally good. Both package managers build on top of &lt;code&gt;pip&lt;/code&gt;. &lt;strong&gt;Fun fact:&lt;/strong&gt; DeepSource is compatible with both Pipenv and Poetry as package managers.&lt;/p&gt;

&lt;p&gt;Pipenv, for example, tracks your top-level dependencies in a &lt;code&gt;Pipfile&lt;/code&gt; and then does the hard work of locking down dependencies in a lockfile name &lt;code&gt;Pipfile.lock&lt;/code&gt;, similar to how &lt;code&gt;npm&lt;/code&gt; manages Node.js packages. Here’s an example &lt;code&gt;Pipfile&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
django = "*"

[requires]
python_version = "3.9"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, you can get a clear picture of the top-level dependencies of your app. Updating dependencies is also much easier because you just need to update the top level packages and the locking algorithm will figure out the most compatible and up-to-date versions of all the sub-dependencies.&lt;/p&gt;

&lt;p&gt;Here is the same example with Django. Notice how Pipenv can identify your top-level dependencies and its dependencies and so on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pipenv graph ↵
Django==3.1.5
  - asgiref [required: &amp;gt;=3.2.10,&amp;lt;4, installed: 3.3.1]
  - pytz [required: Any, installed: 2020.5]
  - sqlparse [required: &amp;gt;=0.2.2, installed: 0.4.1]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your code is hosted on GitHub, make sure you turn on and configure &lt;a href="https://dependabot.com" rel="noopener noreferrer"&gt;Dependabot&lt;/a&gt; as well. It’s a nifty little bot that alerts you if any of your dependencies has gone out of date or if a vulnerability has been identified in the pinned version of a dependency. Dependabot will also make PRs to your repo, automatically updating your packages. Very handy indeed!&lt;/p&gt;

&lt;h3&gt;
  
  
  Runtime assertions
&lt;/h3&gt;

&lt;p&gt;Python has a special &lt;code&gt;assert&lt;/code&gt; keyword for guarding against unexpected situations. The purpose of &lt;code&gt;assert&lt;/code&gt; is simple, verify a condition and raise an error if the condition is not fulfilled. In essence, &lt;code&gt;assert&lt;/code&gt; evaluates the given expression and&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if it evaluates to a truthy value, moves along&lt;/li&gt;
&lt;li&gt;if it evaluates to a falsey value, raises an &lt;code&gt;AssertionError&lt;/code&gt; with the given message&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consider this example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def do_something_dangerous(user, command): assert user.has_permissions(command), f'{user} is not authorized' user.execute(command)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a very simple example where we check if the user has the permissions to perform an action and subsequently perform the given action. In this case, if &lt;code&gt;user.has_permissions()&lt;/code&gt; returns &lt;code&gt;False&lt;/code&gt;, our assertion would cause an &lt;code&gt;AssertionError&lt;/code&gt; and the execution would be halted. Seems pretty safe, right?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiw5bmyi843t1zdoj70pb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiw5bmyi843t1zdoj70pb.gif" width="1024" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No. Assertions are tools for developers during development and debugging phases. Asserts should not be used to guard critical functionality. The Python constant, &lt;code&gt;__debug__&lt;/code&gt; is set to &lt;code&gt;False&lt;/code&gt; during compilation, which removes assert statements from the compiled code to optimise the code for performance. Removing assert statements from the compiled code leaves the function unguarded.&lt;/p&gt;

&lt;p&gt;Another reason to avoid &lt;code&gt;assert&lt;/code&gt;s is that assertion errors are not helpful to debuggers as they provide no information other than the fact that an assertion did not hold up. Defining apt exception classes and then raising their instances is a much more solid solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For an alternative approach, go back to the basics. Here’s the same program, this time using &lt;code&gt;if/else&lt;/code&gt; and a raising a &lt;code&gt;PermissionError&lt;/code&gt; (you’ll need to define it somewhere) when the required assertion is unfulfilled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def do_something_dangerous(user, command): if user.has_permissions(command): # [safer as it will not be removed by compiler user.execute(command) else: raise PermissionError(f'{user} is not authorized') # suitable error class
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code uses straightforward Python constructs, works the same with &lt;code&gt;__debug__&lt;/code&gt; set to &lt;code&gt;True&lt;/code&gt; or &lt;code&gt;False&lt;/code&gt; and raises clear exceptions that can be handled with much more clarity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Achieving Zen
&lt;/h2&gt;

&lt;p&gt;The key takeaway from all of these examples is to never trust your users. Input provided by the users should not be serialized-deserialized, evaluated, executed or rendered. To be safe, you must be careful of what you write and thoroughly audit the code after its been written.&lt;/p&gt;

&lt;p&gt;Do you know what’s better than scanning for vulnerabilities in code after it’s been written? Getting vulnerabilities highlighted as soon as you write code with them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvhev8rkpmmh2uvgk6xuj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvhev8rkpmmh2uvgk6xuj.jpg" width="613" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Bandit
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://dzone.com/articles/top-7-static-code-analysis-tools" rel="noopener noreferrer"&gt;Static Code Analysis tools&lt;/a&gt; such as linters and vulnerability scanners can help you find a lot of issues before they get exploited in the wild. An excellent tool for finding security vulnerabilities in Python is &lt;a href="https://bandit.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;Bandit&lt;/a&gt;. Bandit goes through each file, generates an abstract syntax tree (AST) for it and then runs a whole slew of tests on this AST. Bandit can detect a whole bunch of vulnerabilities out-of-the-box and can also be extended for specific scenarios and compatibility with frameworks via plugins. As a matter of fact, Bandit is capable of detecting all of the aforementioned security shortcomings.&lt;/p&gt;

&lt;p&gt;If you’re a Python developer, I cannot recommend Bandit enough. I could write a whole article extolling its virtues. I might even do that.&lt;/p&gt;

&lt;h3&gt;
  
  
  DeepSource
&lt;/h3&gt;

&lt;p&gt;You should also consider automating this entire audit and review process using code review automation tools like DeepSource that scans your code, on every commit and for every PR, through it’s linters and security analyzers and can automatically fix a multitude of issues. &lt;a href="https://deepsource.io/" rel="noopener noreferrer"&gt;DeepSource&lt;/a&gt; also has its own custom-built analyzers for most languages that are constantly improved and kept up-to-date. And it’s &lt;a href="https://deepsource.io/docs/analyzer/python.html" rel="noopener noreferrer"&gt;incredibly easy to set up&lt;/a&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version = 1

[[analyzers]]
name = "python"
enabled = true

  [analyzers.meta]
  runtime_version = "3.x.x"
  max_line_length = 80

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

&lt;/div&gt;



&lt;p&gt;Who knew it could be so simple?&lt;/p&gt;

&lt;p&gt;Experience the zen of Python, and be careful not to let black-hats disturb your peace!&lt;/p&gt;

</description>
      <category>python</category>
      <category>pythonsecurity</category>
    </item>
    <item>
      <title>5 JavaScript Static Analysis Tools</title>
      <dc:creator>Saif Sadiq</dc:creator>
      <pubDate>Tue, 09 Feb 2021 14:58:39 +0000</pubDate>
      <link>https://forem.com/saifsadiq1995/5-javascript-static-analysis-tools-30ik</link>
      <guid>https://forem.com/saifsadiq1995/5-javascript-static-analysis-tools-30ik</guid>
      <description>&lt;p&gt;With the rise of modern software development practices, the prominence of static analysis has grown. Static code analysis allows developers to improve the codebase's readability and consistency while finding possible bugs and anti-patterns. &lt;a href="https://dzone.com/articles/top-7-static-code-analysis-tools" rel="noopener noreferrer"&gt;Static analysis tools&lt;/a&gt; help us to validate the modern development standards and assess the quality of the same.&lt;/p&gt;

&lt;p&gt;A majority of the software development teams, across the world, have been using static code analysis tools. Static code analysis identifies bad and redundant code and fixes it before it lands in production. With automated static analysis, we don't need to rely on dynamic analysis, where the code gets executed on a processor to identify bugs.&lt;/p&gt;

&lt;p&gt;Let's take a look at some of the best JavaScript static analysis tools that you can make use of.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use Static Analysis for JavaScript?
&lt;/h3&gt;

&lt;p&gt;The Javascript ecosystem covering almost every development need has gathered pace for the past few years. With static analysis, we can easily maintain the code quality with little effort.&lt;/p&gt;

&lt;p&gt;Bugs and duplicated code is retrieved and fixed, with code insights generated at every stage of development. It allows the developers to keep track of the blockers they might face in the code and possibly fix them, thus eliminating a pain point.&lt;/p&gt;

&lt;h3&gt;
  
  
  DeepSource
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://deepsource.io/" rel="noopener noreferrer"&gt;DeepSource&lt;/a&gt; is one of the most popular tools for static analysis, providing tracking over 800+ potential issues, like unused variables, empty functions, usage of Script URLs, and more in JavaScript codebase. DeepSource JavaScript analyzer currently supports a wide variety of Javascript libraries and frameworks like ReactJS, VueJS, AngularJS, Angular, Ember, and more, along with various ECMAScript versions and Typescript. If you are following a style guide, DeepSource provides support for that as well, along with the module system.&lt;/p&gt;

&lt;p&gt;DeepSource strictly enforces &lt;a href="https://eslint.org/docs/rules/" rel="noopener noreferrer"&gt;ESLint core JavaScript rules&lt;/a&gt;, which allow us to identify bugs, anti-patterns, and non-performant code. &lt;/p&gt;

&lt;p&gt;Some key features of DeepSource include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single file configuration.&lt;/li&gt;
&lt;li&gt;Highlight important metrics like documentation coverage and dependency.&lt;/li&gt;
&lt;li&gt;Auto-fix for common issues.&lt;/li&gt;
&lt;li&gt;Code metrics tracking and reporting.&lt;/li&gt;
&lt;li&gt;Analysis of every pull request and commit.&lt;/li&gt;
&lt;li&gt;Integrated dashboard with issue descriptions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These features make DeepSource a lucrative choice for static analysis and provide a go-to-option for code analysis. With the analyzers working at file-level and repository-level, you would never have to worry in the future about maintaining your Javascript code.&lt;/p&gt;

&lt;h3&gt;
  
  
  DeepScan
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://deepscan.io/" rel="noopener noreferrer"&gt;DeepScan&lt;/a&gt; provides automated tracking of issues in the JavaScript codebase through static analysis. DeepScan supports a wide range of Javascript libraries and frameworks like React, Angular, and Vue and banks upon its data-flow analysis to find the code execution flow and issues. It also provides a general grade for the project you are working on to find ideas for improving the codebase quality.&lt;/p&gt;

&lt;p&gt;Some key features of DeepScan includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrated dashboard for issue tracking.&lt;/li&gt;
&lt;li&gt;Real-Time collaboration with team activity.&lt;/li&gt;
&lt;li&gt;Active analysis over the codebase.&lt;/li&gt;
&lt;li&gt;Usage of control flow graph for code execution.&lt;/li&gt;
&lt;li&gt;Grade calculation through issue density tracking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DeepScan is an active choice for developers and enterprise Teams for managing their code quality. Their static analysis goes beyond ESLint, providing more coverage and issue tracking, making it a definite choice to identify tricky issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  LGTM
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://lgtm.com/" rel="noopener noreferrer"&gt;LGTM&lt;/a&gt; states its mission "to promote community-driven security analysis" and has made it possible through automated issue and vulnerability checking. LGTM banks upon CodeQL to drive its issue tracking and finding common bugs that occur across the codebase. LGTM supports an integrated dashboard for real-time analysis, along with issue personalization, to help teams focus on issues that matter to them.&lt;/p&gt;

&lt;p&gt;LGTM supports various general-purpose programming languages, with Javascript being prominent. Its issue tracking is prioritized intelligently, which gives it a specific edge over other Static analysis Tools. &lt;/p&gt;

&lt;p&gt;Some key features of LGTM are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provides SemmleQL to write our Code Analysis Queries.&lt;/li&gt;
&lt;li&gt;Commits are checked every day.&lt;/li&gt;
&lt;li&gt;Provides a REST API to integrate with the workflow.&lt;/li&gt;
&lt;li&gt;Provides real-time project alerts and suppression.&lt;/li&gt;
&lt;li&gt;Analyzed over original repositories, not forks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;LGTM banks upon intelligent detection, which is made possible by analyzing different codebases. Thus it highlights an alert if we introduce a new bug or vulnerability. With granular access to a user dashboard, LGTM is a definite go for maintainers looking for a specific holdover code analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  SonarCloud
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://sonarcloud.io/" rel="noopener noreferrer"&gt;SonarCloud&lt;/a&gt; is yet another static analysis tool that aims to champion quality code among software projects. Featuring an IDE extension, named SonarLint, and other features like bug and code smell detection and continuous inspection, SonarCloud is one of the favorite go-to tools. SonarCloud supports several general-purpose programming languages, with Javascript in prominence.&lt;/p&gt;

&lt;p&gt;SonarCloud can be integrated with CI Pipelines like GitHub Actions and Azure DevOps, to ensure that bad code never lands in production. &lt;/p&gt;

&lt;p&gt;Some key features of SonarCloud are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access to the project dashboard and the project metrics.&lt;/li&gt;
&lt;li&gt;Features &lt;code&gt;Go/No&lt;/code&gt; Go quality Gate while analyzing code.&lt;/li&gt;
&lt;li&gt;Continuous inspection over all major Git providers.&lt;/li&gt;
&lt;li&gt;IDE extension named SonarLint available for better use.&lt;/li&gt;
&lt;li&gt;Supported by TravisCI, GitLabCI, CircleCI, and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tool keeps track of code maintainability, reliability, coverage, and more while aiming to accelerate the reviews from maintainers. With security hotspots as an additional feature, it can provide broader coverage to help developers understand the issues and leaks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Codacy
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.codacy.com/" rel="noopener noreferrer"&gt;Codacy&lt;/a&gt; is one of the most popular static analysis tools providing coverage over issues such as code duplication, complexity, and more. Codacy is integrated with ESLint JavaScript linter to provide quick access to potential issues and bugs, on an integrated dashboard.&lt;/p&gt;

&lt;p&gt;With Codacy, you can add specific repositories you have access to or have forked, and Codacy starts analyzing your code for bugs and style Issues. &lt;/p&gt;

&lt;p&gt;Some key features of Codacy include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automated code reviews and issue tracking.&lt;/li&gt;
&lt;li&gt;Integration with various Git providers.&lt;/li&gt;
&lt;li&gt;Provides code standardization and user management.&lt;/li&gt;
&lt;li&gt;Supported in various workflows and CI integrations.&lt;/li&gt;
&lt;li&gt;Provides self-hosted services as well.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Codacy will re-analyze your source code with every push, which eases code reviews and analysis. With a supporting community, Codacy is gaining large traction among developers for code Reviews and analysis.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>staticanalysis</category>
      <category>codereviews</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Java Code Quality Tools Recommended by Developers</title>
      <dc:creator>Saif Sadiq</dc:creator>
      <pubDate>Mon, 08 Feb 2021 05:40:27 +0000</pubDate>
      <link>https://forem.com/saifsadiq1995/java-code-quality-tools-recommended-by-developers-3j3e</link>
      <guid>https://forem.com/saifsadiq1995/java-code-quality-tools-recommended-by-developers-3j3e</guid>
      <description>&lt;p&gt;The best way to protect your Java code from avoidable bugs is to use static code analysis tools that can help you find and fix problematic code before it reaches production. Let's look at some popular static code analysis tools that can be used to test code from a number of different angles.&lt;/p&gt;

&lt;h2&gt;
  
  
  DeepSource
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://deepsource.io/" rel="noopener noreferrer"&gt;DeepSource&lt;/a&gt; delivers what is probably the best static code analysis you can find for Java. The &lt;a href="https://deepsource.io/docs/analyzer/java.html" rel="noopener noreferrer"&gt;DeepSource Java analyzer&lt;/a&gt; detects 190+ code quality issues, including performance bugs, security risks, bug risks, and anti-patterns. Currently, It supports Gradle Java projects, and in the future, DeepSource will add support for Maven and Android too. DeepSource is also working on bringing Autofix support to the Java analyzer, which will let developers fix issues without writing a single code line.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detects more than 170 code quality issues.&lt;/li&gt;
&lt;li&gt;OpenJDK versions 8 to 14 are currently supported.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Integration:&lt;/strong&gt; Gradle&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Licensing:&lt;/strong&gt; Free to use for open-source, Students, and Non-Profit Organisations. &lt;a href="https://deepsource.io/pricing/" rel="noopener noreferrer"&gt;Paid plans starts from 12 USD user/month&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  SonarQube
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.sonarqube.org/" rel="noopener noreferrer"&gt;SonarQube&lt;/a&gt; is the open-source suite of java static code analysis tools that combines the features of tools such as FindBugs and PMD. SonarQube has very intuitive dashboards that maintain history to help developers track Java code quality over time. SonarQube uses advanced techniques like pattern matching and dataflow analysis to analyze code and identify code smells, bugs, and security vulnerabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It has 597 rules to detect various code quality issues.&lt;/li&gt;
&lt;li&gt;Java language versions supported up-to 14.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Integration:&lt;/strong&gt; Maven, Gradle, Ant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Licensing:&lt;/strong&gt; Community edition is free and open source. &lt;a href="https://www.sonarsource.com/plans-and-pricing/" rel="noopener noreferrer"&gt;License for commercial editions starts at €120&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  SpotBugs
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://spotbugs.github.io/" rel="noopener noreferrer"&gt;SpotBugs&lt;/a&gt; is FindBugs' successor. It is a Java static code analysis tool that examines JVM bytecode and finds traces of potential errors and security vulnerabilities by identifying coding defects. These defects are reported as warnings, but not all of the warnings reported are necessarily defects, e.g., warnings referred to possible performance issues. The latest version reports more than 400 warnings, and all warnings are classified into four ranks: (i) scariest, (ii) scary, (iii) troubling, (iv) of concern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detects more than 400 bug patterns in code.&lt;/li&gt;
&lt;li&gt;SpotBugs requires JRE (or JDK) 1.8.0 or later to run. However, it can analyze programs compiled for any version of Java, from 1.0 to 1.9.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Integration:&lt;/strong&gt; Ant, Maven, Gradle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Licensing:&lt;/strong&gt; &lt;a href="https://github.com/spotbugs/spotbugs" rel="noopener noreferrer"&gt;Free and open-source&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  PMD
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pmd.github.io/" rel="noopener noreferrer"&gt;PMD&lt;/a&gt; analyzes Java source code, validates it with its list of rules, and reports offending lines to the user. PMD can determine common issues such as the hard coding of passwords and IP addresses, the use of the &lt;code&gt;forEach&lt;/code&gt; loop instead of a traditional &lt;code&gt;for&lt;/code&gt; loop, and code that seems to violate the &lt;a href="https://en.wikipedia.org/wiki/Law_of_Demeter" rel="noopener noreferrer"&gt;Law of Demeter&lt;/a&gt; or implement the God Class anti-pattern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More than 250 rules to detect issues in java.&lt;/li&gt;
&lt;li&gt;language support till Java 13&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Integration:&lt;/strong&gt; Maven, Gradle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Licensing:&lt;/strong&gt; &lt;a href="https://pmd.github.io/#downloads" rel="noopener noreferrer"&gt;Free and open-source&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  EclEmma
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.jacoco.org/" rel="noopener noreferrer"&gt;EclEmma&lt;/a&gt;(based on the JaCoCo library) is a free Java code coverage tool for Eclipse. It is a toolkit for measuring code coverage in a java code base and presenting coverage data through visual reports. It highlights the lines of code and the total percentage of code executed, and tracks both line and branch coverage. EclEmma helps developers assess code that has not been adequately tested and focuses on low coverage areas. It supports 3 types of report formats: HTML, XML &amp;amp; CSV.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supports Java class files from version 1.0 to 14.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Integration:&lt;/strong&gt; Ant, Maven.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Licensing:&lt;/strong&gt; &lt;a href="https://www.jacoco.org/download.html" rel="noopener noreferrer"&gt;Free and open-source&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Checkstyle
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://checkstyle.sourceforge.io/" rel="noopener noreferrer"&gt;Checkstyle&lt;/a&gt; is a java static analysis tool that helps developers automate the process of defining a style guide and enforcing coding standards within the enterprise. Checkstyle identifies rules that are violated and help them fix and reformat the code with IDEs such as Eclipse, IntelliJ IDEA or NetBeans. Categories of violations include wildcard imports and whitespace usage around generic tokens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More than 180 checks to enforce java coding style.&lt;/li&gt;
&lt;li&gt;Language support till Java 14.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Integration:&lt;/strong&gt; Ant, Maven.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Licensing:&lt;/strong&gt; &lt;a href="https://checkstyle.org/licenses.html" rel="noopener noreferrer"&gt;Free and open-source&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  JArchitect
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.jarchitect.com/" rel="noopener noreferrer"&gt;JArchitect&lt;/a&gt; is a Java static analysis tool that evaluates code metrics such as the number of method parameters, variables and lines of code, cyclomatic complexity, afferent and efferent coupling, and so forth. It measures, queries, and visualizes your code and avoid unexpected issues, technical debt, and complexity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Language support from Java 8 to 13.&lt;/li&gt;
&lt;li&gt;More than 450 rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Integration:&lt;/strong&gt; Maven, Gradle, Ant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Licensing:&lt;/strong&gt; Free Trial for 14days, Open source license for Free for Non-commercial open source software projects, Personal License - $149, Developer Edition - $299, Build Machine - $549. Submit the form &lt;a href="https://www.jarchitect.com/purchase" rel="noopener noreferrer"&gt;here&lt;/a&gt; to get the pertinent pricing and info for JArchitect.&lt;/p&gt;

&lt;h2&gt;
  
  
  JUnit
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://junit.org/junit5/" rel="noopener noreferrer"&gt;JUnit&lt;/a&gt; is a popular unit testing framework for Java development projects that allows developers to write and run unit tests for Java 8 and above. JUnit tests the state and the behavior of the code with simple yet powerful assertion statements. It is easy to get started with JUnit, and It offers a variety of additional features using annotations for more complex scenarios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JUnit 5(latest release) requires Java 8 (or higher) at runtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Integration:&lt;/strong&gt; Maven, Gradle, Ant&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Licensing:&lt;/strong&gt; &lt;a href="https://junit.org/junit5/docs/current/user-guide/#overview-getting-started-junit-artifacts" rel="noopener noreferrer"&gt;Free and open-source&lt;/a&gt;&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>java</category>
      <category>programming</category>
      <category>coding</category>
    </item>
  </channel>
</rss>
