<?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: Kazuya Matsumoto</title>
    <description>The latest articles on DEV Community by Kazuya Matsumoto (@kazuwombat).</description>
    <link>https://dev.to/kazuwombat</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F45332%2Fe79a72ab-cc53-4949-8a8d-5c780973a198.jpg</url>
      <title>DEV Community: Kazuya Matsumoto</title>
      <link>https://dev.to/kazuwombat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kazuwombat"/>
    <language>en</language>
    <item>
      <title>[VSCode] Launch dev environment automatically</title>
      <dc:creator>Kazuya Matsumoto</dc:creator>
      <pubDate>Sun, 08 May 2022 14:00:44 +0000</pubDate>
      <link>https://dev.to/kazuwombat/vscode-launch-dev-environment-automatically-1ejf</link>
      <guid>https://dev.to/kazuwombat/vscode-launch-dev-environment-automatically-1ejf</guid>
      <description>&lt;h2&gt;
  
  
  [VSCode] Launch dev environment automatically
&lt;/h2&gt;

&lt;p&gt;This is quite sudden, but there are two kinds of developers in the world, keeping the development environment up always and an engineer who drops it every time.&lt;/p&gt;

&lt;p&gt;For developers who drop every time, including me, it is a pain to have to open multiple terminals and type a lot of commands in each one every time.&lt;/p&gt;

&lt;p&gt;So in this article, I’m introducing &lt;strong&gt;how to launch the dev environment automatically when you open a project in VSCode!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you even set up Alfred, which I'll show you as a bonus, you can launch the development environment with a single command, and it will look something like this!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mVXGtC4Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w7ax1r5ox1fepaozagm8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mVXGtC4Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w7ax1r5ox1fepaozagm8.gif" alt="gif" width="600" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s go!&lt;/p&gt;




&lt;h2&gt;
  
  
  Writer’s VSCode and OS version
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;VSCode: 1.66.0&lt;/li&gt;
&lt;li&gt;macOS Monterey&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Hello Custom Task
&lt;/h2&gt;

&lt;p&gt;To automatically execute commands when a project is opened in VSCode, you can use &lt;a href="https://code.visualstudio.com/docs/editor/tasks#_custom-tasks"&gt;Custom tasks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practice makes perfect.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, let's define a task that displays  &lt;code&gt;Hello Custom Task&lt;/code&gt; in your terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Define the task
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Make an empty directory and create a &lt;code&gt;.vscode/tasks.json&lt;/code&gt; in it.
&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/hellovscode-tasks                    
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/hellovscode-tasks/.vscode            
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; ~/hellovscode-tasks/.vscode/tasks.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Open the project(You need to install &lt;a href="https://code.visualstudio.com/docs/setup/mac"&gt;code&lt;/a&gt; command)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code ~/hellovscode-tasks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Define a custom task, edit the &lt;code&gt;.vscode/tasks.json&lt;/code&gt; created in step 1 as follows
&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;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Display&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello Custom Task"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;task。shell&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;process&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;　　　&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;🌟&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;execute&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo Hello Custom Task"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Write&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;over&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;properties&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;executed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;windows&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"windows"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo Hello Custom Task(Windows)"&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="err"&gt;　　　&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Group&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;task&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;belongs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to。test、build、none&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;　　　&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Specify&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;how&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;display&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;execution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;results&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"presentation"&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;"reveal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"panel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"new"&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;"runOptions"&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;🌟&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;When&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;execlutes&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"runOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"folderOpen"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;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;The important part is the part marked with 🌟.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;"command": "echo Hello Custom Task"&lt;/code&gt; : Command to execute&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"runOn": "folderOpen"&lt;/code&gt; : Runs as soon as the project is opened&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see more detail in the schema of &lt;a href="https://code.visualstudio.com/docs/editor/tasks-appendix#_schema-for-tasksjso"&gt;tasks. json&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, &lt;strong&gt;I thought this would run if I reopened the folder, but it does not.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the big pitfall. &lt;br&gt;
&lt;strong&gt;To work &lt;code&gt;"runOn": "folderOpen"&lt;/code&gt;, you need to allow execution by running command manually.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Allow execution of tasks
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Select &lt;code&gt;Cmd+P&lt;/code&gt; &amp;gt; &lt;code&gt;Tasks: Run Task&lt;/code&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3VMDFR_p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oigdo3k6xfg3o9dp63hk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3VMDFR_p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oigdo3k6xfg3o9dp63hk.png" alt="1" width="708" height="504"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the &lt;code&gt;HelloCustomTask&lt;/code&gt; you defined.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3T66YzL5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5z17vc84bbvpzo669539.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3T66YzL5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5z17vc84bbvpzo669539.png" alt="2" width="631" height="83"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then a toast will appear in the lower right corner of the screen asking if you want to allow automatic execution when the folder is opened.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lN2zwOlP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/36uwejhw9ei36nru25te.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lN2zwOlP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/36uwejhw9ei36nru25te.png" alt="3" width="880" height="139"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it, you've defined your task!&lt;/p&gt;

&lt;p&gt;Let’s check it woking by close and reopening the project!&lt;/p&gt;


&lt;h2&gt;
  
  
  Try it out on a real project
&lt;/h2&gt;

&lt;p&gt;Now that you understand the basics of custom tasks, let's try them out on a real project.&lt;/p&gt;

&lt;p&gt;This time, I will use the development environment of &lt;a href="https://site.nitte.app/"&gt;Nitte&lt;/a&gt;, a service scheduling system that I am personally developing, as an example.&lt;/p&gt;

&lt;p&gt;Please replace the command with your own development environment!&lt;/p&gt;
&lt;h3&gt;
  
  
  Define tasks for each command
&lt;/h3&gt;

&lt;p&gt;The following two commands must be executed when launching my development environment.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;yarn run serve: start server&lt;/li&gt;
&lt;li&gt;yarn ngrok: start ngrok&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, I first define tasks to execute these two commands in &lt;code&gt;.vscode/tasks.json.&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;yarn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;serve&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;command&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;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yarn serve"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yarn serve"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"presentation"&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;"reveal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"panel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"new"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;yarn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ngrok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;command&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;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yarn ngrok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yarn ngrok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"presentation"&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;"reveal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"panel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"new"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;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;h3&gt;
  
  
  Combine multiple tasks into one task using dependsOn
&lt;/h3&gt;

&lt;p&gt;Then, define a task that combines the tasks you have created into a single task.&lt;/p&gt;

&lt;p&gt;To combine multiple tasks into one, use the &lt;code&gt;dependsOn&lt;/code&gt; property.&lt;br&gt;
Multiple tasks can be grouped together by describing the labels of the tasks to be grouped as an array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yarn serve"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;　　　&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yarn ngrok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&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="err"&gt;　　　//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;To&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;combine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;multiple&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tasks&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;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Describe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;labels&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tasks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;grouped&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;an&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;array.&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dependsOn"&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="s2"&gt;"yarn serve"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"yarn ngrok"&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;"runOptions"&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;"runOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"folderOpen"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;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;💡 By default, tasks written in "dependsOn" are executed in parallel. &lt;br&gt;
To specify the order of execution, specify "dependsOrder": "sequence".💡 &lt;/p&gt;

&lt;p&gt;Then, as before, allow execution once from &lt;code&gt;Tasks: Run Task.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let’s check it working, It is OK if all defined tasks are executed and the development environment is launched by simply opening the folder.&lt;/p&gt;


&lt;h2&gt;
  
  
  (Bonus) Let's connect with Alfred to make it even easier.
&lt;/h2&gt;

&lt;p&gt;It's already a lot easier, but for me, it is still a hassle to open a terminal and type every time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, we use &lt;a href="https://www.alfredapp.com/workflows/"&gt;Alfred Workflows&lt;/a&gt;  to make it easier.&lt;/p&gt;

&lt;p&gt;⚠️Workflowを使うにはPowerPack(有料)が必要です。⚠️&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Workflows tab in Alfred, select + &amp;gt; Blank Workflow at the bottom right of the screen&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IKkT6CHh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l4pme7u7bnxqctb984lv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IKkT6CHh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l4pme7u7bnxqctb984lv.png" alt="1" width="434" height="1400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Input name and select &lt;code&gt;Create&lt;/code&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xhn8MXfi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pe70rh8j66vrj401pzzr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xhn8MXfi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pe70rh8j66vrj401pzzr.png" alt="2" width="638" height="398"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the Workflow view, right-click &amp;gt; Inputs &amp;gt; Keyword&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B9lGPron--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1gna48etmbpzn8n7rysn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B9lGPron--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1gna48etmbpzn8n7rysn.png" alt="3" width="304" height="300"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enter a keyword to call Workflow. Change to &lt;code&gt;No Argument&lt;/code&gt; and select &lt;code&gt;Save&lt;/code&gt; &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WLRcW-Vm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cy3wqmrdm59d8s5oeo7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WLRcW-Vm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cy3wqmrdm59d8s5oeo7.png" alt="4" width="502" height="283"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the projection coming out of the keyword node &amp;gt; Actions &amp;gt; RunScript&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kcAY1tM7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bn5di7sqn12lkd8payq0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kcAY1tM7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bn5di7sqn12lkd8payq0.png" alt="5" width="588" height="556"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write a script to open the VSCode project and Save.&lt;br&gt;
&lt;/p&gt;&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;# Backend&lt;/span&gt;
/usr/local/bin/code /Users/matsumoto.kazuya/ghq/github.com/WombatTechnology/nitte-backend/functions
&lt;span class="c"&gt;# Frontend&lt;/span&gt;
/usr/local/bin/code /Users/matsumoto.kazuya/ghq/github.com/WombatTechnology/nitte-frontend
&lt;span class="c"&gt;# Open Browser&lt;/span&gt;
/usr/bin/open &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"/Applications/Google Chrome.app"&lt;/span&gt; &lt;span class="s1"&gt;'http://localhost:8080'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡When I ran bash from Alfred, for some reason there is no path, so I ran it with the full path /usr/local/bin/code instead of code💡 &lt;/p&gt;

&lt;p&gt;Now everything is up and running in the development environment with a single command, just like in the video at the beginning!&lt;br&gt;
We did it 🎉&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>automation</category>
      <category>shell</category>
      <category>bash</category>
    </item>
    <item>
      <title>Get hands-on with the Cocoa MVC pattern</title>
      <dc:creator>Kazuya Matsumoto</dc:creator>
      <pubDate>Mon, 29 Jun 2020 09:01:35 +0000</pubDate>
      <link>https://dev.to/kazuwombat/get-hands-on-with-the-cocoa-mvc-pattern-2fg3</link>
      <guid>https://dev.to/kazuwombat/get-hands-on-with-the-cocoa-mvc-pattern-2fg3</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;In this article, I will discuss the Cocoa MVC pattern, which is probably the most commonly used pattern in iOS app implementation.&lt;/p&gt;

&lt;p&gt;Although there are various software architectures such as clean architecture, I think Cocoa MVC pattern is the best for building applications in Swift iOS Storyboard based app, unless you want to use it on a large scale.&lt;/p&gt;

&lt;p&gt;When you read about software architecture in books, you feel understand, but it's often difficult to implement in real applications.&lt;/p&gt;

&lt;p&gt;So, this time, I will try to explain it by implementing a very simple application.&lt;br&gt;
Please take a little time to read it as you move through it with your hands.&lt;/p&gt;
&lt;h1&gt;
  
  
  Get an idea of the Cococa MVC pattern
&lt;/h1&gt;

&lt;p&gt;It's not very efficient to learn Cocoa MVC without knowing anything about it, so you should get a feel for it first.&lt;/p&gt;

&lt;p&gt;We'll review it after implementations, so it's fine if you only have a basic understanding of what it is at this point.&lt;/p&gt;

&lt;p&gt;The MVC pattern stands for Model-View-Controller Pattern, and as the name implies, it divides the code in your application into three roles: Model, View, and Controller.&lt;/p&gt;
&lt;h2&gt;
  
  
  Model
&lt;/h2&gt;

&lt;p&gt;The Model is responsible for maintaining and processing data. For example, connecting with network, calculating something, save data to a local storage...etc.&lt;br&gt;
Everything other than View and Controller is included in Model.&lt;/p&gt;

&lt;p&gt;You should be careful about that Model is different from Model, which represents a table in the SQL database in the framework, in web frame work like Ruby on Rails.&lt;/p&gt;

&lt;p&gt;Also, if the Model changes the data it holds, it will notify the Controller that subscribes to the Model of the change.&lt;/p&gt;
&lt;h2&gt;
  
  
  View
&lt;/h2&gt;

&lt;p&gt;The View is responsible for drawing the screen.&lt;br&gt;
In order to increase reusability, it is important to design View so that it receives input and draws it as it is, without logic as much as possible.&lt;/p&gt;
&lt;h2&gt;
  
  
  Controller
&lt;/h2&gt;

&lt;p&gt;The Controller has references to the Model and View and monitors changes to the Model.&lt;br&gt;
The Controller receives the user's input, requests the Model to process it, and updates the drawing of the View when it detects changes to the Model.&lt;/p&gt;

&lt;p&gt;These can be summarized as follows&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Model&lt;/td&gt;
&lt;td&gt;Processing and holding data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;View&lt;/td&gt;
&lt;td&gt;Drawing View&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Controller&lt;/td&gt;
&lt;td&gt;Accept User input and connect View and Model&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LNEU7F6x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kqn2z8c2iqitndn6plou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LNEU7F6x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kqn2z8c2iqitndn6plou.png" alt="Alt Text" width="880" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A very important point here is that the Controller acts as a bridge between the View and the Model, so that the View and the Model are completely independent of anything else.&lt;br&gt;
By doing so, the View and the Model can be reused in a variety of ways.&lt;br&gt;
On the contrary, Controllers are highly dependent on specific Views and Models, and Cocoa MVC is&lt;br&gt;
&lt;strong&gt;design takes reusability of the View and Model to the extreme, at the expense of reusability of the Controller.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The entire process, from user input to screen drawing, looks like the following&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--13U0Lrlv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ffvv20oosbvqbyrma8e2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--13U0Lrlv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ffvv20oosbvqbyrma8e2.png" alt="Alt Text" width="880" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;[Controller] Accept a user's input.&lt;/li&gt;
&lt;li&gt;[Controller] Request Model to process data.&lt;/li&gt;
&lt;li&gt;[Model] Process data.&lt;/li&gt;
&lt;li&gt;[Model] Notify changes to a subscribing Controller.&lt;/li&gt;
&lt;li&gt;[Controller] Detect changes in the Model.&lt;/li&gt;
&lt;li&gt;[Controller] Request View to draw.&lt;/li&gt;
&lt;li&gt;[View] Draw on the screen.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now that we've gotten the general idea up to this point, let's move on to the next section, where we'll actually start implementing the code!&lt;/p&gt;
&lt;h1&gt;
  
  
  Write Cocoa MVC by yourself
&lt;/h1&gt;

&lt;p&gt;This app is a simple counter application that allows you to increase or decrease numbers with the + and - buttons.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rM3ZkEYa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v0lkmqnwm9mutimb0mqy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rM3ZkEYa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v0lkmqnwm9mutimb0mqy.gif" alt="Alt Text" width="453" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's implement this project using the Cocoa MVC pattern.&lt;br&gt;
You can create a project from scratch, or you can clone it and start with EN/Starter, as I've prepared the initial and final state of the project.&lt;br&gt;
&lt;a href="https://github.com/kazuooooo/CocoaMVCFromScratch"&gt;https://github.com/kazuooooo/CocoaMVCFromScratch&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing the CounterModel.
&lt;/h2&gt;

&lt;p&gt;First, let's start by implementing the MVC M, the Model, the CounterModel.&lt;br&gt;
As mentioned earlier, the role of the Model is to hold and process data.&lt;br&gt;
So required them&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keeps how much the number is now (data retention)&lt;/li&gt;
&lt;li&gt;Increase/decrease the number (data processing)&lt;/li&gt;
&lt;li&gt;Notify the controller monitoring the Model of the change
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Foundation&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;CounterModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;notificationName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;" CounterModelChanged"&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;notificationCenter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NotificationCenter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;// Retain how much the number is now (data retention)&lt;/span&gt;
    &lt;span class="kd"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;didSet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Notify the controller monitoring the Model of the change&lt;/span&gt;
            &lt;span class="n"&gt;notificationCenter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;rawValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CounterModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;notificationName&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;count&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="c1"&gt;// Retain how much the number is now (data retention)&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;countUp&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt; &lt;span class="n"&gt;count&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="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;countDown&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt; &lt;span class="n"&gt;count&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Implementing CounterView.
&lt;/h2&gt;

&lt;p&gt;The next step is to implement CounterView, the V in MVC.&lt;br&gt;
The role of the View is to render.&lt;br&gt;
CountView is responsible for rendering the countLabel through the method render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Foundation&lt;/span&gt;
&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;UIKit&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;CounterView&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIView&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;@IBOutlet&lt;/span&gt; &lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;countLabel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UILabel&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="n"&gt;countLabel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&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;Then create the actual screen in StoryBoard. (If you're using a starter, it will be created in advance.)&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SyfMV0HC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gh12498dyuni5vdx4yni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SyfMV0HC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gh12498dyuni5vdx4yni.png" alt="Alt Text" width="840" height="1802"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't forget the Count Label is connected with an IBOutlet and the CounterView is set to the Custom View.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Qb6Mqhkf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0hnysemw6hsap6f5wvo0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qb6Mqhkf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0hnysemw6hsap6f5wvo0.png" alt="Alt Text" width="880" height="260"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zlUpNmi6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h9qmpmpsetbinqyols96.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zlUpNmi6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h9qmpmpsetbinqyols96.png" alt="Alt Text" width="880" height="317"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing CounterViewController.
&lt;/h2&gt;

&lt;p&gt;Finally, we implement the MVC C, CounterViewController.&lt;/p&gt;

&lt;p&gt;In order to bridge the gap between the View and the Model, &lt;br&gt;
Controller needs&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monitor Model changes&lt;/li&gt;
&lt;li&gt;Accepts user input and asks the Model to process it&lt;/li&gt;
&lt;li&gt;Request the View to draw when the Model is changed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The source is below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;UIKit&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;CounterViewController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIViewController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Keep the View and Model references.&lt;/span&gt;
    &lt;span class="kd"&gt;@IBOutlet&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;counterView&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CounterView&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
    &lt;span class="kd"&gt;private(set)&lt;/span&gt; &lt;span class="kd"&gt;lazy&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;counterModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;CounterModel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;viewDidLoad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;viewDidLoad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c1"&gt;// Monitor changes to the Model&lt;/span&gt;
        &lt;span class="n"&gt;counterModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notificationCenter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addObserver&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;#selector(&lt;/span&gt;&lt;span class="nf"&gt;self.handleCountChange (_:)&lt;/span&gt;&lt;span class="kd"&gt;)&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NSNotification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;rawValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CounterModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notificationName&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt; &lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Detects changes.&lt;/span&gt;
    &lt;span class="kd"&gt;@objc&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;handleCountChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Notification&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="k"&gt;as?&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// requesting the drawing process to the View&lt;/span&gt;
            &lt;span class="n"&gt;counterView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;count&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="c1"&gt;// Accepting input.&lt;/span&gt;
    &lt;span class="kd"&gt;@IBAction&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="kt"&gt;OnPlusButtonTapped&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Any&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Ask the Model to do something.&lt;/span&gt;
        &lt;span class="n"&gt;counterModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;countUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;@IBAction&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="kt"&gt;OnMinusButtonTapped&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;counterModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;countDown&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;Here, too, don't forget to connect button to an IBAction and set up the ViewController class.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z-Hx6hwZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/axcpe3a4bhhtjir70aq0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z-Hx6hwZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/axcpe3a4bhhtjir70aq0.png" alt="Alt Text" width="852" height="184"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cu9bKng8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7bawmmmz1vnld3zv4u79.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cu9bKng8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7bawmmmz1vnld3zv4u79.png" alt="Alt Text" width="880" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, the implementation is complete.&lt;br&gt;
Try a Run and see if the +/- buttons work properly!&lt;/p&gt;
&lt;h1&gt;
  
  
  Review the pattern again
&lt;/h1&gt;

&lt;p&gt;The implementation is complete, but it still doesn't feel like it's just a sutra, and it doesn't feel right somehow, does it?&lt;br&gt;
Finally, let's go over the big picture again, looking at the code.&lt;br&gt;
This will give you a better understanding.&lt;/p&gt;
&lt;h2&gt;
  
  
  Look at dependencies.
&lt;/h2&gt;

&lt;p&gt;First, let's go over the code again, looking at this diagram we saw earlier about dependencies !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LNEU7F6x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kqn2z8c2iqitndn6plou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LNEU7F6x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kqn2z8c2iqitndn6plou.png" alt="Alt Text" width="880" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you look at the code in the Controller, you can see that the CounterViewController has CounterView and CounterModel references and monitor changes of CounterModel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;CounterViewController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIViewController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Has CounterView and CounterModel references&lt;/span&gt;
    &lt;span class="kd"&gt;@IBOutlet&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;counterView&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CounterView&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
    &lt;span class="kd"&gt;private(set)&lt;/span&gt; &lt;span class="kd"&gt;lazy&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;counterModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;CounterModel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;viewDidLoad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;viewDidLoad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c1"&gt;// Monitor model's change&lt;/span&gt;
        &lt;span class="n"&gt;counterModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notificationCenter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;#selector(&lt;/span&gt;&lt;span class="nf"&gt;self.handleCountChange(_:)&lt;/span&gt;&lt;span class="kd"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NSNotification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;rawValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CounterModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notificationName&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, be sure to check the code to see that the View and Model are completely independent of the Controller, which only accepts processing and can be reused.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check process flow
&lt;/h2&gt;

&lt;p&gt;Finally, we will check the whole process flow by looking at the diagram and code, using the + button as an example.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Accept a user’s input.
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b3wjBwos--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fcq6k7lrrc404d8fro0v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b3wjBwos--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fcq6k7lrrc404d8fro0v.png" alt="Alt Text" width="880" height="257"&gt;&lt;/a&gt;&lt;br&gt;
At first, Counter View Controller accepts input via OnPlusButtonTapped method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Accept input&lt;/span&gt;
&lt;span class="kd"&gt;@IBAction&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="kt"&gt;OnPlusButtonTapped&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Request Model to process data
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a6AHPQNE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/77na8ix3h01qmvo240mj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a6AHPQNE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/77na8ix3h01qmvo240mj.png" alt="Alt Text" width="880" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Secondly, the Controller requests Counter Model to count up&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Accept input&lt;/span&gt;
&lt;span class="kd"&gt;@IBAction&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="kt"&gt;OnPlusButtonTapped&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Request model to process&lt;/span&gt;
    &lt;span class="n"&gt;counterModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;countUp&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;h4&gt;
  
  
  3. Process data
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yR5WToYl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/u17gileco9kelbds1izs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yR5WToYl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/u17gileco9kelbds1izs.png" alt="Alt Text" width="880" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thirdly, CounterModel count up the count.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;CounterModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="c1"&gt;// Count up count&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;countUp&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt; &lt;span class="n"&gt;count&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="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Notify changes
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jHUwM1GW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9bfvl9640f1qhd0qhnzg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jHUwM1GW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9bfvl9640f1qhd0qhnzg.png" alt="Alt Text" width="880" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After process data, Model notify changes to subscribers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;CounterModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="kd"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;didSet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Notify changes to subscribers&lt;/span&gt;
            &lt;span class="n"&gt;notificationCenter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;rawValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CounterModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notificationName&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;count&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="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  5. Detect model's change
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v18Zf788--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mpiamfwprwu0676m3cx6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v18Zf788--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mpiamfwprwu0676m3cx6.png" alt="Alt Text" width="880" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Controller detects model's change via the notification observer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;CounterViewController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIViewController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;viewDidLoad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
        &lt;span class="c1"&gt;// Monitor model's change&lt;/span&gt;
        &lt;span class="n"&gt;counterModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notificationCenter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;#selector(&lt;/span&gt;&lt;span class="nf"&gt;self.handleCountChange(_:)&lt;/span&gt;&lt;span class="kd"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NSNotification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;rawValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CounterModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notificationName&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;

    &lt;span class="c1"&gt;// Method fires when model is changed&lt;/span&gt;
    &lt;span class="kd"&gt;@objc&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;handleCountChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Notification&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  6. Request View to render
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R522WAdz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/skityslrg0qvzmil82pd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R522WAdz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/skityslrg0qvzmil82pd.png" alt="Alt Text" width="880" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Controller requests View to render updated count.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;@objc&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;handleCountChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Notification&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="k"&gt;as?&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Request View to render&lt;/span&gt;
        &lt;span class="n"&gt;counterView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;counterModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&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;h4&gt;
  
  
  7. Render View
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0yxt4UCv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7f4ch73artdqvqz0y1rd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0yxt4UCv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7f4ch73artdqvqz0y1rd.png" alt="Alt Text" width="880" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CounterView reflects counter changes to the view.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;CounterView&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIView&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Render view&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="n"&gt;countLabel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&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;
  
  
  At the end
&lt;/h3&gt;

&lt;p&gt;How was that?&lt;br&gt;
Software architecture patterns are hard to understand at first, but once you understand them, they are a very powerful weapon for engineers.&lt;br&gt;
If you don't fully understand something, I recommend you to try to understand it by writing example by yourself.&lt;/p&gt;

</description>
      <category>swift</category>
      <category>ios</category>
      <category>mvc</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Never seeking downloads folder with apple script</title>
      <dc:creator>Kazuya Matsumoto</dc:creator>
      <pubDate>Sat, 25 Apr 2020 06:29:38 +0000</pubDate>
      <link>https://dev.to/kazuwombat/never-seeking-downloads-folder-with-apple-script-33fh</link>
      <guid>https://dev.to/kazuwombat/never-seeking-downloads-folder-with-apple-script-33fh</guid>
      <description>&lt;p&gt;How many times do you download something ever?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download any new software&lt;/li&gt;
&lt;li&gt;Download photos and icons&lt;/li&gt;
&lt;li&gt;Download the file sent to you by email&lt;/li&gt;
&lt;li&gt;...etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And what is the one thing you must do after you download it?&lt;br&gt;
That's right.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Open the download folder! *&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'm sure I'll do it, I'd love to meet someone who doesn't open the download folder after downloading it 😜&lt;/p&gt;

&lt;p&gt;I think most people do this, don't they?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;cmd + space to find finder&lt;/li&gt;
&lt;li&gt;select the download folder&lt;/li&gt;
&lt;li&gt;move or open files&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is such a hassle and a waste of time, isn't it?&lt;br&gt;
This time, I'll show you how to automate the process of opening this download folder using apple script!&lt;/p&gt;
&lt;h2&gt;
  
  
  How to do it
&lt;/h2&gt;

&lt;p&gt;This time, we'll use a feature called &lt;a href="%5BMac%20Automation%20Scripting%20Guide:%20Watching%20Folders%5D(https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html)"&gt;WatchingFolders&lt;/a&gt; in apple script.&lt;/p&gt;

&lt;p&gt;About apple script itself, you can see &lt;a href="http://tonbi.jp/AppleScript/Introduction/01/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First of all, you need to create an apple script by using the script editor, which is the editor of apple script.
Just 5 lines of script will save your time.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight applescript"&gt;&lt;code&gt;&lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="nv"&gt;adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;folder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;items&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;theAttachedFolder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;after&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;receiving&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;theNewItems&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;tell&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;application&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Finder"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;theAttachedFolder&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;tell&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;folder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;items&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Something like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MVtNKmZj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71154/688720a9-18ae-e3a7-c382-774a4ff64211.png" class="article-body-image-wrapper"&gt;&lt;img alt="open_directory_on_add_item_ and _Never_seeking_for_download_folder.png" src="https://res.cloudinary.com/practicaldev/image/fetch/s--MVtNKmZj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71154/688720a9-18ae-e3a7-c382-774a4ff64211.png" width="700" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To explain a little since this is a technical article, when a file is added to a folder, the event handler is called and the object of the folder is put into theAttachedFolder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight applescript"&gt;&lt;code&gt;&lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="nv"&gt;adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;folder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;items&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;theAttachedFolder&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to open that folder in the Finder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight applescript"&gt;&lt;code&gt;&lt;span class="k"&gt;tell&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;application&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Finder"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;theAttachedFolder&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;tell&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Once the script is created, save it. At this time, it is important to note that you need to save it to one of the folders of&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;/Library/Scripts/Folder Action Scripts/ ## Available to any user&lt;/li&gt;
&lt;li&gt;~/Library/Scripts/Folder Action Scripts/ ## Current user only&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The name can be anything, but this time I chose open_directory_on_add_item.&lt;br&gt;
(If you don't have Folder Action Scripts, you can create your own one with the same name.)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Apply the script to the Download folder after saving it.

&lt;ol&gt;
&lt;li&gt;Control-click the folder in Finder.&lt;/li&gt;
&lt;li&gt;Choose Folder Actions Setup from the contextual menu.&lt;/li&gt;
&lt;li&gt;Choose a script to connect to the folder and click Attach.
&lt;img alt="Folder action settings_and_search.png" src="https://res.cloudinary.com/practicaldev/image/fetch/s--1uIByLtj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71154/3552ebfc-7f29-5baf-3137-dacf9b64001d.png" width="507" height="420"&gt;
&lt;/li&gt;
&lt;/ol&gt;


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

&lt;p&gt;Also make sure that Use Folder Actions is checked.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DMnCEIKJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71154/2d934cfd-2edf-a434-2a18-e4efbb6e43df.png" class="article-body-image-wrapper"&gt;&lt;img alt="Folder Action Settings_and_Never_seeking_for_download_folder.png" src="https://res.cloudinary.com/practicaldev/image/fetch/s--DMnCEIKJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71154/2d934cfd-2edf-a434-2a18-e4efbb6e43df.png" width="488" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We're ready to go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Operation check
&lt;/h2&gt;

&lt;p&gt;Finally, let's make sure it works!&lt;br&gt;
I'm going to try to download some kind of icon, whatever it is.&lt;br&gt;
&lt;a href="https://www.flaticon.com/free-icon/wombat_427526?term=wombat&amp;amp;page=1&amp;amp;position=5"&gt;Wombat - Free animals icons&lt;/a&gt;&lt;br&gt;
The download folder should open automatically when it completes!&lt;/p&gt;

&lt;p&gt;Now you're free from the pain of looking for the download folder! You have to try it!&lt;/p&gt;

</description>
      <category>macos</category>
      <category>applescript</category>
      <category>productivity</category>
    </item>
    <item>
      <title>List all only files under directory with shell script</title>
      <dc:creator>Kazuya Matsumoto</dc:creator>
      <pubDate>Thu, 05 Mar 2020 10:04:38 +0000</pubDate>
      <link>https://dev.to/kazuwombat/put-all-only-files-under-directory-3fk4</link>
      <guid>https://dev.to/kazuwombat/put-all-only-files-under-directory-3fk4</guid>
      <description>&lt;p&gt;Thanks to @BenSincla, this article become very simple!&lt;/p&gt;

&lt;p&gt;For example, you have directory like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree A
A
├── B
│   └── b.txt
├── C
│   └── c.txt
└── a.txt

2 directories, 3 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Relative path
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find ./A &lt;span class="nt"&gt;-type&lt;/span&gt; f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Absolute path
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find ./A &lt;span class="nt"&gt;-type&lt;/span&gt; f | &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;file&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"s|^.|&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;|g"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>shell</category>
      <category>bash</category>
      <category>linux</category>
    </item>
    <item>
      <title>Let's make your cardfolio site 💳💨</title>
      <dc:creator>Kazuya Matsumoto</dc:creator>
      <pubDate>Fri, 27 Dec 2019 12:59:20 +0000</pubDate>
      <link>https://dev.to/kazuwombat/let-s-make-your-cardfolio-site-193l</link>
      <guid>https://dev.to/kazuwombat/let-s-make-your-cardfolio-site-193l</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fsr6krbxv8c1l54ggjsk0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fsr6krbxv8c1l54ggjsk0.png" alt="logo.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Cardfolio! ?
&lt;/h1&gt;

&lt;p&gt;Cardfolio! is a Gatsby-based cardfolio site framework.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Wait, what is cardfolio?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;See below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AxQr3p-ca88kRWFm5bJqqBw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AxQr3p-ca88kRWFm5bJqqBw.gif" alt="gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's right! It is a portfolio site just like business card.It has the paper texture and rotation as if a real business card. &lt;/p&gt;

&lt;p&gt;Cardfolio site's true worth is definitely seen when you hand over your business card to someone. Below is my business card, imagine you receive this card.(If you browse this site by mobile, you can access from &lt;a href="https://matsumotokazuya.io/en?fromQR=1" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F0%2Av9CdPfi-PjjJ9Uil" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F0%2Av9CdPfi-PjjJ9Uil" alt="card.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How was that? You can make a great impression to receiver like you just felt 😄&lt;/p&gt;

&lt;p&gt;And this time, I released on Github as OSS so that anyone can create a your own card folio site 😙 I also designed the logo 🖌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kazuooooo/Cardfolio" rel="noopener noreferrer"&gt;Cardfolio!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have used react before, you can easily create it! Also, you can customize your design and paper texture.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to rotate of business card?
&lt;/h1&gt;

&lt;p&gt;You might think&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How this rotation implemented?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let me explain about this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Both side page
&lt;/h2&gt;

&lt;p&gt;To create both side of card, implement these steps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create front and back components respectively and pile up them under container (card) with position: absolute.&lt;/li&gt;
&lt;li&gt;Rotate y axis of the backside component 180 degrees by transform rotateY.&lt;/li&gt;
&lt;li&gt;To switch between frontside and backside, rotate container.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F0%2AhK5no_ExFidTl2wQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F0%2AhK5no_ExFidTl2wQ.png" alt="rotate.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But, there is a pitfall. When it is turned over, mirror inverted frontside component is displayed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F0%2A_hVDCDwB3lmDFclh" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F0%2A_hVDCDwB3lmDFclh" alt="pitfall.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is because if you turn over the DOM with transform3d, the back side of the object will be displayed by default. To solve this, it is necessary to change the default behavior by set backface-visibility to a hidden.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.frontSide&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;backface-visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.backSide&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;backface-visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&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;This way, if you flip it over, the frontside displays nothing, and as a result the back side will be displayed on the screen as the top. Sample code &lt;a href="https://codesandbox.io/s/awesome-poitras-dnk0s" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Rotate according to user operation
&lt;/h2&gt;

&lt;p&gt;Now rotate the card as the user drags. First of all, to detect a drag, you can easily get it using the hook called useDrag in react-use-gesture&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSpring&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-spring&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bind&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDrag&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;down&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;movement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;moveX&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="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;When the drag is detected, the current x coordinate is converted to the y axis angle and the card is rotated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="c1"&gt;// convert Xposition to degree&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;degree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lastDegree&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;moveXToDegree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;moveX&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="err"&gt;　&lt;/span&gt; &lt;span class="c1"&gt;// in draggin&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;down&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// rotate as user dragging&lt;/span&gt;
    &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`rotateY(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;degree&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;deg)`&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;degree&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;Furthermore, when user release his/her finger, need back to a front or back to horizontally with an animation(&lt;a href="https://www.react-spring.io/" rel="noopener noreferrer"&gt;ReactSpring&lt;/a&gt; used). The decision logic is as shown in the following figure&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In first quadrant or third quadrant, decrease the angle.&lt;/li&gt;
&lt;li&gt;In the second and fourth quadrants, increase the angle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F0%2A4chHejrgi7StHkRC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F0%2A4chHejrgi7StHkRC.png" alt="ro"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;last&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// judge back or front and set degree&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;horizontalDegree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calcHorizontalDegreeToReturn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;degree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;setDegree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;horizontalDegree&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;Please see &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fgithub.com%2Fkazuooooo%2FCardfolio%2Fblob%2Fmaster%2Fsrc%2Fhelpers%2FuseCardRotation.ts" rel="noopener noreferrer"&gt;Source Code&lt;/a&gt; for details.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;How was that? Gatsby is a great framework to build a website on a regular basis, moreover it's a good idea to build an OSS based on Gatsby because you can develop while taking advantage of the various benefits of Gatsby 🎁&lt;br&gt;
I hope that one of the readers of this article make their own card folio site using Cardfolio! !&lt;/p&gt;

</description>
      <category>gatsby</category>
      <category>webdev</category>
      <category>react</category>
      <category>career</category>
    </item>
    <item>
      <title>What is Linux test command?</title>
      <dc:creator>Kazuya Matsumoto</dc:creator>
      <pubDate>Wed, 26 Sep 2018 17:49:23 +0000</pubDate>
      <link>https://dev.to/kazuooooo/what-is-linux-test-command-21i5</link>
      <guid>https://dev.to/kazuooooo/what-is-linux-test-command-21i5</guid>
      <description>&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;p&gt;In a word, it is a command to judge conditions.&lt;br&gt;
It can be written as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;test &lt;/span&gt;condition
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the condition part, write the condition you want to judge and result returns below.&lt;/p&gt;

&lt;p&gt;In case of true: 0&lt;br&gt;
In case of false: 1&lt;/p&gt;

&lt;p&gt;(It is opposite judgment of general programming language, because of the practice of returning 0 if the  UNIX program is normally terminated and 1 if it is abnormally terminated)&lt;/p&gt;

&lt;p&gt;Whether a file with a specific file name exists as an example is as follows.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;`shell&lt;br&gt;
test -e exist.text; echo $ status # =&amp;gt; 0&lt;br&gt;
test -e not_exist.text; echo $ status # =&amp;gt; 1&lt;br&gt;
&lt;/code&gt; `&lt;/p&gt;

&lt;h1&gt;
  
  
  Format using []
&lt;/h1&gt;

&lt;p&gt;Apart from the above writing method, the test sentence can be written as follows.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
[ conditions ]&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;With this notation the previous example will be as follows&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;shell&lt;br&gt;
[ -e exist.text ]; echo $ status # =&amp;gt; 0&lt;br&gt;
[ -e not_exist.text ]; echo $ status # =&amp;gt; 1&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;
At this time, it is necessary to empty one space in [] as a caveat.&lt;/p&gt;

&lt;h1&gt;
  
  
  Use with if
&lt;/h1&gt;

&lt;p&gt;In the previous example, we output the result as echo $status, but in reality it is often used with if.&lt;br&gt;
Try writing FizzBuzz with if and test command.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;shell&lt;br&gt;
for i in&lt;/code&gt;seq 1 15&lt;code&gt;&lt;br&gt;
do&lt;br&gt;
if [$ (($ i% 3)) - eq 0] &amp;amp;&amp;amp; [$ (($ i% 5)) - eq 0]; then&lt;br&gt;
  echo 'FizzBuzz'&lt;br&gt;
elif [$ (($ i% 3)) - eq 0]; then&lt;br&gt;
  echo 'Fizz'&lt;br&gt;
elif [$ (($ i% 5)) - eq 0]; then&lt;br&gt;
  echo 'Buzz'&lt;br&gt;
else&lt;br&gt;
  echo $ i&lt;br&gt;
fi&lt;br&gt;
done&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Various condition judgment
&lt;/h1&gt;

&lt;p&gt;The options available with the test command are as follows.&lt;/p&gt;

&lt;h2&gt;
  
  
  File processing
&lt;/h2&gt;

&lt;p&gt;| Condition | Determination |&lt;br&gt;
|: ----------- | ------------: |&lt;br&gt;
| -d file | True if file is a directory |&lt;br&gt;
| -e file | True if file exists |&lt;br&gt;
| -f file | True if file is a regular file (not a directory, etc.)&lt;br&gt;
| -L file | True if file is a symbolic link |&lt;br&gt;
| -r file | True if file is readable |&lt;br&gt;
| -s file | True if size of file is not 0 |&lt;br&gt;
| -w file | True if file is writable |&lt;br&gt;
| -x file | True if file is executable |&lt;/p&gt;

&lt;h2&gt;
  
  
  String processing
&lt;/h2&gt;

&lt;p&gt;| Condition | Determination |&lt;br&gt;
|: ----------- | ------------: |&lt;br&gt;
| -z str | True if the length of str is 0 |&lt;br&gt;
| -n str | True if the length of str is greater than 0 |&lt;br&gt;
| str1 == str2 | True if the strings are equal |&lt;br&gt;
| str1 != str2 | True if the strings are not equal |&lt;/p&gt;

&lt;h2&gt;
  
  
  Numerical processing
&lt;/h2&gt;

&lt;p&gt;| Condition | Determination |&lt;br&gt;
|: ----------- | ------------: |&lt;br&gt;
| int1 -eq int2 | True if int1 and int2 are equal |&lt;br&gt;
| int1 -ne int 2 | True if int1 and int2 are not equal |&lt;br&gt;
| int1 -lt int2 | True if int1 is smaller than int2|&lt;br&gt;
| int1 -le int2 | True if int1 is smaller than equal to int2 |&lt;br&gt;
| int 1 -gt int 2 | True if int 1 is greater than int2 |&lt;br&gt;
| int 1 -ge int 2 | True if int 1 is greater than equal to int2 |&lt;/p&gt;

&lt;h2&gt;
  
  
  logical condition
&lt;/h2&gt;

&lt;p&gt;| Condition | Determination |&lt;br&gt;
|: ----------- | ------------: |&lt;br&gt;
|! Condition | True if condition is false |&lt;br&gt;
| Condition1 -a Condition2 | True if both Condition1 and Condition2 are true |&lt;br&gt;
| Condition1 -o Condition2 | True if either condition1 or condition2 is true |&lt;/p&gt;

&lt;h1&gt;
  
  
  Condition determination using &amp;amp;&amp;amp; and ||
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;shell&lt;br&gt;
command1 &amp;amp;&amp;amp; command2 # When command1 is executed correctly, execute command2&lt;br&gt;
command1 || command2 # When an error occurs with command1, execute command2&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Sometimes you can write an if statement more concisely using the notation&lt;/p&gt;

&lt;p&gt;For example&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;shell&lt;br&gt;
if cat $ 1; then&lt;br&gt;
  echo OK&lt;br&gt;
fi&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;↓&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;sh&lt;br&gt;
cat $ 1 &amp;amp;&amp;amp; echo OK&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;sh&lt;br&gt;
if! [$ ((1% 3)) - eq 0]; then&lt;br&gt;
  echo NG&lt;br&gt;
fi&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;↓&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;sh&lt;br&gt;
[$ ((1% 3)) - eq 0] || echo NG&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can write like this.&lt;/p&gt;

&lt;p&gt;Casually until now&lt;br&gt;
if [hogehoge]&lt;br&gt;
Although I wrote it, I used the test command before I knew it.&lt;br&gt;
It is a useful command which is indispensable when writing a complicated shell.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>shell</category>
      <category>linuxcommand</category>
    </item>
  </channel>
</rss>
