<?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>centresource blog &#187; Jeremy Holland</title>
	<atom:link href="http://blog.centresource.com/author/jholland/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.centresource.com</link>
	<description>the thoughts and ramblings of centresource</description>
	<lastBuildDate>Wed, 22 May 2013 15:48:03 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>A Confederacy of OSes, Part III</title>
		<link>http://blog.centresource.com/2012/10/19/a-confederacy-of-oses-part-iii/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=a-confederacy-of-oses-part-iii</link>
		<comments>http://blog.centresource.com/2012/10/19/a-confederacy-of-oses-part-iii/#comments</comments>
		<pubDate>Fri, 19 Oct 2012 15:34:26 +0000</pubDate>
		<dc:creator>Jeremy Holland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Linux/BSD]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Utilities]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.centresource.com/?p=4452</guid>
		<description><![CDATA[Read Part I and Part II So my strategy is as follows: I use Windows to run web browsers, the odd desktop app like Photoshop, handy GUI utilities like calculators, media playback, and the like. On top of all this, I have installed VirtualBox and the easy-to-install Windows version of Vagrant, running a VM with...]]></description>
				<content:encoded><![CDATA[<p>Read <a href="http://blog.centresource.com/2012/10/15/a-confederacy-of-oses-part-i/">Part I</a> and <a href="http://blog.centresource.com/2012/10/17/a-confederacy-of-oses-part-ii/">Part II</a></p>
<p>So my strategy is as follows: I use Windows to run web browsers, the odd desktop app like Photoshop, handy GUI utilities like calculators, media playback, and the like. On top of all this, I have installed VirtualBox and the easy-to-install Windows version of Vagrant, running a VM with the Ubuntu server distribution (I have no need of the gnome or any other GUI therein.. yet. That may change when I need to start running Selenium-based tests, but it&#8217;ll do for now). I use two PuTTY windows &#8211; one on each monitor &#8211; to connect to the VM, which is configured to startup at boot. I forward the necessary ports from the host to the guest (made easily configurable by Vagrant) and provision the whole affair with Chef.</p>
<p>Internally, I use tmux, vim, and all the usual CLI tools of the trade to ply my own. Servers, databases, services and the like all run internally to the VM, and the only crosstalk I&#8217;ve yet needed to make use of is accessing guest-hosted websites with my host-based browser, a feat easily enabled by Vagrant&#8217;s port forwarding. RDBMS GUIs will likely be needed soon enough, and the same solution will presumably apply thereto.</p>
<p>So, how has it been? So far, the experience has actually been pretty pleasant. After getting the VM&#8217;s hardware and the general translation and keyboard layout bells &amp; whistles configured to my liking, I feel for the most part that I&#8217;m back in my native Linux land when developing. No issues arising from the system being a VM have yet reared their heads, and aside from the MS chrome peeking around the corners of my terminals, I could almost be convinced that I&#8217;d never left. As far as the desktop bit goes, I&#8217;m still acclimating. However, the fact that the sound, the graphics, the power management &#8211; all the hardware in general &#8211; works perfectly without my having to tweak arcane configuration settings is a very great improvement over my earlier experience; and not having to forcefully implement hacky workarounds is a weight off of my shoulders.</p>
<p>That all said, I do have a few qualms. If you know of an acceptable solution to any of these, please comment and share!</p>
<ol>
<li>PuTTY is the best SSH client out of all those I&#8217;ve tried, and it&#8217;s not that great. It&#8217;s profile saving/loading system is nightmarish from a UX standpoint, the built-in fonts are fugly (though I can presumably use others once installed on the OS), but the thing that irks me the most is that I can&#8217;t go fullscreen! I have absolutely no need to see any of that garish MS chrome on the edges of my screen, and having it present detracts from the real estate available to me for tasks of actual importance, as well as simply clashing aesthetically.</li>
<li>The price of the full-featured Windows is prohibitive. There are certain features available only in the Professional or Business or whatever-they&#8217;re-called versions of Windows 7 that I would&#8217;ve found quite useful, but that I don&#8217;t really count as being worth the extra few hundred I&#8217;d have to lay out so to acquire (group policy editing comes to mind).</li>
<li>No real shell script to speak of. Sure, there&#8217;s VBScript and whatever that trash is that passes for a shell in cmd, but these simply don&#8217;t possess the power and terseness of bash.</li>
<li>The godforsaken automatic restart after update. I understand that Windows needs to update itself frequently in order for the boys in Redmond to have the slightest hope of plugging security leaks as fast as they&#8217;re discovered, but I do not at all appreciate having my viewing of some video on Hulu interrupted without discernible warning by my computer suddenly rebooting itself. Turning this trash off is apparently one of the features they reserved for the &#8220;Professional&#8221; users, and I quite frankly don&#8217;t see how this isn&#8217;t a bigger issue among Windows users at large. I understand they&#8217;ll &#8220;fix&#8221; this garbage in Windows 8, but for now, it is pretty off-putting.</li>
</ol>
<p>Anyway, those rants aside, all in all my experience has not been unsatisfactory. Neither, however, has it been revelatory, and I believe I&#8217;ll need more time to make a decision one way or the other. I&#8217;ll keep you all posted!</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.centresource.com/2012/10/19/a-confederacy-of-oses-part-iii/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>A Confederacy of OSes, Part II</title>
		<link>http://blog.centresource.com/2012/10/17/a-confederacy-of-oses-part-ii/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=a-confederacy-of-oses-part-ii</link>
		<comments>http://blog.centresource.com/2012/10/17/a-confederacy-of-oses-part-ii/#comments</comments>
		<pubDate>Wed, 17 Oct 2012 18:04:20 +0000</pubDate>
		<dc:creator>Jeremy Holland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Linux/BSD]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Utilities]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.centresource.com/?p=4450</guid>
		<description><![CDATA[Continued from Part I Due to many factors, setting up Linux turned out to be Hell. Both the kernel and GRUB wouldn&#8217;t have the ability to recognize the aforementioned pseudo-RAID array as a single disk until later (I&#8217;m still not sure if GRUB does), so I first had to effectively wipe the filesystem in its...]]></description>
				<content:encoded><![CDATA[<p><a href="http://blog.centresource.com/2012/10/15/a-confederacy-of-oses-part-i/">Continued from Part I</a></p>
<p>Due to many factors, setting up Linux turned out to be Hell. Both the kernel and GRUB wouldn&#8217;t have the ability to recognize the aforementioned pseudo-RAID array as a single disk until later (I&#8217;m still not sure if GRUB does), so I first had to effectively wipe the filesystem in its entirety and destroy all partitions; turn off the pseudo-RAID functionality in the BIOS (a miracle they allowed me to do so, considering everything else they expressly hid therefrom), re-partition the two drives as truly separate devices, and reinstall Windows on one disk while setting up Linux on the other. That was a night of my life I&#8217;ll never get back, and I considered dropping Windows from the lot entirely, but figured it might be handy to have as a last resort / testing platform and so opted to keep it at the last moment.</p>
<p>Finally having completed the installation, I booted up Linux for the first time and went about the standard post-installation rigamarole of bringing in my dotfiles and configuration settings, installing the basic tools I use everyday, etc. There were other problems during the process, but I cannot fairly lay the blame for them at HP&#8217;s feet. Switchable graphics &#8211; as this machine possessed &#8211; were still a relatively new and uncommon affair, and the distro kernel hadn&#8217;t been built to include certain systems associated therewith. So that&#8217;s <em>one</em> kernel rebuild right there, and I can assure you there were many more as time went on. Other issues include ACPI issues that <em>to this day</em> have not been completely resolved and reappear intermittently and seemingly randomly, a total inability to recognize the microphone, and other hardware-related woes. Still, I persisted, expending the elbow grease to fix what I could and resigning to live with the rest. When finished, I had a perfectly usable little hi-res Linux machine upon which to do my development that I could call 100% my own.</p>
<p>I have now used this machine for a year, and have thoroughly enjoyed it&#8230; when those issues I said I&#8217;d &#8220;live with&#8221; weren&#8217;t driving me absolutely insane. Lately, however, I been having doubts about my choice of OS, cataloged as follows:</p>
<ol>
<li>I had started to miss certain proprietary software that is not made readily available on Linux (Photoshop comes to mind &#8211; I need it rarely, but when I do, GIMP simply isn&#8217;t an adequate substitute). I could run it on Wine, sure, but all my experience with Wine has been less than pleasant, and I didn&#8217;t want to go through that business again.</li>
<li>I was becoming sick of the desktop quirks. I love Linux, and the developers of the various distros have my absolute and utmost respect; but the unfortunate fact is that drivers for hardware show up there last. Due to its low marketshare among PC OSes vendors have little incentive to develop them themselves, and in many cases, open-source and initially imperfect options are all that is available. That said, give it year or so, and you&#8217;ll likely see solid drivers made available; but that year is one in which I&#8217;m not getting my full money&#8217;s worth.</li>
<li>Honestly, I was doing a bit of introspection and reexamining my prejudices against Windows. Why do I hate it so? Could it be that I&#8217;m not giving it a fair chance, not having used it in nearly 10 years? Windows 7 is purportedly a vast improvement to Vista; maybe it was time to give it a chance.</li>
</ol>
<p>Because of these and other thoughts, I decided to try an experiment: I would switch back to the Windows 7 installation on my other, nigh-forgotten drive and try it out as my primary desktop for a few weeks, and see how it went. This post is the story of the start of that journey, and how i reached a place where I was at least not anthropomorphizing my machine in the most violent of fashions.</p>
<p>Now, Windows has its problems: certainly it&#8217;s an absolute crap development environment if you want any real, low-level control of a machine, or if you want to do any development in a language that wasn&#8217;t pinched off from the Great Golden Sphincter of Redmond. The registry&#8217;s a horrid design that &#8211; despite purportedly being recognized as such by its own engineers &#8211; has stubbornly persisted through multiple versions and will almost certainly be there in the next. The built-in command-line interface (cmd) and nearly every third-party one I have yet discovered are all so underpowered as to be little more than curiosities and toys. I won&#8217;t even get <em>started</em> about security. However, it does do one thing quite well: provide an ultimately pleasant, consistently usable desktop environment. For everything else &#8211; as they say &#8211; there&#8217;s Linux.</p>
<p><a href="http://blog.centresource.com/2012/10/19/a-confederacy-of-oses-part-iii/">Continued in Part III!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.centresource.com/2012/10/17/a-confederacy-of-oses-part-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Confederacy of OSes, Part I</title>
		<link>http://blog.centresource.com/2012/10/15/a-confederacy-of-oses-part-i/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=a-confederacy-of-oses-part-i</link>
		<comments>http://blog.centresource.com/2012/10/15/a-confederacy-of-oses-part-i/#comments</comments>
		<pubDate>Mon, 15 Oct 2012 21:42:08 +0000</pubDate>
		<dc:creator>Jeremy Holland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Linux/BSD]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Utilities]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.centresource.com/?p=4440</guid>
		<description><![CDATA[So, recently I&#8217;ve been trying an experiment: I&#8217;ve been using Windows 7 as a base OS for my primary development box. Why did I do this, and how has it been? Allow me to explain. I have been a *-nix man for many years, starting with Mac OS X and it&#8217;s largely-FreeBSD/NetBSD-derived platform. I have...]]></description>
				<content:encoded><![CDATA[<p>So, recently I&#8217;ve been trying an experiment: I&#8217;ve been using Windows 7 as a base OS for my primary development box. Why did I do this, and how has it been? Allow me to explain.</p>
<p>I have been a *-nix man for many years, starting with Mac OS X and it&#8217;s largely-FreeBSD/NetBSD-derived platform. I have literally nothing bad to say about the software of Mac OS X. Nothing. I adore it. What I <em>don&#8217;t</em> adore is the inflated price of the hardware. Certainly, it is of excellent quality; but I in my frugality have this crazy idea that I shouldn&#8217;t have to pay what Neal Stephenson referred to poetically as &#8220;&lt;expletive-redacted&gt;-you money&#8221; (e.g. $2500+) for a laptop with ultimately mediocre specs. I can get a laptop with just about *twice* the power for virtually <em>half</em> the price from a fully reputable manufacturer if I make what I consider to be the relatively small sacrifice of a sexy, top-of-the-line desktop experience and the social mating plumage that is that familiar, brushed aluminum case.</p>
<p>Up until recently the cost wasn&#8217;t really a factor, as my development machines were supplied largely by my employers, including Centresource. My first day on the job, CS set me up with a brand-new, perfectly splendid little 13&#8243; MBP, 4GB RAM, 250GB HD (this was before they were offered with SSDs) and all the other usual trimmings; in addition to a new 27&#8243; external monitor and even one of those mini-display-port-to-VGA adapters. This machine was an absolute pleasure to develop upon for nearly any task I was asked to complete. Unfortunately, as the size and scope of my workload increased (both as commissioned by CS as well as my own, personal, &#8220;for-fun&#8221; work), I began feeling the pinch of those 4GB. So, of my own volition, I sent out to NewEgg and got myself a couple of 8GB chips for a total of 16GB RAM. Good heavens, did that machine fly now.</p>
<p>However, I was now faced with a few issues:</p>
<ol>
<li>CS owned the machine, but I owned the RAM. This isn&#8217;t really a tangible problem since I don&#8217;t expect to be leaving any time soon, but it was nevertheless an admittedly personal reservation based largely in my perhaps-paranoid concerns for privacy and security.</li>
<li>Being that I have crap eyesight to begin with and like viewing multiple documents simultaneously, 13&#8243; was becoming a bit of a pinch-point for my own development whilst away from a desktop station with its extra monitor, whether at home or the office. I frequent coffee shops quite often as remote work environments, and the degree to which my productivity faltered as a result of being limited to the resolution possible on this machine was becoming unacceptable to me (note: I have what some might consider to be ridiculously high standards for my own productivity). In short, I wanted more real estate on the go &#8211; much more; something like 17&#8243;</li>
</ol>
<p>This being the case, I decided it was high time I bought my own computer, since my last personal purchase of same had been nearly 4 years back and a desktop unit besides (as well as now lying disemboweled and largely forgotten upon a table in my garage). I looked at the prices for an Apple laptop with the specs I desired (even the refurbished models), and almost immediately made the decision to buy a PC and switch to Linux as my main desktop environment &#8211; a decision I had toyed with in the past but never really committed to.  However, in order to maximize my very recent investment in the aforementioned memory, I had to find a machine that would accept the same chips in the same configuration.</p>
<p>I found several candidates, but for the money I settled upon an HP Envy 17&#8243;. I will say here that I will never buy another HP computer again: they had loaded down Windows with a truckload of proprietary crapware, they lock out almost every part of the BIOS worth mentioning, and they had taken up all 4 permitted primary partitions on the weird Intel pseudo-RAID array (one with a restore disk-image because they&#8217;re too cheap to print the thing to a DVD, the other with something called HP_TOOLS the purpose of which I cannot readily fathom and have no desire to learn lest it anger me further). Of course, my usage of Windows while in possession of this machine was intended to be minuscule if present at all, and so I quickly set out about installing my preferred Linux desktop distro, Linux Mint (then version 12).</p>
<p><a href="http://blog.centresource.com/2012/10/17/a-confederacy-of-oses-part-ii/">Continued in Part II!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.centresource.com/2012/10/15/a-confederacy-of-oses-part-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Freakin&#8217; asymptotic notation: How does that work?</title>
		<link>http://blog.centresource.com/2012/01/23/freakin-asymptotic-notation-how-does-that-work/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=freakin-asymptotic-notation-how-does-that-work</link>
		<comments>http://blog.centresource.com/2012/01/23/freakin-asymptotic-notation-how-does-that-work/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 18:15:32 +0000</pubDate>
		<dc:creator>Jeremy Holland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Theory]]></category>

		<guid isPermaLink="false">http://blog.centresource.com/?p=3623</guid>
		<description><![CDATA[OK, I&#8217;ll be the first to admit it &#8211; math is my favorite subject. I know that makes me weird &#8211; even among fellow working software engineers &#8211; but it&#8217;s the truth. It&#8217;s also the truth that while they may be boring to many, knowing even a little bit about the numbers of computer science...]]></description>
				<content:encoded><![CDATA[<p>OK, I&#8217;ll be the first to admit it &#8211; math is my favorite subject. I know that makes me weird &#8211; even among fellow working software engineers &#8211; but it&#8217;s the truth. It&#8217;s also the truth that while they may be boring to many, knowing even a little bit about the numbers of computer science can help make you a better software engineer. Today, we&#8217;re going to look at a little piece of applied discrete math &#8211; the analysis of algorithms &#8211; and how we can empirically describe the performance of one algorithm with respect to another using something called &#8220;asymptotic notation&#8221;. If you already know what this is and how to read the various sub-notations, skip the rest of this post: it&#8217;s old news. If you do not know what this is, and would like to, read on! If you do not know what this is and don&#8217;t care, read on anyway &#8211; I promise you it&#8217;ll be worth it.</p>
<p>Now, while I&#8217;m totally guilty of bandying around big scary terms like &#8220;asymptotic notation&#8221; (I&#8217;m a notorious stickler for nomenclature), what this boils down to is the following mathematical notation (and its related brothers, which we&#8217;ll get to later):</p>
<p>[O(g(n))]</p>
<p>Most typically, you&#8217;ll see this used and referred to not as (O(g(n))), which doesn&#8217;t serve much purpose unless we know already what (g(n)) is, but rather in terms of a <strong>specific</strong> (g(n)), say, (n^2):</p>
<p>[O(n^2)]</p>
<p>Moreover, for the purposes of this discussion, we&#8217;re going to look primarily at the following notation style:</p>
<p>[f(n) = O(n^2)]</p>
<p>So what on earth does this mean? Well, let&#8217;s think about algorithms. What is an algorithm? Simply a series of instructions for performing some task, right? In computing specifically an algorithm is implemented as an actual, written program in your language of choice. But under the hood, mathematically, an algorithm is a <strong>function</strong> (sometimes pure, sometimes not): it takes some input(s) and delivers some output. In the above block o&#8217; math, let us equate (f(n)) with some algorithm we would like to implement, say, sorting an array of integers from least to greatest. With an algorithm such as that, you would give it an array of dubiously sorted values, and it would give you back an array containing exactly the same elements but in sorted order. Represented mathematically, we have:</p>
<p>[s(a)]</p>
<p>where (s) is the algorithm function itself, and (a) is the array to be sorted. Now, let&#8217;s keep in mind that there are many different ways of going about sorting an array &#8211; naturally, we would like to pick the fastest one for the task at hand. So in order to know anything about the <em>performance</em> of an algorithm, we should probably come up with some way to represent how long it takes to run. To wit:</p>
<p>[T(s(a))]</p>
<p>represents the &#8220;time&#8221; (T) it takes to run algorithm (s) on input (a). OK. So, how can we begin to reason about what the range of this function might be? Actually, perhaps that&#8217;s jumping the gun &#8211; what would really be the <em>domain</em> of this function? What measurement of your general work-a-day sorting algorithm would dictate how long it takes to run? The answer, my friend, is the size of the input: it should make sense to anybody who&#8217;s actually had to do it that sorting a 10-element array is a heck of a lot faster than sorting a 10,000,000-element array. So, really, our (T) function can be abstracted further as a function of (n), where (n) is the size of the array to be sorted:</p>
<p>[T(n)]</p>
<p>Since the value of (T(n)) will grow as (n) grows (presumably), this seems like a solid footing to start our thinking upon.</p>
<p>Alrighty. Now that we&#8217;ve got some notation to start thinking about how we&#8217;ll build this bad boy, let&#8217;s actually pick a real, concrete algorithm and think through it. For the purposes of simplicity and succinctness (cue laughter), I&#8217;m going to go with <a href="http://en.wikipedia.org/wiki/Bubble_sort">Bubble Sort</a>. If you want to learn more about the actual algorithm, I suggest you read the wikipedia article linked to above, because I&#8217;m gonna skip over a fat exposition on what it actually does and how it does it in favor of thinking about how long it <em>takes</em> to do it, and specifically how long it takes to do it to the worse possible case of input: an array that&#8217;s already been sorted, but reversed. Please note I have copied the following pseudocode directly from wikipedia, and credit therefor is due directly to the author of the page linked to above.</p>
<div style="float: right; text-align: right; line-height: 20px;">(c_{1})<br />
(c_{2})<br />
(c_{3}n)<br />
(c_{4}n)<br />
(c_{5}n(n-1))<br />
(c_{6}n(n-1))<br />
(c_{7}n(n-1))</p>
<p>(c_{8}n)</p></div>
<div style="line-height: 20px;">procedure bubbleSort( A : list of sortable items )<br />
repeat<br />
swapped = false<br />
for i = 1 to length(A) &#8211; 1 inclusive do:<br />
if A[i-1] &gt; A[i] then<br />
swap( A[i-1], A[i] )<br />
swapped = true<br />
end if<br />
end for<br />
until not swapped<br />
end procedure</div>
<p>OK, so that&#8217;s the algorithm from wikipedia &#8211; but what&#8217;s all that nasty-looking business on the right? Put quite simply, that&#8217;s our best guess as to how long that line of code takes to execute! Note that each line is some function of (n) and some constant (c_{i}). Now if we wanted to figure out <em>exactly</em> how long this algorithm takes to run, we&#8217;d need to know the value of those contants, e.g. (c_{1} = 12.2ms) or something. You&#8217;ll notice that some lines <em>only</em> seem to take a constant time to run; that&#8217;s because those lines are only executed once <em>regardless of how big the input is</em>. Other lines are the associated constant multiplied by (n) &#8211; those lines will execute once for every unit of input. Still others are multiplied by (n(n-1)) &#8211; these lines are executed (n-1) times for each input. Now, handily, we can figure out our overall formula by just adding all these things together:</p>
<p>[T(n) = c_{1} + c_{2} + c_{3}n + c_{4}n + c_{5}n(n-1) + c_{6}n(n-1) + c_{7}n(n-1) + c_{8}n]<br />
[T(n) = c_{1} + c_{2} + c_{3}n + c_{4}n + c_{5}n^{2}-n + c_{6}n^{2}-n + c_{7}n^{2}-n + c_{8}n]<br />
[T(n) = (c_{5} + c_{6} + c_{7})n^{2} + (c_{3} + c_{4} + c_{8} - 3)n + (c_{1} + c_{2})]</p>
<p>But it turns out that the precise value of each constant is practically useless &#8211; the constants in question represent such complex matters and concrete facts of the real world as language of implementation, hardware specs, how many other processes are fighting for CPU time, etc. Remember that we only really care about the performance of the <em>algorithm</em> &#8211; not the performance of the hardware or implementation thereof, which is not affected by the algorithm itself. So we can happily simplify our job by just getting rid of all those pesky constants!</p>
<p>[T(n) = n^{2} + n]</p>
<p>Wow, much nicer! But guess what: it gets even simpler. Since, for large enough inputs, the contribution of the lower-order term (n) makes virtually no difference to the output number, we can happily drop that too:</p>
<p>[T(n) = n^{2}]</p>
<p>And voilá! Unfortunately, we&#8217;ve boiled this timing function down so far and stripped so much from it that we can&#8217;t really say that (T(n)) is <em>exactly</em> (n^{2}), just that (in the worst case) it follows a similar curve. More precisely, we have virtually guaranteed that, for large enough inputs, it can never be bigger than some constant (c) <em>times</em> (n^{2}). This is the crux of asymptotic notation &#8211; specifically what is referred to as &#8220;Big-O notation&#8221;. As such, when we say that:</p>
<p>[T(n) = O(n^{2})]</p>
<p>What we mean is that there are some constants (c) and (a), such that for all (n) where (0 le a &lt; n), we know that (T(n) le cn^{2}).</p>
<p>It should also be pointed out that the notation&#8217;s use of the &#8220;equals sign&#8221; is a little unusual &#8211; we&#8217;re not saying that (T(n)) <em>is equal to</em> (O(n^{2})), but that it is of equal or lesser <em>order</em> to (n^{2}). This might be a bit of a trick to wrap your head around at first (it certainly was to me). If I&#8217;d have written the notation myself, I&#8217;d have tried to use some symbol that didn&#8217;t already carry all the connotations and denotations the &#8220;equals sign&#8221; itself does; but c&#8217;est la vie &#8211; this is the way it&#8217;s done. Another way (in fact, the proper way) to think of it is to think of (O(n^{2})) being some set of functions that follow the above definition, and for the notation</p>
<p>[T(n) = O(n^{2})]</p>
<p>to in fact mean</p>
<p>[T(n) in O(n^{2})]</p>
<p>i.e. that (T(n)) is an <em>element</em> of the set (O(n^{2})).</p>
<p>OK, so we&#8217;ve been able to put an upper bound on some hypothetical order of our function (T(n)), but what does that really tell us? Not a whole lot, in isolation. But it really comes into play when you consider other algorithms, such as, say <a href="http://en.wikipedia.org/wiki/Merge_Sort">Merge Sort</a>, which is bounded on top not by (O(n^{2})), but by (O(nlog_{2}n))! Graph those two functions and here&#8217;s what you get ((n^{2}) is in black, (nlog_{2}n) is in red):</p>
<p><a href="http://blog.centresource.com/wordpress/../wp-content/uploads/2012/01/graph-e1327292605398.png"><img class="alignnone size-medium wp-image-4131" title="graph" src="http://blog.centresource.com/content/uploads/2012/01/graph-e1327292808431-300x173.png" alt="" width="300" height="173" /></a></p>
<p>This is a bit of an oversimplification, but sufficient to demonstrate the idea &#8211; notice that very quickly, (n^{2}) begins to overtake (nlog_{2}n), and continues to do so, the gap getting ever wider as n gets ever bigger; and just like in golf, the lower score is the one you want.</p>
<p>So, in what I hope was nutshell-ish if not perfectly so, that&#8217;s the basics of asymptotic notation! There are other, related notations like &#8220;Big Theta&#8221; (Theta(g(n))), &#8220;Big Omega&#8221; (Omega(g(n))), and the lower-case versions of omega and o, but I&#8217;ll leave those to you to explore.</p>
<p>Finally, as a disclaimer, I have tried to make the math herein as simple as possible for the purposes of the demonstration, and I could easily have borked something up terribly (I&#8217;m still getting the hang of LaTeX). If you spot an error, comment and I&#8217;ll see that it&#8217;s corrected. Thanks!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.centresource.com/2012/01/23/freakin-asymptotic-notation-how-does-that-work/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails and MacRabbit&#8217;s CSSEdit</title>
		<link>http://blog.centresource.com/2011/08/05/rails-and-macrabbits-cssedit/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=rails-and-macrabbits-cssedit</link>
		<comments>http://blog.centresource.com/2011/08/05/rails-and-macrabbits-cssedit/#comments</comments>
		<pubDate>Fri, 05 Aug 2011 19:43:19 +0000</pubDate>
		<dc:creator>Jeremy Holland</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blog.centresource.com/?p=3398</guid>
		<description><![CDATA[Just a real quick tip for other Rails developers out there who enjoy the benefits of MacRabbit&#8217;s excellent software CSSEdit. Due to the fact that Rails applies a timestamp to every asset (stylesheet, javascript, and/or image) included in a view via the appropriate helper in order to allow the user to use the Expires header...]]></description>
				<content:encoded><![CDATA[<p>Just a real quick tip for other Rails developers out there who enjoy the benefits of MacRabbit&#8217;s excellent software <a href="http://macrabbit.com/cssedit/">CSSEdit</a>. Due to the fact that Rails applies a timestamp to every asset (stylesheet, javascript, and/or image) included in a view via the appropriate helper in order to allow the user to use the Expires header with said asset (full explanation <a href="http://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html">here</a>), and because CSSEdit overrides stylesheets based on the full URL <em>including the query string</em>, attempting to use the CSSEdit override functionality with a default Rails installation is nigh-impossible. Here&#8217;s how to get around it:</p>
<p>In your development environment file at /config/environments/development.rb, place the following command in the &lt;Your App&gt;::Application.configure block</p>
<pre lang="ruby">
ENV["RAILS_ASSET_ID"] = ''
</pre>
<p>Voilá! Timestamps gone in development.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.centresource.com/2011/08/05/rails-and-macrabbits-cssedit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Developer&#8217;s Arsenal: Jeremy Holland</title>
		<link>http://blog.centresource.com/2011/07/22/a-developers-arsenal-jeremy-holland/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=a-developers-arsenal-jeremy-holland</link>
		<comments>http://blog.centresource.com/2011/07/22/a-developers-arsenal-jeremy-holland/#comments</comments>
		<pubDate>Fri, 22 Jul 2011 23:20:23 +0000</pubDate>
		<dc:creator>Jeremy Holland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Utilities]]></category>

		<guid isPermaLink="false">http://blog.centresource.com/?p=3338</guid>
		<description><![CDATA[So I&#8217;m reading all our designers&#8217; &#8220;Trapper Keeper&#8221; posts, and I figure, &#8220;why should they get to have all the fun? Developers have stuff to say as well!&#8221; In that spirit, here is my attempt to start a similar series for the development department here at CentreSource. class DeveloperArsenal < Programmers::Toolset include CentreSource::JeremyHolland end 1....]]></description>
				<content:encoded><![CDATA[<p>So I&#8217;m reading all our designers&#8217; &#8220;Trapper Keeper&#8221; posts, and I figure, &#8220;why should they get to have all the fun? Developers have stuff to say as well!&#8221; In that spirit, here is my attempt to start a similar series for the development department here at CentreSource.</p>
<pre lang="ruby">class DeveloperArsenal < Programmers::Toolset
  include CentreSource::JeremyHolland
end</pre>
<p><strong>1. What tools do you use daily in the course of your development, and why those tools in particular?</strong></p>
<p>1. <a href="http://http://code.google.com/p/macvim/">MacVim</a> The more-or-less canonical port of the fantastic Vim text editor (itself an extension of the vi editor). While the benefits the GUI MacVim offers over and above the native CLI vim are minimal for an experienced user, I wholeheartedly recommend MacVim for beginners new to the editor; you'll still retain use of your mouse and all the classic OS X key shortcuts (cmd-s, cmd-w, etc) so you can stay productive while learning the new paradigm. Yehuda Katz has <a href="http://yehudakatz.com/2010/07/29/everyone-who-tried-to-convince-me-to-use-vim-was-wrong/">a great blog post on just this subject</a>.<br />
2. <a href="http://www.iterm2.com/#/section/home">iTerm2</a> Hands-down beats the native OS X terminal application. The features I particularly like are automatic copy-to-clipboard on mouse selection of text, true fullscreen, the ability to split a single pane both vertically and horizontally so as to keep multiple shells open and visible simultaneously (even in the aforementioned fullscreen mode), and a number of other little perks and pluses.<br />
3. <a href="http://www.sequelpro.com/">Sequel Pro</a> Holy smokes, I cannot say enough good things about this product. It is a shining example of doing one thing and doing it <strong>incredibly</strong> well - which is providing a simple, beautiful, and easily usable interface that just plain old <em>shows you the data in your database</em>. No crazy-ass graphical query builders, no wonky schema fiddling screens or massively over-complicated index-generation wizards, none of that crap. Everything provides all the functionality I need in what is likely the best possible interface with which said functionality could be represented. My only complaint is that it's MySQL-only, though myself and others are crossing our fingers for PostgreSQL and SQLite support down the road a ways.<br />
4. <a href="http://www.google.com/chrome">Google Chrome</a> Simply the best, fastest browser out there. I used to be a Firefox man, but that browser's javascript engine needs to get off its behind and catch up to the rest of the world.</p>
<p><strong>2. How did you get into development/programming/engineering, and what keeps you in it?</strong></p>
<p>I've always kind of been intrigued by software development. I started with BASIC on my family's Apple IIGS (10 PRINT "<em>[redacted - ed.]</em>"; 20 GOTO 10;), though I obviously didn't publish any world-changing papers based on my experience therewith. I had tooled around with HTML while I was still in high school, back in the SGML-esque days when tag names and attributes were still written in all caps, and even started studying computer science at college. Of course, college being college, I promptly decided to go be a bohemian and make no money. Subsequently, real life being real life and lack of money being a serious impediment to the living thereof, it wasn't long before I took up the programming mantle once more, fell back in love with it, and made it the focus of my career. So here I am today!</p>
<p><strong>3. Who is another programmer or developer you admire, and why?</strong></p>
<p>Martin Fowler. His books and experiences have contributed a great deal to my own understanding of object-oriented programming, and they remain among the first volumes I reach for when I'm facing down a particularly difficult modeling problem. When called upon to train new developers, I put <a href="http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420">Patterns of Enterprise Application Architecture</a> on their required reading list, especially since a great many patterns comprising the Ruby on Rails framework are implemented directly from the book in question.</p>
<p><strong>4. How do you keep yourself up-to-date with the latest technologies and what new or upcoming tech are you excited about?</strong></p>
<p>I never stop being a programmer, and I never stop learning new things. While I definitely don't subscribe to umpteen-thousand RSS feeds, I <strong>have</strong> amassed quite a library during my career (of which I am quite proud - picture below), and am constantly reading a book at least somewhat related to the subject. As far as getting excited about new tech goes, it takes a lot to impress me, so said excitement is pretty rare nowadays. Still, if I had to say something, I'd say graph databases: still in their infancy, but I think a decade or so down the line we might be seeing some awesome implementations and uses for same.</p>
<div id="attachment_3355" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.centresource.com/content/uploads/2011/07/2011-07-22_18-08-28_802.jpg"><img class="size-medium wp-image-3355" title="2011-07-22_18-08-28_802" src="http://blog.centresource.com/content/uploads/2011/07/2011-07-22_18-08-28_802-300x169.jpg" alt="" width="300" height="169" /></a><p class="wp-caption-text">A few aren&#39;t mine, but it&#39;s good to have our developer bookshelf in one place.</p></div>
<p><strong>5. What's your favorite language of the moment? Why?</strong></p>
<p>Ruby, for its flexibility and power; Erlang is a close second, because I'm a lambda calculus nerd.</p>
<p><strong>6. Do you have any advice for nascent developers?</strong></p>
<p>Get yo' math on, read like your life depends on it (it does), and most importantly <strong>don't cop an attitude</strong>. Help your fellow developers when they need it, and accept the help of the same when offered. The quality of our work always goes up when we work as a team (e.g. Pair Programming, which I also recommend you participate in early and often).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.centresource.com/2011/07/22/a-developers-arsenal-jeremy-holland/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simulating the ENUM MySQL Column Type in Rails</title>
		<link>http://blog.centresource.com/2011/06/22/simulating-the-enum-mysql-column-type-in-rails/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=simulating-the-enum-mysql-column-type-in-rails</link>
		<comments>http://blog.centresource.com/2011/06/22/simulating-the-enum-mysql-column-type-in-rails/#comments</comments>
		<pubDate>Wed, 22 Jun 2011 18:28:19 +0000</pubDate>
		<dc:creator>Jeremy Holland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.centresource.com/?p=3222</guid>
		<description><![CDATA[Today I was speccing out a handful of models that had &#8220;enumerable&#8221; attributes &#8211; i.e. attributes that are stored as strings, but whose possible values are limited to being a single element of a finite set of predefined strings. Think something along the lines of, say, the attribute &#8220;color&#8221;: valid values for &#8220;color&#8221; might include...]]></description>
				<content:encoded><![CDATA[<p>Today I was speccing out a handful of models that had &#8220;enumerable&#8221; attributes &#8211; i.e. attributes that are stored as strings, but whose possible values are limited to being a single element of a finite set of predefined strings.</p>
<p>Think something along the lines of, say, the attribute &#8220;color&#8221;: valid values for &#8220;color&#8221; might include &#8220;red&#8221;, &#8220;blue&#8221;, or &#8220;chartreuse&#8221;; while it&#8217;s certainly a large set, it&#8217;s still finite in the sense that there are not an infinite number of values that would satisfy the condition of being a color, and in that the valid values have no common regularity &#8211; i.e. the validity of any string cannot be determined by a regular expression match as said validity is determined purely by semantics, with no discernable extrusion into syntactical space (at least in English and most other germanic and romance languages).</p>
<p>Now, MySQL handily supplies a column type specifically for this purpose: ENUM. When defining an ENUM column in MySQL, one must define along with it a list of its possible values. In the event that one attempts to store a value not in this list in the column in question, the database throws an error, thus handily preventing invalid values from entering the dataset and corrupting the state of the database.</p>
<p>However, when using a database abstraction layer in order to maintain database portability, we unfortunately lose this capability as it is more or less unique to MySQL in the base column-type implementation. PostGRESQL has the ability to create new column types which are predefined as ENUM (via a wholly different paradigm), but both Oracle and SQL Server lack the capability completely.</p>
<p>Given the above, it has been the habit of Rails developers to enforce ENUM-style behavior at the application level via (at least) a call to validates_inclusion_of, and often an overriding of the attribute accessor methods to allow the assignment and retrieval of the values as ruby symbols while still actually persisting them to the database as strings. An example follows:</p>
<pre lang="ruby" line="1">
class Paint < ActiveRecord::Base
  validates_presence_of :color, :in =&gt; [:red, :blue, :chartreuse]

  def color
    read_attribute(:color).to_sym
  end

  def color=(value)
    write_attribute(:color,value.to_s)
  end
end
</pre>
<p>Now, while this is a relatively small quantity of code, it has been my personal experience that the need for an application-enforced ENUM pops up often enough that it becomes somewhat tedious to repeat this pattern over and over and again for different attributes. As such, we at Centresource have just released the enum_simulator plugin for Rails 3+, available under the MIT license at <a href="http://github.com/centresource/enum_simulator">our github repo</a>. It isn't much, but once installed, the code above can be condensed to:</p>
<pre lang="ruby" line="1">
class Paint < ActiveRecord::Base
  enum :color, [:red, :blue, :chartreuse]
end
</pre>
<p>The validates_inclusion_of and symbol&lt;-&gt;string typecasting are defined by the plugin, so we can shorten everything down to one call to the class method enum, wherein the first argument is the attribute in question, and the second is an array of possible values. Install and enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.centresource.com/2011/06/22/simulating-the-enum-mysql-column-type-in-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
