<?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>Jasper Tandy &#187; code</title>
	<atom:link href="http://jspr.tndy.me/tag/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://jspr.tndy.me</link>
	<description></description>
	<lastBuildDate>Tue, 07 Feb 2012 21:37:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>An Automator Folder Action for Screenshots and Dropbox</title>
		<link>http://jspr.tndy.me/an-automator-folder-action-for-screenshots-and-dropbox/</link>
		<comments>http://jspr.tndy.me/an-automator-folder-action-for-screenshots-and-dropbox/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 08:39:33 +0000</pubDate>
		<dc:creator>Jasper</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[applescript]]></category>
		<category><![CDATA[automator]]></category>
		<category><![CDATA[productivity]]></category>
		<category><![CDATA[workflow]]></category>

		<guid isPermaLink="false">http://jspr.tndy.me/?p=3939</guid>
		<description><![CDATA[Photos of dogs and cats and leaves and horizontal lines will be back soon.]]></description>
			<content:encoded><![CDATA[<p>I strive for minimalism when using computers. Less software, less processes, less distraction. I have a block colour as my desktop background. I don&#8217;t install superfluous software, no matter how beautifully-crafted. My computer is a tool (well, my OSX partition is anyway), not a game, so I treat it as such. If you rely on your computer, treat it well. Know where everything is and know what&#8217;s installed at all times. If something becomes surplus to requirements, remove it.</p>
<p>I use <a href="https://www.dropbox.com">Dropbox</a> as my cloud sharing weapon of choice. I share folders with friends and colleagues, and all of my screenshots are saved to a sub-folder of my public folder so that I can easily share them with anyone. This workflow might seem inherently insecure, but I don&#8217;t tend to screenshot things that are particularly secret; whether that&#8217;s a result of my screenshots having been public for so long, I don&#8217;t know.</p>
<p>You can easily change your screenshots directory from your Desktop to your Dropbox folder by opening a Terminal (/Applications/Utilities/Terminal.app) and running the following command:<br />
<code id="screenshotpath"><br />
defaults write com.apple.screencapture location /Path/to/Dropbox/Public/Screenshots<br />
</code></p>
<p>I like to have them in their own folder as I use Public for other things and don&#8217;t want it becoming overrun with screenshots. I don&#8217;t delete images; occupational hazard.</p>
<p>You can now close your Terminal window and go back to ignoring it if it scares you. I know a lot of people are uncomfortable with it. Once you&#8217;re saving screenshots to that directory, you can <a href="/downloads/copy-screenshot-url.workflow.zip">download the Automator Workflow</a>. Unzip and open with Automator. You&#8217;ll be asked if you want to install it. If you trust me, click install and the workflow is copied to the correct directory and opened for you to edit (you&#8217;re going to need to edit).</p>
<p>You should be presented with a screen that looks a little something like this:</p>
<p><img src="http://jspr.tndy.me/up/2011/09/gljtupsuzartjbgyvqmf-826x900.png" alt="Automator Screenshot" /></p>
<p>We&#8217;re only interested in the first box, where you&#8217;ve got some config to edit.</p>
<p><code>dropbox</code>: The path to your Dropbox folder.<br />
<code>screenshots</code>: The path to your Screenshots folder. Must be relative to <code>$dropbox</code>.<br />
<code>dropboxuid</code>: Your Dropbox User ID. Go into your Dropbox Public folder, context-click (right click, thanks Apple) > Dropbox > Copy Public Link. Your User ID is the big number in the URL copied.<br />
<code>bitlyuser</code>: Your <a href="https://bitly.com/">bit.ly</a> username.<br />
<code>bitlyapikey</code>: Your bit.ly <a href="https://bitly.com/a/account">API Key</a> can be found at the bottom of <a href="https://bitly.com/a/account">this page</a>.</p>
<p>You may not care if your URL gets shortened. If this is the case; find the following block of code in the first box:<br />
<code><br />
short=`curl -m 4 -0 "http://api.bit.ly/v3/shorten?login=$bitlyuser&#038;apiKey=$bitlykey&#038;format=txt&#038;uri=$encoded"`<br />
if [ -z $short ]<br />
then<br />
&nbsp;&nbsp;&nbsp;&nbsp;short=$url<br />
fi<br />
echo $short<br />
</code></p>
<p>And replace it with:<br />
<code><br />
echo $url<br />
</code></p>
<p>Now you&#8217;ll just get the Dropbox Public URL copied to your clipboard; not bit.ly (which bit.ly will probably prefer if you take a lot of screenshots!)</p>
<p>I&#8217;m making the following assumptions about your system:</p>
<ul>
<li>You have <a href="http://growl.info/">Growl.app</a> installed. If you&#8217;re not sure, open System Preferences and look for a pane under &#8220;Other&#8221; called &#8220;Growl&#8221;.</li>
<li>You have <a href="https://www.dropbox.com">Dropbox</a> installed</li>
<li>You have changed your Screenshots path (using the <a href="#screenshotpath">method above</a>) to be within your Dropbox Public folder</li>
<li>You have OSX Lion installed. I don&#8217;t see why it shouldn&#8217;t work on Snow Leopard, but I haven&#8217;t tried and I can&#8217;t.</li>
</ul>
<p>If you satisfy those criteria, you should have success with this workflow. It is, however, offered with no support and I will accept no responsibility if you break your computer playing around in the Terminal because it looks like The Matrix or trying to update Ruby (system Ruby works fine) or something. If you&#8217;re friendly and would like some help, please ask on my <a href="http://www.formspring.me/jaspertandy">Formspring</a> and I&#8217;ll try to help. I&#8217;m by no means an expert at Automator, bash or zsh scripting or AppleScript but I can get things to work. I suck at AppleScript so badly that I had to paraphrase the AppleScript portion of this Workflow from <a href="http://growl.info/documentation/applescript-support.php">here</a>.</p>
<p>Yes, <a href="http://www.planetperki.co.uk/">Perkins</a>, I&#8217;ve heard of <a href="http://getcloudapp.com/">Cloud.app</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jspr.tndy.me/an-automator-folder-action-for-screenshots-and-dropbox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>bit tumblr-y, but a quote</title>
		<link>http://jspr.tndy.me/bit-tumblr-y-but-a-quote/</link>
		<comments>http://jspr.tndy.me/bit-tumblr-y-but-a-quote/#comments</comments>
		<pubDate>Fri, 22 Oct 2010 20:38:32 +0000</pubDate>
		<dc:creator>Jasper</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[quote]]></category>
		<category><![CDATA[sense]]></category>

		<guid isPermaLink="false">http://jspr.tndy.me/2010/10/bit-tumblr-y-but-a-quote/</guid>
		<description><![CDATA[Non-developers often assume an application is invariably more valuable with a feature than without it Via literate programmer I can really empathise with this sentiment. There&#8217;s a huge temptation instilled somehow in people buying websites that more features = better quality. We really try to get clients to spend money on quality marketing at Buffalo, [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Non-developers often assume an application is invariably more valuable with a feature than without it</p></blockquote>
<p>Via <a href="http://literateprogrammer.blogspot.com/2010/10/tests-are-facts-code-is-theory.html">literate programmer</a></p>
<p>I can really empathise with this sentiment. There&#8217;s a huge temptation instilled somehow in people buying websites that more features = better quality. We really try to get clients to spend money on quality marketing at <a href="http://www.builtbybuffalo.com">Buffalo</a>, but they rarely realise that a bucket of features is pretty irrelevant if people don&#8217;t know your site exists. In the above, you can substitute the word &#8220;site&#8221; and its variants above with anything really.</p>
]]></content:encoded>
			<wfw:commentRss>http://jspr.tndy.me/bit-tumblr-y-but-a-quote/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I must write out 1000 times&#8230;</title>
		<link>http://jspr.tndy.me/i-must-write-out-1000-times/</link>
		<comments>http://jspr.tndy.me/i-must-write-out-1000-times/#comments</comments>
		<pubDate>Fri, 30 Apr 2010 14:19:00 +0000</pubDate>
		<dc:creator>Jasper</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[serveradmin]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://jspr.tndy.me/?p=2054</guid>
		<description><![CDATA[Copying directories resets permissions Copying directories resets permissions Copying directories resets permissions Copying directories resets permissions Copying directories resets permissions Copying directories resets permissions Copying directories resets permissions Copying directories resets permissions Copying directories resets permissions Copying directories resets permissions Copying directories resets permissions Copying directories resets permissions Copying directories resets permissions Copying directories resets [...]]]></description>
			<content:encoded><![CDATA[<pre>
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
Copying directories resets permissions
</pre>
<p>Not 1000, but you get the idea. Fuck.</p>
]]></content:encoded>
			<wfw:commentRss>http://jspr.tndy.me/i-must-write-out-1000-times/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>impress yourself</title>
		<link>http://jspr.tndy.me/impress-yourself/</link>
		<comments>http://jspr.tndy.me/impress-yourself/#comments</comments>
		<pubDate>Mon, 19 Apr 2010 16:28:20 +0000</pubDate>
		<dc:creator>Jasper</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[productivity]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://jspr.tndy.me/?p=2023</guid>
		<description><![CDATA[Just recently, I realised how important impressing yourself is when trying to maintain enthusiasm with your job. Doesn&#8217;t really matter what you do (as long as you care!), but things can go stale if you keep doing the same thing over and over, and never really provoking an &#8220;AWESOME! I did that!&#8221; reaction. Even if [...]]]></description>
			<content:encoded><![CDATA[<p>Just recently, I realised how important impressing yourself is when trying to maintain enthusiasm with your job. Doesn&#8217;t really matter what you do (as long as you care!), but things can go stale if you keep doing the same thing over and over, and never really provoking an &#8220;AWESOME! I did that!&#8221; reaction. Even if it&#8217;s only something small (at 8 hours a day, 5 days a week, little things can be fairly impressive!), it can give you a needed boost to productivity (ugh), enthusiasm and general satisfaction with work, life and all that!</p>
<p>Personally, I get my kick from cleaning really crappy data. Lucky for me, I&#8217;ve had a lot of crappy data to clean recently, so I&#8217;ve been able to flex my XPath, Regex, semi-complex MySQL and image manipulation muscles relatively frequently. If you&#8217;re as much of a fanatical cleaner and hoarder as I am, cleaning data is probably for you. Grab a 50MB CSV and try to programmatically make sense of it. It&#8217;s fun! I promise.</p>
]]></content:encoded>
			<wfw:commentRss>http://jspr.tndy.me/impress-yourself/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Unit testing</title>
		<link>http://jspr.tndy.me/unit-testing/</link>
		<comments>http://jspr.tndy.me/unit-testing/#comments</comments>
		<pubDate>Tue, 13 Apr 2010 21:27:31 +0000</pubDate>
		<dc:creator>Jasper</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[phpunit]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://jspr.tndy.me/?p=2013</guid>
		<description><![CDATA[This is something that&#8217;s been in my peripheral vision for some time now. I&#8217;ve periodically been struggling to see the need for unit testing in general, without any justification. I can obviously see the benefit of making sure that your code all works and, seeing as I frequently work on ecommerce sites, I can see [...]]]></description>
			<content:encoded><![CDATA[<p>This is something that&#8217;s been in my peripheral vision for some time now. I&#8217;ve periodically been struggling to see the need for unit testing in general, without any justification. I can obviously see the benefit of making sure that your code all works and, seeing as I frequently work on ecommerce sites, I can see it causing far fewer headaches when making changes to purchase processes &#8211; simply being able to run a script to see if anything I changed works right.</p>
<p>However, one drawback of unit testing as a concept is that computers are, as a rule, infallible when it comes to this sort of thing. Humans, on the other hand, are completely fallible. If I make a change to some code in my checkout process that has a knock-on effect I didn&#8217;t count on in my unit testing (like changing the way delivery is calculated/stored/whatever), I wouldn&#8217;t necessarily foresee there being any problems in the email that gets sent after a transaction is completed (that may seem pretty esoteric, but it happened today). Part of this issue arose because I didn&#8217;t write the original site, and there was no way for me to detect that this could&#8217;ve caused a problem without going through every file on the site and manually checking that there was a problem, but another part <em>could</em> have been solved if a good unit testing framework was in place.</p>
<p>Now, when I say &#8220;good&#8221;, what I really mean is &#8220;comprehensive&#8221;. Anyone can write a good unit testing framework and here&#8217;s how, in my opinion. You test /every single dependency/. Everything. Bar nothing. If unit testing could&#8217;ve solved my problem today, it would&#8217;ve been done a little something like this (not exactly like this because the code on this site is largely a mish-mash of procedural and I-don&#8217;t-quite-understand-OOP-so-I&#8217;ll-give-it-my-best-shot &#8211; I assume it would&#8217;ve been very difficult to express this as a unit test).</p>
<p>Say I have a method that outputs this email that gets sent. I would write a unit test to capture the output of that method (when supplied with sample data from my database table, for a little extra reliability). I would then take this method and write my own version of it inside my unit test, so that I know it&#8217;s correct and compare the output of the two methods. If they differ, I would (PHPUnit) assertSame(legacy_method_output,my_method_output), and the test would pass if I hadn&#8217;t fucked it up. Now, the perceptive among you will have spotted something wrong here. In order to write this unit test, I would first have had to know about this email&#8217;s pre-disposition to causing problems in the first place. This, in this case, is the entire battle. Furthermore, I would have had to completely rewrite the method, solely to test that the old method hadn&#8217;t been broken in some way. For future testing purposes, this is really useful but, chances are I&#8217;d just rewrite the method and move on.</p>
<p>All of this isn&#8217;t to say that unit testing is fundamentally flawed. Far from it, in fact. I can see that it&#8217;s an incredibly useful tool for documentation and future-updates. When I come back to code that already has a unit testing framework, I&#8217;d simply make my alterations, run my unit tests until they all pass, then write some more to cater for my currently augmented feature-set. I would then know (with only a shadow of a doubt) that everything is brilliant and nothing is going to get fucked up when I put my code live. That&#8217;s got to be worth it! Not only the above, but unit tests seem to me to serve as excellent developer documentation. If you want to know how something&#8217;s supposed to work, never mind asking the project manager or client (who probably don&#8217;t know, and don&#8217;t really care!), you can just look and the guy who wrote it will have told you! Brilliant.</p>
<p>The only (and sadly, this is a pretty substantial &#8220;only&#8221;) problem is time (as with everything, I guess). You get all of this great peace of mind, but you have to put time into it. And it&#8217;s not just a small amount of time either, it&#8217;s a lot of time. Once you&#8217;ve written all your code (maybe doing it as you go along &#8211; 30 minutes a day or something) you then have to write tests to try and break it, and cater for every potential outcome that could arise from user or developer input of the code you wrote. That&#8217;s a large investment of time. I can&#8217;t quite decide if the net gain is quite worth the input, but I&#8217;m tipping towards a yes. I spend a lot of time a bit stressed about whether a modification I&#8217;ve made is going to cause unexpected problems, and I&#8217;d really like to be able to be more confident with this. I&#8217;m also one of those people who likes doing little scripty things, and gets a great sense of satisfaction from ticking boxes and watching &#8220;make test&#8221; throw out 100% success. Maybe this is for me, after all!</p>
]]></content:encoded>
			<wfw:commentRss>http://jspr.tndy.me/unit-testing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Die, spaghetti-code, die.</title>
		<link>http://jspr.tndy.me/die-spaghetti-code-die/</link>
		<comments>http://jspr.tndy.me/die-spaghetti-code-die/#comments</comments>
		<pubDate>Tue, 09 Jun 2009 14:42:02 +0000</pubDate>
		<dc:creator>Jasper</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[diagram]]></category>
		<category><![CDATA[oop]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[procedural]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[spaghetti]]></category>
		<category><![CDATA[tongue-in-cheek]]></category>
		<category><![CDATA[visualisation]]></category>

		<guid isPermaLink="false">http://jspr.tndy.me/?p=1634</guid>
		<description><![CDATA[I never really got what spaghetti code was until today. That might sound dumb, but it&#8217;s a term that is quite widely-used in different contexts so it can be an odd one. Today, I have been working with code that is devoid of any design, regard for future developers or useful documentation. Like so much [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://jspr.tndy.me/up/3610270537.png" alt="3610270537"/></p>
<p>I never really got what spaghetti code was until today. That might sound dumb, but it&#8217;s a term that is quite widely-used in different contexts so it can be an odd one.</p>
<p>Today, I have been working with code that is devoid of any design, regard for future developers or useful documentation. Like so much PHP, the end result works, so it&#8217;s great. Except it&#8217;s not.</p>
<p>Imagine each line above is a function or method call, which has its own integral part to play in the execution of a web page (in this case). The entry and exit points are single entities, but what goes on in between is nothing short of scary!</p>
<p><img src="http://jspr.tndy.me/up/3610270663.png" alt="3610270663"/></p>
<p>Ideally, I like to see code the main vein of which is there at the start and the end of the app&#8217;s execution. Logic can branch from this as far as it wants to get what it needs, but it&#8217;s ultimately serving a purpose for the main line. The more I delve into OOP in many languages, the more I realise that procedural code is quite liable to spaghetti, whereas OO is not. That&#8217;s not to say it&#8217;s impossible, but it&#8217;s easier to have one method that sets everything in motion, configures your program and then receives and redirects input in OO than it is procedurally. </p>
<p>Since I started properly getting into OO, I started to liken the execution cycle of a procedural program to a glass of water falling. Everything starts from the same point, but over time everything splays out and does its own thing. Debugging procedural code, therefore, is analogous to blindly cleaning the aforementioned spillage &#8211; there is a good chance that the part of the spillage you&#8217;re working on has nothing to do with what you&#8217;re actually trying to achieve &#8211; no matter how relevant it looks!</p>
<p>Unfortunately, I blame PHP for the natural progression of spaghetti code from procedural to half-assed-OO. It&#8217;s so easy to get things done without really knowing what you&#8217;re doing that it&#8217;s actually borderline dangerous. A mishmash of procedural and OO is the absolute worst thing to debug, as it normally combines the horrible execution cycle of procedural apps with the potentially confusing trail of inheritance. Let me tell those who don&#8217;t know &#8211; it is VERY obvious when you&#8217;re working with code written by someone who does not understand inheritance (and I don&#8217;t mean what it is, I mean *why* it is) and it almost always makes their half-baked bastardisation of OO impossible to work with.</p>
<p>Have I had a difficult day? You could say that.</p>
]]></content:encoded>
			<wfw:commentRss>http://jspr.tndy.me/die-spaghetti-code-die/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Utter failure</title>
		<link>http://jspr.tndy.me/utter-failure/</link>
		<comments>http://jspr.tndy.me/utter-failure/#comments</comments>
		<pubDate>Mon, 06 Apr 2009 22:14:58 +0000</pubDate>
		<dc:creator>Jasper</dc:creator>
				<category><![CDATA[me]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[idiot]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://jspr.tndy.me/?p=1462</guid>
		<description><![CDATA[Today reminded me of when I first started writing web applications. When I first started glancing through PHP, and I didn&#8217;t have a clue what was going wrong, why things weren&#8217;t working, or how I was going to fix it. Until, right at the last minute, I took a step back and actually read the [...]]]></description>
			<content:encoded><![CDATA[<p>Today reminded me of when I first started writing web applications. When I first started glancing through PHP, and I didn&#8217;t have a clue what was going wrong, why things weren&#8217;t working, or how I was going to fix it. Until, right at the last minute, I took a step back and actually read the thing I thought was right, only to discover that it was totally wrong. I then wander to the lounge, dejected and beaten and look at my family, asleep and waiting for me.</p>
<p>Sometimes I wish I didn&#8217;t have this obsessive need to solve everything right now. I keep missing out on the important things in my life because I&#8217;m so paranoid that a fresh pair of eyes won&#8217;t fix the problem I&#8217;m having. Tonight, I was so frustrated that I actually cried and shouted and drank and wished for cigarettes. I&#8217;m so pathetic. I worked through deliveries of photos of my babies being cute, and my wife being sleepy and adorable, just to reach the realisation that I need to really look at a problem and stop wasting my time thinking that working harder, or swearing more will solve my problem. Stupid, stupid, stupid.</p>
<p>I need to sleep more, not just go to bed and stare at the ceiling.</p>
]]></content:encoded>
			<wfw:commentRss>http://jspr.tndy.me/utter-failure/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>260: Documentation</title>
		<link>http://jspr.tndy.me/260-documentation/</link>
		<comments>http://jspr.tndy.me/260-documentation/#comments</comments>
		<pubDate>Mon, 16 Feb 2009 22:25:54 +0000</pubDate>
		<dc:creator>Jasper</dc:creator>
				<category><![CDATA[365.1]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[365:365]]></category>
		<category><![CDATA[documentation]]></category>
		<category><![CDATA[moleskine]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://jspr.tndy.me/2009/02/260-documentation/</guid>
		<description><![CDATA[You try being creative when you&#8217;ve spent all day describing parameter data types.]]></description>
			<content:encoded><![CDATA[<p><img src="http://jspr.tndy.me/up/3285282297.jpg" alt="3285282297"/></p>
<p>You try being creative when you&#8217;ve spent all day describing parameter data types.</p>
]]></content:encoded>
			<wfw:commentRss>http://jspr.tndy.me/260-documentation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Working days</title>
		<link>http://jspr.tndy.me/working-days/</link>
		<comments>http://jspr.tndy.me/working-days/#comments</comments>
		<pubDate>Sat, 31 May 2008 09:51:31 +0000</pubDate>
		<dc:creator>Jasper</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[date]]></category>
		<category><![CDATA[headache]]></category>
		<category><![CDATA[OO]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://echohelloworld.com/?p=10</guid>
		<description><![CDATA[I&#8217;m all for reusable code. Whenever I&#8217;m coding, I&#8217;m constantly wondering if there&#8217;s a way that I can further abstract what I&#8217;ve done so I can use it somewhere else. Because of this, I came across a problem yesterday that got the better of me a little. I&#8217;m working on a project at the moment [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m all for reusable code. Whenever I&#8217;m coding, I&#8217;m constantly wondering if there&#8217;s a way that I can further abstract what I&#8217;ve done so I can use it somewhere else. Because of this, I came across a problem yesterday that got the better of me a little.</p>
<p>I&#8217;m working on a project at the moment that requires me to have an awareness of &#8220;working&#8221; days. Specifically, when a product is sold, the customer has three working days to cancel their order. This would be all well and good if there was 365 working days in the year, and all companies were the same. I started out with this assumption, but was quickly confounded.</p>
<p>Before I explain how I solved (well, only partially &#8211; it would require a calendar app to fully solve it to my satisfaction!) it, I&#8217;ll explain a little about how some classes come to be in my workflow.<span id="more-10"></span></p>
<p>When working in PHP, I have around 5 or 6 classes that I take everywhere with me. One for generating a class that represents every database table, one for DOM generation, one for database access, one for laying out application-specific database entity grouping (how hard can one try to avoid saying the word &#8220;model&#8221;?!) and one that acts as a sort of &#8220;other&#8221; class and includes functionality that doesn&#8217;t fit elsewhere. This is a single class (called &#8220;core&#8221;, if you&#8217;re interested) that contains a bunch of un-interrelated static functions. It acts as a breeding ground for functionality that gets bigger and bigger (either in the file or my head) before I give up and move it to its own domain. An example of this was back when I started this way of working and my database access functionality was in here. In a perfect world, only my __autoload() (best function ever, by the way) function would be here but, as I said &#8211; in a perfect world!</p>
<p>So, I have my core::nWorkingDaysPassed function, and all is well. The first argument is the date you&#8217;re counting from, the second is the date you&#8217;re counting to (defaults to now), the third is the number of days you want to count (defaults to 3 because that&#8217;s what I&#8217;m working on now) and the 4th is an array of days of the week that are in your working week, defaulting to Monday through Saturday, again because of what I&#8217;m working on now.</p>
<p>I&#8217;ve already spotted a problem with this function &#8211; it has too many arguments. I don&#8217;t like passing a lot of arguments to a function, and I think this is probably to do with my grounding in PHP &#8211; the argument orders in PHP&#8217;s core functionality is so varying that it&#8217;s incredibly difficult to remember what they are, even for functions you use every day! Luckily the documentation is good enough to counteract this. By the time I&#8217;ve finished this thought, I&#8217;ve spotted another problem &#8211; it doesn&#8217;t take public holidays into account. To take public holidays into account, it&#8217;s going to <strong>need</strong> to be an object of its own. I can&#8217;t get that much functionality into one function. Because of time constraints, and authorisation from the client, holidays are no-longer a concern (as they&#8217;re open, thankfully!).</p>
<p>On to solving my problem. It&#8217;ll be a lot easier to write this in pseudo-code. I know this because I just deleted the verbose version!</p>
<pre>normal_week = ('mo','tu','we','th','fr','sa','su')
working_week = normal_week
for each working_week as day:
	if day is not in argument_working_week:
		remove day from working_week
weeks_spanned = argument_days / 7 rounded up to nearest 1
all_weeks = merge weeks_spanned*normal_weeks
i = first instance of argument_from weekday in all_weeks
j = i + argument_days
while i &lt; j:
	argument_from = argument_from + 1 day
	if all_weeks[i] is in working_week: # normal working day
		i++
	else: # shouldn't count towards our total
		append a day to all_weeks # so we don't run out!
		i++
		j++
if argument_from &gt;= argument_to: # that amount of days has passed
	return True
else:
	return False</pre>
<p>I realise that commenting pseudo-code largely invalidates the need for pseudo-code but it started to look like Python and I didn&#8217;t want to spoil it!</p>
<p>Looking back at it now, I don&#8217;t know why it caused such a headache but I&#8217;m just one of those people who has problems with the difference between dates. I hope this helps someone, though I doubt it will!</p>
]]></content:encoded>
			<wfw:commentRss>http://jspr.tndy.me/working-days/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twitterminal &#8211; A Terminal-based Twitter client in Python</title>
		<link>http://jspr.tndy.me/twitterminal-a-terminal-based-twitter-client-in-python/</link>
		<comments>http://jspr.tndy.me/twitterminal-a-terminal-based-twitter-client-in-python/#comments</comments>
		<pubDate>Tue, 27 May 2008 21:22:10 +0000</pubDate>
		<dc:creator>Jasper</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[boredom]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[terminal]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[twitterminal]]></category>

		<guid isPermaLink="false">http://echohelloworld.com/?p=8</guid>
		<description><![CDATA[So, I&#8217;ve just started looking at Python, and I love it. Last night I was playing around with django, which is ridiculously cool, and tonight I started a Terminal twitter client &#8211; I&#8217;m dubbing it Twitterminal. Imaginitive, eh? It&#8217;s crazy-simple, and I&#8217;m not bothered about people using it or ripping it off so go for [...]]]></description>
			<content:encoded><![CDATA[<p>So, I&#8217;ve just started looking at <a href="http://python.org" target="_blank">Python</a>, and I love it. Last night I was playing around with <a href="http://djangoproject.com" target="_blank">django</a>, which is ridiculously cool, and tonight I started a Terminal <a href="http://twitter.com" target="_blank">twitter</a> client &#8211; I&#8217;m dubbing it Twitterminal. Imaginitive, eh?</p>
<p>It&#8217;s crazy-simple, and I&#8217;m not bothered about people using it or ripping it off so go for your life! The Twitter class, twit.py:<span id="more-8"></span></p>
<pre>import urllib2 as urllib
import base64
import xml.dom.minidom

class Twitter:
	public = 'http://twitter.com/statuses/public_timeline.rss'
	friends = 'http://www.twitter.com/statuses/friends_timeline.xml'
	action = 'public'
	actions = ['public','friends']
	items = []

	def __init__(self):
		pass

	def auth(self,username,password):
		self._username = username
		self._password = password
		self._b64 = base64.encodestring('%s:%s' % (self._username,self._password))
		self._authhead = 'Basic %s' % self._b64

	def setAction(self,action):
		if action not in self.actions:
			return False
		self.action = action

	def fetch(self):
		if self.action == 'public':
			url = self.public
			self._req = urllib.Request(url)
			self._handler = urllib.urlopen(self._req)
			self.parsePublic()
		elif self.action == 'friends':
			url = self.friends
			self._req = urllib.Request(url)
			self._req.add_header('Authorization',self._authhead)
			try:
				self._handler = urllib.urlopen(self._req)
			except IOError, e:
				return False
			self.parseFriends()

	def parsePublic(self):
		txt = self._handler.read()
		feed = xml.dom.minidom.parseString(txt)
		statuses = feed.getElementsByTagName('item')
		for status in statuses:
			self.items.append(status.getElementsByTagName('description')[0].childNodes[0].data)

	def parseFriends(self):
		feed = xml.dom.minidom.parseString(self._handler.read())
		statuses = feed.getElementsByTagName('status')
		for status in statuses:
			self.items.append('%s: %s' % (
				status.getElementsByTagName('screen_name')[0].childNodes[0].data,
				status.getElementsByTagName('text')[0].childNodes[0].data))

	def printall(self):
		for item in self.items:
			print '%sn' % item</pre>
<p>and twitter.py</p>
<pre>#!/usr/bin/python
import sys
from twit import Twitter

twit = Twitter()
if len(sys.argv) == 1:
	twit.setAction('public')
else:
	twit.setAction(sys.argv[1])
if (twit.action == 'friends'): # needs authentication - check sys - 2 is username - 3 is password
	if len(sys.argv) == 4:
		twit.auth(sys.argv[2],sys.argv[3])
	else:
		twit.setAction('public')
if twit.fetch() is False:
	print 'Username or password was incorrect'
twit.printall()</pre>
<p>To use it, you&#8217;ll need to go to the directory that twit.py and twitter.py are in and run chmod +x ./twitter.py so that you can execute it, then use the following commands to access it:</p>
<p>./twitter.py # this will retrieve the last 20 results from the public timeline</p>
<p>./twitter.py public # as ./twitter.py</p>
<p>./twitter.py friends username password # retrieves the last 20 tweets by your friends</p>
<p>there is pretty rudimentary functionality for checking if you&#8217;ve put the correct username or password in, and hopefully it will become more friendly once I get a bit more used to sys.argv and lists in general. This has only been used in python2.5.2 in OSX, so YMMV in other environments. Let me know in comments!</p>
<p>Also, <a href="http://twitter.com/jaspertandy" target="_blank">follow me on twitter</a>.</p>
<p>Also also, I&#8217;ve just noticed that the code is too wide for my layout. It&#8217;s only temporary anyway &#8211; copying still works.</p>
]]></content:encoded>
			<wfw:commentRss>http://jspr.tndy.me/twitterminal-a-terminal-based-twitter-client-in-python/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

