<?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>Forem: Alvaro Cavalcanti</title>
    <description>The latest articles on Forem by Alvaro Cavalcanti (@alvarocavalcanti).</description>
    <link>https://forem.com/alvarocavalcanti</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%2F13230%2F512234.png</url>
      <title>Forem: Alvaro Cavalcanti</title>
      <link>https://forem.com/alvarocavalcanti</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/alvarocavalcanti"/>
    <language>en</language>
    <item>
      <title>Setting Up a Python Remote Interpreter Using Docker</title>
      <dc:creator>Alvaro Cavalcanti</dc:creator>
      <pubDate>Fri, 08 Nov 2019 13:28:19 +0000</pubDate>
      <link>https://forem.com/alvarocavalcanti/setting-up-a-python-remote-interpreter-using-docker-1i24</link>
      <guid>https://forem.com/alvarocavalcanti/setting-up-a-python-remote-interpreter-using-docker-1i24</guid>
      <description>&lt;h1&gt;
  
  
  Why a Remote Interpreter instead of a Virtual Environment?
&lt;/h1&gt;

&lt;p&gt;A well-known pattern in Python (and many other languages) is to rely on virtual environment tools (&lt;code&gt;virtualenv&lt;/code&gt;, &lt;code&gt;pyenv&lt;/code&gt;, etc) to avoid the &lt;a href="https://martinfowler.com/bliki/SnowflakeServer.html"&gt;SnowflakeServer&lt;/a&gt; anti-pattern. These tools create an isolated environment to install all dependencies for any given project.&lt;/p&gt;

&lt;p&gt;But as of today there's an improvement to that pattern, which is to use Docker containers instead. Such containers provide much more flexibility than virtual environment, because they are not limited to a single platform/language, instead they offer a fully-fledged virtual machine. Not to mention the &lt;code&gt;docker-compose&lt;/code&gt; tool where one can have several containers interacting with each other.&lt;/p&gt;

&lt;p&gt;This article will guide the reader on how to set up the two most used Python IDEs for using Docker containers as remote interpreters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;p&gt;A running Docker container with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A volume mounted to your source code (henceforth, &lt;code&gt;/code&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;SSH setup&lt;/li&gt;
&lt;li&gt;SSH enabled for the &lt;code&gt;root:password&lt;/code&gt; creds and the root user allowed to login&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refer to &lt;a href="https://gist.github.com/alvarocavalcanti/24a6f1470d1db724a398ea6204384f00"&gt;this gist&lt;/a&gt; for the necessary Docker files.&lt;/p&gt;

&lt;h2&gt;
  
  
  PyCharm Professional Edition
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Preferences (CMD + ,) &amp;gt; Project Settings &amp;gt; Project Interpreter&lt;/li&gt;
&lt;li&gt;Click on the gear icon next to the "Project Interpreter" dropdown &amp;gt; Add&lt;/li&gt;
&lt;li&gt;Select "SSH Interpreter" &amp;gt; Host: localhost, Port: 9922, Username: root &amp;gt; Password: password &amp;gt; Interpreter: /usr/local/bin/python, Sync folders: Project Root -&amp;gt; /code, Disable "Automatically upload..."&lt;/li&gt;
&lt;li&gt;Confirm the changes and wait for PyCharm to update the indexes&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Visual Studio Code
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-python.python"&gt;Python&lt;/a&gt; extension&lt;/li&gt;
&lt;li&gt;Install the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers"&gt;Remote - Containers&lt;/a&gt; extension&lt;/li&gt;
&lt;li&gt;Open the Command Pallette and type &lt;code&gt;Remote-Containers&lt;/code&gt;, then select the &lt;code&gt;Attach to Running Container...&lt;/code&gt; and selecet the running docker container&lt;/li&gt;
&lt;li&gt;VS Code will restart and reload&lt;/li&gt;
&lt;li&gt;On the &lt;code&gt;Explorer&lt;/code&gt; sidebar, click the &lt;code&gt;open a folder&lt;/code&gt; button and then enter &lt;code&gt;/code&lt;/code&gt; (this will be loaded from the remote container)&lt;/li&gt;
&lt;li&gt;On the &lt;code&gt;Extensions&lt;/code&gt; sidebar, select the &lt;code&gt;Python&lt;/code&gt; extension and install it on the container&lt;/li&gt;
&lt;li&gt;When prompet on which interppreter to use, select &lt;code&gt;/usr/local/bin/python&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open the Command Pallette and type &lt;code&gt;Python: Configure Tests&lt;/code&gt;, then select the &lt;code&gt;unittest&lt;/code&gt; framework&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Expected Results
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Code completion works&lt;/li&gt;
&lt;li&gt;Code navigation works&lt;/li&gt;
&lt;li&gt;Organize imports works&lt;/li&gt;
&lt;li&gt;Import suggestions/discovery works&lt;/li&gt;
&lt;li&gt;(VS Code) Tests (either classes or methods) will have a new line above their definitions, containing two actions: &lt;code&gt;Run Test | Debug Test&lt;/code&gt;, and will be executed upon clicking on them&lt;/li&gt;
&lt;li&gt;(PyCharm) Tests (either classes or methods) can be executed by placing the cursor on them and then using &lt;code&gt;Ctrl+Shift+R&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Bonus: TDD Enablement
&lt;/h2&gt;

&lt;p&gt;One of the key aspects of the Test-Driven Development is to provide a short feedback on each iteration (write a failing test, fix the test, refactor). And a lot of times a project's tooling might work against this principle, as it's fairly common for a project to have a way of executing its test suite, but it is also common that this task will run the entire suite, not just a single test.&lt;/p&gt;

&lt;p&gt;But if you have your IDE of choice able to execute just a single test in a matter of seconds, you will feel way more comfortable on given TDD a try.&lt;/p&gt;

</description>
      <category>python</category>
      <category>pycharm</category>
      <category>vscode</category>
      <category>tdd</category>
    </item>
    <item>
      <title>Readability for Real - Using Meaningful Names for Database Queries</title>
      <dc:creator>Alvaro Cavalcanti</dc:creator>
      <pubDate>Tue, 16 Oct 2018 19:33:22 +0000</pubDate>
      <link>https://forem.com/alvarocavalcanti/readability-for-real---using-meaningful-names-for-database-queries-doc</link>
      <guid>https://forem.com/alvarocavalcanti/readability-for-real---using-meaningful-names-for-database-queries-doc</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%2Fnhxqq6rplki35xzttfw2.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%2Fnhxqq6rplki35xzttfw2.png" alt="Readability"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Readability matters
&lt;/h1&gt;

&lt;p&gt;Anyone that has programmed for a while and had to deal with someone else's code knows it (especially when this someone is yourself, six months ago). It can be frustrating to try to understand a seemingly innocent bunch of lines of code, but end up thinking "what was this person thinking back then?".&lt;/p&gt;

&lt;p&gt;I have come across a scenario similar to the one below, which I managed to have its obscure business rules exposed into the code without the use of comments. You see, I am &lt;strong&gt;strongly&lt;/strong&gt; against using comments. For me, they should be used as a last resort, with maintainability as the main argument for this. We all know how easily comments can get out of synch with the code.&lt;/p&gt;

&lt;h1&gt;
  
  
  Scenario Description
&lt;/h1&gt;

&lt;p&gt;Imagine you have a subscription-based business, where your customers sign up to different plans, which can be billed monthly or annually. This system has been running for a couple of years now and you need to perform some batch process to subscriptions six hours before they get renewed. But this should not be for all plans, you need to exclude the subscriptions to "Partner Plus" plans, both annually and monthly recurrences.&lt;/p&gt;

&lt;p&gt;At first, it may seem simple, but the reality is that during the past years things evolved rather freely and you don't have a simple ID for each plan. In fact, the whole concept of what is a "Partner Plus" plan depends on different things. The plan's name should have "partner" on it, but it's not limited to that alone: "partner agile expo 15", "partner plus", "new partner plus", etc. Also, the price is variable, but at least is always greater than 249.00 for monthly and 2490.00 for annually.&lt;/p&gt;

&lt;h1&gt;
  
  
  Writing the Code
&lt;/h1&gt;

&lt;p&gt;With that in mind, you might end up with a code similar to this (it's a Python code for a Django application):&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="n"&gt;subscriptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;period_end__lte&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan__plan_id__contains&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;partner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan__recurrence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MONTHLY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan__price__gt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;249.00&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan__plan_id__contains&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;partner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan__recurrence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ANNUALLY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan__price__gt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2490.00&lt;/span&gt;&lt;span class="sh"&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;Well, based on what I described earlier this code does the job beautifully. It looks ahead six hours, and excludes the plans that match the Partner Plus definition, right?&lt;/p&gt;

&lt;p&gt;But, what if six months from now a new team member is tasked to change this code. Will she be able to understand &lt;strong&gt;why&lt;/strong&gt; that exclusion is being done? And what kind of objects are being excluded? Most probably she would need to ask around a bit.&lt;/p&gt;

&lt;p&gt;But now have a look on this refactored code:&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="n"&gt;next_6_hours&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;partner_plus_monthly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan__plan_id__contains&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;partner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan__recurrence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MONTHLY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan__price__gt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;249.00&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;partner_plus_annually&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan__plan_id__contains&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;partner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan__recurrence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ANNUALLY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan__price__gt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2490.00&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;subscriptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;period_end__lte&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;next_6_hours&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;partner_plus_monthly&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;partner_plus_annually&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the variables bear the context, and even if the new team member does not get it completely, at least she can be more informed when asking around, she can start off with "why do we need to exclude partner plus plans from this query?".&lt;/p&gt;

&lt;p&gt;The thing with readability-driven refactorings is that they tend to be overlooked due to the seemingly "low impact", because, you know, "it's almost the same code", "everyone in the team knows what it means", "a comment line would do it", etc.&lt;/p&gt;

&lt;p&gt;Well, to that I say: challenge yourself! Writing is about communication. Either writing prose or code!&lt;/p&gt;

&lt;h1&gt;
  
  
  It's Dangerous to go Alone, Take This
&lt;/h1&gt;

&lt;p&gt;Before you go, I'm gonna leave the following link here (and in all my future readability articles) because it was the one article which opened my mind on the matter and I keep coming back to it every now and then: &lt;a href="https://martinfowler.com/bliki/FunctionLength.html" rel="noopener noreferrer"&gt;FunctionLength, by Martin Fowler&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>readability</category>
    </item>
    <item>
      <title>Practical Python - Duck-typing to the rescue!</title>
      <dc:creator>Alvaro Cavalcanti</dc:creator>
      <pubDate>Thu, 04 Oct 2018 14:46:07 +0000</pubDate>
      <link>https://forem.com/alvarocavalcanti/practical-python---duck-typing-to-the-rescue-46e6</link>
      <guid>https://forem.com/alvarocavalcanti/practical-python---duck-typing-to-the-rescue-46e6</guid>
      <description>

&lt;h1&gt;Duck-typing?&lt;/h1&gt;

&lt;p&gt;If it walks like a duck, quacks like a duck and swims like a duck: it's a duck.&lt;/p&gt;

&lt;p&gt;That above is the simple definition of &lt;a href="https://en.wikipedia.org/wiki/Duck_typing"&gt;duck-typing&lt;/a&gt;, which is a great side-effect feature of non-static typed languages, like Python.&lt;/p&gt;

&lt;h1&gt;Alright, how can I use it?&lt;/h1&gt;

&lt;p&gt;Let's consider the following object, a &lt;a href="https://docs.djangoproject.com/en/2.1/topics/db/models/"&gt;Django model&lt;/a&gt; (simplified for this example):&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;address_street&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;address_zip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;pets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ArrayField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c"&gt;# Consider a one-to-many relationship&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, you are tasked with creating a change tracker for the user, but that change should only care about the &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;pets&lt;/code&gt; collection (because reasons). You then create a new model similar to this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;before_username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;before_pets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ArrayField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;after_username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;after_pets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ArrayField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All is well, you have implemented almost every scenario, until you get to the removal of a single &lt;code&gt;Pet&lt;/code&gt; from a &lt;code&gt;User&lt;/code&gt;. The issue is, since the collection is loaded from the database, and you should only track the change once it is completed, it gets tricky to load the previous state. Well, you can grab the initial collection before it gets modified, that's fine, but where to store it? You can also do a &lt;a href="https://docs.python.org/2/library/copy.html"&gt;&lt;code&gt;copy.deepcopy&lt;/code&gt;&lt;/a&gt; of it, but that might sound like using a cannon to kill an ant. Then again, you only need to store the &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;pets&lt;/code&gt; collection.&lt;/p&gt;

&lt;h1&gt;Duck-typing to the rescue!&lt;/h1&gt;

&lt;p&gt;You can use a light-weighted and elegant solution as:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Duck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwds&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__dict__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kwds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above class takes whatever &lt;a href="https://stackoverflow.com/questions/1769403/understanding-kwargs-in-python"&gt;keyword arguments&lt;/a&gt; you pass in and adds them as proprieties to the class and can be used as simple as:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user_duck_before&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Duck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"dog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cat"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;user_duck_after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Duck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"cat"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's it. Now you can use these "ducks" on the deletion flow without much memory overhead.&lt;/p&gt;

&lt;p&gt;This approach is similar to using &lt;a href="https://docs.python.org/3/library/unittest.mock.html"&gt;&lt;code&gt;unites.mock&lt;/code&gt;&lt;/a&gt; but with production code instead of testing code.&lt;/p&gt;

&lt;p&gt;And to be fair, even though I already had the idea in my mind, I didn't came up with the code, I found it on &lt;a href="https://stackoverflow.com/questions/2827623/how-can-i-create-an-object-and-add-attributes-to-it"&gt;this SO post&lt;/a&gt; which pointed me to the &lt;a href="https://code.activestate.com/recipes/52308-the-simple-but-handy-collector-of-a-bunch-of-named/?in=user-97991"&gt;code recipe&lt;/a&gt; by &lt;a href="https://code.activestate.com/recipes/users/97991/"&gt;Alex Martelli&lt;/a&gt;. Thanks, Alex!&lt;/p&gt;

&lt;h2&gt;Edit&lt;/h2&gt;

&lt;p&gt;I realized that something was not clear, but I didn't want to modify it in place, thus this section. What really motivated me in searching for a duck-type approach was the one-to-many collection. In my real world scenario this collection was a &lt;a href="https://docs.djangoproject.com/pt-br/2.1/ref/models/relations/"&gt;&lt;code&gt;RelatedManager&lt;/code&gt;&lt;/a&gt;, which prevented me from loading the previous state after the item have been removed, thus I needed to store that info in a way that I would neither break my contract nor implement an almost identical method just for this new data structure.&lt;/p&gt;


</description>
      <category>python</category>
      <category>ducktyping</category>
    </item>
    <item>
      <title>Ever wished for a pull request dependency check? You've got it.</title>
      <dc:creator>Alvaro Cavalcanti</dc:creator>
      <pubDate>Tue, 06 Mar 2018 19:05:56 +0000</pubDate>
      <link>https://forem.com/alvarocavalcanti/ever-wished-for-a-pull-request-dependency-check-youve-got-it--177g</link>
      <guid>https://forem.com/alvarocavalcanti/ever-wished-for-a-pull-request-dependency-check-youve-got-it--177g</guid>
      <description>&lt;h2&gt;
  
  
  Pull Requests are a thing (like it or not)
&lt;/h2&gt;

&lt;p&gt;Those of us that work with &lt;a href="http://github.com" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, either contributing to some open-source projects or working on private repositories, are familiar with pull requests. Even if your team is adept of &lt;a href="https://trunkbaseddevelopment.com" rel="noopener noreferrer"&gt;trunk based development&lt;/a&gt; you should have heard about PRs as "evil things".&lt;/p&gt;

&lt;p&gt;But if you're on the first group, as myself, and deal with a couple of different repositories that have any kind of dependency between them you might have come around with merging a PR that depended on another repo's PR that wasn't merged yet. I know I have!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Episode®
&lt;/h2&gt;

&lt;p&gt;It was a RoR frontend that depended on a Django-Rest-Framework backend. We merged the former before the latter, thus some production bugs cropped up and we had to deal with them.&lt;/p&gt;

&lt;p&gt;After that episode, I started looking for tools that could prevent that from happening again. And it would be awesome to have some tool that would publish against the PR status/check, the same way CI services as &lt;a href="https://jenkins.io" rel="noopener noreferrer"&gt;Jenkins&lt;/a&gt; and &lt;a href="https://circleci.com" rel="noopener noreferrer"&gt;CircleCI&lt;/a&gt; and some GitHub features do.&lt;/p&gt;

&lt;p&gt;To be honest, I did find a couple of tools/services that seemed to offer this feature. What I didn't like, tho, was that they had a &lt;strong&gt;truckload&lt;/strong&gt; of features. And I didn't want that, I wanted a simple checker.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you don't like, do it yourself
&lt;/h2&gt;

&lt;p&gt;From that point I changed my research. Instead of looking for a tool, I started looking at GitHub API's documentation. I decided to create a tool myself and it felt quite achievable after my initial research.&lt;/p&gt;

&lt;p&gt;As I felt really comfortable and productive with Python, it was my platform of choice. But instead of going with &lt;a href="http://www.django-rest-framework.org" rel="noopener noreferrer"&gt;Django-Rest-Framework&lt;/a&gt; I chose &lt;a href="http://flask.pocoo.org" rel="noopener noreferrer"&gt;Flask&lt;/a&gt; for two reasons, 1) a Flask app is way slimmer than a DRF one, and slim and simple is better, and 2) I wanted to try Flask out. :)&lt;/p&gt;

&lt;h2&gt;
  
  
  There you have it: Pierre DeCheck
&lt;/h2&gt;

&lt;p&gt;After roughly 2 months, and a complete rewrite, I had a working version that was ready for real-world testing. Here I present to you: &lt;a href="https://github.com/alvarocavalcanti/pierre-decheck" rel="noopener noreferrer"&gt;Pierre DeCheck&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pierre's concept is simple, it should be configured as a webhook for a given repository, then you add the dependencies to a PR using keywords like "Depends on #2" for same-repo issues/PRs, or "Depends on owner/repo#2" for external ones and then it will publish a check to your PR status, telling you if the dependencies are met or not:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Falvarocavalcanti%2Fpierre-decheck%2Fraw%2Fmaster%2Fpull_request_checks.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Falvarocavalcanti%2Fpierre-decheck%2Fraw%2Fmaster%2Fpull_request_checks.png" alt="A Pull Request's checks" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The installation and usage details can be found on &lt;a href="https://github.com/alvarocavalcanti/pierre-decheck#installation" rel="noopener noreferrer"&gt;Pierre's GitHub page&lt;/a&gt; and the only caveat you should be aware of is that, for now, the dependency check is synchronous. Meaning that when GitHub sends an event to the webhook, the check and status update will be made during that request. Which isn't optimal at all, I know, but it's a start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Edit:&lt;/strong&gt; Pierre will perform checks only upon PR creation and Comment Activity (added/removed). In every case it will fetch all the PR's bodies (the PR body itself and from all its comments), extract the dependencies and perform the checks. Thus, it &lt;strong&gt;does not&lt;/strong&gt; observe the dependencies themselves and re-run the checks if their status change. But who knows what future holds? Feel free to &lt;a href="https://github.com/alvarocavalcanti/pierre-decheck/issues/new" rel="noopener noreferrer"&gt;create an issue/feature request&lt;/a&gt;! :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Help Wanted
&lt;/h2&gt;

&lt;p&gt;So, if you think this tool could help your team, it would be great if you could test it, create issues for the bugs you find and even contribute!&lt;/p&gt;

&lt;p&gt;Thanks a lot!&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>opensource</category>
      <category>python</category>
      <category>flask</category>
    </item>
    <item>
      <title>To Create or To Fix?</title>
      <dc:creator>Alvaro Cavalcanti</dc:creator>
      <pubDate>Thu, 08 Feb 2018 22:18:15 +0000</pubDate>
      <link>https://forem.com/alvarocavalcanti/to-create-or-to-fix--4l0n</link>
      <guid>https://forem.com/alvarocavalcanti/to-create-or-to-fix--4l0n</guid>
      <description>

&lt;p&gt;The first thrill we feel upon writing the first line of code in our life is when we make the computer &lt;strong&gt;do something&lt;/strong&gt;. Write our name, say hi to the world or even print a computed sum. It's the joy of creation.&lt;/p&gt;

&lt;p&gt;Of course that feeling does not last for too long, because the first bug is never too far away. Then the back-and-forth begins. Writing features and fixing bugs. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's the circle of life.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Further down the road we end up with a lot of created features, and a pretty good amount of crushed bugs. Which ones did you enjoy the most?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If I must pick one...&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It will be crushing bugs!&lt;/p&gt;

&lt;p&gt;To be fair, it's really exciting to talk to the P.O. trying to understand better the requirements for a given story, to do either a kickoff or a desk-check session with the users and see the value of that feature in their eyes. And to deliver that, obviously.&lt;/p&gt;

&lt;p&gt;But in the end it feels more rewarding, to me, to get a bug and crush it. To read through the logs, to understand better the business, the code and investigate. The investigation is thrilling. Unfortunately, the bugs usually come bundled into a pressure pan, with anxious people who want it to be gone and that's not really pleasant.&lt;/p&gt;

&lt;p&gt;But even then, I do enjoy the investigation and the fixing.&lt;/p&gt;

&lt;p&gt;What about you peeps?&lt;/p&gt;


</description>
      <category>coding</category>
      <category>bugfixing</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Hi, I'm Alvaro Cavalcanti</title>
      <dc:creator>Alvaro Cavalcanti</dc:creator>
      <pubDate>Fri, 24 Mar 2017 18:10:35 +0000</pubDate>
      <link>https://forem.com/alvarocavalcanti/hi-im-alvaro-cavalcanti</link>
      <guid>https://forem.com/alvarocavalcanti/hi-im-alvaro-cavalcanti</guid>
      <description>&lt;p&gt;I have been coding for almost 20 years.&lt;/p&gt;

&lt;p&gt;You can find me on Twitter as &lt;a href="https://twitter.com/alvarocavalcant" rel="noopener noreferrer"&gt;@alvarocavalcant&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I live in Recife (Pernambuco, Brasil).&lt;/p&gt;

&lt;p&gt;I work for ThoughtWorks&lt;/p&gt;

&lt;p&gt;I mostly program in these languages: Swift, Python and Java.&lt;/p&gt;

&lt;p&gt;I am currently learning more about iOS and Mobile Architectures.&lt;/p&gt;

&lt;p&gt;Nice to meet you.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
