<?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: David</title>
    <description>The latest articles on DEV Community by David (@davidkwan95).</description>
    <link>https://dev.to/davidkwan95</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%2F267851%2F65e23286-290a-4c6d-845b-f25599bf1dec.jpeg</url>
      <title>DEV Community: David</title>
      <link>https://dev.to/davidkwan95</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidkwan95"/>
    <language>en</language>
    <item>
      <title>How I Speed up My Django Test Suite by 200%</title>
      <dc:creator>David</dc:creator>
      <pubDate>Sat, 14 Dec 2019 17:04:34 +0000</pubDate>
      <link>https://dev.to/davidkwan95/how-i-speed-up-my-django-test-suite-by-200-214g</link>
      <guid>https://dev.to/davidkwan95/how-i-speed-up-my-django-test-suite-by-200-214g</guid>
      <description>&lt;p&gt;tl;dr: Add &lt;code&gt;--parallel&lt;/code&gt; at the end of the test command&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Earlier this week I was deploying a new feature on a legacy codebase. The whole test took 60 minutes before it was done. If this was going to be a one-time deployment, I was gonna let it slide off. I will have to work with this codebase for a little bit longer however, so I need to find a quick way to speed up the test suite.&lt;/p&gt;

&lt;p&gt;I then looked for how to make Django test run in parallel and found it really quickly. It's achieved just by adding &lt;code&gt;--parallel&lt;/code&gt; option in the test command, e.g. &lt;code&gt;python manage.py test --parallel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So problem solved right? The test ended in 5 minutes. Unfortunately, it ended in 5 minutes because the test failed. After some time figuring out why it failed, I realized that the failing tests were using Redis Queue (django-rq). Apparently running the &lt;code&gt;--parallel&lt;/code&gt; command didn't isolate it.&lt;/p&gt;

&lt;p&gt;I googled how to isolate the django-rq when running the test in parallel, but unfortunately, I wasn't able to find the solution. I then had 2 choices: abandon my plan on speeding the test suite, or writing a custom test runner. I chose the latter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing a custom Django Test Runner to isolate Redis Queue
&lt;/h2&gt;

&lt;p&gt;Before writing the test, I read up on how Django isolate the test database. I knew I would either extend or copied most of the logic from that. After digging around, I found the code where the database isolation happens.&lt;/p&gt;

&lt;p&gt;Now let's write the custom test runner. Please note that I am using django-rq library. The way to set the Redis connection might be different. Still, the idea to isolate it remains the same. We will achieve isolation by assigning a unique database index to the Redis configuration for each worker.&lt;/p&gt;

&lt;p&gt;Firstly, we need to supply a different function to &lt;code&gt;init_worker&lt;/code&gt; in Django's &lt;code&gt;ParallelTestSuite&lt;/code&gt;. To achieve that, we will write our custom test suite called &lt;code&gt;CustomParallelTestSuite&lt;/code&gt; that extends &lt;code&gt;ParallelTestSuite&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test.runner&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;_init_worker&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test.runner&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ParallelTestSuite&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;redis_parallel_init_worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;_init_worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomParallelTestSuite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParallelTestSuite&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;init_worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis_parallel_init_worker&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We still need to isolate the database however, that's why we will still call the &lt;code&gt;_init_worker&lt;/code&gt; function inside our function.&lt;/p&gt;

&lt;p&gt;Now we also need to modify the default base runner to use our &lt;code&gt;CustomParallelTestSuite&lt;/code&gt; as well. We will do this by extending the &lt;code&gt;DiscoverRunner&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test.runner&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DiscoverRunner&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomDiscoverRunner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DiscoverRunner&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;parallel_test_suite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CustomParallelTestSuite&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sweet! All we've done up till now is only creating new classes, but the behavior of the test runner remains the same. Now it's time to modify the &lt;code&gt;redis_parallel_init_worker&lt;/code&gt; to add the functionality of isolating the Redis. I copied most of the worker counter from &lt;code&gt;_init_worker&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.conf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test.runner&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;_init_worker&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test.runner&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DiscoverRunner&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test.runner&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ParallelTestSuite&lt;/span&gt;

&lt;span class="n"&gt;_worker_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;redis_parallel_init_worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django_rq.settings&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QUEUES&lt;/span&gt;
    &lt;span class="n"&gt;_init_worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="s"&gt;"""
    Switch redis databases dedicated to this worker.
    This helper lives at module-level because of the multiprocessing module's
    requirements.
    """&lt;/span&gt;

    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;_worker_id&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_lock&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;_worker_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="n"&gt;settings_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'RQ_QUEUES'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;QUEUES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;settings_dict&lt;/span&gt;
    &lt;span class="n"&gt;QUEUES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'default'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s"&gt;'DB'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_worker_id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, we've assigned a unique Redis database index based on their &lt;code&gt;_worker_id&lt;/code&gt;, and Redis isolation is achieved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full code
&lt;/h2&gt;

&lt;p&gt;Here's the full code for the custom test runner we just wrote.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# myapp/test/runner.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.conf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test.runner&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;_init_worker&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test.runner&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DiscoverRunner&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test.runner&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ParallelTestSuite&lt;/span&gt;

&lt;span class="n"&gt;_worker_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;redis_parallel_init_worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django_rq.settings&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QUEUES&lt;/span&gt;
    &lt;span class="n"&gt;_init_worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="s"&gt;"""
    Switch redis databases dedicated to this worker.
    This helper lives at module-level because of the multiprocessing module's
    requirements.
    """&lt;/span&gt;

    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;_worker_id&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_lock&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;_worker_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="n"&gt;settings_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'RQ_QUEUES'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;QUEUES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;settings_dict&lt;/span&gt;
    &lt;span class="n"&gt;QUEUES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'default'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s"&gt;'DB'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_worker_id&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomParallelTestSuite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParallelTestSuite&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;init_worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis_parallel_init_worker&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomDiscoverRunner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DiscoverRunner&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;parallel_test_suite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CustomParallelTestSuite&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding to settings to refer to use the custom test suite
&lt;/h2&gt;

&lt;p&gt;Now the last thing we need to do is to change our settings to use the test runner we've just created. To do this add &lt;code&gt;TEST_RUNNER = 'path.to.custom_runner.CustomRunnerClass'&lt;/code&gt; in &lt;code&gt;settings.py&lt;/code&gt;, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# settings.py
&lt;/span&gt;&lt;span class="n"&gt;TEST_RUNNER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'myapp.test.runner.CustomDiscoverRunner'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Now, calling the command with &lt;code&gt;--parallel&lt;/code&gt; runs the test correctly as intended. The test eventually ended in about 17 minutes, a speedup of around 3 times! Some of the tests can still be optimized if I wanted to increase the speed further, but I'm satisfied with this result for now.&lt;/p&gt;

&lt;p&gt;Thanks for reading, I hope this post gives you a basic idea on how to write your own custom test runner if you encountered a similar problem. See you next time.&lt;/p&gt;

</description>
      <category>django</category>
      <category>testing</category>
      <category>optimization</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Why Learning Programming is Hard and Tips for Learning it Better</title>
      <dc:creator>David</dc:creator>
      <pubDate>Sat, 23 Nov 2019 16:16:13 +0000</pubDate>
      <link>https://dev.to/davidkwan95/why-learning-programming-is-hard-5fd6</link>
      <guid>https://dev.to/davidkwan95/why-learning-programming-is-hard-5fd6</guid>
      <description>&lt;p&gt;Have you ever encountered any difficulties when you first started programming? Some people are going to say learning programming is not hard. I can think of a few reasons why they say programming is easy. Maybe they are geniuses, who have a strong analytical background. Perhaps they just forgot the hardships they had when they started. The last reason I can think of is, they simply haven’t reached that point (or pointers in C) yet.&lt;/p&gt;

&lt;p&gt;A lot of people are going to have difficulties when they started programming, or even after they have learned it for a while, so don’t be discouraged if you just started and find it difficult.&lt;/p&gt;

&lt;p&gt;Maybe you know someone who can program a complex system easily. Most likely it looks easy because they spent a lot of time mastering it. They might also have encountered similar problems in the past. You can after all say, programming is about making a complex problem into smaller problems that can be solved easily by itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Programming learning curve
&lt;/h2&gt;

&lt;p&gt;I believe the learning curve of programming is not linear. Once you reach a certain level, you will hit a wall. You will feel like you are unable to get better, not knowing how to improve. This will keep happening until you learn (or unlearn in some cases) a skill/knowledge. If you are familiar with games that have ranking/rating systems, you sometimes will feel like getting stuck in certain ranks despite you keep playing it. The only way to get past that is to figure out what you are missing and work on that to reach the next level. Once you’ve worked on that, you will feel like you are making a lot of progress, until you hit the next walls.&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%2Fi.imgur.com%2F2lMHq7e.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%2Fi.imgur.com%2F2lMHq7e.png" alt="Programming learning curve"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Phases of learning programming
&lt;/h2&gt;

&lt;p&gt;This is just an example of learning phases based on my own experience and observations. This might differ from how you learn. I try to identify problems that are frequently blocking people’s learning progresses and try to come up with a solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  First phase
&lt;/h3&gt;

&lt;p&gt;This phase is where people get familiar with programming languages syntaxes and concepts: variables, if/else, for loop, functions. Once they learn this, there’s a first wall they have to overcome. How do you combine these concepts to create a running program?&lt;/p&gt;

&lt;p&gt;For those who have a mentor guiding them, they should be able to get passed through this quickly. For those who don’t have one, I suggest following tutorials on how to create an app and learn from the patterns on how to build one.&lt;/p&gt;

&lt;p&gt;People who can’t pass this probably won’t stay for long and usually gives up on programming.&lt;/p&gt;

&lt;h3&gt;
  
  
  Second phase
&lt;/h3&gt;

&lt;p&gt;Those who make it to this phase should be able to create an application by now. The next wall to overcome is the difficulty to create a larger-scale application. Things get harder to maintain, changing one part of the app is causing bugs on another. This is another wall programmers have to overcome before they can advance. The solution to this is to learn how to write clean code, having knowledge about design patterns and principles. I recommend reading these or lookup for a summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship-ebook/dp/B001GSTOAM" rel="noopener noreferrer"&gt;Clean Code by Robert C. Martin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Head-First-Design-Patterns-Brain-Friendly/dp/0596007124" rel="noopener noreferrer"&gt;Head First Design Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kamranahmedse/design-patterns-for-humans" rel="noopener noreferrer"&gt;Design pattern for humans&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Third phase
&lt;/h3&gt;

&lt;p&gt;This phase happens when people start to work as a team. This is skippable because some people work alone and have never worked as a team. I suggest trying to work in a team at least once. It’s going to teach you some skills that you will never learn otherwise. You don’t have to be working in a company, you can just try and work on a project with a small number of people.&lt;/p&gt;

&lt;p&gt;There might be another obstacle here for people to overcome, or probably not depending on the individuals. Some people might find it hard to work with other people. Some problems that might occur are communication problems, unable to read others’ code, etc.&lt;/p&gt;

&lt;p&gt;I can’t really give any good advice, but here’s my thought. For communication, try and sit down with your teammates and keep evaluating how you work as a team. What works for a team doesn’t guarantee it’s going to work in another. For reading code, try to simulate the code on a piece of paper. Reading the test specs might help to explain what the code is trying to achieve, so you should start from there.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fourth phase
&lt;/h3&gt;

&lt;p&gt;Programmers at this phase should now know a few design patterns or principles, and how to write a clean code. Often times, I see programmers fall into the trap of trying to apply a design pattern they’ve learned to every problem. Sometimes using a design pattern is just adding complexity to the code. Your app is probably not needing that much flexibility yet (check out &lt;a href="https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it" rel="noopener noreferrer"&gt;YAGNI&lt;/a&gt; principle).&lt;/p&gt;

&lt;p&gt;So I’ve come to the conclusion that the biggest wall for this phase is not being able to understand trade-offs. These programmers tend to try and adhere to all of the principles/patterns they’ve learned. I personally think they are just a guide to help, and it’s all about trade-offs. Implementing a principle will be good in one situation, but it might be bad in another. That’s the difficulty of trying to level up in this phase, knowing when to pick a solution over another.&lt;/p&gt;

&lt;p&gt;One way to sharpen your skills in making these kinds of decisions is, try to learn about anti-patterns before going on with patterns. Anti-patterns will give you a general idea of what not to do. Just keep yourself reminded that at the end of the day, you shouldn’t be adhering to all anti-patterns all the time. Remember, it’s about trade-offs. It might actually be good in certain situations!&lt;/p&gt;

&lt;p&gt;There are probably a lot more phases after this, but I haven’t observed a lot to write about it. If you have any stories, please share it in the comments!&lt;/p&gt;

&lt;h2&gt;
  
  
  Make learning programming easier
&lt;/h2&gt;

&lt;p&gt;So why do I think learning programming is hard? Most of the time it’s because people don’t know what to learn. What to learn largely depends on your goal and how experienced you are. I don’t believe just trying to code for 10,000 hours is gonna help. Instead, try to learn efficiently. Here are a few tips to make you learn more efficiently:&lt;/p&gt;

&lt;h3&gt;
  
  
  Have a goal in mind
&lt;/h3&gt;

&lt;p&gt;Don’t just learn randomly. Build a roadmap for learning. For example, if you want to be a web developer, first find out what people usually learn to achieve that. You can check out the roadmap for being a web developer in this article: &lt;a href="https://www.freecodecamp.org/news/2019-web-developer-roadmap/" rel="noopener noreferrer"&gt;The 2019 Web Developer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have other roadmaps of learning, please share it in the comments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Read other people’s code
&lt;/h3&gt;

&lt;p&gt;Do you remember when I said programming is about making a complex problem into smaller problems? Doing so requires experience, and by keep writing codes, you will have little difficulty solving the same problem the next time you encounter it. There’s a way to speed it up though. By reading other people’s code, you save the time needed to think up the solutions for yourself. Just remember to try to solve a problem by yourself from time to time in order to keep your problem-solving skills sharp.&lt;/p&gt;

&lt;h3&gt;
  
  
  Find a mentor
&lt;/h3&gt;

&lt;p&gt;Most of the time people don’t improve because they don’t know what to learn. Having a mentor will help to identify what to learn next. Mentors can also help to provide the moral support you need in case you are giving up.&lt;/p&gt;

&lt;p&gt;Recently I found &lt;a href="https://codingcoach.io/" rel="noopener noreferrer"&gt;Coding Coach&lt;/a&gt;, a platform where you can find a mentor for free. It’s a cool community! If you are an experienced developer, I suggest you apply as a mentor too. You might learn a thing or two becoming one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Personally, I think programming is hard. The reason being, programming is not just about writing a bunch of codes to solve a problem. Being a good programmer requires other skills such as collaborating, maintaining, ensuring codes don’t break, writing codes that other people understand and so on.&lt;/p&gt;

&lt;p&gt;If you are currently trying to improve by trying to code repeatedly, please take a step back. Try to learn more efficiently instead. If you have any other learning tips, please share it in the comments.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>advice</category>
      <category>learningtocode</category>
    </item>
  </channel>
</rss>
