<?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: Paul Isaris</title>
    <description>The latest articles on DEV Community by Paul Isaris (@pavlosisaris).</description>
    <link>https://dev.to/pavlosisaris</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F35635%2F522050db-b4f4-438e-bb9c-b2a5eaa4807a.jpg</url>
      <title>DEV Community: Paul Isaris</title>
      <link>https://dev.to/pavlosisaris</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pavlosisaris"/>
    <language>en</language>
    <item>
      <title>Serving Large Private Files from Laravel</title>
      <dc:creator>Paul Isaris</dc:creator>
      <pubDate>Mon, 12 Oct 2026 12:58:00 +0000</pubDate>
      <link>https://dev.to/pavlosisaris/serving-large-private-files-from-laravel-1lp8</link>
      <guid>https://dev.to/pavlosisaris/serving-large-private-files-from-laravel-1lp8</guid>
      <description>&lt;h1&gt;
  
  
  Serving Large Private Files from Laravel
&lt;/h1&gt;

&lt;p&gt;(image by &lt;a href="https://www.pexels.com/" rel="noopener noreferrer"&gt;pexels&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Let's suppose you need to show a set of large files to a small group of users. Say a few hundred photographs, 6000 x 4000 JPEGs of about 7 MB each, straight from the camera, and &lt;strong&gt;only the members of a team may open them.&lt;/strong&gt; Nobody else, logged in or not.&lt;/p&gt;

&lt;p&gt;The reason you want to serve the originals might be scientific: the users need to zoom in and inspect details, so downscaling the images is not always a solution. The same applies to scanned documents, medical images, or any file where the detail is the point.&lt;/p&gt;

&lt;p&gt;If you have served files from Laravel before, you know the first thing that comes to mind: &lt;code&gt;php artisan storage:link&lt;/code&gt;, drop the files under &lt;code&gt;storage/app/public&lt;/code&gt;, and write &lt;code&gt;&amp;lt;img src="/storage/..."&amp;gt;&lt;/code&gt;. It takes five minutes and it works. It is also the &lt;strong&gt;wrong tool&lt;/strong&gt; for this case! I hit exactly this scenario in an application I work on, and this post walks through what I built instead and why.&lt;/p&gt;

&lt;p&gt;The post is for anyone who serves files that are not public: uploads, datasets, scans, contracts, paid downloads. The code is written on Laravel 13 (PHP 8.3+), but the approach is decoupled from the framework and the version. The principles apply to any web application that needs to check who is asking before handing out a file.&lt;/p&gt;

&lt;h2&gt;
  
  
  The naive scenario, and why it fails
&lt;/h2&gt;

&lt;p&gt;The public disk exists for files that anyone may fetch: logos, avatars, marketing assets. The symlink turns &lt;code&gt;storage/app/public&lt;/code&gt; into &lt;code&gt;public/storage&lt;/code&gt;, and from then on the web server hands the files out directly. Laravel is not involved in those requests at all. That is the point of the feature, and it is exactly the problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Anyone who has the URL gets the file.&lt;/strong&gt; The session, the roles, and the policies never run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The URLs are guessable&lt;/strong&gt;. Files named &lt;code&gt;11.JPG&lt;/code&gt;, &lt;code&gt;12.JPG&lt;/code&gt;, &lt;code&gt;13.JPG&lt;/code&gt; can be fetched with a loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The symlink must exist on every server.&lt;/strong&gt; Forget it on one deployment target and every file is a 404.&lt;/li&gt;
&lt;li&gt;Moving the files later, to another directory or to S3, &lt;strong&gt;changes every URL&lt;/strong&gt; the frontend ever rendered.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Signed URLs are the usual answer for the first two points, and they are a good one when the files live on S3. For a directory on the application server, I wanted something simpler: one endpoint that checks who is asking and then streams the file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the files where they are, point a disk at them
&lt;/h2&gt;

&lt;p&gt;The files live in a directory outside the Laravel tree. In my case it is a separate git repository, cloned next to the application, because the data has its own history and its own owners. Nothing is copied into &lt;code&gt;storage/&lt;/code&gt;. The application only needs to know where the directory is, so the path is a config value with an environment override:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// config/files.php&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'root'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;base_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'FILES_PATH'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'files'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A filesystem disk is rooted at that path. It is a local disk with no &lt;code&gt;url&lt;/code&gt; key, which means Laravel cannot build a public URL for it even by accident:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// config/filesystems.php&lt;/span&gt;
&lt;span class="s1"&gt;'files'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'local'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'root'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'files.root'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;'throw'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'report'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&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;The database stores two things per file: the directory of the collection it belongs to (&lt;code&gt;Expedition_2024&lt;/code&gt;) on the collection row, and the file name (&lt;code&gt;11.JPG&lt;/code&gt;) on the file row. Together they make the path relative to the disk. The absolute path never leaves the server.&lt;/p&gt;

&lt;p&gt;The tests get their own root: &lt;code&gt;phpunit.xml&lt;/code&gt; sets &lt;code&gt;FILES_PATH&lt;/code&gt; to a directory with three small committed fixtures, so the suite never touches the real data.&lt;/p&gt;

&lt;h2&gt;
  
  
  One authorized endpoint
&lt;/h2&gt;

&lt;p&gt;The route takes the collection the user is browsing and the file they want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'collections/{collection}/files/{file}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;CollectionFileController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'show'&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="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'auth'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'collections.file'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The frontend receives this URL inside the page payload and puts it in an &lt;code&gt;&amp;lt;img src&amp;gt;&lt;/code&gt;. The browser sends the session cookie with the request, as with any other same-origin URL, so nothing special happens on the client.&lt;/p&gt;

&lt;p&gt;Authorization lives in a form request. It asks two questions: may this user see files of this collection, and does this file belong to this collection? The second check matters. Without it, a member of one collection could request any file id in the database and the policy check alone would pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShowCollectionFileRequest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;FormRequest&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;findOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'collection'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nc"&gt;Gate&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;allows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'viewFile'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$collection&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CollectionFile&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;findOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'file'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;collection_id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nv"&gt;$collection&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The policy behind the gate is plain: admins, and users who are members of the collection. The controller then builds the path and streams the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CollectionFileController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="no"&gt;string&lt;/span&gt; &lt;span class="no"&gt;CACHE_CONTROL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'private, max-age=86400'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ShowCollectionFileRequest&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$collection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;StreamedResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$fileRow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CollectionFile&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;findOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$collectionRow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;findOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$collection&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$collectionRow&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$fileName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$fileRow&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nf"&gt;abort_unless&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isSafeSegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$directory&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP_NOT_FOUND&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;abort_unless&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isSafeSegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fileName&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP_NOT_FOUND&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$relativePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$directory&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$fileName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nf"&gt;abort_unless&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Storage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;disk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'files'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$relativePath&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP_NOT_FOUND&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Storage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;disk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'files'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$relativePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'Cache-Control'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;CACHE_CONTROL&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="cd"&gt;/** A single path segment: non-empty, no separators, no parent references. */&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;isSafeSegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;mixed&lt;/span&gt; &lt;span class="nv"&gt;$segment&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;is_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$segment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$segment&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
            &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nf"&gt;str_contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$segment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nf"&gt;str_contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$segment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'\\'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nf"&gt;str_contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$segment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&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;p&gt;Two details are deliberate.&lt;br&gt;
First, both path segments come from the database, not from the request, and both are still checked. A row can be edited by hand, an import can have a bug, and &lt;code&gt;../../.env&lt;/code&gt; in a file name must not become a readable path. Each segment has to be a single directory or file name: no slashes, no backslashes, no &lt;code&gt;..&lt;/code&gt;. Second, the status codes are a choice. A guest never reaches this code: the &lt;code&gt;auth&lt;/code&gt; middleware redirects every guest to the login page, whether the collection exists or not, so anonymous traffic learns nothing. An authenticated user without access gets a 403. That tells them the id exists, and I accept it: they are known users, and a 404 for a collection they already know about is only confusing. Failures after authorization, such as an unsafe path or a missing file on disk, are a 404.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Storage::response()&lt;/code&gt; returns a &lt;code&gt;StreamedResponse&lt;/code&gt;. PHP reads the file in chunks and writes them to the output, so a 7 MB file does not get loaded into memory as a string.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cache it privately
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Cache-Control&lt;/code&gt; header is the one line that makes the approach practical. &lt;code&gt;private&lt;/code&gt; tells the browser it may keep the file and tells every shared cache on the way that it may not. &lt;code&gt;max-age=86400&lt;/code&gt; means that for a day, opening the same file again costs no request at all. A user who moves back and forth between images gets each file once.&lt;/p&gt;

&lt;p&gt;What is still missing is an &lt;code&gt;ETag&lt;/code&gt; or a &lt;code&gt;Last-Modified&lt;/code&gt; header. After the day is over, the browser downloads the file again instead of asking whether it changed. The fix is a few lines in the same controller; I left it out here to keep the example short.&lt;/p&gt;
&lt;h2&gt;
  
  
  The tests that pin it down
&lt;/h2&gt;

&lt;p&gt;The feature test for the endpoint has eight cases, and I think the list is worth more than the code, because it is the contract:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a guest is redirected to the login page, so anonymous traffic cannot probe which ids exist;&lt;/li&gt;
&lt;li&gt;an authenticated non-member gets a 403 (deliberate: known users may learn that the collection exists);&lt;/li&gt;
&lt;li&gt;a member gets a 200 with &lt;code&gt;image/jpeg&lt;/code&gt; and the private cache header;&lt;/li&gt;
&lt;li&gt;an admin gets a 200 without being a member;&lt;/li&gt;
&lt;li&gt;a file that belongs to a different collection gets a 403, for the same reason;&lt;/li&gt;
&lt;li&gt;a file name containing &lt;code&gt;..&lt;/code&gt; gets a 404;&lt;/li&gt;
&lt;li&gt;a collection with no directory gets a 404;&lt;/li&gt;
&lt;li&gt;a directory containing &lt;code&gt;..&lt;/code&gt; gets a 404.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fixtures are three small JPEGs committed to the repository. The real files are never needed to run the suite, which is the only way the suite stays runnable on a fresh clone and on CI.&lt;/p&gt;
&lt;h2&gt;
  
  
  Is streaming through PHP fast enough?
&lt;/h2&gt;

&lt;p&gt;Honest answer: for the application I had in mind, yes, and I measured before deciding. One user opens one file at a time. The first load costs one PHP process for about 7 MB; every later load of the same file is served from the browser cache. And since the users zoom into details, generating smaller copies would not have replaced the original anyway; it would only have added a second set of files to keep in sync.&lt;/p&gt;

&lt;p&gt;If your numbers are different, if hundreds of users open large files at once, keep the design and move the bytes out of PHP. nginx has &lt;code&gt;X-Accel-Redirect&lt;/code&gt; and Apache has &lt;code&gt;X-Sendfile&lt;/code&gt;: the controller still runs the authorization and then returns an empty response with a header that names the file; the web server streams it. The nginx side is one internal location:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/protected-files/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;internal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;alias&lt;/span&gt; &lt;span class="n"&gt;/var/www/files/&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;And the controller returns the header instead of the stream:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'X-Accel-Redirect'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'/protected-files/'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$relativePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'Content-Type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$fileRow&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;mime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'Cache-Control'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;CACHE_CONTROL&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;The policy, the path checks and the tests stay the same. Only the last line changes, which is the reason to keep the authorization in Laravel in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three things that need attention
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;EXIF orientation.&lt;/strong&gt; Browsers rotate a JPEG according to its EXIF Orientation tag, but &lt;code&gt;getimagesize()&lt;/code&gt; returns the raw sensor dimensions. If you store width and height at import time, for example so the page can reserve the right aspect ratio before the image loads, a phone photo with Orientation 6 ends up stored as landscape and displayed as portrait. Read the tag and swap the two values for orientations 5 to 8:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nb"&gt;set_error_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$exif&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;exif_read_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$absolutePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;restore_error_handler&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$rotated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$exif&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;in_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$exif&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Orientation'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The error handler is there because &lt;code&gt;exif_read_data()&lt;/code&gt; emits a warning, not an exception, for files without EXIF data, and a missing tag is a normal case. &lt;code&gt;exif_read_data()&lt;/code&gt; also lives in an optional PHP extension. Declare it, or the import fails on the first host that lacks it:&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="nl"&gt;"require"&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;"php"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^8.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ext-exif"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;&lt;strong&gt;CMYK JPEGs.&lt;/strong&gt; Some files come out of desktop tools in CMYK. Browsers decode CMYK JPEGs, but the colours come out wrong. Since the files are served unchanged, the fix belongs in the data: convert those sources to sRGB once. If you generate derivatives, this is where you would do it instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inline serving of any type.&lt;/strong&gt; The endpoint streams whatever the row points at, with the file's own content type, on the application's origin. For a trusted directory that is acceptable. For user uploads it is not: an SVG or HTML file served inline runs scripts on your origin. Restrict the content type to what the feature needs, or add &lt;code&gt;Content-Disposition: attachment&lt;/code&gt; for everything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trade-offs to accept
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The files live outside the Laravel directory layout. Every deployment target has to provide the directory and set &lt;code&gt;FILES_PATH&lt;/code&gt;. It is one more step in the deploy, and it must be documented, but it is a step that &lt;code&gt;storage:link&lt;/code&gt; did not need.&lt;/li&gt;
&lt;li&gt;Each first load of a file is a PHP process. The cache header and, if needed, &lt;code&gt;X-Accel-Redirect&lt;/code&gt; keep that in check, but it is a cost that a static file server does not have.&lt;/li&gt;
&lt;li&gt;Membership is checked per collection, not per file. If some members may see only some files, the form request is where a tighter check would go.&lt;/li&gt;
&lt;li&gt;No S3 yet. When the disk becomes S3, streaming through PHP stops making sense and temporary signed URLs take over. The authorization code stays; the controller's last line changes again.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Private files need an endpoint, not a symlink. The endpoint has four jobs: check who is asking, check that the file belongs to what they are allowed to see, refuse to build a path from anything that is not a plain file name, and stream the bytes with a private cache header. Everything else, from where the files live to which server sends the bytes, is a configuration detail that can change later without touching the rules. Write the eight tests first; they are the part you will still rely on after the next refactoring.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>security</category>
      <category>web</category>
    </item>
    <item>
      <title>Mastering Code Quality in Laravel: Pint with Git Hooks and Docker</title>
      <dc:creator>Paul Isaris</dc:creator>
      <pubDate>Tue, 05 Nov 2024 18:19:00 +0000</pubDate>
      <link>https://dev.to/pavlosisaris/mastering-code-quality-in-laravel-pint-with-git-hooks-and-docker-365l</link>
      <guid>https://dev.to/pavlosisaris/mastering-code-quality-in-laravel-pint-with-git-hooks-and-docker-365l</guid>
      <description>&lt;h1&gt;
  
  
  Mastering Code Quality in Laravel: Pint with Git Hooks and Docker
&lt;/h1&gt;

&lt;p&gt;(image by &lt;a href="https://www.pexels.com/" rel="noopener noreferrer"&gt;pexels&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;This post was originally published at &lt;a href="https://paulisaris.com/mastering-code-quality-in-laravel-pint-with-git-hooks-and-docker/" rel="noopener noreferrer"&gt;paulisaris.com&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As developers, we all know how important clean, consistent code is for maintaining a large-scale Laravel application. Not only does well-formatted code boost readability, but it also ensures team-wide consistency and helps avoid pesky formatting debates during code reviews.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://laravel.com/docs/11.x/pint" rel="noopener noreferrer"&gt;&lt;strong&gt;Pint&lt;/strong&gt;&lt;/a&gt;, a powerful tool introduced by the Laravel ecosystem to &lt;strong&gt;automatically format PHP code&lt;/strong&gt; according to opinionated best practices.&lt;/p&gt;




&lt;p&gt;In this article, we'll explore how to integrate &lt;a href="https://laravel.com/docs/11.x/pint" rel="noopener noreferrer"&gt;Pint&lt;/a&gt; into your Laravel application and take it a step further by running Pint inside a Docker container using &lt;strong&gt;Docker Compose&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This approach ensures that code formatting is consistent across environments and makes it easier for developers using different setups to maintain uniformity in their codebase.&lt;br&gt;
Let's dive into the details! 🚀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9gc66koasgckyk804wkt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9gc66koasgckyk804wkt.png" title="Laravel Pint formatting" alt="Pint in Laravel" width="799" height="328"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Use Pint in Laravel?
&lt;/h2&gt;

&lt;p&gt;Pint is a zero-configuration tool that formats PHP code following &lt;strong&gt;PHP-CS-Fixer&lt;/strong&gt; standards. It comes preconfigured to support modern PHP standards, making it an essential part of any Laravel developer's toolkit.&lt;br&gt;
Automating code formatting helps reduce human errors, eliminates minor formatting discussions in code reviews, and accelerates development workflows by enforcing consistent style across all files. 🥷&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is this important?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Consistency&lt;/strong&gt;: Pint ensures your code style is uniform across the team. No more personal preferences affecting how the code looks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Readability&lt;/strong&gt;: Clean code is easier to read and maintain. Pint automatically handles indentation, spacing, and other small details, making your codebase more readable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation&lt;/strong&gt;: By integrating Pint in pre-commit Git hooks or running it via Docker, you can automate code formatting, making it one less thing to worry about in your CI pipeline.&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Setting Up Pint in a Laravel Application
&lt;/h2&gt;

&lt;p&gt;Let’s walk through the steps of integrating Pint into a Laravel application. For this, we'll use a simple Laravel app as our use case.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: Create a New Laravel Application
&lt;/h3&gt;

&lt;p&gt;To get started, let's create a new Laravel project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer create-project &lt;span class="nt"&gt;--prefer-dist&lt;/span&gt; laravel/laravel pint-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a fresh Laravel project in the &lt;code&gt;pint-demo&lt;/code&gt; directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Install Laravel Pint
&lt;/h3&gt;

&lt;p&gt;You can install Pint as a development dependency by running the following command in your Laravel project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require laravel/pint &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install Pint in the vendor/bin directory, where you can run it whenever you need to format your code. You can run Pint on your PHP files using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./vendor/bin/pint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Automating Pint with Husky and Git Hooks
&lt;/h3&gt;

&lt;p&gt;Running Pint manually can become a chore. To automate this, you can set up a pre-commit Git hook to ensure that Pint runs and formats your code every time you make a commit. This guarantees that all committed code is properly formatted.&lt;/p&gt;

&lt;p&gt;In order to make sure Pint runs automatically before every Git commit, we can use &lt;a href="https://www.npmjs.com/package/husky" rel="noopener noreferrer"&gt;Husky&lt;/a&gt;, which is a tool that makes it easy to manage Git hooks in npm-based projects. Here's how to set it up in your Laravel project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install Husky:&lt;/strong&gt; First, install Husky as a dev dependency:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;husky &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Set up Husky:&lt;/strong&gt; Add the following script to your &lt;code&gt;package.json&lt;/code&gt; to automatically set up Husky during &lt;code&gt;npm install&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&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;"scripts"&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;"prepare"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"husky install"&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;Then, run &lt;code&gt;npm install&lt;/code&gt; to initialize Husky:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create a Pre-commit Hook:&lt;/strong&gt; Set up a Git pre-commit hook that runs Pint before every commit:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx husky add .husky/pre-commit &lt;span class="s2"&gt;"vendor/bin/pint"&lt;/span&gt;

&lt;span class="nb"&gt;chmod&lt;/span&gt; +x .husky/pre-commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a &lt;code&gt;pre-commit&lt;/code&gt; hook in the &lt;code&gt;.husky&lt;/code&gt; directory that ensures Pint runs whenever a developer attempts to commit code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Using Pint Inside Docker
&lt;/h2&gt;

&lt;p&gt;In a modern development environment, many teams rely on Docker to ensure consistency across different machines. Running Pint inside Docker ensures that your development environment is identical, regardless of your operating system or local setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Setting Up Docker for Pint
&lt;/h3&gt;

&lt;p&gt;You can run Pint inside a Docker container using Docker Compose. Here's how to set it up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, add a &lt;code&gt;docker-compose.yml&lt;/code&gt; file to your project if you don’t have one. Here’s an example configuration for a typical Laravel app:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;version: &lt;span class="s1"&gt;'3.8'&lt;/span&gt;

services:
  app:
    image: php:8.1-cli
    volumes:
      - .:/var/www
      - ./vendor:/var/www/vendor
    working_dir: /var/www
    &lt;span class="nb"&gt;command&lt;/span&gt;: bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"while true; do sleep 1; done"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Modify your &lt;code&gt;pre-commit&lt;/code&gt; hook to run Pint inside the Docker container. Open the &lt;code&gt;.husky/pre-commit&lt;/code&gt; file and update it as follows:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# .husky/pre-commit&lt;/span&gt;

&lt;span class="c"&gt;# Load .env variables from the project root, line by line&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; .env &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'='&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; key value &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="c"&gt;# Skip lines that are comments or do not contain valid key=value format&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-Eq&lt;/span&gt; &lt;span class="s1"&gt;'^[A-Za-z_][A-Za-z0-9_]*$'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;fi
    done&lt;/span&gt; &amp;lt; .env
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Get a list of staged files&lt;/span&gt;
&lt;span class="nv"&gt;STAGED_FILES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git diff &lt;span class="nt"&gt;--cached&lt;/span&gt; &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="nt"&gt;--diff-filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;d&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Separate PHP files from other files, only if there are staged files&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STAGED_FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nv"&gt;PHP_FILES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STAGED_FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'\.php$'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;OTHER_FILES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STAGED_FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s1"&gt;'\.php$'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nv"&gt;PHP_FILES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
    &lt;span class="nv"&gt;OTHER_FILES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Exit early if there are no files staged (unlikely, but for safety)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STAGED_FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No files staged for commit. Exiting."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Run Pint for PHP files only&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PHP_FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$USE_DOCKER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Running Pint in Docker for PHP files..."&lt;/span&gt;
        docker compose &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-T&lt;/span&gt; php vendor/bin/pint &lt;span class="nv"&gt;$PHP_FILES&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Pint failed while running inside Docker."&lt;/span&gt;
            &lt;span class="nb"&gt;exit &lt;/span&gt;1
        &lt;span class="k"&gt;fi
    else
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Running Pint locally for PHP files..."&lt;/span&gt;
        vendor/bin/pint &lt;span class="nv"&gt;$PHP_FILES&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Pint failed while running locally."&lt;/span&gt;
            &lt;span class="nb"&gt;exit &lt;/span&gt;1
        &lt;span class="k"&gt;fi
    fi&lt;/span&gt;

    &lt;span class="c"&gt;# Restage PHP files after Pint formatting&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PHP_FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs &lt;span class="nt"&gt;-r&lt;/span&gt; git add
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Restage all non-PHP files&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OTHER_FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OTHER_FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs &lt;span class="nt"&gt;-r&lt;/span&gt; git add
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Pre-commit hook completed successfully."&lt;/span&gt;

&lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script checks if the &lt;code&gt;USE_DOCKER&lt;/code&gt; environment variable (in your Laravel &lt;code&gt;.env&lt;/code&gt; file) is set to &lt;code&gt;"true"&lt;/code&gt;. If it is, it runs Pint inside the Docker container. Otherwise, it runs Pint locally. &lt;/p&gt;

&lt;p&gt;This setup gives flexibility to your team, as developers can choose whether they want to run Pint locally or in Docker.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Running Docker Compose
&lt;/h3&gt;

&lt;p&gt;To run Pint in Docker, make sure you have your containers up and running. You can start Docker Compose with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Bonus: Best Practices for Running Pint in Laravel Applications
&lt;/h2&gt;

&lt;p&gt;Here are a few tips and guidelines for fellow developers working with Pint and Docker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Pre-commit Hooks:&lt;/strong&gt; Automate Pint formatting with pre-commit hooks to enforce consistency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Docker for Consistency:&lt;/strong&gt; By running Pint inside a Docker container, you ensure that all team members have the same environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customize Pint:&lt;/strong&gt; Laravel Pint comes pre-configured, but you can customize its rules by adding a pint.json configuration file if you need to enforce specific styles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep Docker Lightweight:&lt;/strong&gt; In your &lt;code&gt;docker-compose.yml&lt;/code&gt; file, mount only the necessary volumes (such as the application and &lt;code&gt;vendor&lt;/code&gt; directories) to avoid performance issues.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Using Pint in your Laravel application is a simple yet powerful way to ensure consistent code quality and formatting. &lt;/p&gt;

&lt;p&gt;By integrating it with Git hooks, Husky, and Docker, you can automate this process, making it part of your daily development workflow. Whether you run Pint locally or inside a Docker container, it can save time, prevent common formatting errors, and make your codebase cleaner and more maintainable!&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>docker</category>
      <category>hooks</category>
      <category>pint</category>
    </item>
    <item>
      <title>Make Windows Terminal Awesome with ZSH and Oh My ZSH!</title>
      <dc:creator>Paul Isaris</dc:creator>
      <pubDate>Wed, 15 May 2024 07:10:00 +0000</pubDate>
      <link>https://dev.to/pavlosisaris/windows-command-line-revolution-unleash-zsh-and-oh-my-zsh-a-simple-guide-for-developers-271o</link>
      <guid>https://dev.to/pavlosisaris/windows-command-line-revolution-unleash-zsh-and-oh-my-zsh-a-simple-guide-for-developers-271o</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;In this guide, we'll walk you through the installation and configuration of ZSH and Oh My ZSH on Windows, so you can&lt;br&gt;
enjoy the power and flexibility of these tools without leaving the comfort of your Windows environment.&lt;/p&gt;
&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;
Embracing ZSH on Windows

&lt;ul&gt;
&lt;li&gt;Introducing ZSH: The Ultimate Shell Experience&lt;/li&gt;
&lt;li&gt;Oh My ZSH!: ZSH Supercharged&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Step 1: Install Git + Git Bash for Windows&lt;/li&gt;
&lt;li&gt;
Step 2: Installation and Configuration of ZSH in Windows

&lt;ul&gt;
&lt;li&gt;2.1: Download ZSH&lt;/li&gt;
&lt;li&gt;2.2: Install ZSH&lt;/li&gt;
&lt;li&gt;2.3: Verify the ZSH Installation&lt;/li&gt;
&lt;li&gt;2.4: Set ZSH as the Default Shell&lt;/li&gt;
&lt;li&gt;2.5: Fix Displaying of Unexpected Characters&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Step 3: Installation and Configuration of Oh My ZSH! on Windows

&lt;ul&gt;
&lt;li&gt;3.1: Installation of Oh My ZSH!&lt;/li&gt;
&lt;li&gt;3.2: Customization of Oh My ZSH!&lt;/li&gt;
&lt;li&gt;Fonts&lt;/li&gt;
&lt;li&gt;Theme&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Are you tired of the mundane Windows command prompt?&lt;/p&gt;

&lt;p&gt;Do you yearn for the powerful Linux terminal, but don't&lt;br&gt;
want to deal with the complexities of &lt;code&gt;WSL&lt;/code&gt; (Windows Subsystem for Linux)?&lt;/p&gt;

&lt;p&gt;Well, rejoice, fellow developers, for there is a solution! With the&lt;br&gt;
combination of:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/downloads" rel="noopener noreferrer"&gt;Git Bash for Windows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.zsh.org/" rel="noopener noreferrer"&gt;ZSH&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ohmyz.sh/" rel="noopener noreferrer"&gt;Oh My ZSH!&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;you can transform your Windows command line experience into something truly remarkable.&lt;/p&gt;

&lt;p&gt;In this guide, we'll walk you through the installation and configuration of ZSH and Oh My ZSH on Windows, so you can&lt;br&gt;
enjoy the power and flexibility of these tools without leaving the comfort of your Windows environment.&lt;/p&gt;
&lt;h2&gt;
  
  
  Embracing ZSH on Windows
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Introducing ZSH: The Ultimate Shell Experience
&lt;/h3&gt;

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

&lt;p&gt;&lt;em&gt;Image description: ZSH logo.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ZSH&lt;/code&gt;, or &lt;strong&gt;&lt;em&gt;Z Shell&lt;/em&gt;&lt;/strong&gt;, is a powerful command interpreter for UNIX-like operating systems. It offers advanced features&lt;br&gt;
such as&lt;br&gt;
improved tab completion, spelling correction, and extensive customization options.&lt;/p&gt;
&lt;h3&gt;
  
  
  Oh My ZSH!: ZSH Supercharged
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxsum8l0gv83icz4sae7j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxsum8l0gv83icz4sae7j.png" alt="Oh My ZSH!" width="800" height="535"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image description: Oh My ZSH! logo featuring a cute cartoon character with a command prompt.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But what truly takes ZSH to the next level is Oh My ZSH! This open-source framework for managing ZSH configurations&lt;br&gt;
comes packed with a plethora of themes, plugins, and helpers. &lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Install Git + Git Bash for Windows
&lt;/h2&gt;

&lt;p&gt;If you haven't already, download and install Git for Windows from the&lt;br&gt;
official website. This will give you access to Git Bash, which serves as the entry point for ZSH. You can find the&lt;br&gt;
Git for Windows installer &lt;a href="https://git-scm.com/download/win" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Git Bash is needed so that we also have the &lt;code&gt;bash&lt;/code&gt; shell available, which is required for ZSH to run, and also for&lt;br&gt;
having the &lt;code&gt;~/.bashrc&lt;/code&gt; file available.&lt;br&gt;
The &lt;code&gt;~/.bashrc&lt;/code&gt; file is installed at &lt;code&gt;C:\Users\&amp;lt;your user name&amp;gt;\.bashrc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt;: Make sure to select the option to use Git from the Windows Command Prompt during the installation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ALSO IMPORTANT&lt;/strong&gt;: When opening the Windows Terminal app, make sure to select the Git Bash profile as the default&lt;br&gt;
terminal profile! (Select it from the dropdown menu in the top right corner of the terminal window), and then set it as&lt;br&gt;
default in the Settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxsct24ozerlg82hu3qt2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxsct24ozerlg82hu3qt2.png" alt="Git Bash in Windows Terminal" width="617" height="330"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image description: Selecting Git Bash as a terminal profile&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Installation and Configuration of ZSH in Windows
&lt;/h2&gt;

&lt;p&gt;Now that we understand the components, let's get down to business. Here's how you can install and configure ZSH and Oh&lt;br&gt;
My ZSH! on your Windows machine without the need for WSL.&lt;/p&gt;
&lt;h3&gt;
  
  
  2.1: Download ZSH
&lt;/h3&gt;

&lt;p&gt;Once Bash for Windows is set up, it is time to install ZSH:&lt;br&gt;
Download the latest MSYS2 zsh package from the MSYS2 package repository. The file will be named&lt;br&gt;
like: &lt;code&gt;zsh-#.#-#-x86_64.pkg.tar.zst&lt;/code&gt;. You can find the latest version &lt;a href="https://packages.msys2.org/package/zsh" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  2.2: Install ZSH
&lt;/h3&gt;

&lt;p&gt;Extract the contents of the zip file (which will include &lt;code&gt;etc&lt;/code&gt; and &lt;code&gt;usr&lt;/code&gt; directories) into your &lt;code&gt;Git&lt;br&gt;
Bash&lt;/code&gt;&lt;br&gt;
installation directory. This will be in &lt;code&gt;C:\Program Files\Git&lt;/code&gt;. You should merge the contents of the folder when&lt;br&gt;
asked (&lt;br&gt;
&lt;strong&gt;no files should be getting overridden&lt;/strong&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  2.3: Verify the ZSH Installation
&lt;/h3&gt;

&lt;p&gt;Open Git Bash and run &lt;code&gt;zsh --version&lt;/code&gt; to ensure that ZSH is installed correctly.&lt;/p&gt;
&lt;h3&gt;
  
  
  2.4: Set ZSH as the Default Shell
&lt;/h3&gt;

&lt;p&gt;After installation, set ZSH as your default shell by appending the following to&lt;br&gt;
your &lt;code&gt;C:\Users\&amp;lt;your user name&amp;gt;\.bashrc&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; 1 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;exec &lt;/span&gt;zsh
   &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.5: Fix Displaying of Unexpected Characters
&lt;/h3&gt;

&lt;p&gt;Fix the displaying of garbled characters on terminal by appending this line in&lt;br&gt;
your &lt;code&gt;C:\Users\&amp;lt;your user name&amp;gt;\.bashrc&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   /c/Windows/System32/chcp.com 65001 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Close and reopen the terminal, to save those changes. The first time ZSH will ask for some files creation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Installation and Configuration of Oh My ZSH! on Windows
&lt;/h2&gt;

&lt;p&gt;As we said earlier, &lt;strong&gt;Oh My ZSH!&lt;/strong&gt; is the cherry on top of the &lt;strong&gt;ZSH&lt;/strong&gt; cake. Let's see how you can install and configure&lt;br&gt;
it on your Windows machine.&lt;/p&gt;
&lt;h3&gt;
  
  
  3.1: Installation of Oh My ZSH!
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Install Oh My ZSH!&lt;/strong&gt;: With ZSH in place, installing Oh My ZSH! is a breeze. Simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3.2: Customization of Oh My ZSH!
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Fonts
&lt;/h4&gt;

&lt;p&gt;Download and install manually&lt;br&gt;
the &lt;a href="https://github.com/romkatv/powerlevel10k#meslo-nerd-font-patched-for-powerlevel10k" rel="noopener noreferrer"&gt;Meslo Nerd Fonts&lt;/a&gt; to include&lt;br&gt;
all glyphs and symbols that &lt;code&gt;Powerlevel10k&lt;/code&gt; may need.&lt;/p&gt;

&lt;h4&gt;
  
  
  Theme
&lt;/h4&gt;

&lt;p&gt;There are a lot of themes, with &lt;a href="https://github.com/romkatv/powerlevel10k" rel="noopener noreferrer"&gt;Powerlevel10k&lt;/a&gt; being the most popular and&lt;br&gt;
powerful. To install it, check the instructions &lt;a href="https://github.com/romkatv/powerlevel10k?tab=readme-ov-file#installation" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Congratulations! You've now unlocked the full potential of ZSH and Oh My ZSH! on Windows. With its advanced features and&lt;br&gt;
endless customization options, ZSH is sure to revolutionize your command line workflow. So why wait? Dive in today and&lt;br&gt;
elevate your development experience like never before.&lt;/p&gt;

</description>
      <category>windows</category>
      <category>productivity</category>
      <category>tutorial</category>
      <category>development</category>
    </item>
    <item>
      <title>My Hacktoberfest 2022 contributions</title>
      <dc:creator>Paul Isaris</dc:creator>
      <pubDate>Sat, 15 Oct 2022 06:20:09 +0000</pubDate>
      <link>https://dev.to/pavlosisaris/my-hacktoberfest-2022-contributions-1bki</link>
      <guid>https://dev.to/pavlosisaris/my-hacktoberfest-2022-contributions-1bki</guid>
      <description>&lt;h3&gt;
  
  
  Intro
&lt;/h3&gt;

&lt;p&gt;My name is Paul, I come from the sunny country of Greece (locaten in Athens), and I am a software engineer with 8 years of experience in the field. &lt;br&gt;
I work at a not-for-profit software company called &lt;a href="https://www.scify.gr/site/en/" rel="noopener noreferrer"&gt;SciFY&lt;/a&gt;, where we build software with a societal impact, like video games for the blind, assistive technologies, e-democracy tools, and more. Check out our &lt;a href="https://github.com/scify" rel="noopener noreferrer"&gt;Github profile&lt;/a&gt;! 🤩👨🏼‍🦽&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://github.com/scify" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F2966036%3Fs%3D280%26v%3D4" height="280" class="m-0" width="280"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://github.com/scify" rel="noopener noreferrer" class="c-link"&gt;
            SciFY Not-for-profit Company · GitHub
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Ιnnovation using Science &amp;amp; IT |  We bring technology and research results as usable solutions to everyday life - SciFY Not-for-profit Company
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.githubassets.com%2Ffavicons%2Ffavicon.svg" width="32" height="32"&gt;
          github.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


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

&lt;p&gt;I have studied Computer Science in Greece, and I much enjoy learning new things about everything! 🦾👨🏼‍🚀&lt;/p&gt;

&lt;h3&gt;
  
  
  Progress
&lt;/h3&gt;

&lt;p&gt;I join Hacktoberfest every year, since 2017. I much enjoy the enthusiasm of the FOSS community, and the hype of open-source software during this month. I also get a chance to work again on small -yet important- updates and improvements of our open-source projects! 🎃🧙 &lt;/p&gt;

&lt;h3&gt;
  
  
  Contributions
&lt;/h3&gt;

&lt;p&gt;This year I decided to contribute to the very own projects of the organization I work for. We have some legacy application that needed revamping, and some others that are in the process of adding new features to.&lt;/p&gt;

&lt;p&gt;More specifically:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. ICSee (I Can See) Android app for people with low-vision
&lt;/h4&gt;

&lt;p&gt;ICSee is an Android app, written in Java. It helps people with low-vision to see small texts through the phone camera, by applying special real-time filters. &lt;br&gt;
In the context of Hacktoberfest 2022, I took the opportunity to upgrade the app to the latest version of &lt;a href="https://opencv.org/" rel="noopener noreferrer"&gt;OpenCV&lt;/a&gt; (the library we use to handle real-time image processing), as well as support new languages.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/scify" rel="noopener noreferrer"&gt;
        scify
      &lt;/a&gt; / &lt;a href="https://github.com/scify/ICSee" rel="noopener noreferrer"&gt;
        ICSee
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      ICSee runs on small portable devices (smartphones, tablets) and makes reading and object identification easier. Simply, conveniently and always available!
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;ICSee&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/scify/ICSee/master/app/src/main/res/drawable/icsee_logo3.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fscify%2FICSee%2Fmaster%2Fapp%2Fsrc%2Fmain%2Fres%2Fdrawable%2Ficsee_logo3.png" alt="ICSee logo"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;ICSee is an application that helps people with visual impairments see more clearly. It is developed
by &lt;a href="https://scify.org/en" rel="nofollow noopener noreferrer"&gt;SciFY&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We created an application that allows people with visual impairments to read!&lt;/p&gt;
&lt;p&gt;You can watch a video of the application in action &lt;a href="https://www.youtube.com/watch?v=Wb4_S6ngTjM&amp;amp;feature=youtu.be" rel="nofollow noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With ICSee:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The user can simply point their smartphone/tablet’s camera to what they want to take a better look at, and they see a
processed, clearer image on their screen.&lt;/li&gt;
&lt;li&gt;In this way, they can read a small text (e.g. the check or menu at a restaurant, the charge amount on the taxi meter
the name on a doorbell).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;How does it work? ICSee:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;processes the image/video from a smartphone/table’s camera in real-time,&lt;/li&gt;
&lt;li&gt;applies a series of filters, and&lt;/li&gt;
&lt;li&gt;projects a result that’s easier to read or identify on the screen.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Abstract&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;It is an application for small portable devices (smart phones, tablets) that will help…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/scify/ICSee" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h4&gt;
  
  
  2. Dianoia mobile app for people with emerging, early-stage dementia
&lt;/h4&gt;

&lt;p&gt;People with dementia, due to the ongoing decline in their mental abilities, need proper care at each stage. Their carers feel they have a great responsibility in their hands. Therefore, dementia affects not only the person dealing with it, but the caregivers, too.&lt;/p&gt;

&lt;p&gt;Dianoia is an &lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic&lt;/a&gt; smartphone app for family caregivers and health professionals in order to provide knowledge about simple techniques of non-pharmaceutical interventions will provide valuable insight and tools.&lt;/p&gt;

&lt;p&gt;In the context of Hacktoberfest 2022, I took the opportunity to enrich the app with new content, fix several bugs, and make the UI look much smoother!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/scify" rel="noopener noreferrer"&gt;
        scify
      &lt;/a&gt; / &lt;a href="https://github.com/scify/Dianoia-app" rel="noopener noreferrer"&gt;
        Dianoia-app
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Mobile (Ionic 3 - Angular 4) app about non-pharmaceutical activities and information for people with dementia.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Dianoia - Ionic Mobile app&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/scify/Dianoia-app/master/resources/splash.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fscify%2FDianoia-app%2Fmaster%2Fresources%2Fsplash.png" width="500"&gt;&lt;/a&gt;
&lt;/p&gt;



&lt;p&gt;A demo of the app (in Greek) can be found at &lt;a href="https://scify.github.io/Dianoia-app/#/home" rel="nofollow noopener noreferrer"&gt;scify.github.io/Dianoia-app&lt;/a&gt;.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Non-pharmaceutical activities for people with dementia&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Pre-setup steps&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;This is a legacy Ionic 3 / Cordova 8 project that requires specific older versions of tools. Follow these steps carefully.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;1. Node.js&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;It is very easy to install multiple versions of NodeJS and npm, by using &lt;a href="https://github.com/creationix/nvm" rel="noopener noreferrer"&gt;Node Version Manager (nvm)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This project was built using the following versions of nodejs and npm:&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;node -v
v14.21.1

npm -v
6.14.17&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;If you are using &lt;a href="https://github.com/nvm-sh/nvm" rel="noopener noreferrer"&gt;&lt;code&gt;nvm&lt;/code&gt;&lt;/a&gt;, run this command in order to sync to the correct NodeJS version for the project:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;nvm install
nvm use&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;2. Java 8&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;This project requires &lt;strong&gt;Java 8 (1.8)&lt;/strong&gt; - newer versions are not compatible with Gradle 4.x.&lt;/p&gt;

&lt;p&gt;Install OpenJDK 8:&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;sudo apt update
sudo apt install openjdk-8-jdk&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;If you have multiple Java versions installed, select Java 8 as…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/scify/Dianoia-app" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  Reflections
&lt;/h3&gt;

&lt;p&gt;Like every year, it is beyond exctiting to see the software development communitu to passionate about such an innovative event. 🧑🏿‍🚀&lt;/p&gt;

&lt;p&gt;This year, I also liked the inclusion of low-code or even no-code contributions, since I think that such endeavor will introduce open-source to an even wider audience! ❤️🥳&lt;/p&gt;

&lt;p&gt;I look forward to participating in Hacktoberfest every year! 😄👨‍💻&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>opensource</category>
    </item>
    <item>
      <title>PHP 8 Is here! A step in the right direction?</title>
      <dc:creator>Paul Isaris</dc:creator>
      <pubDate>Sun, 11 Apr 2021 10:15:00 +0000</pubDate>
      <link>https://dev.to/pavlosisaris/php-8-is-here-a-step-in-the-right-direction-41ad</link>
      <guid>https://dev.to/pavlosisaris/php-8-is-here-a-step-in-the-right-direction-41ad</guid>
      <description>&lt;p&gt;post photo by &lt;a href="https://www.pexels.com/" rel="noopener noreferrer"&gt;pexels&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;PHP 8 is finally here!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PHP 8.0 is a major update of the PHP language.&lt;br&gt;
It contains many new features and optimizations including &lt;strong&gt;named arguments&lt;/strong&gt;, &lt;strong&gt;union types&lt;/strong&gt;, &lt;strong&gt;attributes&lt;/strong&gt;, &lt;strong&gt;constructor property promotion&lt;/strong&gt;, &lt;strong&gt;match expression&lt;/strong&gt;, &lt;strong&gt;nullsafe operator&lt;/strong&gt;, &lt;strong&gt;JIT&lt;/strong&gt;, and improvements in the &lt;strong&gt;type system&lt;/strong&gt;, &lt;strong&gt;error handling&lt;/strong&gt;, and &lt;strong&gt;consistency&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we will review all the new features and changes, and share some thoughts about each of the changes, as well as on the roadmap that PHP seems to be carving ahead.&lt;/p&gt;

&lt;p&gt;You can read all about these in the &lt;a href="https://www.php.net/releases/8.0/en.php" rel="noopener noreferrer"&gt;official release announcement&lt;/a&gt; as well.&lt;/p&gt;
&lt;h1&gt;
  
  
  New features
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Named arguments
&lt;/h2&gt;

&lt;p&gt;In PHP 8, when calling a function, you can omit the non-required arguments, and pass only what is desired.&lt;/p&gt;
&lt;h3&gt;
  
  
  Named Parameters example
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;my_awesome_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$expires&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="mf"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let's say now that we want to call this function, but only specify the &lt;code&gt;$name&lt;/code&gt; and &lt;code&gt;$expires&lt;/code&gt; attributes.&lt;/p&gt;

&lt;p&gt;In PHP 7:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// calling the function. but we only want to specify $name and $expires&lt;/span&gt;
&lt;span class="nf"&gt;my_awesome_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In PHP 8:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// calling the function. but we only want to specify $name and $expires&lt;/span&gt;
&lt;span class="nf"&gt;my_awesome_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'test'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expires&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  My thoughts on named parameters
&lt;/h3&gt;

&lt;p&gt;This is a nice and handy touch. Many languages nowadays support this kind of method calling.&lt;br&gt;&lt;br&gt;
However, this design can lead to functions that break the &lt;a href="https://en.wikipedia.org/wiki/Single-responsibility_principle" rel="noopener noreferrer"&gt;Single-responsibility_principle&lt;/a&gt;, by resulting in methods that "do too much" by having many parameters. So, as always, use with caution ;-)&lt;/p&gt;
&lt;h2&gt;
  
  
  Attributes
&lt;/h2&gt;

&lt;p&gt;Attributes are the new kid in the block. It is essentially a configuration language embedded directly into code.&lt;br&gt;&lt;br&gt;
Attributes is a &lt;strong&gt;native PHP syntax&lt;/strong&gt; that offers the ability to add structured, machine-readable metadata information on declarations in code: Classes, methods, functions, parameters, properties, etc.&lt;/p&gt;
&lt;h3&gt;
  
  
  Attributes Example
&lt;/h3&gt;

&lt;p&gt;In PHP 7 (With PHPDocs):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookController&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @Route("/api/books/{id}", methods={"GET"})
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&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 PHP 8:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookController&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;#[Route("/api/books/{id}", methods: ["GET"])]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&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;h2&gt;
  
  
  Constructor property promotion
&lt;/h2&gt;

&lt;p&gt;The basic idea is simple: ditch all the class properties and the variable assignments, and prefix the constructor parameters with &lt;code&gt;public&lt;/code&gt;, &lt;code&gt;protected&lt;/code&gt;, or &lt;code&gt;private&lt;/code&gt;. PHP will take that new syntax, and transform it to normal syntax under the hood, before actually executing the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Constructor properties example
&lt;/h3&gt;

&lt;p&gt;In PHP 7:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Point&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In PHP 8:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Point&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&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;
  
  
  My thoughts on Constructor property promotion
&lt;/h3&gt;

&lt;p&gt;Constructor property promotion reduces the amount of code that is required, leading to smaller and cleaner classes.&lt;br&gt;&lt;br&gt;
If you still want to have class properties that are not part of the constructor parameters, you can declare them in the old way, and instantiate them (or nor), inside the constructor.&lt;/p&gt;
&lt;h2&gt;
  
  
  Union types
&lt;/h2&gt;

&lt;p&gt;Union types are a way of declaring &lt;strong&gt;multiple types&lt;/strong&gt; for a property/variable.&lt;br&gt;
So if a function parameter can take either &lt;code&gt;string&lt;/code&gt; or &lt;code&gt;int&lt;/code&gt; values, you can now declare it as &lt;code&gt;string|int&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
This is something that you could not do in PHP 7, only using PHPDocs (so it was not part of the PHP core libraries, but existed in the PHPDocs).&lt;br&gt;&lt;br&gt;
Instead of PHPDoc annotations for a combination of types, you can use native union type declarations that are validated at &lt;strong&gt;runtime&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Union types example
&lt;/h3&gt;

&lt;p&gt;In PHP 7:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cd"&gt;/** @var int|float */&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="cd"&gt;/**
   * @param float|int $price
   */&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// OK at runtime&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In PHP 8, since Union types are part of the PHP runtime library and compiler, this will throw an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$price&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// TypeError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  My thoughts on Union types
&lt;/h3&gt;

&lt;p&gt;As a &lt;a href="https://en.wikipedia.org/wiki/SOLID" rel="noopener noreferrer"&gt;SOLID Principles&lt;/a&gt; advocate, I am not a big fan of this change.&lt;br&gt;&lt;br&gt;
I can understand that it can help speed things up and adds a level of control over my code, but I believe that if your code gets &lt;strong&gt;often&lt;/strong&gt; to the point that you need to use union type for a property, then there is definitely something you need to think about.&lt;/p&gt;
&lt;h2&gt;
  
  
  Match expression
&lt;/h2&gt;

&lt;p&gt;Match expression syntax is one of the nicest features in PHP 8 that improves the &lt;code&gt;switch&lt;/code&gt; syntax in multiple ways.&lt;/p&gt;

&lt;p&gt;Let's start by comparing the two. Here's a classic &lt;code&gt;switch&lt;/code&gt; example (example from &lt;a href="https://stitcher.io/blog/php-8-match-or-switch" rel="noopener noreferrer"&gt;this&lt;/a&gt; article):&lt;/p&gt;

&lt;p&gt;In PHP 7 (using &lt;code&gt;switch&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$statusCode&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="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'not found'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'server error'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;break&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="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'unknown status code'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;break&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 PHP 8 (using &lt;code&gt;match&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$statusCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;400&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'not found'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;500&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'server error'&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;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'unknown status code'&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;
  
  
  My thoughts on the match expression feature
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;match&lt;/code&gt; will do &lt;strong&gt;strict&lt;/strong&gt; type checks instead of &lt;strong&gt;loose&lt;/strong&gt; ones. It's like using &lt;code&gt;===&lt;/code&gt; instead of &lt;code&gt;==&lt;/code&gt;.&lt;br&gt;
In my opinion, this is a good chance, since it makes the code stricter and more expressive.&lt;br&gt;&lt;br&gt;
Also, If you forget to check for a value, and when there's no default arm specified, PHP will throw an &lt;code&gt;UnhandledMatchError&lt;/code&gt; exception.&lt;br&gt;&lt;br&gt;
Again more strictness, but it will prevent subtle bugs from going unnoticed.&lt;br&gt;&lt;br&gt;
To fix this, you should wrap the &lt;code&gt;match&lt;/code&gt; expression inside a separate method, and deal with the &lt;code&gt;UnhandledMatchError&lt;/code&gt; exception there, by returning a default value.&lt;/p&gt;
&lt;h2&gt;
  
  
  Nullsafe operator
&lt;/h2&gt;

&lt;p&gt;Instead of null check conditions, you can now use a chain of calls with the new nullsafe operator.&lt;br&gt;&lt;br&gt;
When the evaluation of one element in the chain fails, the execution of the entire chain aborts, and the entire chain evaluates to null.&lt;/p&gt;
&lt;h3&gt;
  
  
  Example of nullsafe operator
&lt;/h3&gt;

&lt;p&gt;In PHP 7:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$book&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$book&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$author&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$author&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getAddress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$address&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$address&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;country&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;p&gt;In PHP 8:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$book&lt;/span&gt;&lt;span class="o"&gt;?-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;?-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getAddress&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  My thoughts on nullsafe operator
&lt;/h3&gt;

&lt;p&gt;I have mixed feelings about this.&lt;br&gt;&lt;br&gt;
Of course, it is a handy touch since it leads to less and definitely more readable code.&lt;br&gt;&lt;br&gt;
But again, by looking at the big picture, why would our code even &lt;strong&gt;&lt;em&gt;need to check so deeply and greedily?&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Should our code have Business rules that restrain such behavior?&lt;br&gt;
So, again a handy new feature, but use with caution...&lt;/p&gt;
&lt;h2&gt;
  
  
  Saner string to number comparisons
&lt;/h2&gt;

&lt;p&gt;When comparing to a numeric string, PHP 8 uses a number comparison. Otherwise, it converts the number to a string and uses a string comparison.&lt;/p&gt;

&lt;p&gt;In PHP 7:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'foobar'&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In PHP 8:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'foobar'&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is definitely a step in the right direction, but only given that PHP is trying to be a stricter language.&lt;br&gt;&lt;br&gt;
When we say equals, we should mean &lt;strong&gt;equals&lt;/strong&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  My overall thoughts on PHP 8
&lt;/h2&gt;

&lt;p&gt;PHP is undoubtedly trying to become a stricter, more "serious" language.&lt;br&gt;&lt;br&gt;
As a big fan of &lt;a href="https://en.wikipedia.org/wiki/Object-oriented_programming" rel="noopener noreferrer"&gt;OOP&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/SOLID" rel="noopener noreferrer"&gt;SOLID Principles&lt;/a&gt; principles, I am totally happy and on board with this direction.&lt;br&gt;&lt;br&gt;
Also, as you will see in the upgrade guide, PHP 8 is generally backwards-friendly, since it does not break a lot of functionality from the previous major releases. Cool!  &lt;/p&gt;

&lt;p&gt;So let's try to use all the new features of PHP as consciously as possible, and build awesome things!&lt;/p&gt;

&lt;p&gt;If you are content with the new PHP version, take a look at the &lt;a href="https://www.php.net/manual/en/migration80.php" rel="noopener noreferrer"&gt;migration guide&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
What are your thoughts on PHP 8?&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
      <category>laravel</category>
      <category>discuss</category>
    </item>
    <item>
      <title>What’s New In the 2020 Scrum Guide Update</title>
      <dc:creator>Paul Isaris</dc:creator>
      <pubDate>Sun, 29 Nov 2020 12:58:05 +0000</pubDate>
      <link>https://dev.to/pavlosisaris/what-s-new-in-the-2020-scrum-guide-update-4c2e</link>
      <guid>https://dev.to/pavlosisaris/what-s-new-in-the-2020-scrum-guide-update-4c2e</guid>
      <description>&lt;p&gt;Post photo by &lt;a href="https://www.pexels.com/" rel="noopener noreferrer"&gt;pexels&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally published on &lt;a href="https://paulisaris.com/whats-new-in-the-2020-scrum-guide-update/" rel="noopener noreferrer"&gt;paulisaris.com&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;2020 Is (finally) coming to an end, but it wouldn't leave us with anything less than another surprise!&lt;/p&gt;

&lt;p&gt;On November 18, 2020, Ken Schwaber and Jeff Sutherland published an update of the Scrum Guide. &lt;br&gt;&lt;br&gt;
According to the co-creators, the Scrum Guide 2020 aims at “bringing Scrum back to being a minimally sufficient framework by removing or softening prescriptive language”.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;In this article, we will review what was added, &lt;a href="https://www.scrum.org/resources/blog/scrum-guide-2020-update-what-has-been-removed" rel="noopener noreferrer"&gt;what was removed&lt;/a&gt;, what has not, and what you need to take care of.&lt;/p&gt;

&lt;p&gt;For an audio version of the 2020 Scrum Guide, check &lt;a href="https://www.youtube.com/watch?v=k9UBINcAcHw&amp;amp;ab_channel=Incrementor" rel="noopener noreferrer"&gt;this link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also see a side-by-side comparison of the new Scrum Guide &lt;a href="https://www.scrum.org/resources/blog/scrum-guide-2020-and-2017-side-side-comparison" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fegn52985kgsrqdafr4pc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fegn52985kgsrqdafr4pc.png" alt="Scrum poster" width="800" height="565"&gt;&lt;/a&gt; &lt;br&gt;
 &lt;/p&gt;image taken from &lt;a href="https://www.scrum.org/" rel="noopener noreferrer"&gt;scrum.org&lt;/a&gt;

&lt;h1&gt;
  
  
  In a nutshell
&lt;/h1&gt;

&lt;h4&gt;
  
  
  Simpler language, more inclusion with the "Scrum team", Addition of "Why?" To Sprint Planning
&lt;/h4&gt;

&lt;p&gt;The new Scrum guide adopted a &lt;strong&gt;simpler language&lt;/strong&gt; and generally &lt;strong&gt;removed software-specific terminology&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
The authors also reduced it's size, from 19 pages in 2017, to 14 pages.&lt;/p&gt;

&lt;h4&gt;
  
  
  No more "3 questions", no servant-leadership
&lt;/h4&gt;

&lt;p&gt;The Scrum Guide is now less prescriptive, and more direct.&lt;br&gt;&lt;br&gt;
It eliminates many suggestions such as the &lt;strong&gt;Daily Scrum questions&lt;/strong&gt;, removes the "at least one mandatory action item from the Retrospective becoming a part of the Sprint Backlog" part as well as the advice on why Sprint cancelations are rare events. &lt;/p&gt;

&lt;p&gt;There is neither mention of the three questions during the Daily Scrum, nor of the term "servant leadership" of the Scrum Master.&lt;br&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  No mention of "agile"
&lt;/h4&gt;

&lt;p&gt;A very interesting fact though, is that there is not mention of the &lt;strong&gt;&lt;em&gt;"agile"&lt;/em&gt;&lt;/strong&gt; word!&lt;br&gt;&lt;br&gt;
Instead, there is an abvious shift towards getting Scrum to follow the &lt;strong&gt;&lt;em&gt;"lean"&lt;/em&gt;&lt;/strong&gt; principle.&lt;br&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Main motto not stated
&lt;/h4&gt;

&lt;p&gt;Also, the obvious is &lt;strong&gt;no&lt;/strong&gt; longer stated: &lt;strong&gt;Scrum is indeed not trivial to master&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  In a bigger nutshell
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Changes that are worth mentioning
&lt;/h2&gt;

&lt;p&gt;Here are the bolder changes that are worth to review and reflect on:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. No mention of the three questions during the Daily Scrum
&lt;/h3&gt;

&lt;p&gt;OK, let's begin with the elephant in the room. No more 3 questions imposed in the Daily Scrum meeting!&lt;/p&gt;

&lt;p&gt;Even in the 2017 versions, the three questions “What did I do yesterday that helped the Development Team meet the Sprint Goal?” and so on, were optional. &lt;/p&gt;

&lt;p&gt;This means that the "Developers" (since &lt;strong&gt;there is no more a "Development Team"&lt;/strong&gt;), can follow any structure they want, provided that it focuses on the plan for the day.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. No more "Development Team"
&lt;/h3&gt;

&lt;p&gt;That's right! The Development Team is no more. Long live the &lt;strong&gt;"Developers"&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;This aims to &lt;strong&gt;eliminate the team within a team&lt;/strong&gt; (often forming a silo) and normalize the often alienated relationship between the Product Owner and the Development Team.&lt;/p&gt;

&lt;p&gt;Additionally, this change was to &lt;strong&gt;increase responsibility&lt;/strong&gt; for the Product as one team and not just as the Product Owner.&lt;br&gt;&lt;br&gt;
   Every member of the Scrum Team has the responsibility of the Product being built!&lt;/p&gt;

&lt;h3&gt;
  
  
  3. A brand new Sprint Planning
&lt;/h3&gt;

&lt;p&gt;Since 2017, the focus on Sprint Planning was on "what we are building", and "how we are building it"&lt;br&gt;
   The Sprint Planning in 2020 has been enriched with a third topic - &lt;strong&gt;Why&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;To make it easier for stakeholders to inspect a Product, the Scrum Team must now also focus on "Why" they are selecting the designated Backlog items, from the Product Backlog. &lt;/p&gt;

&lt;p&gt;It's the &lt;strong&gt;job of the Product Owner&lt;/strong&gt; to propose how this Sprint could increase the product’s value.&lt;/p&gt;

&lt;p&gt;Read more &lt;a href="https://www.scrum.org/resources/blog/why-what-how-sprint-planning" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. “Done” now creates a Product Increment
&lt;/h3&gt;

&lt;p&gt;This change was made to embrace the quality of work. &lt;/p&gt;

&lt;p&gt;According to the new guide:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The Definition of Done is a formal description of the state of the Increment when it meets the quality measures required for the product.&lt;br&gt;&lt;br&gt;
The moment a Product Backlog item meets the Definition of Done, an Increment is born."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  5. Definition of Done Created By Scrum Team
&lt;/h3&gt;

&lt;p&gt;Alright, so this is a big change. &lt;/p&gt;

&lt;p&gt;From the 2020 Scrum Guide:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The entire Scrum Team is accountable for creating a valuable, useful Increment every Sprint.” &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While there are still explicit accountabilities for the Product Owner, Scrum Master, and Developers, all three roles must work together effectively to be successful with Scrum.&lt;/p&gt;

&lt;p&gt;This is another evidence that Scrum now is following a more &lt;strong&gt;holistic approach&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;A Definition of Done is most effective when created as a collaboration among the entire Scrum Team. &lt;br&gt;&lt;br&gt;
So, next time you are planning your Scrum and defining the Definition of Done, don't forget to also include the Product Owner and the Scrum Master in the process! &lt;/p&gt;

&lt;p&gt;Read more &lt;a href="https://www.scrum.org/resources/blog/2020-scrum-guide-definition-done-created-scrum-team" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Don't present partially done items in the Sprint Review
&lt;/h3&gt;

&lt;p&gt;That's right. we already knew that partially "Done" items &lt;strong&gt;were not accepted as part of the Increment&lt;/strong&gt;. &lt;br&gt;But, this version of the guide goes a step further: &lt;strong&gt;Don't present them&lt;/strong&gt;, and never speak about them until they are "Done".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The Definition of Done is a formal description of the state of the Increment when it meets the quality measures required for the product. &lt;br&gt;&lt;br&gt;
   The moment a Product Backlog item meets the Definition of Done, an Increment is born."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  7. A new term: The Product Goal
&lt;/h3&gt;

&lt;p&gt;As &lt;a href="https://www.scrum.org/resources/blog/scrum-guide-2020-update-introducing-product-goal" rel="noopener noreferrer"&gt;the new guide states&lt;/a&gt;, there is a new kid around the block! &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The Product Goal describes a future state of the product which can serve as a target for the Scrum Team to plan against. […] The Product Goal is the long-term objective of the Scrum Team."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Don't freak out, the Product Goal is not entirely new, since Scrum teams had a goal anyway. (What is the point of building software if you don't have a goal...?)&lt;/p&gt;

&lt;p&gt;But it now has a name and it is clearly defined.&lt;/p&gt;

&lt;p&gt;The Product Goal provides context to the Product Backlog. &lt;br&gt;&lt;br&gt;
   It can be thought of as the "why" we are doing all of this work. It can be used as the elevator pitch to "what is the Scrum Team working on?". &lt;/p&gt;

&lt;p&gt;So think of it more as a &lt;strong&gt;1-sentence way&lt;/strong&gt; of describing the whole product, and why you are building it!&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Don't treat Sprint Review as a "Release Gate"
&lt;/h3&gt;

&lt;p&gt;Many Scrum teams have shifted from constructive Sprint reviews to "Release Gates", making the Sprint Review just a meeting to tell the Product Owner "You can go ahead and release the increment now!". &lt;/p&gt;

&lt;p&gt;The new Scrum guide addresses this by stating that &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The Sprint Review should never be considered a gate to releasing value."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So use the Sprint Review to learn and reflect, and detach it from the release cycle.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. New Product Explanation
&lt;/h3&gt;

&lt;p&gt;With a brand new Product Explanation, it becomes clear that Scrum now shifts beyond just software. In my opinion, it won't be long before we see Scrum implemented widely in non-software teams, as well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A product is a vehicle to deliver value.&lt;br&gt;&lt;br&gt;
It has a clear boundary, known stakeholders, well-defined users, or customers.&lt;br&gt;&lt;br&gt;
A product could be a service, a physical product, or something more abstract."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  10. Servant leadership no longer mentioned
&lt;/h3&gt;

&lt;p&gt;Even if servant leadership is not mentioned directly, I don't think that the authors aim to shape Scrum Masters to be anything else than servant leaders.&lt;/p&gt;

&lt;p&gt;The new guide describes the Scrum Master as following: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Scrum Masters are true leaders who serve the Scrum Team and the larger organization."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is now likely that the "Scrum Master" job title will include a job description that is larger than the accountabilities described in the Scrum Guide since it is treated as an organization leader role.&lt;/p&gt;

&lt;h3&gt;
  
  
  11. The spotlight is on the Scrum team
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;"The Scrum Team is responsible for all product-related activities from stakeholder collaboration, verification, maintenance, operation, experimentation, research and development, and anything else that might be required."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a more holistic approach than the previous version had. Now, it is clearly stated that it's not only developers who bear responsibility for the product, &lt;strong&gt;but the team as a whole&lt;/strong&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  12. "Commitments"
&lt;/h3&gt;

&lt;p&gt;The Product Goal, the Sprint Goal, and the Definition of Done are now mentioned as &lt;a href="https://www.scrum.org/resources/blog/scrum-guide-2020-update-commitments" rel="noopener noreferrer"&gt;&lt;strong&gt;"Commitments"&lt;/strong&gt;&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;This is a bridge to connect &lt;strong&gt;Scrum Values&lt;/strong&gt; (commitment, focus, respect, courage, openness) with the "Scrum Empiricism": Transparency, Inspection, and Adaptation. &lt;/p&gt;

&lt;p&gt;The Scrum Guide describes a commitment as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Each artifact contains a commitment to ensure it provides information that enhances transparency and focus against which progress can be measured.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Each of the three artifacts now contains "commitments" to them.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Product Goal is the commitment for the Product Backlog.&lt;/li&gt;
&lt;li&gt;Sprint Goal is the commitment for Sprint Backlog.&lt;/li&gt;
&lt;li&gt;Definition of Done is the commitment to the Increment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Read more &lt;a href="https://www.scrum.org/resources/blog/addition-commitments-each-artifact" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F51mkyyp844kz34qohe9r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F51mkyyp844kz34qohe9r.png" alt="Scrum poster" width="800" height="567"&gt;&lt;/a&gt; &lt;br&gt;
 &lt;/p&gt;image taken from &lt;a href="https://www.scrum.org/" rel="noopener noreferrer"&gt;scrum.org&lt;/a&gt;

&lt;h1&gt;
  
  
  Further Readings
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.scrum.org/resources/blog/scrum-guide-2020-and-2017-side-side-comparison" rel="noopener noreferrer"&gt;Scrum Guide 2020 and 2017: A Side-by-Side Comparison&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.scrum.org/resources/blog/scrum-guide-2020-update-what-has-been-removed" rel="noopener noreferrer"&gt;Scrum Guide 2020 Update - What has been removed&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.scrum.org/resources/blog/scrum-guide-2020-update-introducing-product-goal" rel="noopener noreferrer"&gt;Scrum Guide 2020 Update - Introducing the Product Goal&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.scrum.org/resources/blog/why-what-how-sprint-planning" rel="noopener noreferrer"&gt;Why, What, How - Sprint Planning&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.scrum.org/resources/blog/what-4-key-changes-scrum-guide-tell-us-about-scrum" rel="noopener noreferrer"&gt;What 4 Key Changes To The Scrum Guide Tell Us About Scrum&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.scrum.org/resources/blog/2020-scrum-guide-definition-done-created-scrum-team" rel="noopener noreferrer"&gt;2020 Scrum Guide: Definition of Done Created By Scrum Team&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.scrum.org/resources/blog/home-product-goal-definition-done-and-sprint-goal" rel="noopener noreferrer"&gt;A Home for Product Goal, Definition of Done, and Sprint Goal&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.scrum.org/resources/blog/scrum-guide-2020-update-commitments" rel="noopener noreferrer"&gt;Scrum Guide 2020 Update - Commitments&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;The 2020 Scrum Guide includes significant changes to the framework to broaden its appeal to applications beyond software development. &lt;/p&gt;

&lt;p&gt;It &lt;strong&gt;simplifies&lt;/strong&gt; the language used, and it &lt;strong&gt;empowers&lt;/strong&gt; the "Scrum Team", in favor of the "Development Team". &lt;/p&gt;

&lt;p&gt;It also makes the Sprint more &lt;strong&gt;meaningful&lt;/strong&gt;, by making the &lt;strong&gt;Sprint Goal obligatory&lt;/strong&gt;.&lt;br&gt;
Scrum Master as a role is now treated as a &lt;strong&gt;leader of the organization&lt;/strong&gt;, and not just a mere coach who acts upon request, as a servant leader.&lt;/p&gt;

&lt;p&gt;In my opinion, the changes are in the &lt;strong&gt;right direction&lt;/strong&gt;. &lt;br&gt;&lt;br&gt;
More responsibility to the team as a whole, and an apparent need for the Developers to start collaborating more with the Product Owner. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Product Owner now has more responsibility&lt;/strong&gt; for the Product Backlog, since they have to explain the current Product Goal to the whole Scrum Team.&lt;/p&gt;

&lt;p&gt;But, don't fret. As stated on scrum.org website, &lt;a href="https://www.scrum.org/resources/blog/scrum-guide-2020-update-scrum-still-scrum" rel="noopener noreferrer"&gt;Scrum is still Scrum!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is your opinion on the Scrum Guide 2020 changes?&lt;/p&gt;

</description>
      <category>news</category>
      <category>agile</category>
      <category>scrum</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to introduce a new developer to a project</title>
      <dc:creator>Paul Isaris</dc:creator>
      <pubDate>Mon, 17 Aug 2020 08:03:26 +0000</pubDate>
      <link>https://dev.to/dailydotdev/how-to-introduce-a-new-developer-to-a-project-2866</link>
      <guid>https://dev.to/dailydotdev/how-to-introduce-a-new-developer-to-a-project-2866</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Often, there is a need to introduce a new developer to the team for a specific project. &lt;br&gt;
This onboarding process is never easy and sometimes tends to be &lt;strong&gt;painful&lt;/strong&gt; for the new member and &lt;strong&gt;frustrating&lt;/strong&gt; for the team, which has to keep working on the already defined tasks without a significant impact on their productivity.&lt;/p&gt;

&lt;p&gt;Of course, this process differs from team to team and is proportional to the seniority level of the new team member, as well as the time they have been working at the company.&lt;/p&gt;

&lt;p&gt;I will try to keep the following guide as abstract as possible, to accommodate most cases. Keep in mind, though, to tailor the recommendations to fit your team's needs and post your thoughts in the comments!&lt;/p&gt;

&lt;p&gt;This guide assumes a typical 8-hour workday. It is further divided into subsections, with ideas about what to do during each time of the day. Feel free to update it according to the habits and ceremonies of your team, to maximize value.&lt;/p&gt;

&lt;h1&gt;
  
  
  The 2-day plan
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Day 1
&lt;/h2&gt;

&lt;p&gt;This is the first day that the new team member will start working along with your team. It is a very special day, of course!&lt;br&gt;
You don't want to stress them or to make them feel lost, even though it is highly likely that they will feel overwhelmed anyway.&lt;br&gt;
Try to be as cool as possible and not throw deadlines and project reports to their face.&lt;br&gt;
Your job is to make them feel &lt;strong&gt;welcome and productive&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 1 - Morning:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A short overview of what the business does&lt;/strong&gt; (an hour, tops) - understanding how the company makes money is essential. If the new developer is in the company already, then a brief introduction of the project is in order, along with the business side - how the project works and how the client makes revenue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A short overview of the high-level architecture&lt;/strong&gt; (no more than a couple of hours). If the team has already decided upon frameworks, Database technologies, 3rd party libraries, or external APIs, this is something that should be communicated in time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A learning plan&lt;/strong&gt; for project-specific technologies. The new developer needs to feel not only that they have the time required to get up to speed with all the languages and the frameworks, but also that there is no time to slack off, or feel &lt;strong&gt;unproductive&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Day 1 - Afternoon:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Update on the learning plan;&lt;/strong&gt; Questions, answers, and a small update of what has been taught so far. The goal of this is that the new developer does not waste time researching everything about the new language/framework, but only this 20% that will get them going and become productive, according to the &lt;a href="https://en.wikipedia.org/wiki/Pareto_principle" rel="noopener noreferrer"&gt;Pareto Principle&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;** learning** how to set up a project in the new language/framework. They will need to do that anyway so that it will come in handy.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Day 2
&lt;/h2&gt;

&lt;p&gt;During this day, the new team member should get cracking with &lt;strong&gt;real project tasks&lt;/strong&gt;. However, this doesn't mean that the learning stops. On the contrary, the learning now has a supplementary role, and it becomes less important as the tasks progress, and the developer feels more comfortable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 2 - Morning:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;** project set up and initialization**. If the project has an existing codebase, the new developer will need to clone it to their machine, set it up, and get it to compile/build/run (depends on the framework). This is usually not easy, and every other developer on the team needs to pay attention here.&lt;br&gt;&lt;br&gt;
Often, this process reveals a lack of proper documentation of the project. Developers sometimes assume things, especially for the installation/set-up procedure of a project. So this is an excellent opportunity to revamp the documentation of the project and make sure that there are no assumptions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A specific task&lt;/strong&gt; which gets them familiar with just one or two files in the codebase, done with one of the more experienced programmers sitting with them to help 1:1. It is crucial for a new developer not to feel alone on a task.&lt;br&gt;The best strategy is to assign them to a task that only exposes them to as few files as possible so that they don't feel lost.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Day 2 - Afternoon:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A couple of short specific tasks&lt;/strong&gt; with an experienced programmer dedicated to helping a "small group of starters" (typically 2–3).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flying solo on a small task&lt;/strong&gt;, but knowing that they can ask for help [this never stops.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Repeat&lt;/strong&gt;, with increasingly larger tasks, covering more of the codebase.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point, the new developer should already feel comfortable and productive. However, remember that as the difficulty of the tasks increase, they may feel overwhelmed again, and that's usually when the &lt;a href="https://en.wikipedia.org/wiki/Impostor_syndrome" rel="noopener noreferrer"&gt;Impostor syndrome&lt;/a&gt; occurs.&lt;br&gt;So, it becomes obvious that the new team member should feel free to ask any questions, no matter how "stupid" or "obvious" they may seem.&lt;/p&gt;

&lt;h1&gt;
  
  
  What to do now - action points
&lt;/h1&gt;

&lt;p&gt;After you have read this guide, it's time to get cracking and &lt;strong&gt;create your personalized&lt;/strong&gt; onboarding plan!&lt;br&gt;
Of course, your organization has its own rules and pain points, and the team your a member of may benefit from different situations and &lt;strong&gt;habits&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;After all, it's your responsibility to create an onboarding guide that best &lt;strong&gt;fits and serves&lt;/strong&gt; your team's needs.&lt;/p&gt;

&lt;p&gt;So, go ahead and don't be afraid to spend some time writing down ideas and situations that you and your team found &lt;strong&gt;difficult&lt;/strong&gt; and &lt;strong&gt;unsustainable&lt;/strong&gt; in the past. Then, write how these problems could be &lt;strong&gt;alleviated&lt;/strong&gt;, by applying the 2-day onboarding plan, and ** don't be afraid to try** your plan (we only get &lt;strong&gt;better&lt;/strong&gt; by trial and error!)&lt;/p&gt;

&lt;h1&gt;
  
  
  Last thoughts
&lt;/h1&gt;

&lt;p&gt;To conclude, adding a new member to a software team &lt;strong&gt;is not an easy task&lt;/strong&gt;. Sometimes we forget how important the onboarding process can be, resulting in &lt;strong&gt;poor estimates&lt;/strong&gt; (as the onboarding is hugely underestimated), Impostor syndromes, and confusion for the entire team.&lt;br&gt;
Having a solid and effective onboarding plan is crucial as it ensures both &lt;strong&gt;productivity&lt;/strong&gt; and &lt;strong&gt;good morale&lt;/strong&gt; for the &lt;strong&gt;entire team&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Further readings
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.process.st/checklist/developer-onboarding-checklist-for-startups/" rel="noopener noreferrer"&gt;Developer Onboarding Checklist for Startups&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/92bondstreet/awesome-onboarding" rel="noopener noreferrer"&gt;Awesome Onboarding - GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.dragonspears.com/blog/developer-onboarding-checklist-for-successful-agile-teams" rel="noopener noreferrer"&gt;Developer Onboarding Checklist for Successful Agile Teams&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cover photo by &lt;a href="https://www.pexels.com/" rel="noopener noreferrer"&gt;pexels&lt;/a&gt;&lt;br&gt;
This post also appears on &lt;a href="https://paulisaris.com/how-to-introduce-a-new-developer-to-a-project/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;a href="https://r.daily.dev/get?r=devto" rel="noopener noreferrer"&gt;daily.dev&lt;/a&gt; delivers the best programming news every new tab. We will rank hundreds of qualified sources for you so that you can hack the future.&lt;/em&gt;&lt;br&gt;
&lt;a href="https://r.daily.dev/get?r=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb996k4sm4efhietrzups.png" alt="Daily Poster" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>help</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>10 Tips For a Productive Virtual Meeting</title>
      <dc:creator>Paul Isaris</dc:creator>
      <pubDate>Wed, 01 Apr 2020 05:41:08 +0000</pubDate>
      <link>https://dev.to/pavlosisaris/10-tips-for-a-productive-virtual-meeting-35dk</link>
      <guid>https://dev.to/pavlosisaris/10-tips-for-a-productive-virtual-meeting-35dk</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@johnschno?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;John Schnobrich&lt;/a&gt; on &lt;a href="https://unsplash.com" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://paulisaris.com/10-tips-for-a-productive-virtual-meeting/" rel="noopener noreferrer"&gt;paulisaris.com&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;It's this strange time of the &lt;strong&gt;"Social distancing era"&lt;/strong&gt;, because of the coronavirus bizarre situation.&lt;br&gt;
Regardless of how long this lasts or whatever the world will look like after it ends, it is for sure an interesting time to be alive and &lt;strong&gt;trying to make a living through a pandemic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We, as developers, are fortunate enough to be able to still work with little to no severe impacts&lt;br&gt;
in our everyday tasks and projects. Most of us have set-up our homework offices, poured ourselves a cup of&lt;br&gt;
coffee or tea and get cracking with our tasks.&lt;/p&gt;

&lt;p&gt;However, with everything that is happening around the world, teams now face the challenge of doing most of their work virtually. Meetings with the team and the clients,  code reviews, &lt;a href="https://www.scrum.org/resources/what-is-scrum" rel="noopener noreferrer"&gt;Scrum&lt;/a&gt; events, all work-related social events have been moved to the &lt;strong&gt;"virtual world"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What this essentially means, is that we should find a way to remain productive and professional, even in this scenario.&lt;br&gt;
Some of us have been having more experience with this, while some others are just being introduced to the world of virtual meetings, and they need some guidance.&lt;/p&gt;

&lt;p&gt;In this post, I share 10 tips for ensuring that we have productive meetings and that value is being delivered, no matter the situation.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Steps
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Prepare some material beforehand
&lt;/h2&gt;

&lt;p&gt;It's crucial for the meeting to be targeted towards a well-known &lt;strong&gt;goal and subject&lt;/strong&gt;.&lt;br&gt;
Spend some time to bring together a document (which preferably can be edited online by key participants). This is very important in the case that you are hosting the meeting.&lt;br&gt;
In this document, specify the &lt;strong&gt;meeting goal&lt;/strong&gt; (or leave it to be completed as soon as the meeting starts).&lt;/p&gt;

&lt;p&gt;Also, don't forget to prepare any links, presentation files, videos, application credentials and notes that you may need during the meeting.&lt;/p&gt;

&lt;p&gt;Being well prepared is a sign of utmost &lt;strong&gt;professionalism&lt;/strong&gt;, something we all like to be congratulated for!&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Prepare and check your equipment
&lt;/h2&gt;

&lt;p&gt;Nobody likes to join a virtual meeting only to find out that their camera is not working or that their microphone is hissing and making weird noises. &lt;/p&gt;

&lt;p&gt;At least 30 minutes before the meeting starts, dedicate some time to &lt;strong&gt;set up your equipment&lt;/strong&gt;. Make sure that the room has the proper lighting for the camera, and that your voice sounds as expected through the microphone.&lt;/p&gt;

&lt;p&gt;Most software applications for virtual meetings (eg Skype, Hangouts, Zoom, etc) have a built-in process for doing the tasks above. Spend 2 minutes before the meeting starts to do a final technical check-up and be ready!&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Please, mute your microphone!
&lt;/h2&gt;

&lt;p&gt;Seriously, I can't stress this enough. As long as you are not speaking, please mute your microphone. It makes everyone's life difficult and makes people want to leave the meeting even more. &lt;/p&gt;

&lt;p&gt;Also, when the meeting starts, remind everyone of the golden &lt;strong&gt;"Mute when not speaking" rule&lt;/strong&gt;.&lt;br&gt;
It's extremely easy to unmute your microphone when you want to speak or ask a question.&lt;/p&gt;

&lt;p&gt;If the Internet connectivity is not good during the meeting, you can kindly ask the other participants to close their cameras so that you can hear them (even though you will not be able to see them).&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Set the mood for the meeting
&lt;/h2&gt;

&lt;p&gt;If you are hosting the meeting, it's always a good starter to set the mood.&lt;br&gt;
Start by asking you everyone is doing so that you add a personal touch. Remember, all participants are joining the meeting from their personal space which may include crying kinds, noisy neighbors, shouting construction site workers (even though the latter is not the case in a pandemic).&lt;/p&gt;

&lt;p&gt;Begin by sharing the document from step 1, and ask everyone to confirm that they have access to see it. Remark the &lt;strong&gt;meeting goal&lt;/strong&gt; and try to come up with an estimation of how long the meeting should be so that all the participants are on the same page and can organize their after-meeting tasks better.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Set the rules for the meeting
&lt;/h2&gt;

&lt;p&gt;Again, this is very important, especially if you are the host. Remember, that some of the participants might be using the virtual meeting software for the first time, so it's a nice idea to take some time and explain how the meeting is going to run.&lt;/p&gt;

&lt;p&gt;For example, you can start by prompting everyone to mute their microphones (after the introductions of course) and use the &lt;strong&gt;"raise hand"&lt;/strong&gt; functionality when they want to intervene.&lt;/p&gt;

&lt;p&gt;Besides, it goes without saying that if a participant is acting selfishly (by not letting others speak for example), you should address the problem by reminding them of the rules throughout the meeting.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Prepare your environment for screen-sharing ;-)
&lt;/h2&gt;

&lt;p&gt;When participating in a virtual meeting, you might need to share your screen for several reasons. Be it that you want to show something to the people or to showcase the application you have been working on to a client.&lt;/p&gt;

&lt;p&gt;The thing is that during this pandemic era, we are working from our home setups. This means that you will probably be using your home computer to join the meeting.&lt;br&gt;
So, your desktop, web browser and applications window should be in a &lt;strong&gt;"presentation-ready" state&lt;/strong&gt; ;-)&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Don't be afraid to close the camera
&lt;/h2&gt;

&lt;p&gt;Working from home also means using the home network. Especially in the case that you are using Wi-Fi, your Internet connectivity might not be the best. To add insult to injury, remember also that, because most people are working from home, Internet networks are stressed already and you might not get a good service.&lt;/p&gt;

&lt;p&gt;In the unfortunate event that this happens, excuse yourself by explaining the situation and feel free to close your camera. After all, the important part of the meeting is probably to be able to hear the other participants and be able to &lt;strong&gt;communicate with them&lt;/strong&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  8. Revise often and take notes
&lt;/h2&gt;

&lt;p&gt;It is a common scenario that virtual meetings go on forever, and after a while, people don't pay attention to what is being said. After all, there is no one around to restrain them from checking their phones or open a new tab in the browser...&lt;/p&gt;

&lt;p&gt;You should make sure that &lt;strong&gt;value is being delivered&lt;/strong&gt; through the meeting. So note-keeping will both keep you concentrated on the meeting and will result in an organized after-meeting roadmap for the next steps.&lt;/p&gt;

&lt;p&gt;Additionally, if you are the host of the meeting, you should often vocally revise what is being said, to wake up the participants who are slacking off and prompt them to voice any objections or additions they might be having.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Resist the urge to check your phone
&lt;/h2&gt;

&lt;p&gt;As stated in the previous step, it is a common thing for virtual meetings to result in only a handful of people paying attention while all the others are checking and replying to their e-mails or checking their social media.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's important to resist the urge to do so!&lt;/strong&gt; Remember, participating in a meeting -whether virtual or not- means that you have the responsibility to be present in your full professional "outfit". After all, you might miss something really important which will probably result in numerous other meetings and e-mails!&lt;/p&gt;

&lt;h2&gt;
  
  
  10. There will be chaos. And that's OK!
&lt;/h2&gt;

&lt;p&gt;Sure, everybody will try their best for the meeting to be as efficient and productive as possible. However, bear in mind that &lt;strong&gt;chaos&lt;/strong&gt; (either technical or not) should be expected.&lt;/p&gt;

&lt;p&gt;The microphones will not be operating as planned, networks will fail, whole sentences will be asked to be repeated for people who "did not quite catch the last 5 minutes of your talk".&lt;/p&gt;

&lt;p&gt;And you know what?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is perfectly fine&lt;/em&gt;. As developers, we are experienced in working with technical difficulties and finding alternate solutions to our problems: Skype is not working? Let's all switch to Zoom. Microphone not working? Fine, write in the chatbox. &lt;br&gt;
The whole meeting thing is not working? Fine, let's either organize another time for it or compress it in an e-mail (after all, &lt;strong&gt;&lt;em&gt;most meetings should have been e-mails&lt;/em&gt;&lt;/strong&gt;, right?)&lt;/p&gt;

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

&lt;p&gt;In these strange yet important times, it is more vital than ever that we are able to prove that technology is helping things keep moving and we -as a purely technological field- are obliged to do so.&lt;/p&gt;

&lt;p&gt;What are your thoughts on virtual meetings?&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>beginners</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Scrum Events demystified - Sprint Planning</title>
      <dc:creator>Paul Isaris</dc:creator>
      <pubDate>Tue, 18 Feb 2020 15:29:18 +0000</pubDate>
      <link>https://dev.to/pavlosisaris/scrum-events-demystified-sprint-planning-1pg6</link>
      <guid>https://dev.to/pavlosisaris/scrum-events-demystified-sprint-planning-1pg6</guid>
      <description>&lt;p&gt;post photo by &lt;a href="https://www.pexels.com/" rel="noopener noreferrer"&gt;pexels&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;This post is the second part of the "Scrum events demystified" post series. You can find the first part here:&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/pavlosisaris/scrum-events-demystified-the-sprint-2j8c" class="crayons-story__hidden-navigation-link"&gt;Scrum Events demystified - The Sprint&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/pavlosisaris" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F35635%2F522050db-b4f4-438e-bb9c-b2a5eaa4807a.jpg" alt="pavlosisaris profile" class="crayons-avatar__image" width="500" height="500"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/pavlosisaris" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Paul Isaris
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Paul Isaris
                
                
              
              &lt;div id="story-author-preview-content-253365" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/pavlosisaris" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F35635%2F522050db-b4f4-438e-bb9c-b2a5eaa4807a.jpg" class="crayons-avatar__image" alt="" width="500" height="500"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Paul Isaris&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/pavlosisaris/scrum-events-demystified-the-sprint-2j8c" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Feb 2 '20&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/pavlosisaris/scrum-events-demystified-the-sprint-2j8c" id="article-link-253365"&gt;
          Scrum Events demystified - The Sprint
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/agile"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;agile&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/pavlosisaris/scrum-events-demystified-the-sprint-2j8c" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;18&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/pavlosisaris/scrum-events-demystified-the-sprint-2j8c#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;






&lt;p&gt;In order to successfully execute the Scrum tasks and maximize the Increment value, a team needs to pay attention to the chronologically first Event in the Sprint; &lt;strong&gt;&lt;em&gt;The Sprint Planning event&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  About Sprint Planning
&lt;/h1&gt;

&lt;p&gt;Sprint Planning is a &lt;strong&gt;time-boxed event&lt;/strong&gt; (as all events are in Scrum). &lt;br&gt;
 Time-boxed means that it has a &lt;strong&gt;predefined, specific time span&lt;/strong&gt;, &lt;br&gt;
 and should start and end exactly when this period dictates. &lt;br&gt;&lt;/p&gt;

&lt;p&gt;For example, the team might agree upon having one-month Sprints. &lt;br&gt;
 Other teams might be more comfortable and productive with 2-week Sprints.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For 1-month Sprints, the Sprint Planning event should be 8-hours long&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Who should attend the Sprint Planning event?&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
 Everyone (Product Owner, Scrum Master, Development team).&lt;/p&gt;

&lt;p&gt;The Sprint Planning event's goal is to address the following topics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Selecting the work to do in the Sprint&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The product owner explains the backlog items to the Development team.&lt;br&gt;
The development team determines the number of backlog items that will be brought into the Sprint Backlog&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Planning how the sprint work will be done&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The Development Team does this. The Development Team needs to only do necessary planning work for the first few days of the Sprint. As the development team analyses the work they selected from the backlog, they can renegotiate the work with the Product Owner.&lt;br&gt;
Ideally, the Sprint Backlog tasks are decomposed so they can be finished within a business day.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;During the Sprint Planning event, the Development Team is supposed to construct the &lt;strong&gt;Sprint Backlog&lt;/strong&gt;, a collection of tasks that will be owned and developed by the Developers.&lt;/p&gt;

&lt;p&gt;According to the Scrum Guide:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The Sprint Backlog is a plan with enough detail that changes in progress can be understood at the Daily Scrum”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Most common questions and misconceptions about Sprint Planning
&lt;/h1&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Why is Sprint planning important?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sprint Planning is important because the outcomes of it are the Sprint Goal and a plan of delivering the Increment. Both the Sprint Goal and -of course- the Increment are integral parts of the product development process and define whether the product will be successful or not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Should the Sprint Backlog remain intact after Sprint Planning?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No.&lt;/strong&gt; The Development Team modifies the Sprint Backlog throughout the Sprint, And the Sprint Backlog emerges during the Sprint. This emergence occurs as the Development Team works through the Sprint and gains more knowledge about the work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Should the tasks in the Product Backlog be User stories?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No.&lt;/strong&gt; Actually, the tasks in the Sprint Backlog can be expressed however the Development Team desires, as long as they are clear and communicate the work to be done.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;How are the Product Backlog items prioritized and by whom?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In Scrum, The &lt;strong&gt;Product Owner&lt;/strong&gt; is responsible for maximizing the value of the product and they manage the Product Backlog as such. 
During Sprint Planning the 
Product Owner suggests the objective of the upcoming Sprint and proposes 
which Product Backlog Items will help achieve this objective.
So, the items in the Product Backlog are ordered by &lt;strong&gt;value&lt;/strong&gt;.
The most important ones go at the top so that they are selected for the next Sprint Backlog.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Does the whole Scrum team agrees on the estimates for a task?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No.&lt;/strong&gt; Only the development team creates estimates, which can, of course, be communicated with the other stakeholders (Product Owner and business stakeholders), but &lt;strong&gt;in no way negotiated with them&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;When a task is assigned to a developer, are they solemnly responsible for it?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No.&lt;/strong&gt; All tasks in the Sprint Backlog belong to the whole Development Team and the whole Development Team is responsible for them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Is the Sprint Backlog just a collection of tasks selected from the Product Backlog, to be done in the current Sprint?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No.&lt;/strong&gt; The Sprint Backlog also contains a plan of how the work will be done. It might contain tasks, sub-tasks, notes, and development guidelines.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;In conclusion, the Sprint Planning event is a &lt;strong&gt;time-boxed event&lt;/strong&gt;, during which the Scrum Team discusses the next Sprint, it's &lt;strong&gt;goal&lt;/strong&gt; and &lt;strong&gt;how this goal will be achieved&lt;/strong&gt;. The Product Owner prioritizes the user stories in the Product Backlog and the Development Team picks the user stories and creates estimates for them.&lt;/p&gt;

&lt;p&gt;The team discusses in more detail &lt;strong&gt;how&lt;/strong&gt; they will deliver the selected product backlog items. This may (but does not have to) include identifying tasks for the product backlog items, whether there are any dependencies between the items, and discussing the technologies or development paradigms that will be utilized.&lt;br&gt;
 &lt;/p&gt;

&lt;br&gt;
 In this series, I will be clarifying all Scrum events and demystifying the most common misconceptions about them.

&lt;p&gt;Please share your thoughts in the comments, and stay tuned for the &lt;br&gt;
 next part of the series!&lt;/p&gt;

</description>
      <category>agile</category>
      <category>scrum</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Scrum Events demystified - The Sprint</title>
      <dc:creator>Paul Isaris</dc:creator>
      <pubDate>Sun, 02 Feb 2020 09:36:49 +0000</pubDate>
      <link>https://dev.to/pavlosisaris/scrum-events-demystified-the-sprint-2j8c</link>
      <guid>https://dev.to/pavlosisaris/scrum-events-demystified-the-sprint-2j8c</guid>
      <description>&lt;p&gt;post photo by &lt;a href="https://www.pexels.com/" rel="noopener noreferrer"&gt;pexels&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post was originally published on my &lt;a href="https://paulisaris.com/scrum-events-demystified---the-sprint/" rel="noopener noreferrer"&gt;personal blog&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;This post is the first part of the "Scrum events demystified" post series.&lt;br&gt;
In this series, I will try to shed some light on the most common events in the Scrum framework.&lt;/p&gt;

&lt;p&gt;First things first, let's begin by defining Scrum:&lt;/p&gt;

&lt;p&gt;According to the &lt;a href="https://www.scrum.org/resources/scrum-guide" rel="noopener noreferrer"&gt;Scrum Guide&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Scrum (n): A framework within which people can address complex adaptive problems, while productively and creatively delivering products of the highest possible value.&lt;br&gt;&lt;br&gt;&lt;br&gt;
  Scrum is a process framework that has been used to manage work on complex products since the early 1990s.&lt;br&gt;&lt;br&gt;Scrum is not a process, technique, or definitive method. Rather, it is a framework within which you can employ various processes and techniques. &lt;br&gt;&lt;br&gt;Scrum makes clear the relative efficacy of your product management and work techniques so that you can continuously improve the product, the team, and the working environment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Indeed, Scrum is successfully used for many years now, from teams that want to carry out risky projects in an Agile way.&lt;br&gt;
 A critical part of the Scrum methodology is the Scrum Events. &lt;/p&gt;

&lt;p&gt;All in all, Scrum (as much as most Agile methodologies) has an &lt;br&gt;
 allergy when it comes to long, pointless meetings that include &lt;br&gt;
 business people and only result in:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Countless hours lost from what could have been productive work&lt;/li&gt;
&lt;li&gt;Developers wondering what they did to deserve one more PowerPoint presentation&lt;/li&gt;
&lt;li&gt;A ton of calories gained from the pastries that are usually served&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Today I will be presenting the heart of Scrum, &lt;br&gt;
the most important of all Scrum events; &lt;strong&gt;&lt;em&gt;The Sprint&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Disclaimer:&lt;/em&gt;&lt;/strong&gt; Some might argue that the Sprint is &lt;strong&gt;, not&lt;br&gt;
 an event itself&lt;/strong&gt; since it merely acts as a &lt;strong&gt;container&lt;/strong&gt; for all other &lt;br&gt;
 Scrum events. This, of course, is true, but it is beneficial to treat it as an event (or a pseudo-event) to get a better grasp of what Scrum is about. &lt;/p&gt;

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

&lt;h1&gt;
  
  
  About the Sprint
&lt;/h1&gt;

&lt;p&gt;The Sprint is a &lt;strong&gt;time-boxed event&lt;/strong&gt; (as all events are in Scrum). &lt;br&gt;
Time-boxed means that it has a &lt;strong&gt;predefined, specific time span&lt;/strong&gt;, &lt;br&gt;
and should start and end exactly when this period dictates. &lt;br&gt;&lt;/p&gt;

&lt;p&gt;For example, the team might agree upon having one-month Sprints. &lt;br&gt;
Other teams might be more comfortable and productive with 2-week Sprints.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;It is generally &lt;strong&gt;up to the whole Scrum Team to decide the time span&lt;/strong&gt;, &lt;br&gt;
given considerations such as the team composition, the risk of the project, &lt;br&gt;
and the team members' availability.&lt;/p&gt;

&lt;p&gt;Once the Sprint starts, the team &lt;strong&gt;focuses&lt;/strong&gt; on the tasks that were selected for work and that will add up to the final &lt;strong&gt;Sprint Increment&lt;/strong&gt;, for the pre-defined &lt;strong&gt;Sprint Goal&lt;/strong&gt; to be completed.&lt;/p&gt;

&lt;p&gt;These tasks (and the Sprint Goal) should have already been defined and agreed upon during &lt;strong&gt;Sprint Planning&lt;/strong&gt; (another Scrum event that will be presented in the next article of the series).&lt;/p&gt;

&lt;p&gt;During the Sprint, the team is supposed to work uninterrupted on the tasks that compose the &lt;strong&gt;Sprint Backlog&lt;/strong&gt;. Any external changes and requests are not welcome, since they are destined to decrease productivity, and should either be discarded or be dealt with by the whole &lt;strong&gt;Scrum Team&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.go2group.com%2Fwp-content%2Fuploads%2F2019%2F09%2FMeme-1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.go2group.com%2Fwp-content%2Fuploads%2F2019%2F09%2FMeme-1.gif" title="Scrum gif" alt="Scrum gif" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Most common questions and misconceptions about Sprints
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;What is the maximum time for a Sprint? Can the team have 2-month Sprints?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The maximum time that a Sprint may last is &lt;em&gt;one month&lt;/em&gt;. Anything more &lt;br&gt;
than that decreases focus and should be broken into multiple Sprints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;What does the team need to start a new Sprint?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a Sprint to start, the team needs 3 things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;A Sprint Goal&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
The Sprint Goal is set during the Sprint planning and should not change during the Sprint. It describes what the output of the Sprint &lt;br&gt;
should be and is agreed upon by the whole team&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;A Sprint Backlog&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
The Sprint Backlog is the collection of tasks that should be done during the Sprint. They are picked from the Development &lt;br&gt;
Team by looking at what the Product Owner has prioritized in the Product Backlog.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;A General plan of how the team should do the work&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
During Sprint Planning, the team decides not only what should &lt;br&gt;
be done during the Sprint, but &lt;strong&gt;&lt;em&gt;how&lt;/em&gt;&lt;/strong&gt; things should be done.&lt;br&gt; &lt;br&gt;
This has to do with the &lt;strong&gt;Definition of Done&lt;/strong&gt; the team has set for &lt;br&gt;
the project and should be flexible enough to tolerate unexpected changes, and evolve with them during the Sprint.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/l4EoRqcypxsvGuRk4/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/l4EoRqcypxsvGuRk4/giphy.gif" title="Team gif" alt="Team gif" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Who is responsible for defining the Sprint Goal for a given Sprint?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Product Owner&lt;/strong&gt; is responsible for maximizing the value of the product &lt;br&gt;
and they manage the Product Backlog as such. &lt;br&gt;&lt;br&gt;
During Sprint Planning the &lt;br&gt;
Product Owner suggests the objective of the upcoming Sprint and proposes &lt;br&gt;
which Product Backlog Items will help achieve this objective.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Can the Sprint Goal change during the Sprint?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No.&lt;/strong&gt; As the Scrum Guide states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No changes are made that would endanger the Sprint Goal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the Sprint Goal becomes obsolete or does not make sense anymore, &lt;br&gt;
then the Sprint should be canceled by the &lt;strong&gt;Product Owner&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Can a Sprint be terminated before the designated date? Who is responsible for terminating it?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yes.&lt;/strong&gt; As I described above, a Sprint can be canceled if ** its goal becomes obsolete*&lt;em&gt;. This may happen when the business goals of the company change, or the market needs dictate so.&lt;br&gt;
The only person able to cancel the Sprint is the **Product Owner&lt;/em&gt;*.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;What if the Development Team finishes all the work that is in the Sprint Backlog?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Sprint Backlog&lt;/strong&gt; (the collection of tasks that the team has agreed &lt;br&gt;
to carry out during the Sprint) is &lt;strong&gt;subject to change&lt;/strong&gt;. &lt;br&gt;
&lt;br&gt;If all the tasks are done ("done" as to meet the &lt;strong&gt;Definition Of Done&lt;/strong&gt;), the Development team can choose new tasks from the Product Backlog and bring them into the Sprint Backlog.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;What if at the end of the Sprint there are unfinished tasks in the Sprint Backlog?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is again very common. A remark that should be made here is that &lt;br&gt;
the Development Team agrees to complete a set of tasks during the Sprint, &lt;br&gt;
but &lt;strong&gt;is in no way obliged to complete them at any cost&lt;/strong&gt;.&lt;br&gt; &lt;/p&gt;

&lt;p&gt;When the time is over, the Sprint is over as well. Any unfinished tasks &lt;br&gt;
do not count as part of the Sprint output and are put back into the Product Backlog. &lt;br&gt;Usually, these tasks will be brought into the Sprint Backlog of the next Sprint, for the Development Team to finally complete them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/Rn1nEzE4BTdC0/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Rn1nEzE4BTdC0/giphy.gif" title="Flexible gif" alt="Flexible gif" width="497" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;What happens between 2 Sprints?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nothing!&lt;/strong&gt; As soon as the first Sprint is over (and by "over" we mean that all of other events contained in this Sprint are done), the new Sprint begins right away.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;What if someone from the Development Team leaves the company during a Sprint?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These changes are not common, but the Development Team and the Sprint should be Agile enough to tolerate such changes. &lt;br&gt; &lt;/p&gt;

&lt;p&gt;Usually, there may be a decrease in productivity for some time, and some tasks might remain unfinished and go back into the Product Backlog when the Sprint ends.&lt;/p&gt;

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

&lt;p&gt;In conclusion, the Sprint is a time-boxed event, during which the Development Team works towards a pre-defined goal that will add value to the product (the &lt;strong&gt;Increment&lt;/strong&gt;), and acts as a container for other &lt;br&gt;
Scrum events.&lt;/p&gt;

&lt;p&gt;In this series, I will be clarifying all Scrum &lt;br&gt;
events and demystifying the most common misconceptions about them.&lt;/p&gt;

&lt;p&gt;Please share your thoughts in the comments, and stay tuned for the &lt;br&gt;
next part of the series!&lt;/p&gt;

</description>
      <category>agile</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Creating a pagination component in Vue JS</title>
      <dc:creator>Paul Isaris</dc:creator>
      <pubDate>Sat, 12 Oct 2019 12:27:00 +0000</pubDate>
      <link>https://dev.to/pavlosisaris/creating-a-pagination-component-in-vue-2793</link>
      <guid>https://dev.to/pavlosisaris/creating-a-pagination-component-in-vue-2793</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;This article was originally published at &lt;a href="https://paulisaris.com/creating-a-pagination-component-in-vue.js/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;post photo by &lt;a href="https://www.pexels.com/" rel="noopener noreferrer"&gt;pexels&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vuejs.org/v2/guide/" rel="noopener noreferrer"&gt;Vue.js&lt;/a&gt; is a progressive JavaScript framework that allows you to create compelling &lt;br&gt;
user interfaces efficiently and easily. &lt;/p&gt;

&lt;p&gt;In this post, we are going to create a pagination component, able to have a dynamic number&lt;br&gt;
of steps!&lt;/p&gt;

&lt;p&gt;Our final application will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frmv7319oe3btfpiyqfse.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frmv7319oe3btfpiyqfse.gif" alt="Example pagination component" width="720" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, you can find the Github repo here:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/PavlosIsaris" rel="noopener noreferrer"&gt;
        PavlosIsaris
      &lt;/a&gt; / &lt;a href="https://github.com/PavlosIsaris/Vue.js-pagination-example" rel="noopener noreferrer"&gt;
        Vue.js-pagination-example
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      This is a simple Vue.js application showcasing a basic pagination component.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h1&gt;
  
  
  Project set up
&lt;/h1&gt;

&lt;p&gt;use the vue cli to create out app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @vue/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Next, we make use of the CLI to create all the boilerplate for our app:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vue create pagination-component-vue-example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In order to verify that the initialization part was successfully completed, &lt;br&gt;
let's go into our project's directory and &lt;code&gt;serve&lt;/code&gt; our app:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;pagination-component-vue-example
npm run serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If everything goes as planned, we will receive no error messages, and will &lt;br&gt;
see the Vue.js default page upon navigating to &lt;a href="http://localhost:8080/" rel="noopener noreferrer"&gt;http://localhost:8080/&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;Vue runs some initialization commands, and our project has been created.&lt;/p&gt;

&lt;p&gt;It's time to design our app!&lt;/p&gt;

&lt;p&gt;We will create a pagination component that will take as parameters&lt;/p&gt;

&lt;p&gt;And we will use the app component in order to test it.&lt;/p&gt;

&lt;p&gt;First thing first, let's get rid of the &lt;code&gt;src/components/HelloWorld.vue&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We are going to create a &lt;code&gt;src/components/PaginationComponent.vue&lt;/code&gt; which will hold &lt;br&gt;
the logic for our pagination component.&lt;/p&gt;

&lt;p&gt;In this tutorial, I will use &lt;a href="https://getbootstrap.com/" rel="noopener noreferrer"&gt;Bootstrap&lt;/a&gt; in order to&lt;br&gt;
style the HTML in a clean way, but feel totally free to skip this step (or use another HTML library).&lt;/p&gt;

&lt;p&gt;Change &lt;code&gt;src/App.vue&lt;/code&gt; to reflect the following:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&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;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;pagination-component&amp;gt;&amp;lt;/pagination-component&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;import&lt;/span&gt; &lt;span class="nx"&gt;PaginationComponent&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;./components/PaginationComponent.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bootstrap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;PaginationComponent&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;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;"~bootstrap/dist/css/bootstrap.min.css"&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;style&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;For the time being, we can leave our &lt;code&gt;src/components/PaginationComponent.vue&lt;/code&gt; empty and dumb:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&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;
   I'm an example component.         
&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="nf"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Component mounted.&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="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;h1&gt;
  
  
  Designing our pagination component
&lt;/h1&gt;

&lt;p&gt;Now, we need to converge on what our pagination component should do, what it's limitations would be,&lt;br&gt;
and how it should be used by our app.&lt;/p&gt;

&lt;p&gt;In my app, I decided that I would like to have a "only backwards free" strategy, meaning that&lt;br&gt;
Once the user is on the n'th step, they should only be able to navigate to previous steps through&lt;br&gt;
the navigation links.&lt;/p&gt;

&lt;p&gt;In order fo the user to move forward, they need to click on the "Next" button.&lt;br&gt;
This may come in handy when you have a paginated form with steps, in which you would like to\&lt;br&gt;
perform some sort of validation before allowing the user to proceed to the next step.&lt;/p&gt;

&lt;p&gt;Having these functional requirements in mind, we can construct a &lt;code&gt;steps&lt;/code&gt; array that will&lt;br&gt;
be passed from the app component own to the pagination component.&lt;/p&gt;

&lt;p&gt;So, let's change our &lt;code&gt;App.vue&lt;/code&gt; to reflect the following:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&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;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;pagination-component&amp;gt;&amp;lt;/pagination-component&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;import&lt;/span&gt; &lt;span class="nx"&gt;PaginationComponent&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;./components/PaginationComponent.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bootstrap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;PaginationComponent&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;steps&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="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Introduction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;allowNext&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="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Second&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;allowNext&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="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Third&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;allowNext&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="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Final&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;allowNext&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="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;We constructed a &lt;code&gt;steps&lt;/code&gt; array, which will define the different "pages" in the pagination component.&lt;br&gt;
The &lt;code&gt;allowNext&lt;/code&gt; property can define whether we would like the user to be able to go to the next step by clicking on&lt;br&gt;
the pagination link.&lt;/p&gt;
&lt;h1&gt;
  
  
  Dynamic number of slots
&lt;/h1&gt;

&lt;p&gt;Next, we would like to hae a way of defining a &lt;b&gt;dynamic&lt;/b&gt; number of slots in the pagination&lt;br&gt;
component, so that we can pass as many steps as we want.&lt;br&gt;
Before that, let's redesign our pagination component to reflect the following:&lt;/p&gt;


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



&lt;p&gt;As we can see here, we use the &lt;code&gt;steps&lt;/code&gt; prop in order to show the pgination header link (as a&lt;br&gt;
bootstrap breadcrumb item), as well as the corresponding Vue &lt;code&gt;slot&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Creating the dynamic slots
&lt;/h1&gt;

&lt;p&gt;Now, its time to tie it all together! &lt;br&gt;
Update &lt;code&gt;App.vue&lt;/code&gt; to reflect the following:&lt;/p&gt;


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


&lt;p&gt;As you can see, we pass a dynamic number of &lt;code&gt;template&lt;/code&gt; components, that will serve as each &lt;br&gt;
of the steps' content. The limitation here is that the number of the templates should be equal to&lt;br&gt;
the number of the steps that we create in the &lt;code&gt;data&lt;/code&gt; section of &lt;code&gt;App.vue&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Example Usage
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frmv7319oe3btfpiyqfse.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frmv7319oe3btfpiyqfse.gif" alt="Example pagination component" width="720" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pretty cool, huh?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>vue</category>
    </item>
    <item>
      <title>How to be awesome at your daily stand-up with 7 steps</title>
      <dc:creator>Paul Isaris</dc:creator>
      <pubDate>Tue, 20 Aug 2019 15:53:23 +0000</pubDate>
      <link>https://dev.to/pavlosisaris/how-to-be-awesome-at-your-daily-stand-up-with-7-steps-gid</link>
      <guid>https://dev.to/pavlosisaris/how-to-be-awesome-at-your-daily-stand-up-with-7-steps-gid</guid>
      <description>&lt;p&gt;This article was originally published at &lt;a href="https://paulisaris.com/how-to-be-awesome-at-your-daily-stand-up-with-7-steps/" rel="noopener noreferrer"&gt;paulisaris.com&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;A daily stand-up meeting is an essential part of many workplaces these days. &lt;/p&gt;

&lt;p&gt;Either when following the Scrum methodology or simply &lt;br&gt;
when wanting to tighten the bonds between the team members and stakeholders,&lt;br&gt;
the performance of the daily stand-up can either make or break your day.&lt;/p&gt;

&lt;p&gt;Let's be honest here. Every workplace does their stand-ups differently.&lt;br&gt;
But that's really OK! It's not another formal, dull meeting that requires you to stick&lt;br&gt;
to the procedure. On the contrary, stand-up meetings are part of the &lt;a href="https://en.wikipedia.org/wiki/Agile_software_development" rel="noopener noreferrer"&gt;Agile&lt;/a&gt;&lt;br&gt;
approach, meaning that the &lt;strong&gt;practices and procedures should be adaptive and flexible.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;A good and compact stand-up meeting is a great way to organize a team and plan your day.&lt;br&gt;
However, sometimes the meeting gets a bad rap. &lt;br&gt;
Some even argue it’s an outdated practice and a waste of time.&lt;/p&gt;

&lt;p&gt;So, I put together the best tips and tricks to help your daily stand-up meeting run &lt;br&gt;
like a &lt;strong&gt;lean, mean, effective machine.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What is a stand-up meeting, to begin with?
&lt;/h1&gt;

&lt;p&gt;According to &lt;a href="https://en.wikipedia.org/wiki/Stand-up_meeting" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A &lt;strong&gt;stand-up meeting&lt;/strong&gt; (or simply "stand-up") is a meeting in which attendees typically participate while standing. The discomfort of standing for long periods is intended to keep the meetings short."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But, why on earth would we want to be uncomfortable when having a meeting?&lt;/p&gt;

&lt;p&gt;Truth be told, &lt;strong&gt;meetings suck&lt;/strong&gt;. And, especially in the Software Development industry, &lt;strong&gt;meetings suck big time&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Endless hours, managers and other business-related people demanding financial and sales goals, powerpoint presentations, and bowls with stale cookies are usually the settings which make us, developers, wanting to jump out of the closest window.&lt;/p&gt;

&lt;p&gt;With the introduction of Agile and Lean development methods, there is a profound need to eliminate these deadly meetings, while keeping all team members informed. And voila, we now have the stand-up meeting, aiming to be extremely compact and productive. No bullshiting, no long introductions, no stale cookies. Just the gist of the day!&lt;/p&gt;

&lt;p&gt;So, let's see a list of rules that will help you perform well in your stand-up, and manage to get the most out of it:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Cut it short
&lt;/h2&gt;

&lt;p&gt;Make sure you respect the stand-up rules, pal. "The discomfort of standing for long periods is intended to keep the meetings short.", so why torture your fellow co-workers? &lt;br&gt;
A key point here is to plan ahead. Note down the high-level tasks you accomplished last day, and try to focus only on the main problem you face today. &lt;br&gt;
This will not only help in keeping the meeting short, but it will also keep your focus on the main impedance, for which you may ask a co-worker for help after the meeting. ;)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Survival Tip:&lt;/strong&gt; Keep notes before the meeting&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. Respect (and don't interrupt) others
&lt;/h2&gt;

&lt;p&gt;I know that you want to help. I know that you are just a good comrade who has something to add to the conversation and has to do it &lt;strong&gt;NOW&lt;/strong&gt;. &lt;br&gt;
But for the love of God, let the speaking person finish. They are trying to squeeze a hard ay's work into 1 minute, so don't make it more difficult for them! &lt;/p&gt;

&lt;p&gt;Also, try not to converse with others while someone is talking. It's just bad manners. The whole meeting is just a few minutes long, I bet you can wait until it's over.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Survival Tip:&lt;/strong&gt; Keep notes during the meeting, so that you can elaborate on what others said, later on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  3. Don't look at your phone (or computer screen)
&lt;/h2&gt;

&lt;p&gt;Keeping meetings sane is all about respect. And you may be disrespectful even without knowing it. Glancing at your phone to check your social, or checking your emails/perform an update on your computer may be tempting tasks to perform while someone is talking, but just imagine how you would feel when, while saying something important, everyone was staring at their screens or scrolling through Instagram...&lt;/p&gt;

&lt;p&gt;Don't worry, an effective stand-up meeting is only several minutes long, so you will have the chance to re-connect with the online world soon enough.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Survival tip:&lt;/strong&gt; put your phone away and turn off your screen as soon as the stand-up meeting kicks off.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  4. Shape your high-level tasks
&lt;/h2&gt;

&lt;p&gt;I know that you struggled with that Database connection for half a day and tried to debug that @&amp;amp;)&amp;amp;@#! outdated npm package version mismatch for the better part of this day.&lt;br&gt;
Honestly, nobody wants to hear about that, &lt;em&gt;not in this level&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Especially when having non-developers participating in the stand-up meeting, it is crucial to shaping your tasks in a way that will be comprehensible by all members.&lt;/p&gt;

&lt;p&gt;Keep in mind that learning how to describe a technical task in a non-technical way is of great importance in general; &lt;br&gt;
It will make you look like a human to non-developers and will boost your soft skills greatly!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Survival tip:&lt;/strong&gt; Write down your tasks and, for each task, come up with a high-level, non-technical title.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  5. Prioritize, prioritize, prioritize
&lt;/h2&gt;

&lt;p&gt;I simply can't stress this enough. Just think about it: You participate in a meeting and you have seconds to describe a full day's work. &lt;br&gt;
Don't make the mistake of beginning with the most recent tasks. I know that it's these tasks that pop into your mind more easily, but you should prioritize first what *&lt;em&gt;would make sense for the other members, as well&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you have a task involving another member, or if you have an update on a task that concerns someone else, please be a lamb and start with that one!&lt;br&gt;
You will catch everyone's attention more easily, and they will able to chip in with their feedback as well (after the meeting has ended).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Survival tip:&lt;/strong&gt; Start with tasks concerning other team members, before losing their attention.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  6. Ask for help
&lt;/h2&gt;

&lt;p&gt;You heard me. Stand-ups are not just about describing a list of tasks you did. On the contrary, they are also about ensuring that you will make it through the day so that you will be able to describe new tasks tomorrow (hehe).&lt;/p&gt;

&lt;p&gt;If you face a problem regarding something and you are passed the point of googling it with no success, you should ask for help. Asking for help is not about being ignorant or lazy. It's about being professional. Your goal is to do your tasks and if some other co-worker can help you with that, then they can help you with your goal.&lt;/p&gt;

&lt;p&gt;So, don't be selfish and ask for help before losing more time trying on your own. This does not mean of course that you should ask for help &lt;strong&gt;every&lt;/strong&gt; time you face a problem. You should be (or become) mature enough to admit when you can't go on on your own but would like some help.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Survival tip:&lt;/strong&gt; Make sure you ask for help on time, by forming the right questions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  7. Proactively offer help
&lt;/h2&gt;

&lt;p&gt;Continuing from the previous item, it's easy to imagine that many people have a hard time when asking for help. Your job is to solve problems, so why making it difficult for them? If you pay attention to what others say during the stand-up, you will find plenty of chances to offer your help.&lt;/p&gt;

&lt;p&gt;Being a technical problem you have faced before or a non-technical task you have already encountered, there are many things which you can help alleviate. Your co-workers will look up to you as a role model, and they will become even better at asking and offering help.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Survival tip:&lt;/strong&gt; Listen carefully to what others say. You will find many chances to offer your help.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;Stand-up meetings should not be another dull chore in the office. &lt;br&gt;
When done correctly, they can prove a beneficial asset to any team and &lt;br&gt;
can even strengthen the bonds between the team members.&lt;/p&gt;

&lt;p&gt;With the right steps, we can make sure to make the most out of them,&lt;br&gt;
by being focused on efficiency and respecting your co-workers.&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>agile</category>
      <category>motivation</category>
    </item>
  </channel>
</rss>
