<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Programming on Noetic Nought</title>
    <link>https://punchagan.muse-amuse.in/tags/programming/</link>
    <description>Recent content in Programming on Noetic Nought</description>
    <generator>Hugo</generator>
    <language>en-US</language>
    <copyright>© 2006-2026 CC-BY-SA-4.0</copyright>
    <lastBuildDate>Fri, 30 Jan 2026 16:58:00 +0530</lastBuildDate>
    <atom:link href="https://punchagan.muse-amuse.in/tags/programming/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Why my Elfeed index was 0 bytes</title>
      <link>https://punchagan.muse-amuse.in/blog/elfeed-index-0-bytes/</link>
      <pubDate>Fri, 30 Jan 2026 16:58:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/elfeed-index-0-bytes/</guid>
      <description>&lt;p&gt;My Linux machine crashed, while I was in the middle of a video call. I&#xA;restarted quickly, and continued the discussion. Later, when I was trying to&#xA;sync &lt;a href=&#34;https://github.com/skeeto/elfeed&#34;&gt;Elfeed&lt;/a&gt; updates onto the &lt;a href=&#34;https://github.com/punchagan/elfeed-offline/&#34;&gt;Elfeed Offline&lt;/a&gt; app on my phone, I found it acting&#xA;weird. All the &lt;a href=&#34;https://punchagan.muse-amuse.in/blog/offline-friendly-elfeed-web-ui/&#34;&gt;bazillion things&lt;/a&gt; needed to get it working were in place, but it&#xA;was still complaining about the Emacs Elfeed server not being accessible. I&#xA;tried opening Elfeed inside Emacs and failed! The index file in &lt;a href=&#34;https://punchagan.muse-amuse.in/blog/elfeed-db-back-up-hooks/&#34;&gt;Elfeed&amp;rsquo;s DB was&#xA;empty&lt;/a&gt;! Gone! Poof!&lt;/p&gt;&#xA;&lt;p&gt;Frustrating, but I didn&amp;rsquo;t have time to look into what happened. I would&amp;rsquo;ve been&#xA;furious if I had been using Elfeed for longer and had a lot more metadata&#xA;saved. But, it was only a few weeks of lost metadata - posts I read, starred,&#xA;etc. I quickly setup a &lt;a href=&#34;https://punchagan.muse-amuse.in/blog/elfeed-db-back-up-hooks/&#34;&gt;Git based backup&lt;/a&gt; to prevent future losses and moved on.&lt;/p&gt;&#xA;&lt;p&gt;Later, I found time to dig into what might have happened&amp;hellip;&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-breadcrumbs&#34;&gt;The breadcrumbs&lt;/h2&gt;&#xA;&lt;p&gt;Elfeed stores all the metadata for all the posts in an &lt;code&gt;index&lt;/code&gt; file with a&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Content-addressable_storage&#34;&gt;content addressed store&lt;/a&gt; of the contents of each of the posts. The index file is&#xA;simply a dump of the hash-table containing the metadata for the subscribed&#xA;feeds, their entries and metadata like tags, read/unread status, etc.&lt;/p&gt;&#xA;&lt;p&gt;The DB save happens in &lt;a href=&#34;https://github.com/skeeto/elfeed/blob/a39fb78e34ee25dc8baea83376f929d7c128344f/elfeed-db.el#L271&#34;&gt;&lt;code&gt;elfeed-db-save&lt;/code&gt;&lt;/a&gt;, which simply dumps the hash-table to&#xA;disk inside a call to the &lt;code&gt;with-temp-file&lt;/code&gt; macro.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;defun&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;elfeed-db-save&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;; &amp;lt;snip&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;with-temp-file&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;expand-file-name&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;index&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;elfeed-db-directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;; ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;princ&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;format&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;;;; Elfeed Database Index (version %s)\n\n&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                       &lt;span class=&#34;nv&#34;&gt;elfeed-db-version&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;; ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;prin1&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;elfeed-db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;with-temp-file&lt;/code&gt;, as its documentation says, lets you create a new buffer,&#xA;evaluate the &lt;code&gt;body&lt;/code&gt; there, and write the buffer to &lt;code&gt;file&lt;/code&gt;. For a moment, I&#xA;thought there was some temporary file involved, but nope! I guess the name&#xA;comes as an extension from &lt;code&gt;with-temp-buffer&lt;/code&gt; which does create a temporary&#xA;buffer where the &lt;code&gt;body&lt;/code&gt; of the macro gets evaluated. Stripped to its core, &lt;a href=&#34;https://github.com/emacs-mirror/emacs/blob/3b547e4f5dc99dc157b52a059cf234f7a5d15112/lisp/subr.el#L5300-L5318&#34;&gt;this&#xA;function&lt;/a&gt; is:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;temp-file&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;temp-buffer&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;generate-new-buffer&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34; *temp file*&amp;#34;&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;prog1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;with-current-buffer&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;temp-buffer&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         &lt;span class=&#34;o&#34;&gt;,@&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;with-current-buffer&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;temp-buffer&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;write-region&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;temp-file&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;write-region-and-o-trunc&#34;&gt;&lt;code&gt;write-region&lt;/code&gt; and &lt;code&gt;O_TRUNC&lt;/code&gt;&lt;/h2&gt;&#xA;&lt;p&gt;So, &lt;a href=&#34;https://github.com/emacs-mirror/emacs/blob/3b547e4f5dc99dc157b52a059cf234f7a5d15112/src/fileio.c#L5512&#34;&gt;&lt;code&gt;write-region&lt;/code&gt; is the workhorse&lt;/a&gt; which writes the contents of the temporary&#xA;buffer to disk. It&amp;rsquo;s a roughly 300 line long C function that essentially opens&#xA;the file with the flags &lt;code&gt;O_WRONLY | O_CREAT | O_TRUNC&lt;/code&gt; (in this case) and then&#xA;does something to write the contents to the file, etc. Honestly, I didn&amp;rsquo;t look&#xA;at anything else too carefully after I spotted the &lt;code&gt;O_TRUNC&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The man page of &lt;code&gt;open&lt;/code&gt; explains &lt;code&gt;O_TRUNC&lt;/code&gt; as follows:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;O_TRUNC :: If the file already exists and is a regular file and the access mode&#xA;allows writing (i.e., is O_RDWR or O_WRONLY) it will be truncated to&#xA;length 0.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Voilà!&lt;/p&gt;&#xA;&lt;p&gt;The write is not atomic. The file first gets truncated to length 0, and then we&#xA;hope that the new contents get correctly written before something goes wrong.&lt;/p&gt;&#xA;&lt;p&gt;It now makes sense why the file got truncated to 0 bytes. The crash happened&#xA;after the &lt;code&gt;open&lt;/code&gt;, but before the write. Somehow the crash happened in this&#xA;short window, and poof!&lt;/p&gt;&#xA;&lt;h2 id=&#34;emacs-has-backup-files-doesn-t-it&#34;&gt;Emacs has backup files, doesn&amp;rsquo;t it?&lt;/h2&gt;&#xA;&lt;p&gt;Temporary files with &lt;code&gt;~&lt;/code&gt; in their file extensions have definitely annoyed me in&#xA;the past when Emacs created them where I didn&amp;rsquo;t want them. So, I do know that&#xA;Emacs has back-up mechanisms out of the box. But, it turns out that the backups&#xA;occur in code paths that are more interactive, like &lt;code&gt;save-buffer&lt;/code&gt;,&#xA;&lt;code&gt;write-file&lt;/code&gt;, etc. And not via the programmatic APIs like &lt;code&gt;write-region&lt;/code&gt; or the&#xA;higher level &lt;code&gt;with-temp-file&lt;/code&gt;. &lt;code&gt;save-buffer&lt;/code&gt; calls &lt;code&gt;backup-buffer&lt;/code&gt; before&#xA;writing, but &lt;code&gt;write-region&lt;/code&gt; is much more low-level and doesn&amp;rsquo;t deal with&#xA;backups.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-fix&#34;&gt;The fix&lt;/h2&gt;&#xA;&lt;p&gt;My &amp;ldquo;fix&amp;rdquo; for this is to backup the Elfeed data in a git repository to be able&#xA;to recover from any such corruptions of data, which I already wrote about &lt;a href=&#34;https://punchagan.muse-amuse.in/blog/elfeed-db-back-up-hooks/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I know that any code that uses &lt;code&gt;with-temp-file&lt;/code&gt; (or &lt;code&gt;write-region&lt;/code&gt;) could be&#xA;affected by this, and the right fix for this may be to write to a temporary&#xA;file and rename it. Maybe next time I lose data I&amp;rsquo;ll actually fix it properly.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>GitHub Gists from Emacs Orgmode</title>
      <link>https://punchagan.muse-amuse.in/blog/ox-gist/</link>
      <pubDate>Tue, 26 Apr 2022 12:37:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/ox-gist/</guid>
      <description>&lt;p&gt;TL;DR: I released my first Emacs MELPA package &amp;ndash; &lt;a href=&#34;https://melpa.org/#/ox-gist&#34;&gt;ox-gist&lt;/a&gt; &amp;ndash; An Orgmode backend&#xA;to export and update sub-trees and buffers to GitHub gists.  It was a great&#xA;experience contributing to MELPA.&lt;/p&gt;&#xA;&lt;h2 id=&#34;motivation&#34;&gt;Motivation&lt;/h2&gt;&#xA;&lt;p&gt;I often share bits and pieces of my &lt;code&gt;journal.org&lt;/code&gt; file with others, mostly for&#xA;reading, some times for comments. The file contains different subtrees for each&#xA;day with subtrees for different topics, meetings, articles, etc.&lt;/p&gt;&#xA;&lt;p&gt;Orgmode lets you export subtrees to specific file names using the&#xA;&lt;code&gt;EXPORT_FILE_NAME&lt;/code&gt; property (and &lt;code&gt;FILE_NAME&lt;/code&gt; buffer export option when&#xA;exporting full buffers). It is easy to create these exported files on a&#xA;publicly accessible webserver using the power of &lt;a href=&#34;https://www.gnu.org/software/tramp/&#34;&gt;Emacs TRAMP mode&lt;/a&gt;.  For&#xA;instance, I often set the property to some thing like&#xA;&lt;code&gt;/ssh:muse-amuse.in:~/public_html/&amp;lt;filename&amp;gt;&lt;/code&gt; to publish stuff.&lt;/p&gt;&#xA;&lt;p&gt;But, exporting to HTML is a distraction some times because I start fiddling&#xA;with CSS and styling. Exporting to a simple org file doesn&amp;rsquo;t seem to cut it&#xA;because there&amp;rsquo;s no styling at all, and making longer exports hard to read in a&#xA;web-browser.  Exporting to a GitHub Gist is a nice middle ground because GitHub&#xA;renders Orgmode files reasonably well. Additionally, the comment functionality&#xA;is pretty handy.&lt;/p&gt;&#xA;&lt;p&gt;I could also directly use &lt;a href=&#34;https://github.com/defunkt/&#34;&gt;@defunkt&lt;/a&gt;&amp;rsquo;s excellent &lt;a href=&#34;https://github.com/defunkt/gist.el&#34;&gt;&lt;code&gt;gist.el&lt;/code&gt;&lt;/a&gt; to share stuff as&#xA;Gists.  I&amp;rsquo;ve used it in the past, and it works well when I don&amp;rsquo;t care about&#xA;having the contents of the Gist locally on my machine. It&amp;rsquo;s also quite easy to&#xA;update existing/old Gists in this scenario, since there&amp;rsquo;s a single &amp;ldquo;source of&#xA;truth&amp;rdquo; and &lt;code&gt;gist.el&lt;/code&gt; makes it quite easy to update Gists.&lt;/p&gt;&#xA;&lt;p&gt;But, this isn&amp;rsquo;t good enough when I want to have a &amp;ldquo;synced&amp;rdquo; copy of the text on&#xA;my machine.  Also, it doesn&amp;rsquo;t work very well when I want to share just a&#xA;subtree from my notes file, and not the entire file.  I&amp;rsquo;ve to export the&#xA;subtree to a temporary Orgmode buffer and then create a Gist from that buffer.&lt;/p&gt;&#xA;&lt;h2 id=&#34;hackish-wrapper-around-gist-dot-el&#34;&gt;Hackish wrapper around &lt;code&gt;gist.el&lt;/code&gt;&lt;/h2&gt;&#xA;&lt;p&gt;A couple or so years ago, I wrote a wrapper around &lt;code&gt;gist.el&lt;/code&gt; to let me post&#xA;Orgmode subtrees as a Gist and also update them when I edited these subtrees&#xA;locally.  There was no support for exporting entire buffers since that wasn&amp;rsquo;t&#xA;my use-case.  This wrapper code was just a part of my &lt;code&gt;.emacs&lt;/code&gt; and worked&#xA;reasonably well for me.&lt;/p&gt;&#xA;&lt;p&gt;A few weeks ago, I ended up procrastinating on writing and sharing notes for a&#xA;discussion with a friend, and extracted this wrapper as a separate package &amp;ndash;&#xA;&lt;code&gt;org2gist&lt;/code&gt; &amp;ndash; to make it easy for other people to use.&lt;/p&gt;&#xA;&lt;h2 id=&#34;melpa-submission-and-feedback&#34;&gt;MELPA submission and feedback&lt;/h2&gt;&#xA;&lt;p&gt;I &lt;a href=&#34;https://github.com/melpa/melpa/pull/7940&#34;&gt;submitted&lt;/a&gt; this as a package to &lt;a href=&#34;https://melpa.org/&#34;&gt;MELPA&lt;/a&gt; while being skeptical about whether it&#xA;would be accepted.  I wasn&amp;rsquo;t sure if my thin wrapper around &lt;code&gt;gist.el&lt;/code&gt; would&#xA;meet MELPA&amp;rsquo;s criteria for a &amp;ldquo;Reasonably innovative package&amp;rdquo;:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;MELPA provides a curated set of Emacs Lisp packages, not an exhaustive list&#xA;of every single Emacs Lisp file ever created. By default, MELPA maintainers&#xA;will reject packages that duplicate functionality provided by existing&#xA;packages. Please try to improve existing packages instead of creating new&#xA;ones when possible.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;It was a pleasant surprise to get very helpful reviews from the MELPA&#xA;maintainers.  They not only thought the package was good enough to include in&#xA;MELPA, but also looked at it&amp;rsquo;s code and gave great feedback &amp;mdash; not just basic&#xA;quality checks before accepting the package into MELPA.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m pretty sure mainting a package repository like MELPA is a lot of work, but&#xA;as an end-user it mostly just worked for me and I never really gave it much&#xA;thought.  It was eye-opening to submit the package to MELPA and see first-hand&#xA;the care and effort the maintainers put into what goes into the repository.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/riscy/&#34;&gt;@riscy&lt;/a&gt; (a MELPA maintainer) &lt;a href=&#34;https://github.com/melpa/melpa/pull/7940#issuecomment-1080036663&#34;&gt;suggested&lt;/a&gt; a different approach that I hadn&amp;rsquo;t&#xA;thought of &amp;mdash; turning the wrapper into an &lt;a href=&#34;https://orgmode.org/manual/Exporting.html&#34;&gt;Orgmode Export backend&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;current-version-ox-gist&#34;&gt;Current version: &lt;code&gt;ox-gist&lt;/code&gt;&lt;/h2&gt;&#xA;&lt;p&gt;It turned out to be a great idea which I ended up implementing.  The user&#xA;interface became much cleaner, since it used the Orgmode Export UI.  And it&#xA;also forced me to &amp;ldquo;complete&amp;rdquo; the feature-set by adding support for exporting&#xA;entire Orgmode buffers to GitHub Gists, not just subtrees.&lt;/p&gt;&#xA;&lt;p&gt;The package now adds an Orgmode export backend that lets you export a subtree&#xA;or the whole buffer as a GitHub Gist, similar to how you&amp;rsquo;d export to HTML or&#xA;LaTeX from Orgmode. The GitHub Gist ID is saved for each exported buffer or&#xA;subtree and is to update a Gist when re-exporting an already exported subtree&#xA;or buffer.&lt;/p&gt;&#xA;&lt;h2 id=&#34;outro&#34;&gt;Outro&lt;/h2&gt;&#xA;&lt;p&gt;The package has now been added to MELPA as &lt;a href=&#34;https://github.com/punchagan/ox-gist&#34;&gt;&lt;code&gt;ox-gist&lt;/code&gt;&lt;/a&gt;.  Feel free to give it a&#xA;spin and give feedback directly to me or on the &lt;a href=&#34;https://github.com/punchagan/ox-gist/issues&#34;&gt;issue tracker&lt;/a&gt;!&lt;/p&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t know if anyone else would find the package useful and use it, though,&#xA;MELPA tells me that 20-odd people atleast downloaded it.  I&amp;rsquo;m happy this code&#xA;may be to a handful of people.&lt;/p&gt;&#xA;&lt;p&gt;Also, I now have a new found appreciation for MELPA and the work put into it by&#xA;the maintainers.  I&amp;rsquo;m glad I took the time out to submit this package to MELPA.&lt;/p&gt;&#xA;&lt;div style=&#34;font-size:small;&#34; class=&#34;reviewers&#34;&gt;&#xA;&lt;p&gt;Thanks to &lt;a href=&#34;http://baali.muse-amuse.in&#34;&gt;Shantanu&lt;/a&gt; for reading drafts and helping me restructure this post.&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Thoughts on Technical Debt</title>
      <link>https://punchagan.muse-amuse.in/blog/thoughts-on-technical-debt/</link>
      <pubDate>Tue, 23 Apr 2019 07:52:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/thoughts-on-technical-debt/</guid>
      <description>&lt;p&gt;I recently watched &lt;a href=&#34;https://www.youtube.com/watch?v=pqeJFYwnkjE&#34;&gt;this short video by Ward Cunningham&lt;/a&gt; where he reflects on the&#xA;history, motivation for, and common misunderstandings of the term Technical&#xA;debt.&lt;/p&gt;&#xA;&lt;p&gt;This post is just some of my reflections on Technical debt, based on ideas and&#xA;thoughts from &lt;a href=&#34;https://en.wikipedia.org/wiki/Ward%5FCunningham&#34;&gt;Ward Cunningham&lt;/a&gt;, &lt;a href=&#34;https://martinfowler.com/&#34;&gt;Martin Fowler&lt;/a&gt; and &lt;a href=&#34;https://en.wikipedia.org/wiki/Robert%5FC.%5FMartin&#34;&gt;Uncle Bob&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-is-technical-debt&#34;&gt;What is Technical Debt?&lt;/h2&gt;&#xA;&lt;p&gt;Ward Cunningham coined the &amp;ldquo;Techincal Debt&amp;rdquo; metaphor &amp;ndash; he used the metaphor to&#xA;explain the idea of shipping something with a limited understanding of the&#xA;problem, in the hope of gaining a better understanding as more people interact&#xA;with the shipped code.&lt;/p&gt;&#xA;&lt;p&gt;The difference between the understanding of the problem and how the code models&#xA;it is going to slow down the developers. This &amp;ldquo;slowing down&amp;rdquo; is equivalent to&#xA;paying interest, until we take out the time to refactor the code to accurately&#xA;reflect the current understanding of the problem.&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-take-on-technical-debt&#34;&gt;Why take on Technical Debt?&lt;/h2&gt;&#xA;&lt;p&gt;When Cunningham says debt, he means shipping code with a partial, unclear or&#xA;even incorrect understanding of the problem and how it should be modeled. You&#xA;are willing to get the code out of the door, to improve this understanding.&lt;/p&gt;&#xA;&lt;p&gt;With borrowed money, sometimes you can do something sooner than you would&#xA;otherwise. Similarly, rushing software out the door can help us get some&#xA;experience with it, which would help gain a better understanding and improve the&#xA;software.&lt;/p&gt;&#xA;&lt;h2 id=&#34;a-mess-is-not-a-debt-or-is-it&#34;&gt;A mess is not a debt, or is it?&lt;/h2&gt;&#xA;&lt;p&gt;Cunningham says that people confuse messily written code with technical debt. He&#xA;is of the opinion that messy code isn&amp;rsquo;t technical debt. He&amp;rsquo;s never in favor of&#xA;shipping bad or messy code. He emphasizes that code that&amp;rsquo;s shipped should always&#xA;be clear enough to refactor easily, when required, even if it doesn&amp;rsquo;t model our&#xA;current understanding of the problem very accurately.&lt;/p&gt;&#xA;&lt;p&gt;Uncle Bob also has a post, on similar lines, where he says, &lt;a href=&#34;https://sites.google.com/site/unclebobconsultingllc/a-mess-is-not-a-technical-debt&#34;&gt;a mess is not a&#xA;technical debt&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Martin Fowler, on the other hand, argues that the debt metaphor is a useful&#xA;metaphor to think about and to communicate problems in code &amp;mdash; especially to&#xA;non-technical people &amp;mdash; irrespective of the reason for the problem.&lt;/p&gt;&#xA;&lt;p&gt;Not shipping messy code makes sense. But, the debt metaphor is a useful tool to&#xA;talk about existing &amp;ldquo;messy&amp;rdquo; code, compared to just calling it messy code.&#xA;Looking at it as a debt lets you think about whether or not it&amp;rsquo;s worth paying&#xA;off, and if so when, etc. The Technical Debt Quadrant (explained below) further&#xA;classified this debt into 4 classes, which makes it even more useful to identify&#xA;bad code as debt.&lt;/p&gt;&#xA;&lt;h2 id=&#34;technical-debt-quadrant&#34;&gt;Technical Debt Quadrant&lt;/h2&gt;&#xA;&lt;p&gt;Martin Fowler came up with a &lt;a href=&#34;https://martinfowler.com/bliki/TechnicalDebtQuadrant.html&#34;&gt;Technical Debt Quadrant&lt;/a&gt; which incorporates other&#xA;kinds of debt, along with the one Ward Cunningham originally defined.&lt;/p&gt;&#xA;&lt;figure&gt;&lt;img src=&#34;https://martinfowler.com/bliki/images/techDebtQuadrant.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;p&gt;Fowler comes up with two kinds of divisions of debt &amp;mdash; Reckless vs Prudent and&#xA;Inadvertent vs Deliberate.&lt;/p&gt;&#xA;&lt;p&gt;When Ward says he&amp;rsquo;s against writing bad code, I think he means he&amp;rsquo;s never for&#xA;taking on reckless debt. Uncle Bob&amp;rsquo;s mess is also what Fowler would call&#xA;Reckless debt.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Reckless-Deliberate&lt;/strong&gt; debt is code written out of not caring enough about the&#xA;code, or not stopping to think about everything that&amp;rsquo;s going on with the code,&#xA;or just being mentally lazy. Code-reviews seem like one good way to avoid this&#xA;kind of debt.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Reckless-Inadvertent&lt;/strong&gt; debt is something that&amp;rsquo;s hard to prevent. It sounds like&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=GiPe1OiKQuk&#34;&gt;unknown-unknowns&lt;/a&gt; territory to me. The developers or the team would probably&#xA;benefit from improving their general design skills and/or getting some external&#xA;help as consultants, etc.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Prudent-Deliberate&lt;/strong&gt; debt is what Ward talks about, I think, in his video. You&#xA;know your understanding is not good enough, but you aren&amp;rsquo;t yet sure what&amp;rsquo;s the&#xA;right design is. You may gather more knowledge about the problem while the&#xA;software is out there in the wild and being used.&lt;/p&gt;&#xA;&lt;p&gt;Ward talks about better understanding. But, you may not always realize that your&#xA;understanding is incomplete, when you are shipping the code. This I think would&#xA;put it in the 4th quadrant - &lt;strong&gt;Prudent-Inadvertent&lt;/strong&gt; debt.&lt;/p&gt;&#xA;&lt;h2 id=&#34;is-everything-tech-debt&#34;&gt;Is everything tech debt?&lt;/h2&gt;&#xA;&lt;p&gt;The Tech Debt quadrant seems to make a lot of things seem to fit into the debt&#xA;metaphor, but there are some things that I&amp;rsquo;m not sure about.&lt;/p&gt;&#xA;&lt;p&gt;For example, it can be a significant time investment to update dependencies.&#xA;Often, teams don&amp;rsquo;t update dependencies until it becomes absolutely essential &amp;mdash;&#xA;&amp;ldquo;don&amp;rsquo;t fix what ain&amp;rsquo;t broken&amp;rdquo;. This strategy of postponing of updates, to use&#xA;the time for other things, seems like taking on a debt. But, I&amp;rsquo;m not sure which&#xA;quadrant to put it into.&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-should-i-care&#34;&gt;Why should I care?&lt;/h2&gt;&#xA;&lt;p&gt;Just calling code messy isn&amp;rsquo;t really qualifying the mess, and helping us talk&#xA;about how to tackle it. Thinking about debt while taking decisions seems&#xA;helpful, especially with further classification of debt into the 4 quadrants.&lt;/p&gt;&#xA;&lt;p&gt;It helps think about whether we&amp;rsquo;d like to pay off debts we have taken, and to&#xA;communicate with non-technical people the kind of &amp;ldquo;maintenance&amp;rdquo; or refactoring&#xA;work we plan to take up, and why it is important to do so. The deliberate debt&#xA;concept can be used to think and communicate about things we aren&amp;rsquo;t dealing&#xA;with, right now, in the interest of shipping software quicker.&lt;/p&gt;&#xA;&lt;h2 id=&#34;keeping-track-and-repaying-debt&#34;&gt;Keeping track and repaying debt&lt;/h2&gt;&#xA;&lt;p&gt;If a debt is something we can take on deliberately, and we can take on multiple&#xA;such debts, what would be a good way to keep track of these debts?&lt;/p&gt;&#xA;&lt;p&gt;Keeping a list of these debts that we periodically review, seems like a good&#xA;idea. We check if our understanding has improved from the time we took on a&#xA;debt, and take out time to incorporate it back into the code.&lt;/p&gt;&#xA;&lt;p&gt;This list could just be a bunch of FIXMEs in the code with some detailed&#xA;explanation of the debt, and why it was required, or just a list of issues in&#xA;the issue tracker with a special tag to make it easy to find them.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;div style=&#34;font-size:small;&#34; class=&#34;reviewers&#34;&gt;&#xA;  &lt;div&gt;&lt;/div&gt;&#xA;&lt;p&gt;Thanks to &lt;a href=&#34;https://baali.muse-amuse.in&#34;&gt;Shantanu Choudhary&lt;/a&gt; and &lt;a href=&#34;https://vkrishnaswam.github.io/&#34;&gt;Vivek Krishnaswamy&lt;/a&gt; for reading drafts of this post&#xA;and giving helpful suggestions.&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Heroku apps with custom-domain and Cloudflare SSL</title>
      <link>https://punchagan.muse-amuse.in/blog/heroku-apps-custom-domain-cloudflare-ssl/</link>
      <pubDate>Thu, 14 Mar 2019 13:03:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/heroku-apps-custom-domain-cloudflare-ssl/</guid>
      <description>&lt;h2 id=&#34;motivation&#34;&gt;Motivation&lt;/h2&gt;&#xA;&lt;p&gt;I have a bunch of small (toy?) apps hosted on Heroku. They are probably used by&#xA;a few dozen people, at most. For these apps, I&amp;rsquo;d like the following setup:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Use a custom domain for the apps&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Heroku provides domains of the form &lt;code&gt;appname.herokuapp.com&lt;/code&gt; for all apps.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;But, it also has the option to add one or more custom domains&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I usually already have a domain under which I want to add a sub-domain,&#xA;where these apps would run.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Use HTTPS for all connections&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The domains or the sub-domains usually don&amp;rsquo;t already already have an SSL&#xA;certificate. With lets-encrypt, I guess this can change in future.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Heroku provides SSL certificates for the default domain&#xA;(&lt;code&gt;appname.herokuapp.com&lt;/code&gt;) for free.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;They also have an option to buy SSL certificates for custom domains, but&#xA;they are expensive!&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I&amp;rsquo;m going to use &lt;a href=&#34;https://www.cloudflare.com/ssl/&#34;&gt;Cloudflare&amp;rsquo;s free SSL service&lt;/a&gt; instead. I&amp;rsquo;d like to have&#xA;SSL for the full domain, and not just the app&amp;rsquo;s subdomain.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Redirect all the requests to the Heroku domain to the custom domain&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Nobody should really be using the &lt;code&gt;appname.herokuapp.com&lt;/code&gt; domain, in case&#xA;I&amp;rsquo;d like to move away from it.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;A few lines of app (Flask) code can do this for us.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;setup&#34;&gt;Setup&lt;/h2&gt;&#xA;&lt;h3 id=&#34;setup-dns-to-use-cloudflare&#34;&gt;Setup DNS to use Cloudflare&lt;/h3&gt;&#xA;&lt;p&gt;Since we plan to use Cloudflare for the SSL certificates, we need to change DNS&#xA;settings at our domain registrar to use Cloudflare. We first need to create a&#xA;Cloudflare account, and &lt;a href=&#34;https://support.cloudflare.com/hc/en-us/articles/201720164-Step-2-Create-a-Cloudflare-account-and-add-a-website&#34;&gt;let Cloudflare do a DNS scan&lt;/a&gt; to add all the existing&#xA;domain settings automatically. Next we point to the &lt;a href=&#34;https://support.cloudflare.com/hc/en-us/articles/205195708&#34;&gt;Cloudflare DNS servers&lt;/a&gt; on&#xA;our domain registrar.&lt;/p&gt;&#xA;&lt;h3 id=&#34;enable-https-always-in-cloudflare&#34;&gt;Enable HTTPS always in Cloudflare&lt;/h3&gt;&#xA;&lt;p&gt;Using &lt;a href=&#34;https://support.cloudflare.com/hc/en-us/articles/218411427#always-use-https&#34;&gt;page rules in Cloudflare&lt;/a&gt;, add a rule for the whole domain to &amp;ldquo;Always use&#xA;HTTPS&amp;rdquo;. For example, use the url &lt;code&gt;http://*example.com/*&lt;/code&gt; and select the &lt;code&gt;Always use HTTPS&lt;/code&gt; option.&lt;/p&gt;&#xA;&lt;h3 id=&#34;select-the-ssl-option-to-use&#34;&gt;Select the SSL option to use&lt;/h3&gt;&#xA;&lt;p&gt;Cloudflare provides &lt;a href=&#34;https://support.cloudflare.com/hc/en-us/articles/200170416-What-do-the-SSL-options-mean-&#34;&gt;different options for the SSL setting&lt;/a&gt; which changes whether&#xA;or not traffic is encrypted between Cloudflare and the Heroku app.&lt;/p&gt;&#xA;&lt;p&gt;Choose &lt;code&gt;Full (strict)&lt;/code&gt; to enable encryption between Cloudflare and Heroku.&lt;/p&gt;&#xA;&lt;p&gt;If you are not so concerned about encryption between Cloudflare and Heroku, you&#xA;could select the &lt;code&gt;Flexible&lt;/code&gt; option too.&lt;/p&gt;&#xA;&lt;h3 id=&#34;add-a-custom-domain-in-heroku&#34;&gt;Add a custom domain in Heroku&lt;/h3&gt;&#xA;&lt;p&gt;Add a &lt;a href=&#34;https://devcenter.heroku.com/articles/custom-domains&#34;&gt;custom domain&lt;/a&gt; &amp;ndash; &lt;code&gt;app.example.com&lt;/code&gt; &amp;ndash; in Heroku&amp;rsquo;s settings.&lt;/p&gt;&#xA;&lt;p&gt;Heroku provides a DNS Target that needs to be used as the destination for a&#xA;CNAME setting in the DNS provider (Cloudflare). The DNS Target looks something&#xA;like &lt;code&gt;foo-bar-123abcdef.herokudns.com&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;If you chose &lt;code&gt;Full (strict)&lt;/code&gt; SSL option, this DNS target cannot be used and can&#xA;be ignored.&lt;/p&gt;&#xA;&lt;h3 id=&#34;add-a-cname-for-the-subdomain&#34;&gt;Add a CNAME for the subdomain&lt;/h3&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://support.cloudflare.com/hc/en-us/articles/360019093151-#h%5F60566325041543261564371&#34;&gt;Add a new CNAME setting&lt;/a&gt; in Cloudflare for &lt;code&gt;app.example.com&lt;/code&gt; and use the&#xA;app&amp;rsquo;s Heroku domain name (&lt;code&gt;appname.herokuapp.com&lt;/code&gt;) as the destination value/IP&#xA;address.&lt;/p&gt;&#xA;&lt;p&gt;It is important to use the &lt;code&gt;appname.herokuapp.com&lt;/code&gt; value if the SSL settings you&#xA;chose above was &lt;code&gt;Full (strict)&lt;/code&gt;. Using the DNS Target provided by Heroku instead&#xA;(&lt;code&gt;foo-bar-123abcdef.herokudns.com&lt;/code&gt;) would give an &lt;a href=&#34;https://support.cloudflare.com/hc/en-us/articles/200278659&#34;&gt;SSL Handshake error&lt;/a&gt; since the&#xA;SSL certificate provided by Heroku only works for the &lt;code&gt;appname.herokuapp.com&lt;/code&gt;&#xA;domain, and not for &lt;code&gt;foo-bar-123abcdef.herokudns.com&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If you chose &lt;code&gt;Flexible&lt;/code&gt;, though, you can use the DNS Target provided by Heroku&#xA;&amp;ndash; &lt;code&gt;foo-bar-123abcdef.herokudns.com&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Also, ensure that the Cloudflare Proxy Toggle is toggled on &amp;ndash; &lt;em&gt;the cloud icon&#xA;is orange, not grey&lt;/em&gt;!&lt;/p&gt;&#xA;&lt;h3 id=&#34;redirect-all-requests&#34;&gt;Redirect all requests&lt;/h3&gt;&#xA;&lt;p&gt;We redirect all the requests coming to the old domain to the new one.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@app.before_request&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;redirect_heroku&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;Redirect herokuapp requests.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;urlparts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;urlparse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;urlparts&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;netloc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;appname.herokuapp.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;urlparts_list&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;urlparts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;urlparts_list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;app.example.com&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;redirect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;urlunparse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;urlparts_list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;code&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;301&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;enforce-https-on-heroku&#34;&gt;Enforce HTTPS on Heroku&lt;/h2&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t care about a custom domain and just wish to enforce SSL for the&#xA;Heroku domain (&lt;code&gt;appname.herokuapp.com&lt;/code&gt;), &lt;code&gt;Flask-SSLify&lt;/code&gt; is the way to go. The&#xA;app can be hosted on Heroku and we can use the certs provided for free.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;flask_sslify&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SSLify&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Flask&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;DYNO&amp;#34;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Always use SSL if the app is running on Heroku (not locally)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;sslify&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SSLify&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve done this setup, or some parts of it quite a few times, but each time I&#xA;seem to need to look up the documentation. Every time, it seems to take longer&#xA;than it needs to! Hopefully, this post will make it quick and reproducible.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>2018 in Review</title>
      <link>https://punchagan.muse-amuse.in/blog/2018-in-review/</link>
      <pubDate>Thu, 17 Jan 2019 15:02:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/2018-in-review/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s my review of 2018 - my first successful annual review. I remember wanting&#xA;to do something like this, a couple of times before too. This time, I managed to&#xA;get started and wrap it up!&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve been inspired to write one by a some reviews that I read this year &amp;ndash; some&#xA;of them do it every year.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Sher Minn&amp;rsquo;s &lt;a href=&#34;http://piratefsh.github.io/2018/12/25/2018-retrospective.html&#34;&gt;visual retorospective&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Nat&amp;rsquo;s &lt;a href=&#34;https://writing.natwelch.com/post/685&#34;&gt;month-wise review&lt;/a&gt;, with a review of 2018 goals and a bunch of goals&#xA;for 2019.&lt;/li&gt;&#xA;&lt;li&gt;Julia Evans has an &lt;a href=&#34;https://jvns.ca/blog/2018/12/23/2018--year-in-review/&#34;&gt;annual review&lt;/a&gt; with a bunch of &amp;ldquo;conclusions&amp;rdquo; listing what&#xA;worked in 2018.&lt;/li&gt;&#xA;&lt;li&gt;James Clear answers &lt;a href=&#34;https://jamesclear.com/2018-annual-review&#34;&gt;three questions every year&lt;/a&gt; - what went well, what didn&amp;rsquo;t,&#xA;and what were the learnings.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://sachachua.com/blog/2018/08/turning-35-life-as-a-34-year-old/&#34;&gt;Sacha Chua&lt;/a&gt;&amp;rsquo;s reviews were one of the earliest reviews that I read, and they&#xA;inspired so much awe! I may not be able to do as much quantified-self type&#xA;posts as her, any time soon, but I love them!&lt;/li&gt;&#xA;&lt;li&gt;Buster Benson does annual reviews on his &lt;a href=&#34;https://medium.com/@buster/42-dig-deeper-e2278d1fe015&#34;&gt;birthday every year&lt;/a&gt;. He gives himself&#xA;a motto to live-by, each year.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;My review isn&amp;rsquo;t as systematic as any of these. But, I have some inspiring&#xA;examples in front of me to aspire to. Hope this will start something that I can&#xA;keep doing annually from now, if not more frequently.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve divided my review into a few different areas - based mostly the time I have&#xA;spent on them, how important I feel they are, and the extent of notes I have in&#xA;those areas.&lt;/p&gt;&#xA;&lt;h2 id=&#34;work&#34;&gt;Work&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I continue to work on &lt;a href=&#34;https://github.com/akvo/akvo-rsr/&#34;&gt;RSR&lt;/a&gt; at &lt;a href=&#34;https://akvo.org/&#34;&gt;Akvo&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The most challenging project was to wrangle a legacy permissions system that&#xA;worked at an organization level to give some kind of user level permissions.&#xA;The project was plagued with incomplete communication of requirements from our&#xA;partners, failure to understand the complexity of the legacy code, and weird&#xA;bugs manifesting in even weirder ways. We eventually delivered something, but&#xA;I&amp;rsquo;m not at all happy with the solution, how long it took and how the whole&#xA;project felt.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The company has been in a cost-cutting mode, and has been rethinking the way&#xA;the products are positioned - &lt;a href=&#34;https://akvo.org/blog/reflecting-learning-and-connecting-in-2019/&#34;&gt;transitioning more into a single&#xA;solution/experience for our partners&lt;/a&gt;. This makes a lot of sense &amp;ndash; the focus&#xA;shifts from building tools to solving problems, which is great! But, I wasn&amp;rsquo;t&#xA;particularly happy about how much RSR features in these conversations. Towards&#xA;the end of the year, our team has managed to get more conversations going on&#xA;involving RSR, but we need more.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;A couple of friends asked me if I&amp;rsquo;d want to work for their companies, but I&#xA;decided not to. But, these were opportunities to think more about what I want&#xA;out of my job and the work I do. This is a work in progress.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I did some mentoring at one friend&amp;rsquo;s company, and got to know the team and&#xA;their work pretty well.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I gave an interview at a company that I came across at PyCon which went&#xA;horribly, partially because I didn&amp;rsquo;t prepare well and partially because of&#xA;interview jitters. I was expecting a better interview experience from them,&#xA;though, given how much I liked their team culture, etc.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I also happened to take my first ever front-end interviews, along with a team&#xA;mate. I really liked how he led the interviews, and made the interview&#xA;candidates feel comfortable. I learned a thing or two, including the fact that&#xA;I don&amp;rsquo;t know a lot of things that people with a more structured and systematic&#xA;approach to learning front-end development would know.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I didn&amp;rsquo;t attend too many events this year, like always. But, I really enjoyed&#xA;PyCon - especially the Keynotes by &lt;a href=&#34;https://www.youtube.com/watch?v=ls1jva653bc&#34;&gt;Sidu Ponnappa&lt;/a&gt; and &lt;a href=&#34;https://www.youtube.com/watch?v=-4fzFKihmJw&#34;&gt;Armin Ronacher&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;side-projects&#34;&gt;Side projects&lt;/h2&gt;&#xA;&lt;p&gt;I worked on a bunch of side-projects this year, some of them abandoned, some&#xA;completed and found useful, some abandoned after the first version turned out to&#xA;be not so useful. Most of the stuff was &amp;ldquo;webby&amp;rdquo;, and unsurprisingly a bunch of&#xA;my side-projects were Ultimate related.&lt;/p&gt;&#xA;&lt;dl&gt;&#xA;&lt;dt&gt;Zulip&lt;/dt&gt;&#xA;&lt;dd&gt;I spent a quite a bit of my spare time between about March and&#xA;September contributing to &lt;a href=&#34;https://zulipchat.com/&#34;&gt;Zulip&lt;/a&gt; &amp;ndash; mainly as a mentor on the&#xA;&lt;a href=&#34;https://github.com/zulip/zulip-terminal&#34;&gt;zulip-terminal&lt;/a&gt; project, apart from some minor contributions around&#xA;improving setting up of the dev environment for the &lt;a href=&#34;https://github.com/zulip/zulip-terminal&#34;&gt;zulip-server&lt;/a&gt;&#xA;project. I also facilitated a &lt;a href=&#34;https://in.pycon.org/cfp/devsprint-2018/proposals/zulip-sprint~eXlAe/&#34;&gt;Zulip sprint&lt;/a&gt; during PyCon at Hyderabad.&#xA;&lt;p&gt;I also got to attend the Zulip India Summit! It was great to meet a&#xA;whole bunch of Zulip contributors. I especially enjoyed the&#xA;conversations with and the presentations by Tim and Greg, mostly&#xA;around developer productivity.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m really impressed and inspired by the amount of care and effort&#xA;that is put into stream-lining the process of contributing to the&#xA;project, and the emphasis on developer productivity.&lt;/p&gt;&#xA;&lt;p&gt;I played around with a little bit of React Native development, but&#xA;wasn&amp;rsquo;t able to devote much time to it. I&amp;rsquo;d like to play around some&#xA;more with it, this year.&lt;/p&gt;&#xA;&lt;/dd&gt;&#xA;&lt;dt&gt;Find Playo Venue&lt;/dt&gt;&#xA;&lt;dd&gt;I wrote a &lt;a href=&#34;https://punchagan.github.io/playo-find-venue/&#34;&gt;simple map based tool&lt;/a&gt; to find the most suitably&#xA;located Playo venue with good ratings, when some of my friends and I were&#xA;playing a lot of badminton together. I still use it sometimes, but we&amp;rsquo;ve&#xA;mostly figured out our &amp;ldquo;favorite&amp;rdquo; venues.&lt;/dd&gt;&#xA;&lt;dt&gt;moditweetarchive&lt;/dt&gt;&#xA;&lt;dd&gt;I built a &lt;a href=&#34;http://moditweetarchive.herokuapp.com/&#34;&gt;site&lt;/a&gt; inspired by &lt;a href=&#34;http://trumptwitterarchive.com/&#34;&gt;this Trump tweet archive&lt;/a&gt; for&#xA;Modi&amp;rsquo;s tweets. I used &lt;a href=&#34;https://plot.ly/products/dash/&#34;&gt;Dash&lt;/a&gt; to build it, and it was quite fun, despite a few&#xA;annoyances. This tweet archive, though, isn&amp;rsquo;t as interesting as the Trump&#xA;archive, since the tweets are more calculated and strategic. But, a few&#xA;things could be added to make it more useful.&#xA;&lt;p&gt;The repo is private as of now, but I&amp;rsquo;m happy to share the code, if anyone&#xA;is interested.&lt;/p&gt;&#xA;&lt;/dd&gt;&#xA;&lt;dt&gt;Blaggregator&lt;/dt&gt;&#xA;&lt;dd&gt;I spent a couple of weekends maintaining &lt;a href=&#34;https://blaggregator.recurse.com/about/&#34;&gt;Blaggregator&lt;/a&gt;. I&#xA;updated Django to 1.11.x which is also something I did on Akvo&#xA;RSR (my work project), later during the year. I also worked on&#xA;making the crawl faster by handling dead blogs better, etc.&lt;/dd&gt;&#xA;&lt;dt&gt;weblogviz&lt;/dt&gt;&#xA;&lt;dd&gt;I tried to get started with learning some &lt;a href=&#34;https://www.rust-lang.org/&#34;&gt;Rust&lt;/a&gt;, and as an&#xA;exercise, I started building a &lt;a href=&#34;https://github.com/punchagan/weblogviz&#34;&gt;tool to analyze Apache logs&lt;/a&gt; and&#xA;show some useful stats.&lt;/dd&gt;&#xA;&lt;dt&gt;Org-mode to Zulip helpers&lt;/dt&gt;&#xA;&lt;dd&gt;I wrote some &lt;a href=&#34;https://github.com/punchagan/zulip-helpers.el&#34;&gt;Emacs helpers to post to Zulip&lt;/a&gt;. I&amp;rsquo;m&#xA;quite happy with being able to post longer messages from inside Emacs -&#xA;this lets me retain a copy of things like my checkins or interesting links&#xA;in my notes/journal file.&lt;/dd&gt;&#xA;&lt;dt&gt;aradhana.org&lt;/dt&gt;&#xA;&lt;dd&gt;I tried to help a friend of mine build a newer website for&#xA;&lt;a href=&#34;http://www.aradhana.org/&#34;&gt;aradhana.org&lt;/a&gt;, and spent about a couple of days on it. But,&#xA;there were other bigger problems which needed attention from&#xA;my friends, and this site just fell by the wayside.&lt;/dd&gt;&#xA;&lt;dt&gt;Abandoned projects&lt;/dt&gt;&#xA;&lt;dd&gt;There are bunch of other projects that I&amp;rsquo;ve abandoned. I&#xA;may end up spending some time looking into them, this year.&lt;/dd&gt;&#xA;&lt;/dl&gt;&#xA;&lt;h3 id=&#34;ultimate-related-projects&#34;&gt;Ultimate related projects&lt;/h3&gt;&#xA;&lt;dl&gt;&#xA;&lt;dt&gt;SOTG Calculator&lt;/dt&gt;&#xA;&lt;dd&gt;I had the chance to look at the &lt;a href=&#34;http://www.wfdf.org/sotg/spirit-rules-a-scoring&#34;&gt;Spirit scoring sheets&lt;/a&gt; for a&#xA;couple of tournaments, in the beginning of 2018, and was utterly&#xA;disappointed. I always knew that it was a lot of work to get the top scores&#xA;just a few minutes after the final game, but I found a lot more mistakes&#xA;than I expected &amp;ndash; a lot of them were easy to avoid with just a little&#xA;automation.&#xA;&lt;p&gt;To help improve the situation, I built a &lt;a href=&#34;http://sotg-calculator.herokuapp.com/&#34;&gt;simple webapp&lt;/a&gt; to compute the&#xA;scores from a Google Spread Sheet. Finding the initial adopters turned out&#xA;to be very hard, despite the app making life a lot easier for people. It&#xA;was disappointing to see people saying they didn&amp;rsquo;t have enough time to try&#xA;the app, and instead chose to manually compute everything that the app&#xA;could&amp;rsquo;ve done with a couple of clicks!&lt;/p&gt;&#xA;&lt;p&gt;But, eventually it started to be pushed as the official tool starting this&#xA;season, and has found a bunch of happy users.&lt;/p&gt;&#xA;&lt;/dd&gt;&#xA;&lt;dt&gt;Team RSVP&lt;/dt&gt;&#xA;&lt;dd&gt;We used Whatsapp to co-ordinate team practices and to keep track&#xA;of the players attending, etc. But, this started to get quite&#xA;spammy, and it was a hassle to have other conversations on the&#xA;group, while folks were calling in for a practice. It was a&#xA;nightmare to have people call in for two different events at the&#xA;same time.&#xA;&lt;p&gt;To see if people were willing to switch away to something less&#xA;spammy, a friend and I started with a &lt;a href=&#34;https://github.com/thatte-idli-kaal-soup/rsvpapp&#34;&gt;simple RSVP app&lt;/a&gt; and most&#xA;people seemed to not mind using it.&lt;/p&gt;&#xA;&lt;p&gt;Unsurprisingly, the app eventually got &lt;a href=&#34;https://rsvp.thatteidlikaalsoup.team/features&#34;&gt;a lot of features&lt;/a&gt; - to&#xA;make it easy to manage team practices and team resources like&#xA;photos and training material. It is being used regularly by the&#xA;team, without too many problems.&lt;/p&gt;&#xA;&lt;p&gt;As an after thought, may be we have an over-engineered solution,&#xA;and just asking everyone to use (Google) Calender &amp;amp; Email&#xA;would&amp;rsquo;ve worked.&lt;/p&gt;&#xA;&lt;/dd&gt;&#xA;&lt;dt&gt;Huddle magazine archive&lt;/dt&gt;&#xA;&lt;dd&gt;The Huddle was a good Ultimate related magazine run&#xA;by Ben &amp;amp; Andy a few years ago. They eventually stopped running it, and the&#xA;archives disappeared from the &lt;a href=&#34;https://the-huddle.org/&#34;&gt;original site&lt;/a&gt; but are available on the &lt;a href=&#34;https://www.usaultimate.org/huddle/issue001.aspx&#34;&gt;USA&#xA;Ultimate website&lt;/a&gt; which is super hard to read! I wrote some &lt;a href=&#34;https://github.com/thatte-idli-kaal-soup/the-huddle&#34;&gt;code&lt;/a&gt; to scrape&#xA;the site, and convert the articles into markdown posts and made a more&#xA;readable version of the magazine &lt;a href=&#34;https://thatte-idli-kaal-soup.github.io/the-huddle/&#34;&gt;here&lt;/a&gt;.&#xA;&lt;p&gt;I tried to get in touch with Ben &amp;amp; Andy, to ask if they were interested to&#xA;replace the &amp;ldquo;coming soon&amp;rdquo; message on the original site with these archives,&#xA;but didn&amp;rsquo;t succeed. Posting it on Reddit and sharing it with my team got&#xA;some people interested, and hopefully they keep using it.&lt;/p&gt;&#xA;&lt;/dd&gt;&#xA;&lt;dt&gt;vquiz&lt;/dt&gt;&#xA;&lt;dd&gt;To help my team with understanding rules better, I built a light&#xA;weight &lt;a href=&#34;https://github.com/punchagan/vquiz&#34;&gt;tool to easily create video based quizzes&lt;/a&gt; - embed video and&#xA;ask related questions, use videos to show answers.&#xA;&lt;p&gt;To build a question bank, I tried to get some people on the team to&#xA;volunteer, but it didn&amp;rsquo;t really take off.&lt;/p&gt;&#xA;&lt;/dd&gt;&#xA;&lt;/dl&gt;&#xA;&lt;h2 id=&#34;ultimate-frisbee&#34;&gt;Ultimate Frisbee&lt;/h2&gt;&#xA;&lt;p&gt;2018 was filled with a lot of Ultimate - not just playing, but also thinking,&#xA;talking and planning.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Our team had a couple of the best tournaments that we&amp;rsquo;ve since I&amp;rsquo;ve been&#xA;playing with the team - not just in terms of the results but in how much fun&#xA;we all seemed to have together.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I captained the team in a bunch of tournaments. I&amp;rsquo;m not sure how exactly I got&#xA;to be the captain &amp;ndash; I guess it was just stepping forward for a tournament and&#xA;offering to spend the time and effort required. It was a great learning for&#xA;me, and I&amp;rsquo;ve learned some things about people and leading them that I would&amp;rsquo;ve&#xA;taken much longer to learn. I also think I did get better over the course of&#xA;the year &amp;ndash; I got more confident and the team also trusted me much more.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;In the past, game time at tournaments has been a big concern. We experimented&#xA;with a bunch of simple rotation systems &amp;ndash; essentially just systems to keep&#xA;track of how much each person has been playing, and trying to prevent too many&#xA;imbalances. People were encouraged to bring forth their concerns and ideas&#xA;during the games, rather than keep everything until the end of the tournament&#xA;when it is not fixable until the next time!&lt;/p&gt;&#xA;&lt;p&gt;We had the luxury of being able to try this since everyone on the team had&#xA;more or less the same skill level, and everyone trusted the system. It helped&#xA;take players&amp;rsquo; minds off playing time, and helped them focus on actually making&#xA;the most of the opportunities on the field. Most of the complaints about&#xA;game-time seem to have gone away.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Communicating the reasoning behind a decision is as important as communicating&#xA;the plan. Often, I&amp;rsquo;d hear surprising responses to a plan or just generally&#xA;disappointing comments like how decisions were being made arbitrarily, when we&#xA;were actually spending a lot of time and energy to try and make decisions. On&#xA;most occasions, I felt the reason was the lack of an understanding of the&#xA;reasons behind a decision.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Team communication was another tricky thing that I&amp;rsquo;ve had to wrestle with. The&#xA;team still needs to find a balance between communicating over a WhatsApp group&#xA;or discussing things in person, and the fact that most people are very busy to&#xA;make in-person meetings with a good attendance happen. We are experimenting&#xA;with a few things to see what works and what doesn&amp;rsquo;t.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;At tournaments, having a positive environment where everyone is supportive and&#xA;has each others&amp;rsquo; back is the most important thing for me. Irrespective of how&#xA;much practice we had together and what kind of strategies we practiced, just&#xA;having a team where everyone is positive and helpful goes a long way.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, this positivity is also such a fragile thing that needs to&#xA;be carefully protected and nurtured. It&amp;rsquo;s very easy for one negative comment&#xA;or thought to spread negativity and discontent like wild-fire.&lt;/p&gt;&#xA;&lt;p&gt;I think as a captain, I should&amp;rsquo;ve strived harder to safe guarding and&#xA;cultivating this positivity in the team.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Thanks to some discussions I had with my teammates, I spent a lot of time&#xA;thinking about what it means to feel like a valued member of a team, and what&#xA;it means to feel like you are contributing and making a difference. Being&#xA;chosen an MVP during a game is external validation that you made a difference&#xA;in a game, but only one or two people get that validation in each game. What&#xA;about the rest of the dozen or so other people? How can we as a team recognize&#xA;and acknowledge each others&amp;rsquo; contributions to each point or game?&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Some of these questions will continue to take up some of my mindspace this year,&#xA;whether or not I continue to captain the team.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I also took up the role of UPAI&amp;rsquo;s &lt;a href=&#34;http://indiaultimate.org/governance-committee&#34;&gt;Director of Technology&lt;/a&gt; (aka sys-admin) along&#xA;with AK. It&amp;rsquo;s mostly been minor email or slack related change requests, and&#xA;nothing more. But, it&amp;rsquo;s been fun to get to know some of the people in the&#xA;Ultimate community a little better. I also helped organize the &lt;a href=&#34;http://indiaultimate.org/p/proceedings-of-upai-national-conference-2018&#34;&gt;UPAI conference&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;writing&#34;&gt;Writing&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I wrote only 8 blog posts, but 6 of them in the second half of the year!&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Some friends and I started a &lt;a href=&#34;https://sasha.wtf/writing-club/&#34;&gt;Writing Club&lt;/a&gt; in July, and it&amp;rsquo;s been going strong&#xA;so far. It has not only helped me publish at least one blog post a month, but&#xA;based on the responses I&amp;rsquo;ve received, I feel it has also improved the quality&#xA;of my writing. A lot of credit goes to my friends who read initial drafts of&#xA;my writing, and gave me really good suggestions on how to improve them.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;My journaling and personal note taking improved slightly as compared to last&#xA;year - I have more notes for 2018, than 2017. And that&amp;rsquo;s how I was able to&#xA;write this review post. But, I think the notes are restricted to a few areas&#xA;of my life, and I can take some actions to write about other things that are&#xA;important too.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;relationships&#34;&gt;Relationships&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I started a couple of Zulip instances with my friends on it &amp;ndash; one with my&#xA;college friends and another with my Ultimate team mates on it. My friends from&#xA;college went back to WhatsApp, but the other Zulip realm has had some pretty&#xA;conversations, especially on #beanbags. It hasn&amp;rsquo;t been super active towards&#xA;the end of the year, but I&amp;rsquo;m really happy it exists, and hope it continues to&#xA;grow this year.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;It was good to have some more teammates turn into friends. Thanks to all the&#xA;Ultimate stuff I&amp;rsquo;ve been doing, I got to spend a lot more time with some of&#xA;the people that I previously hadn&amp;rsquo;t interacted much with.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Tarle, a teammate and friend, passed away. 4 months and he&amp;rsquo;s still dead. We&#xA;all miss him a lot! But, we&amp;rsquo;ve also come together stronger, in some ways.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve tried scheduling regular check-ins with some friends who live far away.&#xA;They worked for a bit, but seem to be easily swallowed by higher priority&#xA;things. When they did happen, though, they were quite nice!&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Towards the end of the year, I moved houses. The new house is well furnished&#xA;and has neighbors who mostly mind their business &amp;ndash; I had a lot of friends and&#xA;family visiting, which has been good.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;2019-goals-ideas&#34;&gt;2019 goals/ideas&lt;/h2&gt;&#xA;&lt;p&gt;I want to give having a motto for an year a shot, a la Buster Benson. My motto&#xA;for 2019 is &amp;ldquo;Be Deliberate&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m not sure I know exactly what this entails, and I&amp;rsquo;m sure I&amp;rsquo;ll get a better&#xA;understanding of it, as the year goes by. But, here are few things that I think&#xA;would be good starting points:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Choose what I read more deliberately, and read for understanding rather than&#xA;just information. Keep better notes of the books I read.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Go back to using &lt;a href=&#34;https://github.com/punchagan/howdy&#34;&gt;Howdy&lt;/a&gt; or creating check-ins with more people, and making sure&#xA;that they happen. Prefer meeting in person or audio/video calls, rather than&#xA;chat.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Journal more about feelings and thoughts, especially when making decisions,&#xA;rather than just about events. Journal about more areas of my life rather than&#xA;just &amp;ldquo;work&amp;rdquo; related stuff.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Consider hiring an editor to help write better blog posts, and improve writing&#xA;style. Getting reviews and suggestions from my Writing Club friends has been&#xA;good, but this would be a level up.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Look for mentors in other areas of life - especially those where I feel like&#xA;I&amp;rsquo;m plateauing.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Pick side projects more carefully. One thing that I would be deliberately&#xA;thinking more about would be working on side projects that pay.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Write quarterly posts to document my improved understanding of the theme &amp;ndash; Be&#xA;Deliberate &amp;ndash; and to track progress I&amp;rsquo;m making on these goals.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;Thanks &lt;a href=&#34;https://tinyurl.com/ydd4s7jd&#34;&gt;Kartik Krovvidi&lt;/a&gt; and &lt;a href=&#34;http://baali.muse-amuse.in/&#34;&gt;Shantanu Choudhary&lt;/a&gt; for reading drafts of this post,&#xA;being excited about it, and useful suggestions to make it better.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Software development practices for sports teams</title>
      <link>https://punchagan.muse-amuse.in/blog/software-development-practices-sports-teams/</link>
      <pubDate>Sun, 23 Sep 2018 11:31:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/software-development-practices-sports-teams/</guid>
      <description>&lt;h2 id=&#34;motivation&#34;&gt;Motivation&lt;/h2&gt;&#xA;&lt;p&gt;A few weeks ago, I came across &lt;a href=&#34;https://www.youtube.com/watch?v=SHOVVnRB4h0&#34;&gt;a talk on Mob programming&lt;/a&gt; &amp;mdash; a technique for&#xA;working on a software project as a team, that was accidentally discovered by a&#xA;team trying to figure out how to work well together. The speaker lets us in on&#xA;how they stumbled on it, and how they fine-tuned it to make it more effective&#xA;while being relaxed and enjoyable.&lt;/p&gt;&#xA;&lt;p&gt;A few days before that, I shared &lt;a href=&#34;http://daydreamsinruby.com/getting-feedback/&#34;&gt;a post&lt;/a&gt; on &amp;ldquo;getting feedback (as a software&#xA;developer)&amp;rdquo; with my &lt;a href=&#34;https://www.youtube.com/watch?v=zEKnqFBajiI&#34;&gt;Ultimate Frisbee&lt;/a&gt; team-mates and it seemed to resonate with&#xA;them. I&amp;rsquo;m often looking at things happening in my sports team from a software&#xA;guy&amp;rsquo;s perspective, since I spend a lot of time being the software guy. But, I&#xA;rarely, if ever, directly share these thoughts and ideas with my team-mates.&lt;/p&gt;&#xA;&lt;p&gt;But, the mob programming talk inspired me to make a conscious effort to look for&#xA;software development patterns that could be adopted by &lt;a href=&#34;https://thatteidlikaalsoup.team/&#34;&gt;our (sports) team&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Most players on our team have been playing Ultimate for a while now (2-5 years).&#xA;So, we have more problems due to miscommunication and everyone not being on the&#xA;same page, than we have due to lack of skills or knowledge. When someone on the&#xA;team does not understand the plan, the whole plan goes for a toss.&lt;/p&gt;&#xA;&lt;p&gt;How do we make sure that everyone understands what the team is trying to do and&#xA;is able to contribute their bit to the team&amp;rsquo;s plans and success? How do we make&#xA;playing with each other as enjoyable as it can be?&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;The object isn&amp;rsquo;t to make art, it&amp;rsquo;s to be in that wonderful state which makes&#xA;art inevitable.&amp;rdquo; &amp;mdash; Robert Henri&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;some-ideas-for-adoption&#34;&gt;Some ideas for adoption&lt;/h2&gt;&#xA;&lt;p&gt;Here are some ideas that, I think, could be adopted by our team. Some of these&#xA;are things that teams, including ours, do in some shape or form. But,&#xA;identifying and naming would make it easier for people to talk about them and&#xA;develop a common understanding of why and how to do them.&lt;/p&gt;&#xA;&lt;h3 id=&#34;ubiquitous-language&#34;&gt;Ubiquitous Language&lt;/h3&gt;&#xA;&lt;p&gt;Eric Evans, in his book Domain Driven Design, talks about building a &lt;a href=&#34;https://martinfowler.com/bliki/UbiquitousLanguage.html&#34;&gt;Ubiquitous&#xA;language&lt;/a&gt; in the team. It grows as the team&amp;rsquo;s understanding of the problem grows,&#xA;and helps the team communicate clearly throughout the development cycle.&lt;/p&gt;&#xA;&lt;p&gt;Our team plays a lot of zone defense, and it usually works well for us But, it&#xA;wasn&amp;rsquo;t working particularly well, during one of the tournaments last year.&#xA;Luckily, we had &lt;a href=&#34;https://www.instagram.com/monsieurmoby/&#34;&gt;Moby&lt;/a&gt; playing with us, and he asked us some probing questions&#xA;around the objective of the play and the roles of each of the players. With just&#xA;a short chat and a few small adjustments, the zone became way more effective.&#xA;Essentially, we built a common understanding of the objective of the defense and&#xA;brought everyone onto the same page.&lt;/p&gt;&#xA;&lt;p&gt;Ultimate teams use a lot of lingo &amp;ndash; a lot. New players just pick it up by&#xA;osmosis, at practice, from the senior folks. This works most of the time, except&#xA;when it doesn&amp;rsquo;t. Each person on the team has a slightly different understanding&#xA;of what a term means, and the difference is sometimes big enough to cause a plan&#xA;to fail due to miscommunication. Spending time building a common understanding&#xA;would make the team communicate and operate more effectively. Practicing game&#xA;scenarios is essentially a way of doing this, but it would be worth thinking&#xA;about and discussing the terms and the language being used.&lt;/p&gt;&#xA;&lt;p&gt;Off-field lingo should also be clarified using a similar process &amp;ndash; for&#xA;instance, what does &amp;ldquo;good sideline support&amp;rdquo; mean? What does giving or not giving&#xA;&amp;ldquo;feedback on the field&amp;rdquo; mean?&lt;/p&gt;&#xA;&lt;h3 id=&#34;sprints&#34;&gt;Sprints&lt;/h3&gt;&#xA;&lt;p&gt;Agile development recommends continuous development of software. Often software&#xA;teams use 2-4 week development cycles, called &lt;a href=&#34;http://wiki.c2.com/?ScrumSprint&#34;&gt;sprints&lt;/a&gt;. For each sprint, the team&#xA;sets itself a goal, and the whole team prioritizes tasks and makes decisions&#xA;in-line with this goal.&lt;/p&gt;&#xA;&lt;p&gt;Sports teams would also benefit from sprints &amp;ndash; short and focused practice&#xA;cycles, where everyone on the team is aware of the team&amp;rsquo;s goal. This would make&#xA;it much easier for players to help each other out. Also, players can align their&#xA;individual goals with the team goal, making practices much more effective.&lt;/p&gt;&#xA;&lt;h3 id=&#34;retrospectives&#34;&gt;Retrospectives&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;At regular intervals, the team reflects on how to become more effective, then&#xA;tunes and adjusts its behavior accordingly. &amp;mdash; The Agile Manifesto&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Most Ultimate teams do some kind of post-practice retrospectives, though, they&#xA;don&amp;rsquo;t call it that. These retrospectives are a discussion of the good, bad and&#xA;the ugly. Usually, no conscious decisions are made about what practices are&#xA;working well for the team, and what should be taken forward to upcoming ones.&lt;/p&gt;&#xA;&lt;p&gt;Slightly longer term retrospectives would be quite useful too. If a team adopts&#xA;the idea of sprints, each new sprint should start with a retrospective of the&#xA;last one and planning for the next.&lt;/p&gt;&#xA;&lt;p&gt;A retrospective&amp;rsquo;s participants are expected to follow the &lt;a href=&#34;http://retrospectivewiki.org/index.php?title=The_Prime_Directive&#34;&gt;prime directive&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Regardless of what we discover, we understand and truly believe that everyone&#xA;did the best job they could, given what they knew at the time, their skills and&#xA;abilities, the resources available, and the situation at hand. &amp;mdash; Norm Kerth,&#xA;&lt;em&gt;Project Retrospectives: A Handbook for Team Review&lt;/em&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Internalising this would be really helpful especially during post-tournament&#xA;retrospectives, where emotions can run high &amp;ndash; it would keep the discussion&#xA;positive and focused on identifying problems and finding solutions, rather than&#xA;spiraling into blame games, defensive arguments, etc.&lt;/p&gt;&#xA;&lt;h3 id=&#34;daily-stand-ups&#34;&gt;Daily Stand-ups&lt;/h3&gt;&#xA;&lt;p&gt;Agile teams &lt;a href=&#34;https://www.mountaingoatsoftware.com/agile/scrum/meetings/daily-scrum&#34;&gt;gather each day&lt;/a&gt; at the start of the work-day, to let each know about&#xA;the progress of the work-items. The team tries to help each other get rid of the&#xA;impediments to progress.&lt;/p&gt;&#xA;&lt;p&gt;Ultimate teams could also benefit operating in this style &amp;ndash; everyone shares&#xA;with each other what they are working on, and the problems in their learning.&#xA;This would make it easier for others to look out for things to help with.&#xA;Team-mates would limit themselves to giving feedback to the thing that a player&#xA;is working on.&lt;/p&gt;&#xA;&lt;p&gt;Players setting themselves a small number of clear focus points would also force&#xA;them to consciously think about and work on their game more effectively.&lt;/p&gt;&#xA;&lt;h3 id=&#34;face-to-face-communication&#34;&gt;Face-to-face communication&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The most efficient and effective method of conveying information to and within a&#xA;development team is face-to-face conversation. &amp;mdash; The Agile Manifesto&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;As our team has grown larger over the years, more and more communication has&#xA;moved to the WhatsApp group. Keeping everyone informed via face-to-face&#xA;communication, at this team size needs a lot of co-ordination and planning, and&#xA;the time at practice is considered to be too precious to be spent talking and&#xA;not practicing.&lt;/p&gt;&#xA;&lt;p&gt;But, clearly WhatsApp doesn&amp;rsquo;t seem like the best medium to have discussions.&#xA;Discussions rarely, if ever, happen on our groups. It often just seems to be&#xA;information dissemination. Using a &lt;a href=&#34;http://zulipchat.com/hello&#34;&gt;better communication tool&lt;/a&gt; could mitigate a&#xA;few of these problems, but face-to-face discussions have other benefits. They&#xA;bring about a greater sense of belonging to the team and increase buy-in into&#xA;the team&amp;rsquo;s plans.&lt;/p&gt;&#xA;&lt;h3 id=&#34;unit-tests-vs-dot-integration-tests&#34;&gt;Unit tests vs. Integration tests&lt;/h3&gt;&#xA;&lt;p&gt;Practice games are helpful to gauge if a team is playing well together and if&#xA;its plans are working. This seems analogous to &lt;a href=&#34;http://wiki.c2.com/?IntegrationTest&#34;&gt;integration tests&lt;/a&gt; &amp;mdash; checking&#xA;that we have functional software, end-to-end.&lt;/p&gt;&#xA;&lt;p&gt;But, in the early stages of development, it&amp;rsquo;s common to write &lt;a href=&#34;http://wiki.c2.com/?UnitTest&#34;&gt;unit-tests&lt;/a&gt; &amp;ndash;&#xA;tests to ensure that each of the individual components works well in isolation.&#xA;An analogous thing would be to have individual evaluations to help players&#xA;identify weak areas, and to measure progress in those areas. It would also&#xA;prevent players from slipping on important &amp;ldquo;indicators&amp;rdquo;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;other-ideas-to-think-about&#34;&gt;Other ideas to think about&lt;/h2&gt;&#xA;&lt;p&gt;Some ideas that I find interesting, but don&amp;rsquo;t yet know if and how they can be&#xA;adopted by sports teams are below.&lt;/p&gt;&#xA;&lt;h3 id=&#34;mob-programming&#34;&gt;Mob programming&lt;/h3&gt;&#xA;&lt;p&gt;In a &lt;a href=&#34;https://www.agilealliance.org/resources/experience-reports/mob-programming-agile2014/&#34;&gt;mob programming session&lt;/a&gt;, everyone on the team is working on the same&#xA;computer, in the same room, at the same time. This seems tremendously&#xA;ineffective at the face of it, but turns out to be a good way to produce high&#xA;quality software, quickly.&lt;/p&gt;&#xA;&lt;h3 id=&#34;hammock-driven-development&#34;&gt;Hammock driven development&lt;/h3&gt;&#xA;&lt;p&gt;Bugs are incredibly expensive to be found and fixed in production software. They&#xA;are cheaper to fix in the development phase. But, the design phase is the best&#xA;place to fix them.&lt;/p&gt;&#xA;&lt;p&gt;Rich Hickey &lt;a href=&#34;https://www.youtube.com/watch?v=f84n5oFoZBc&#34;&gt;recommends&lt;/a&gt; feeding a lot of information about the problem you are&#xA;trying to solve to your waking mind, so that your background mind can feed off&#xA;of it while you are asleep, and make useful connections.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Build projects around motivated individuals. Give them the environment and&#xA;support they need, and trust them to get the job done.  &amp;mdash; The Agile manifesto&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;This sounds exactly like what players in our team need too. The captains and the&#xA;mentors in the team should work towards providing the environment and the&#xA;support everyone on the team needs, and trust them to do the job.&lt;/p&gt;&#xA;&lt;div style=&#34;font-size:small;&#34; class=&#34;reviewers&#34;&gt;&#xA;&lt;p&gt;Thanks Meghana Iyer, &lt;a href=&#34;https://twitter.com/cloud9trt/&#34;&gt;Ravitheja Tetali&lt;/a&gt;, &lt;a href=&#34;http://baali.muse-amuse.in/&#34;&gt;Shantanu Choudhary&lt;/a&gt;, &lt;a href=&#34;https://twitter.com/vandith&#34;&gt;Vandith PSR&lt;/a&gt;, &lt;a href=&#34;https://varunrn.wordpress.com/&#34;&gt;Varun&#xA;Rangarajan&lt;/a&gt; and Vivek Krishnaswamy for reading drafts of this post and giving&#xA;helpful suggestions.&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Python&#39;s globals</title>
      <link>https://punchagan.muse-amuse.in/blog/python-globals/</link>
      <pubDate>Sun, 29 Jul 2018 09:09:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/python-globals/</guid>
      <description>&lt;h2 id=&#34;tl-dr&#34;&gt;TL; DR&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The &lt;code&gt;global&lt;/code&gt; statement is a parser directive to indicate that &lt;code&gt;globals&lt;/code&gt; are&#xA;being used. When looking up &lt;code&gt;globals&lt;/code&gt;, the &lt;code&gt;globals&lt;/code&gt; of the current scope are&#xA;fetched.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Python&amp;rsquo;s &lt;code&gt;globals&lt;/code&gt; are really just module-level.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Every function has an associated &lt;code&gt;__globals__&lt;/code&gt; dictionary, which is the &lt;strong&gt;same&#xA;as the module&amp;rsquo;s &lt;code&gt;__dict__&lt;/code&gt; for the module where it was defined&lt;/strong&gt;. This&#xA;&lt;code&gt;__globals__&lt;/code&gt; dict is the name-space that is looked up when trying to fetch&#xA;&lt;code&gt;globals&lt;/code&gt; within a function.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Avoid globals to make it easier to test functions&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;motivation&#34;&gt;Motivation&lt;/h2&gt;&#xA;&lt;p&gt;During a mentoring session I was doing recently, we ran into a problem with&#xA;&lt;code&gt;globals&lt;/code&gt; in Python.&lt;/p&gt;&#xA;&lt;p&gt;Here is a toy example to describe what we were seeing.&lt;/p&gt;&#xA;&lt;p&gt;We had code in a module &lt;code&gt;foo.py&lt;/code&gt; where the function &lt;code&gt;f&lt;/code&gt; was using a global&#xA;defined in &lt;code&gt;main&lt;/code&gt;, and we were trying to write tests for the function &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# foo.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;global&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Running this file &lt;code&gt;foo.py&lt;/code&gt; prints out &lt;code&gt;5&lt;/code&gt; as expected.&lt;/p&gt;&#xA;&lt;p&gt;We would now like to import &lt;code&gt;f&lt;/code&gt; into a different module and use it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;running-f-in-a-different-module&#34;&gt;Running &lt;code&gt;f&lt;/code&gt; in a different module&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# bar.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;foo&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Running the module &lt;code&gt;bar.py&lt;/code&gt; gives us a &lt;code&gt;NameError&lt;/code&gt;, as expected. The name &lt;code&gt;a&lt;/code&gt;&#xA;was defined in the &lt;code&gt;main&lt;/code&gt; in &lt;code&gt;foo.py&lt;/code&gt; which is never being run when the code is&#xA;imported in &lt;code&gt;bar.py&lt;/code&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;Traceback&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;most&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;recent&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;File&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;bar.py&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;module&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;File&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;bar.py&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;File&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;foo.py&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;ne&#34;&gt;NameError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;global&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;defined&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;setting-a-global-value-for-a&#34;&gt;Setting a global value for &lt;code&gt;a&lt;/code&gt;&lt;/h2&gt;&#xA;&lt;p&gt;We&amp;rsquo;d like to be able to run &lt;code&gt;f&lt;/code&gt; without running &lt;code&gt;main&lt;/code&gt; and the first fix that&#xA;comes to mind is to set the value of &lt;code&gt;a&lt;/code&gt; in &lt;code&gt;bar&lt;/code&gt;, and let &lt;code&gt;f&lt;/code&gt; use that.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# bar.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;global&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Surprise! Nothing changes.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;Traceback&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;most&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;recent&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;File&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/tmp/example/bar.py&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;13&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;module&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;File&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/tmp/example/bar.py&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;File&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/tmp/example/foo.py&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;ne&#34;&gt;NameError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;global&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;defined&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Why doesn&amp;rsquo;t this work?!&lt;/p&gt;&#xA;&lt;h2 id=&#34;function-globals-and-the-global-statement&#34;&gt;Function &lt;code&gt;__globals__&lt;/code&gt; and the &lt;code&gt;global&lt;/code&gt; statement&lt;/h2&gt;&#xA;&lt;p&gt;The &lt;code&gt;global&lt;/code&gt; statement is a directive to the parser, that specifies that the&#xA;variable being assigned to is a global variable.&lt;/p&gt;&#xA;&lt;p&gt;This can be seen by looking at the disassembled code for &lt;code&gt;f&lt;/code&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;dis&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;foo&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;dis&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;5&lt;/span&gt;           &lt;span class=&#34;err&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;LOAD_GLOBAL&lt;/span&gt;              &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;err&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;LOAD_GLOBAL&lt;/span&gt;              &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;err&#34;&gt;4&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;CALL_FUNCTION&lt;/span&gt;            &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;err&#34;&gt;6&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;POP_TOP&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;err&#34;&gt;8&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;LOAD_CONST&lt;/span&gt;               &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           &lt;span class=&#34;err&#34;&gt;10&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;RETURN_VALUE&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;globals&lt;/code&gt; for the current frame are fetched, and the value is updated in that&#xA;dict. Each function in Python has an associated &lt;code&gt;__globals__&lt;/code&gt; dict which is a&#xA;reference to that module&amp;rsquo;s &lt;code&gt;__dict__&lt;/code&gt; in which the function was defined. So, in&#xA;the case where we try to set the &lt;code&gt;a = 4&lt;/code&gt; in &lt;code&gt;bar.main&lt;/code&gt;, the &lt;code&gt;main&lt;/code&gt; function&amp;rsquo;s&#xA;&lt;code&gt;__globals__&lt;/code&gt; dict is being updated.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# bar.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;global&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__globals__&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;keys&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__globals__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;dict_keys&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;__name__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__doc__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__package__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__loader__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__spec__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__annotations__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__builtins__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__file__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__cached__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;f&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;dis&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;main&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see &lt;code&gt;a&lt;/code&gt; is being set to &lt;code&gt;4&lt;/code&gt;, but &lt;code&gt;f&lt;/code&gt; still doesn&amp;rsquo;t see value, since&#xA;it has it&amp;rsquo;s own &lt;code&gt;__globals__&lt;/code&gt; dictionary. Printing the &lt;code&gt;globals&lt;/code&gt; dictionary for&#xA;&lt;code&gt;f&lt;/code&gt; should make that clear.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;foo&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__globals__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the variable &lt;code&gt;a&lt;/code&gt; was declared in the module &lt;code&gt;foo&lt;/code&gt; outside of any of the&#xA;functions, it would be in &lt;code&gt;f&lt;/code&gt;&amp;rsquo;s &lt;code&gt;__globals__&lt;/code&gt; dict when it is imported, and&#xA;hence the name error would go away, but setting it still would not work.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# foo.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;global&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# bar.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;foo&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;global&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Running &lt;code&gt;bar.py&lt;/code&gt; would print the value &lt;code&gt;3&lt;/code&gt; which has been defined in &lt;code&gt;foo.py&lt;/code&gt;,&#xA;and not &lt;code&gt;4&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;updating-globals&#34;&gt;Updating &lt;code&gt;__globals__&lt;/code&gt;&lt;/h2&gt;&#xA;&lt;p&gt;To update the value of &lt;code&gt;a&lt;/code&gt; for &lt;code&gt;f&lt;/code&gt;, we could modify it&amp;rsquo;s &lt;code&gt;globals&lt;/code&gt; dict.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# bar.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;foo&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__globals__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;module-dict-and-monkey-patching&#34;&gt;Module &lt;code&gt;__dict__&lt;/code&gt; and monkey-patching&lt;/h2&gt;&#xA;&lt;p&gt;As mentioned previously, a function&amp;rsquo;s &lt;code&gt;__globals__&lt;/code&gt; dict is a reference to the&#xA;module&amp;rsquo;s &lt;code&gt;__dict__&lt;/code&gt; for the module where the function was defined. So, we could&#xA;achieve the same result as above by updating &lt;code&gt;foo.__dict__&lt;/code&gt;. And setting an&#xA;attribute on the module &lt;code&gt;foo&lt;/code&gt; is the same as updating this dict.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# bar.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;foo&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;foo&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;foo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you have used a library like &lt;code&gt;mock&lt;/code&gt; to patch some code while running tests,&#xA;this is essentially what is happening. The &lt;code&gt;target&lt;/code&gt; module&amp;rsquo;s dict is looked up&#xA;for the specified object/function and replaced with a mock object.&lt;/p&gt;&#xA;&lt;h2 id=&#34;use-an-argument-to-make-it-testable&#34;&gt;Use an argument to make it testable&lt;/h2&gt;&#xA;&lt;p&gt;The function &lt;code&gt;f&lt;/code&gt; would&amp;rsquo;ve been much easier to test, if it took &lt;code&gt;a&lt;/code&gt; as an&#xA;argument, instead of using a global value. This functional approach would make&#xA;the code easier to reason about too.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# foo.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# bar.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;foo&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Thanks to &lt;a href=&#34;https://in.linkedin.com/in/akshaya-mukundhan&#34;&gt;Akshaya&lt;/a&gt; and &lt;a href=&#34;http://baali.muse-amuse.in&#34;&gt;Shantanu&lt;/a&gt; for reviewing this blog post.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Assist time</title>
      <link>https://punchagan.muse-amuse.in/blog/assist-time/</link>
      <pubDate>Tue, 14 Jun 2016 00:00:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/assist-time/</guid>
      <description>&lt;p&gt;I sometimes hang out on &lt;a href=&#34;http://webchat.freenode.net/?channels=%2523org-mode&#34;&gt;#org-mode&lt;/a&gt; or &lt;a href=&#34;http://webchat.freenode.net/?channels=%2523nikola&#34;&gt;#nikola&lt;/a&gt; and answer questions. I usually am&#xA;not able to answer off the top of my head and I look up docs or dig through the&#xA;code.  Sometimes, we find ready-made documented answers, but other times we end&#xA;up contributing some documentation, filing an issue, submitting a patch or&#xA;hacking up something for that super-special use-case.&lt;/p&gt;&#xA;&lt;p&gt;Until now, I looked at this time as IRC time, which loosely translates to&#xA;distraction time.  But, I&amp;rsquo;m usually learning about the tools I use a little bit&#xA;more. Even when I&amp;rsquo;m not, I&amp;rsquo;m helping someone do something they want to do.&#xA;Sometimes empowering them to fix future problems on their own.  And indirectly&#xA;making the user community a wee-bit happier, and possibly the software a tiny&#xA;bit better.&lt;/p&gt;&#xA;&lt;p&gt;This isn&amp;rsquo;t limited just to helping someone on IRC.  Helping out a co-worker do&#xA;something that they are new to, or just adding a comment or editing a&#xA;Stack-overflow answer may end up in the &amp;ldquo;distraction time&amp;rdquo; bin, just because&#xA;you weren&amp;rsquo;t doing something on your TODO list.  It needn&amp;rsquo;t be.&lt;/p&gt;&#xA;&lt;p&gt;Taking cue from &lt;a href=&#34;https://en.wikipedia.org/wiki/Assist_(football)&#34;&gt;scorers in Football&lt;/a&gt;, I decided to call this time &lt;strong&gt;assist time&lt;/strong&gt;&#xA;and to try to start seeing this time as (semi-)productive. Naming helps.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Reading-time based scheduling</title>
      <link>https://punchagan.muse-amuse.in/blog/reading-time-based-scheduling/</link>
      <pubDate>Mon, 06 Jun 2016 00:00:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/reading-time-based-scheduling/</guid>
      <description>&lt;p&gt;I had posted a link to an poem written on Medium on a Slack channel that I use&#xA;with friends.  A friend said that she liked the fact that the Slack article&#xA;preview had the reading time from Medium in it.  She could decide whether or&#xA;not she wanted to read the poem or any other article at that moment.&lt;/p&gt;&#xA;&lt;p&gt;This gave me the idea for a reading time extension for my &lt;a href=&#34;https://www.chromium.org/getting-involved/download-chromium&#34;&gt;browser&lt;/a&gt;, or my &lt;a href=&#34;https://github.com/skeeto/elfeed&#34;&gt;feed&#xA;reader&lt;/a&gt; or my &lt;a href=&#34;https://pinboard.in&#34;&gt;bookmarks&lt;/a&gt; &amp;ndash; my reading list.  The first version should be able to&#xA;compute or extract the reading time for an article or a tab in my browser, and&#xA;index them.  I want to be able to specify the amount of time I will be able to&#xA;spend reading, and be presented with something from my reading list.  I think&#xA;this would help with scheduling the reading of longer articles, and also to&#xA;actually help me get through my reading list.&lt;/p&gt;&#xA;&lt;p&gt;Reading time estimates that use heuristics based on word-count may not really&#xA;work, and may do &lt;a href=&#34;https://medium.com/@fchimero/this-should-only-take-a-minute-or-four-probably-e38bb7bf2adf#.mvkd09m6m&#34;&gt;more harm than good&lt;/a&gt;.  But, it may still be worth a try to see&#xA;if it helps my reading habits in any way.  A quick search pointed me to &lt;a href=&#34;https://chrome.google.com/webstore/detail/readism-article-reading-t/bmiolhceebkeljaikojgcoeefblcihje&#34;&gt;this&#xA;extension&lt;/a&gt;, that can give the reading time for any page but doesn&amp;rsquo;t really do&#xA;what I want.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Stepping AFK</title>
      <link>https://punchagan.muse-amuse.in/blog/stepping-afk/</link>
      <pubDate>Fri, 03 Jun 2016 00:00:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/stepping-afk/</guid>
      <description>&lt;p&gt;In the past few weeks, I noticed three instances where I was forced to take a&#xA;break exactly when I was ready to jump in and write some code to fix a bug or&#xA;add a small feature.  I had to step out of the house and take a walk to meet&#xA;someone, etc.&lt;/p&gt;&#xA;&lt;p&gt;I ended up getting ideas during the walks, which significantly changed and&#xA;simplified how I would&amp;rsquo;ve implemented things, if not for those breaks.  Even if&#xA;I did end up zeroing down to those solutions, I am pretty sure it would&amp;rsquo;ve&#xA;taken a couple of not-so-good attempts and much longer than it did.&lt;/p&gt;&#xA;&lt;p&gt;Context switches are usually considered to be &lt;a href=&#34;http://heeris.id.au/2013/this-is-why-you-shouldnt-interrupt-a-programmer/&#34;&gt;expensive for programmers&lt;/a&gt;, but&#xA;taking a break at the exact time when I had all the required context loaded&#xA;into my head seemed to help. It was also probably helpful that I was taking a&#xA;walk, and there wasn&amp;rsquo;t really any other inputs or outputs competing for the&#xA;space in my head.&lt;/p&gt;&#xA;&lt;p&gt;This got me thinking about doing this more deliberately &amp;ndash; I&amp;rsquo;d love to hear&#xA;about any experiences or any experiments any of you have done with this.  Also,&#xA;I&amp;rsquo;m reminded of Rich Hickey&amp;rsquo;s &lt;a href=&#34;https://www.youtube.com/watch?v=f84n5oFoZBc&#34;&gt;Hammock Driven Development&lt;/a&gt; talk and I wonder if&#xA;this is a smaller/different version of it, and makes me want to try out the&#xA;things he suggests more deliberately.  If any of you has thoughts and&#xA;suggestions, I&amp;rsquo;d love to hear from you!&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Thinking about Data Ethics</title>
      <link>https://punchagan.muse-amuse.in/blog/thinking-about-data-ethics/</link>
      <pubDate>Wed, 25 May 2016 00:00:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/thinking-about-data-ethics/</guid>
      <description>&lt;p&gt;Earlier this month, a researcher made a dataset containing the profiles of about&#xA;70,000 users public. He didn&amp;rsquo;t really see a problem in doing this because he&#xA;felt he was only presenting &lt;a href=&#34;https://twitter.com/KirkegaardEmil/status/730449904909324289&#34;&gt;already publicly available&lt;/a&gt; data in a more usable&#xA;form. was only presenting it in a more usable form.&lt;/p&gt;&#xA;&lt;p&gt;Yesterday, I came across this quote in the very first chapter of &lt;a href=&#34;https://twitter.com/allendowney&#34;&gt;Allen Downey&lt;/a&gt;&amp;rsquo;s&#xA;book &lt;a href=&#34;http://greenteapress.com/thinkstats2/index.html&#34;&gt;Think Stats&lt;/a&gt; which I liked a lot, and reminded me of this incident.&lt;/p&gt;&#xA;&lt;figure&gt;&lt;img src=&#34;//c2.staticflickr.com/8/7193/26969166130_58e4865f47_b.jpg&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;p&gt;I hadn&amp;rsquo;t looked at the OKCupid data release and the discussion around it much,&#xA;but I went back and read &lt;a href=&#34;https://points.datasociety.net/okcupid-data-release-fiasco-ba0388348cd#.u8xxlkqsv&#34;&gt;this article&lt;/a&gt; by a social media researcher who thinks a&#xA;lot about these things.&lt;/p&gt;&#xA;&lt;p&gt;She puts forth a lot of interesting ideas to think about ethics. Some things&#xA;that stood out to me are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Ask yourself how the person whose data you are using feels about the data.&lt;/li&gt;&#xA;&lt;li&gt;Taking a &amp;lsquo;what if&amp;rsquo; impact approach to thinking about data and ethics.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Also, you needn&amp;rsquo;t really call yourself a researcher to be actually doing&#xA;experiments with (or &lt;a href=&#34;http://www.npr.org/2016/05/17/478266839/this-is-your-brain-on-uber&#34;&gt;analyzing&lt;/a&gt;) &amp;ldquo;big-data&amp;rdquo; and discovering and putting out facts&#xA;that have an impact &amp;ndash; however big or small. You should really go read the&#xA;article, whether or not you are a researcher using data.&lt;/p&gt;&#xA;&lt;p&gt;Incidentally, there is a meet-up on &lt;a href=&#34;http://www.meetup.com/DataKind-Bangalore/events/231310093/&#34;&gt;Data Ethics&lt;/a&gt; this weekend in Bangalore. I&amp;rsquo;m&#xA;excited to learn and think more about this, and talk to others who care.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Level-up Tools</title>
      <link>https://punchagan.muse-amuse.in/blog/level-up-tools/</link>
      <pubDate>Mon, 23 May 2016 00:00:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/level-up-tools/</guid>
      <description>&lt;p&gt;Thanks to a &lt;a href=&#34;https://twitter.com/baali_&#34;&gt;friend&lt;/a&gt; I got an upgrade to our still-being-setup kitchen.  I now&#xA;have a non-stick pan along with a few more new additions.  I would previously&#xA;use a bowl that people usually use to boil &lt;a href=&#34;http://img6a.flixcart.com/image/pot-pan/t/s/8/aluminium-polish-top-jk-vallabhdas-400x400-imae7w9y9ehukjhx.jpeg&#34;&gt;milk&lt;/a&gt; etc. for making whatever I did.&#xA;The non-stick pan feels so great!  It has made it a lot simpler to make some of&#xA;the things I used to, because its non-stick. And it has vastly expanded the&#xA;possibilities of things I can make, by virtue of being flat and wide based.&#xA;The pan is such a great addition to my kitchen paraphernalia, and it adds a new&#xA;dimension to the kind of things I can make.  I&amp;rsquo;m not here to write a user&#xA;review for it, though.&lt;/p&gt;&#xA;&lt;p&gt;What are such tools in other things that you do, that drastically changed the&#xA;way you did something, or added a new dimension to the kinds of things you&#xA;could do, tools that make you feel like you have a new super-power?  Learning&#xA;to write Python (after starting off with C) seemed to give me so much power&#xA;allowing me to focus on the problem, rather than fussing over the low level&#xA;details. Sasha mentions in &lt;a href=&#34;http://sasha.wtf/anki-post-1/&#34;&gt;this post&lt;/a&gt; how using a Spaced Repetition System like&#xA;&lt;a href=&#34;https://ankiweb.net/&#34;&gt;Anki&lt;/a&gt; drastically improved her efficiency because she could focus on thinking&#xA;about higher level things rather than trying to recall or search for what&#xA;method or function to use to do something.&lt;/p&gt;&#xA;&lt;p&gt;What are some such level-up tools for you? Is there a systematic approach to&#xA;discovering tools?&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Tedium in work-flows</title>
      <link>https://punchagan.muse-amuse.in/blog/tedium-in-work-flows/</link>
      <pubDate>Thu, 19 May 2016 00:00:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/tedium-in-work-flows/</guid>
      <description>&lt;p&gt;I use &lt;a href=&#34;http://getnikola.com&#34;&gt;Nikola&lt;/a&gt; for generating this blog. When creating a new post, it prompts for&#xA;a title, and creates a file for the post.&lt;/p&gt;&#xA;&lt;p&gt;Often I&amp;rsquo;m starting off with only a vague idea that needs to be fleshed out&#xA;before it can be published (or discarded). It is quite difficult to come up&#xA;with a title at this stage. I just want to start a draft and write things down!&lt;/p&gt;&#xA;&lt;p&gt;I could use a &amp;ldquo;draft-title&amp;rdquo; and change it after finishing a post, but this&#xA;feels tedious &amp;ndash; requires 3 steps &amp;ndash; change the title, post filename and post&#xA;slug.  The last two steps are optional, really, but I feel they are important&#xA;especially when the original title is very different from the new one.&lt;/p&gt;&#xA;&lt;p&gt;Being forced to come up with a title before anything else, feels tedious and,&#xA;adds to the effort required to start off a new post.  I shouldn&amp;rsquo;t really be&#xA;worrying about the effort required to change the title of an unwritten post,&#xA;but it happens subconsciously.&lt;/p&gt;&#xA;&lt;p&gt;To work around this, I now have a &amp;ldquo;re-title utility&amp;rdquo; in my editor that takes&#xA;care of all the tedious details.  I can start with a random title, like&#xA;Draft-1, and change it when I&amp;rsquo;m done with the post.  I feel this is going to&#xA;lead to a lot more drafts, at the very least, if not published posts.&lt;/p&gt;&#xA;&lt;p&gt;Another work-flow related thing I came across recently was @Malabarba&amp;rsquo;s &lt;a href=&#34;https://github.com/clojure-emacs/cider/issues/1717#issue-150907043&#34;&gt;issue&lt;/a&gt;&#xA;on CIDER (an IDE for Clojure in Emacs).  The &lt;a href=&#34;http://www.braveclojure.com/getting-started/#Using_the_REPL&#34;&gt;REPL&lt;/a&gt; takes a while to startup and&#xA;this caused him to not use CIDER for running tests, if there wasn&amp;rsquo;t an already&#xA;open REPL.&lt;/p&gt;&#xA;&lt;p&gt;The tedium that people feel effects how they use the tool.  Not surprisingly,&#xA;making tedious-feeling tasks a breeze with the tool also effects how and how&#xA;much they use it.  Subtle variations in a work-flow could make or break it.&#xA;How do you discover such potential work-flow make-or-break-ers? I think, these&#xA;things would help:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Use the tool yourself (dog-food)&lt;/li&gt;&#xA;&lt;li&gt;Talk to (or watch!) people using your tool&lt;/li&gt;&#xA;&lt;li&gt;Look at work-flows in other similar tools&lt;/li&gt;&#xA;&lt;li&gt;Thinking explicitly about various scenarios and simplifying or improving&#xA;work-flows&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I&amp;rsquo;d love to hear examples of this, and any ideas or thoughts you may have on&#xA;identifying and fixing such things!&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Error messages and new users</title>
      <link>https://punchagan.muse-amuse.in/blog/error-messages-and-new-users/</link>
      <pubDate>Tue, 17 May 2016 00:00:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/error-messages-and-new-users/</guid>
      <description>&lt;p&gt;I was helping a friend of mine setup &lt;a href=&#34;http://jajoosam.github.io&#34;&gt;his blog&lt;/a&gt; and we were trying to use &lt;a href=&#34;http://hexo.io&#34;&gt;Hexo&lt;/a&gt; &amp;ndash;&#xA;a static site generator.  We chose a Javascript based tool since he&amp;rsquo;s trying to&#xA;learn Javascript.  I skimmed through active Javascript projects in &lt;a href=&#34;https://staticsitegenerators.net&#34;&gt;this list&lt;/a&gt;&#xA;and finally zeroed down upon Hexo based on its popularity.  I promised to help&#xA;my friend to set this up, but he first tried to do it on his own and got back&#xA;to me after an hour or so, quite frustrated and almost on the verge of giving&#xA;up setting it up.  I didn&amp;rsquo;t expect this from a tool that had so many stars,&#xA;forks, plugins and so much active development.&lt;/p&gt;&#xA;&lt;p&gt;We finally got it working, but we found that the error messages were horrendous&#xA;&amp;ndash; even for someone who has been using free and open-source tools for a while&#xA;now.  Printing out errors from compiler or interpreter directly along with the&#xA;stack trace is almost always the worst thing to do for a tool/utility (as&#xA;opposed to an API or library).  The stack trace is definitely useful, for&#xA;developers trying to build upon or improve your tool.  Have a debug or&#xA;development mode where developers can get all the information they need.&lt;/p&gt;&#xA;&lt;p&gt;If you care about your users, especially new users, make sure you spend&#xA;sufficient time on showing human-readable messages. If possible list the&#xA;possible causes for every error along with tips for troubleshooting.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>How I learnt to use Emacs&#39; profiler</title>
      <link>https://punchagan.muse-amuse.in/blog/how-i-learnt-to-use-emacs-profiler/</link>
      <pubDate>Sat, 03 Jan 2015 02:01:17 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/how-i-learnt-to-use-emacs-profiler/</guid>
      <description>&lt;p&gt;I learnt to use Emacs&amp;rsquo; profiler yesterday, after many hours of yak-shaving,&#xA;trying to get &lt;a href=&#34;https://github.com/novoid/Memacs&#34;&gt;Memacs&lt;/a&gt; working.  Memacs is a &lt;a href=&#34;http://en.wikipedia.org/wiki/Memex&#34;&gt;memory extension&lt;/a&gt; system for Emacs&#xA;written by Karl Voit, that I have been meaning to try out for a long time now.&#xA;Seeing lots of review posts at the turn of the year and watching Karl&amp;rsquo;s recent&#xA;&lt;a href=&#34;http://emacslife.com/emacs-chats/chat-karl-voit.html&#34;&gt;Emacs Chat with Sacha Chua&lt;/a&gt; pushed me to try and finally set it up.&lt;/p&gt;&#xA;&lt;p&gt;I started writing a &lt;a href=&#34;https://github.com/punchagan/Memacs/blob/chrome/memacs/chromium.py&#34;&gt;module&lt;/a&gt; to create a Memacs file &amp;ndash; an org archive file &amp;ndash;&#xA;from my browser history.  It was pretty easy to write, and I had it spitting&#xA;out a huge file with 22k entries after about a couple of hours of work.  Then I&#xA;excitedly pulled up my agenda, and turned on the option to view archived&#xA;entries, only to be super-disappointed.  It turned out to be extremely slow!&#xA;Actually, the agenda never came up with the 22k entries file that I had. At&#xA;least not in 5 or so minutes, before I got impatient.  The performance was&#xA;unacceptable even when I reduced it to 5k entries.&lt;/p&gt;&#xA;&lt;p&gt;I was pretty sure it wasn&amp;rsquo;t that slow for Karl in his &lt;a href=&#34;https://www.youtube.com/watch?v=SaKPr4J0K2I#t=999&#34;&gt;demo&lt;/a&gt; and &lt;a href=&#34;https://twitter.com/punchagan/status/550723377871065088&#34;&gt;tweeted&lt;/a&gt; to him,&#xA;asking for a workaround. Meanwhile, I looked at his dot-emacs, but wasn&amp;rsquo;t able&#xA;to dig out what was needed to speed up things. He confirmed that his&#xA;performance was way better than what I was getting.&lt;/p&gt;&#xA;&lt;p&gt;First, I ruled out the possibility of it being because of the SSD, since&#xA;clearly my CPU usage was peaking, and the task was CPU bound and not I/O.&#xA;Next, I tried using the same file on a different machine (with a different&#xA;version of Emacs and org-mode), and it worked blazingly fast.  So, it was&#xA;either the version of Emacs or org-mode that I was using.&lt;/p&gt;&#xA;&lt;p&gt;I should have stopped, thought clearly, and started experimenting with org&#xA;version, but hindsight is 20-20.  I tried Ubuntu&amp;rsquo;s pre-built Emacs and agendas&#xA;were fast!  I suspected my Emacs build, since I recently started building Emacs&#xA;from git.  I built two or three other versions of Emacs, and wasted a lot of&#xA;time, before realizing that I wasn&amp;rsquo;t using the org-mode source bundled inside&#xA;Emacs for the tests, and there were two &amp;ldquo;independent&amp;rdquo; variables.&lt;/p&gt;&#xA;&lt;p&gt;Finally, I began bisecting org-mode&amp;rsquo;s source and found that all hell broke&#xA;loose with an &lt;a href=&#34;http://orgmode.org/w/?p=org-mode.git;a=commitdiff;h=b88c5464db2cb0d90d4f30e43b5e08d2b1c1fcea;hp=8cc4e09950594b2abec2502e9218318570595ac5&#34;&gt;inconspicuous change&lt;/a&gt; around release 8.2.6.  It turns out that&#xA;org-overview was broken before this, and collapsing all the trees in a newly&#xA;opened org-buffer (default option) wasn&amp;rsquo;t working. Once this bug was fixed,&#xA;opening huge org files would slow down by a great deal, in turn causing agenda&#xA;generation to be unbearably slow.&lt;/p&gt;&#xA;&lt;p&gt;All I had to do was add a &lt;code&gt;#+STARTUP: showeverything&lt;/code&gt; to the top of the file.&#xA;This speeded up things by about 50 times!  It turns out, I later found out,&#xA;that all of this is documented on &lt;a href=&#34;http://orgmode.org/worg/agenda-optimization.html&#34;&gt;Worg&lt;/a&gt;. I did try a few search engine queries,&#xA;but sadly none of them brought this up.  Adding the following to my config,&#xA;speeded up agenda generation by about 150-200 times!&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;setq&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;org-agenda-inhibit-startup&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;;; ~50x speedup&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;setq&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;org-agenda-use-tag-inheritance&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;;; 3-4x speedup&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the course of all this debugging, I learnt how to use Emacs&amp;rsquo; profiler.  The&#xA;profile reports along with git bisect, eventually helped me figure out what the&#xA;problem was.&lt;/p&gt;&#xA;&lt;p&gt;To profile the CPU usage, all you have to do is add a call like&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;profiler-start&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;&amp;#39;cpu&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;;; or M-x profiler-start&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;at the place where you wish to start it.  Emacs will then start collecting&#xA;information about where time is being spent, by sampling every&#xA;&lt;code&gt;sampling-interval&lt;/code&gt; seconds (default 10^6 nanoseconds = 1 milli second).&lt;/p&gt;&#xA;&lt;p&gt;You can view the information being collected, at any point of time using&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;profiler-report&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;;; or M-x profiler-report&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The report is a nice, interactive tree with the percentage of time spent in&#xA;each call. You can stop profiling by calling &lt;code&gt;(profiler-stop)&lt;/code&gt;.  If you have&#xA;more than one report, you can compare them by hitting &lt;code&gt;=&lt;/code&gt; in one of the report&#xA;buffers.  I&amp;rsquo;m definitely going to use this for other things! (like speeding up&#xA;my startup?)&lt;/p&gt;&#xA;&lt;p&gt;Now that I have Memacs working with reasonably fast agenda views, I&amp;rsquo;m looking&#xA;forward to collecting as much personal information as I can!  Thanks Karl for&#xA;writing Memacs.  I am going to be a pretty heavy user, I think!  There seem to&#xA;be a few rough edges, though, and I hope to help smoothen them out a little&#xA;bit, over the next few weeks.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Martin Fowler on Refactoring @ RubyRogues</title>
      <link>https://punchagan.muse-amuse.in/blog/martin-fowler-on-refactoring-rubyrogues/</link>
      <pubDate>Sat, 25 Oct 2014 00:00:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/martin-fowler-on-refactoring-rubyrogues/</guid>
      <description>&lt;p&gt;I stumbled on a &lt;a href=&#34;http://rubyrogues.com/178-rr-book-club-refactoring-ruby-with-martin-fowler/&#34;&gt;Ruby Rogues podcast&lt;/a&gt; yesterday, which had &lt;a href=&#34;http://martinfowlwer.com&#34;&gt;Martin Fowler&lt;/a&gt; as the&#xA;guest.  I really enjoyed the discussion on Refactoring (the noun, the verb and&#xA;the book!)&lt;/p&gt;&#xA;&lt;p&gt;Martin clarified in the podcast that refactoring (the verb/process) is a&#xA;sequence of very small refactorings, while you keep making sure that you can&#xA;run the test suite always.  A refactoring (noun) is a change where you change&#xA;the structure of the code without any externally observable changes, with the&#xA;intent of making it easier to understand and cheaper to change in future.&lt;/p&gt;&#xA;&lt;p&gt;I also really liked the metaphor of a &amp;lsquo;healthy code base&amp;rsquo;.  Refactoring is,&#xA;then, the process of keeping healthy &amp;ndash; exercise, speaking metaphorically.  You&#xA;can stack up all the exercise you need to do, until you get really unfit.&#xA;Refactoring, similarly, needs to be done regularly, to keep the code base&#xA;healthy.  This lets you go faster, in the future.&lt;/p&gt;&#xA;&lt;p&gt;I also really liked the advise about trying to push back the mental contexts&#xA;you build, while trying to debug/understand some code that is not very clear,&#xA;by refactoring the code to make it clearer.  Code needn&amp;rsquo;t be one big chunk of&#xA;cryptographic text.  Code is writing.  It should be clear and understandable.&#xA;Or, at least we should strive to make it so!&lt;/p&gt;&#xA;&lt;p&gt;The discussion, as always on this podcast, was very lively, pleasant and&#xA;enjoyable! Enjoy!&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Recurse Center, 2014-07-07</title>
      <link>https://punchagan.muse-amuse.in/recurse-center/recurse-center-2014-07-07/</link>
      <pubDate>Tue, 08 Jul 2014 10:07:20 -0400</pubDate>
      <guid>https://punchagan.muse-amuse.in/recurse-center/recurse-center-2014-07-07/</guid>
      <description>&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;As preparation for a one-on-one this week with one of the facilitators, I was&#xA;wondering if I was really getting better as a programmer, by doing what I am&#xA;doing.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I have heard at numerous places that reading and reflection are keys to&#xA;getting better. I feel like I haven&amp;rsquo;t been giving these things much attention&#xA;in the past couple of weeks. I don&amp;rsquo;t catch up on reading all the awesome&#xA;reading material shared on Zulip and I switched from writing this blog post&#xA;first thing in the morning, to any-time-after-lunch. I don&amp;rsquo;t think this&#xA;worked out very well. Writing the post worked as a way to reflect on what I&#xA;had done yesterday, and what I should be doing today. So, I am back to&#xA;writing the blog post, first thing in the morning!&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Yesterday, I worked on indexing the Python sources in a way that the&#xA;inspection code can look up, later.  During this process, I found that my&#xA;code to use libclang&amp;rsquo;s AST wasn&amp;rsquo;t generic enough, and I had to clean it up to&#xA;be able to extract useful information from any file in the &lt;code&gt;cpython&lt;/code&gt; sources.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;We also got to attend a super-awesome talk by &lt;a href=&#34;http://words.steveklabnik.com/&#34;&gt;Steve Labnik&lt;/a&gt;! He talked about&#xA;his progression from being an application developer, to writing libraries, to&#xA;working on languages (as a professional developer). He made a lot of&#xA;interesting and inspiring points during his talk.  Some of those that stuck&#xA;with me are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;None of these is particularly harder than any of the other. Depending on&#xA;each person&amp;rsquo;s personality, or the way their brain works, they are good at&#xA;doing one or the other.&lt;/li&gt;&#xA;&lt;li&gt;Getting good at programming is a matter of showing up, more than about the&#xA;&amp;ldquo;genes&amp;rdquo;.  He repeated quite a few times that he disliked the idea of &amp;ldquo;baby&#xA;hacker&amp;rdquo;, and left out the story of his childhood and college programming&#xA;days! I&amp;rsquo;m totally stealing his idea of meeting every saturday at 1pm, with&#xA;a bunch of friends and working until it was 10pm or so, when they could get&#xA;cheap beer and food!  And he did this all through his college!  It is&#xA;interesting that this idea is so similar to Hacker School!&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;It was a very enjoyable and inspiring talk on the whole.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The plan for today is to actually have the parsed information dumped into&#xA;some persistent format, and modify the inspect code to actually use it.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I will also be pairing with Kyle for a few hours on working through some of&#xA;&lt;a href=&#34;http://mitpress.mit.edu/books/audio-programming-book&#34;&gt;http://mitpress.mit.edu/books/audio-programming-book&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Best Practices for Scientific Computing</title>
      <link>https://punchagan.muse-amuse.in/blog/best-practices-for-scientific-computing/</link>
      <pubDate>Mon, 24 Dec 2012 00:00:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/best-practices-for-scientific-computing/</guid>
      <description>&lt;p&gt;Shantanu and I gave a short talk titled &amp;ldquo;Software Carpentry for&#xA;Scientists&amp;rdquo; for the graduate students of Chemical Engineering&#xA;department, IISc, this Friday.  We gave a short introduction to&#xA;Git, TDD, Numpy/Scipy, etc and mentioned a few things from Greg&#xA;Wilson et al&amp;rsquo;s paper.&lt;/p&gt;&#xA;&lt;p&gt;I promised to revert to them with links to a few resources.  I&#xA;figured it would be more beneficial, if I just put it in a&#xA;publicly available place.&lt;/p&gt;&#xA;&lt;p&gt;A summary of the paper by Greg Wilson et. al., is below.&lt;/p&gt;&#xA;&lt;h2 id=&#34;useful-resources&#34;&gt;Useful resources&lt;/h2&gt;&#xA;&lt;h3 id=&#34;software-carpentry&#34;&gt;Software Carpentry&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Paper by Greg Wilson et. al.&lt;/li&gt;&#xA;&lt;li&gt;Software Carpentry&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;git-and-version-control&#34;&gt;Git &amp;amp; version control&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://bit.ly/VfbOww&#34;&gt;http://bit.ly/VfbOww&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://karlagius.com/2009/01/09/version-control-for-the-masses/&#34;&gt;http://karlagius.com/2009/01/09/version-control-for-the-masses/&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://try.github.com&#34;&gt;http://try.github.com&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://betterexplained.com/articles/a-visual-guide-to-version-control/&#34;&gt;http://betterexplained.com/articles/a-visual-guide-to-version-control/&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://betterexplained.com/articles/intro-to-distributed-version-control-illustrated/&#34;&gt;http://betterexplained.com/articles/intro-to-distributed-version-control-illustrated/&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;tdd&#34;&gt;TDD&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://software-carpentry.org/4_0/test/index.html&#34;&gt;http://software-carpentry.org/4_0/test/index.html&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.google.co.in/?q=TDD+matlab&#34;&gt;https://www.google.co.in/?q=TDD+matlab&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;scipy&#34;&gt;SciPy&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://scipy-lectures.github.com&#34;&gt;http://scipy-lectures.github.com&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;python&#34;&gt;Python&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://docs.python.org/tutorial&#34;&gt;http://docs.python.org/tutorial&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;gui-tools-in-python&#34;&gt;GUI tools in Python&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://code.enthought.com/projects/traits/docs/html/tutorials/traits_ui_scientific_app.html&#34;&gt;http://code.enthought.com/projects/traits/docs/html/tutorials/traits_ui_scientific_app.html&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://docs.enthought.com/traits&#34;&gt;http://docs.enthought.com/traits&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://docs.enthought.com/traitsui&#34;&gt;http://docs.enthought.com/traitsui&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://docs.enthought.com/enaml&#34;&gt;http://docs.enthought.com/enaml&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;summary-of-paper-by-greg-wilson-et-dot-al-dot&#34;&gt;Summary of paper by Greg Wilson et. al.&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Write programs for people, not computers&#xA;&lt;ul&gt;&#xA;&lt;li&gt;a program should not require its readers to hold more than a&#xA;handful of facts in memory at once.&lt;/li&gt;&#xA;&lt;li&gt;names should be consistent, distinctive and meaningful.&lt;/li&gt;&#xA;&lt;li&gt;code style and formatting should be consistent.&lt;/li&gt;&#xA;&lt;li&gt;all aspects of software development should be broken down&#xA;into tasks roughly an hour long&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Automate repetitive tasks&#xA;&lt;ul&gt;&#xA;&lt;li&gt;rely on the computer to repeat tasks&lt;/li&gt;&#xA;&lt;li&gt;save recent commands in a file for re-use&lt;/li&gt;&#xA;&lt;li&gt;use a build to automate scientific work-flows&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Use the computer to record history&#xA;&lt;ul&gt;&#xA;&lt;li&gt;software tools should be used to track computational work&#xA;automatically.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Make incremental changes&#xA;&lt;ul&gt;&#xA;&lt;li&gt;work in small steps with frequent feedback and course&#xA;correction&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Use version control&#xA;&lt;ul&gt;&#xA;&lt;li&gt;use a version control system&lt;/li&gt;&#xA;&lt;li&gt;everything that has been created manually should be put in&#xA;version control&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Don&amp;rsquo;t repeat yourself (or others)&#xA;&lt;ul&gt;&#xA;&lt;li&gt;every piece of data must have a single authoritative&#xA;representation in the system&lt;/li&gt;&#xA;&lt;li&gt;code should be modularized rather than copied and pasted&lt;/li&gt;&#xA;&lt;li&gt;re-use code instead of rewriting it&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Plan for mistakes&#xA;&lt;ul&gt;&#xA;&lt;li&gt;add assertions to programs to check their operation&lt;/li&gt;&#xA;&lt;li&gt;use an off-the-shelf unit testing library&lt;/li&gt;&#xA;&lt;li&gt;use all available oracles when testing programs&lt;/li&gt;&#xA;&lt;li&gt;turn bugs into test cases&lt;/li&gt;&#xA;&lt;li&gt;use a symbolic debugger&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Optimize software only after it works correctly&#xA;&lt;ul&gt;&#xA;&lt;li&gt;use a profiler to identify bottlenecks&lt;/li&gt;&#xA;&lt;li&gt;write code in the highest-level language possible&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Document design and purpose, not mechanics&#xA;&lt;ul&gt;&#xA;&lt;li&gt;document interfaces and reasons, not implementations&lt;/li&gt;&#xA;&lt;li&gt;refactor code instead of explaining how it works&lt;/li&gt;&#xA;&lt;li&gt;embed the documentation for a piece of software in that software&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Collaborate&#xA;&lt;ul&gt;&#xA;&lt;li&gt;use pre-merge code reviews&lt;/li&gt;&#xA;&lt;li&gt;use pair programming when bringing someone new up to speed&#xA;and when tackling particularly tricky problems&lt;/li&gt;&#xA;&lt;li&gt;use an issue tracking tool&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
    </item>
    <item>
      <title>3 tips for those shipping (commercial) apps</title>
      <link>https://punchagan.muse-amuse.in/blog/3-tips-for-those-shipping-commercial-apps/</link>
      <pubDate>Wed, 28 Nov 2012 00:00:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/3-tips-for-those-shipping-commercial-apps/</guid>
      <description>&lt;p&gt;Here are some very generic (and paraphrased) notes from a short&#xA;talk today, by Deepankar Sharma.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Whenever you release a new major version, make sure you keep a&#xA;copy of the whole &amp;ldquo;ecosystem&amp;rdquo; to be able to run it whenever you&#xA;want.  At any point in time, you should be able to run any&#xA;version of your software.&lt;/li&gt;&#xA;&lt;li&gt;When writing benchmarks/tests/etc., try and ensure that you&#xA;cover a broad spectrum of test data, to try and replicate the&#xA;different types of data that users could possibly have.&lt;/li&gt;&#xA;&lt;li&gt;Don&amp;rsquo;t develop applications with modes.  Be very careful before&#xA;you add a new mode to your application, effectively adding one&#xA;more code path to maintain.&lt;/li&gt;&#xA;&lt;li&gt;(Bonus) Beware of too much extensibility&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
    </item>
    <item>
      <title>Advice - Programming in Elisp</title>
      <link>https://punchagan.muse-amuse.in/blog/advice-programming-in-elisp/</link>
      <pubDate>Fri, 06 Aug 2010 00:00:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/advice-programming-in-elisp/</guid>
      <description>&lt;p&gt;Below is a mail sent by Eric Schulte to the org-mode mailing list&#xA;answering a query on how to write elisp for org-mode. I am&#xA;reproducing it here, since it is useful advice for me. The actual&#xA;thread is &lt;a href=&#34;http://permalink.gmane.org/gmane.emacs.orgmode/27579&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;The way that I learned how to program in emacs lisp was mainly&#xA;using two commands `elisp-index-search&amp;rsquo; bound to `C-h e&amp;rsquo; on my&#xA;system, and most importantly `describe-function&amp;rsquo; bound to `C-h f&amp;rsquo;.&#xA;With `describe-function&amp;rsquo; you can look at the source code of&#xA;functions whose behavior you are familiar with, you can then copy&#xA;portions of the code to your &lt;strong&gt;scratch&lt;/strong&gt; buffer where they can be&#xA;edited and evaluated with `eval-defun&amp;rsquo; bound to `C-M-x&amp;rsquo;.  Now with&#xA;Babel, instead of doing this in the scratch buffer you could do&#xA;this in emacs-lisp code blocks in an org file, enabling notes and&#xA;hierarchical organization &amp;ndash; it can be nice to have your noodling&#xA;all collected in one file for later reference.&lt;/p&gt;&#xA;&lt;p&gt;If you are going to do any serious work with lisp, I would&#xA;emphatically recommend using paredit-mode, and becoming friends&#xA;with the Sexp movement functions&lt;/p&gt;&#xA;&lt;p&gt;C-M-f&#x9;runs the command paredit-forward&#xA;C-M-b&#x9;runs the command paredit-backward&#xA;C-M-u&#x9;runs the command backward-up-list&#xA;C-M-k&#x9;runs the command kill-sexp&#xA;C-y&#x9;runs the command yank&lt;/p&gt;&#xA;&lt;p&gt;They allow you to manipulate lisp code on the level of logical&#xA;expressions, the utility of which can not be over stated.&lt;/p&gt;&#xA;&lt;p&gt;As for working with Org-mode in particular, I&amp;rsquo;d recommend looking&#xA;at the documentation and source-code of Org-mode functions with&#xA;`describe-function&amp;rsquo;, and then looking for how these functions are&#xA;actually used in the Org-mode code base with `rgrep&#39;.&lt;/p&gt;&#xA;&lt;p&gt;For a more structured learning experience, I&amp;rsquo;ve heard very good&#xA;things about &lt;a href=&#34;http://www.gnu.org/software/emacs/emacs-lisp-intro/&#34;&gt;http://www.gnu.org/software/emacs/emacs-lisp-intro/&lt;/a&gt;,&#xA;although I haven&amp;rsquo;t used it myself.&lt;/p&gt;&#xA;&lt;p&gt;Hope this helps.  Happy Hacking &amp;ndash; Eric&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;</description>
    </item>
  </channel>
</rss>
