<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: SourceLevel</title>
    <description>The latest articles on DEV Community by SourceLevel (@sourcelevel).</description>
    <link>https://dev.to/sourcelevel</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%2Forganization%2Fprofile_image%2F864%2F74ca8045-6ab7-45a7-9d65-410a9eb670af.png</url>
      <title>DEV Community: SourceLevel</title>
      <link>https://dev.to/sourcelevel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sourcelevel"/>
    <language>en</language>
    <item>
      <title>Mastering Git: The lesser-known commands you could be using (or not)</title>
      <dc:creator>Weverton Timoteo</dc:creator>
      <pubDate>Wed, 16 Aug 2023 12:52:38 +0000</pubDate>
      <link>https://dev.to/sourcelevel/mastering-git-the-lesser-known-commands-you-could-be-using-or-not-1234</link>
      <guid>https://dev.to/sourcelevel/mastering-git-the-lesser-known-commands-you-could-be-using-or-not-1234</guid>
      <description>&lt;p&gt;Navigating the vast landscape of Git commands can sometimes feel like venturing into a bustling marketplace where everyone seems to know the most popular stalls: &lt;strong&gt;&lt;code&gt;pull&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;commit&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;push&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;rebase&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;stash&lt;/code&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;code&gt;checkout&lt;/code&gt;&lt;/strong&gt;. These commands are the cornerstone of everyday version control tasks, often forming the basis of a developer's Git journey. But amidst this bustling crowd of common commands, have you ever paused to wonder, "What else can Git do?" Have you ever caught yourself in the quiet moments, pondering the existence of lesser-known Git commands that could potentially transform your workflow?&lt;/p&gt;

&lt;p&gt;Join us as we navigate through these unexplored corners of Git, revealing commands that may have eluded your attention but can significantly enhance your mastery of version control.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;git switch&lt;/code&gt;: a fresh approach to branch management
&lt;/h2&gt;

&lt;p&gt;While &lt;code&gt;git checkout&lt;/code&gt; remains a versatile command for various purposes, it also comes with the potential to inadvertently discard changes or create confusion. Enter &lt;code&gt;git switch&lt;/code&gt;, introduced in Git version 2.23 as a dedicated tool for branch management.&lt;/p&gt;

&lt;p&gt;Unlike the all-encompassing nature of &lt;code&gt;git checkout&lt;/code&gt;, &lt;code&gt;git switch&lt;/code&gt; focuses solely on simplifying branch-related operations. Its purpose is straightforward: to provide a clearer and safer way to switch branches, reducing the risk of errors and data loss.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Consider Using &lt;code&gt;git switch&lt;/code&gt;?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you've ever felt the unease of accidentally losing your work while using &lt;code&gt;git checkout&lt;/code&gt;, &lt;code&gt;git switch&lt;/code&gt; offers a more reassuring alternative. This command offers explicit error messages and is designed to minimize the chances of unintentional changes.&lt;/p&gt;

&lt;p&gt;Here are some examples of how you can use &lt;code&gt;git switch&lt;/code&gt; effectively:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create and switch to a new branch with &lt;code&gt;git switch -c my-new-branch&lt;/code&gt;, using the current commit as its base.&lt;/li&gt;
&lt;li&gt;Swiftly switch to the &lt;code&gt;main&lt;/code&gt; branch using &lt;code&gt;git switch main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Return to the previous branch by employing &lt;code&gt;git switch -&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;git bisect&lt;/code&gt;: tracking bugs down
&lt;/h2&gt;

&lt;p&gt;In software development, locating a bug can be akin to finding a needle in a haystack. But fear not – the &lt;code&gt;git bisect&lt;/code&gt; command is here to help. It's like a guided missile for tracking down the elusive bug.&lt;/p&gt;

&lt;p&gt;Here's how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Identify Known States&lt;/strong&gt;: First, you need to identify a "good" commit (when the code worked) and a "bad" commit (when the bug surfaced).&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Start Bisecting&lt;/strong&gt;: Begin the process with:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git bisect start
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mark Known Commits&lt;/strong&gt;: Tag the known "good" and "bad" commits:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git bisect good &amp;lt;good-commit&amp;gt;
git bisect bad &amp;lt;bad-commit&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Navigate Commits&lt;/strong&gt;: Git will automatically guide you to a commit between the two states. You test your code there. To see which commit you're at:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git log -n 1 --oneline
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Continue the Hunt&lt;/strong&gt;: Based on your test, you mark the commit as "good" or "bad":&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git bisect good  &lt;span class="c"&gt;# or git bisect bad&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Repeat Until Found&lt;/strong&gt;: Git will automatically move to the next commit within the narrowed range. You repeat the process until you've pinpointed the bug's source.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;End the Hunt&lt;/strong&gt;: When you've found the problematic commit:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git bisect reset
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This concludes the process and takes you back to the clean state and the previous &lt;code&gt;HEAD&lt;/code&gt; before you started the &lt;code&gt;bisect&lt;/code&gt; process.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;git notes&lt;/code&gt;: Enhancing Commit Context
&lt;/h2&gt;

&lt;p&gt;Git notes provide a versatile way to attach supplementary information to a commit without altering the commit itself.&lt;/p&gt;

&lt;p&gt;Imagine you and your team found yourselves in a Git repository with less-than-ideal commit messages. Often, commits lack the necessary clarity to explain their purpose effectively. This feature allows you to enrich commits with essential context without the need to modify or rewrite commit SHA1.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to Utilize Git Notes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stored locally within &lt;code&gt;.git/refs/notes&lt;/code&gt;, Git notes remain separate from the main commit data. By default, they are not pushed to the remote repository. However, this can be changed by pushing them in a manner similar to &lt;code&gt;git tag&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;git push origin refs/notes/commits
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To retrieve existing notes from a remote repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git fetch origin refs/notes/commits:refs/notes/commits
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding Notes to Commits
&lt;/h3&gt;

&lt;p&gt;You can easily add notes to existing commits using the &lt;code&gt;git notes add&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git notes add -m "Introduce irreversible migrations at this point" &amp;lt;commit-sha1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;m&lt;/code&gt; option is optional. If omitted, your default text editor will open, allowing for a more detailed explanation.&lt;/li&gt;
&lt;li&gt;If you skip providing &lt;code&gt;&amp;lt;commit-sha1&amp;gt;&lt;/code&gt;, the &lt;code&gt;HEAD&lt;/code&gt; commit will be assumed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Removing Notes
&lt;/h3&gt;

&lt;p&gt;Removing notes is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git notes remove &amp;lt;commit-SHA1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Listing and Viewing Notes
&lt;/h3&gt;

&lt;p&gt;To list all existing notes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git notes list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more in-depth insight into a specific note:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git notes show &amp;lt;commit-SHA1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, GitHub no longer displays &lt;strong&gt;&lt;code&gt;git notes&lt;/code&gt;&lt;/strong&gt; in its UI. This adjustment, in my opinion, reflects the limited usage of these commands. By making this change, GitHub appears to be fostering a culture of encouraging developers to consistently produce improved commits without the temptation to revisit or dwell on the details of previous commits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sharing Diffs: &lt;code&gt;git diff&lt;/code&gt; + &lt;code&gt;git apply&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Consider a common scenario: a pair programming session happens to address a specific problem. During this interaction, the most experienced developer takes the lead, demonstrating a viable solution by implementing essential changes.&lt;/p&gt;

&lt;p&gt;As the collaborative session unfolds, these changes become crucial building blocks for the solution. To facilitate the smooth continuation of this collaborative effort, Git provides two essential commands: &lt;code&gt;git diff&lt;/code&gt; and &lt;code&gt;git apply&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once the demonstration is complete, and the necessary changes are in place, you can encapsulate these modifications within a concise patch file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git diff &amp;gt; ~/Downloads/pair_programming_session.patch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other developer can then seamlessly incorporate these modifications into their local codebase using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git apply pair_programming_session.patch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this manner, Git offers an efficient mechanism for transferring insights and progress gained from collaborative coding sessions, ensuring that developmental strides are effectively communicated.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Embrace Unfamiliar Commands&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I understand that consistently learning new tools and programming languages can be challenging. However, it's important to recognize that &lt;strong&gt;&lt;code&gt;git&lt;/code&gt;&lt;/strong&gt; serves as a tool for delivering your work. Thus, make it a practice to regularly peruse the official documentation and keep your &lt;strong&gt;&lt;code&gt;git&lt;/code&gt;&lt;/strong&gt; CLI updated to fully leverage its capabilities and embrace new features.&lt;/p&gt;

&lt;p&gt;Have you ever considered integrating these commands into your workflow? I hope you've found something useful or at least identified a command to avoid using.&lt;/p&gt;

</description>
      <category>git</category>
      <category>codereview</category>
      <category>bestpractices</category>
      <category>github</category>
    </item>
    <item>
      <title>The Perfect Git Commit Quest</title>
      <dc:creator>Weverton Timoteo</dc:creator>
      <pubDate>Mon, 07 Aug 2023 19:16:44 +0000</pubDate>
      <link>https://dev.to/sourcelevel/the-perfect-git-commit-quest-1kjm</link>
      <guid>https://dev.to/sourcelevel/the-perfect-git-commit-quest-1kjm</guid>
      <description>&lt;h2&gt;
  
  
  The Importance of Writing a Good Commit Message
&lt;/h2&gt;

&lt;p&gt;When it comes to Git commits, a well-crafted message is more than just a technical necessity. It serves as documentation, providing essential context for future reference. During a &lt;strong&gt;&lt;code&gt;git show&lt;/code&gt;&lt;/strong&gt;, a descriptive commit message offers valuable insights into the changes made, aiding comprehension and troubleshooting.&lt;/p&gt;

&lt;p&gt;Furthermore, communicating with accessible peers about implementation and modifications opens doors for constructive collaboration and alternative perspectives. Tech leads can also better understand your approach, enabling them to offer valuable advice on advancing the solution using alternate methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  Commit Title/Header/Subject
&lt;/h2&gt;

&lt;p&gt;The commit header should be concise, with a maximum length of 72 characters in GitHub, to avoid truncation with ellipsis. Ending the title with a period is unnecessary, as every character counts. Starting with an imperative mood verb, such as &lt;strong&gt;&lt;code&gt;Add&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;Fix&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;Remove&lt;/code&gt;&lt;/strong&gt;, or &lt;strong&gt;&lt;code&gt;Refactor&lt;/code&gt;&lt;/strong&gt;, sets a clear and actionable tone for the commit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Conventional Commits
&lt;/h3&gt;

&lt;p&gt;To provide even more context, consider following the &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/"&gt;Conventional Commits&lt;/a&gt; specification, which builds on the Angular Commit Guidelines. Prefix the title with specific keywords like fix, feature/feat, refactor, deploy, chore, docs, or test. Each prefix highlights the nature of the changes made.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;fix&lt;/strong&gt;: Represents a bug fix for your application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;feature&lt;/strong&gt; / &lt;strong&gt;feat&lt;/strong&gt;: Adds a new feature to your application or library.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;refactor&lt;/strong&gt;: A code change that neither fixes a bug nor adds a feature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;deploy&lt;/strong&gt;: Changes related to the deployment process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;chore&lt;/strong&gt;: Upgrades libraries and/or performs maintenance tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;docs&lt;/strong&gt;: Documentation-only changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;test&lt;/strong&gt;: Adding missing tests or correcting existing tests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feature(shopping-cart): Add remove button

User can now remove the item entirely from shopping cart.

On clicking the button an animation transition will be
displayed.

https://linear.app/&amp;lt;workspace&amp;gt;/issue/A-123/add-ability-to-remove-item-from-shopping-cart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Commit Body
&lt;/h2&gt;

&lt;p&gt;Adding a line break between the header and the body helps organize information clearly. You can mention the files affected by the changes and explain the purpose and accomplishments of the commit. Keeping individual lines within 100 characters enhances readability.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a linebreak between Header and the body&lt;/li&gt;
&lt;li&gt;You can mention which files are included in these changes&lt;/li&gt;
&lt;li&gt;Explain why and what was accomplished in this commit&lt;/li&gt;
&lt;li&gt;Many tools recommends that any line cannot be longer than 100 characters, making each one more readable&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Commit message conventions (Annotations)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Co-authored-by&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Marking your pairs during commits is essential for effective collaboration, especially in pair programming (eXtreme Programming). When the author accepts the &lt;code&gt;suggestions&lt;/code&gt; block made during a Pull Request review, GitHub doesn’t use &lt;code&gt;Suggested-by&lt;/code&gt; convention, instead it uses &lt;code&gt;Co-authored-by&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;While there are &lt;a href="https://archive.kernel.org/oldwiki/git.wiki.kernel.org/index.php/CommitMessageConventions.html"&gt;more conventions to follow&lt;/a&gt;, in common workflows, using &lt;strong&gt;&lt;code&gt;Co-authored-by&lt;/code&gt;&lt;/strong&gt; is strongly recommended.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Commit?
&lt;/h2&gt;

&lt;p&gt;Committing early and often throughout development is highly recommended. Delaying commits until the end of the process can create challenges in organizing atomic commits, crafting a coherent narrative, and receiving timely feedback during the Code Review process. By committing regularly, you can easily create a Draft Pull/Merge Request to seek immediate peer input.&lt;/p&gt;

&lt;h2&gt;
  
  
  Staging the Changes
&lt;/h2&gt;

&lt;p&gt;Simplify your commit process with tools like &lt;strong&gt;&lt;a href="https://github.com/jesseduffield/lazygit"&gt;LazyGit&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://jonas.github.io/tig/"&gt;tig&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://desktop.github.com/"&gt;GitHub Desktop&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://www.git-tower.com/"&gt;Git Tower&lt;/a&gt;&lt;/strong&gt;, or &lt;strong&gt;&lt;a href="https://www.gitkraken.com/"&gt;GitKraken&lt;/a&gt;&lt;/strong&gt;. When making changes, think of each commit as a "package" that should be "revertable" through &lt;strong&gt;&lt;code&gt;git revert&lt;/code&gt;&lt;/strong&gt; without breaking the build or test suite. Run tests right after creating a commit to ensure changes do not disrupt the suite. To temporarily remove existing changes, use &lt;strong&gt;&lt;code&gt;git stash --include-untracked&lt;/code&gt;&lt;/strong&gt;, then remember to &lt;strong&gt;&lt;code&gt;git stash pop&lt;/code&gt;&lt;/strong&gt; and continue the commit process.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Forgot Something in the Previous Commit?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you missed including a change, you can easily remedy the situation with &lt;strong&gt;&lt;code&gt;git add&lt;/code&gt;&lt;/strong&gt; followed by &lt;strong&gt;&lt;code&gt;git commit --amend&lt;/code&gt;&lt;/strong&gt;. The &lt;strong&gt;&lt;code&gt;--amend&lt;/code&gt;&lt;/strong&gt; command picks up your previous commit message (don't forget to update the details about the inclusion) before pushing it with &lt;strong&gt;&lt;code&gt;git push&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Note that if you already pushed the commit, you'll need to use &lt;strong&gt;&lt;code&gt;git push -f&lt;/code&gt;&lt;/strong&gt; to replace the existing commit with the regenerated SHA1 commit from the amendment. If you're collaborating with others in the same branch, remind your peers to pull the changes, though no impact is expected if they haven't started working in this branch yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Art of Summarize: Drafting/Opening a Pull Request&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When working on a project for 2-5 days, summarizing your work in a Pull Request can be challenging. Leverage your well-crafted commit messages to read the story and provide concise summaries to your reviewers. Doing so not only streamlines the review process but also serves as documentation for future reference.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Tuning Your &lt;code&gt;git&lt;/code&gt; Command&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Ensure your &lt;strong&gt;&lt;code&gt;$EDITOR&lt;/code&gt;&lt;/strong&gt; is set to your favorite editor for &lt;strong&gt;&lt;code&gt;git commit&lt;/code&gt;&lt;/strong&gt; execution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;EDITOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;nvim&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also configure &lt;strong&gt;&lt;code&gt;core.editor&lt;/code&gt;&lt;/strong&gt; to open any &lt;strong&gt;&lt;code&gt;git&lt;/code&gt;&lt;/strong&gt; command in your preferred editor (Visual Studio Code in this example):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;git&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;global&lt;/span&gt; &lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;wait&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Use Templates for Commit Messages&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Simplify the git commit message structure by using templates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;git&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;global&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/.gitmessage.tx&lt;/span&gt;&lt;span class="err"&gt;t
&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;git&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not sure how to start? Use this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Replace&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt; &lt;span class="na"&gt;imperative&lt;/span&gt;&lt;span class="err"&gt;),&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="na"&gt;50&lt;/span&gt; &lt;span class="na"&gt;chars&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;no&lt;/span&gt; &lt;span class="na"&gt;period&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="na"&gt;Keep&lt;/span&gt; &lt;span class="na"&gt;this&lt;/span&gt; &lt;span class="na"&gt;blankline&lt;/span&gt; &lt;span class="na"&gt;above&lt;/span&gt; &lt;span class="na"&gt;but&lt;/span&gt; &lt;span class="na"&gt;replace&lt;/span&gt; &lt;span class="na"&gt;this&lt;/span&gt; &lt;span class="na"&gt;line&lt;/span&gt; &lt;span class="na"&gt;and&lt;/span&gt; &lt;span class="na"&gt;below&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="na"&gt;by&lt;/span&gt; &lt;span class="na"&gt;your&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt; &lt;span class="na"&gt;explaining&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="na"&gt;what&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="na"&gt;and&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="na"&gt;whay&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;not&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="na"&gt;how&lt;/span&gt;&lt;span class="err"&gt;*)&lt;/span&gt; &lt;span class="na"&gt;no&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="na"&gt;more&lt;/span&gt; &lt;span class="na"&gt;than&lt;/span&gt; &lt;span class="na"&gt;100&lt;/span&gt; &lt;span class="na"&gt;chars&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="na"&gt;Here&lt;/span&gt; &lt;span class="na"&gt;is&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt; &lt;span class="na"&gt;footer&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;include&lt;/span&gt; &lt;span class="na"&gt;the&lt;/span&gt; &lt;span class="na"&gt;Git&lt;/span&gt; &lt;span class="na"&gt;Conventions&lt;/span&gt; &lt;span class="na"&gt;annotations&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="na"&gt;you&lt;/span&gt; &lt;span class="na"&gt;prefer&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;such&lt;/span&gt; &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; 
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="na"&gt;Co-authored-by&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;noreply&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;github&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;com&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Journey to Better Commits: Level Up! Quest Completed!
&lt;/h2&gt;

&lt;p&gt;In the journey of perfecting your Git commits, you've unlocked the art of crafting informative and context-rich messages that enhance your development process. Embracing Conventional Commits, staging your changes, and committing early and often, you've laid the foundation for collaborative and efficient code reviews.&lt;/p&gt;

&lt;p&gt;Before marking your Pull Request as “Ready for review”, check this blog post: '&lt;a href="https://sourcelevel.io/blog/10-items-to-check-before-assigning-a-pull-request-to-someone-plus-a-bonus"&gt;10 Items to Check Before Assigning a Pull Request to Someone&lt;/a&gt;.' Should your team seek more opportunities for reviews, venture into the realm of '&lt;a href="https://sourcelevel.io/blog/creating-code-reviews-opportunities"&gt;Creating Code Review Opportunities&lt;/a&gt;' for valuable insights. &lt;strong&gt;Continue your quest for better commits and conquer new challenges, kupo!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>codereview</category>
      <category>bestpractices</category>
      <category>github</category>
    </item>
    <item>
      <title>Creating Code Reviews opportunities</title>
      <dc:creator>Weverton Timoteo</dc:creator>
      <pubDate>Mon, 31 Jul 2023 18:40:52 +0000</pubDate>
      <link>https://dev.to/sourcelevel/creating-code-reviews-opportunities-2a0g</link>
      <guid>https://dev.to/sourcelevel/creating-code-reviews-opportunities-2a0g</guid>
      <description>&lt;p&gt;Picture this: Your team is working on a project, and Pull/Merge Requests are piling up without any reviews. Code Reviews are not just a formality; they are an incredible opportunity to learn, grow, motivate, mentor, debate, and share knowledge. So, how can you turn this situation around and make the most out of Code Reviews to enhance your development process?&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding Time Slots - Optimizing Your Review Routine
&lt;/h2&gt;

&lt;p&gt;Reviewing code shouldn't be an added burden to your team's daily tasks. Instead, seamlessly integrate it into your workflow by using available time slots. Take advantage of moments like coffee breaks, filling your water bottle, grabbing a coffee, or just before lunchtime and wrapping up the day. By incorporating these review moments into your daily rhythm, you ensure consistent Code Reviews without disrupting your workflow, promoting a culture of continuous improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Interruptions to Your Advantage
&lt;/h2&gt;

&lt;p&gt;Interruptions are unavoidable, but they can also be opportunities for the Code Review process. When interrupted, use the time to review code. Seamlessly integrate Code Reviews into various workflow transitions, such as finishing user stories, pulling new user stories, opening pull requests, merging pull requests, and ending pair programming sessions.&lt;/p&gt;

&lt;p&gt;Dedicate specific time slots for reviews to ensure a focused approach. Avoid rushing reviews under time pressure; communicate time constraints and plan for thorough reviews. Prioritize quality over quantity; thoroughly review a few Pull Requests rather than performing hasty, superficial reviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maximizing Collaboration: Pair Programming's Hidden Gem - Code Reviews
&lt;/h2&gt;

&lt;p&gt;Pair programming fosters collaboration and knowledge sharing. At the end of a session, leverage this opportunity for collaborative Code Reviews. Engage in open discussions, share feedback, document decisions, and celebrate successes, boosting collaboration, code quality, and a culture of continuous learning and growth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Empowering Psychological Safety in Code Review Discussions
&lt;/h2&gt;

&lt;p&gt;Prioritize psychological safety to enhance team collaboration and code quality. Encourage openness and embrace diverse perspectives during reviews. Deliver feedback respectfully and focus on the code, not the developer. Lead by example, treat mistakes as learning opportunities, and provide guidance to support less experienced team members. Welcome questions and set clear expectations for Code Reviews.&lt;/p&gt;

&lt;p&gt;Empowering psychological safety encourages questions and fosters a welcoming environment for other reviewers to participate and interact. Your team can foster a culture of trust, continuous improvement, and code excellence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimizing Code Reviews with Available Tools
&lt;/h2&gt;

&lt;p&gt;Streamline the Code Review process and avoid overlooking reviews by using available tools. GitHub Reminders, integrated with Slack, improve communication and collaboration. Assigned "Reviewers" receive direct messages, ensuring timely notifications. Configure a Slack channel to receive daily reminders, helping the team stay informed and address reviews promptly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fostering Accountability through Code Reviews
&lt;/h2&gt;

&lt;p&gt;Code Reviews promote accountability within your team. As "Reviewers," team members take ownership of the codebase, ensuring it meets the team's standards. A culture of mutual support and continuous improvement emerges, enhancing overall productivity and code quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Embrace a Strong Code Review Culture
&lt;/h2&gt;

&lt;p&gt;Before assigning a Pull Request to someone, consider taking a moment to review it yourself. By ensuring your PR is well-prepared and clear, you set the stage for efficient and effective feedback sessions. To optimize your Code Review process and discover essential tips for preparing Pull Requests, explore our blog post &lt;strong&gt;&lt;a href="https://sourcelevel.io/blog/10-items-to-check-before-assigning-a-pull-request-to-someone-plus-a-bonus"&gt;here&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With a proactive approach to Code Reviews and a commitment to continuous learning, your team will thrive in a collaborative and supportive environment.&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>codequality</category>
      <category>pullrequests</category>
      <category>github</category>
    </item>
    <item>
      <title>Sunsetting SourceLevel’s Automated Code Review feature: What’s next?</title>
      <dc:creator>Weverton Timoteo</dc:creator>
      <pubDate>Wed, 15 Jun 2022 20:13:05 +0000</pubDate>
      <link>https://dev.to/sourcelevel/sunsetting-sourcelevels-code-quality-feature-whats-next-15i1</link>
      <guid>https://dev.to/sourcelevel/sunsetting-sourcelevels-code-quality-feature-whats-next-15i1</guid>
      <description>&lt;p&gt;When we launched SourceLevel, we had a great focus on Automated Code Review, through 30+ Open Source linters (including support for Ruby, JavaScript, Elixir, Golang, PHP, Python, etc.). During product validation we have introduced some use case metrics which includes Work In Progress, Engagement, and Deliveries.&lt;/p&gt;

&lt;p&gt;Last year, we released a new product completely focused on Engineering Metrics. And we’ve decided to sunset the Automated Code Review feature, improving our Analytics product bringing visibility over every corner of the delivery pipeline in a Data &amp;amp; Analytics Solution for Engineering Teams.&lt;/p&gt;

&lt;p&gt;We still consider Code Quality metrics relevant, but we don’t think we should keep running the linters since a lot of free alternatives are available to be included in your Continuous Integration pipeline, such as &lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the future, we are considering importing issues identified by these runners through our API. We’d recommend including the linter that you use to your GitHub Actions pipeline or consider installing &lt;a href="https://danger.systems/"&gt;Danger.systems&lt;/a&gt; (which supports Ruby, Python, Swift, Kotlin, and JavaScript) for your organization.&lt;/p&gt;

&lt;p&gt;We’ll start contacting existing customers to notify about Automated Code Review sunset and schedule a turn-off customer-by-customer.&lt;/p&gt;

&lt;p&gt;Currently, Analytics is providing metrics for Software Engineering Management, to see a glimpse of what we offer, go to our &lt;a href="https://sourcelevel.io/engineering-metrics"&gt;Engineering Metrics page&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>linters</category>
      <category>engineeringops</category>
      <category>engineeringmanagement</category>
    </item>
    <item>
      <title>RuboCop: How to install and configure</title>
      <dc:creator>Gustavo Araujo</dc:creator>
      <pubDate>Tue, 15 Mar 2022 14:07:51 +0000</pubDate>
      <link>https://dev.to/sourcelevel/rubocop-how-to-install-and-configure-3cbi</link>
      <guid>https://dev.to/sourcelevel/rubocop-how-to-install-and-configure-3cbi</guid>
      <description>&lt;p&gt;That Code quality is important, and any high-performing team knows it, but do you follow a guideline to standardize your codebase and make sure that everyone is going and looking in the same direction?&lt;/p&gt;

&lt;p&gt;Making a brief introduction, this is the goal of a linter: A tool that analyzes your source code to identify programming errors, bugs, and suspicious constructions &lt;em&gt;(&lt;a href="https://en.wikipedia.org/wiki/Lint_(software)" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The main objective is to ensure that your code follows the same rules and practices, to look like the entire code was written by the same person.&lt;/p&gt;

&lt;p&gt;In a large variety of linters from Ruby, we have &lt;strong&gt;&lt;a href="https://github.com/rubocop/rubocop/" rel="noopener noreferrer"&gt;RuboCop&lt;/a&gt;&lt;/strong&gt; (available as a gem) that follows the best practices described in &lt;a href="https://rubystyle.guide/" rel="noopener noreferrer"&gt;The Ruby Style Guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the advantages of using a linter is to save time reviewing code because it prevents small issues like inconsistent variable names and practices during the development process. With that, the code review is more efficient, and it can be focused on implementations and features requirements.&lt;/p&gt;

&lt;p&gt;Starting using RuboCop is very straightforward and doesn’t depend on anyone else to setup it. You can install the gem and run it immediately during your workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;To install the RuboCop, it’s quick and easy. Let's consider here that all your Ruby environment is working, so just execute the following command to install the latest RuboCop version available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ gem install rubocop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;RuboCop officially supports the &lt;strong&gt;MRI 2.5+&lt;/strong&gt; and &lt;strong&gt;jRuby 9.2+&lt;/strong&gt; implementations. You can also install directly in the project using Bundler, adding the gem to your &lt;code&gt;Gemfile&lt;/code&gt;, and then run &lt;code&gt;bundle install&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;The RuboCop behavior can be controlled in the &lt;code&gt;.rubocop.yml&lt;/code&gt; file in the root path where you want to execute it. In this file, you can enable/disable certain cops (rules) or change their behavior.&lt;/p&gt;

&lt;p&gt;All cops are grouped into departments: &lt;strong&gt;Style&lt;/strong&gt;, &lt;strong&gt;Layout&lt;/strong&gt;, &lt;strong&gt;Lint&lt;/strong&gt;, &lt;strong&gt;Naming&lt;/strong&gt;, &lt;strong&gt;Security&lt;/strong&gt;, &lt;strong&gt;Metrics&lt;/strong&gt;, &lt;strong&gt;Migration&lt;/strong&gt;, &lt;strong&gt;Bundler,&lt;/strong&gt; and &lt;strong&gt;Gemspec&lt;/strong&gt;. You can read about the cops and their departments in the &lt;a href="https://docs.rubocop.org/rubocop/cops.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;. For reference purposes, check the configuration file that we use in &lt;a href="https://sourcelevel.io/" rel="noopener noreferrer"&gt;SourceLevel&lt;/a&gt; in our &lt;a href="https://github.com/sourcelevel/linters/blob/main/.rubocop.yml" rel="noopener noreferrer"&gt;linter’s configuration repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.rubocop.yml&lt;/code&gt; file has the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inherit_from: ../.rubocop.yml

require: rubocop-rails

Style/Encoding:
  Enabled: false

Layout/LineLength:
  Max: 99

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

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note 1: We’re using &lt;code&gt;inherit_from&lt;/code&gt; to inherit all defined cops in the other file. See more in the &lt;a href="https://docs.rubocop.org/rubocop/configuration.html#inheritance" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;br&gt;
Note 2: If you’re using **Rails&lt;/em&gt;&lt;em&gt;, it’s important to require the &lt;code&gt;rubocop-rails&lt;/code&gt; extension (remember to add it to your &lt;code&gt;Gemfile&lt;/code&gt;), which will force RuboCop to follow the &lt;a href="https://rails.rubystyle.guide/" rel="noopener noreferrer"&gt;conventions and good practices&lt;/a&gt; defined by the Rails community.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;By default, when executed, the RuboCop looks for &lt;code&gt;.rubocop.yml&lt;/code&gt; in the current directory, then in your home path (&lt;code&gt;~/.rubocop.yml&lt;/code&gt;), and in the last case it will use the defaults. More details about RuboCop’s configuration file can be found on the &lt;a href="https://docs.rubocop.org/rubocop/configuration.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to create your configuration file, which I encourage, a good starting point is to use the &lt;a href="https://github.com/rubocop/rubocop/blob/master/.rubocop.yml" rel="noopener noreferrer"&gt;configuration&lt;/a&gt; available in the RuboCop repository as a reference. You can review cop by cop and configure what suits you. Just remember to check the cop availability for the version of RuboCop that you’re using.&lt;/p&gt;

&lt;p&gt;Keep in mind that style rules that belong to the &lt;code&gt;Style&lt;/code&gt; namespace are configurable and optional. A good recommendation is that these rules need to be discussed and defined with the entire team, not by a single person.&lt;/p&gt;

&lt;p&gt;It’s nice to mention that you can write your own cops, called &lt;strong&gt;Custom Cops&lt;/strong&gt;. With that, you can create your own rules, defining your practices to ensure that they will be followed. You can find more information about this process in &lt;a href="https://docs.rubocop.org/rubocop/development.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;To use the RuboCop you just need to navigate to the directory where you want to run the linter, and execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ rubocop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can specify a file/path too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ rubocop lib/file.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s possible to specify a list of directories and files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ rubocop app/ spec/ lib/file.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running RuboCop, you’ll get an output with offenses, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Offenses:

test.rb:1:1: C: Style/FrozenStringLiteralComment: Missing magic comment # frozen_string_literal: true.
def badName
^
test.rb:1:5: C: Naming/MethodName: Use snake_case for method names.
def badName
    ^^^^^^^
test.rb:2:3: C: Style/GuardClause: Use a guard clause instead of wrapping the code inside a conditional expression.
  if something
  ^^
test.rb:2:3: C: Style/IfUnlessModifier: Favor modifier if usage when having a single-line body. Another good alternative is the usage of control flow &amp;amp;&amp;amp;/||.
  if something
  ^^
test.rb:4:5: W: Layout/EndAlignment: end at 4, 4 is not aligned with if at 2, 2.
    end
    ^^^

1 file inspected, 5 offenses detected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Autocorrecting
&lt;/h3&gt;

&lt;p&gt;A great thing about RuboCop is the autocorrecting feature. This option fix automatically all possible offenses in your code, based on defined rules. In our case, we use &lt;code&gt;-a&lt;/code&gt; that fix safe offenses, but you can be more optimistic and use &lt;code&gt;-A&lt;/code&gt; to fix all offenses (including unsafe), but you need to use it with caution.&lt;/p&gt;

&lt;p&gt;To use them, you just need to run RuboCop with this autocorrecting argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ rubocop --auto-correct
# or
$ rubocop -a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check all &lt;strong&gt;RoboCop’s&lt;/strong&gt; arguments using the &lt;code&gt;--help&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;rubocop&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just for linking purposes, you can check the &lt;a href="https://docs.rubocop.org/rubocop/usage/auto_correct.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; to know more about autocorrect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating with other tools
&lt;/h2&gt;

&lt;p&gt;RuboCop integrates with many other tools. You may integrate it into your code editor to run it every time you save a file, and you'll immediately get its insights. &lt;/p&gt;

&lt;p&gt;For a list of currently supported code editors, you can check &lt;a href="https://docs.rubocop.org/rubocop/integration_with_other_tools.html#editor-integration" rel="noopener noreferrer"&gt;this page&lt;/a&gt; on documentation, and if your favorite is not listed, it’s a great opportunity to contribute to RuboCop implementing an integration.&lt;/p&gt;

&lt;p&gt;Another great usage is creating a &lt;a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks" rel="noopener noreferrer"&gt;Git Hook&lt;/a&gt; to run RuboCop before every commit. You can also setup RuboCop to be run into your Continuous Integration service (such as GitHub Actions) to have some insights for every commit. In all cases, more details can be found in the &lt;a href="https://docs.rubocop.org/rubocop/integration_with_other_tools.html#git-pre-commit-hook-integration-with-pre-commit" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed the content, and thank you for reading.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>linters</category>
      <category>rails</category>
      <category>rubocop</category>
    </item>
    <item>
      <title>State of Golang linters and the differences between them</title>
      <dc:creator>Weverton Timoteo</dc:creator>
      <pubDate>Tue, 18 Jan 2022 10:45:27 +0000</pubDate>
      <link>https://dev.to/sourcelevel/state-of-golang-linters-and-the-differences-between-them-5a3d</link>
      <guid>https://dev.to/sourcelevel/state-of-golang-linters-and-the-differences-between-them-5a3d</guid>
      <description>&lt;p&gt;Golang is full of tools to help us on developing securer, reliable, and useful apps. And there is a category that I would like to talk about: &lt;strong&gt;Static Analysis through Linters&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a linter?
&lt;/h2&gt;

&lt;p&gt;Linter is a tool that analyzes source code without the need to compile/run your app or install any dependencies. It will perform many checks in the static code (the code that you write) of your app.&lt;/p&gt;

&lt;p&gt;It is useful to help software developers ensure coding styles, identify tech debt, small issues, bugs, and suspicious constructs. Helping you and your team in the entire development flow.&lt;/p&gt;

&lt;p&gt;Linters &lt;a href="https://sourcelevel.io/linters-unleashing-the-power-of-static-code-analysis"&gt;are available for many languages&lt;/a&gt;, but let us take a look at the Golang ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  First things first: how do linters analyze code?
&lt;/h2&gt;

&lt;p&gt;Most linters analyzes the result of two phases:&lt;/p&gt;

&lt;h3&gt;
  
  
  Lexer
&lt;/h3&gt;

&lt;p&gt;Also known as tokenizing/scanning is the phase in which we convert the source code statements into &lt;em&gt;tokens&lt;/em&gt;. So each keyword, constant, variable in our code will produce a token.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parser
&lt;/h3&gt;

&lt;p&gt;It will take the tokens produced in the previous phase and try to determine whether these statements are semantically correct.&lt;/p&gt;

&lt;h3&gt;
  
  
  Golang packages
&lt;/h3&gt;

&lt;p&gt;In Golang we have &lt;code&gt;scanner&lt;/code&gt;, &lt;code&gt;token&lt;/code&gt;, &lt;code&gt;parser&lt;/code&gt;, and &lt;code&gt;ast&lt;/code&gt; (Abstract Syntax Tree) packages. Let's jump straight to a practical example by checking this simple snippet:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, SourceLevel!"&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;Okay, nothing new here. Now we'll use Golang standard library packages to visualize the &lt;code&gt;ast&lt;/code&gt; generated by the code above:&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;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"go/ast"&lt;/span&gt;
    &lt;span class="s"&gt;"go/parser"&lt;/span&gt;
    &lt;span class="s"&gt;"go/token"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// src is the input for which we want to print the AST.&lt;/span&gt;
    &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;`our-hello-world-code`&lt;/span&gt;

    &lt;span class="c"&gt;// Create the AST by parsing src.&lt;/span&gt;
    &lt;span class="n"&gt;fset&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewFileSet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// positions are relative to fset&lt;/span&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;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;src&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="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="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Print the AST.&lt;/span&gt;
    &lt;span class="n"&gt;ast&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="n"&gt;fset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&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;Now let's run this code and look the generated AST:&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="m"&gt;0&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ast&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="m"&gt;1&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="n"&gt;Package&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1&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;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ident&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="m"&gt;3&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="n"&gt;NamePos&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;
 &lt;span class="m"&gt;4&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"main"&lt;/span&gt;
 &lt;span class="m"&gt;5&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="m"&gt;6&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="n"&gt;Decls&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decl&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="m"&gt;7&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="m"&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;ast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FuncDecl&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="m"&gt;8&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="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ident&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="m"&gt;9&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;span class="c"&gt;// Name content&lt;/span&gt;
&lt;span class="m"&gt;16&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="p"&gt;}&lt;/span&gt;
&lt;span class="m"&gt;17&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="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FuncType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="m"&gt;18&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;span class="c"&gt;// Type content&lt;/span&gt;
&lt;span class="m"&gt;23&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="p"&gt;}&lt;/span&gt;
&lt;span class="m"&gt;24&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="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BlockStmt&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="m"&gt;25&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;span class="c"&gt;// Body content&lt;/span&gt;
&lt;span class="m"&gt;47&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="p"&gt;}&lt;/span&gt;
&lt;span class="m"&gt;48&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="m"&gt;49&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="m"&gt;50&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="n"&gt;Scope&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scope&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="m"&gt;51&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="n"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="m"&gt;52&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="s"&gt;"main"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt; &lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;53&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="m"&gt;54&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="m"&gt;55&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="n"&gt;Unresolved&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ident&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="m"&gt;56&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt; &lt;span class="m"&gt;29&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;57&lt;/span&gt;  &lt;span class="o"&gt;.&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="m"&gt;58&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the AST describes the previous block in a struct called &lt;code&gt;ast.File&lt;/code&gt;which is compound by the following structure:&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;File&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;Doc&lt;/span&gt;        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;CommentGroup&lt;/span&gt;   &lt;span class="c"&gt;// associated documentation; or nil&lt;/span&gt;
    &lt;span class="n"&gt;Package&lt;/span&gt;    &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pos&lt;/span&gt;       &lt;span class="c"&gt;// position of "package" keyword&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;       &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Ident&lt;/span&gt;          &lt;span class="c"&gt;// package name&lt;/span&gt;
    &lt;span class="n"&gt;Decls&lt;/span&gt;      &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Decl&lt;/span&gt;          &lt;span class="c"&gt;// top-level declarations; or nil&lt;/span&gt;
    &lt;span class="n"&gt;Scope&lt;/span&gt;      &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Scope&lt;/span&gt;          &lt;span class="c"&gt;// package scope (this file only)&lt;/span&gt;
    &lt;span class="n"&gt;Imports&lt;/span&gt;    &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ImportSpec&lt;/span&gt;   &lt;span class="c"&gt;// imports in this file&lt;/span&gt;
    &lt;span class="n"&gt;Unresolved&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Ident&lt;/span&gt;        &lt;span class="c"&gt;// unresolved identifiers in this file&lt;/span&gt;
    &lt;span class="n"&gt;Comments&lt;/span&gt;   &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;CommentGroup&lt;/span&gt; &lt;span class="c"&gt;// list of all comments in the source file&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To understand more about lexical scanning and how this struct is filled, I would recommend &lt;a href="https://www.youtube.com/watch?v=HxaD_trXwRE"&gt;Rob Pike talk&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Using AST is possible to check the formatting, code complexity, bug risk, unused variables, and a lot more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Formatting
&lt;/h2&gt;

&lt;p&gt;To format code in Golang, we can use the &lt;code&gt;gofmt&lt;/code&gt; package, which is already present in the installation, so you can run it to automatically indent and format your code. Note that it uses tabs for indentation and blanks for alignment.&lt;/p&gt;

&lt;p&gt;Here is a simple snippet from &lt;a href="https://gobyexample.com/closures"&gt;Go by Examples&lt;/a&gt; unformatted:&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;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;intSeq&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="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&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="n"&gt;i&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;i&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

    &lt;span class="n"&gt;nextInt&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;intSeq&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nextInt&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nextInt&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
       &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nextInt&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="n"&gt;newInts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;intSeq&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newInts&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;Then it will be formatted this way:&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;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;intSeq&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="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&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="n"&gt;i&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;i&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

    &lt;span class="n"&gt;nextInt&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;intSeq&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nextInt&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nextInt&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nextInt&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="n"&gt;newInts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;intSeq&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newInts&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;So we can observe that &lt;code&gt;import&lt;/code&gt; earned an extra linebreak but the empty line after &lt;code&gt;main&lt;/code&gt; function declaration is still there. So we can assume that we shouldn’t transfer the responsibility of keeping your code readable to the &lt;code&gt;gofmt&lt;/code&gt;: consider it as a helper on accomplishing readable and maintainable code.&lt;/p&gt;

&lt;p&gt;It’s highly recommended to run &lt;code&gt;gofmt&lt;/code&gt; before you commit your changes, you can even &lt;a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks"&gt;configure a precommit hook&lt;/a&gt; for that. If you want to overwrite the changes instead of printing them, you should use &lt;code&gt;gofmt -w&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simplify option
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;gofmt&lt;/code&gt; has a &lt;code&gt;-s&lt;/code&gt; as Simplify command, when running with this option it considers the following:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An array, slice, or map composite literal of the form:&lt;/strong&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="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;{}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will be simplified to:&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="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;T&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;&lt;strong&gt;A slice expression of the form:&lt;/strong&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;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will be simplified to:&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;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;A range of the form:&lt;/strong&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;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="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;v&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will be simplified to:&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;x&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;v&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that for this example, if you think that variable is important for other collaborators, maybe instead of just dropping it with &lt;code&gt;_&lt;/code&gt; I would recommend using &lt;code&gt;_meaningfulName&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A range of the form:&lt;/strong&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="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;v&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will be simplified to:&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="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;v&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that it could be incompatible with earlier versions of Go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check unused imports
&lt;/h2&gt;

&lt;p&gt;On some occasions, we can find ourselves trying different packages during implementation and just give up on using them. By using &lt;code&gt;[goimports&lt;/code&gt; package](&lt;a href="https://pkg.go.dev/golang.org/x/tools/cmd/goimports"&gt;https://pkg.go.dev/golang.org/x/tools/cmd/goimports&lt;/a&gt;) we can identify which packages are being imported and unreferenced in our code and also add missing ones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;golang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&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;tools&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;goimports&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then use it by running with &lt;code&gt;-l&lt;/code&gt; option to specify a path, in our case we’re doing a recursive search in the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;imports&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;./..&lt;/span&gt;
&lt;span class="o"&gt;../&lt;/span&gt;&lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;vendor&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;robfig&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cron&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So it identified that &lt;code&gt;cron/doc&lt;/code&gt; is unreferenced in our code and it’s safe to remove it from our code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Complexity
&lt;/h2&gt;

&lt;p&gt;Linters can be also used to identify how complex your implementation is, using some methodologies as example, let’s start by exploring ABC Metrics.&lt;/p&gt;

&lt;h3&gt;
  
  
  ABC Metrics
&lt;/h3&gt;

&lt;p&gt;It’s common nowadays to refer to how large a codebase is by referring to the LoC (Lines of Code) it contains. To have an alternate metric to LoC, Jerry Fitzpatrick proposed a concept called &lt;a href="https://en.wikipedia.org/wiki/ABC_Software_Metric"&gt;ABC Metric&lt;/a&gt;, which are compounded by the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;(A) Assignment counts:&lt;/strong&gt; &lt;code&gt;=&lt;/code&gt; , &lt;code&gt;*=&lt;/code&gt; , &lt;code&gt;/=&lt;/code&gt;, &lt;code&gt;%=&lt;/code&gt;, &lt;code&gt;+=&lt;/code&gt;, &lt;code&gt;&amp;lt;&amp;lt;=&lt;/code&gt;, &lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt;, &lt;code&gt;&amp;amp;=&lt;/code&gt;, &lt;code&gt;^=&lt;/code&gt;, &lt;code&gt;++&lt;/code&gt;, and &lt;code&gt;--&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;(B) Branch counts when:&lt;/strong&gt; Function is called&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;(C) Conditionals counts:&lt;/strong&gt; Booleans or logic test (&lt;code&gt;?&lt;/code&gt;, &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;, &lt;code&gt;!=&lt;/code&gt;, &lt;code&gt;else&lt;/code&gt;, and &lt;code&gt;case&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Caution:&lt;/em&gt;&lt;/strong&gt; This metric should &lt;strong&gt;not&lt;/strong&gt; be used as a “score” to decrease, consider it as just an indicator of your codebase or current file being analyzed.&lt;/p&gt;

&lt;p&gt;To have this indicator in Golang, you can use &lt;code&gt;[abcgo&lt;/code&gt; package](&lt;a href="https://github.com/droptheplot/abcgo):"&gt;https://github.com/droptheplot/abcgo):&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/droptheplot/abcgo
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$GOPATH&lt;/span&gt;/src/github.com/droptheplot/abcgo &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; go &lt;span class="nb"&gt;install&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Give the following Golang snippet:&lt;br&gt;
&lt;/p&gt;

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

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

    &lt;span class="s"&gt;"my_app/persistence"&lt;/span&gt;
    &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="s"&gt;"my_app/services"&lt;/span&gt;

    &lt;span class="n"&gt;flag&lt;/span&gt; &lt;span class="s"&gt;"github.com/ogier/pflag"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// flags&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;filepath&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&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;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NFlag&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="n"&gt;printUsage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;persistence&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Prepare&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringVarP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"filepath"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"f"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Load CSV to lookup for data"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;printUsage&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;"Usage: %s [options]&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;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&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;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;"Options:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrintDefaults&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then let’s analyze this example using &lt;code&gt;abcgo&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;abcgo &lt;span class="nt"&gt;-path&lt;/span&gt; main.go
Source            Func         Score   A   B   C
/tmp/main.go:18   main         5       0   5   1
/tmp/main.go:29   init         1       0   1   0
/tmp/main.go:33   printUsage   4       0   4   0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, it will print the &lt;em&gt;Score&lt;/em&gt; based on each &lt;code&gt;function&lt;/code&gt; found in the file. This metric can help new collaborators identify files that a pair programming session would be required during the onboarding period.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cyclomatic Complexity
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Cyclomatic_complexity"&gt;Cyclomatic Complexity&lt;/a&gt; in another hand, besides the complex name, has a simple explanation: it calculates how many paths your code has. It is useful to indicate that you may break your implementation in separate abstractions or give some &lt;a href="https://en.wikipedia.org/wiki/Code_smell"&gt;code smells&lt;/a&gt; and insights.&lt;/p&gt;

&lt;p&gt;To analyze our Golang code let use &lt;code&gt;[gocyclo&lt;/code&gt; package](&lt;a href="https://github.com/fzipp/gocyclo):"&gt;https://github.com/fzipp/gocyclo):&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/fzipp/gocyclo/cmd/gocyclo@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then let’s check the same piece of code that we’ve analyzed in the ABC Metrics section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gocyclo main.go
2 main main main.go:18:1
1 main printUsage main.go:33:1
1 main init main.go:29:1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also breaks the output based on function name, so we can see that the &lt;code&gt;main&lt;/code&gt; function has 2 paths since we’re using &lt;code&gt;if&lt;/code&gt; conditional there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Style and Patterns Checking
&lt;/h2&gt;

&lt;p&gt;To verify code style and patterns in your codebase, Golang already came with &lt;code&gt;[golint](https://github.com/golang/lint)&lt;/code&gt; installed. Which was a linter that offer no customization but it was performing recommended checks from the Golang development team. It was archived in mid-2021 and it is being recommended &lt;a href="https://staticcheck.io/"&gt;Staticcheck&lt;/a&gt; be used as a replacement.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Golint vs Staticcheck vs revive&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before Staticcheck was recommended, we had &lt;a href="https://revive.run/"&gt;revive&lt;/a&gt;, which for me sounds more like a community alternative linter.&lt;/p&gt;

&lt;p&gt;As revive states how different it is from archived &lt;code&gt;golint&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allows us to enable or disable rules using a configuration file.&lt;/li&gt;
&lt;li&gt;Allows us to configure the linting rules with a TOML file.&lt;/li&gt;
&lt;li&gt;2x faster running the same rules as golint.&lt;/li&gt;
&lt;li&gt;Provides functionality for disabling a specific rule or the entire linter for a file or a range of lines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;golint&lt;/strong&gt; allows this only for generated files.&lt;/li&gt;
&lt;li&gt;Optional type checking. Most rules in golint do not require type checking. If you disable them in the config file, revive will run over 6x faster than golint.&lt;/li&gt;
&lt;li&gt;Provides multiple formatters which let us customize the output.&lt;/li&gt;
&lt;li&gt;Allows us to customize the return code for the entire linter or based on the failure of only some rules.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Everyone can extend it easily with custom rules or formatters.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revive&lt;/strong&gt; provides more rules compared to &lt;strong&gt;golint&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing revive linter
&lt;/h3&gt;

&lt;p&gt;I think the extra point goes for &lt;strong&gt;revive&lt;/strong&gt; at the point of creating custom rules or formatters. Wanna try it?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/mgechev/revive@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can run it with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;revive &lt;span class="nt"&gt;-exclude&lt;/span&gt; vendor/... &lt;span class="nt"&gt;-formatter&lt;/span&gt; friendly ./...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I often exclude my &lt;code&gt;vendor&lt;/code&gt; directory since my dependencies are there. If you want to customize the checks to be used, you can supply a configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Ignores files with "GENERATED" header, similar to golint&lt;/span&gt;
ignoreGeneratedHeader = true

&lt;span class="gh"&gt;# Sets the default severity to "warning"&lt;/span&gt;
severity = "warning"

&lt;span class="gh"&gt;# Sets the default failure confidence. The semantics behind this property&lt;/span&gt;
&lt;span class="gh"&gt;# is that revive ignores all failures with a confidence level below 0.8.&lt;/span&gt;
confidence = 0.8

&lt;span class="gh"&gt;# Sets the error code for failures with severity "error"&lt;/span&gt;
errorCode = 0

&lt;span class="gh"&gt;# Sets the error code for failures with severity "warning"&lt;/span&gt;
warningCode = 0

&lt;span class="gh"&gt;# Configuration of the `cyclomatic` rule. Here we specify that&lt;/span&gt;
&lt;span class="gh"&gt;# the rule should fail if it detects code with higher complexity than 10.&lt;/span&gt;
[rule.cyclomatic]
  arguments = [10]

&lt;span class="gh"&gt;# Sets the severity of the `package-comments` rule to "error".&lt;/span&gt;
[rule.package-comments]
  severity = "error"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you should pass it on running &lt;code&gt;revive&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;$ revive -exclude vendor/... -config revive.toml -formatter friendly ./...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What else?
&lt;/h2&gt;

&lt;p&gt;As I’ve shown, you can use linters for many possibilities, you can also focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Unused code&lt;/li&gt;
&lt;li&gt;Reports&lt;/li&gt;
&lt;li&gt;Outdated packages&lt;/li&gt;
&lt;li&gt;Code without tests (no coverage)&lt;/li&gt;
&lt;li&gt;Magic number detector&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to try new linters that I didn’t mention here, I’d recommend the &lt;a href="https://github.com/golangci/awesome-go-linters#linters"&gt;archived repository awesome-go-linters&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to start?
&lt;/h2&gt;

&lt;p&gt;To start, consider using &lt;code&gt;gofmt&lt;/code&gt; before each commit or whenever you remember to run, then try &lt;code&gt;revive&lt;/code&gt;. Which linters are you using?&lt;/p&gt;

</description>
      <category>go</category>
      <category>linters</category>
      <category>golint</category>
      <category>staticcheck</category>
    </item>
    <item>
      <title>3 better Engineering Metrics uses for Managers</title>
      <dc:creator>George Guimarães</dc:creator>
      <pubDate>Fri, 12 Mar 2021 18:30:55 +0000</pubDate>
      <link>https://dev.to/sourcelevel/3-better-engineering-metrics-uses-for-managers-mcp</link>
      <guid>https://dev.to/sourcelevel/3-better-engineering-metrics-uses-for-managers-mcp</guid>
      <description>&lt;p&gt;Many managers use engineering metrics to set goals. They measure the product delivery process and then use these numbers to set &lt;a href="https://sourcelevel.io/blog/okrs-vs-kpis-explanation-with-examples-for-engineering-teams" rel="noopener noreferrer"&gt;OKRs&lt;/a&gt;, attach to a pay raise or promotion, or micromanage. All the ways lead to pressure for achieving a specific number.&lt;/p&gt;

&lt;p&gt;I’ve worked in teams in which managers would make leaderboards and control every individual’s output. It didn’t solve the problem, though. Micromanaging only increases illusory productivity, not the performance itself.&lt;/p&gt;

&lt;p&gt;At the cultural level, it changes how the team dynamic works. Individualism increases and the team starts to make bad engineering decisions. The focus becomes to be at the top of the leaderboard, not delivering an excellent product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There are other ways to use metrics&lt;/strong&gt;. They serve multiple purposes, and managers can use them on different occasions. In this article, I listed three better ways to use metrics within engineering teams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Metrics to motivate the team
&lt;/h2&gt;

&lt;p&gt;Nobody likes to have their work wasted because of misalignments. Engineers want to work on what’s important and relevant. Add challenges to the equation, and engineers will have fun doing their jobs.&lt;/p&gt;

&lt;p&gt;In this sense, managers need to communicate what’s most important clearly. If the team understands the plan, it is easier for them to see how they fit.&lt;/p&gt;

&lt;p&gt;Some kinds of work are fast, and the team stays motivated from the beginning to the end. However, when an activity takes too much time, the team may lack the feeling of achievement. When it happens, morale and motivation tend to drop. Managers can avoid it by establishing smaller, tangible, and measurable milestones in the long run.&lt;/p&gt;

&lt;p&gt;If a team has 30 technical debts that need to be addressed, managers can break it into a doable plan. It can be fixing one technical debt by a week or fixing ten up to the end of the quarter. The tactics don’t matter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The crucial thing here is to enable the team to sense progress&lt;/strong&gt;. Every week the leader can discuss the progress. In this case, metrics are not micromanaging anyone. They’re an indicator of progress. If the improvement is not satisfactory, that’s the right moment to change the plans, not blame.&lt;/p&gt;

&lt;p&gt;Regularly looking to a metric towards a plan brings a sense of progress and a frequent feeling of achievement. That’s great. Besides, don’t hesitate to celebrate small and big wins. Both are essential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Metrics as indicators
&lt;/h2&gt;

&lt;p&gt;Metrics don’t tell the story; the context does. Metrics are merely a quantitative view of the facts. That’s important to have in mind when measuring, especially for those metrics that managers take as productivity.&lt;/p&gt;

&lt;p&gt;The usage of indexes differs from traditional goals. Goals are future-centric and represent where the team should be from now. Indexes, on the other hand, show the present, like an indicator.&lt;/p&gt;

&lt;p&gt;Therefore, &lt;strong&gt;a better approach is using Engineering Metrics as indicators&lt;/strong&gt;. The hardest part is to find the appropriate set of metrics to compose the index.&lt;/p&gt;

&lt;p&gt;For example, the &lt;a href="https://sourcelevel.io/blog/3-benefits-of-devops-metrics-within-engineering-teams" rel="noopener noreferrer"&gt;Lead Time for Change&lt;/a&gt;, which measures from commit to deployment, is an excellent index of how fast the team works. It includes many outputs — commits, pull requests, deployments — and practices — coding, testing, DevOps, Product.&lt;/p&gt;

&lt;p&gt;When it comes to quality, the problem can be more complicated. As quality is subjective, engineering managers may diverge.&lt;/p&gt;

&lt;p&gt;Choosing the correct set of metrics depends on many aspects, such as team maturity, the company’s strategic goals, and product positioning. It could be the number of bugs found in production or the meantime to a system to recover from failure.&lt;/p&gt;

&lt;p&gt;There are many metrics that we could use. Collaboration, culture, quality are all abstract terms that need a measurement. Once it’s covered, tracking indexes’ evolution over time can point to real-life changes.&lt;/p&gt;

&lt;p&gt;I recommend starting with what seems obvious, then polish it as you learn.&lt;/p&gt;

&lt;h2&gt;
  
  
  Experimentation and innovation
&lt;/h2&gt;

&lt;p&gt;In the last years, lots of frameworks, practices, and tools came out. Some of them changed the way we develop software — &lt;a href="https://www.atlassian.com/agile/agile-at-scale/spotify" rel="noopener noreferrer"&gt;Spotify Model&lt;/a&gt;, to cite a famous one. They usually come from big companies that have a culture of experimenting.&lt;/p&gt;

&lt;p&gt;Not every experiment needs to be that big and successful, though. Small improvements in the system are enough for our daily activities. But how can we tell whether an experiment has worked or not? Yes, metrics.&lt;/p&gt;

&lt;p&gt;If managers measure outcomes instead of outputs,  &lt;strong&gt;metrics become a powerful tool for empowering engineering teams with autonomy and responsibility&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The teams themselves can look at the metrics as indicators and tell whether their initiatives are working or not. They can try new practices, change the process, and dive into innovation. The only restriction would be not changing metrics for the bad.&lt;/p&gt;

&lt;p&gt;Growth Marketers use this dynamic in daily operations. And I believe engineering teams should benefit from it as well.&lt;/p&gt;

&lt;p&gt;The secret of enabling innovation is an instrumented system and strategic experimentation. There must be a rationale behind each initiative. And metrics will tell how successful they are.&lt;/p&gt;

&lt;p&gt;To make it useful, it requires a fast feedback loop. It would be costly if every experiment had to run for months to determine its success. Early feedback — looking at how metrics behave — enables changing directions when things are not going well.&lt;/p&gt;

&lt;h2&gt;
  
  
  In short
&lt;/h2&gt;

&lt;p&gt;Metrics shouldn’t be villains. They are a vital tool for modern software development. There is no space for micromanaging anymore because it just doesn’t work.&lt;/p&gt;

&lt;p&gt;I listed in this article three better uses for metrics than comparing individuals against their peers.&lt;/p&gt;

&lt;p&gt;In summary, we should look for metrics as indicators. They can motivate the team, tell how the system responds to daily activities, and enable innovation through experimentation.&lt;/p&gt;

&lt;p&gt;SourceLevel provides a set of metrics that managers can use as indicators. If you’re unsure about what to measure, &lt;a href="https://sourcelevel.io/software-engineering-kpi-consultation" rel="noopener noreferrer"&gt;apply for a Free Strategy Session&lt;/a&gt; with me. If you’re wondering how to implement pragmatic metrics in your team, &lt;a href="https://sourcelevel.io/schedule-your-demo" rel="noopener noreferrer"&gt;Schedule a Demo&lt;/a&gt;, and I will be happy to show.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sourcelevel.io/blog/3-better-engineering-metrics-uses-for-managers" rel="noopener noreferrer"&gt;3 better Engineering Metrics uses for Managers&lt;/a&gt; appeared first on &lt;a href="https://sourcelevel.io" rel="noopener noreferrer"&gt;SourceLevel&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>engineeringmanagement</category>
      <category>engineeringmetrics</category>
    </item>
    <item>
      <title>Three signs your team needs Engineering Metrics ASAP</title>
      <dc:creator>George Guimarães</dc:creator>
      <pubDate>Thu, 28 Jan 2021 17:36:25 +0000</pubDate>
      <link>https://dev.to/sourcelevel/three-signs-your-team-needs-engineering-metrics-asap-ldi</link>
      <guid>https://dev.to/sourcelevel/three-signs-your-team-needs-engineering-metrics-asap-ldi</guid>
      <description>&lt;p&gt;I’ve been using &lt;a href="https://sourcelevel.io/engineering-metrics" rel="noopener noreferrer"&gt;Engineering Metrics&lt;/a&gt; for a while, and I am amazed by the significant impacts on engineering teams. Metrics is a topic I genuinely care about. During my days at Plataformatec, we used to discuss a lot about them. At the time, we used to focus on an Agile perspective.&lt;/p&gt;

&lt;p&gt;Our team was not satisfied in measuring Velocity in Story Points, nor we thought that estimating was helpful. So, we dug into Kanban philosophy and learned new statics techniques.&lt;/p&gt;

&lt;p&gt;We found out that measuring the cards’ flow through the board was more accurate and useful and that forecasting using Monte Carlo could give us more realistic estimations.&lt;/p&gt;

&lt;p&gt;Despite having many customers, we discovered that most of them had similar problems: lack of visibility and alignment. Once we introduced our metrics, the product teams had a north star.&lt;/p&gt;

&lt;p&gt;Besides, we also noticed that many CTOs had no metric to show to the board. The CMO could prove they were bringing qualified leads, the CFO had data to show their team reduced costs, but CTOs usually had no concrete metrics.&lt;/p&gt;

&lt;p&gt;Well, in summary, that’s the story behind SourceLevel. Over time, we received lots of valuable feedback, and we’re confident our product is in the right direction. We are helping companies to accelerate their deliveries sustainably and effectively.&lt;/p&gt;

&lt;p&gt;For this article, I separated three signs that you need Engineering Metrics in your teams. Check if you identify with any.&lt;/p&gt;

&lt;h2&gt;
  
  
  #1 — You don’t know in which step of the product delivery bottleneck is.
&lt;/h2&gt;

&lt;p&gt;For a commit to reach production, the code goes through a lot of steps. Many of them rely on human activities, like coding and peer-reviewing. The nature of this kind of work varies in quantity, time spent, and many other intrinsic variables.&lt;/p&gt;

&lt;p&gt;When you analyze the big picture, engineers in all levels of experience collaborate to solve a diverse type of demand, from bugs to refactorings, from typos to new releases, and so on.&lt;/p&gt;

&lt;p&gt;Systems are more complex than the sum of the parts. That’s why measuring individuals make no sense. The outputs produced vary too much in sizes, shapes, and purposes.&lt;/p&gt;

&lt;p&gt;Besides, overseeing everything is very difficult. It increases significantly when the team scales up. So, you need to instrument each step by gathering data from commits, pull requests, and deploys — as a start —, so that you can inspect them to find improvement opportunities.&lt;/p&gt;

&lt;p&gt;If you think there’s no bottleneck in your process or don’t know where it is, I strongly recommend instrumenting your system with Engineering Metrics.&lt;/p&gt;

&lt;h2&gt;
  
  
  #2 — You don’t have any metric to report upwards.
&lt;/h2&gt;

&lt;p&gt;Every area has its standard metrics. You work for many companies, but the CMO or CFO, for instance, will always report pretty much the same metrics. However, the engineering area still doesn’t have a consolidated metric to report upwards.&lt;/p&gt;

&lt;p&gt;I’ve seen many CTO fail because they couldn’t prove the team was making progress or that demand was over the capacity. Many executives still rely on gut feelings and outdated estimating methods.&lt;/p&gt;

&lt;p&gt;By measuring the whole process and then being able to drill down on specific parts of the system, CTOs and managers can understand their initiatives’ impact and create better reports.&lt;/p&gt;

&lt;h2&gt;
  
  
  #3 — You don’t know whether the team is making progress towards desired outcomes.
&lt;/h2&gt;

&lt;p&gt;When you focus on outputs, the results usually don’t go along with the outcomes. If the team’s productivity is measured by how many Pull Requests get merged, smart engineers will close as many Pull Requests as possible. It doesn’t matter whether the team reviewed it properly.&lt;/p&gt;

&lt;p&gt;The organizational culture is abstract and changes frequently. Metrics are a crucial factor. Measuring the outputs, as the number of Merged Pull Requests, isn’t enough. Leaders need to measure the outcomes.&lt;/p&gt;

&lt;p&gt;The engineering outcome is not only “code in production.” As a delivery system, we want engineering to deliver clean, well-tested, and reliable code to production faster in a sustainable — and predictable — way.&lt;/p&gt;

&lt;p&gt;When the leaders spread this message across all teams and give the team autonomy to do whatever change they need, we have the benefits of measuring outcomes: teams are not attached to outputs to experiment and innovate. The chosen set of metrics provides the alignment.&lt;/p&gt;

&lt;p&gt;For example, a way to deliver faster would be moving from a Pull Request approach to a trunk-based one. It can accelerate deliveries, but on the other hand, would the code still be well-tested and reliable? If the team is not mature enough, there are great chances it would not.&lt;/p&gt;

&lt;p&gt;That said, after defining the outcomes for your engineering success, I strongly recommend looking for a set of metrics that reflects the results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do you want to know more about Engineering Metrics?
&lt;/h2&gt;

&lt;p&gt;If you want to read more about Engineering Metrics, I’ve written a lot about them recently. You can find them under this &lt;a href="https://sourcelevel.io/blog/category/metrics" rel="noopener noreferrer"&gt;category&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feel free to &lt;a href="https://calendly.com/georgeguimaraes/call-15m" rel="noopener noreferrer"&gt;schedule a 15-min chat&lt;/a&gt; with me to talk about the challenges at your company. Maybe, I can handle more resources for you.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sourcelevel.io/blog/three-signs-your-team-needs-engineering-metrics-asap" rel="noopener noreferrer"&gt;Three signs your team needs Engineering Metrics ASAP&lt;/a&gt; appeared first on &lt;a href="https://sourcelevel.io" rel="noopener noreferrer"&gt;SourceLevel&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>uncategorized</category>
    </item>
    <item>
      <title>3 Benefits of DevOps Metrics within Engineering Teams</title>
      <dc:creator>George Guimarães</dc:creator>
      <pubDate>Thu, 14 Jan 2021 18:33:44 +0000</pubDate>
      <link>https://dev.to/sourcelevel/3-benefits-of-devops-metrics-within-engineering-teams-ci3</link>
      <guid>https://dev.to/sourcelevel/3-benefits-of-devops-metrics-within-engineering-teams-ci3</guid>
      <description>&lt;p&gt;DevOps metrics is a trending topic among software engineering managers. These metrics became very popular after the publication of &lt;a href="https://itrevolution.com/book/accelerate/" rel="noopener noreferrer"&gt;Accelerate — The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations&lt;/a&gt; and the yearly The State of DevOps reports.&lt;/p&gt;

&lt;p&gt;If you’re not familiar, here’s are the 4 DevOps Metrics proposed by the work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delivery Lead Time, which is also known by Lead Time for Change or Cycle Time&lt;/li&gt;
&lt;li&gt;Deployment Frequency, also known as Delivery Throughput&lt;/li&gt;
&lt;li&gt;Time to Restore Service&lt;/li&gt;
&lt;li&gt;Change Fail Rate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you search for “DevOps metrics,” you’ll quickly find many articles listing much more than four of them. Although I wouldn’t say they’re wrong, that’s something we need to pay attention to. Overseeing too many metrics — or DevOps KPIs, to cite a common term — at once can bring more problems than solutions.&lt;/p&gt;

&lt;p&gt;For this article, I prepared a brief list with three benefits of using those metrics so that you can accelerate engineering deliveries at your place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefit #1 — They consider only the engineering scope.
&lt;/h2&gt;

&lt;p&gt;In the article &lt;a href="https://leaddev.com/scaling-software-systems/primer-engineering-delivery-metrics" rel="noopener noreferrer"&gt;A primer on engineering delivery metrics — Scaling software &amp;amp; systems&lt;/a&gt;, Buritica states that the product conception and design phase varies too much and then defends measuring what the engineering team is responsible for: from commit to deploy.&lt;/p&gt;

&lt;p&gt;It makes sense. The  &lt;strong&gt;product design phase&lt;/strong&gt;  defines what should be built, and considering it as engineering work distorts its efficiency. On the other hand, focusing on the  &lt;strong&gt;product delivery phase&lt;/strong&gt;  allows managers to understand precisely how shipping code to production works.&lt;/p&gt;

&lt;p&gt;In short, DevOps metrics show the big picture of your whole engineering process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefit #2 — It promotes collaboration and alignment.
&lt;/h2&gt;

&lt;p&gt;I don’t believe in developer or engineer productivity. Metrics such as the number of Lines of Code added, commits, and user story points delivered usually bring anxiety, depression, and burnout — to cite a few of them mentioned in Isaac Lyman’s article &lt;a href="https://stackoverflow.blog/2020/12/07/measuring-developer-productivity/" rel="noopener noreferrer"&gt;Can developer productivity be measured?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Modern Software Development requires collaboration. More than that, it relies on teamwork. It’s like a complex system that needs a hint of chaos to work appropriately. Because of that, it’s useless to measure individual productivity. If you measure each individual by inputs or outputs, the system will adapt to it, and then you’ll see a local improvement.&lt;/p&gt;

&lt;p&gt;However, what about the other vital aspects of engineering success, such as quality, stability, and maintainability? The team probably won’t take them into account during the daily activities because what matters at the end of the day is to reach a certain number of inputs or outputs done.&lt;/p&gt;

&lt;p&gt;In my opinion, this is a management anti-pattern. If we want engineering teams to collaborate, then we need to see how they work together. Every institutionalized practice, process, or automation changes how the system behaves altogether.&lt;/p&gt;

&lt;p&gt;That’s why you need metrics that fully represent the big picture to understand if they have improved or worsened the team’s dynamic. As a result, teams work with high autonomy guided by the alignment provided by metrics that tell what’s expected from them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefit #3 — Improving the system is more effective.
&lt;/h2&gt;

&lt;p&gt;If you compare two individuals, given they’re humans, it very likely they won’t perform the same. Depending on the type of demand — whether it’s a bug, a new feature, or PoC —, their motivation, how clear the task, the related experiences they had, and many other aspects can cause divergences in the numbers.&lt;/p&gt;

&lt;p&gt;In a Leaderboard, there will always have someone at the bottom. Even if you start a mentorship program to leverage individual productivity, it doesn’t mean all engineers will produce the same.&lt;/p&gt;

&lt;p&gt;However, you can find whether a mentorship program is working by looking at the system. If the system is delivering more, with quality and reliability, it’s working. It doesn’t matter who is at the bottom or the top of the Leaderboard.&lt;/p&gt;

&lt;p&gt;Daniel Markovitz wrote in an article for the Harvard Business Review called &lt;a href="https://hbr.org/amp/2021/01/productivity-is-about-your-systems-not-your-people" rel="noopener noreferrer"&gt;Productivity Is About Your Systems, Not Your People&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As legendary statistician and management consultant W. Edwards Deming argued in his book Out of the Crisis, 94% of most problems and possibilities for improvement belong to the system, not the individual. I would argue that most productivity improvements belong there as well. Personal solutions can be useful, but the most effective antidote to low productivity and inefficiency must be implemented at the system level, not the individual level.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Understanding the impact of engineering initiatives, projects, and daily activities on the system outcomes makes it much more likely to managers drive their teams to high-performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  You’ll probably need more metrics later.
&lt;/h2&gt;

&lt;p&gt;DevOps metrics are enough for having the big picture. But sometimes, we need to zoom in and see how the system behaves in a specific part of the process. In this case, you’ll need more metrics.&lt;/p&gt;

&lt;p&gt;You may have a better idea of what I’m talking about reading Smruti Patel’s article &lt;a href="https://leaddev.com/productivity-eng-velocity/debugging-engineering-velocity-and-leading-high-performing-teams" rel="noopener noreferrer"&gt;Debugging engineering velocity and leading high-performing teams — Productivity &amp;amp; Eng velocity&lt;/a&gt;. Breaking the process into smaller steps is fundamental to understand where bottlenecks and issues are. Then, managers can complement their view by instrumenting those steps.&lt;/p&gt;

&lt;p&gt;These complementary metrics give managers visibility and allow the teams to detach from inputs and outputs. So, they can elaborate on sophisticated solutions that impact the whole system.&lt;/p&gt;

&lt;p&gt;However, the team should align every action with those 4 DevOps Metrics.&lt;/p&gt;

&lt;h2&gt;
  
  
  In short
&lt;/h2&gt;

&lt;p&gt;The 4 DevOps Metrics are excellent to give managers a big view. However, to debug the process, they need to instrument the system using other metrics. It’s like Observability, but for the process.&lt;/p&gt;

&lt;p&gt;For more ideas of how and what to measure, I strongly recommend our latest e-book, &lt;a href="https://sourcelevel.io/engineering-manager-playbook-high-performance-teams" rel="noopener noreferrer"&gt;The Engineering Manager’s Play for debuggable and observable processes&lt;/a&gt;. It has quality content with examples of what to measure in each delivery phase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;See Engineering Metrics Live:&lt;/strong&gt; &lt;a href="https://sourcelevel.io/engineering-metrics" rel="noopener noreferrer"&gt;Click here&lt;/a&gt; to get a &lt;strong&gt;full demo&lt;/strong&gt; of SourceLevel Engineering Metrics and how they can help your team.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sourcelevel.io/blog/3-benefits-of-devops-metrics-within-engineering-teams" rel="noopener noreferrer"&gt;3 Benefits of DevOps Metrics within Engineering Teams&lt;/a&gt; appeared first on &lt;a href="https://sourcelevel.io" rel="noopener noreferrer"&gt;SourceLevel&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>engineeringmanagement</category>
      <category>metrics</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why you should adopt a community-maintained javascript style guide</title>
      <dc:creator>George Guimarães</dc:creator>
      <pubDate>Tue, 01 Dec 2020 11:35:00 +0000</pubDate>
      <link>https://dev.to/sourcelevel/why-you-should-adopt-a-community-maintained-javascript-style-guide-45ll</link>
      <guid>https://dev.to/sourcelevel/why-you-should-adopt-a-community-maintained-javascript-style-guide-45ll</guid>
      <description>&lt;p&gt;Airbnb’s JavaScript style guide is the most popular set of rules for code standardization available. The repository is open for &lt;a href="https://github.com/airbnb/javascript" rel="noopener noreferrer"&gt;contributions on GitHub&lt;/a&gt;. Yet, other style guides follow the same approach. They’re well maintained and available for free, such as &lt;a href="https://google.github.io/styleguide/jsguide.html" rel="noopener noreferrer"&gt;Google&lt;/a&gt;‘s, &lt;a href="https://github.com/standard/standard" rel="noopener noreferrer"&gt;Standard&lt;/a&gt;‘s, and &lt;a href="https://github.com/rwaldron/idiomatic.js/" rel="noopener noreferrer"&gt;Idiomatic&lt;/a&gt;‘s.&lt;/p&gt;

&lt;p&gt;If you search more deeply, you can find even more style guides used by tech companies or individuals. There’s not a single way to write and format code, and that’s good and healthy.&lt;/p&gt;

&lt;p&gt;However, even with lots of conventions documented out there, many companies prefer to write their version, which usually leads to a waste of time and effectiveness, as gathering the team to discuss aesthetic aspects of the code can be both time-consuming and exhausting.&lt;/p&gt;

&lt;p&gt;In this article, I list reasons to enforce my opinion that choosing a community-maintained javascript style guide is the best thing for everyone — with few exceptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maintaining a style guide is time-consuming
&lt;/h2&gt;

&lt;p&gt;Each engineer develops a preference over time. Some people prefer tabs, others space; some prefer single quotes, others double quotes; and so on. Does the preference affect the quality of the code? I don’t think so. Does the preference affect the end-users value perception? I don’t believe it.&lt;/p&gt;

&lt;p&gt;The fact is that quality and value aren’t expressed on coding preferences. They derive from solid processes and tools that support engineering activities. So, instead of focusing on discussing preferences, it’s more productive to focus on designing robust and well-crafted systems.&lt;/p&gt;

&lt;p&gt;It’s fundamental to say that engineering teams and product final users benefit from a standardized codebase. The more a codebase looks like written by a single person, the faster and less buggy the development tends to be.&lt;/p&gt;

&lt;p&gt;In this case, writing a document that states how code should look is not enough. It’s necessary to adopt and institutionalize as a practice, and the best tools available for that are linters. Linters use static code analysis to find mismatches. Examples include &lt;a href="https://sourcelevel.io/blog/how-to-setup-eslint-and-prettier-on-node" rel="noopener noreferrer"&gt;eslint and prettier for JavaScript&lt;/a&gt;, pylint for python, and rubocop for Ruby.&lt;/p&gt;

&lt;p&gt;Community-maintained projects run this discussion with a broad reach, and detach those discussions to engineering daily activities. Maintenance is more frequent and peer-reviewed than in-house solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maintaining the linter’s configuration files is laborious
&lt;/h2&gt;

&lt;p&gt;Keeping a document with the company’s rules requires dedication as new versions of the programming language or framework comes out. What engineering teams always neglect is that style guides get obsolete as people leave and join the company as well.&lt;/p&gt;

&lt;p&gt;In small or mid-sized teams, when you hire opinionated engineers or fire senior developers, there are great chances that old discussions emerge again. As changing documentation is harder, linters’ configuration files differ from the predefined styles.&lt;/p&gt;

&lt;p&gt;The same occurs with code documentation, which always ends up in the question: is it outdated documentation or an implementation bug?&lt;/p&gt;

&lt;p&gt;Taking as an example the Airbnb JavaScript style guide, you can notice the documentation ships with some linters files already configured, which saves time and enforces consistency between the style guide documentation and how it performs the checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Faster ramp up of new-hires
&lt;/h2&gt;

&lt;p&gt;If your company adopts a specific style guide with lots of custom rules for linters, then the ramp-up of new-hires is slower. The same may apply if different teams adopt different code conventions — which sounds against the idea of standardization of the code. The uniqueness of the settings increases the cognitive demand for new-hires during onboarding.&lt;/p&gt;

&lt;p&gt;It means that adopting a community-maintained style guide helps scaling companies. In fact, I strongly recommend choosing a style guide before growing fast, as the coordination efforts of doing it afterward is significantly higher.&lt;/p&gt;

&lt;p&gt;When you use the Airbnb, Standard, Idiomatic or whatever JavaScript style guide, the adherence to them will probably be higher than understanding and promoting your company’s own. Many of the hired engineers may already know the rules by heart, which accelerates the ramp up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback comes from the community
&lt;/h2&gt;

&lt;p&gt;Prefer a community-based solution over a custom implementation. That’s what I believe is the best for companies I worked for, and what I always foster as part of SourceLevel’s culture.&lt;/p&gt;

&lt;p&gt;Besides all the open-source benefits, the strongest point of adopting an open-source style guide is getting external feedback. Otherwise, the team relies only on their experience. The external view brings more value to the discussion.&lt;/p&gt;

&lt;p&gt;If you the team really has strong arguments on a certain preference, the repository is open-source, and will accept a pull request or issue for discussing the matter. Of course, you can’t take the change as granted. But you definitively can collaborate with the community by sharing your opinions. And this is the kind of environment I want to promote.&lt;/p&gt;

&lt;h2&gt;
  
  
  Few exceptions
&lt;/h2&gt;

&lt;p&gt;I think there are few exceptions to the rule. If your company is big enough, or maybe has created a framework that became very popular, then you might consider creating a public style guide. The community can help in the process, and it is a win-win.&lt;/p&gt;

&lt;p&gt;This rule applies to big open-source projects as well. After establishing the rules for that project, it can be used by other people and companies around the world. However, if you don’t intend to put effort into maintaining it, I’d simply adopt an existing style guide.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sourcelevel.io/blog/why-you-should-adopt-a-community-maintained-javascript-style-guide" rel="noopener noreferrer"&gt;Why you should adopt a community-maintained javascript style guide&lt;/a&gt; appeared first on &lt;a href="https://sourcelevel.io" rel="noopener noreferrer"&gt;SourceLevel&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>developmenttools</category>
    </item>
    <item>
      <title>On the Four Key DevOps Metrics, and why I measure them differently</title>
      <dc:creator>George Guimarães</dc:creator>
      <pubDate>Fri, 06 Nov 2020 18:21:03 +0000</pubDate>
      <link>https://dev.to/sourcelevel/on-the-four-key-devops-metrics-and-why-i-measure-them-differently-4fo6</link>
      <guid>https://dev.to/sourcelevel/on-the-four-key-devops-metrics-and-why-i-measure-them-differently-4fo6</guid>
      <description>&lt;p&gt;The four key DevOps metrics are an exciting set of measurements. They’re getting more and more relevant since the book &lt;a href="https://books.google.com.br/books/about/Accelerate.html?id=85XHAQAACAAJ" rel="noopener noreferrer"&gt;Accelerate&lt;/a&gt; has been published. I firmly believe they’re essential for engineering teams seeking effectiveness and efficiency.&lt;/p&gt;

&lt;p&gt;The Four key DevOps metrics are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lead Time for Change&lt;/li&gt;
&lt;li&gt;Deploy Frequency&lt;/li&gt;
&lt;li&gt;Change Failure Rate&lt;/li&gt;
&lt;li&gt;Median Time to Restore (MTTR)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can learn more about measuring it in &lt;a href="https://stelligent.com/2018/12/21/measuring-devops-success-with-four-key-metrics/" rel="noopener noreferrer"&gt;Paul Duvall’s article&lt;/a&gt; or reading the &lt;a href="https://cloud.google.com/devops/state-of-devops" rel="noopener noreferrer"&gt;2019 Accelerate State of DevOps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I want to explore why I like them and why we measure it slightly differently at Source Level. I’ll focus on the Lead Time for Change and Deploy Frequency, as I have more experience working with them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why are the Four Key DevOps Metrics essential for engineering teams?
&lt;/h2&gt;

&lt;p&gt;The main goal of an engineering team is to add value for the customers through technology. Delivering value is abstract, and describing what it means is hard.&lt;/p&gt;

&lt;p&gt;Sometimes value translates into a single line of code or even in a configuration change. But at other times, value translates into three months of 8-sized-team work. It happens because value perception is not attached to the work itself. It’s bound to what end-users extract from the running product.&lt;/p&gt;

&lt;p&gt;That’s why measuring Story Points is useless. The team attributes a numeric value based on how much effort a given User Story or task requires. So, Story Points measures engineering performance based on their effort. And, as stated, it’s not related to the end-user perception of value.&lt;/p&gt;

&lt;p&gt;However, Modern Software Development requires agility, and it doesn’t come from the nature of the work, such as painful features or slippery bugs. Agility comes from a smooth and sustainable process.&lt;/p&gt;

&lt;p&gt;Some years ago, using agility and process in the same sentence would be hilarious. But agile’s core is to respond to change appropriately, and delivering more doing less is a consequence, not the goal.&lt;/p&gt;

&lt;p&gt;That said, the Four Key DevOps metrics become the best allies of &lt;a href="https://sourcelevel.io/how-tech-leads-and-team-leads-can-measure-teams-productivity" rel="noopener noreferrer"&gt;Tech Leads, Engineering Managers, and VPs of Engineering looking for efficiency&lt;/a&gt;. These roles require full attention to the big picture, and DevOps metrics give a perfect overview of how the system responds to daily activities.&lt;/p&gt;

&lt;p&gt;Lead Time for Change and Deploy Frequency summarize the development pipeline, and any change in the process reflects on them. Managers should have them in their dashboards or any other accessible and accurate place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Considerations on Lead Time for Change
&lt;/h3&gt;

&lt;p&gt;Lead Time for Change measures how much time it takes for a code change to reach production. It’s crucial to measure up to production because staging or any other non-official environment won’t provide any value.&lt;/p&gt;

&lt;p&gt;However, it raises an interesting discussion on feature toggles (or feature flags). Deploying a new feature is not the final step of the value chain if your team uses feature toggles or feature flags. Features must be enabled to add value, and so, I’d consider measuring not only Lead Time for Change but also the Lead Time to Value.&lt;/p&gt;

&lt;p&gt;Another aspect I’d like to point is statistics. The recommendation is to calculate the Median Lead Time for Change. It outputs the value at the midpoint of a frequency distribution. In other words, half of the changes are equal or less the median. But how about the other half of the changes? They could take considerably more.&lt;/p&gt;

&lt;p&gt;At SourceLevel, we’ve been more likely to use the 75th percentile as the default metric and keeping track of the 95th percentile as well. The 75th percentile is more comprehensive and realistic. In contrast, the 95th percentile gives us an idea of the small portion of work left out of the count and excludes the top 5% most time-consuming changes, as we consider them outliers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Considerations on Deploy Frequency
&lt;/h3&gt;

&lt;p&gt;Deploy Frequency measures how many times code changes reached production in a period. It can be measure as deploy per hour, per day, per week, per month, and so on.&lt;/p&gt;

&lt;p&gt;It’s crucial to adjust the period properly. Saying a team deploys four times in a month sounds like a team deploys once in a week. But it may not be accurate. If the team deploys four times at the end of a month, it means the team has a different pace than deploying once a week.&lt;/p&gt;

&lt;p&gt;If it’s usual for your team to have one or zero deploys per day, don’t measure it in days. Start measuring in weeks. Once the team starts deploying more than seven times a week, you can switch for days. Switch to shorter timeframes whenever possible, but always respecting the accuracy of the information.&lt;/p&gt;

&lt;h2&gt;
  
  
  In short
&lt;/h2&gt;

&lt;p&gt;The Four Key DevOps Metrics are useful and give an overall idea of how the system responds to daily activities. Lead Time for Change and Deploy Frequency are much more price than Story Points and should be accessible and accurate.&lt;/p&gt;

&lt;p&gt;Tech Leads, Engineering Managers, and VP of Engineering benefit from these &lt;a href="https://sourcelevel.io/engineering-metrics" rel="noopener noreferrer"&gt;metrics&lt;/a&gt;. Although &lt;a href="https://sourcelevel.io/blog/5-responsibilities-of-a-tech-lead-and-17-metrics-to-track-their-performance" rel="noopener noreferrer"&gt;more metrics&lt;/a&gt; are necessary to investigate problems, they are excellent indicators of the engineering process healthiness.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sourcelevel.io/blog/on-the-four-key-devops-metrics-and-why-i-measure-them-differently" rel="noopener noreferrer"&gt;On the Four Key DevOps Metrics, and why I measure them differently&lt;/a&gt; appeared first on &lt;a href="https://sourcelevel.io" rel="noopener noreferrer"&gt;SourceLevel&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>agilemetrics</category>
      <category>engineeringmanagemen</category>
      <category>engineeringmetrics</category>
      <category>deployfrequency</category>
    </item>
    <item>
      <title>OKRs vs. KPIs: explanation with examples for Engineering Teams.</title>
      <dc:creator>George Guimarães</dc:creator>
      <pubDate>Tue, 20 Oct 2020 22:04:32 +0000</pubDate>
      <link>https://dev.to/sourcelevel/okrs-vs-kpis-explanation-with-examples-for-engineering-teams-1phb</link>
      <guid>https://dev.to/sourcelevel/okrs-vs-kpis-explanation-with-examples-for-engineering-teams-1phb</guid>
      <description>&lt;p&gt;&lt;em&gt;OKRs vs. KPIs, what are the differences?&lt;/em&gt; That’s a common question I hear from managers of Engineering Teams. KPIs are more straightforward to explain than &lt;a href="https://en.wikipedia.org/wiki/OKR" rel="noopener noreferrer"&gt;OKRs&lt;/a&gt;, which can be tricky and more complex. They don’t mean the same, although they are connected.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are KPIs?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;KPI stands for Key Performance Indicators.&lt;/strong&gt; In other words, KPIs are a set of metrics that should give you an overview of the area or team’s performance. They need to be measurable and comparable.&lt;/p&gt;

&lt;p&gt;If you look at many KPIs, they’re not fulfilling their purpose. Organizations should select as few as possible so that tracking the progress is possible. Besides, all the significant changes in process and company goals should impact the numbers.&lt;/p&gt;

&lt;p&gt;Then, managing an area or a team becomes more tangible: when the KPIs show poor performance, it’s time to act. The actions taken should reflect better numbers; otherwise, managers need to find another strategy and act differently.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are OKRs?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;OKRs stands for Objective Key Results&lt;/strong&gt;. It’s a managing methodology that is popular in Silicon Valey. It’s been widely adopted by companies and startups at scale. It’s also seen as an alternative or complement for strategic planning.&lt;/p&gt;

&lt;p&gt;OKRs’ primary purpose is to define Objectives that must align with the business and a set of Key Results. Each Key Result needs to have a measurable number as the goal and a limit date. The limit date means that the goal should be achieved within that time frame.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the difference between KPIs and OKRs?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;KPIs provide an overview of the area or team for managers, whereas OKRs must focus on its future.&lt;/strong&gt; That said, it becomes clear that KPIs are a controlling tool, and OKRs intend to change an organization’s status quo and keep track of its progress by periodic assessment meetings.&lt;/p&gt;

&lt;p&gt;It’s crucial to have that in mind when choosing the KPIs and the OKRs. Otherwise, they become useless and can even play against business goals. Let’s see some examples of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples of OKRs and KPIs for Engineering Teams
&lt;/h2&gt;

&lt;p&gt;Below there is a list of KPIs examples. However, you can find more examples in my article &lt;a href="https://sourcelevel.io/blog/software-engineering-kpis-how-to-choose-the-best-fitting-metrics" rel="noopener noreferrer"&gt;Software Engineering KPIs: how to choose the best fitting metrics&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deploy Frequency&lt;/strong&gt; : it’s a sum of the &lt;a href="https://thenewstack.io/measuring-engineering-velocity-deploy-frequency-as-a-vital-sign-of-devops-health/" rel="noopener noreferrer"&gt;number of deploys made by day&lt;/a&gt;, week, or month, depending on the organization’s need. &lt;em&gt;It shows how frequently the team — or area — delivers value to the final user&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time to Merge&lt;/strong&gt; : it measures the number of days a Pull Request remains open or under review. You can find an average or, as I prefer, see the 75th percentile of all pull requests closed in a given period. &lt;em&gt;It shows how performant is the team&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time to Recover&lt;/strong&gt; : how much time does the application is inaccessible after an error? &lt;em&gt;This metric tells a lot about how engineering teams respond to failures.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When thinking of OKRs, Engineering Teams may consider Objectives such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Improving the Time to Market of new features&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lessen the Churn rate of the product&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are some possible Key Results for  &lt;strong&gt;Improving the Time to Market of new features&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Increase the Deploy Frequency to 37/week until &lt;/strong&gt;. Assuming you deploy less than 37 times a week currently, increasing the frequency means you’re delivering more. Delivering more is crucial to achieving a more competitive Time to Market.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduce the 75th percentile of Time to Merge to 3 days until &lt;/strong&gt;. Instead of the Median or Average, I prefer using the 75th percentile for Key Results. In other words, it means that 75% of the Pull Requests must be merged up to 3 days after they were opened. The team can achieve it by opening lighter pull requests or engaging in collaborators’ pull requests instead of working on a new work item.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the second object,  &lt;strong&gt;Lessen the Churn rate of the product&lt;/strong&gt; , let’s assume you know the primary source of churn comes due to a high number of errors in the application. Then, the Key Results could include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reduce the number of Technical Debts to 15 until &lt;/strong&gt;. Let’s say you have 30 Technical Debts currently. It’s a 50% improvement. There are many chances that improving the codebase will positively affect the churn rate and help in the KR of the previous Objective. The cleaner the code, the better it embraces the changes. It means you can reduce the churn and also achieve better Time to Market by gardening your codebase.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduce the Mean Time to Recover to Recover (MTTR) to 3 minutes until &lt;/strong&gt;. The team needs to monitor application outages, connectivity problems, 503 errors, and other failures to ensure end-users’ experience is not impacted with more than 3 minutes of instability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  In short,
&lt;/h2&gt;

&lt;p&gt;KPIs and OKRs are not the same. They have different purposes. KPIs aim to give managers an overview of how the team or area is working, whereas OKRs focus on providing the team a direction and then tracking its progress.&lt;/p&gt;

&lt;p&gt;I presented some examples of KPIs and OKRs for Engineering Teams to illustrate the difference. SourceLevel provides lots of metrics, which may include your KPIs. Check out our &lt;a href="https://sourcelevel.io/engineering-metrics" rel="noopener noreferrer"&gt;Analytics feature&lt;/a&gt;, or &lt;a href="https://sourcelevel.io/schedule-your-demo" rel="noopener noreferrer"&gt;schedule a demo with me&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you need to define KPIs for your team, I am giving away a &lt;a href="https://sourcelevel.io/software-engineering-kpi-consultation" rel="noopener noreferrer"&gt;30-min consultation meeting&lt;/a&gt;. Schedule a demo so that we can discuss your specific needs.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sourcelevel.io/blog/okrs-vs-kpis-explanation-with-examples-for-engineering-teams" rel="noopener noreferrer"&gt;OKRs vs. KPIs: explanation with examples for Engineering Teams.&lt;/a&gt; appeared first on &lt;a href="https://sourcelevel.io" rel="noopener noreferrer"&gt;SourceLevel&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>engineeringmanagemen</category>
      <category>engineeringmetrics</category>
      <category>deployfrequency</category>
      <category>leadtime</category>
    </item>
  </channel>
</rss>
