<?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: Patrick Ahmetovic</title>
    <description>The latest articles on DEV Community by Patrick Ahmetovic (@patriscus).</description>
    <link>https://dev.to/patriscus</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F441664%2F14867922-9afb-4126-a84a-66c30440f7d2.jpeg</url>
      <title>DEV Community: Patrick Ahmetovic</title>
      <link>https://dev.to/patriscus</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/patriscus"/>
    <language>en</language>
    <item>
      <title>Let the computer do the work.</title>
      <dc:creator>Patrick Ahmetovic</dc:creator>
      <pubDate>Mon, 08 Mar 2021 20:58:57 +0000</pubDate>
      <link>https://dev.to/patriscus/let-the-computer-do-the-work-535a</link>
      <guid>https://dev.to/patriscus/let-the-computer-do-the-work-535a</guid>
      <description>&lt;p&gt;I don't particularly appreciate spending a fair amount of time reading through documentation about style guides, team conventions, guidelines, and more. I wouldn't say I like having to think about every reference in those documentation pages to make sure that I don't write code that is violating any of these.&lt;/p&gt;

&lt;p&gt;That is why I usually try to let the computer do the work. Here are some notes about the tools I like to use:&lt;/p&gt;

&lt;h2&gt;
  
  
  ESLint
&lt;/h2&gt;

&lt;p&gt;ESLint is a linting tool that can cover many aspects of your source code. For example, I could enable the &lt;code&gt;eqeqeq&lt;/code&gt; rule and automatically check that I'm using &lt;code&gt;===&lt;/code&gt; instead of &lt;code&gt;==&lt;/code&gt; in my conditions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ESLint will suggest using === instead of ==&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iWrite&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;thisCondition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ESLint will complain.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the configuration file is extensible, different settings can be shared across the team, organization, or the world. This way, I can specify rules by providing a config and, whenever a rule is broken, give feedback without me needing to check it manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prettier
&lt;/h2&gt;

&lt;p&gt;Promoted as an &lt;em&gt;opinionated code formatter&lt;/em&gt;, Prettier rectifies the need to discuss things like tabs and spaces and other formatting concerns. Instead, the code is formatted through rules defined in a config file.&lt;/p&gt;

&lt;p&gt;It can format the code on save, check if the code is not formatted correctly, and automatically fix most of the errors.&lt;/p&gt;

&lt;p&gt;I like to use ESLint for style guide purposes (like the &lt;code&gt;eqeqeq&lt;/code&gt; rule mentioned above) while Prettier takes care of my code's formatting.&lt;/p&gt;

&lt;h2&gt;
  
  
  stylelint
&lt;/h2&gt;

&lt;p&gt;Stylelint is a linter similar to ESLint, but instead of checking JavaScript code, stylelint will validate your stylesheets instead.&lt;/p&gt;

&lt;p&gt;Much of the same benefits of ESLint apply. With stylelint, I can specify and enforce code styles and practices throughout the CSS code I write.&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript
&lt;/h2&gt;

&lt;p&gt;As a superset of JavaScript, TypeScript enables developers to add types to JS code. The TypeScript compiler can provide quick feedback should the code contain errors that can be determined statically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TypeScript would catch the invalid type &lt;code&gt;string&lt;/code&gt; of the second argument we pass to the &lt;code&gt;add&lt;/code&gt; function. These checks can catch a lot of unexpected errors even without ever having to run the code.&lt;/p&gt;

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

&lt;p&gt;Writing self-testing code is a topic in itself. However, I want to give notes on some of the tools I've liked to use so far:&lt;/p&gt;

&lt;h3&gt;
  
  
  Jest
&lt;/h3&gt;

&lt;p&gt;Jest is a testing framework that offers an extensive API for writing your tests. It comes with a nifty &lt;code&gt;--watch&lt;/code&gt; mode, as well as a plethora of different assertion possibilities and excellent mocking capabilities. Paired with additional features such as coverage reports, custom matcher support, and plugin support, I've primarily used Jest for testing my code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cypress
&lt;/h3&gt;

&lt;p&gt;Cypress is a great way to write E2E tests that can verify use cases involving multiple system components without mocking parts.&lt;/p&gt;

&lt;p&gt;Instead of manually clicking around on a webpage, Cypress will go through the commands with an automated runner. While doing that, assertions can automatically check if everything is as expected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing Libary suite
&lt;/h3&gt;

&lt;p&gt;I am a fan of the &lt;a href="https://testing-library.com/"&gt;Testing Library&lt;/a&gt; suite, specifically the Vue Testing Library and React Testing Library. These test utilities allow me to write my tests in a more readable way while implicitly checking other aspects of my code, such as accessibility.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;userEvent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/user-event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-path/Counter.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`updates the displayed text with correct counter value`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Counter is: 0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/increment/i&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;

  &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Counter is: 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In the future, I want to explore the &lt;a href="https://testing-library.com/docs/cypress-testing-library/intro/"&gt;Cypress Testing Library&lt;/a&gt; as well to use a similar API as the other Testing Libraries for E2E tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Husky for git hooks
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;husky&lt;/code&gt; is a great package that lets me add git hooks with ease. These hooks provide points at which I can run custom code for various purposes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"husky"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"pre-commit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint . --ext .js,.ts"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of the time, I've used &lt;code&gt;husky&lt;/code&gt; to add a pre-commit hook that runs a custom validate script (using many of the tools mentioned in this post). On failure, the developer cannot commit the code and has first to fix the issues. That enables a rapid feedback loop and ensures that the necessary checks have been made before making a commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  lint-staged
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;lint-staged&lt;/code&gt; is a package that runs specified commands only against staged files. That avoids checking your whole project by narrowing it down to the files that will get committed next.&lt;/p&gt;

&lt;p&gt;For me, &lt;code&gt;husky&lt;/code&gt; and &lt;code&gt;lint-staged&lt;/code&gt; go hand in hand together, meaning I usually configure &lt;code&gt;husky&lt;/code&gt; to call my &lt;code&gt;lint-staged&lt;/code&gt; script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"husky"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"pre-commit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lint-staged"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lint-staged"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"*.js"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run validate"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Further notes
&lt;/h2&gt;

&lt;p&gt;One of the projects I didn't use yet but would like to is commitlint. commitlint can transfer rules and concepts from &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/"&gt;conventional commits&lt;/a&gt; to a config file. It then lints git commit messages and tries to find violations against those rules.&lt;/p&gt;

</description>
      <category>webdev</category>
    </item>
    <item>
      <title>Non-Prop Attributes in Vue</title>
      <dc:creator>Patrick Ahmetovic</dc:creator>
      <pubDate>Tue, 23 Feb 2021 10:50:12 +0000</pubDate>
      <link>https://dev.to/patriscus/non-prop-attributes-in-vue-2bm8</link>
      <guid>https://dev.to/patriscus/non-prop-attributes-in-vue-2bm8</guid>
      <description>&lt;p&gt;During the implementation of a custom component, I explored the documentation to learn about a behavior that previously seemed a bit magical to me: Non-Prop Attributes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Props in Vue
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;props&lt;/code&gt; are one of the ways you can implement component communication in Vue. It is pretty similar to React and provides an API to express the properties such as &lt;code&gt;type&lt;/code&gt;, &lt;code&gt;required&lt;/code&gt;, and &lt;code&gt;default&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As an example, let's look at an input component that receives a prop named &lt;code&gt;value&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// BaseInput.vue
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;v-bind=&lt;/span&gt;&lt;span class="s"&gt;"$attrs"&lt;/span&gt; &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BaseInput&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's a possible usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// MyComponent.vue
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;BaseInput&lt;/span&gt; &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Non-Prop Attributes
&lt;/h2&gt;

&lt;p&gt;But what if you do this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// MyComponent.vue
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;BaseInput&lt;/span&gt; &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt; &lt;span class="na"&gt;:readonly=&lt;/span&gt;&lt;span class="s"&gt;"isReadOnly"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;readonly&lt;/code&gt; is &lt;strong&gt;not&lt;/strong&gt; defined in the &lt;code&gt;props&lt;/code&gt; definition of &lt;code&gt;BaseInput&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// BaseInput.vue
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;// No definition for readonly&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what happens with it?&lt;/p&gt;

&lt;p&gt;In such cases, Vue adds these attributes to the &lt;code&gt;$attrs&lt;/code&gt; object accessible as an instance property. In the example above, &lt;code&gt;readonly&lt;/code&gt; gets added to the object as &lt;code&gt;$attrs.readonly&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"readonly"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Attribute Inheritance
&lt;/h2&gt;

&lt;p&gt;Attribute inheritance (and disabling it) can leverage the usage of Non-Prop attributes. By default, attributes are added to the &lt;code&gt;root&lt;/code&gt; element of your template. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// BaseInput.vue
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// MyComponent.vue
&lt;span class="nt"&gt;&amp;lt;BaseInput&lt;/span&gt; &lt;span class="na"&gt;data-testid=&lt;/span&gt;&lt;span class="s"&gt;"my-component-id"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Will result in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-testid=&lt;/span&gt;&lt;span class="s"&gt;"my-component-id"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;inheritAttrs: false&lt;/code&gt;, we can opt-out of this default behavior to tell Vue that we are explicitly going to bind the attributes where we need to. In the example above, we may want to set the &lt;code&gt;input&lt;/code&gt; element's attributes rather than the outer &lt;code&gt;div&lt;/code&gt;. To do that, we add &lt;code&gt;v-bind="$attrs"&lt;/code&gt; to the &lt;code&gt;input&lt;/code&gt; element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// BaseInput.vue
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;v-bind=&lt;/span&gt;&lt;span class="s"&gt;"$attrs"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;inheritAttrs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, &lt;code&gt;&amp;lt;BaseInput data-testid="my-component-id" /&amp;gt;&lt;/code&gt; will result in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;data-testid=&lt;/span&gt;&lt;span class="s"&gt;"my-component-id"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is especially useful when all the possible attribute keys are either unknown beforehand or tedious to manually define as a prop. For instance, an &lt;code&gt;input&lt;/code&gt; element can have a multitude of different attributes such as &lt;code&gt;value&lt;/code&gt;, &lt;code&gt;disabled&lt;/code&gt;, &lt;code&gt;type&lt;/code&gt;, &lt;code&gt;readonly&lt;/code&gt;, and more. Another example would be to add &lt;code&gt;data-testid&lt;/code&gt; (or other data attributes) for testing purposes or integration with 3rd party libraries.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: In Vue 2, the &lt;code&gt;class&lt;/code&gt; and &lt;code&gt;style&lt;/code&gt; attributes are not added to &lt;code&gt;$attrs&lt;/code&gt;. That means that despite using &lt;code&gt;inheritAttrs: false&lt;/code&gt;, these two attributes are added to the &lt;code&gt;root&lt;/code&gt; element no  matter what. This behavior changed in Vue 3 by adding them to &lt;code&gt;$attrs&lt;/code&gt; as well.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Tailwind. My experience using it for a month now.</title>
      <dc:creator>Patrick Ahmetovic</dc:creator>
      <pubDate>Sat, 10 Oct 2020 16:15:36 +0000</pubDate>
      <link>https://dev.to/patriscus/tailwind-my-experience-using-it-for-a-month-now-bj0</link>
      <guid>https://dev.to/patriscus/tailwind-my-experience-using-it-for-a-month-now-bj0</guid>
      <description>&lt;p&gt;Let's be honest. Writing CSS can sometimes be a b*tch. As projects grow larger, the CSS styles can become quite hard to maintain - from naming things, trying to align content perfectly and figuring out which selector overrules your new styles.&lt;/p&gt;

&lt;p&gt;As a result, people have come up with many ways to make it easier for us. Some like to use CSS-in-JS. Others are vigilant about using BEM naming to make sure their styles are named descriptively. Frameworks such as Bootstrap &amp;amp; Tailwind are helping by providing a pre-defined API you can use to make your designs come to life.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1rsxkgsrrz4e5b4wnvnw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1rsxkgsrrz4e5b4wnvnw.jpg" alt="Grass field in the wind"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was recently excited to hear that I got the chance to use Tailwind in one of our new projects. I have been meaning to learn more about it as I have heard good feedback within the community and online channels.&lt;/p&gt;

&lt;p&gt;This post is a short summary of all the things I got to learn about Tailwind during the first month of using it and what my experiences were like.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Tailwind?
&lt;/h2&gt;

&lt;p&gt;Tailwind promotes itself as a &lt;em&gt;"utility-first CSS framework for rapidly building custom designs."&lt;/em&gt; The philosophy of Tailwind is to provide an API (utility classes) which you can combine to go from design to implementation. Using these classes in your HTML markup has another effect: all your styles are visible from within the markup itself. What do I mean by that? Let's look at an example:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/patriscus/embed/KKMpPMv?height=600&amp;amp;default-tab=html,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The example shows an image with a rounded border and box shadow applied. The image is contained in a &lt;code&gt;div&lt;/code&gt; that defines padding around it.&lt;/p&gt;

&lt;p&gt;As you can see, not a single (custom) CSS rule was needed. Everything was achieved by using the utility classes Tailwind provides. We are able to get a sense of how the element will be styled just by looking at the HTML directly.&lt;/p&gt;

&lt;p&gt;Tailwind offers many features that make this possible: built-in functionalities for responsive design, pseudo-class variants and other things. Please make sure to check out the &lt;a href="https://tailwindcss.com/docs/utility-first" rel="noopener noreferrer"&gt;docs&lt;/a&gt; to get a sense of all the cool things Tailwind can do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alright enough about Tailwind. How was my experience?
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Pros:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj7o1ayouiufxmxz7ybck.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj7o1ayouiufxmxz7ybck.jpg" alt="Pin with a heart on it"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  It's customizable.
&lt;/h3&gt;

&lt;p&gt;Tailwind has been built with customizability in mind. As of now, I was able to easily change spacing values, font families or colors with ease. The great thing about this is that Tailwind does not restrict you in any way. Although it provides (in my opinion) very sensible default values, you are free to change them as you please.&lt;/p&gt;

&lt;h3&gt;
  
  
  It establishes a rule set for both developers &amp;amp; designers.
&lt;/h3&gt;

&lt;p&gt;With the power of customizability, Tailwind (or more so the Tailwind config) is great at being the source of truth for your designs. After collaborating with designers, it is easy to transfer the properties &amp;amp; values agreed upon (e.g. spacing) to Tailwind. This helps tremendously when implementign designs as all the values (ideally) are in the pool of utility classes. If, for whatever reason, one of those values is modified, all changes are immediately visible in all parts of your application. As an example, let's suppose you change the font size value for &lt;code&gt;xl&lt;/code&gt; from &lt;code&gt;1.25rem&lt;/code&gt; (the default) to &lt;code&gt;1.35rem&lt;/code&gt;. Now every element you have applied the &lt;code&gt;text-xl&lt;/code&gt; utility class will automatically use your new value.&lt;/p&gt;

&lt;h3&gt;
  
  
  No naming. No problems.
&lt;/h3&gt;

&lt;p&gt;Although I initially thought that this aspect will only play a minor role for my development workflow, I have got to love not having to come up with well-named CSS classes. While previously I have enjoyed using BEM naming, I still had to regularly debate with myself on how I should name certain elements. Tailwind removes that part entirely, making you focus more on what really matters: the styles to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Specificity.
&lt;/h3&gt;

&lt;p&gt;As projects grow bigger, maintaining CSS styles tend to also become harder. During the first month, I could also observe that another advantage to using Tailwind is that it requires no effort to overwrite (or add) new styles. In a perfect world, developers wouldn't have to address overly specific CSS selectors which overrule newly applied styles. Unfortunately, I don't live in this perfect world. In the past I have seen selectors constantly clashing with my styles, thus leaving me to add other overly specific styles. While this is not ideal, I am happy to see that Tailwind (so far) removed this as each element is only composed of the utility classes they need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cons:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7c8cwrd411tfzfc1vco7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7c8cwrd411tfzfc1vco7.jpg" alt="A puppy wrapped in a blanket, looking rather sad"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  One off styling.
&lt;/h3&gt;

&lt;p&gt;One of the biggest advantages of Tailwind is that you can craft a well defined configuration upon which your utilties are generated. However, this is also part of one of my biggest pain points - one off styling. Sometimes the design requires to go out of bounds with the options that are laid out to you. Sure you can discuss to add them in the config but sometimes that is also not the best option, as this style might only really be needed in that specific case.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://www.youtube.com/watch?v=J_7_mnFSLDg" rel="noopener noreferrer"&gt;Adam Wathan's great talk on Tailwind best practices&lt;/a&gt;, he mentions that using inline styles can be useful to go around these obstacles. In most cases this tip was already enough for me and I was able to happily move on. In other cases, it still didn't feel quite right (keeping in mind that this is subjective). As an example, inline styles do not support media queries which you might need for one off cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your markup may get polluted.
&lt;/h3&gt;

&lt;p&gt;Moving all your CSS rules from a stylesheet to the HTML markup naturally makes your &lt;code&gt;class=""&lt;/code&gt; attributes grow quite large. Especially when the element needs a lot of those to be responsive and look good on all devices.&lt;/p&gt;

&lt;p&gt;I am not bothered much by it. However, I can understand if other developers may find it ugly or too "noisy".&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;I have been using Tailwind for a month now. So far I have enjoyed the process and I am excited to see how using this framework will scale as more and more of my projects will use it. I would recommend everyone to spend little time playing around with Tailwind and see how well it integrates with your projects.&lt;/p&gt;

&lt;p&gt;If you have used Tailwind, have any questions or just want to say hi, please feel free to comment below. You can also reach out to me on &lt;a href="https://twitter.com/patriscus" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>tailwindcss</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Why I like srcset and why you'll like it too - a quick guide to resolution switching</title>
      <dc:creator>Patrick Ahmetovic</dc:creator>
      <pubDate>Fri, 09 Oct 2020 13:32:40 +0000</pubDate>
      <link>https://dev.to/patriscus/why-i-like-srcset-and-why-you-ll-like-it-too-a-quick-guide-to-resolution-switching-2nc0</link>
      <guid>https://dev.to/patriscus/why-i-like-srcset-and-why-you-ll-like-it-too-a-quick-guide-to-resolution-switching-2nc0</guid>
      <description>&lt;p&gt;It is hard to keep focus on all the different problems we are facing to deliver the best possible experience to our users. One of those is the question of "How can I use sharp images (e.g. for high-DPI devices) while not draining bandwidth for users who might not need it?"&lt;/p&gt;

&lt;p&gt;This post is a short (but hopefully sweet) introduction to &lt;code&gt;srcset&lt;/code&gt; with a focus on resolution switching- a really neat way to solve this problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is srcset?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F01wh4hb9jwcg2gkztrxq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F01wh4hb9jwcg2gkztrxq.jpg" alt="Long exposure image in which a question make was drawn using light"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;srcset&lt;/code&gt; is oftentimes used as an attribute for an HTML &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element. Its purpose is to provide a list of image sources (i.e. URLs) from which the browser can choose from based on additional information you are providing. In this post, we are going to focus on specifying the resolutions. However, please note that &lt;code&gt;srcset&lt;/code&gt; also supports other use cases - feel free to check them out &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Here's a short example on how you can define a list of images along with their resolutions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image_1x.jpg"&lt;/span&gt;
    &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
        image_1x.jpg 1x,
        image_2x.jpg 2x"&lt;/span&gt;
    &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"A beautiful alt description of some image"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In simplified terms, we are basically saying: "Look browser, I have a &lt;code&gt;srcset&lt;/code&gt; defined - &lt;code&gt;image_1x.jpg&lt;/code&gt; is &lt;code&gt;1x&lt;/code&gt; resolution (basically the base), &lt;code&gt;image_2x.jpg&lt;/code&gt; is &lt;code&gt;2x&lt;/code&gt; the resolution" and so on. The browser can then use this information to decide which image to render.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: in the above example, you could also just use &lt;code&gt;image_1x.jpg,&lt;/code&gt; instead of &lt;code&gt;image_1x.jpg 1x,&lt;/code&gt; because &lt;code&gt;1x&lt;/code&gt; is implied. However, I personally like to specify it either way to make it more explicit.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Alright. But how does that help me and the user?
&lt;/h3&gt;

&lt;p&gt;The benefit of using this approach is that the browser will be able to determine what the user will need. Suppose the user is looking at the page using a high-DPI screen (think of Retina devices), the browser will be able to recognize it and say "Whoops, we got a nice screen with good resolution.. the &lt;code&gt;1x&lt;/code&gt; resolution probably won't make the cut so I'll better request and use the image defined as  &lt;code&gt;2x&lt;/code&gt;."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc3350lcqi0iowtoeyxqk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc3350lcqi0iowtoeyxqk.jpg" alt="Long exposure image forming light trails"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The cool part is that this way, you automatically save your users bandwidth when the higher resolution image is not needed as the browser will not make a request to get it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final thoughts
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;srcset&lt;/code&gt; is a very nice tool we can use to optimize our web pages even further. While I have only focused on specifying the resolution, please &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images" rel="noopener noreferrer"&gt;take a look at the other use cases&lt;/a&gt; you might find &lt;code&gt;srcset&lt;/code&gt; helpful for.&lt;/p&gt;

&lt;p&gt;Unfortunately, there's one thing I haven't mentioned yet and that is that &lt;code&gt;srcset&lt;/code&gt; is not supported on IE11. If your project needs to support IE11 you will have to fall back on polyfills or other ways to achieve comparable results. &lt;/p&gt;

&lt;p&gt;I hope you enjoyed this short post. Feel free to comment if you want to leave feedback or just want to say hello. You can also reach out to me at &lt;a href="https://twitter.com/patriscus" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>html</category>
    </item>
    <item>
      <title>A Sticky Situation (position sticky in CSS)</title>
      <dc:creator>Patrick Ahmetovic</dc:creator>
      <pubDate>Tue, 06 Oct 2020 10:37:24 +0000</pubDate>
      <link>https://dev.to/patriscus/a-sticky-situation-position-sticky-in-css-35oe</link>
      <guid>https://dev.to/patriscus/a-sticky-situation-position-sticky-in-css-35oe</guid>
      <description>&lt;p&gt;Many months ago,  I was finding myself implementing a sticky navigation bar using vanilla JS. Not because I didn't know about &lt;code&gt;position: sticky;&lt;/code&gt; but because I needed to support IE11 (😢). So while this initially kept me from checking it out more closely, it made me even happier once I was finally able to use it later on.&lt;/p&gt;

&lt;p&gt;This post is a short primer on what the &lt;code&gt;sticky&lt;/code&gt; value is and where you might find it useful when implementing designs and layouts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is sticky?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/xTiN0ByzdgHIjqZBzq/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/xTiN0ByzdgHIjqZBzq/giphy.gif" alt="Man jumping and sticking on a wall"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sticky&lt;/code&gt; is one of the 5 values the &lt;code&gt;position&lt;/code&gt; property can use as a keyword. Taking a look at the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/position"&gt;MDN documentation&lt;/a&gt;, we can learn that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The element is positioned according to the normal flow of the document, and then offset relative to its nearest scrolling ancestor and containing block (nearest block-level ancestor), including table-related elements, based on the values of top, right, bottom, and left. The offset does not affect the position of any other elements."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's simplify this statement a bit.&lt;/p&gt;

&lt;p&gt;When using the keyword &lt;code&gt;sticky&lt;/code&gt;, you have to specify at least one of the 4 following properties: &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;right&lt;/code&gt;, &lt;code&gt;bottom&lt;/code&gt; or  &lt;code&gt;left&lt;/code&gt;. In simplified terms, these values then determine the "offset" of the sticky behavior, meaning when the stickiness should start.&lt;/p&gt;

&lt;p&gt;Let's take a look at a common use case to see how we would use the &lt;code&gt;top&lt;/code&gt; property: A navigation bar that gets sticky when the user scrolls further down the page:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/patriscus/embed/dyXbpOE?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;As you can see, the navigation bar sticks at the top of the page with (in this case) a zero pixel offset, essentially meaning right at the top of the screen. Feel free to go to the CodePen and play around with the top value. This way, you'll see that the navigation bar will start to stick sooner or later, depending on which value you've entered.&lt;/p&gt;

&lt;p&gt;When you compare sticky to fixed, you can clearly see some similarities. When I was beginning to learn about the sticky value, I initially thought of it as "a delayed position fixed". While in some sense that's still how I think about it, an important aspect is that sticky is confined within the nearest scrollable ancestor.&lt;/p&gt;

&lt;p&gt;Why would you care? Because that means, &lt;strong&gt;sticky stops being sticky when it reaches the end of the ancestor&lt;/strong&gt;. This is a minor detail that initially didn't fit my "delayed fixed position" mindset. And because of that, I tried to come up with a quick visualization on what exactly I mean:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/patriscus/embed/mdEbWqe?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The sticky element stops right at the bottom of the container it is defined in. This is a really neat way to produce layout &amp;amp; designs that require an element to be sticky while scrolling through the page. I implemented a short prototype to show you a potential use case:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/patriscus/embed/MWyNXwx?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Final considerations
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/RrpeMQCWQS3K0/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/RrpeMQCWQS3K0/giphy.gif" alt='Two man standing in front of a whiteboard, one turning and nodding to the audience - text on screen reads "Think about it"'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sticky&lt;/code&gt; made it much more convenient for developers to define elements that need to stick at certain regions of the page. While previously you had to rely on JavaScript for that, you can now simply use the built-in CSS properties to accomplish the same effect with much less overhead and implementation effort.&lt;/p&gt;

&lt;p&gt;However, checking &lt;a href="https://caniuse.com/css-sticky"&gt;caniuse.com&lt;/a&gt; will show you that while the browser support overall is really good, you still have to think about IE11 if you still need to support it. &lt;/p&gt;

&lt;p&gt;I hope this little post was able to help some to hear/learn about position &lt;code&gt;sticky&lt;/code&gt;. If you have any feedback, tips or just generally want to say hi, please feel free to leave a comment. Alternatively, you can hit me up on &lt;a href="https://twitter.com/patriscus"&gt;Twitter&lt;/a&gt; as well.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Would I go to university again?</title>
      <dc:creator>Patrick Ahmetovic</dc:creator>
      <pubDate>Mon, 24 Aug 2020 21:13:44 +0000</pubDate>
      <link>https://dev.to/patriscus/would-i-go-to-university-again-31ad</link>
      <guid>https://dev.to/patriscus/would-i-go-to-university-again-31ad</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Note: This post will be about my experience studying computer science in Vienna. This means that I will probably leave out problems/thoughts/worries out of the room that people in other geographies may have - partially because I am just not aware of those and partially because they didn't apply to my studies. I still hope that you will enjoy the read.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Go to school, continue studies at university and you will get a good job. It's a simple 3-step process society has come up with to live a "successful" life - at least that's how I've picked it up living and growing up in Austria.&lt;/p&gt;

&lt;p&gt;Now that I've finished my bachelor studies, I want to take some time to reflect on the things I have enjoyed or disliked while studying computer science.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pros
&lt;/h2&gt;

&lt;p&gt;Studying at a university comes with a lot of advantages. In this section I want to show some of the main reasons why I would consider doing it again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Everything is planned out
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EEHN_xlG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5zdzoo3chlk8sgmfmsxe.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EEHN_xlG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5zdzoo3chlk8sgmfmsxe.jpg" alt="A picture of a pin board where pins are interconnected by threads"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bachelor studies have the nice property that they follow a certain curriculum. You start with programming classes in the first semester, progress to more advanced algorithms in the second semester and find yourself writing distributed system applications in the fourth. All while simultaneously gathering knowledge in other fields like Operating Systems, Networking, Human-Computer Interaction and more.&lt;/p&gt;

&lt;p&gt;This cuts out all the time you would need to research online to either build a plan yourself or find one that suits your needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Overcoming challenges
&lt;/h3&gt;

&lt;p&gt;University is all about challenges. Exams, presentations, assignments, group projects - everything  is a challenge in itself for which you must work hard to overcome those.&lt;/p&gt;

&lt;p&gt;But I am forever grateful for these experiences - the night where I didn't know why my implementation of &lt;a href="https://www.educative.io/edpresso/what-is-dijkstras-algorithm"&gt;Dijkstra's Algorithm&lt;/a&gt; suggested going right instead of left, the hours I desperately tried to find how the solution to a math equation was "easily obtained" as suggested by the textbook or the worries I had when I saw the assignment title "Develop a ray-tracer" despite having no clue how it works (let alone how it should be implemented).&lt;/p&gt;

&lt;p&gt;When looking at the field of programming, these experiences taught me a valuable lesson: Nobody knows everything in programming. Instead focus on the core concepts, familiarize yourself with the problem at hand, use the resources given to you (shout-out to Stack Overflow) and &lt;strong&gt;just try&lt;/strong&gt;. More often than not, you will see that trying worked out and you've gained new skills and experiences along the way.&lt;/p&gt;

&lt;p&gt;In doing that repeatedly, I have built the confidence to say that I can pick up any languages/frameworks/concepts as long as I just try and experiment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Meeting new people
&lt;/h3&gt;

&lt;p&gt;Universities are usually a confined space in which you wander around from one lecture hall to another. This naturally forces you to meet new people along the way and, eventually, build new relationships with some of them.&lt;/p&gt;

&lt;p&gt;And since everyone is studying the same thing (my university had a separate faculty for computer science), the chances are higher to have common interests with the people around you.&lt;/p&gt;

&lt;p&gt;I have met quite a lot of boys and girls during my time at university. With some of them I disconnected along the way, with others I have build strong relationships that reach far beyond the confinements of university and the related topics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building a network
&lt;/h3&gt;

&lt;p&gt;Similar to the point above, you also interact with professors, tutors and other members of the university. And in some instances, promising opportunities arise from the conversations you have with them.&lt;/p&gt;

&lt;p&gt;I have friends who have landed their first internships through recommendations of their professors. Others got a lead which they converted into stable part-time positions besides studies.&lt;/p&gt;

&lt;p&gt;For example, I was fortunate enough to get a free ticket for the &lt;a href="https://wearedevelopers.com"&gt;WeAreDeveloper&lt;/a&gt; congress from our faculty. There I have landed my first internship after collecting some courage to go to a booth and straight up ask for opportunities. &lt;/p&gt;

&lt;h2&gt;
  
  
  Cons
&lt;/h2&gt;

&lt;p&gt;Unfortunately, not everything was a great experience. This section will unveil some which I consider to be the main pain points while studying at a university.&lt;/p&gt;

&lt;h3&gt;
  
  
  It is stressful
&lt;/h3&gt;

&lt;p&gt;This statement is subjective. However, I am confident in saying that, for most students, computer science is not a piece of cake. &lt;/p&gt;

&lt;p&gt;Each semester you get bombarded with gazillion facts, concepts, terms and other things related to your courses. When finals week arrives, your caffeine intake will probably increase by 400% in order to cram in the last details while you sit at your desk late in the night.&lt;/p&gt;

&lt;p&gt;If you didn't want to fall behind, you had to work hard. For some the pace was just too quick so they eventually dropped out or put their studies on hold. But with enough ambition, it was possible to win the battle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Not everything is up to date
&lt;/h3&gt;

&lt;p&gt;As I've mentioned earlier, in university studies you follow a certain curriculum. While this is one of the main advantages it can also be seen as one of the greatest disadvantages - simply because some course materials are not up to date.&lt;/p&gt;

&lt;p&gt;One day I was watching &lt;a href="https://youtu.be/DonWQh-JxHk?t=97"&gt;a talk given by Sven Peters&lt;/a&gt;. In this talk, he briefly&lt;br&gt;
mentions how the waterfall model was oftentimes not suitable as a software development process and that we evolved to other (agile) methodologies. Well, guess what? I learned about the waterfall model one week prior to watching the talk in my Software Engineering class. On the contrary, my exposure to Scrum, Kanban and other methodologies at university was in the form of&lt;br&gt;
one slide in a ~70 slides presentation.&lt;/p&gt;

&lt;p&gt;I don't want to put that much weight on this example alone. In numerous instances my classes have failed to even look around to see what the current status quo is - which brings me to my next point.&lt;/p&gt;

&lt;h3&gt;
  
  
  You could teach yourself instead
&lt;/h3&gt;

&lt;p&gt;Most of the time I studied for an exam or worked on an assignment I didn't look at the material that was provided by the professors. Instead, I looked at what topic I need to learn and tried to find videos and resources online - because in most cases they were far superior.&lt;/p&gt;

&lt;p&gt;So why would you need the resources the professors have created? For me, the answer is that you don't really need them. I merely used them as reference for which topic we were currently at. I believe everyone can find the resources they need as long as they know what they want to learn.&lt;/p&gt;

&lt;p&gt;I never had the impression that I had access to resources that people outside of university wouldn't have access to. You could buy the recommended books (or try to find it in a library), substitute the presentation slides with online articles and watch videos instead of lectures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Classes don't prepare you for the real world
&lt;/h3&gt;

&lt;p&gt;It may be my subjective perspective. But I believe that university alone fails to prepare you for the real world in software engineering.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j1RNiDHq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s4qnt8ciian9ivdki69e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j1RNiDHq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s4qnt8ciian9ivdki69e.jpg" alt="A road sign pointing both left and right"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was fortunate enough to find a job as a frontend developer shortly after finishing my second semester. This way, I was able to develop skills that I would have never picked up to this extend during my studies. Here's an example tweet, touching on my point:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Given that we spend more time reading code than writing new one, I think it‘s a missed opportunity to not teach refactoring at university. My experience is that everything revolved around finishing new projects, never to improve an existing code&lt;br&gt;
Patrick Ahmetovic (&lt;a href="https://twitter.com/patriscus"&gt;@patriscus&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At university, I never had to work on a bigger project, I never (really) had to read code written by others, I never had to resolve merge conflicts and I never even had to create a pull-request when we worked on a project as a team. I could go on but I'm trying to keep myself short.&lt;/p&gt;

&lt;p&gt;I would just keep in mind that despite all the things you learn, the real world may present itself to be vastly different.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;While I had some unpleasant experiences I would consider my time at university as time well spent. However, I strongly believe that you do not need to get a degree in order to be a developer. At this day and age I would rather see university as an opportunity to meet like-minded people, build the discipline to work on tough topics and develop confidence along the way. You may choose to take those opportunities there, or you might choose to use meetups, platforms (like &lt;a href="https://dev.to"&gt;dev.to&lt;/a&gt;) and online classes (like &lt;a href="https://freecodecamp.com"&gt;freecodecamp.com&lt;/a&gt;) instead - in the end I am certain that you can succeed either way.&lt;/p&gt;

</description>
      <category>learning</category>
      <category>webdev</category>
    </item>
    <item>
      <title>My experience writing a linter for Go</title>
      <dc:creator>Patrick Ahmetovic</dc:creator>
      <pubDate>Sun, 09 Aug 2020 07:35:32 +0000</pubDate>
      <link>https://dev.to/patriscus/my-experience-writing-a-linter-for-go-217l</link>
      <guid>https://dev.to/patriscus/my-experience-writing-a-linter-for-go-217l</guid>
      <description>&lt;p&gt;Linting your source code is oftentimes an integral part in software development processes. Whether it is to check if you misspelled words, violate against a certain code style or recklessly used tabs over spaces (don't worry, I won't judge), linters offer a great way to automate mundane tasks to free up time and energy for other things.&lt;/p&gt;

&lt;p&gt;As the time had arrived for me to work on my bachelor thesis, I decided on implementing a linter for source code written in Go - primarily because I wanted to learn a new language and always wondered if I could write a linting application myself.&lt;/p&gt;

&lt;p&gt;In this post I want to explain some of the concepts I have picked up while working on the project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Linting using an Abstract Syntax Tree (AST)
&lt;/h3&gt;

&lt;p&gt;Abstract Syntax Trees decompose your source code and represent it in a tree form. This way you can traverse the resulting tree, enabling you to collect information you are interested in.&lt;/p&gt;

&lt;p&gt;Let's look at a really small example of what I mean by "tree form":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tItZlkij--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/83cq3uvwg6w9tkptommc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tItZlkij--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/83cq3uvwg6w9tkptommc.jpg" alt="Sample AST tree for a simple condition"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Go, the standard package provides us with &lt;code&gt;go/ast&lt;/code&gt; which already implements a lot of the functions you would typically need for building and traversing a tree.&lt;/p&gt;

&lt;p&gt;In the scenario above, you would be able to inspect the components by looking at the &lt;code&gt;.X&lt;/code&gt; (a) and &lt;code&gt;.Y&lt;/code&gt; (b) components of &lt;code&gt;.BinaryExpr&lt;/code&gt; (==).&lt;/p&gt;

&lt;p&gt;For one of my use cases, I needed to check how many conditional operands a specific condition has. I then used the information to suggest decomposing the condition to smaller pieces if the count exceeds a limit.&lt;/p&gt;

&lt;p&gt;The following code shows how a conditional statement gets evaluated to eventually obtain the total count of operands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validator&lt;/span&gt; &lt;span class="n"&gt;DecomposeConditionsValidator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;evaluateConditionalExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stmt&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;Expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;expression&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;stmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&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;BinaryExpr&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&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;validator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;evaluateConditionalExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;evaluateConditionalExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&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;ParenExpr&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;validator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;evaluateConditionalExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the tree nodes are traversed in a recursive manner, thus providing us with the sum of operands when the recursive invocation stops.&lt;/p&gt;

&lt;h3&gt;
  
  
  Traversing the file system
&lt;/h3&gt;

&lt;p&gt;Linting applications usually validate each file recursively, starting from a root directory. For each file, a AST is constructed which is then used as the input for the rules/validators setup by the author.&lt;/p&gt;

&lt;p&gt;Usually you can use packages for your programming language that abstract the file system by providing methods to interact with it. I was surprised to see how neatly Go is supporting recursive traversal with &lt;code&gt;path/filepath&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's a simplified view on how I used recursive file traversal:&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;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Walk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;linter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&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;FileInfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// construct AST tree&lt;/span&gt;
  &lt;span class="c"&gt;// initialize data structure to store results&lt;/span&gt;

  &lt;span class="c"&gt;// for each rule&lt;/span&gt;
  &lt;span class="c"&gt;//    check the AST tree&lt;/span&gt;
  &lt;span class="c"&gt;//    append to the results&lt;/span&gt;

  &lt;span class="c"&gt;// add results to a linting report structure &lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// return linting report&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Defining the rules (validators)
&lt;/h3&gt;

&lt;p&gt;Now we have established how a linter traverses the file system and how source code is represented by an abstract syntax tree. Another crucial part of the system is the implementation of validators (or whatever you want to call them).&lt;/p&gt;

&lt;p&gt;As an example, let's say you wanted to check the length of each variable name in order to suggest more expressive names when the length is only 1 (let's discard valid reasons you might use such short names - e.g. Point.X or Point.Y coordinates). You would then express this rule as functions/methods/classes (you choose), usually defined in separate files.&lt;br&gt;
As an example, &lt;a href="https://github.com/eslint/eslint/tree/master/lib/rules"&gt;you can check how ESLint organizes their rules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the use case above, you could for example represent "fail when the variable name length is below a limit" as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;elem&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;statement&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lhs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;identifier&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&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="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;identifier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rule&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Limit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Failed&lt;/span&gt;
                &lt;span class="n"&gt;identifierNames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;identifierNames&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;identifier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Displaying the results
&lt;/h3&gt;

&lt;p&gt;In order to decouple the presentation of the linting results from the creation, I defined a common report structure to store the output generated by the program. Here is a sample structure I have used for my linter:&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;Report&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;Id&lt;/span&gt;           &lt;span class="n"&gt;primitive&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObjectID&lt;/span&gt; &lt;span class="s"&gt;`bson:"_id"`&lt;/span&gt;
    &lt;span class="n"&gt;Timestamp&lt;/span&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;          &lt;span class="s"&gt;`bson:"timestamp"`&lt;/span&gt;
    &lt;span class="n"&gt;FileCount&lt;/span&gt;    &lt;span class="kt"&gt;int&lt;/span&gt;                &lt;span class="s"&gt;`bson:"fileCount"`&lt;/span&gt;
    &lt;span class="n"&gt;ErrorCount&lt;/span&gt;   &lt;span class="kt"&gt;int&lt;/span&gt;                &lt;span class="s"&gt;`bson:"errorCount"`&lt;/span&gt;
    &lt;span class="n"&gt;WarningCount&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;                &lt;span class="s"&gt;`bson:"warningCount"`&lt;/span&gt;
    &lt;span class="n"&gt;PassedCount&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;                &lt;span class="s"&gt;`bson:"passedCount"`&lt;/span&gt;
    &lt;span class="n"&gt;Files&lt;/span&gt;        &lt;span class="n"&gt;FileResultList&lt;/span&gt;     &lt;span class="s"&gt;`bson:"files"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apart from the file results themselves, some metadata is stored for later processing. While the structure above may not be the most extensible one, it was sufficient enough for me to implement the requirements of the project.&lt;/p&gt;

&lt;p&gt;For later display, I stored the results in MongoDB and retrieved them by using a REST API that is being called by a React frontend application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;It is interesting to see how many components need to interact&lt;br&gt;
in order to provide valuable feedback for developers. First we traverse through the file system while constructing an abstract syntax tree for each file. Then we can lint the source code with validators to eventually display the results to the users.&lt;/p&gt;

&lt;p&gt;However, given the short time span, I wasn't able to fully implement all of the capabilities a good linter usually provides. Some of them include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Annotations to ignore lines or blocks of source code&lt;/li&gt;
&lt;li&gt;Automatically fix warnings/errors found&lt;/li&gt;
&lt;li&gt;Extensive configuration options&lt;/li&gt;
&lt;li&gt;IDE integrations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While I have laid out some of the core components of my linter, I still hope to eventually return and learn more about the inner-workings of the mechanisms outlined above.&lt;/p&gt;

</description>
      <category>go</category>
      <category>linter</category>
    </item>
  </channel>
</rss>
