<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
<channel>
<title>Feed &#124; Ian Lai</title>
<atom:link href="https://www.fyianlai.com/feed/index.xml" rel="self" type="application/rss+xml"/>
<link>https://www.fyianlai.com</link>
<description>Words from an autodidact, full-stack web developer / software engineer who is currently based in London.</description>
<lastBuildDate>Wed, 13 Jun 2018 03:57:43 +0000</lastBuildDate>
<pubDate>Mon, 21 Sep 2015 19:51:00 +0000</pubDate>
<generator>Jekyll - http://jekyllrb.com/</generator>
<language>en-GB</language>

<item>
<title>Introducing: HistoryX for Chrome</title>
<pubDate>Mon, 21 Sep 2015 19:51:00 +0000</pubDate>
<link>https://www.fyianlai.com/2015/09/introducing-historyx-for-chrome/</link>
<guid isPermaLink="true">https://www.fyianlai.com/2015/09/introducing-historyx-for-chrome/</guid>
<dc:creator>Ian Lai</dc:creator>
<description><![CDATA[<p><a href="https://www.fyianlai.com/img/historyx.png"><img src="https://www.fyianlai.com/img/historyx.png" alt="HistoryX for Chrome" /></a></p>

<p>I am excited to introduce, <a href="https://github.com/MrSaints/historyx">History<sup>χ</sup></a> <em>(v2.4.0)</em>, an open source <a href="https://goo.gl/d8D1JP">Chrome extension</a> that I have been sporadically working on this past week. In the project manifest (and on GitHub), it is described as an <em>“extension to enhance your browsing history experience”</em>. But more specifically, it is an extension which, when enabled, will replace your existing history page with one that is leaner, and expanded with functionality.</p>

<p>It is ideal for regular, and power users alike. The former can take advantage of the improved interface, and smooth <a href="https://www.google.com/design/spec/material-design/introduction.html">materialesque</a> browsing experience, while the latter can take advantage of the <strong>search, sort, group, and filter features</strong>.</p>

<hr />

<p><a href="https://goo.gl/d8D1JP"><img src="https://developer.chrome.com/webstore/images/ChromeWebStore_Badge_v2_206x58.png" alt="Install via Chrome Web Store" /></a></p>

<p>You can <a href="https://goo.gl/d8D1JP">install v2.4.0</a> in the Chrome Web Store now or download the <a href="https://github.com/MrSaints/historyx">source</a>, and run it in <a href="https://developer.chrome.com/extensions/getstarted#unpacked">developer mode</a>.</p>

]]></description>
<content:encoded><![CDATA[<p><a href="https://www.fyianlai.com/img/historyx.png"><img src="https://www.fyianlai.com/img/historyx.png" alt="HistoryX for Chrome" /></a></p>

<p>I am excited to introduce, <a href="https://github.com/MrSaints/historyx">History<sup>χ</sup></a> <em>(v2.4.0)</em>, an open source <a href="https://goo.gl/d8D1JP">Chrome extension</a> that I have been sporadically working on this past week. In the project manifest (and on GitHub), it is described as an <em>“extension to enhance your browsing history experience”</em>. But more specifically, it is an extension which, when enabled, will replace your existing history page with one that is leaner, and expanded with functionality.</p>

<p>It is ideal for regular, and power users alike. The former can take advantage of the improved interface, and smooth <a href="https://www.google.com/design/spec/material-design/introduction.html">materialesque</a> browsing experience, while the latter can take advantage of the <strong>search, sort, group, and filter features</strong>.</p>

<hr />

<p><a href="https://goo.gl/d8D1JP"><img src="https://developer.chrome.com/webstore/images/ChromeWebStore_Badge_v2_206x58.png" alt="Install via Chrome Web Store" /></a></p>

<p>You can <a href="https://goo.gl/d8D1JP">install v2.4.0</a> in the Chrome Web Store now or download the <a href="https://github.com/MrSaints/historyx">source</a>, and run it in <a href="https://developer.chrome.com/extensions/getstarted#unpacked">developer mode</a>.</p>

<!--more-->

<h2 id="background">Background</h2>

<p>The key motivator behind this extension is my dissatisfaction over the currently available options (I will <a href="#reasons">elaborate</a> on this later), and my desire for a history page that can allow me to sift through my historical web visits quickly.</p>

<p>As a web developer, and someone with a mild obsessive-compulsive personality disorder (OCPD), I often find myself trying to retrace my previous visits to recall what I have done recently / in the past or trying to locate a website that I vaguely remember.
For example, occasionally something may trigger me to remember a specific phrase from an article I have read or perhaps a well-designed component from a website.  I will subsequently have an urge to locate where this ambiguous “memory” was derived from so I can properly take note of it or share it <em>(yes, I have a bad tendency to hoard information online, and I have way too many bookmarks)</em>. The only way I can achieve all this is through going back in time with what I can remember (e.g. keywords, pages I visited before / after, dates, etc).</p>

<p>This extension was built to cater for that need. After all, sometimes what I find unimportant, may become useful in the future. But obviously, since this is quite a complex need, it does have a lot of [planned] features that can help accomplish a bunch of other needs.</p>

<h3 id="features">Features</h3>

<p><a href="https://www.fyianlai.com/img/historyx-screenshot.png"><img src="https://www.fyianlai.com/img/historyx-screenshot.png" alt="v2.4.0" /></a></p>

<p>History<sup>χ</sup> supports the basic listing, deleting, searching, and paging feature that you can find on the default browser page.</p>

<p>Additionally, you can:</p>

<ul>
  <li>Change the amount of results per page;</li>
  <li>Filter the results by date through a user-friendly calendar (you can also browse between months, and years quickly by selecting the calendar’s header);</li>
  <li>View the total number of results, and the current range of results you are viewing;</li>
  <li>View the total number of times you visited a page;</li>
  <li>View the specific time you visited a page;</li>
  <li>Access the paging controls at the top or bottom of your results (unlike the default page which only allows you to do this at the bottom of it);</li>
  <li>And much more!</li>
</ul>

<p><em><strong>Tip:</strong> select the current date to toggle filtering by date.</em></p>

<p>At the moment, the results are in chronological order. Over the next couple of days (or weeks) however, I will be rolling out support for sorting (e.g. by hostname), and grouping results (e.g. by hour).</p>

<h3 id="future">Future</h3>

<p>Going forward, I intend on implementing <a href="https://en.wikipedia.org/wiki/Internationalization_and_localization">internationalization (il8n)</a> through Chrome’s <a href="https://developer.chrome.com/extensions/i18n"><code class="highlighter-rouge">chrome.i18n</code> infrastructure</a>. Support for il8n however, is likely to come later as I am hoping to optimise the existing code base, and work on ways to streamline the existing workflows. I am looking to shorten the time, and effort needed to perform common tasks by both the user, and the computer (this will potentially involve caching, and fat-cutting).</p>

<p>At the time of this post’s publication, <strong><a href="https://developer.chrome.com/extensions/omnibox">omnibox</a> (i.e. autocomplete), tagging, and saved searches</strong> are other major features I have in mind for this extension. You can find out more by viewing the <a href="https://github.com/MrSaints/historyx/issues/1">roadmap</a> in the <a href="https://github.com/MrSaints/historyx">official project repository</a>.</p>

<p>There are no plans for other browsers.</p>

<h3 id="historyχ-vs-other-extensions"><a name="reasons"></a>History<sup>χ</sup> vs. other extensions</h3>

<p>So, why should you use this extension vs. other history extensions?</p>

<p>First, unlike most Chrome extensions, this extension is entirely <strong>open source.</strong></p>

<p><strong>There are no ads. There are no trackers. It is completely transparent, and non-intrusive.</strong></p>

<p>You can fork the project, improve it, personalise it or simply just investigate it to validate my claims. Alternatively, you can run your own copy if you do not trust me.</p>

<p>The closest competitor to this extension is tracking your every action via Google Analytics.</p>

<p>Furthermore, as it is open source, you do not have to wait very long for a bug to be patched or for a feature to be added. And if you have a background in JavaScript, you can even do it yourself. The project is being actively developed (or at least I hope it will be even long after I am unavailable to lead it), and feature requests are welcomed.</p>

<p>Indeed, in <a href="https://en.wikipedia.org/wiki/The_Cathedral_and_the_Bazaar">The Cathedral and the Bazaar (1999)</a> by Eric S. Raymond, he succinctly describes what he calls <strong>Linus’ Law</strong>, that:</p>

<blockquote>
  <p>Given enough eyeballs, all bugs are shallow.</p>
</blockquote>

<p>Second, it relies on a <strong>modern UI library, and web architecture</strong> that have been tested in large production environments.</p>

<p>It is not running on a complex spaghetti bowl of dependencies, and jQuery plugins. Each component, action, store, constant, and utility are isolated in their own file. This will allow you to follow the logic, and trace problems more effortlessly. It also makes it easier for new features to be added.</p>

<p>Several similar extensions are running on outdated libraries, and conflicting dependencies. Consequently, its developers will find it hard to maintain their code base, and to eradicate unpredictable behaviour.
For example, one extension I have used for my history page (before this development came along) has been prone to crashes, and long load times. This problem has not been resolved for several months (although, this might be linked to my point about the nature of open source software).</p>

<p><a name="constraint"></a>Finally, <strong>results are not omitted.</strong></p>

<p>Due to a limitation in <a href="https://developer.chrome.com/extensions/history"><code class="highlighter-rouge">chrome.history</code> API</a> (that is, it only returns the last visited time, not the actual visit time of an entry), a similar extension omits stale visits in older dates. Simply put, if you were to visit Facebook now, an entry of you visiting it yesterday will not show up. This extension instead chooses to show you all the links you have visited in a given date or from a query filter even if it has been visited recently.</p>

<p>Unfortunately, I am still in the midst of developing a workaround to show the <em>real</em> visit time of <em>stale links</em>.</p>

<h4 id="tldr">TL;DR</h4>

<ul>
  <li>Open source;</li>
  <li>Ad-free;</li>
  <li>Tracker-free;</li>
  <li>Active development;</li>
  <li>Modern, predictable, and stable dependencies;</li>
  <li>Intuitive UI;</li>
  <li>High-performance;</li>
  <li>Fully featured.</li>
</ul>

<p>This is the first, and last history page extension you will ever need.</p>

<h2 id="development">Development</h2>

<p><a href="https://www.fyianlai.com/img/historyx-screenshot-2.png"><img src="https://www.fyianlai.com/img/historyx-screenshot-2.png" alt="Source Code" /></a></p>

<p>I have decided to release the extension after <del><strong>64 commits</strong></del> <strong>75 commits</strong> consisting of a name change, several changes to its dependencies, and countless iterations to both its design, and code architecture. In spite of all this, it is far from its <em>final form</em>. And there is still a long <a href="https://github.com/MrSaints/historyx/issues/1">list of additions, and improvements</a> that have yet to be made.</p>

<p>It is a <em>work in progress</em>.</p>

<p>It is built with heavy reliance on the latest, and most popular web libraries including <a href="https://facebook.github.io/react/">React</a> (Facebook’s UI library), and <a href="https://github.com/BinaryMuse/fluxxor">Fluxxor</a> (a set of tools implementing the <a href="https://facebook.github.io/flux/">Flux architecture</a>). It also relies on styles provided by <a href="http://v4-alpha.getbootstrap.com/">Bootstrap v4 (Alpha)</a>.</p>

<p>You can examine the <a href="https://github.com/MrSaints/historyx">source code</a> to see the symbiosis of these libraries, and the use of <a href="https://developer.chrome.com/extensions/history"><code class="highlighter-rouge">chrome.history</code> API</a>.</p>

<p>Unfortunately, I will not be documenting the development process in this post, but I will be saving it for another post, soon. Nevertheless, I would like to welcome contributions in any way, shape or form (e.g. pull requests, issues, feature requests, etc). You are most welcome to participate in the <a href="https://github.com/MrSaints/historyx">development</a> process.</p>

<p>This project does not have an official communication channel, but I am generally easy to reach via <a href="https://twitter.com/MrSaints">Twitter</a>, and IRC (join <a href="http://www.fyrechat.net/">FyreChat</a> #sandbox channel). I am also available via <a href="/hello">e-mail</a> (using my contact form).</p>

<h2 id="post-publishing">Post-publishing</h2>

<p><del>It has just occurred to me, upon publishing my extension, that I have not included any option to delete a visit. I will be releasing a new version to address this as soon as possible.</del></p>

<p><strong>Update v2.4.0 (23/09/15):</strong></p>

<ul>
  <li>You can now delete a visit from your history. For developers, the delete button can be found in the history actions component. Mouseover a visit to see the delete button;</li>
  <li>The visit’s full URL is now shown below its title;</li>
  <li>The results’ data are organised (i.e. positioned) through flexbox. From my knowledge, this should be supported in most Chrome browsers (31+).</li>
</ul>

<p>Finally, there are several FAQs I would like to address before they are brought up:</p>

<ol>
  <li>
    <p><strong>In the results, why are some of the dates shown in full?</strong></p>

    <p>As mentioned <a href="#constraint">earlier</a>, there are several constraints when using the <a href="https://developer.chrome.com/extensions/history"><code class="highlighter-rouge">chrome.history</code> API</a>. One of which is that it only returns the date / time you last visited a website (i.e. most recent access to a URL). If you have visited it before, it will still show up in the API results as a visit, but it will not show the actual date / time you visited it.</p>
  </li>
  <li>
    <p><strong>How does the search feature work?</strong></p>

    <p>It is currently relying on the <a href="https://developer.chrome.com/extensions/history#method-search"><code class="highlighter-rouge">chrome.history.search</code> API</a> method to fetch the results. In the future, I will be implementing a <em>client-side</em> (i.e. JavaScript) search. The current search method should nevertheless be sufficient in most use cases.</p>
  </li>
  <li>
    <p><strong>How do I remove the date filter (i.e. show all)?</strong></p>

    <p>Select the current date in the calendar. It can be toggled.</p>
  </li>
  <li>
    <p><strong>What is the logo supposed to be?</strong></p>

    <p><a href="https://www.fyianlai.com/img/flux.jpg"><img src="https://www.fyianlai.com/img/flux.jpg" alt="Flux Capacitor" /></a></p>

    <p>It is a very unimaginative modification of the <a href="https://en.wikipedia.org/wiki/DeLorean_time_machine">flux capacitor</a> to resemble the letter X. The flux capacitor is the core component of a fictional time machine - called the <em>DeLorean</em> - from the movie <a href="https://en.wikipedia.org/wiki/Back_to_the_Future">Back to the Future</a>. In the words of Dr. Emmet Brown, a fictional character (or rather, a mad scientist) in the movie, it is:</p>

    <blockquote>
      <p>What makes time travel possible.</p>
    </blockquote>

    <p>Coincidentally, Flux is also the backbone of this extension. It is the application architecture that I am using for the <a href="http://fluxxor.com/what-is-flux.html">unidirectional propagation</a> of data, and changes in the UI. Thus, I felt it was only fitting to reference the flux capacitor. After all, this extension is essentially a time machine for Chrome.</p>

    <p>In fact, the extension was named <em>DeLorean</em> for a while, until I decided to change it because I felt that it would not be an easy name for people to find (on Chrome Web Store) or remember. The current name seems to reflect its intent a lot better to those who have never watched <em>Back to the Future</em>.</p>
  </li>
</ol>

]]></content:encoded>
</item>

<item>
<title>Prepare() in Beego Web Framework</title>
<pubDate>Tue, 04 Nov 2014 09:24:00 +0000</pubDate>
<link>https://www.fyianlai.com/2014/11/prepare-in-beego-web-app-framework/</link>
<guid isPermaLink="true">https://www.fyianlai.com/2014/11/prepare-in-beego-web-app-framework/</guid>
<dc:creator>Ian Lai</dc:creator>
<description><![CDATA[<p><a href="http://beego.me/docs/mvc/controller/controller.md"><code class="highlighter-rouge">Prepare()</code></a> is a method exposed by <a href="https://godoc.org/github.com/astaxie/beego#Controller"><code class="highlighter-rouge">beego.Controller{}</code></a> and it is executed prior to the method corresponding to your route and HTTP request (the action). It is not a filter and thus, it can easily be extended (much like the <code class="highlighter-rouge">Get()</code> and <code class="highlighter-rouge">Post()</code> method) for a variety of functions such as:</p>

<ul>
  <li><strong>Session control:</strong> ACL-based authentication and authorization</li>
  <li><strong>Globals:</strong> Setting [ REUSABLE ] defaults for your template (stylesheets, JavaScipts, variables…)</li>
</ul>

]]></description>
<content:encoded><![CDATA[<p><a href="http://beego.me/docs/mvc/controller/controller.md"><code class="highlighter-rouge">Prepare()</code></a> is a method exposed by <a href="https://godoc.org/github.com/astaxie/beego#Controller"><code class="highlighter-rouge">beego.Controller{}</code></a> and it is executed prior to the method corresponding to your route and HTTP request (the action). It is not a filter and thus, it can easily be extended (much like the <code class="highlighter-rouge">Get()</code> and <code class="highlighter-rouge">Post()</code> method) for a variety of functions such as:</p>

<ul>
  <li><strong>Session control:</strong> ACL-based authentication and authorization</li>
  <li><strong>Globals:</strong> Setting [ REUSABLE ] defaults for your template (stylesheets, JavaScipts, variables…)</li>
</ul>

<!--more-->

<h2 id="core--base-controller-globals">Core / base controller (globals)</h2>

<p>We may for example create a core / base controller that would set <code class="highlighter-rouge">layout.tpl</code> as its default layout and assign a template variable to a string array of stylesheets or JavaScripts to import.</p>

<h6 id="controllersbasego">controllers/base.go:</h6>

<figure class="highlight"><pre><code class="language-go" data-lang="go"><span class="k">type</span><span class="x"> </span><span class="n">BaseController</span><span class="x"> </span><span class="k">struct</span><span class="x"> </span><span class="p">{</span><span class="x">
    </span><span class="c">// Embedding: "Inherit" beego.Controller</span><span class="x">
    </span><span class="n">beego</span><span class="o">.</span><span class="n">Controller</span><span class="x">
</span><span class="p">}</span><span class="x">

</span><span class="k">func</span><span class="x"> </span><span class="p">(</span><span class="n">this</span><span class="x"> </span><span class="o">*</span><span class="n">BaseController</span><span class="p">)</span><span class="x"> </span><span class="n">Prepare</span><span class="p">()</span><span class="x"> </span><span class="p">{</span><span class="x">
    </span><span class="c">// Overwrite beego.Controller.Layout (string)</span><span class="x">
    </span><span class="n">this</span><span class="o">.</span><span class="n">Layout</span><span class="x"> </span><span class="o">=</span><span class="x"> </span><span class="s">"layout.tpl"</span><span class="x">

    </span><span class="c">// beego.Controller.Data comprises of a map of template variables</span><span class="x">
    </span><span class="n">this</span><span class="o">.</span><span class="n">Data</span><span class="p">[</span><span class="s">"HeadStyles"</span><span class="p">]</span><span class="x"> </span><span class="o">=</span><span class="x"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="x">
        </span><span class="s">"//cdn.jsdelivr.net/pure/0.5.0/pure-min.css"</span><span class="p">,</span><span class="x">
        </span><span class="s">"//yui.yahooapis.com/pure/0.5.0/grids-responsive-min.css"</span><span class="p">,</span><span class="x">
        </span><span class="s">"//fonts.googleapis.com/css?family=Roboto:400,500,300"</span><span class="p">,</span><span class="x">
        </span><span class="s">"/static/css/base.css"</span><span class="p">,</span><span class="x">
    </span><span class="p">}</span><span class="x">

    </span><span class="n">this</span><span class="o">.</span><span class="n">Data</span><span class="p">[</span><span class="s">"HeadScripts"</span><span class="p">]</span><span class="x"> </span><span class="o">=</span><span class="x"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="x">
        </span><span class="s">"//cdn.jsdelivr.net/modernizr/2.8.3/modernizr.min.js"</span><span class="p">,</span><span class="x">
    </span><span class="p">}</span><span class="x">
</span><span class="p">}</span></code></pre></figure>

<p>Any <em>new struct</em> embedding <code class="highlighter-rouge">BaseController{}</code> will now inherit its methods and variables (only <code class="highlighter-rouge">Prepare()</code> in this case) as well as those in the anonymous member <code class="highlighter-rouge">beego.Controller{}</code> as it is embedded in <code class="highlighter-rouge">BaseController{}</code> (refer to the first few lines). Unless the new struct sets its own <code class="highlighter-rouge">Prepare()</code> method, Beego will fallback to using the next defined <code class="highlighter-rouge">Prepare()</code> which in this case, belongs to <code class="highlighter-rouge">BaseController{}</code>. Our <em>new struct</em> will now have a <code class="highlighter-rouge">Layout</code> variable that is set to <code class="highlighter-rouge">layout.tpl</code> (overwriting <code class="highlighter-rouge">beego.Controller{}</code> default) and an array of styles and scripts in <code class="highlighter-rouge">HeadStyles</code> and <code class="highlighter-rouge">HeadScripts</code> template variable (set via <code class="highlighter-rouge">Data</code>) respectively, by default.</p>

<p><strong>Fun fact:</strong> <a href="https://github.com/astaxie/beego/blob/master/controller.go#L112"><code class="highlighter-rouge">beego.Controller.Prepare()</code></a> does not contain any logic.</p>

<p>This is useful for reducing redundancy in our controllers. Indeed, we do not have to define the same <code class="highlighter-rouge">Layout</code> in every controller, and we may, on a per controller method basis, add or remove styles and scripts from our template just by altering the <code class="highlighter-rouge">HeadStyles</code> and <code class="highlighter-rouge">HeadScripts</code> array. For example, assuming we have a layout…</p>

<h6 id="viewslayouttpl">views/layout.tpl:</h6>

<figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="cp">&lt;!doctype html&gt;</span>
<span class="nt">&lt;html</span> <span class="na">class=</span><span class="s">"no-js"</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;head&gt;</span>
        <span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;meta</span> <span class="na">http-equiv=</span><span class="s">"X-UA-Compatible"</span> <span class="na">content=</span><span class="s">"IE=edge"</span><span class="nt">&gt;</span>

        <span class="nt">&lt;title&gt;</span>Beego App: {{.Title}}<span class="nt">&lt;/title&gt;</span>
        <span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"description"</span> <span class="na">content=</span><span class="s">""</span><span class="nt">&gt;</span>
        <span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"viewport"</span> <span class="na">content=</span><span class="s">"width=device-width, initial-scale=1"</span><span class="nt">&gt;</span>

        {{range .HeadStyles}}
            <span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">href=</span><span class="s">"{{.}}"</span><span class="nt">&gt;</span>
        {{end}}

        {{range .HeadScripts}}
            <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">"{{.}}"</span><span class="nt">&gt;&lt;/script&gt;</span>
        {{end}}
    <span class="nt">&lt;/head&gt;</span>

    <span class="nt">&lt;body&gt;</span>
        {{.LayoutContent}}
    <span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span></code></pre></figure>

<p>And a <em>new struct</em> controller named <code class="highlighter-rouge">HelloWorldController</code> implementing <code class="highlighter-rouge">BaseController{}</code>.</p>

<h6 id="controllershelloworldgo">controllers/helloworld.go:</h6>

<figure class="highlight"><pre><code class="language-go" data-lang="go"><span class="k">type</span><span class="x"> </span><span class="n">HelloWorldController</span><span class="x"> </span><span class="k">struct</span><span class="x"> </span><span class="p">{</span><span class="x">
    </span><span class="c">// Embedding: "Inherit" BaseController</span><span class="x">
    </span><span class="n">BaseController</span><span class="x">
</span><span class="p">}</span><span class="x">

</span><span class="k">func</span><span class="x"> </span><span class="p">(</span><span class="n">this</span><span class="x"> </span><span class="o">*</span><span class="n">HelloWorldController</span><span class="p">)</span><span class="x"> </span><span class="n">Get</span><span class="p">()</span><span class="x"> </span><span class="p">{</span><span class="x">
    </span><span class="c">// Set {{.Title}}</span><span class="x">
    </span><span class="n">this</span><span class="o">.</span><span class="n">Data</span><span class="p">[</span><span class="s">"Title"</span><span class="p">]</span><span class="x"> </span><span class="o">=</span><span class="x"> </span><span class="s">"Hello World!"</span><span class="x">

    </span><span class="c">// TplNames is parsed into {{.LayoutContent}}</span><span class="x">
    </span><span class="n">this</span><span class="o">.</span><span class="n">TplNames</span><span class="x"> </span><span class="o">=</span><span class="x"> </span><span class="s">"hello_world.tpl"</span><span class="x">
</span><span class="p">}</span></code></pre></figure>

<p>Beego will automatically render (if the <code class="highlighter-rouge">AutoRender</code> config is enabled) <code class="highlighter-rouge">hello_world.tpl</code> AND <code class="highlighter-rouge">layout.tpl</code>. The contents of <code class="highlighter-rouge">hello_world.tpl</code> will be imported into the <code class="highlighter-rouge">LayoutContent</code> template variable [ in the curly braces ]. Additionally, <code class="highlighter-rouge">{{range .HeadStyles}}</code> and <code class="highlighter-rouge">{{range .HeadScripts}}</code> will loop through our string array of stylesheets and JavaScripts so that we can import them into our HTML page. Our HTML document title will be “Beego App: Hello World!” once successfully rendered.</p>

<p>Notice that in our <code class="highlighter-rouge">HelloWorldController.Get()</code> method we did not have to define what <code class="highlighter-rouge">Layout</code> is as it was already defined by <code class="highlighter-rouge">HelloWorldController{}</code> parent, the <code class="highlighter-rouge">BaseController{}</code>. Thus, when the <code class="highlighter-rouge">Render()</code> method is fired, it will be in the <a href="https://github.com/astaxie/beego/blob/master/controller.go#L197">context of</a> <code class="highlighter-rouge">HelloWorldController{}</code>. We can even include specific stylesheets and scripts specific for the <code class="highlighter-rouge">HelloWorldController.Get()</code> method by using Go’s <code class="highlighter-rouge">append</code> function on <code class="highlighter-rouge">this.Data["HeadScripts"]</code>.</p>

<p>If we were to rewrite <code class="highlighter-rouge">HelloWorldController{}</code> to implement <code class="highlighter-rouge">beego.Controller{}</code> instead, <code class="highlighter-rouge">Layout</code> will not be defined as well as the other template variables we are using for our JavaScript and stylesheet imports. The resulting HTML output will simply be a parsed <code class="highlighter-rouge">hello_world.tpl</code> without <code class="highlighter-rouge">layout.tpl</code>.</p>

<p>You may visualise the inheritance of our controllers in the following manner:</p>

<ol>
  <li>beego.Controller</li>
  <li>beego.Controller -&gt; BaseController</li>
  <li>beego.Controller -&gt; BaseController -&gt; HelloWorldController</li>
</ol>

<p>By extending the original <code class="highlighter-rouge">beego.Controller{}</code> we may overwrite its methods and variables, and implement our own logic that will better cater to our needs. Best of all, we can abide by DRY (Do Not Repeat Yourself) principles.</p>

<h2 id="execute-parent-prepare">Execute parent Prepare()</h2>

<p>If we were to create a new <code class="highlighter-rouge">Prepare()</code> method in <code class="highlighter-rouge">HelloWorldController{}</code>, the <code class="highlighter-rouge">Prepare()</code> method in <code class="highlighter-rouge">BaseController{}</code> will no longer be fired (for reasons we have highlighted above - it is overwritten). We may still however, execute the “parent” method by calling the struct name directly (for anonymous members) or the field name. For example:</p>

<h6 id="controllershelloworld_with_parentgo">controllers/helloworld_with_parent.go:</h6>

<figure class="highlight"><pre><code class="language-go" data-lang="go"><span class="k">func</span><span class="x"> </span><span class="p">(</span><span class="n">this</span><span class="x"> </span><span class="o">*</span><span class="n">HelloWorldController</span><span class="p">)</span><span class="x"> </span><span class="n">Prepare</span><span class="p">()</span><span class="x"> </span><span class="p">{</span><span class="x">
    </span><span class="n">this</span><span class="o">.</span><span class="n">BaseController</span><span class="o">.</span><span class="n">Prepare</span><span class="p">()</span><span class="x">

    </span><span class="c">// Do other stuff</span><span class="x">
</span><span class="p">}</span></code></pre></figure>

<p>Both <code class="highlighter-rouge">HelloWorldController.Prepare()</code> and <code class="highlighter-rouge">BaseController.Prepare()</code> will now be fired in that order.</p>

<p>Through this additional extension, we may not only maintain the logic and variables established in our parent controller, but extend them further to encompass new logic or variables for all methods in a controller. We may for a specific controller, validate a user session to see if they are logged in and redirect them away from it if they are not, and at the same time, we can still keep our parent variables which can be used to render the template to those who are logged in and validated.</p>

<p>As a final note, it is probably worth exploring <a href="https://godoc.org/github.com/astaxie/beego">Beego Godocs</a>, <a href="https://github.com/astaxie/beego/">Beego source code</a> and <a href="https://github.com/beego/wetalk">WeTalk</a>, a project made in Beego by… Beego to learn more about the ins and outs of the framework (not as well documented on the official website, probably due to the lack of English contributors). You can see <code class="highlighter-rouge">Prepare()</code> in action in <a href="https://github.com/AnnaDaphne/Admin">Anna &amp; Daphne’s admin control panel</a>.</p>
]]></content:encoded>
</item>

<item>
<title>Passwords. You're Doing It Wrong</title>
<pubDate>Wed, 21 May 2014 05:47:00 +0000</pubDate>
<link>https://www.fyianlai.com/2014/05/passwords-youre-doing-it-wrong/</link>
<guid isPermaLink="true">https://www.fyianlai.com/2014/05/passwords-youre-doing-it-wrong/</guid>
<dc:creator>Ian Lai</dc:creator>
<description><![CDATA[<p>I seem to be having difficulties getting into the <em>mood</em> to revise for an exam tomorrow. It is what I <em>should</em> be doing, but what I really <em>want</em> to be doing is to code all day. Unfortunately, as it is exam season I have decided to self-impose a ban on coding until I have completed all my exams. Fortunately, I do not recall banning myself from making a blog post so here we go.</p>

<p>If you are running a website that requires a user-password-based authentication system there is a high chance you are probably handling the password poorly (at least in my books). Indeed, several e-commerce and e-banking websites are <a href="https://defuse.ca/password-policy-hall-of-shame.htm">doing it wrong</a> too. As a disclaimer, I am neither an expert in web security nor am I one in user experience. The following post is not targeted towards a layperson. I am merely synthesising a list of <del>bad</del> questionable password practices by web developers and they are based on personal observations (albeit, with some support from the web community).</p>

]]></description>
<content:encoded><![CDATA[<p>I seem to be having difficulties getting into the <em>mood</em> to revise for an exam tomorrow. It is what I <em>should</em> be doing, but what I really <em>want</em> to be doing is to code all day. Unfortunately, as it is exam season I have decided to self-impose a ban on coding until I have completed all my exams. Fortunately, I do not recall banning myself from making a blog post so here we go.</p>

<p>If you are running a website that requires a user-password-based authentication system there is a high chance you are probably handling the password poorly (at least in my books). Indeed, several e-commerce and e-banking websites are <a href="https://defuse.ca/password-policy-hall-of-shame.htm">doing it wrong</a> too. As a disclaimer, I am neither an expert in web security nor am I one in user experience. The following post is not targeted towards a layperson. I am merely synthesising a list of <del>bad</del> questionable password practices by web developers and they are based on personal observations (albeit, with some support from the web community).</p>

<!--more-->

<h2 id="unnecessary-requirements">Unnecessary requirements…</h2>

<h3 id="maximum-password-length">Maximum password length.</h3>

<p>I can only identify <a href="http://security.stackexchange.com/questions/33470/what-technical-reasons-are-there-to-have-low-maximum-password-lengths">six key reasons</a> why any website would choose to set an upper bound limit on a user’s password:</p>

<ol>
  <li>The use of legacy systems and/or a legacy password hashing function;</li>
  <li>Convention and/or a guideline set by a very naïve, higher authority;</li>
  <li>To store the password in plaintext or encrypted plaintext (different from hashing) [to accommodate a database schema];</li>
  <li>Developing from point 3: to prevent injection-based attacks;</li>
  <li><em>Reduce likelihood of users forgetting?</em></li>
  <li>To mitigate (D)DoS attacks.</li>
</ol>

<p>I do not find reasons one to four reasonable at all. They are <a href="http://stackoverflow.com/questions/98768/should-i-impose-a-maximum-length-on-passwords">not valid excuses</a> in this day and age.</p>

<p>Your authentication system should be <a href="https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet#Design_password_storage_assuming_eventual_compromise">“designed for failure”</a>. With the increasing number of <a href="http://www.crn.com/slide-shows/security/240159149/the-10-biggest-data-breaches-of-2013-so-far.htm">prominent database breaches</a>, it is no longer logical (rather, it never was) to assume your users’ confidential data are not susceptible to compromise. As such, it is not logical to store passwords in plaintext or in an encrypted format that is either reversible or generated by a <a href="http://valerieaurora.org/hash.html#footnote2">weak cryptographic hash function</a>. You are exposing your users (particularly those who share their password across different websites) to risk in the event your users’ credentials are exposed to malicious individuals.</p>

<p>Reason 4 should not be an issue once you have password hashing in place as you are merely storing the hashed password, and thus, you should neither be passing any system-sensitive command to the database nor should you be validating the original password in plaintext. The length of a user-entered password will not affect the length of the hashed password, and hence, it will not affect the database schema (it will remain consistent).</p>

<p>Reason 5 should be accounted for via <em>automated</em> password recovery processes. Users should be given the freedom to set a password of any length (even if they are more likely to forget them, but that is not for you to judge) inasmuch as it is not detrimental to your website (reason 6). In my opinion, it is bad UX to set such hard limit.</p>

<p>Reason 6 is a machine problem, not a user one, and they should not be punished for it. The machine should be configured to deal with DoS attacks and to drop adverse request handlers (e.g. via request thresholds, filters etc). DDoS attacks may be mitigated by building the website to deal with CSRF (e.g. via captchas, hidden key, etc). Admittedly, dealing with DDoS attacks are far more complex, but by preventing remote requests you are removing one source of attack and you will increase the complexity for the attacker. Worst-case scenario, it is justifiable to set a generous upper bound limit.</p>

<p>We set a lower bound (minimum) limit for passwords because shorter passwords are <a href="https://www.owasp.org/index.php/Password_length_%26_complexity">easier to guess and/or brute force</a> (for humans and machines alike). Thus, it is only logical to allow for longer passwords with higher entropy.</p>

<h3 id="passwords-with-special-characters">Passwords with special characters.</h3>

<p>Websites that do not allow special characters in passwords seem to imply the same reasons postulated above. Indeed, this practice strongly implies to me that the web developer is concerned with the content of the password as it may be malicious (reason 4), and this makes me very concerned as well.</p>

<p>As I have explained already, if the password is hashed this should not be a concern at all. You are not passing system-sensitive commands. You are passing gibberish. If it is a concern, then chances are it is probably stored in plaintext or in a format that is reversible (and potentially harmful for the system in the web developer’s perspective). This should raise some serious red flags.</p>

<p>Instead, special characters should be encouraged. They add complexity to the resulting hashed password thereby increasing the time it will take to crack the password via hardware and technique-based attacks (e.g. dictionary, brute force, etc). On the contrary to <a href="http://xkcd.com/936/">XKCD-936</a>, it is <a href="http://www.reddit.com/r/YouShouldKnow/comments/232uch/ysk_how_to_properly_choose_a_secure_password_the/">no longer secure</a> to set a purely alphanumeric password, let alone one that is composed of words. Granted, it does increase the entropy of your password and reduces the likelihood of someone guessing it. The concern arises however, from the assumption [that I have previously made] that if the hash of your users’ password are stolen, they are vulnerable to being cracked by dictionary-based attacks.</p>

<h3 id="freedom-and-predictability">Freedom and predictability.</h3>

<p>Imposing machine requirements on passwords is fundamentally <a href="https://www.linkedin.com/today/post/article/20140511002225-12181762-error-message-are-evil?trk=tod-home-art-list-large_0">bad UX</a> and bad security design.</p>

<p>Users should be given as many opportunities as possible to safeguard their own accounts and identities. Web developers should accommodate for this, and not the other way around. A restriction-less password is the first step in doing so. It will grant users the freedom [and arguably, the <em>responsibility</em>] to ensure the security of their own account. Users with a greater affinity towards higher quality passwords should not be restrained by petty limits on the length and/or characters. Other [strongly encouraged] steps may be taken including password expiration, two-factor authentication, limits on failed authentication attempts (lockout), IP address restrictions, SSL etc.</p>

<p>It is also a bad security design as it <em>helps</em> attackers by reducing the range of possible passwords. For example, an attacker needs to only test for alphanumeric passwords if a website is set to allow alphanumeric passwords only. There is no need to account for other characters. Thus, a lack of <em>password definition / rules</em> will provide another variable for the attacker to account for thereby increasing the complexity (or rather, broadening the assumptions).</p>

<h3 id="a-note-on-hashes">A note on hashes.</h3>

<p>Cryptographic hash functions generally return a fixed-length hash value. Consequently, there is a chance that a hash of one string may be the hash of another string. This phenomenon is known as a hash collision, and while the possibility exists, some cryptographic hash function are more resistant to it than others (the cost of discovering these collisions, e.g. via birthday attacks, are much higher). Consequently, there may be some diminishing returns beyond some password length depending on the strength of the cryptographic hash function used.</p>

<h2 id="password-strength-checkers-andminimum-score">Password strength checkers and minimum score.</h2>

<p>Password strength checkers rely on a <a href="http://en.wikipedia.org/wiki/Password_strength">custom security criteria</a> which more often than not, is flawed. They are commonly calculated by measuring the entropy of the password or by comparing it to a set of regular expressions. High scores may be achieved by lengthier passwords (such as those composed purely of random words), but the overall quality of the passwords may not necessarily be high, for reasons explained above (they may even fall in a list of common passwords or patterns).</p>

<p>For someone who is not familiar to the concept of passwords such a mechanism would be useful for guiding the user towards a more complex password with greater entropy, and hence, theoretically greater security. Enforcing a score-based restriction is nevertheless bad UX (it forces users to behave like machines which may also give a false sense of security), and in some cases, it may be a bad security design if it forces users to conform to a certain pattern of password (e.g. start with capitals, include X or Y, etc).</p>

<p>Indeed, the findings in a <a href="http://reusablesec.blogspot.co.uk/2010/10/new-paper-on-password-security-metrics.html">research into the NIST model of password entropy</a> (a heavily recommended scheme for estimating the entropy of human-selected passwords) showed that:</p>

<blockquote>
  <p>…the NIST model of password entropy <strong>does not match up</strong> with real world password usage or password cracking attacks. If that wasn’t controversial enough, we then made the even more substantial claim that the current use of Shannon Entropy to model the security provided by human generated passwords at best provides no actionable information to the defender. At worse, it leads to a defender having an <strong>overly optimistic view of the security</strong> provided by their password creation policies while at the same time resulting in <strong>overly burdensome requirements</strong> for the end users.</p>
</blockquote>

<h2 id="password-account-recovery"><del>Password</del> Account recovery.</h2>

<p>Assuming most “forgotten password” functionality relies on a user’s e-mail address, then no credentials (the password in particular) should be sent to the user via e-mail, regardless of whether it is the user’s original password or if it is a randomly generated password.</p>

<p>Indeed, for security reasons, under no circumstances should you have access to the user’s original password. As I have previously mentioned, passwords should not be stored in plaintext or in a format that is easily reversible. It must be hashed using a reliable cryptographic hash function. Any website that sends you your password is clearly not handling your data securely, and it is probably not trustworthy.</p>

<p>It is also not advisable to reset the user’s password. By setting a randomly generated password without the user’s prior consent you are doing the following:</p>

<ol>
  <li>Diminishing users’ freedom and control over their data.</li>
  <li>Potentially jeopardizing users’ security should they choose to write it down (due to its complexity) or should someone else see the password in their e-mail account.</li>
  <li>Developing from the previous points: it may increase the complexity (adds more steps) of the recovery process as the user is likely to change the automatically set password upon authentication.</li>
</ol>

<p>The user should be given the freedom to set a new password immediately. This is probably how the user wants it to be anyway.</p>

<p>Measures should also be taken to secure the account recovery interface (e.g. via unique tokens, expiration, throttling, etc), but it is not for the purpose of this article to discuss. Refer to the <a href="http://stackoverflow.com/questions/549/the-definitive-guide-to-form-based-website-authentication">definitive guide to form based website authentication</a> for more information.</p>

<h2 id="passworddata-validation"><del>Password</del> Data validation.</h2>

<p>Users should be informed about the validation requirements before the validation process occurs, not after. It will save the user’s time and it is less frustrating that way. They should not be expected to predict a system’s design only to be punished for not being able to do so. Don Norman’s <a href="https://www.linkedin.com/today/post/article/20140511002225-12181762-error-message-are-evil?trk=tod-home-art-list-large_0">“Error Messages Are Evil”</a> summarises this problem succinctly:</p>

<blockquote>
  <p>A truly collaborative system would tell me the requirements before I did the work. If there are special ways you want stuff entered, tell me before I enter it, not afterwards. How many times must we endure the indignity of typing in a long string only to be told afterwards that it doesn’t fit the machine’s whims (more accurately, doesn’t fit the whims of the programmer)?</p>
</blockquote>

<p>Restrictions may vary from one website to another. Thus, it should be made explicitly clear what would constitute an “acceptable password” (e.g. special characters, uppercase/lowercase, numbers, etc) if you do intend on setting restrictions. Take French Connection United Kingdom (FCUK) online registration form for example:</p>

<p><a href="https://www.fyianlai.com/img/fcuk.jpg"><img src="https://www.fyianlai.com/img/fcuk.jpg" alt="Vague restrictions" /></a></p>

<p>The developers only made clear the lower bound limits, but made no attempt at informing me of the specific upper bound limits (even after the form has been validated). Please do not force your users into a guessing game. It took me several attempts before I realised that the character limit was 12 and that I could not use special characters. By making the lower bound limits obvious instead of the upper bound limits, you are only <em>encouraging</em> users to go for the bare minimum (to avoid your otherwise annoyingly vague form rules and error messages).</p>

<h2 id="password-masking">Password masking.</h2>

<p>Jakob Nielsen’s <a href="http://www.nngroup.com/articles/stop-password-masking/">“Stop Password Masking”</a> thoroughly summarises the problems with password masking:</p>

<blockquote>
  <p>Usability suffers when users type in passwords and the only feedback they get is a row of bullets. Typically, masking passwords doesn’t even increase security, but it does cost you business due to login failures.</p>

  <p>…there’s usually nobody looking over your shoulder when you log in to a website. It’s just you, sitting all alone in your office, suffering reduced usability to protect against a non-issue.</p>
</blockquote>

<p>It is a legacy design ingrained by browser vendors. We have adhered to it because it is simple and conventional. In reality, the lack of feedback makes us more prone to errors or bad password practices (e.g. simple passwords, copy-pasting, etc), and the former is exemplified by the need for an extra password field as confirmation (further complicating registration processes).</p>

<p>Nielsen instead recommends offering users a checkbox to have their password masked for high-risk locations (internet cafes) or high-risk applications (bank accounts). Indeed, Microsoft’s Internet Explorer 10 have included a small icon for password fields that will allow users to view their password in plaintext.</p>

<p>If you have never heard of Nielsen, he is an acclaimed web usability consultant. He is known for publishing his <a href="http://www.nngroup.com/articles/ten-usability-heuristics/">usability heuristics</a> in 1994. Currently, his heuristics are perhaps the most-used heuristics for user interface design. It is a set of guidelines that may be used to identify potential usability problems in a design (albeit, not strictly). You can run a heuristic evaluation on your own website through <a href="https://chrome.google.com/webstore/detail/ux-check/giekhiebdpmljgchjojblnekkcgpdobp">UX Check</a> (a Chrome extension).</p>

<h2 id="do-what-we-can-with-what-we-got">Do what we can with what we got.</h2>

<p>Password-based authentication systems are inherently flawed, but they are the <a href="https://stormpath.com/blog/long-live-password/">best we got</a> with regards to ease of deployment, security, and usability (although projects like Mozilla’s <a href="https://developer.mozilla.org/en-US/Persona/Why_Persona">Persona</a> are trying to challenge this). We should not make such a system worse than it already is. We should work towards perfecting it while <a href="https://medium.com/design-startups/4a08d6afe0a1">striking a balance</a> between security and usability.</p>

<p>Ultimately, <a href="http://harvardmagazine.com/2000/01/code-is-law-html">code is law</a> and the web developer is the <em>legislator</em>. As the legislator, you are responsible for the behaviour and the security of your users. You can make their web experience pleasant or unpleasant. You can do whatever you can to <a href="http://stackoverflow.com/questions/2794016/what-should-every-programmer-know-about-security">guarantee their security</a> and the security of the information they provide you with, or you can just neglect them and deal with a PR sh*tstorm (for lack of a better word) when your complacency is exposed.</p>

<p>The decision is yours to make.</p>

<h2 id="an-ongoing-discourse">An ongoing discourse.</h2>

<p>Preventing errors from occurring is always the <a href="http://www.sitepoint.com/error-message-ux/">best course of action</a>, but when that is not a possibility, ensure it is <a href="http://uxmas.com/2012/the-4-hs-of-writing-error-messages">human, helpful, humorous and humble</a>.</p>

<p><strong>Update (23/05/2014): </strong>Interestingly enough, I wrote this article (and published it privately) before <a href="http://www.bbc.co.uk/news/technology-27539799">eBay suffered a data breach</a> recently. Impeccable timing.</p>

<p><strong>Update (30/07/2014):</strong> There is a Tumblr dedicated towards <em>shaming</em> websites storing passwords in plaintext. Unlike the password hall of shame linked earlier in this article, <a href="http://plaintextoffenders.com">PlainTextOffenders.com</a> is new and kept more up-to-date with submissions from the community. I strongly recommend reading the <a href="http://plaintextoffenders.com/faq/devs">Developers FAQ</a> even though some of the points has already been highlighted in this article <em>(albeit, not as succinctly).</em></p>

<p><strong>Update (14/08/2014):</strong> Jeff Atwood from Coding Horror (and the co-founder of Stack Overflow / Stack Exchange) wrote a post in 2007 targeted towards developers <a href="http://blog.codinghorror.com/youre-probably-storing-passwords-incorrectly/">“storing passwords incorrectly”</a>. It is worth a read albeit being dated.</p>

<p><strong>Update (04/11/2014):</strong> Is it time for <a href="http://notebook.ideapublic.org/2014/one-less-password/">Passwordless Authentication</a>? Researchers at Mozilla proposed an <em>innovative</em> approach towards login systems which relies on authentication tokens sent to the users’ e-mail address or through SMS. Thoughts?</p>

<p><strong>Update (30/01/2015):</strong> Duncan of <a href="https://vtllf.org/">Vents that Look Like Faces</a> discussed the prospects of <a href="https://vtllf.org/blog/ssh-web-sign-in"><em>piggybacking</em> on existing  SSH technology</a> and using it as an option for web sign-in. A demo was also developed as a proof-of-concept and assessments were made based on usability, deployability and security considerations (part of a scoring framework advanced in <a href="http://research.microsoft.com/pubs/161585/QuestToReplacePasswords.pdf">The Quest to Replace Passwords</a> by Joseph Bonneau, Cormac Herley, Paul C. van Oorschot and Frank Stajano). These considerations allows us to consider the intricacies of attempts at replacing the conventional password system, and it allows us to contextualise the longevity as well as the prevalence of such system design. Through this framework we can weigh the relative advantages and disadvantages of alternative modes of login.</p>

<p><strong>Update (11/09/2015):</strong> Anthony, the editor-in-chief of <a href="http://uxmovement.com/">UX Movement</a>, provides a case for <a href="http://uxmovement.com/forms/why-the-confirm-password-field-must-die/">removing the password confirmation field</a>, and forced password masking as it is likely to lower conversion rate. Similarly, he recommends that a “show password toggle” should instead be offered.</p>

<blockquote>
  <p>By giving users control over their password input, you give them the peace of mind to complete your form.</p>
</blockquote>

<p><strong>Update (08/10/2015):</strong> <a href="http://password-shaming.tumblr.com/">Password Requirements Shaming</a> is yet another Tumblr dedicated towards <em>shaming</em> websites with ridiculous password requirements / questionable management practices. Commentary is included for most of the offending sites.</p>

<p><strong>Update (21/11/2015):</strong> In <a href="http://joelcalifa.com/blog/patronizing-passwords/">Patronizing Passwords</a>, Joel writes:</p>

<blockquote>
  <p>We have to remember that at the end of the day, users are more than just a weak point of security in our systems. Our services exist for our users, not despite them. I like to think there are ways to get people to use strong passwords without forcing their hands and negatively affecting their experience using our products.</p>
</blockquote>

<p><strong>Update (01/12/2015):</strong> In <a href="http://www.developertown.com/the-password-paradox/">The Password Paradox</a>, the author mirrors the aforementioned arguments about password masking:</p>

<blockquote>
  <p>Clear text passwords do increase usability, but don’t force the change on existing users. Password masking is best offered as an option to maintain user trust in the site.</p>
</blockquote>
]]></content:encoded>
</item>

<item>
<title>On Long Showers &amp; Deep Thoughts</title>
<pubDate>Sun, 11 May 2014 15:20:00 +0000</pubDate>
<link>https://www.fyianlai.com/2014/05/on-long-showers-and-deep-thought/</link>
<guid isPermaLink="true">https://www.fyianlai.com/2014/05/on-long-showers-and-deep-thought/</guid>
<dc:creator>Ian Lai</dc:creator>
<description><![CDATA[<p>The following post is a <em>x-post</em> from my [private] Tumblr. I think this is the only post from my Tumblr worthy of being included here (available for the public, if anyone is even interested; and search engines). The post was in response to (or rather, just building upon) an <a href="http://edwardspoonhands.com/post/81366082695/hank-is-there-any-psychological-or-biological-reason">answer provided by Hank Green</a> to a question posed by another Tumblr user.</p>

<hr />

<blockquote>
  <p><a href="http://lukemichael5.tumblr.com/"><strong>lukemichael5 asked:</strong></a></p>

  <p>Hank, Is there any psychological or biological reason for why people stand in the shower for a long time when thinking? Does the running water provide any mental relief? Could there be an evolutionary reason why? Have I asked too many questions for you to answer? (Probably)</p>
</blockquote>

<blockquote>
  <p><a href="http://edwardspoonhands.com/post/81366082695/hank-is-there-any-psychological-or-biological-reason"><strong>edwardspoonhands answered:</strong></a></p>

  <p>I honestly think it’s because every other moment of the day is filled up with THING TO DO! ADVERTISEMENT! SMARTPHONE! STIMULUS! GET IN THE CAR! DO THING! STOP STOPPING! START STARTING! NO THINKY! THINKY BAD! GO GO SPEND WATCH DO MOVE GO! The shower is like, the last place where you can feel ok about just standing there.</p>
</blockquote>

]]></description>
<content:encoded><![CDATA[<p>The following post is a <em>x-post</em> from my [private] Tumblr. I think this is the only post from my Tumblr worthy of being included here (available for the public, if anyone is even interested; and search engines). The post was in response to (or rather, just building upon) an <a href="http://edwardspoonhands.com/post/81366082695/hank-is-there-any-psychological-or-biological-reason">answer provided by Hank Green</a> to a question posed by another Tumblr user.</p>

<hr />

<blockquote>
  <p><a href="http://lukemichael5.tumblr.com/"><strong>lukemichael5 asked:</strong></a></p>

  <p>Hank, Is there any psychological or biological reason for why people stand in the shower for a long time when thinking? Does the running water provide any mental relief? Could there be an evolutionary reason why? Have I asked too many questions for you to answer? (Probably)</p>
</blockquote>

<blockquote>
  <p><a href="http://edwardspoonhands.com/post/81366082695/hank-is-there-any-psychological-or-biological-reason"><strong>edwardspoonhands answered:</strong></a></p>

  <p>I honestly think it’s because every other moment of the day is filled up with THING TO DO! ADVERTISEMENT! SMARTPHONE! STIMULUS! GET IN THE CAR! DO THING! STOP STOPPING! START STARTING! NO THINKY! THINKY BAD! GO GO SPEND WATCH DO MOVE GO! The shower is like, the last place where you can feel ok about just standing there.</p>
</blockquote>

<!--more-->

<p>I’m going to take a shot at this question since I’ve been <a href="/2013/07/28/building-a-new-home/" title="Building a new home">pondering over it</a> for some time, looking for the right <em>[scientific] answer(s).</em> Based on what I know, I think it is a combination of both psychological and biological reasons: cognitive neuroscience (perhaps some elements of behavioural psychology as well).</p>

<p>Apologies for my naive response, as a disclaimer I am not an expert so take what I say with a grain of salt.</p>

<h2 id="it-is-biology">It is biology…</h2>

<p>Firstly, the “thinking” part of a long shower I believe is - as Hank stated - a result of a <a href="http://journals.lww.com/investigativeradiology/Citation/1988/01000/The_Study_of_Perception.10.aspx">bombardment of stimuli</a> from our sensory organs in our everyday lives. Obviously, our central nervous system (CNS) isn’t capable of responding to each and every one of the stimuli and consequently, we have developed (un)conscious filtering mechanisms - see <a href="http://en.wikipedia.org/wiki/Selective_perception">selective perception</a>. In the shower however, we aren’t subjected to this bombardment (or at least my showers aren’t) that has been exacerbated by the internet and social media in particular over the past couple of years. I suppose this is why we can be in a <em>state of Zen</em> and <em>think better</em>, inevitably losing track of time.</p>

<p>As the saying goes, a hot shower helps takes your mind off things <em>(escape from reality?).</em></p>

<p>I don’t think that answers the question really well though.</p>

<p>If we unpack the first answer further, I suppose it is because showers are essentially <a href="http://en.wikipedia.org/wiki/Hydrotherapy">hydrotherapy</a>. It is a natural sedative due to the way our body responds to things like the temperature and the pressure exerted by the water (the hydrostatic effect of water generates a sort of “massage-like feeling”). These sensations are communicated through our nerves, to our CNS, and to the rest of our body - <a href="http://www.naturaltherapypages.com.au/article/hydrotherapy">stimulating and invigorating</a> various bodily activities, e.g. <a href="http://www.scientificamerican.com/article/why-do-you-think-better-after-walk-exercise/">improving our blood circulation which may be a contributing factor to our improved ability to think</a>.</p>

<p>Indeed, <a href="http://www.medical-hypotheses.com/article/S0306-9877(07)00376-3/abstract">a study showed</a> that “a moderately hot shower, could have a ‘crowding out’ effect on pathological processes within the mesolimbic system”. Simply put, [moderately hot] water does provide mental and physical relief by suppressing pain-related neurotransmission / negative stimuli. Cold water however, may depress activity of the frontal cortex (sedative effect). See <a href="http://neuroscience.uth.tmc.edu/s2/chapter08.html">pain modulations and mechanisms</a>.</p>

<p>It is no wonder why we may often find showers so relaxing. It is therapeutic.</p>

<h2 id="but-psychology">But, psychology!</h2>

<p>I figured I should include a section about psychology as well because a. I am going to assume there will be anomalies and if so, psychology can account for the differences; and b. I like psychology.</p>

<p>Firstly, our behaviour and appreciation of standing “in the shower for a long time when thinking” may have been developed over time through psychological conditioning. The <a href="http://www.sparknotes.com/psychology/psych101/learning/section2.rhtml">law of effect</a> states that any behavior that has good consequences will tend to be repeated, and any behavior that has bad consequences will tend to be avoided. This is known as <a href="http://psychology.about.com/od/behavioralpsychology/a/classical-vs-operant-conditioning.htm">operant conditioning</a> (learning based on the consequences of previous occurrences of the behaviour).</p>

<p>As I have explained earlier, the consequences of long showers may be the alleviation of stress (negative reinforcement) and/or the enhanced ability to think (positive reinforcement). If you find this desirable, the frequency of the behaviour being repeated will be increased. Think of it this way, you’re more likely to behave in class if it means getting some sort of reward from your teacher or reducing the likelihood of a punishment. In this case, you may resort to a [long] shower if it helps you escape all the stress caused by the stimuli you have received in your surroundings.</p>

<p>Before I conclude, I think it is worth mentioning the <a href="https://www.boundless.com/psychology/motivation/approaches-to-explaining-motivation/drive-reduction-theory/">drive-reduction theory</a> despite its pitfalls. The theory states that “humans are motivated to reduce the state of tension caused when certain biological needs are not satisfied”. Basically, we are motivated / driven to behave in certain ways by the active need to maintain a certain state of balance or equilibrium (<a href="http://en.wikipedia.org/wiki/Homeostasis">homeostasis</a>). Building on what I’ve already mentioned in the last paragraph, the reduction of the drive acts as a reinforcement for that behaviour. I may be overextending this theory for this question, but a long shower may satisfy our need to think or relax, and its success / reliability in doing so will reinforce our craving for it.</p>

<p>With that being said, will you stand in the shower for a long time when thinking if it was extremely cold or hot?</p>

<p>Suum cuique pulchrum est. To each his own is beautiful.</p>

<h4 id="there-may-be-an-evolutionary-explanation-but-it-is-too-fluffy-and-subject-to-a-lot-of-criticisms">There may be an <a href="http://www.reddit.com/r/explainlikeimfive/comments/1gk3vm/eli5_why_do_humans_have_such_a_strong_desire_to/cal5v5m">evolutionary explanation</a>, but it is too fluffy and subject to a lot of criticisms.</h4>

<p>To close, biology and psychology works hand in hand to explain the phenomenon that is showers and thinking.</p>

<p>Perhaps this can also explain why you think a lot when you are about to sleep or when you meditate / partake in yoga, Tai chi, etc.</p>

<p><em>I was tempted to say, science and psychology, but that would imply psychology is not a science which may be offensive. That is another debate for another day…</em></p>

<p><strong>TL;DR:</strong> Read everything from the beginning.</p>
]]></content:encoded>
</item>

<item>
<title>Moving Forward</title>
<pubDate>Fri, 03 Jan 2014 03:34:00 +0000</pubDate>
<link>https://www.fyianlai.com/2014/01/moving-forward/</link>
<guid isPermaLink="true">https://www.fyianlai.com/2014/01/moving-forward/</guid>
<dc:creator>Ian Lai</dc:creator>
<description><![CDATA[<h2 id="out-with-the-old-and-in-with-the-new">Out with the old and in with the new.</h2>

<p>Towards the end of 2013, I decided that I was going to begin blogging more often <em>(or at least try to)</em> and that I was going to do so on my existing WordPress platform. It was not a decision made as part of my New Year’s resolution for 2014 and indeed, it may never materialise.</p>

<p>I nevertheless took the first steps by removing all my old and unimportant posts as they felt like a distraction and dead weight. For the old and slightly more important posts (the ones that are bringing me traffic) I decided to update them (four actually) and to tag them as Legacy. I worked sporadically over a period of one month - as I have been busy - before I was finally satisfied to make a post about it today.</p>

]]></description>
<content:encoded><![CDATA[<h2 id="out-with-the-old-and-in-with-the-new">Out with the old and in with the new.</h2>

<p>Towards the end of 2013, I decided that I was going to begin blogging more often <em>(or at least try to)</em> and that I was going to do so on my existing WordPress platform. It was not a decision made as part of my New Year’s resolution for 2014 and indeed, it may never materialise.</p>

<p>I nevertheless took the first steps by removing all my old and unimportant posts as they felt like a distraction and dead weight. For the old and slightly more important posts (the ones that are bringing me traffic) I decided to update them (four actually) and to tag them as Legacy. I worked sporadically over a period of one month - as I have been busy - before I was finally satisfied to make a post about it today.</p>

<!--more-->

<h3 id="the-legacy">The legacy.</h3>

<p>In computing, the term legacy is used to denote software or hardware that has been superseded but is difficult to replace because of its wide use [Oxford Dictionary]. The older versions of Internet Explorer for example, were considered legacy web browsers for some time (and I am not too sure if it is still the case) until there were major strides in the online community towards pushing for more modern alternatives including Google Chrome and Firefox - hence, their increasing market share.</p>

<p>I have marked four of my web design / development related posts as legacy as I do not intend on updating them anymore. Thus, the contents of the posts - be it technical or purely descriptive - may or may not be relevant today or in the near future. The <a href="/2012/02/wordpress-boilerplate-custom-database/" title="WordPress: Connecting to an external/secondary database">WordPress code</a> I have written for example, may no longer be usable in the near future (it should still be at the time of this post) due to WordPress rapid development cycle. Furthermore, my <a href="/2012/02/web-design-and-development-bookmarks-part-1/" title="Web design and development bookmarks – part 1">web design / development bookmarks</a> may no longer be accessible or useful due to the quick evolution of technologies and of trends in the web arena.</p>

<p>Perhaps one day I will remove them, but for now I am keeping them as I believe it still adds some value to my barren website (and hopefully to the web community which I owe a lot to).</p>

<h3 id="the-unimportant">The unimportant.</h3>

<p>If I recall correctly, I had previously mentioned somewhere that I was unsure of what I should do with my older posts and that I felt they should be kept as they served almost like a time capsule and an insight to my past. Well, I decided to remove them, but only from the public. I still have a backup with me, but I highly doubt I will ever go back through it. Indeed, I could not even be bothered to look at my previous two posts before I decided to write this.</p>

<p>They are a burden to keep and would give a misconception of who I am today. Maybe I am being a bit too pessimistic, but I am convinced humans are naturally <a href="/2013/04/i-dont-care-really/" title="I don’t care, really">judgmental by nature</a> <em>(I do care now)</em>, be it conscious or unconscious, we all judge and build preconceived notions of others to aid our everyday interaction. I intend on keeping this website professional unlike its past.</p>

<h3 id="the-wordpress">The WordPress.</h3>

<p>The recent <a href="http://wordpress.org/">WordPress 3.8 update (“Parker”)</a> reminded me of why I had started with it instead of all the other solutions available. Simply, it is innovative, open and flexible. A huge time-saver as well! If there is any <a href="/2013/07/building-a-new-home/" title="Building a new home">reasons why I am not comfortable blogging</a> I do not think it has anything to do with the platform anymore. I was probably making excuses before (<a href="http://medium.com">Medium</a> is still pretty cool though). The new admin UI changes on WordPress are nevertheless absolutely stunning. Perhaps once I have developed a custom theme (not that there is anything wrong with the existing one) and switched over to Markdown - which should hopefully be included in JetPack soon - it will start to feel more like home.</p>

<h2 id="finally-going-rogue">Finally, going rogue.</h2>

<p>Besides Twitter and YouTube, I just do not feel social anymore. Both online and offline. I have tried to remove myself from all of it, or at least remove my identity. I have deleted my Tumblr in the process and made private my Twitter account (to hide it from the prying eyes of a particular person, or people, I am not too sure…).</p>

<p>If there is anything I would like to dedicate more time to it will probably be the open source community, particularly in the web sector. Thus, I have tried to be more active on <a href="https://github.com/MrSaints">GitHub</a> and like my legacy posts I have decided to update my old repositories as well.</p>

<p>Nothing relieves my stress more than coding. There are times when it can get frustrating, but I always feel like I am more in control. In our world however, it feels like there are things that we can not control and circumstances that we can not alter. If my code is not functioning the way it should, I know it is because of my incompetency and I know, I can fix it with enough persistence. It is also extremely gratifying to design and build whatever you like or whatever comes to mind with simply a computer and an internet connection.</p>

<p>Maybe that is why I do not feel social anymore. I do not feel in control of social situations and they simply add to my stress.</p>

<p>Regardless, the web is awesome.</p>

<h3 id="that-is-all-for-now">That is all for now.</h3>

<p>Happy new year.</p>
]]></content:encoded>
</item>

<item>
<title>Building a New Home</title>
<pubDate>Sun, 28 Jul 2013 06:19:00 +0000</pubDate>
<link>https://www.fyianlai.com/2013/07/building-a-new-home/</link>
<guid isPermaLink="true">https://www.fyianlai.com/2013/07/building-a-new-home/</guid>
<dc:creator>Ian Lai</dc:creator>
<description><![CDATA[<p>It is unbelievable how I am able to think of so much to talk about and to write about when I am trying to sleep or when I am taking a shower; however, when I attempt to convey my thoughts, I am unable to synthesise the blob that is in my brain. For a long time (and even most recently) I have tried to convince myself that it was due to my <a href="/2013/04/i-dont-care-really/">insecurities and fear of creating an abomination of unguided thoughts</a>, a Frankenstein. I am a master to countless number of Frankensteins and one need only browse my archives to discover them. Perhaps once I have developed an environment that is conducive for the interaction of my thoughts and my social skills (writing and speaking in this context) will I be capable of overcoming this obstacle - the “right state of mind”.</p>

]]></description>
<content:encoded><![CDATA[<p>It is unbelievable how I am able to think of so much to talk about and to write about when I am trying to sleep or when I am taking a shower; however, when I attempt to convey my thoughts, I am unable to synthesise the blob that is in my brain. For a long time (and even most recently) I have tried to convince myself that it was due to my <a href="/2013/04/i-dont-care-really/">insecurities and fear of creating an abomination of unguided thoughts</a>, a Frankenstein. I am a master to countless number of Frankensteins and one need only browse my archives to discover them. Perhaps once I have developed an environment that is conducive for the interaction of my thoughts and my social skills (writing and speaking in this context) will I be capable of overcoming this obstacle - the “right state of mind”.</p>

<!--more-->

<p>A part of me however, has begun considering the possibility that I may not have come to terms with the observed fact that anything non-mathematical is incapable of achieving perfection (thanks Plato, really). I feel it is crucial for any writing or social platform to emulate the sort of environment we experience in real life to provide the necessary psychological cues and to hence, create a genuine experience; a sense of home. For example, I have recently sought refuge at <a href="http://www.medium.com">Medium</a> and have attempted to publish my first writing but to no avail. Being the amour-propre (I use this term very loosely) man who I am, Medium’s lack of author attribution (and rights) is unappealing to me and while it succeeds in creating a “social experience” I can call home, this home is definitely not mine. It is not one which I can call <a href="/">fyianlai.com</a>, that is for sure. Meanwhile, my existing WordPress web site is one which I can call <a href="/">fyianlai.com</a>, but it is not one which can emulate the serenity that I experience in a distraction-free, warm shower or in my cosy bed - at least not to the extent at which Medium achieves it. Obviously developing my own platform is the only advisable option at this point, but that brings me back to the original <del>question</del> problem, how do I achieve the utopian platform?</p>

<p>I have been stuck at a creative and to some extent, a logical block these past few days while trying to brainstorm ideas for my web site’s design and its features. Should I pursue the “static site” approach or should I consider the “dynamic” approach instead? How should it look like and how do I design it so that it does not seem like a complete rip-off from another site? Building a new home is not easy. There are a lot of considerations and re-branding is definitely one of them. One consideration leads to another. Indeed, if re-branding is the key objective then the technologies utilised would say a lot about you as a web developer, and particularly your awareness about the current trends. If I am incapable of achieving the “perfect platform”, how certain can I be that simply moving out of WordPress would encourage me to be more “social” in my internet home?</p>

<p>I am uncertain if my dilemma lies in a failure to emulate an experience, or if its philosophically and psychologically related. The latter being my absurd pursuit for perfection and a simultaneous recognition of the lack of feasibility of such task. For example, I would commit an unnecessary amount of time to formulate what I deem the “perfect essay” that would encompass all relevant sources I have acquired only to resent it the moment I discover flaws and imperfections. Based on the aforementioned assessment and example, I suppose my passivity can only be explained as an equilibrium, and specifically, a mental stalemate whereby doing nothing will achieve less psychological conflict. I find myself difficult to analyse sometimes so my only solution for now is to search and destroy all possible roots of the problem. Indeed, I am writing this post to address the latter problem, hoping that I would eventually condition myself into accepting and ignoring this cognitive dissonance. After all, practice makes <em>perfect</em>.</p>

<p>It is this process of self-discovery that really fascinates me. After all, humans are dynamic in nature and unlike mathematics, we can not achieve the same level of objectivity, but that is something I will save for and discuss in a future post.</p>

<blockquote>
  <p>Seeing then that truth consisteth in the right ordering of names in our affirmations, a man that seeketh precise truth had need to remember what every name he uses stands for, and to place it accordingly; or else he will find himself entangled in words, as a bird in lime twigs; the more he struggles, the more belimed. And therefore in <strong>geometry (which is the only science that it hath pleased God hitherto to bestow on mankind)</strong>, men begin at settling the significations of their words; which settling of significations, they call <strong>definitions</strong>, and place them in the beginning of their reckoning.</p>

  <p><strong>- Hobbes, Leviathan</strong></p>
</blockquote>
]]></content:encoded>
</item>

<item>
<title>I Don't Care, Really</title>
<pubDate>Sat, 27 Apr 2013 10:56:00 +0000</pubDate>
<link>https://www.fyianlai.com/2013/04/i-dont-care-really/</link>
<guid isPermaLink="true">https://www.fyianlai.com/2013/04/i-dont-care-really/</guid>
<dc:creator>Ian Lai</dc:creator>
<description><![CDATA[<p>I am well, thanks for asking. It has been a while since I posted anything here. There are a few reasons why but I guess the main reason is my fear of judgement by others. It is the same reason why I have deleted most of my blogs in the past a few months after I have created them.</p>

]]></description>
<content:encoded><![CDATA[<p>I am well, thanks for asking. It has been a while since I posted anything here. There are a few reasons why but I guess the main reason is my fear of judgement by others. It is the same reason why I have deleted most of my blogs in the past a few months after I have created them.</p>

<!--more-->

<p>A recurring process of self-reflection has often made me dissatisfied with my past behaviour and even my past writings. The process is further catalysed by my concerns that as a native English speaker and a student in a somewhat prestigious university, it is necessary for me to be well-versed in the English language and articulative. After all, I am currently pursuing a course that is essay-based in its entirety. I am unfortunately, terrible at phrasing complex sentences according to many of my past English teachers and their criticisms in the past have to some extent, diminished my confidence in publicising any of my writings. I am nevertheless, grateful for their guidance.</p>

<p>My grasp of language however, is not the only reason why and I feel I am often constrained by demand characteristics. For those who know me personally, I can be quite critical on certain issues and I feel my opinions may be strongly opposed or even criticised. I honestly dislike making mistakes and I do not like pre-conceptions of me based around mere words.</p>

<p>Finally, as a “self-proclaimed web developer and designer”, I have a rather bad ego which makes me reconsider the way I have presented my posts, from the little things like the formatting to things like the theme and colour scheme.</p>

<p>I have a brain bug that is making conscious reconsiderations before I make a post and after I make one. It is killing me because I am unable to express myself and for some reason I think going on a hiatus or deleting myself off the internet is the only way to solve it.</p>

<p>It seems as though, the more I read what I have written or even work on something I have created (e.g. a web application), the more I find flaws with it and dislike it entirely. I guess I can never be satisfied.</p>

<p>It may seem quite ironic that I am finally expressing myself through this post. I wished I had this figured out before I massacred my past writings. Simply put: I don’t care. Welcome to my website. A home for my thoughts. I am tired of being stuck in an online identity crisis that is constrained by my Schizophrenic tendencies. Humans are instinctively judgemental and I should not have let that defined who I am. If anything, I should have kept my old posts and continued posting as it would have shown an evolution of myself, as an individual - a timecapsule of me. I am not politically correct and neither is anyone if you are speaking in terms of social constructivism. If I am empirically incorrect, I will learn from my mistakes. I am not writing an academic paper so I shouldn’t even be concerned about my linguistic abilities, even so, most academic writings I have read are poorly articulated.</p>

<p>In short, I have conquered my fear. I do not know why or how but I suppose several experiences in the past have made me realise that we are all the same, simply looking to stand out from a pool of tiny units in a vast cosmos just so we feel different from all the other units for a while. Here is the legitimate me. I am happy in my own way and I don’t care even if this post is redundant. I am just going to keep moving forward.</p>
]]></content:encoded>
</item>

<item>
<title>Web Design &amp; Development Bookmarks - Part 2</title>
<pubDate>Sun, 25 Mar 2012 17:32:00 +0000</pubDate>
<link>https://www.fyianlai.com/2012/03/web-design-and-development-bookmarks-part-2/</link>
<guid isPermaLink="true">https://www.fyianlai.com/2012/03/web-design-and-development-bookmarks-part-2/</guid>
<dc:creator>Ian Lai</dc:creator>
<description><![CDATA[<p>The following is a <em>re-mastered</em> collection of bookmarks from <strong>March 2012</strong> comprising of what I deem are useful web design and development resources, libraries, articles, etc. They were obtained from a variety of sources such as <a href="http://www.codevisually.com">CodeVisually</a>, <a href="http://www.speckyboy.com">Speckyboy</a>, <a href="http://www.smashingmagazine.com">Smashing Magazine</a>, <a href="http://www.nettuts.com">NETTUTS</a> and <a href="http://news.ycombinator.com/">Hacker News</a>.</p>

]]></description>
<content:encoded><![CDATA[<p>The following is a <em>re-mastered</em> collection of bookmarks from <strong>March 2012</strong> comprising of what I deem are useful web design and development resources, libraries, articles, etc. They were obtained from a variety of sources such as <a href="http://www.codevisually.com">CodeVisually</a>, <a href="http://www.speckyboy.com">Speckyboy</a>, <a href="http://www.smashingmagazine.com">Smashing Magazine</a>, <a href="http://www.nettuts.com">NETTUTS</a> and <a href="http://news.ycombinator.com/">Hacker News</a>.</p>

<!--more-->

<p>For a full list of content-curation web sites and users you can check out my <a href="https://twitter.com/MrSaints/friends">Twitter list here</a>. I have discontinued my “web dev/design bookmark” series of posts in favour of a unified collection of bookmarks in Evernote. You can check that out <a href="https://www.evernote.com/shard/s233/sh/473897f7-0543-4b26-b849-18ded36d3236/f972fb216d32beb01866bc45615f87c8?noteKey=f972fb216d32beb01866bc45615f87c8&amp;noteGuid=473897f7-0543-4b26-b849-18ded36d3236">here</a> - I have not included some of the links below.</p>

<p>I originally created this blog post along with <a href="/2012/02/web-design-and-development-bookmarks-part-1/">part 1</a> because I wanted to curate a list of useful links that I could come back to in the future, especially in cases where I vaguely remember where a certain resource or an article was from. There are a lot of cool stuff on the internet and sometimes you do not want to lose track of it.</p>

<p>The web design and development community is vast and fascinating. If you are part of it, hopefully you would have figured that out by now and if not, you need only to explore all the links in this post to understand what I mean.</p>

<p>I apologise in advance if any of the links below no longer work. I will not keep the following post updated anymore as I have previously mentioned. I hope you will nevertheless find this post of some use.</p>

<hr />

<h3 id="html--css--js">HTML / CSS / JS</h3>

<ul>
  <li><a href="http://www.developerdrive.com/2012/03/pushing-updates-to-the-web-page-with-html5-server-sent-events/">Pushing Updates to the Web Page with HTML5 Server-Sent Events</a></li>
  <li><a href="http://www.webstuffshare.com/2012/03/sweet-tooltip-a-jquery-css3-tooltips/">jQuery &amp; CSS3 Tooltips</a></li>
  <li><a href="http://davidwalsh.name/webkit-css">WebKit Marquee CSS: Bringin’ Sexy Back</a></li>
  <li><a href="http://davidwalsh.name/webkit-css">Interesting -webkit CSS Properties</a></li>
  <li><a href="http://net.tutsplus.com/tutorials/html-css-techniques/sass-vs-less-vs-stylus-a-preprocessor-shootout/">Sass vs. LESS vs. Stylus: Preprocessor Shootout</a></li>
  <li><a href="http://paulirish.com/2012/vendor-prefixes-are-not-developer-friendly/">Vendor prefixes are not developer-friendly</a></li>
  <li><a href="http://paulirish.com/2012/box-sizing-border-box-ftw/">Paul Irish: * { box-sizing: border-box } FTW (Solving Width &amp; Padding Problem</a><a href="http://paulirish.com/2012/box-sizing-border-box-ftw/">s)</a></li>
  <li><a href="http://osvaldas.info/blog/more-noticeable-html-bookmarks">More Noticeable HTML Bookmarks (jQuery)</a></li>
  <li><a href="http://codevisually.com/fontomas-a-tool-that-helps-to-combine-iconic-webfonts/">Fontomas – A tool that helps to combine Iconic webfonts</a></li>
  <li><a href="http://tympanus.net/codrops/2012/03/27/login-and-registration-form-with-html5-and-css3/">Login and Registration Form With HTML5 and CSS3</a></li>
  <li><a href="http://html5doctor.com/using-modernizr-to-detect-html5-features-and-provide-fallbacks/">Using Modernizr to detect HTML5 features and provide fallbacks</a></li>
  <li><a href="http://joelb.me/blog/2012/maintaining-css-style-states-using-infinite-transition-delays/">Maintaining CSS Style States using “Infinite” Transition Delays</a></li>
  <li><a href="http://www.inwebson.com/jquery/jqfloat-js-a-floating-effect-with-jquery/">jqFloat.js – A Floating Effect with jQuery!</a></li>
</ul>

<h3 id="frameworks--libraries">Frameworks / Libraries</h3>

<ul>
  <li><a href="https://github.com/donatkinson/bootstrapwp-Twitter-Bootstrap-for-WordPress">Twitter Bootstrap For Wordpress</a></li>
  <li><a href="http://addyosmani.github.com/basket.js/">basket.js - A simple (proof-of-concept) script loader that caches scripts with localStorage</a></li>
  <li><a href="http://chico-ui.com.ar/">Chico UI - A free and open source collection of easy-to-use web tools for developers and designers</a></li>
  <li><a href="http://getskeleton.com/#">Skeleton - A Beautiful Boilerplate for Responsive, Mobile-Friendly Development</a></li>
  <li><a href="http://www.dexy.it/">Dexy - “The Most Powerful, Flexible Documentation Tool Ever”</a></li>
  <li><a href="http://needim.github.com/noty/">noty – Easily create alert, success, error and confirmation messages</a></li>
</ul>

<h3 id="inspiration">Inspiration</h3>

<ul>
  <li><a href="http://speckyboy.com/2011/05/08/building-a-great-web-design-portfolio-%E2%80%93-10-best-tips-40-examples/">Building a Great Web Design Portfolio – 10 Best Tips &amp; Examples </a></li>
  <li><a href="http://speckyboy.com/2010/05/27/five-alternative-methods-for-typography-inspiration/">Five Alternative Methods for Typography Inspiration</a></li>
  <li><a href="http://speckyboy.com/2010/11/14/18-super-quick-web-typography-tips-for-newbies/">18 Super Quick Web Typography Tips for Newbies</a></li>
</ul>

<h3 id="free-resources">Free Resources</h3>

<ul>
  <li><a href="http://simptp.webege.com/">Simple Tape - Free Minimalist HTML Site Template </a></li>
  <li><a href="http://www.eleventhemes.com/stumblr-theme/">Stumblr - Tumblr Style Wordpress Theme (Micro Blog)</a></li>
  <li><a href="http://speckyboy.com/2010/05/30/liquid-fluid-and-elastic-layout-templates-tools-and-frameworks/">Liquid, Fluid and Elastic Layout Templates, Tools and Frameworks</a></li>
  <li><a href="http://www.webdesignerdepot.com/2012/03/free-download-inspire-backend-admin-template-psd/">Free download: “Inspire” Backend Admin Template (PSD)</a></li>
  <li><a href="http://inspectelement.com/freebies/origin-lite-a-free-wordpress-theme/">Origin: Free Wordpress Theme</a></li>
</ul>

<h3 id="optimization--testing">Optimization / Testing</h3>

<ul>
  <li><a href="http://speckyboy.com/2012/03/12/website-speed-part-4-php-programming-for-speed/">Website Speed Part 4: PHP Programming for Speed</a></li>
  <li><a href="http://codebomber.com/jquery/resizer/">Resizer - A responsive design bookmarklet</a></li>
  <li><a href="http://calendar.perfplanet.com/2011/why-inlining-everything-is-not-the-answer/">Why Inlining Everything Is NOT The Answer</a></li>
  <li><a href="http://dirtymarkup.com/">Dirty Markup – Tidy and beautify your HTML, CSS &amp; JS code</a></li>
  <li><a href="http://kraken.io/">Kraken Web Optimizer - Online Optimization Tool</a></li>
  <li><a href="http://typedjs.com/">TypedJS - Sanity Check Your JavaScript</a></li>
</ul>

<h3 id="others">Others</h3>

<ul>
  <li><a href="http://speckyboy.com/2012/03/06/weekly-design-news-resources-tutorials-and-freebies-n-123/">More Resources, Tutorials &amp; Freebies (Speckyboy Weekly 06/03)</a></li>
  <li><a href="http://speckyboy.com/2012/03/15/50-time-saving-photoshop-actions-to-boost-your-images/">50 Time Saving Photoshop Actions To Boost Your Images</a></li>
  <li><a href="http://www.smashingmagazine.com/2012/03/09/top-non-destructive-photoshop-techniques/">Top Non-Destructive Photoshop Techniques</a></li>
  <li><a href="http://net.tutsplus.com/tutorials/php/php-5-4-is-here-what-you-must-know/">PHP 5.4 is Here! What You Must Know</a></li>
  <li><a href="http://wp.smashingmagazine.com/2012/03/22/useful-wordpress-tools-themes-plugins/">Useful WordPress Tools, Themes And Plugins</a></li>
  <li><a href="http://medialoot.com/blog/high-resolution-web/">How to Prepare for The High-Resolution Web</a></li>
</ul>
]]></content:encoded>
</item>

<item>
<title>Web Design &amp; Development Bookmarks - Part 1</title>
<pubDate>Fri, 24 Feb 2012 04:17:00 +0000</pubDate>
<link>https://www.fyianlai.com/2012/02/web-design-and-development-bookmarks-part-1/</link>
<guid isPermaLink="true">https://www.fyianlai.com/2012/02/web-design-and-development-bookmarks-part-1/</guid>
<dc:creator>Ian Lai</dc:creator>
<description><![CDATA[<p>The following is a <em>re-mastered</em> collection of bookmarks from <strong>February 2012</strong> comprising of what I deem are useful web design and development resources, libraries, articles, etc. They were obtained from a variety of sources such as <a href="http://www.codevisually.com">CodeVisually</a>, <a href="http://www.speckyboy.com">Speckyboy</a>, <a href="http://www.smashingmagazine.com">Smashing Magazine</a>, <a href="http://www.nettuts.com">NETTUTS</a> and <a href="http://news.ycombinator.com/">Hacker News</a>.</p>

]]></description>
<content:encoded><![CDATA[<p>The following is a <em>re-mastered</em> collection of bookmarks from <strong>February 2012</strong> comprising of what I deem are useful web design and development resources, libraries, articles, etc. They were obtained from a variety of sources such as <a href="http://www.codevisually.com">CodeVisually</a>, <a href="http://www.speckyboy.com">Speckyboy</a>, <a href="http://www.smashingmagazine.com">Smashing Magazine</a>, <a href="http://www.nettuts.com">NETTUTS</a> and <a href="http://news.ycombinator.com/">Hacker News</a>.</p>

<!--more-->

<p>For a full list of content-curation web sites and users you can check out my <a href="https://twitter.com/MrSaints/friends">Twitter list here</a>. I have discontinued my “web dev/design bookmark” series of posts in favour of a unified collection of bookmarks in Evernote. You can check that out <a href="https://www.evernote.com/shard/s233/sh/473897f7-0543-4b26-b849-18ded36d3236/f972fb216d32beb01866bc45615f87c8?noteKey=f972fb216d32beb01866bc45615f87c8&amp;noteGuid=473897f7-0543-4b26-b849-18ded36d3236">here</a> - I have not included some of the links below.</p>

<p>I originally created this blog post along with <a href="/2012/03/web-design-and-development-bookmarks-part-2/">part 2</a> because I wanted to curate a list of useful links that I could come back to in the future, especially in cases where I vaguely remember where a certain resource or an article was from. There are a lot of cool stuff on the internet and sometimes you do not want to lose track of it.</p>

<p>The web design and development community is vast and fascinating. If you are part of it, hopefully you would have figured that out by now and if not, you need only to explore all the links in this post to understand what I mean.</p>

<p>I apologise in advance if any of the links below no longer work. I will not keep the following post updated anymore as I have previously mentioned. I hope you will nevertheless find this post of some use.</p>

<hr />

<h3 id="html--css--js">HTML / CSS / JS</h3>

<ul>
  <li><a href="http://www.sitepoint.com/pure-css3-paper-curl/">How to Create CSS3 Paper Curls Without Images</a></li>
  <li><a href="http://www.paulund.co.uk/creating-different-css3-box-shadows-effects">Different CSS3 Box Shadows Effects</a></li>
  <li><a href="http://webdesign.tutsplus.com/tutorials/site-elements/orman-clarks-chunky-3d-web-buttons-the-css3-version/">Orman Clark’s Chunky 3D Web Buttons: The CSS3 Version</a></li>
  <li><a href="http://learnjquery.tutsplus.com/">Learn jQuery In 30 Days</a></li>
  <li><a href="http://www.html5canvastutorials.com/">HTML5 Canvas Tutorials</a></li>
  <li><a href="http://html5please.com/">HTML5 Please - Use the new and shiny responsibly</a></li>
  <li><a href="http://orderedlist.com/blog/articles/flared-borders-with-css/">Flared Borders With CSS</a></li>
  <li><a href="http://speckyboy.com/2012/02/15/how-to-build-a-stylish-css3-search-box/">How to Build a Stylish CSS3 Search Box</a></li>
  <li><a href="https://developer.mozilla.org/en/CSS/CSS_Reference">CSS Reference</a></li>
  <li><a href="http://tympanus.net/codrops/2011/11/09/interactive-html5-typography/">Interactive Typography Effects With HTML5</a></li>
  <li><a href="http://tympanus.net/codrops/2011/10/24/creative-css3-animation-menus/">Creative CSS3 Animation Menus</a></li>
  <li><a href="http://www.uiparade.com/wp-content/themes/artiste/live-tools/ribbon-builder.html">CSS3 Ribbon Builder</a></li>
  <li><a href="http://bearcss.com/">Bear CSS - Generate CSS Based On Your HTML</a></li>
  <li><a href="http://thinkvitamin.com/code/fun-with-html5-forms/">Fun With HTML5 Forms</a></li>
  <li><a href="http://www.nucaptcha.com/">Video Re-Captcha</a></li>
  <li><a href="http://www.josscrowcroft.com/projects/motioncaptcha-jquery-plugin/">MotionCAPTCHA - Stop Spam, Draw Shapes</a></li>
</ul>

<h3 id="frameworks--libraries">Frameworks / Libraries</h3>

<ul>
  <li><a href="http://www.netmagazine.com/tutorials/discover-facebook-s-developer-tools">Discover Facebook’s developer tools</a></li>
  <li><a href="http://fatfree.sourceforge.net/">PHP Fat Free Framework (F3)</a></li>
  <li><a href="http://twitter.github.com/bootstrap/">Bootstrap - HTML/CSS Framework (by Twitter)</a></li>
  <li><a href="http://twitter.github.com/hogan.js/">Hojan.js - 2.5k  JS Templating Engine (by Twitter)</a></li>
  <li><a href="http://microjs.com/">Microjs: Fantastic Micro-Frameworks andMicro-Libraries for Fun and Profit!</a></li>
  <li><a href="http://html5boilerplate.com/">HTML5 Boilerplate</a></li>
  <li><a href="http://www.initializr.com/">Initializr - Start A HTML5 Project In 15 Seconds</a></li>
  <li><a href="http://www.modernizr.com/">Modernizr - Feature Detection</a></li>
  <li><a href="http://yepnopejs.com/">YepNope.JS - ASYNC Conditional Resource Loader</a></li>
  <li><a href="http://www.cdnjs.com/">CDN.JS - CDN For Popular JS Libraries</a></li>
  <li><a href="http://sharrre.com/">Sharrre - A plugin for sharing buttons</a></li>
  <li><a href="https://github.com/mythz/jquip">jQuip - “jQuery In Parts”</a></li>
</ul>

<h3 id="inspiration">Inspiration</h3>

<ul>
  <li><a href="http://sixrevisions.com/web_design/16-best-web-design-galleries-for-inspiration/">16 Best Web Design Galleries for Inspiration</a></li>
  <li><a href="http://www.tuttoaster.com/33-kick-ass-websites-for-your-inspiration/">33 Kick-Ass Websites for Your Inspiration</a></li>
  <li><a href="http://bestdesignoptions.com/?p=4076">20 Magazine Layout Designs for Inspiration</a></li>
  <li><a href="http://speckyboy.com/2008/06/15/32-inspirational-examples-of-amazing-layout-and-typography/">32 Inspiring Examples of Amazing Layout and Typography</a></li>
</ul>

<h3 id="free-resources">Free Resources</h3>

<ul>
  <li><a href="http://inspirationfeed.com/graphics/freebies/50-stunning-pixel-perfect-psd-freebies/">50 Stunning Pixel Perfect PSD Freebies</a></li>
  <li><a href="http://www.webdesignerdepot.com/2011/07/50-psd-ui-web-design-elements/">50+ PSD UI Web design elements</a></li>
  <li><a href="http://webdesign.tutsplus.com/articles/roundups/30-icon-packs-for-web-designers-that-dont-suck/">35+ Icon Packs For Web Designers (That Don’t Suck!)</a></li>
  <li><a href="http://speckyboy.com/2011/09/08/20-more-fresh-free-fonts-for-beautiful-headlines/">20 More Fresh &amp; Free Fonts for Beautiful Headlines</a></li>
  <li><a href="http://www.famfamfam.com/lab/icons/">FAMFAMFAM Icons</a></li>
  <li><a href="http://www.entypo.com/">Entypo - 100+ carefully crafted pictograms</a></li>
  <li><a href="http://codevisually.com/heydings-icons-a-free-fontface-icon-set/">Heydings Icon - A Free @font-face Icon Set</a></li>
</ul>

<h3 id="optimization">Optimization</h3>

<ul>
  <li><a href="http://speckyboy.com/2011/12/02/give-your-site-a-health-check-infographic/">Give Your Site A Health Check (Infographic)</a></li>
  <li><a href="http://fennb.com/microcaching-speed-your-app-up-250x-with-no-n/">Microcaching: Speed your app up 250x with no new code</a></li>
  <li><a href="https://optimizely.appspot.com/">Optimizely: A/B Testing</a></li>
</ul>

<h3 id="others">Others</h3>

<ul>
  <li><a href="http://www.graphicmania.net/tips-for-creating-a-magazine-layout-in-indesign/">Tips for Creating a Magazine Layout in InDesign</a></li>
  <li><a href="http://acko.net/blog/this-is-your-brain-on-css/">Your Brain On CSS - CSS 3D Demo</a></li>
  <li><a href="http://www.photonstorm.com/archives/2759/the-reality-of-html5-game-development-and-making-money-from-it">The Reality of HTML5 Game Development and making money from it</a></li>
  <li><a href="http://www.catswhocode.com/">Useful PHP Snippets &amp; More</a></li>
  <li><a href="http://nicolasgallagher.com/about-normalize-css/">About normalize.css</a></li>
  <li><a href="http://www.alistapart.com/articles/taking-advantage-of-html5-and-css3-with-modernizr/">Taking Advantage of HTML5 and CSS3 with Modernizr</a></li>
</ul>
]]></content:encoded>
</item>

<item>
<title>WordPress: Connecting to an External / Secondary Database</title>
<pubDate>Mon, 06 Feb 2012 04:06:00 +0000</pubDate>
<link>https://www.fyianlai.com/2012/02/wordpress-boilerplate-custom-database/</link>
<guid isPermaLink="true">https://www.fyianlai.com/2012/02/wordpress-boilerplate-custom-database/</guid>
<dc:creator>Ian Lai</dc:creator>
<description><![CDATA[<p><strong><code class="highlighter-rouge">$wpdb</code> can only access and manipulate the WordPress database. How may I do the same for another database with different credentials?</strong></p>

<p>WordPress provides developers with a class of functions to manipulate the database and this is particularly useful for custom plugins and/or themes. Developers may interface - create, read, write and/or delete data - with the WordPress database via the <a href="http://codex.wordpress.org/Class_Reference/wpdb">global <code class="highlighter-rouge">$wpdb</code> object</a>; however, to interact with another database (an external/secondary one) a new instantiation of the wpdb class is required. In WordPress’ codex, <a href="http://wordpress.org/extend/plugins/hyperdb/">hyperdb</a> is recommended as the solution <em>“for extremely complicated setups with many databases”</em>. If however, you are not too keen on using someone else’s plugin it is pretty simple to create your own custom database object using the wpdb class.</p>

]]></description>
<content:encoded><![CDATA[<p><strong><code class="highlighter-rouge">$wpdb</code> can only access and manipulate the WordPress database. How may I do the same for another database with different credentials?</strong></p>

<p>WordPress provides developers with a class of functions to manipulate the database and this is particularly useful for custom plugins and/or themes. Developers may interface - create, read, write and/or delete data - with the WordPress database via the <a href="http://codex.wordpress.org/Class_Reference/wpdb">global <code class="highlighter-rouge">$wpdb</code> object</a>; however, to interact with another database (an external/secondary one) a new instantiation of the wpdb class is required. In WordPress’ codex, <a href="http://wordpress.org/extend/plugins/hyperdb/">hyperdb</a> is recommended as the solution <em>“for extremely complicated setups with many databases”</em>. If however, you are not too keen on using someone else’s plugin it is pretty simple to create your own custom database object using the wpdb class.</p>

<!--more-->

<p>Here is a <a href="https://gist.github.com/MrSaints/8209879">gist</a> of how you may do so:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
</pre></td><td class="code"><pre><span class="cp">&lt;?php</span>
<span class="nb">define</span><span class="p">(</span><span class="s1">'DB_HOST'</span><span class="p">,</span> <span class="s1">'127.0.0.1'</span><span class="p">);</span>
<span class="nb">define</span><span class="p">(</span><span class="s1">'DB_USER'</span><span class="p">,</span> <span class="s1">'root'</span><span class="p">);</span>
<span class="nb">define</span><span class="p">(</span><span class="s1">'DB_PASS'</span><span class="p">,</span> <span class="s1">'password'</span><span class="p">);</span>
<span class="nb">define</span><span class="p">(</span><span class="s1">'DB_NAME'</span><span class="p">,</span> <span class="s1">'school'</span><span class="p">);</span>

<span class="k">class</span> <span class="nc">CustomDatabase</span>
<span class="p">{</span>
    <span class="k">private</span> <span class="nv">$db</span><span class="p">;</span>

    <span class="k">public</span> <span class="k">function</span> <span class="nf">__construct</span><span class="p">()</span> <span class="p">{</span>
        <span class="c1">// Connect To Database
</span>        <span class="k">try</span> <span class="p">{</span>
            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">db</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">wpdb</span><span class="p">(</span><span class="nx">DB_USER</span><span class="p">,</span> <span class="nx">DB_PASS</span><span class="p">,</span> <span class="nx">DB_NAME</span><span class="p">,</span> <span class="nx">DB_HOST</span><span class="p">);</span>
            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">db</span><span class="o">-&gt;</span><span class="na">show_errors</span><span class="p">();</span> <span class="c1">// Debug
</span>        <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">Exception</span> <span class="nv">$e</span><span class="p">)</span> <span class="p">{</span>    <span class="c1">// Database Error
</span>            <span class="k">echo</span> <span class="nv">$e</span><span class="o">-&gt;</span><span class="na">getMessage</span><span class="p">();</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="c1">// Example Query -- Count Students
</span>    <span class="k">public</span> <span class="k">function</span> <span class="nf">count_users</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">db</span><span class="o">-&gt;</span><span class="na">get_var</span><span class="p">(</span><span class="s2">"SELECT COUNT(*) FROM `students`;--"</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// Example Query #2 -- Update Student Name
</span>    <span class="k">public</span> <span class="k">function</span> <span class="nf">update_student_id</span><span class="p">(</span><span class="nv">$student_id</span><span class="p">,</span> <span class="nv">$student_name</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">db</span><span class="o">-&gt;</span><span class="na">update</span><span class="p">(</span>
            <span class="s1">'students'</span><span class="p">,</span>
            <span class="k">array</span><span class="p">(</span><span class="s1">'student_name'</span> <span class="o">=&gt;</span> <span class="nv">$student_name</span><span class="p">),</span>
            <span class="k">array</span><span class="p">(</span><span class="s1">'student_id'</span> <span class="o">=&gt;</span> <span class="nv">$student_id</span><span class="p">),</span>
            <span class="k">array</span><span class="p">(</span><span class="s1">'%s'</span><span class="p">),</span> <span class="k">array</span><span class="p">(</span><span class="s1">'%d'</span><span class="p">)</span>
        <span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="nv">$Custom_DB</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">CustomDatabase</span><span class="p">;</span>
<span class="cp">?&gt;</span></pre></td></tr></tbody></table></code></pre></figure>

<h2 id="explain-it-to-me">Explain it to me?</h2>

<p>The example in the gist above demonstrates how you can use the wpdb class provided by WordPress to communicate with an external database with entirely different database credentials (host, username, password and database name) as evident from line 2 to 5. In the example above, we are working with a database containing data of students in a school.</p>

<p>The CustomDatabase class seen above begins by instantiating the wpdb class into <code class="highlighter-rouge">$this-&gt;db</code> object as seen by the class constructor (line 11 to 19). A connection to the external database is stored in the object and it will not interfere with your WordPress database connection (which is likely if you were to connect using conventional PHP MySQL functions). Unlike the <code class="highlighter-rouge">$wpdb</code> global object however, <code class="highlighter-rouge">$this-&gt;db</code> is only accessible by the class itself (hence, the <a href="http://www.php.net/manual/en/language.oop5.visibility.php">private declaration</a>) and it is not publicly accessible (unless you make it so). Furthermore, <code class="highlighter-rouge">$wpdb</code> is only capable of interacting with the WordPress database as I have previously mentioned.</p>

<p>Using the custom instantiation of wpdb (stored in <code class="highlighter-rouge">$this-&gt;wpdb</code>) we can then manipulate data from our external database as seen on line 21 to 34. The <code class="highlighter-rouge">count_users()</code> function will return the total number of students in our students table of our external database. The <code class="highlighter-rouge">update_student_id()</code> function will update the students table by changing the name of a student with a specified student ID. As <code class="highlighter-rouge">$this-&gt;wpdb</code> is an object instantiation of the wpdb class, you may use any of its methods (refer to the <a href="http://codex.wordpress.org/Class_Reference/wpdb">WordPress Codex</a> to find out more about the methods you may use along with their respective arguments/parameters).</p>

<p>You may use the described functions above by calling <code class="highlighter-rouge">$Custom_DB-&gt;count_users()</code>. The try-catch statement in the example is not necessary, but you should include a fallback / a mechanism to deal with failed database connections as it may interfere with your application.</p>

<h2 id="and-were-done">And we’re done.</h2>

<p>There is always a learning curve involved when working with new plugins, libraries, frameworks, etc. In the case of WordPress, it is unfortunately pretty steep in my honest opinion. The WordPress Codex is incomplete and in several occasions, provide close to no real world example that is accompanied by in-depth explanation. Fortunately for us developers, there are several websites and communities committed to providing what the WordPress Codex lacks (The <a href="http://wp.tutsplus.com/">Tuts+ Network</a> and <a href="http://css-tricks.com/snippets/wordpress/">CSS-Tricks</a> just to name a few).</p>

<h2 id="dont-get-me-wrong">Don’t get me wrong.</h2>

<p>The WordPress Codex is not entirely flawed nor should it be considered useless. It succeeds in many areas (particularly on articles that are featured on its <a href="http://codex.wordpress.org/">home page</a>). It is merely ineffective. Indeed, it fails to compensate for <a href="http://wp.smashingmagazine.com/2012/07/04/writing-effective-wordpress-documentation/">various types</a> of learning preferences. Those who are capable of deciphering and experimenting with the ins and outs of its simplicity will excel best. It is definitely not easy to get to grips with initially, but with dozens of resources out there (tutorials, frameworks, plugins, etc) and a strong support network (e.g. <a href="http://stackoverflow.com/">Stack Overflow</a>), I suppose there is not any real need for the Codex to be heavily revamped and the time saved may be invested in other areas such as improving the overall code base, which the developers are doing a fantastic job at.</p>

<p>As always, feedback and opinions are welcomed.</p>
]]></content:encoded>
</item>
</channel>
</rss>