<?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: James Ford</title>
    <description>The latest articles on DEV Community by James Ford (@psyked).</description>
    <link>https://dev.to/psyked</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%2F8039%2Fcb131e28-1fc6-4b65-a074-c2ad15460196.jpeg</url>
      <title>DEV Community: James Ford</title>
      <link>https://dev.to/psyked</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/psyked"/>
    <language>en</language>
    <item>
      <title>On the establishment of Engineering Guidelines</title>
      <dc:creator>James Ford</dc:creator>
      <pubDate>Wed, 28 Sep 2022 06:42:15 +0000</pubDate>
      <link>https://dev.to/psyked/on-the-establishment-of-engineering-guidelines-3mg1</link>
      <guid>https://dev.to/psyked/on-the-establishment-of-engineering-guidelines-3mg1</guid>
      <description>&lt;h2&gt;
  
  
  A shared vision
&lt;/h2&gt;

&lt;p&gt;One of the most challenging aspects of leading software engineers is achieving a consensus. This is true everywhere I've had experience, and with any scale and any cohort and on any subject.&lt;/p&gt;

&lt;p&gt;A consensus is important for practical things such as team harmony, code consistency and quality of output but it is especially important for ephemeral topics such as "strategy" or "best practices."&lt;/p&gt;

&lt;p&gt;The trouble is that much of the "wisdom" and "knowledge" held, internalised and enshrined by engineers is accumulated not by a teachable linear path but by an inefficient process of osmosis from the industry zeitgeist making it quite impossible to replicate. Being impossible to replicate makes it difficult to teach, as it robs you of some of the resources you'd use to convert and convince others. &lt;/p&gt;

&lt;p&gt;This experience you have - the lessons learnt or the things that have read which 'resonated' with you during your time as software engineer - are the treasures amidst the strata of your career, and the things that further influence your thought processes and decision making. They are the things which make you a leader, instead of just a good coder, and it's those things that we want to extract, distil, critically evaluate and then disseminate.&lt;/p&gt;

&lt;p&gt;There's a problem with knowledge transfer that can be alleviated by better identifying &lt;em&gt;what&lt;/em&gt; to share, but transferring the wisdom - the opinions and interpretations of an individual - is another challenge of its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Codified Wisdom
&lt;/h2&gt;

&lt;p&gt;Enter then, our Engineering Guidelines. These are the output of a concerted effort to codify and document the wisdom of individuals, identify common themes, name them and prioritise them in accordance with our business strategy.&lt;/p&gt;

&lt;p&gt;The goal of our Engineering Guidelines is to persist and achieve consistency over a longer time period, and scale better and reach further than any individual could on their own.&lt;/p&gt;

&lt;p&gt;The source of truth for our guidelines is their written form - a collection of documents in our Wiki - but we can remix and reformat the content as appropriate for different scenarios, whether that be a workshop, presentation or release checklist.&lt;/p&gt;

&lt;p&gt;The most important part of these guidelines is that they're documented, explained and evidenced. This means that they can be tracked, challenged, evolved and extended as requirements, technologies and trends also evolve over the course of time.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>guidelines</category>
      <category>leadership</category>
      <category>influencing</category>
    </item>
    <item>
      <title>Better Code Reviews.</title>
      <dc:creator>James Ford</dc:creator>
      <pubDate>Tue, 03 Sep 2019 06:40:11 +0000</pubDate>
      <link>https://dev.to/psyked/better-code-reviews-5b28</link>
      <guid>https://dev.to/psyked/better-code-reviews-5b28</guid>
      <description>&lt;h2&gt;
  
  
  Reducing fear and friction in the review process.
&lt;/h2&gt;

&lt;p&gt;Code reviews are an essential part of developing software. And potentially one of the most challenging parts, because it involves exercising skills that aren’t necessary to write code, like diplomacy, tact and judgement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bOgArl2X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2656/1%2Ae_GcUPHFZitEAn0DUrp7FA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bOgArl2X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2656/1%2Ae_GcUPHFZitEAn0DUrp7FA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A problem that can be solved with code might only have one correct solution, but that solution can be written in many different ways. And many of those different ways satisfy other unwritten criteria, such as execution time, capacity for reuse, simplicity, comprehensibility, portability and consistency.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Test-driven_development"&gt;Test-Driven-Development (TDD)&lt;/a&gt; process makes checking technical solutions to problems simpler because it puts an emphasis on identifying problems to be solved and the ways of verifying the technical accuracy of a solution in advance of actually writing any code. But when we perform a code review, we’re looking for more than just the solution to a problem, because that verification is a boolean — the tests either pass, or they fail.&lt;/p&gt;

&lt;p&gt;Code reviews are less about the solution and more about the shades of grey, and applying the unwritten rules of software development.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unwritten rules
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Having unwritten rules of software development is a bad thing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Technical solutions are nice because they’re exact, precise and all aspects of them can be quantified. People solutions are complicated because they’re everything else.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jOCsmQWt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2680/1%2AZHwn8cArmOGrRm485LZldw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jOCsmQWt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2680/1%2AZHwn8cArmOGrRm485LZldw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Code reviews are the point at which another person comes and looks at the code you’ve written, and picks out its flaws. Maybe the code you’ve written is too complex, maybe it’s too simple. Maybe your variable names aren’t consistent with the rest of the codebase, or it’s not &lt;a href="https://en.wikipedia.org/wiki/Object-oriented_programming"&gt;Object-Oriented&lt;/a&gt; enough or it’s not &lt;a href="https://en.wikipedia.org/wiki/Functional_programming"&gt;Functional&lt;/a&gt; enough. Maybe, maybe, maybe.&lt;/p&gt;

&lt;p&gt;That’s the trouble with code reviews — they can be subjective, inconsistent in their scrutiny or based on unpredictable criteria.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don’t stop reviewing!
&lt;/h3&gt;

&lt;p&gt;We shouldn’t do away with code reviews. Code reviews are an excellent tool for maintaining consistency and a shared understanding in a team. Code reviews are an essential part of software development, and they should be done in all directions — juniors reviewing seniors and vice versa.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7lSdDF4A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2740/1%2Aybbr-iq5zv6LiTnOtGnzng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7lSdDF4A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2740/1%2Aybbr-iq5zv6LiTnOtGnzng.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But code reviews can easily feel like personal attacks, which is why we have things like the &lt;a href="https://retrospectivewiki.org/index.php?title=The_Prime_Directive"&gt;Prime Directive&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Regardless of what we discover, we understand and truly believe that everyone did the best job they could, given what they knew at the time, their skills and abilities, the resources available, and the situation at hand. — &lt;a href="http://www.retrospectives.com/pages/retroPrimeDirective.html"&gt;Norm Kerth&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can’t control humans. We can encourage better behaviours and be more mindful about the feedback that’s delivered in a review process, but it’s always going to be subjective, for the reviewer and reviewee.&lt;/p&gt;

&lt;p&gt;Part of the answer to making code reviews better might well lie in removing the unknown criteria from the process — either by restricting review comments to only criteria specified in the original task, or by broadening scope of the task definition to include all possible ways in which a solution could be evaluated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Restricting feedback
&lt;/h3&gt;

&lt;p&gt;Restricting feedback during a review isn’t an approach that’s likely to result in long term happiness and team contentment. Reviews are an opportunity for engineers to express their thoughts, and censoring feedback in one place is only likely to make it emerge again in another channel. Isolating discussions to specific topics tends to lead to an endless series of disconnected conversations that distract from the original problem that spawned them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Broader acceptance criteria
&lt;/h3&gt;

&lt;p&gt;Broader criteria can reduce the surprise elements of a code review, but it can quickly become overly prescriptive about the way a problem is solved rather than defining what an acceptable solution looks like. Not only that, broadening the criteria for a task to include all possible measures of acceptable code runs the risk of creating impossible tasks for engineers to take on — solving the problem becomes too daunting, the feasibility of achieving certain criteria might be unknown at the beginning or impossible to satisfy, or the proposed solution is over-engineered and needlessly complex when a simpler solution would suffice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OjI3xECR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2732/1%2ABtyDT7fENtRa5D-SmwS_fw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OjI3xECR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2732/1%2ABtyDT7fENtRa5D-SmwS_fw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The best solution to the challenge of making code reviews better likely has nothing to do with what policy or process actually gets put into place to facilitate them. The technical solution is binary — it works, or it doesn’t — but the opinions and experiences of engineers vary, leading to unpredictable results and quality standards in reviews.&lt;/p&gt;

&lt;p&gt;A code review has to be organic, as it’s an opportunity for all members of the development team to have oversight and give input on each others’ code prior to it being finalised. It’s an opportunity for everyone to learn and for the team to make collective decisions about the future direction of other tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Code Reviews
&lt;/h2&gt;

&lt;p&gt;The problem with having an organic approach to code reviews is that it seems to encourage purely functional commentary, which focuses only on the things that need to change, and not the elements which are good.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--onmKKtb6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2204/1%2A2bcWexIZDKKmyIan9T1QHA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--onmKKtb6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2204/1%2A2bcWexIZDKKmyIan9T1QHA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If a code review is only about highlighting the negatives, the overall result is negative. It should have some positives as well. Focussing exclusively on the bad elements, and where changes are perceived to be needed only serves to highlight and exacerbate any underlying divisions in the team. And that’s bad. However well-meaning a review might be, it can be received as a personal attack. We’re human and we respond emotionally to attacks, and negative reviews given improperly sow dissent and can reinforce any underlying differences in age, experience, gender, seniority, organisational structure, culture or personality.&lt;/p&gt;

&lt;p&gt;I’m fortunate in that I’m a middle aged white male working in the tech industry, I have years of development experience, I’m the Technical Lead of my team and I’m familiar with my code base. I shouldn’t have a reason to feel attacked when someone reviews my code, and I have no underlying feelings of imposter syndrome or voices that tell me this industry isn’t for me. But not everyone has these luxuries of their background, and even I feel an emotional when my code is reviewed negatively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Be kind.
&lt;/h3&gt;

&lt;p&gt;The bottom line to this is, be kind. Be respectful, be diplomatic and give feedback about the positives as well as the negatives — it doesn’t all have to be an actionable list of tasks to complete, and treat it as a review and not a nitpicking exercise. As a team you’re working to create a shared understanding and a unified codebase. Treat your code reviews accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Review Checklist
&lt;/h2&gt;

&lt;p&gt;I don’t believe that better code reviews can be mandated by any change in processes or ways of working. Code Reviews are a human-driven part of development and as such rely on the behaviours of humans. The best way to encourage behaviours is to lead with them, and to help me lead with them I follow an (informal) checklist which I’ve put together for myself, which looks as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Has this person contributed code before?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Are they contributing in the format expected by the team?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Are the automated tests passing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Have new automated tests been added?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What’s bad about this code?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What’s good about this code?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What’s non-critical but worth considering as an extension?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this code production ready?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What else would I say if we were face-to-face?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nSTPslQ6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2458/1%2AlVJzlGMYp6Jzn6AM3igZKA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nSTPslQ6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2458/1%2AlVJzlGMYp6Jzn6AM3igZKA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that’s it. No magic formulas I’m afraid, just be a better human.&lt;/p&gt;

&lt;p&gt;Illustrations courtesy of &lt;a href="https://undraw.co/"&gt;unDraw&lt;/a&gt;&lt;/p&gt;

</description>
      <category>collaboration</category>
      <category>codereview</category>
      <category>work</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Checking Availability in Office 365</title>
      <dc:creator>James Ford</dc:creator>
      <pubDate>Wed, 13 Feb 2019 12:27:27 +0000</pubDate>
      <link>https://dev.to/psyked/checking-availability-in-office-365-4893</link>
      <guid>https://dev.to/psyked/checking-availability-in-office-365-4893</guid>
      <description>&lt;h4&gt;
  
  
  How to check for meeting room availability using the (beta) Office 365 Graph API.
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Strange as it may seem this isn’t something that’s obvious to figure out, so allow me to save you half an hour of searching and just give you the answer.&lt;/p&gt;
&lt;/blockquote&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AxxKgPqB6Hkmx6y3gJS8LwA.jpeg" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AxxKgPqB6Hkmx6y3gJS8LwA.jpeg"&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/photos/mcLpPD36-2k?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;rawpixel&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/meeting?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Background
&lt;/h3&gt;

&lt;p&gt;At the office we have a range of virtual and physical meeting rooms, but as good as off-the-shelf tools are, it’s still a laborious task to find an available room at a moment’s notice. It would be nice to tap into some APIs and be able to build our own custom tooling to make the availability more… visible.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Answer; aka. How to do it:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;First, get an API Access Token.&lt;/li&gt;
&lt;li&gt;Make a Graph API request with a JSON payload that outlines the target email addresses and the time period to check.&lt;/li&gt;
&lt;li&gt;Parse the response into usable data.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Getting an Access Token
&lt;/h4&gt;

&lt;p&gt;Before starting you need an &lt;em&gt;Access Token,&lt;/em&gt; which you can either get by following the steps in &lt;a href="https://docs.microsoft.com/en-us/graph/auth-overview" rel="noopener noreferrer"&gt;the official documentation&lt;/a&gt;, or to make things simpler you can try out requests using the Graph Explorer tool:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.microsoft.com/graph/graph-explorer/" rel="noopener noreferrer"&gt;Graph Explorer - Microsoft Graph&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Making a Graph API request
&lt;/h4&gt;

&lt;p&gt;Make a POST request to the /me/calendar/getschedule Graph API endpoint: &lt;a href="https://graph.microsoft.com/beta/me/calendar/getschedule" rel="noopener noreferrer"&gt;https://graph.microsoft.com/beta/me/calendar/getschedule&lt;/a&gt;, — which is currently only available in beta — using a JSON request body that looks something like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This request body includes the accounts for availability to be checked; &lt;em&gt;Schedules,&lt;/em&gt; the start and end of the time period to check and the level of detail to look at; the &lt;em&gt;availaibilityViewInterval&lt;/em&gt; — all of which affects the level of detail that comes back in the response.&lt;/p&gt;

&lt;p&gt;By way of example, we can make this request using CURL, like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Or to make this same request with Javascript, like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Or just use the Graph Explorer:&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AVQA7cjULHa_YPoxh1i1fWw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AVQA7cjULHa_YPoxh1i1fWw.png"&gt;&lt;/a&gt;Using the Graph Explorer UI&lt;/p&gt;

&lt;h4&gt;
  
  
  Parse the response
&lt;/h4&gt;

&lt;p&gt;The response that comes back from the API will look something like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This response contains a object for each Schedule requested, a representation of the schedule availability, and the available details of each item in the schedule.&lt;/p&gt;

&lt;p&gt;I find the &lt;em&gt;availabilityView&lt;/em&gt; portion of the API response interesting — it’s a string that’s generated dynamically and represents the high-level availability for segments of time, beginning at the start time and split based on the initial &lt;em&gt;availabilityViewInterval&lt;/em&gt; property of the POST request. The values in this string correspond with the following availability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 = free
1 = tentative
2 = busy
3 = out of office
4 = working elsewhere
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This response can save you recursively parsing the &lt;em&gt;scheduleItems&lt;/em&gt;, and you only have to split the string on each character to calculate availability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alternatives / the Explanation:
&lt;/h3&gt;

&lt;p&gt;Checking calendars — whether it be for Meeting Rooms or for attendees — seems like it should be trivial task but it’s historically been quite complicated, because the APIs that expose the data needed to power this functionality usually requires read-level permissions from the calendar owner.&lt;/p&gt;

&lt;p&gt;When I first attempted to build this functionality, I assumed that I could simply check the public calendar of the 20-or-so meeting rooms and collate the data myself, but I quickly discovered that the API doesn’t work that way, and each of the meeting rooms would require me to have been granted explicit permissions to their calendar, which wasn’t going to happen.&lt;/p&gt;

&lt;p&gt;Fortunately, the &lt;em&gt;getSchedule&lt;/em&gt; endpoint of the API exists under/me/calendar , so it just works, without the need for additional permissions. Counter-intuitive? Maybe. But it works, so we’ll overlook that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Official Documentation
&lt;/h3&gt;

&lt;p&gt;Here’s a link to the official documentation for this API endpoint:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/graph/outlook-get-free-busy-schedule" rel="noopener noreferrer"&gt;Get free/busy schedule of users and resources (preview) - Microsoft Graph&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s all for now — so let’s go check schedules!&lt;/p&gt;




</description>
      <category>tech</category>
      <category>schedulingsoftware</category>
      <category>api</category>
      <category>office365</category>
    </item>
    <item>
      <title>Inspired by Open Source.</title>
      <dc:creator>James Ford</dc:creator>
      <pubDate>Tue, 05 Feb 2019 11:10:18 +0000</pubDate>
      <link>https://dev.to/psyked/inspired-by-open-source-2p96</link>
      <guid>https://dev.to/psyked/inspired-by-open-source-2p96</guid>
      <description>&lt;h4&gt;
  
  
  Inner-sourcing at Compare the Market.
&lt;/h4&gt;

&lt;p&gt;The Open Source community is an inspiration for us at ComparetheMarket — how it operates, the quality of their output and the ways they manage and engage with the community — all of it raises our expectations and standards, and I love that. 😍&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Inner Sourcing?
&lt;/h4&gt;

&lt;p&gt;We’re unlikely to ever really be able to take our internal code and make it open source, but inspired by the open-source community and in particular by Paypal’s inner-sourcing initiative we’ve created our own ‘inner-sourcing’ initiative, to take our internal collaboration to “the next level.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://paypal.github.io/InnerSourceCommons/" rel="noopener noreferrer"&gt;InnerSource Commons&lt;/a&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%2Fcdn-images-1.medium.com%2Fmax%2F480%2F1%2ATdp9_xM-umMUGyY3GzI1rA.gif" 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%2Fcdn-images-1.medium.com%2Fmax%2F480%2F1%2ATdp9_xM-umMUGyY3GzI1rA.gif"&gt;&lt;/a&gt;Next Level, here we come…&lt;/p&gt;

&lt;h4&gt;
  
  
  Embracing GitHub
&lt;/h4&gt;

&lt;p&gt;As a business we’ve traditionally used JIRA to track projects, but the GitHub UI feels more suited to open source style (collaborative) projects. We made the decision early on to embrace GitHub, and as much as possible stick to using only a single platform. We’ve incrementally adopted more and more features available through GitHub, and although other platforms are available, we always tried to work with the platforms we had available than introduce anything new.&lt;/p&gt;

&lt;p&gt;Without further ado, here’s a few of things that our team has adopted, inspired by open source…&lt;/p&gt;

&lt;h3&gt;
  
  
  Documentation
&lt;/h3&gt;

&lt;p&gt;Yeah, everyone has documentation. But what format, what kind, what quality and for which audience is the documentation produced? Projects like &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; set the gold standard here, with a broad coverage of different kinds of docs tailored to different audiences: starting with introductory concepts, tutorials, and moving through to highly detailed technical specifications.&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7ayHFm_JP7eZ1xkFrT_ofw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7ayHFm_JP7eZ1xkFrT_ofw.png"&gt;&lt;/a&gt;Our existing Storybook — based component documentation&lt;/p&gt;

&lt;p&gt;We already had &lt;a href="https://storybook.js.org/" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; for documenting our project, but now we’ve introduced our own hand-authored web-based documentation pages built with the aid of &lt;a href="https://docusaurus.io/" rel="noopener noreferrer"&gt;Docusaurus.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docusaurus.io/" rel="noopener noreferrer"&gt;Docusaurus · Easy to Maintain Open Source Documentation Websites&lt;/a&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AShjZwBxmRXHBLuDJqPygvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AShjZwBxmRXHBLuDJqPygvw.png"&gt;&lt;/a&gt;Our Docusaurus — powered documentation pages.&lt;/p&gt;

&lt;p&gt;Of course, the technology that drives a system isn’t important, it’s the content and how it’s written that matters most. We channel all of our contributors to a single website for our documentation, and for everything we produce we try to include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High-level conceptual overviews,&lt;/li&gt;
&lt;li&gt;Contributor guidelines,&lt;/li&gt;
&lt;li&gt;Manually-authored documentation,&lt;/li&gt;
&lt;li&gt;Auto-generated API documentation,&lt;/li&gt;
&lt;li&gt;‘Quick start’ instructions,&lt;/li&gt;
&lt;li&gt;Detailed step-by-step tutorials and a few bits more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What’s really neat is Docusaurus’s own integration for editing pages via GitHub Pull Requests, making it really easy for readers to make their own contributions to the docs and expand or correct things as they work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Semantic Versioning
&lt;/h3&gt;

&lt;p&gt;Adopting semantic versioning was almost a no-brainer. Almost every open source library uses it, so it’s already an accepted part of the developer consciousness, and it’s a useful framework for the team because it really makes us reflect on the importance and severity of changes that we make when we release new versions of our code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;Semantic Versioning 2.0.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It took us a little while to properly understand how to apply Semantic Versioning to our library and we made a few mistakes at the start, but we wouldn’t be without it now. We took a lot of ideas and attitudes towards versioning from the &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; team and embedded them into our workflow, and have established our own set of scripts to give us an element of automation and a set of workspace pre-release checks before we publish, to avoid repeating any common errors when publishing versions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monorepos
&lt;/h3&gt;

&lt;p&gt;When we begin planning our new library we started off with multiple projects, each with their own separate GitHub repository, but that quickly started to become difficult and tedious to manage.&lt;/p&gt;

&lt;p&gt;Before long we were in a situation where feature requests, issue reports and pull requests were being raised against multiple repositories, or the wrong repository, or would have knock-on effects on others and the administrative overhead of keeping everything compatible and up-to-date became overwhelming. What we needed was to establish a ‘single source of truth’ and find a way of collating feedback and disseminating updates.&lt;/p&gt;

&lt;p&gt;Fortunately others like &lt;a href="https://lernajs.io/" rel="noopener noreferrer"&gt;Babel 🐠&lt;/a&gt; have already encountered this challenge and solved it with the help of Monorepos — single repositories with multiple output packages — so it made a lot of sense for us to explore adopting the same approach for our own project. We did that with a project called &lt;a href="https://lernajs.io/" rel="noopener noreferrer"&gt;Lerna.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lernajs.io/" rel="noopener noreferrer"&gt;Lerna · A tool for managing JavaScript projects with multiple packages.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pull Requests
&lt;/h3&gt;

&lt;p&gt;Pull Requests are our strategy for contributing to the codebase, from people both internal and external to the core dev team. They serve as the nexus for our discussions about code, motivations for a change, making our work as transparent as possible.&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%2Fcdn-images-1.medium.com%2Fmax%2F776%2F1%2AjqTHa2Rxn9kI_YZUZLJIHQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F776%2F1%2AjqTHa2Rxn9kI_YZUZLJIHQ.png"&gt;&lt;/a&gt;Pull Request comments image, from the GitHub docs&lt;/p&gt;

&lt;p&gt;The core team remain the only ones able to merge code into the main branch and to publish releases (more on that in a moment) but Pull Requests allow anyone in the company to propose a code change, at any point, without going through other formal processes.&lt;/p&gt;

&lt;p&gt;In addition, we work in a tightly regulated industry and so have legal and compliance considerations for most things we do, and Pull Requests give us the ability to easily peer review and ‘sign off’ on technical changes before adopting them and allow for reviews and refinement before incorporating anything into the main development branch.&lt;/p&gt;

&lt;p&gt;On the practical side of things we use branch-level permissions, required status checks, automated testing and commit squashing to keep things manageable. We keep as many of these checks as possible automated and they come from sources like the GitHub Marketplace (more on that in a moment.) Branch-level permissions and required status checks give us a balance of flexibility — the ability to restrict anyone from pushing to the master branch without approval from another human, for example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://help.github.com/articles/about-required-status-checks/" rel="noopener noreferrer"&gt;About required status checks - User Documentation&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  (GitHub) Webhooks
&lt;/h3&gt;

&lt;p&gt;Manual reviews of code are one thing, but we also have a series of automated checks and triggers that come from Pull Requests and commits.&lt;/p&gt;

&lt;p&gt;To make our reviews easier we automate as much as we can, and as such we’ve adopted GitHub webhook integrations with systems like GoCD, Jenkins and our own homemade tools.&lt;/p&gt;

&lt;p&gt;We use these tools to run automated unit tests, code linting checks, avoid committing work-in-progress code, ensure that change log files are updated and integrate with our JIRA systems.&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%2Fcdn-images-1.medium.com%2Fmax%2F778%2F1%2AtJQnFiG3FZ4bIexJO1WoEA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F778%2F1%2AtJQnFiG3FZ4bIexJO1WoEA.png"&gt;&lt;/a&gt;Required status checks image, from the GitHub docs&lt;/p&gt;

&lt;p&gt;For the future we’ve got our sights set on adding things like automated visual regression and accessibility testing, cross-browser and integration tests, code styles and linting, just to make it that little bit easier to keep our standards high.&lt;/p&gt;

&lt;p&gt;At the moment, we’re currently using &lt;a href="https://github.com/apps/probot-changelog" rel="noopener noreferrer"&gt;changelog,&lt;/a&gt; &lt;a href="https://github.com/marketplace/wip" rel="noopener noreferrer"&gt;WIP&lt;/a&gt; and &lt;a href="https://probot.github.io/apps/auto-comment/" rel="noopener noreferrer"&gt;Auto-comment,&lt;/a&gt; as well as our own GoCD server integration and &lt;a href="https://github.com/psyked/github-jira-integration" rel="noopener noreferrer"&gt;Github-JIRA-integration&lt;/a&gt; plugins:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/apps/probot-changelog" rel="noopener noreferrer"&gt;Build software better, together&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://probot.github.io/apps/wip/" rel="noopener noreferrer"&gt;Work In Progress&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://probot.github.io/apps/auto-comment/" rel="noopener noreferrer"&gt;Auto-comment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/psyked/github-jira-integration" rel="noopener noreferrer"&gt;psyked/github-jira-integration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the future, we’d love to get involved with something like CodeCov and/or GitHub Actions. As Yoda once said, &lt;em&gt;“Always in motion, the future is…”&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://codecov.io/" rel="noopener noreferrer"&gt;Code Coverage Done Right | Codecov&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.github.com/actions/" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Releases (on GitHub)
&lt;/h3&gt;

&lt;p&gt;Hot on the heels of Semantic Versioning is GitHub releases. Arguably this seems like a small thing, but let me tell you why it has a significant impact…&lt;/p&gt;

&lt;p&gt;As we build our library of code we periodically publish releases. We use semantic versioning and we publish releases to an internal NPM Registry, and then we communicate this to dependent project teams. So we have our changelog, our documentation, and our semantic versioning. On top of this there’s also our internal NPM Registry and Slack channel where we publicise our releases. All of these channels also have a lot of other things also happening in them, so there’s a lot of noise to filter through if you only want to discover the latest releases.&lt;/p&gt;

&lt;p&gt;With a little bit of post-publish scripting we’ve tied together the GitHub Releases interface with our actual release process. Now whenever we publish to NPM we auto-update the release and release notes on GitHub, and this becomes a good long-term record of releases that’s slightly easier to work with than the changelog alone.&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AV0MeMykeSznnXjTmdfRJ-g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AV0MeMykeSznnXjTmdfRJ-g.png"&gt;&lt;/a&gt;Screenshot from the GitHub releases interface&lt;/p&gt;

&lt;p&gt;And finally…&lt;/p&gt;

&lt;h3&gt;
  
  
  Contributor Swag
&lt;/h3&gt;

&lt;p&gt;All the best projects have stickers and contributor swag as incentives and rewards, and everyone* loves to display their allegiance via laptop stickers.&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARfedvHYZKGKGTxnkuNQ8gA.jpeg" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARfedvHYZKGKGTxnkuNQ8gA.jpeg"&gt;&lt;/a&gt;Pictured: One cool laptop.&lt;/p&gt;

&lt;p&gt;We want to encourage contributions from as many people as possible in our inner sourcing strategy, but sometimes just saying ‘thanks’ doesn’t seem enough. So as an extra surprise for our contributors, we’ve arranged for some limited-edition contributor swag to be produced and distributed to everyone that has contributed to our project 😄&lt;/p&gt;




</description>
      <category>tech</category>
      <category>opensource</category>
      <category>workflowautomation</category>
      <category>innersource</category>
    </item>
    <item>
      <title>Recognition and Rewards</title>
      <dc:creator>James Ford</dc:creator>
      <pubDate>Tue, 04 Dec 2018 13:44:59 +0000</pubDate>
      <link>https://dev.to/psyked/recognition-and-rewards-1l9i</link>
      <guid>https://dev.to/psyked/recognition-and-rewards-1l9i</guid>
      <description>&lt;h4&gt;
  
  
  Incentivising gratitude in the workplace
&lt;/h4&gt;

&lt;p&gt;Being recognised and rewarded for your efforts in the workplace is important, as is taking the time to recognise and reward others. Taking the time to deliver a direct, verbal expression of gratitude can mean a lot to its recipient, but adding a tangible reward makes it even better.&lt;/p&gt;

&lt;p&gt;Common sense says gratitude and appreciation for their efforts makes people feel happier. Science says happier people are more resilient, more motivated and more productive. Being included in a happy environment makes people happy.&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANxKaG9HNtdzjS5jkKPevwA.jpeg" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANxKaG9HNtdzjS5jkKPevwA.jpeg"&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/photos/fbgFbOTOWz4?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;rawpixel&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/happyness?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Taking time to express gratitude to others is a mindset that doesn’t seem very common, that is to say it’s not a habit that many people naturally have. Perhaps it’s a cultural thing, but as gratitude is a cornerstone of happiness, it makes sense for a business to encourage a culture of gratitude and peer recognition in the workplace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/media/526111d3b15ff7014c33ad92ba8137c9/href" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/526111d3b15ff7014c33ad92ba8137c9/href" rel="noopener noreferrer"&gt;https://medium.com/media/526111d3b15ff7014c33ad92ba8137c9/href&lt;/a&gt;&lt;a href="https://medium.com/media/bda31c71366506b91fa69defedd0e63f/href" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/bda31c71366506b91fa69defedd0e63f/href" rel="noopener noreferrer"&gt;https://medium.com/media/bda31c71366506b91fa69defedd0e63f/href&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Real world examples
&lt;/h3&gt;

&lt;p&gt;I’ve worked at a few companies which support this idea of giving thanks, and here is a bit of information on the systems they have in place, followed by a little analysis of them.&lt;/p&gt;

&lt;h4&gt;
  
  
  Magic Moments
&lt;/h4&gt;

&lt;p&gt;At &lt;a href="https://www.mmtdigital.co.uk/" rel="noopener noreferrer"&gt;MMT Digital,&lt;/a&gt; we had ‘Magic Moments’ – a scheme where anyone could nominate anyone else for a reward. Nominations are made by means of a message to HR or line managers, and had three tiers (small, medium and large.) When you made the nomination you would detail what exactly had been done to earn a ‘Magic Moment’, and you could indicate what you’d like to give the recipient as a reward.&lt;/p&gt;

&lt;p&gt;The process was manually operated, with a little oversight and approval from line managers. The awarding process was fairly low-key and private, being between yourself, the recipient and your respective line managers.&lt;/p&gt;

&lt;h4&gt;
  
  
  HeyTaco!
&lt;/h4&gt;

&lt;p&gt;At &lt;a href="https://www.deeson.co.uk/" rel="noopener noreferrer"&gt;Deeson,&lt;/a&gt; we used an app called &lt;a href="https://www.heytaco.chat/" rel="noopener noreferrer"&gt;HeyTaco!&lt;/a&gt; to express gratitude, with a reward up for grabs each week for the top Taco recipients.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.heytaco.chat" rel="noopener noreferrer"&gt;HeyTaco!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;HeyTaco! is a Slack integration, and each day everyone in the company had a budget of five Tacos (🌮) which they could elect to award to someone else in the company.&lt;/p&gt;

&lt;p&gt;There was no rigid criteria for awarding Tacos, it could be anything from having a birthday to smashing out some awesome work. Everyone had the same amount of Tacos, and all awarding of Tacos was public. You could award single or multiple tacos to individuals throughout the day or award them to multiple people at once.&lt;/p&gt;

&lt;p&gt;At the end of the week a leaderboard of Taco recipients would collated and on a Monday morning the Top 5 from the leaderboard would be selected, a die would be rolled (recorded on video for the remote staff) and on a result of 1 or 6 those people would win money from the pool. On anything else, the value of the unused pool would be rolled over to next weeks die roll. You could win up to £50 each, and if the pool was larger the remaining value went to a local charity.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Competition was fierce, but I managed to get lucky and be in the Top Five one week and win with a lucky roll of the die. I spent my portion of the award money on some frivolous socks to wear at the office, because why not?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Instants
&lt;/h4&gt;

&lt;p&gt;At &lt;a href="https://www.bglgroup.co.uk/comparethemarket/benefits" rel="noopener noreferrer"&gt;CompareTheMarket&lt;/a&gt; we have ‘Instants’, which is a bespoke system for rewarding colleagues. Through the intranet we can visit the Instants page, select an employee, enter a reason for awarding them an Instant, select a company value which they’ve demonstrated and then pick a gift from the available pool. The reward is then emailed to the recipient and your respective line managers. No waiting, no approval needed, hence the name.&lt;/p&gt;

&lt;p&gt;The rewards vary depending on availability and the office they’re located in, but can be anything from a free drink, chocolate or a shopping voucher to a half day holiday. The company has a generous but shared pool of rewards available for a specific time period, so to an extent you have to be lucky enough to get the reward you might want, but there’s always something available.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Taking a bit of inspiration from HeyTaco!, the team has recently built in a Slack integration for Instants, which lists the top receivers for the previous week, and I’m sure there’s more functionality they’re working on as we speak.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Analysis
&lt;/h3&gt;

&lt;p&gt;Each of these systems is different, and arguably each flawed or open to exploitation, but any recognition systems can be exploited or manipulated if that’s your intention. Here’s some of the major pros and cons – without meaning to criticise too harshly. For all of these, my default position is that any system is better than no system at all.&lt;/p&gt;

&lt;h4&gt;
  
  
  Magic Moments
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; allows you to give personalised, graded rewards to anyone, and it’s a conscious coordinated affair to arrange a reward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; What I really felt was lacking from Magic Moments was the low-key nature of the rewards. Often they were a private thing, and while genuinely open to everyone, they weren’t promoted as much as they could have been – had these rewards been more publicly announced, it might have encouraged wider participation in the scheme.&lt;/p&gt;

&lt;h4&gt;
  
  
  HeyTaco!
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; as a Slack plugin it ties in very well with remote teams, and giving everyone a budget of 5 Tacos a day encourages very active, public and frequent positive feedback loop.&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AXdWnmeWBs35CNAUXlXb7Rg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AXdWnmeWBs35CNAUXlXb7Rg.png"&gt;&lt;/a&gt;&lt;a href="https://www.heytaco.chat/" rel="noopener noreferrer"&gt;HeyTaco!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; Our usage of HeyTaco! felt very much like a popularity contest. The interface was very slick and the app was good, but ultimately it felt that those that repeatedly won the weekly competition were those that worked across multiple teams – designers, managers, Agile coaches – and not people working away on a single team.&lt;/p&gt;

&lt;p&gt;The inevitable end result being that it’s a numbers game, which drowned out the achievements and recognition of everyone when it comes to the weekly competition. The dice roll element added some fun, but after multiple consecutive weeks being pipped to the leaderboard by the same people, it didn’t quite feel very inclusive.&lt;/p&gt;

&lt;h4&gt;
  
  
  Instants
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Instants is an automated system for issuing rewards. What I particularly like is that it feels more direct – there’s no need to coordinate with line managers or others to arrange a reward, and it arrives and can be claimed immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; If there’s any criticisms to be levied, it’s that the rewards come from a shared pool across the company. Thus, if you want to give someone a certain reward and there’s none left in the pool you either have to give them an alternative reward or wait until the pool is refilled!&lt;/p&gt;

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

&lt;p&gt;Expressing your appreciation for colleagues does wonders for your working relationship and builds a tighter bond. Similarly a harmonious, appreciative working environment does wonders for productivity and employee retention. With these benefits it makes sense for the company to invest in a mechanism to promote a better, more thankful, working culture.&lt;/p&gt;

&lt;p&gt;It’s better to have a system – even if it is flawed or imperfect – as part of a commitment to improving your company culture, than it is to have none at all.&lt;/p&gt;

&lt;p&gt;Personally I like the visibility and interaction that HeyTaco! provides, but ultimately I prefer the ease and immediacy of the Instants system. Feedback should be direct and easy to give, and that’s what a successful system will do.&lt;/p&gt;




</description>
      <category>workplacerelations</category>
      <category>workplaceculture</category>
      <category>softwaredevelopment</category>
      <category>lifeatctm</category>
    </item>
    <item>
      <title>Putting our Component library on a diet.</title>
      <dc:creator>James Ford</dc:creator>
      <pubDate>Tue, 06 Nov 2018 16:49:11 +0000</pubDate>
      <link>https://dev.to/psyked/putting-our-component-library-on-a-diet-gfb</link>
      <guid>https://dev.to/psyked/putting-our-component-library-on-a-diet-gfb</guid>
      <description>&lt;h4&gt;
  
  
  Performance matters, and “Houston, we have a problem.”
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tLqR_KQM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A-urAq0XXMQ4RSLRAiP600Q.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tLqR_KQM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A-urAq0XXMQ4RSLRAiP600Q.jpeg" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/photos/bSpqe48INMg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Bernard Hermant&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/balloon?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A shared set of components is a great idea, so long as using those components doesn’t bloat your client applications. This is a brief tale of how we got it wrong, what the cause of our issues was, and how we fixed it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Introduction
&lt;/h4&gt;

&lt;p&gt;At c&lt;a href="http://tech.comparethemarket.com"&gt;omparethemarket.com&lt;/a&gt; we produce an internal library of React Components which are used across different portions of our website, which is part of a strategy that we refer to as ‘inner sourcing.’ It’s a great idea for getting consistency across our sites, but we soon realised that we had a bit of a problem with performance, page weight and download times.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1EP-jkEm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/930/1%2AGP4hZgcAS1FRAoOs6NEj1A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1EP-jkEm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/930/1%2AGP4hZgcAS1FRAoOs6NEj1A.png" alt=""&gt;&lt;/a&gt;A (cropped) screenshot of the network chart from WebPageTest.org&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ltxdR3mK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AtJ0KsYyUuJHv1N5niwnztA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ltxdR3mK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AtJ0KsYyUuJHv1N5niwnztA.png" alt=""&gt;&lt;/a&gt;A (cropped) screenshot from the Chrome DevTools&lt;/p&gt;

&lt;p&gt;The screenshots (above) shows some stats from one of our pages, which was using an early version of our component library. From this we could see that the Javascript file needed to load our page was around 300 KB in size, and uncompressed on the customer’s browser to a meaty 1.2 MB of raw code. 😱&lt;/p&gt;

&lt;p&gt;The indicative performance impact of this single file — as shown in the WebPageTest.org snapshot above — is approximately half a second. That’s half a second of the browser doing literally nothing other than downloading, parsing and executing this file, during which it displays a nothing to the user.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Generally speaking, the majority of website performance issues are Front-End problems, and not hardware or network issues.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://www.stevesouders.com/blog/2012/02/10/the-performance-golden-rule/"&gt;the Performance Golden Rule&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This single file is actually a React application which renders the whole page. It is render-blocking, meaning that it must be downloaded and parsed by the browser before anything on the page can display, and thus this one single file is one big problem for performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Page Size Matters
&lt;/h3&gt;

&lt;p&gt;Everything about Page Speed and Performance is all intermingled, but Javascript file size is a good indicator of how long the file will take to download, be parsed by the browser, and then execute.&lt;/p&gt;

&lt;p&gt;There’s a certain amount of file size we can’t avoid with our Javascript. We need libraries like React for the experience we’re developing, and a shared library of components is a sensible idea, but something somewhere has gone horribly wrong if our output bundle size is so huge. — In some cases, we were seeing reports of &lt;strong&gt;+500Kb&lt;/strong&gt; file size being introduced on the addition of a single button, so something wasn’t correct.&lt;/p&gt;

&lt;h3&gt;
  
  
  Experiment Driven Development
&lt;/h3&gt;

&lt;p&gt;To take a closer look at what’s going on, we created a simple React application, looked at the application size, added a single (styled Button) component, and looked at the application size again.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://facebook.github.io/create-react-app/"&gt;create-react-app&lt;/a&gt; tool outputs some pretty decent metrics as part of its default build process, so this became our quick-and-easy, side-effect free environment for testing the impact our library has on build sizes. (There could quite conceivably be issues elsewhere in the code of those making these reports, so it’s important to have a reliable benchmark.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XweXtKlP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AClStjmpOU1aVgY8WToWyBw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XweXtKlP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AClStjmpOU1aVgY8WToWyBw.png" alt=""&gt;&lt;/a&gt;On the left: The out-of-the-box app. On the right: With a single component added.&lt;/p&gt;

&lt;p&gt;It’s not quite +500 KB gzipped, but 75 KB is still an excessive amount of code for a single styled Button. Looking at the output bundles, it soon became clear that what was happening is that when we include any component, we’re also getting the source code of a dozen other components whose source code is also included in our library, but isn’t actually being used by our sample application. Not good.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AAOrNvQW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AjIJwzDv3t26povgiIjAo3Q.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AAOrNvQW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AjIJwzDv3t26povgiIjAo3Q.jpeg" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/photos/466ENaLuhLY?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Markus Spiske&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/dead-code?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Tree Shaking / Dead code elimination
&lt;/h4&gt;

&lt;p&gt;All of this additional code for unused components is increasing our bundle size, but I had expected Webpack — with its native support for &lt;a href="https://webpack.js.org/guides/tree-shaking/"&gt;dead code elimination&lt;/a&gt; — to automagically remove that unused library code and deliver a more optimised bundle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developers.google.com/web/fundamentals/performance/optimizing-javascript/tree-shaking/"&gt;Reduce JavaScript Payloads with Tree Shaking | Web Fundamentals | Google Developers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, why didn’t it?&lt;/p&gt;

&lt;p&gt;The answer to this question is complex and fairly specific to our project, but it involves our Babel configuration, our CommonJS output format and our use of CSS modules. All of these elements combine to create library bundles which fundamentally cannot be tree-shaken by Webpack.&lt;/p&gt;

&lt;p&gt;So, how to we build a tree-shakable library bundle?&lt;/p&gt;

&lt;h3&gt;
  
  
  A better bundler… with rollup.js
&lt;/h3&gt;

&lt;p&gt;After a lot of experimenting with different options and configurations for Webpack, we eventually realised that it was ‘the wrong tool for the job’ when it came to building our bundle of library components. As a replacement we picked &lt;a href="https://rollupjs.org/guide/en"&gt;rollup.js&lt;/a&gt;, which amongst other perks is better at producing library bundles that supports dead code elimination.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rollupjs.org/guide/en"&gt;rollup.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our consumer applications still use Webpack to package our final React applications, but using rollup.js for our library bundles now means that when Webpack compiles its output, it’s able to tree shake our library code and eliminate the components that aren’t used.&lt;/p&gt;

&lt;p&gt;And the final results?&lt;/p&gt;

&lt;p&gt;On our example project, switching to Rollup-bundled libraries immediately saves an extra 22 KB out of 75 KB (almost 30%) with literally no changes to the example application itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LsYwjhhb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AIfqILOaabFh4BSnX1HcOIQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LsYwjhhb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AIfqILOaabFh4BSnX1HcOIQ.png" alt=""&gt;&lt;/a&gt;On the left: Create-react-app using our library packaged with Webpack, on the right: using the library packaged with rollup.&lt;/p&gt;

&lt;p&gt;Even more exciting is the effect when we applied this same updated library to a real-world example, which yielded optimisations closer to 60% of the total file size:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File sizes after gzip:

 287.02 KB (-430.7 KB) build/static/js/main.5978ff57.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;430.7 KB&lt;/strong&gt; saved from our output bundle, thanks to using a tree-shakable React Component library, bundled with properly-configured Rollup instead of our out-of-the-box Webpack configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;Our React Component library was part of a natural evolution from several projects, but we took our eye off the performance impact of the code that we were building and it quickly snowballed into something that had detrimental effect on the projects that included it.&lt;/p&gt;

&lt;p&gt;The root cause of this problem was our bundling strategy, and the fact that it couldn’t determine which code was necessary to render the components, so it always included everything.&lt;/p&gt;

&lt;p&gt;The solution was to shift our bundling strategy into Rollup and also to change our Babel configuration to one that better supported dead-code elimination.&lt;/p&gt;

&lt;p&gt;Webpack isn’t a bad tool, but it has to be configured properly and used for the correct tasks, and because of the gradual nature of our project evolution, our setup wasn’t suitable. Pausing, evaluating, and spending some time focussing on our build processes has allowed us to make these gains.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Javascript syntax patterns, such as CommonJS, have different side effects when it comes to dead-code elimination in your code bundler.&lt;/li&gt;
&lt;li&gt;Webpack is good for bundling projects, but Rollup is better for libraries.&lt;/li&gt;
&lt;li&gt;You’re still going to need Babel, regardless of whether you’re working with Webpack or Rollup. It’s the Babel configuration which has the biggest effect on the outcome.&lt;/li&gt;
&lt;li&gt;Test, test and test again, and do it in an environment that is representative of your anticipated customers’ workspace.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bonus: Create-React-App 2 &amp;amp; Webpack 4
&lt;/h3&gt;

&lt;p&gt;Since originally penning this article, we’ve had clients update to using &lt;a href="https://github.com/facebook/create-react-app"&gt;create-react-app&lt;/a&gt; version 2 and Webpack 4, which delivers even more benefits to our bundle size and performance, with no additional code changes.&lt;/p&gt;

&lt;p&gt;Repeating the tests with version 2 yields these results in our example application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z0_Dw7h5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A2JGy_KCP4AB-c-MooUlH0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z0_Dw7h5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A2JGy_KCP4AB-c-MooUlH0g.png" alt=""&gt;&lt;/a&gt;On the left: Create-react-app 2, on the right: with our library added&lt;/p&gt;

&lt;p&gt;And here’s a real world example of the bundle size output on &lt;strong&gt;create-react-app&lt;/strong&gt; version 1.1.4:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File sizes after gzip:

188.49 KB build/static/js/main.53169928.js
 112.37 KB build/static/js/BasicQuestions.9168ec4c.chunk.js
 110.43 KB build/static/js/ComplexQuestions.5706b399.chunk.js
 110.4 KB build/static/js/SubQuestions.194d1d33.chunk.js
 110.3 KB build/static/js/CustomQuestions.736521d5.chunk.js

File sizes after gzip:

255.75 KB build/static/js/main.b68bc851.js
 846 B build/static/css/main.a86b8cd7.css
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And the same real-world project again, this time using &lt;strong&gt;create-react-app&lt;/strong&gt; version 2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File sizes after gzip:

112.58 KB build/static/js/7.58c36855.chunk.js
 66.56 KB build/static/js/0.72b13458.chunk.js
 65.62 KB (-122.87 KB) build/static/js/main.20b9faa3.chunk.js
 40.56 KB build/static/js/1.ac53a9a6.chunk.js
 3.32 KB (-109.06 KB) build/static/js/BasicQuestions.6df1fce5.chunk.js
 1.47 KB (-108.96 KB) build/static/js/ComplexQuestions.61562335.chunk.js
 1.44 KB (-108.97 KB) build/static/js/SubQuestions.d5066422.chunk.js
 1.24 KB (-109.06 KB) build/static/js/CustomQuestions.b2e5a8af.chunk.js
 1.24 KB build/static/js/runtime~main.6da60b22.js

File sizes after gzip:

156.02 KB build/static/js/1.c932bec8.chunk.js
 89.89 KB (-165.86 KB) build/static/js/main.2f744215.chunk.js
 837 B (-9 B) build/static/css/main.8ee9f0fa.chunk.css
 763 B build/static/js/runtime~main.229c360f.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A ‘simple’ upgrade that implements cleverer bundle splitting for shared code libraries, and we’ve automatically saved even more 100’s of KB across the site, which is pretty neat. 👍&lt;/p&gt;




</description>
      <category>tech</category>
      <category>webpack</category>
      <category>javascript</category>
      <category>frontenddev</category>
    </item>
    <item>
      <title>ESLint + Visual Studio Code: Editor integration For The Win</title>
      <dc:creator>James Ford</dc:creator>
      <pubDate>Thu, 18 Oct 2018 09:31:36 +0000</pubDate>
      <link>https://dev.to/psyked/eslint-visual-studio-code-editor-integration-for-the-win-jb8</link>
      <guid>https://dev.to/psyked/eslint-visual-studio-code-editor-integration-for-the-win-jb8</guid>
      <description>&lt;p&gt;Coding is complicated — there are loads of best practices to remember, guidelines to follow and ‘known issues’ to avoid — so it helps to have a ‘helping hand’ while you work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---GoJn40g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/398/1%2ATPkhIqPgVzFSSpwdlVwhVw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---GoJn40g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/398/1%2ATPkhIqPgVzFSSpwdlVwhVw.png" alt=""&gt;&lt;/a&gt;ESLint — &lt;a href="https://eslint.org/"&gt;&lt;/a&gt;&lt;a href="https://eslint.org/"&gt;https://eslint.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eslint.org/"&gt;ESLint - Pluggable JavaScript linter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt; is an extendible linter — or code checking tool — that can be set up as a standalone tool or integrated into the Visual Studio Code editor.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;‘A linter or lint refers to tools that analyze source code to flag programming errors, bugs, stylistic errors, and suspicious constructs.’ &lt;a href="https://en.wikipedia.org/wiki/Lint_(software)"&gt;[Wikipedia]&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With ESLint properly configured in your editor, your development experience can be almost as-if you’re continually pair-programming with (an insufferably polite and knowledgeable) know-it-all. And as daunting as that might be, it’ll help you produce better quality code and teach you as you work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring Visual Studio Code with ESLint
&lt;/h3&gt;

&lt;p&gt;First, a preamble: I’m going to start by setting up a React project using create-react-app, which gives me a package.json at the root of the project and manages dependencies through NPM.&lt;/p&gt;

&lt;p&gt;To get a new project set up, run the following commands:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/facebook/create-react-app"&gt;facebook/create-react-app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, install &lt;a href="https://github.com/facebook/create-react-app"&gt;create-react-app&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -g create-react-app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, to create a new project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create-react-app eslint-integration-example
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And when we want to, we can run the project like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd eslint-integration-example
npm start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Setting up ESLint
&lt;/h4&gt;

&lt;p&gt;ESLint could be installed globally, but for better portability and resilience let’s add it, and some plugins and settings, to the project, with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev \
eslint \
babel-eslint \
eslint-config-airbnb \
eslint-config-babel \
eslint-config-prettier \
eslint-plugin-import \
eslint-plugin-react
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With all of those plugins installed, my package.json file looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P2lnbJZ9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AxsrntccR6nCD51Gr9zKwvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P2lnbJZ9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AxsrntccR6nCD51Gr9zKwvg.png" alt=""&gt;&lt;/a&gt;The package.json file with ESLint configs and plugins&lt;/p&gt;

&lt;p&gt;Strictly speaking, the necessary plugins for adding ESLint is only actually eslint, but I’ve added the other plugins in this example because they’re the ones I’m currently using in my active projects.&lt;/p&gt;

&lt;p&gt;Alongside these npm packages, we’ll also add a configuration file to the root of the project, called .eslintrc, which looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zO1fw0gD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AAgug9EAS4QMlUuLOMNyv8Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zO1fw0gD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AAgug9EAS4QMlUuLOMNyv8Q.png" alt=""&gt;&lt;/a&gt;My .eslintrc file&lt;/p&gt;

&lt;p&gt;This tells ESLint to import the &lt;strong&gt;airbnb&lt;/strong&gt; , &lt;strong&gt;prettier&lt;/strong&gt; and &lt;strong&gt;jsx-a11y&lt;/strong&gt; configurations (that we installed in the previous command) as a starting point, and gives us a springboard from which to extend the configuration in the future.&lt;/p&gt;

&lt;p&gt;To run eslint against our code we can use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx eslint src/App.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Which gives the following output in the terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4gA47_Q3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A_P4YPpbVg4L-Utu7egF-vg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4gA47_Q3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A_P4YPpbVg4L-Utu7egF-vg.png" alt=""&gt;&lt;/a&gt;Test output from the terminal&lt;/p&gt;

&lt;p&gt;To make things a little easier to run, we can also add this command to the scripts section of the package.json file, making it look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5iMhQfZL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/770/1%2AWIn_eNNTYewBEd9AAuO8-g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5iMhQfZL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/770/1%2AWIn_eNNTYewBEd9AAuO8-g.png" alt=""&gt;&lt;/a&gt;The scripts section of the package.json file&lt;/p&gt;

&lt;p&gt;It’s already pretty neat to be able to run ESLint and highlight issues with our code like this, but what really takes it to the next level is editor integration.&lt;/p&gt;

&lt;h4&gt;
  
  
  Integrating with Visual Studio Code
&lt;/h4&gt;

&lt;p&gt;The ESLint plugin can be installed from the Visual Studio Marketplace, and gives easy integration with Visual Studio Code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint"&gt;ESLint&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What does it actually do though? It adds inline code error highlighting, which transforms your editing experience (as illustrated below)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dpH0qcDy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AO6Q5VDIKC4UM_sfJOlE82w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dpH0qcDy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AO6Q5VDIKC4UM_sfJOlE82w.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YV-WcCAD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2An20krHQQGci7D347-4HELQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YV-WcCAD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2An20krHQQGci7D347-4HELQ.png" alt=""&gt;&lt;/a&gt;On the left: Without ESLint integration, On the right: With ESLint integration&lt;/p&gt;

&lt;p&gt;With the plugin set up, rather than having the ESLint as a task that needs to be invoked manually, it runs automatically, displays the results inline with your code, and updates as you type so you get the kind of user experience you’d expect from a spell-checker but with the complexity of your ESLint rules.&lt;/p&gt;

&lt;p&gt;It’s not all about inline validation though, there’s also some sweet integration with the rest of the editor, such as the ‘Problems’ panel:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kv5XTahh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AdvvNjcPydPLfeOswJ9u-Sg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kv5XTahh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AdvvNjcPydPLfeOswJ9u-Sg.png" alt=""&gt;&lt;/a&gt;(above) ESLint integration with the ‘Problems’ panel&lt;/p&gt;

&lt;h4&gt;
  
  
  Extension Suggestions
&lt;/h4&gt;

&lt;p&gt;Seeing this editor integration does rely on having the correct plugin installed though, which can be a bit of a tedious task to maintain if you’re on a development team. To assist with this, we can add a VSCode extensions configuration file, which will prompt Visual Studio Code to suggest the installation of extensions when appropriate.&lt;/p&gt;

&lt;p&gt;Create a file called extensions.json in a directory named .vscode in the root of the project, with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
 "recommendations": [
 "dbaeumer.vscode-eslint",
 "esbenp.prettier-vscode",
 "dzannotti.vscode-babel-coloring"
 ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The official documentation for this feature can be found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://code.visualstudio.com/docs/editor/extension-gallery#_workspace-recommended-extensions"&gt;Managing Extensions in Visual Studio Code&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Why ESLint?
&lt;/h4&gt;

&lt;p&gt;What makes ESLint cool is that it’s something that can be extended to check for more than just logical code errors, it can check for things like accessibility issues or inconsistent code formatting, which is why I’ve added &lt;a href="https://github.com/evcohen/eslint-plugin-jsx-a11y"&gt;react-jsx-a11y&lt;/a&gt; and the &lt;a href="https://github.com/prettier/prettier-eslint"&gt;prettier&lt;/a&gt; plugins to plugins list.&lt;/p&gt;

&lt;p&gt;And with all of that setup, you can experience what it’s like to Pair Program with a stickler for consistency and best practices, without actually having to be pairing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KUxp06wi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A84wQvgcY-qeS92WYYvJBTA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KUxp06wi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A84wQvgcY-qeS92WYYvJBTA.jpeg" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/photos/ZKBzlifgkgw?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Mimi Thian&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/pointing-at-code?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;




</description>
      <category>visualstudiocode</category>
      <category>javascript</category>
      <category>eslint</category>
      <category>tech</category>
    </item>
    <item>
      <title>Building a humanised command-line interface with Node.js</title>
      <dc:creator>James Ford</dc:creator>
      <pubDate>Mon, 13 Aug 2018 08:31:01 +0000</pubDate>
      <link>https://dev.to/psyked/building-a-humanised-command-line-interface-with-node-js-4813</link>
      <guid>https://dev.to/psyked/building-a-humanised-command-line-interface-with-node-js-4813</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AFd45W9R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Ah89l_KJR8w2NrzQXtPCAmw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AFd45W9R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Ah89l_KJR8w2NrzQXtPCAmw.jpeg" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/photos/R4WCbazrD1g?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Rock’n Roll Monkey&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/robot-face?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Because config management sucks.
&lt;/h4&gt;

&lt;h3&gt;
  
  
  Background
&lt;/h3&gt;

&lt;p&gt;As a by-product of my day-to-day software development work I have created a lot of specific-task automation scripts. If there’s a task that I need to perform on a fairly regular basis that involves multiple steps and which &lt;em&gt;could&lt;/em&gt; be automated, I &lt;em&gt;will&lt;/em&gt; (eventually) write myself a script to automate it.&lt;/p&gt;

&lt;p&gt;I do this because — generally speaking — I enjoy writing the scripts and because abstracting mundane tasks into these scripts reduces the cognitive overhead and frees my time up for thinking about other aspects of my day-to-day job.&lt;/p&gt;

&lt;h4&gt;
  
  
  Configurable code
&lt;/h4&gt;

&lt;p&gt;It’s well established that hard-coding values into code instantly makes it less reusable, and that extracting those values into code variables is logical because it then becomes easier to reliably make broad changes to the code.&lt;/p&gt;

&lt;p&gt;To make a script reusable without actually editing source code each time there are two common strategies. One of them is passing configuration as arguments on the command line, and the other is creating and editing a config file which stores the options in a more long-lived format. Command line arguments are good for one-off commands and config files are great for repeated reuse with the same settings.&lt;/p&gt;

&lt;h4&gt;
  
  
  Problem
&lt;/h4&gt;

&lt;p&gt;Both command line arguments and configuration files require knowledge of the available options and a measure of preparation — neither is quite as easy as a GUI (Graphical User Interface) could make the experience, and neither of them typically have an intuitive interface.&lt;/p&gt;

&lt;p&gt;I always assume that in a few months’ time I will have completely forgotten everything about how to configure my scripts, and with no hope of finding assistance on StackOverflow or Google I need to ensure that I make them straightforward and operator-friendly.&lt;/p&gt;

&lt;h3&gt;
  
  
  A humanised experience 🤖
&lt;/h3&gt;

&lt;p&gt;Essentially I want my command-line interfaces to be a little more human in their interactions with me and behave more like an artificial assistant like Alexa or Siri and less like a computer. That’s a &lt;em&gt;humanized experience.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Without further ado, let’s make a simple script &lt;em&gt;more human.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Core code
&lt;/h4&gt;

&lt;p&gt;(Below) I have a Node.js script which communicates with the GitHub API to retrieve stats about a repository. It’s currently set up to take a configuration file in JSON format and also returns the output as JSON.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HFDdft3e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A9wYVk5O73upqdOuwzQRhsg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HFDdft3e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A9wYVk5O73upqdOuwzQRhsg.png" alt=""&gt;&lt;/a&gt;getstats.json&lt;/p&gt;

&lt;p&gt;What the code (above) is doing is using the &lt;strong&gt;node-fetch&lt;/strong&gt; module to make a request to the GitHub GraphQL API, and then it’s taking the response from that API and doing a bit of processing on the responses before spitting them back out as a string.&lt;/p&gt;

&lt;p&gt;The information that’s absent from the source code and which is supplied by the config file is the &lt;strong&gt;repository owner&lt;/strong&gt; , the &lt;strong&gt;repository name&lt;/strong&gt; , a &lt;strong&gt;start date&lt;/strong&gt; and an &lt;strong&gt;end date&lt;/strong&gt; , all of which are used to identify the target repository and filter the response data.&lt;/p&gt;

&lt;p&gt;For completeness, the GraphQL query used looks like this (below):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JceksDgk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AWgKscWyWBMi_hdV0cR26Ew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JceksDgk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AWgKscWyWBMi_hdV0cR26Ew.png" alt=""&gt;&lt;/a&gt;query.gql&lt;/p&gt;

&lt;p&gt;Now we’ve got the code, how do we actually execute it and fetch our data?&lt;/p&gt;

&lt;h4&gt;
  
  
  Executing scripts with command line options
&lt;/h4&gt;

&lt;p&gt;Without a humanised journey, I’d use a command like this (below) to execute my script return the repository stats:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node index.js psyked psyked.github.io 2018-08-08 2018-08-12
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Executing scripts with config files
&lt;/h4&gt;

&lt;p&gt;If I was taking the config file approach, I’d create a .json file with those settings in, save it as psyked-config.json in the same directory and then use the command (below) to run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node index.js ./psyked-config.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It’s a little less to type on each execution and does ensure that the options would be the same each time, but it’s still not user friendly &lt;em&gt;enough.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Humanised command line experiences
&lt;/h4&gt;

&lt;p&gt;The &lt;em&gt;humanised&lt;/em&gt; approach starts with only the simplest command (below):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node index.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;From then on it switches over to an interactive experience, which looks like this (below) — asking questions, hinting at responses and finally mapping inputs into the same data structure that would exist in a proper config file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8KMOepIA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/975/1%2Aa5eNNjsXIESU_a1EsTpqUA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8KMOepIA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/975/1%2Aa5eNNjsXIESU_a1EsTpqUA.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This experience is all facilitated by a module called &lt;strong&gt;Inquirer&lt;/strong&gt; , which adds a really simple layer of code that supports several common types of question to the command line.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/SBoudrias/Inquirer.js"&gt;SBoudrias/Inquirer.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inquirer can prompt for several types of data, chain questions together, validate the responses and more. To achieve the questions used in the screen capture above I’m using the following code (below):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gq9JymQv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AIRQ0WOaSRF9lV_-gu4ydbQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gq9JymQv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AIRQ0WOaSRF9lV_-gu4ydbQ.png" alt=""&gt;&lt;/a&gt;index.js&lt;/p&gt;

&lt;p&gt;… and that’s about it. Humanised command-line interfaces with Node.js.&lt;/p&gt;

&lt;p&gt;The big advantage that this approach has over other options is that playing around with the data feels so much easier. Putting all the values on a single line feels like an arduous process, especially if you make a mistake. Creating and editing multiple config files is much the same, but following an old-school wizard approach to running scripts? That’s fun. 🎩&lt;/p&gt;

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

&lt;p&gt;The &lt;strong&gt;Inquirer.js&lt;/strong&gt; module makes it easy to make command line interfaces more operator friendly. It’s simple to author the questions and map the results into our code, and the experience at the outcome far outweighs the effort spent configuring the module.&lt;/p&gt;




</description>
      <category>javascript</category>
      <category>commandlineinterfa</category>
      <category>node</category>
      <category>userexperience</category>
    </item>
  </channel>
</rss>
