<?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>if(is_geek)... &#187; Programming</title>
	<atom:link href="http://www.ifisgeek.com/tag/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ifisgeek.com</link>
	<description>Look! A New Doot!</description>
	<lastBuildDate>Thu, 03 Sep 2009 04:51:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Does Usability Really Matter?</title>
		<link>http://www.ifisgeek.com/2009/09/02/does-usability-really-matter/</link>
		<comments>http://www.ifisgeek.com/2009/09/02/does-usability-really-matter/#comments</comments>
		<pubDate>Thu, 03 Sep 2009 04:51:49 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=265</guid>
		<description><![CDATA[I&#8217;ll be the first to admit that I am not a usability expert and, in general, I think that there is too much talk about usability with little real benefit. However, as a good computer scientist, I believe that it is an important part of software engineering. There are people who know a hell of [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll be the first to admit that I am not a usability expert and, in general, I think that there is too much talk about usability with little real benefit. However, as a good computer scientist, I believe that it is an important part of software engineering. There are people who know a hell of a lot about it and I tend to rely on them to make the appropriate decisions regarding how I should be making my software more usable. This is quite odd. In most other aspects of development, I like to question things and learn the bits I don&#8217;t know very well. When it comes to usability, however, I have always been happy to let someone else do the thinking.</p>
<div style="float:right;padding:10px;"><a href="http://www.ifisgeek.com/wp-content/uploads/IMG_3662.JPG" target="_blank"><img src="http://www.ifisgeek.com/wp-content/uploads/IMG_3662.JPG" alt="Devices" title="Devices" width="300" height="225" class="alignnone size-medium wp-image-266" border="0" /></a></div>
<p>Recently though, I have started to pay more attention to usability &#8211; in software and in other aspects of life. The image to the right is of my television and associated devices (apologies for the blur). I was looking at this tonight and I started wondering why those of us who work with software are so concerned with usability when it seems like no one else is. Let&#8217;s take a look at the various indicator lights that are visible in this picture. First off, there&#8217;s my Wii. It is in standby mode and is displaying an amber light. That makes sense, right? It&#8217;s not fully on and not fully off. So, amber indicates standby. Below that is my stereo receiver. It is on and has a green light on it. Again, this makes logical sense. Then there is my TV. It is on but it sports a <em>red</em> light to indicate the on state. Finally, in the lower right is my satellite receiver which has both a green and an amber light on it. This would seem to indicate a state somewhere between standby and on, but the device is fully on.</p>
<p>So, has a single sale of one of these devices ever been lost due to the lack of usability the indicator lights represent? I highly doubt it. I also don&#8217;t know anyone who has ever test-driven a television&#8217;s menus before purchase. Sure, we probably see the menus when the sales guy is talking to us about resolution and contrast ratio, but we&#8217;re not paying attention to that. We completely ignore the usability aspects of these common items because we are more concerned with how well the device does its primary function. In the case of a television, we only care about how good the picture looks.</p>
<p>Why then do we as software developers hold ourselves, in theory anyway, to such a higher standard? Why is usability so much more important with software than other products? Could it be a hold over from the days when there was resistance to computers from older generations? Perhaps when there was widespread resistance to anything to do with computers there was a much greater need to make the applications on the computers so amazingly easy to use in order for their benefit to be readily apparent. If so, do we still need to try so hard?</p>
<p>Perhaps it has nothing to do with the user and everything to do with the software. With non-software items it is usually very easy to describe what they do in a short sentence. What does your television do? It allows me to watch shows and movies. What does your razor do? It shaves my facial hair. Now, think about the software you use. Can you easily describe the function of the software the same? Firefox lets me view web pages. It also lets me search Google. It shows me videos. It plays Flash games. The list goes on. Could usability be a problem for software because we are simply trying to jam too much functionality into our applications?</p>
<p>There is an example from the non-software world which makes me think this might be the case. Think of a Swiss Army Knife. You can&#8217;t easily describe all of its functions in a single sentence. You also cannot say that the damn thing is in any way a usability success. It is a pain in the ass to use, but it saves you from carrying more stuff. Maybe the answer to software usability is not massive amounts of research and testing to make a Swiss Army Knife application a little more usable. Maybe the answer is to make our applications simpler and make more of them. The popularity of gadgets/widgets and the thousands of wee little Facebook applications could be an indication that this is true.</p>
<p>I don&#8217;t know if any of this is really relevant to a discussion on usability, but it is the way things look to me. I have many powerful applications on my computer, but I do tend to prefer using a dashboard widget if available. I tend to frequent websites that focus on one thing and do it really well. It might very well be that what we perceive as usability issues are just a case of Jack of all trades, master of none. If anyone more enlightened on the subject that me has some additional insights, please leave me some comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2009/09/02/does-usability-really-matter/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Splitting Django Models Into Separate Files</title>
		<link>http://www.ifisgeek.com/2009/01/26/splitting-django-models-into-separate-files/</link>
		<comments>http://www.ifisgeek.com/2009/01/26/splitting-django-models-into-separate-files/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 04:16:38 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[VendAsta]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=182</guid>
		<description><![CDATA[A little while ago I wrote a post about getting Django unittests to work on DreamHost. The particular problem with the DreamHost setup is that they don&#8217;t allow you to programmatically create and drop databases and the default Django unittest behaviour is to do just that: create a brand new test db, use it and [...]]]></description>
			<content:encoded><![CDATA[<p>A little while ago I wrote a post about <a href="http://www.ifisgeek.com/2008/12/27/django-unittesting-on-dreamhost/">getting Django unittests to work on DreamHost</a>. The particular problem with the DreamHost setup is that they don&#8217;t allow you to programmatically create and drop databases and the default Django unittest behaviour is to do just that: create a brand new test db, use it and then drop it. Since I wrote that post I have begun migrating all of my domains away from DreamHost but I have still found that technique to be useful with new projects.</p>
<p>I first started using Django when I started at VendAsta and this issue didn&#8217;t creep up there because we are use Google App Engine and its DataStore on the backend instead of a traditional database. With no database there was no issue with creating/dropping anything. It was only when I started using Django on my own that I came across that problem. There was one more issue with Django that I came across only when I started doing things outside of work: Django expects all of your models to be in a single file called models.py. I hate that. A lot.</p>
<p>I did some googling about the problem and found that there were a bunch of other people who didn&#8217;t like it much either. There were a few solutions but they all involved manually mucking about with the __all__ attribute in the __init__.py file of your models directory. Sure, it works, but I don&#8217;t like having to define a model in two places to use it. Oddly enough it was in some test code at work that I found the answer.</p>
<p>For our project at VendAsta we are using the Django App Engine Helper to provide a nice easy interface to the DataStore on the backend. A part of this is a small __init__.py file which allows you to spread your tests out in multiple files. Django likes its tests to be in a single tests.py file just like it likes its models to be in models.py. The wee bit of Google code is shown in Listing 1.</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python2.4</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># Copyright 2008 Google Inc.</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span>
<span style="color: #808080; font-style: italic;"># you may not use this file except in compliance with the License.</span>
<span style="color: #808080; font-style: italic;"># You may obtain a copy of the License at</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;">#     http://www.apache.org/licenses/LICENSE-2.0</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># Unless required by applicable law or agreed to in writing, software</span>
<span style="color: #808080; font-style: italic;"># distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span>
<span style="color: #808080; font-style: italic;"># WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span>
<span style="color: #808080; font-style: italic;"># See the License for the specific language governing permissions and</span>
<span style="color: #808080; font-style: italic;"># limitations under the License.</span>
&nbsp;
&nbsp;
&nbsp;
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Loads all the _test.py files into the top level of the package.
&nbsp;
This file is a hack around the fact that Django expects the tests &quot;module&quot; to
be a single tests.py file and cannot handle a tests package inside an
application.
&nbsp;
All _test.py files inside this package are imported and any classes derived
from unittest.TestCase are then referenced from this file itself so that they
appear at the top level of the tests &quot;module&quot; that Django will import.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">types</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
&nbsp;
PACKAGE = <span style="color: #483d8b;">'appname.tests'</span>
TEST_RE = r<span style="color: #483d8b;">&quot;^.*_test.py$&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Search through every file inside this package.</span>
test_names = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
test_dir = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span> __file__<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> filename <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span>test_dir<span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>TEST_RE, filename<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">continue</span>
  <span style="color: #808080; font-style: italic;"># Import the test file and find all TestClass clases inside it.</span>
  test_module = <span style="color: #008000;">__import__</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s.%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>PACKAGE, filename<span style="color: black;">&#91;</span>:-3<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>, 
                           <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>, <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>,
                           filename<span style="color: black;">&#91;</span>:-3<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> name <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>test_module<span style="color: black;">&#41;</span>:
    item = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>test_module, name<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: black;">&#40;</span><span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>item, <span style="color: black;">&#40;</span><span style="color: #008000;">type</span>, <span style="color: #dc143c;">types</span>.<span style="color: black;">ClassType</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span>
            <span style="color: #008000;">issubclass</span><span style="color: black;">&#40;</span>item, <span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestCase</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
      <span style="color: #ff7700;font-weight:bold;">continue</span>
    <span style="color: #808080; font-style: italic;"># Found a test, bring into the module namespace.</span>
    <span style="color: #ff7700;font-weight:bold;">exec</span> <span style="color: #483d8b;">&quot;%s = item&quot;</span> <span style="color: #66cc66;">%</span> name
    test_names.<span style="color: black;">append</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Hide everything other than the test cases from other modules.</span>
__all__ = test_names</pre></td></tr></table></div>

<h5>Listing 1: __init__.py file from Google for a tests module</h5>
</p>
<p>Essentially what this file does is loop through all files in the same directory and for each on that matches the pattern listed on line 40 (in this case, files that end in &#8216;_test.py&#8217;) and import all of the Classes from those files that are subclasses of the TestCase class. Finally, the code on line 62 does the magic with __all__ that I wanted to avoid doing manually for my models. It was this line that caught my attention and started me wondering if this code could be used for spreading models across multiple files.</p>
<p>In order for this to work for models there are a few things that need to be changed. First of all, on line 40, the pattern should be changed to match on *.py to grab all of the python files in the directory. Then, on line 46, add<br />
<blockquote> or filename == &#8220;__init__.py&#8221;</p></blockquote>
<p> to ensure that we don&#8217;t try to import the file we are in. Finally, remove the subclass requirement from line 55, as we are just concerned with importing classes here not what they inherit from. Putting it all together results in Listing 2. Place that in the __init__.py of a directory called models and you&#8217;ll not have to manually manage the __all__ list for your models in separate files.</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>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
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python2.4</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">types</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
&nbsp;
PACKAGE = <span style="color: #483d8b;">'my_app.models'</span>
MODEL_RE = r<span style="color: #483d8b;">&quot;^.*.py$&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Search through every file inside this package.</span>
model_names = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
model_dir = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span> __file__<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> filename <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span>model_dir<span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>MODEL_RE, filename<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> filename == <span style="color: #483d8b;">&quot;__init__.py&quot;</span>:
    <span style="color: #ff7700;font-weight:bold;">continue</span>
  <span style="color: #808080; font-style: italic;"># Import the model file and find all clases inside it.</span>
  model_module = <span style="color: #008000;">__import__</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s.%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>PACKAGE, filename<span style="color: black;">&#91;</span>:-3<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>,
                           <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>, <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>,
                           filename<span style="color: black;">&#91;</span>:-3<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> name <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>model_module<span style="color: black;">&#41;</span>:
    item = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>model_module, name<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>item, <span style="color: black;">&#40;</span><span style="color: #008000;">type</span>, <span style="color: #dc143c;">types</span>.<span style="color: black;">ClassType</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
      <span style="color: #ff7700;font-weight:bold;">continue</span>
    <span style="color: #808080; font-style: italic;"># Found a model, bring into the module namespace.</span>
    <span style="color: #ff7700;font-weight:bold;">exec</span> <span style="color: #483d8b;">&quot;%s = item&quot;</span> <span style="color: #66cc66;">%</span> name
    model_names.<span style="color: black;">append</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Hide everything other than the classes from other modules.</span>
__all__ = model_names</pre></td></tr></table></div>

<h5>Listing 2: __init__.py file modified for a models module</h5>
</p>
<p>Now, there is one last thing that you are going to need to do in order for everything to run properly in Django. It is a very simple addition to the end of each of your classes. I have seem some people complaining about the need to do this in various forums, but honestly, if you are using any form of modern text editing application, it should only take you about 2 minutes to create a new template for a model that has the little piece of code shown in Listing 3 at the bottom of the class (replace your_app_name with your actual app name).</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Meta:
        <span style="color: #483d8b;">&quot;&quot;&quot;Meta Class for your model.&quot;&quot;&quot;</span>
        app_label = <span style="color: #483d8b;">'your_app_name'</span></pre></td></tr></table></div>

<h5>Listing 3: Meta class required at the end of each model for proper functioning.</h5></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2009/01/26/splitting-django-models-into-separate-files/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Reflections on MFS Sprint 1</title>
		<link>http://www.ifisgeek.com/2009/01/06/reflections-on-mfs-sprint-1/</link>
		<comments>http://www.ifisgeek.com/2009/01/06/reflections-on-mfs-sprint-1/#comments</comments>
		<pubDate>Wed, 07 Jan 2009 05:46:36 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[VendAsta]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[Long Way Round]]></category>
		<category><![CDATA[Planning]]></category>
		<category><![CDATA[Scrum]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=164</guid>
		<description><![CDATA[Today at VendAsta we had our first full day of planning for the MyFrontSteps Sprint #2. We did some high level planning yesterday as well as demoing and a post mortem for the first Sprint. Having had a chance to relax this evening watching a few episodes of Long Way Round with my wife, there [...]]]></description>
			<content:encoded><![CDATA[<p>Today at VendAsta we had our first full day of planning for the MyFrontSteps Sprint #2. We did some high level planning yesterday as well as demoing and a post mortem for the first Sprint. Having had a chance to relax this evening watching a few episodes of Long Way Round with my wife, there are a few things that have struck me about the whole Scrum process as it works at VendAsta.</p>
<p>First and foremost, I absolutely love the amount of planning and forethought that goes into each 30-day development sprint. My past two jobs had nothing that even remotely compares to this. One was an online grocery store (which just recently discontinued operations) which meant that most development was done within the demands of an operating e-business and as a result needed to be very seat-of-the-pants. The other was a manufacturing company which meant that development processes were heavily driven by the demands of sales and manufacturing departments and those demands could and would change in the blink of an eye. Needless to say, I have found the change to be very liberating.</p>
<p>That is not to say that we couldn&#8217;t do more planning. One of the things that we found working through our first sprint was that while we felt we had done a great deal of planning up front, there was actually a lot of granularity that we were lacking. This is something we are endeavoring to overcome in the planning for Sprint 2. As much as I love the planning sessions we are having and as exciting as I find the whole process, it is a very tiring and draining experience. Well worth it, but wearying nonetheless.</p>
<p>A second major thing that struck me was how well we worked as a team. Considering the fact that five people were placed on a development team, given a couple of weeks to do some research and get to know each other and then thrust into the middle of a very ambitious project, we somehow managed to work very well together. Coupling this with the fact that we are working with a large number of cutting edge technologies, I would have expected at least a little friction to develop somewhere in the team over the course of 30 days, but none did. I believe that this is largely due to the environment at VendAsta and their hiring process. Everyone who gets hired there has to go through a lunch with other developers whom they will be working with. If those devs don&#8217;t think that you are a good fit for the team and the company, you don&#8217;t get hired. I don&#8217;t know why more companies don&#8217;t operate this way. People from HR departments should use VendAsta as a case study in how to build a whole company that just &#8220;gels&#8221;.</p>
<p>Finally, in the past two days I have been very impressed with the manner in which some of the trouble spots from Sprint 1 have been discussed. Previously, I have experienced project post mortems that are nothing more than a gathering of people around a table to point fingers at each other. In our post mortem yesterday we were encouraged to be completely honest and frank about what we did and didn&#8217;t like about how Sprint 1 went. At no point was there any finger pointing and the blame game just didn&#8217;t happen. The maturity of my team mates and our &#8220;chickens&#8221; impressed me to no end.</p>
<p>So, that is about it for my impressions on Sprint 1. We&#8217;re neck deep in planning Sprint 2 right now so I am afraid that Episode 4 of Roger&#8217;s Wars will still be a couple of days away. I&#8217;ve had a few people contact me asking when the rest of the saga was going to unfold but with the holidays and now our sprint planning, I&#8217;m having trouble finding the time to do it when my head is not either a) jell-o or b) utterly focused on work. Tomorrow or the next day I hope to sit myself down with a pot of Earl Grey and hammer out the fourth installment. Thanks for your patience <img src='http://www.ifisgeek.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2009/01/06/reflections-on-mfs-sprint-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Django Unittesting on Dreamhost</title>
		<link>http://www.ifisgeek.com/2008/12/27/django-unittesting-on-dreamhost/</link>
		<comments>http://www.ifisgeek.com/2008/12/27/django-unittesting-on-dreamhost/#comments</comments>
		<pubDate>Sun, 28 Dec 2008 04:56:08 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[dreamhost]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=150</guid>
		<description><![CDATA[The default test behaviour for a Django site creates and then destroys a whole test database on each test run. Normally this is not a problem, but the way Dreamhost has their MySQL setup running, the commands to create and drop databases are not available outside of their administration panel. What follows is the solution I have come up with and am currently using to run Django unittests with my Dreamhost MySQL databases.]]></description>
			<content:encoded><![CDATA[<p>Unit testing. It&#8217;s important. We all know that, even if we don&#8217;t practice what we preach. There was zero policy on unit testing at my last job, but now that I have started working at VendAsta, there is plenty of support for proper testing at the highest levels. Now that I am getting back into the habit of writing unit tests for my code at work I have been starting to focus on proper testing for my code at home. Combining Django and hosting with Dreamhost has proven to be a bit of a challenge.
<p>The first hurdle is actually getting a Django site running on Dreamhost. Luckily, there is this <a href="http://www.soasi.com/2008/09/django-10-on-dreamhost-with-passenger-mod_rails/">blog post</a> which details exactly how to get your site up and running on Dreamhost. I have used this method a couple of times (once modified to get a Satchmo install running) and have met with success each time.</p>
<p>Once the site is running, setting up tests poses another problem. The default test behaviour for a Django site creates and then destroys a whole test database on each test run. Normally this is not a problem, but the way Dreamhost has their MySQL setup running, the commands to create and drop databases are not available outside of their administration panel. What follows is the solution I have come up with and am currently using to run Django unittests with my Dreamhost MySQL databases.</p>
<p>First of all, it is important to understand a little about the default testing setup that Django uses. When you run the command <code>python manage.py test</code>, Django looks at the TEST_RUNNER setting to determine what to do. By default this setting points to django.test.simple.run_tests. A quick look and we can see that this is the functionality we want to alter. Specifically, lines 2 and 4 shown in listing #1 are what we need to replace.</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span> <span style="color: #ff7700;font-weight:bold;">import</span> connection
connection.<span style="color: black;">creation</span>.<span style="color: black;">create_test_db</span><span style="color: black;">&#40;</span>verbosity, autoclobber=<span style="color: #ff7700;font-weight:bold;">not</span> interactive<span style="color: black;">&#41;</span>
result = <span style="color: #dc143c;">unittest</span>.<span style="color: black;">TextTestRunner</span><span style="color: black;">&#40;</span>verbosity=verbosity<span style="color: black;">&#41;</span>.<span style="color: black;">run</span><span style="color: black;">&#40;</span>suite<span style="color: black;">&#41;</span>
connection.<span style="color: black;">creation</span>.<span style="color: black;">destroy_test_db</span><span style="color: black;">&#40;</span>old_name, verbosity<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h5>Listing 1: Excerpt from django.test.simple.run_tests</h5>
</p>
<p>It is these lines which make the calls to create and then drop the test database. The functionality needed, however, in order to work with Dreamhost&#8217;s setup, is to &#8220;flush&#8221; and existing test database both before and after the test run is complete. I have accomplished this through the creation of a method called <code>flush_test_db</code>, shown in Listing #2.</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> flush_test_db<span style="color: black;">&#40;</span>test_db<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Method to flush out the test database, removing tables, before
    and after test runs&quot;&quot;&quot;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span> <span style="color: #ff7700;font-weight:bold;">import</span> connection 
    cursor = connection.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
&nbsp;
    current_tables =  connection.<span style="color: black;">introspection</span>.<span style="color: black;">table_names</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> table <span style="color: #ff7700;font-weight:bold;">in</span> current_tables:
        cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;use %s&quot;</span> <span style="color: #66cc66;">%</span> test_db<span style="color: black;">&#41;</span>
        cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;drop table %s&quot;</span> <span style="color: #66cc66;">%</span> table<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h5>Listing 2: New method to remove all tables from the test db</h5>
</p>
<p>With this method, we can drop all of the tables in the test db both before and after a test run. It is necessary to do both just in case something goes horribly awry during a test run and we end up with leftover data from a previous test run. With this new method, we can then create a new version of the run_tests method and place both methods into a new file. I called my file test_runner.py and placed it in a tests directory within my app. The complete test_runner.py is shown in Listing 3.</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;Override of the simple tests module from django in order to skip
database creation and use an existing db&quot;&quot;&quot;</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span>.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> get_app, get_apps
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span>.<span style="color: black;">backends</span>.<span style="color: black;">creation</span> <span style="color: #ff7700;font-weight:bold;">import</span> TEST_DATABASE_PREFIX
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: #dc143c;">test</span> <span style="color: #ff7700;font-weight:bold;">import</span> simple
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: #dc143c;">test</span>.<span style="color: black;">utils</span> <span style="color: #ff7700;font-weight:bold;">import</span> setup_test_environment, teardown_test_environment
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span> <span style="color: #ff7700;font-weight:bold;">import</span> management 
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> flush_test_db<span style="color: black;">&#40;</span>test_db<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Method to flush out the test database, removing tables, before
    and after test runs&quot;&quot;&quot;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span> <span style="color: #ff7700;font-weight:bold;">import</span> connection 
    cursor = connection.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
&nbsp;
    current_tables =  connection.<span style="color: black;">introspection</span>.<span style="color: black;">table_names</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> table <span style="color: #ff7700;font-weight:bold;">in</span> current_tables:
        cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;use %s&quot;</span> <span style="color: #66cc66;">%</span> test_db<span style="color: black;">&#41;</span>
        cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;drop table %s&quot;</span> <span style="color: #66cc66;">%</span> table<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> run_tests<span style="color: black;">&#40;</span>test_labels, verbosity=1, interactive=<span style="color: #008000;">True</span>, extra_tests=<span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    Replacement for the run_tests in Django.
    &quot;&quot;&quot;</span>
    setup_test_environment<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    settings.<span style="color: black;">DEBUG</span> = <span style="color: #008000;">False</span>    
    suite = <span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestSuite</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> test_labels:
        <span style="color: #ff7700;font-weight:bold;">for</span> label <span style="color: #ff7700;font-weight:bold;">in</span> test_labels:
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #483d8b;">'.'</span> <span style="color: #ff7700;font-weight:bold;">in</span> label:
                suite.<span style="color: black;">addTest</span><span style="color: black;">&#40;</span>simple.<span style="color: black;">build_test</span><span style="color: black;">&#40;</span>label<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                app = get_app<span style="color: black;">&#40;</span>label<span style="color: black;">&#41;</span>
                suite.<span style="color: black;">addTest</span><span style="color: black;">&#40;</span>simple.<span style="color: black;">build_suite</span><span style="color: black;">&#40;</span>app<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> app <span style="color: #ff7700;font-weight:bold;">in</span> get_apps<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            suite.<span style="color: black;">addTest</span><span style="color: black;">&#40;</span>simple.<span style="color: black;">build_suite</span><span style="color: black;">&#40;</span>app<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: #dc143c;">test</span> <span style="color: #ff7700;font-weight:bold;">in</span> extra_tests:
        suite.<span style="color: black;">addTest</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">test</span><span style="color: black;">&#41;</span>
&nbsp;
    old_name = settings.<span style="color: black;">DATABASE_NAME</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> settings.<span style="color: black;">TEST_DATABASE_NAME</span>:
        test_database_name = settings.<span style="color: black;">TEST_DATABASE_NAME</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        test_database_name = TEST_DATABASE_PREFIX + settings.<span style="color: black;">DATABASE_NAME</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#replace the normal DATABASE_NAME with the name of the test db</span>
    settings.<span style="color: black;">DATABASE_NAME</span> = test_database_name
&nbsp;
    <span style="color: #808080; font-style: italic;">#flush the test db</span>
    flush_test_db<span style="color: black;">&#40;</span>test_database_name<span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;">#load the test db with models</span>
    management.<span style="color: black;">call_command</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'syncdb'</span><span style="color: black;">&#41;</span>
&nbsp;
    result = <span style="color: #dc143c;">unittest</span>.<span style="color: black;">TextTestRunner</span><span style="color: black;">&#40;</span>verbosity=verbosity<span style="color: black;">&#41;</span>.<span style="color: black;">run</span><span style="color: black;">&#40;</span>suite<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#flush the test db again</span>
    flush_test_db<span style="color: black;">&#40;</span>test_database_name<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#reset the value of DATABASE_NAME in settings</span>
    settings.<span style="color: black;">DATABASE_NAME</span> = old_name
    teardown_test_environment<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>result.<span style="color: black;">failures</span><span style="color: black;">&#41;</span> + <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>result.<span style="color: black;">errors</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h5>Listing 3: The complete test_runner.py</h5>
</p>
<p>The final step is to point the test framework to your new test runner by placing a new line in your settings.py. The exact value will vary based on where in your project you have placed the new test runner. In this example I have placed the test_runner.py file, containing the run_tests method in the tests directory of an app called &#8216;your_app&#8217;. This is shown in listing 4.</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="python" style="font-family:monospace;">TEST_RUNNER = <span style="color: #483d8b;">'your_app.tests.test_runner.run_tests'</span></pre></td></tr></table></div>

<h5>Listing 4: Settings.py setting pointing the test framework towards your new test_runner</h5>
</p>
<p>Finally a few words of caveat. I have omitted any comments I am using to tell pylint to ignore certain things and I have done little in this sample code to properly handle Exceptions that might arise. Nevertheless, this should get you a good start on running unit tests in Django if you host your site with Dreamhost.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2008/12/27/django-unittesting-on-dreamhost/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Giving Back</title>
		<link>http://www.ifisgeek.com/2008/11/24/giving-back/</link>
		<comments>http://www.ifisgeek.com/2008/11/24/giving-back/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 14:32:56 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[VendAsta]]></category>
		<category><![CDATA[Work]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/2008/11/24/giving-back/</guid>
		<description><![CDATA[I have been a long time fan of open source software. Over the years I have utilized countless open source projects to accomplish large tasks with ease for both my day job and my consulting work. Using these projects has always saved me a lot of reinventing the wheel and has made work on projects [...]]]></description>
			<content:encoded><![CDATA[<p>I have been a long time fan of open source software. Over the years I have utilized countless open source projects to accomplish large tasks with ease for both my day job and my consulting work. Using these projects has always saved me a lot of reinventing the wheel and has made work on projects much easier.</p>
<p>For the past three and a half years, I have been working in a very heavy Microsoft shop. As a result, it was always difficult to get acceptance for open source projects at Cover-All. The more work I started doing on web projects the easier it became to bring some open source into the fold but there certainly wasn&#8217;t any interest in giving anything back to those projects we benefited from and, even if there was interest, there wouldn&#8217;t have been time to do so anyway.</p>
<p>At VendAsta, things are a lot different. Here is a company that not only embraces the use of open source projects but actually encourages everyone to give back to those projects if they make any improvements / changes to them. I absolutely love that! This has given me the opportunity to give back to my first open source project!</p>
<p>I have been doing some work on developing Facebook applications over the past few weeks. Specifically, I have been using the awesome <a href='http://code.google.com/p/pyfacebook/'>pyFacebook</a> library. This is a Python library which gives the same functionality as the Facebook-supplied PHP client library, except with the goodness of Python. A total bonus for us is the fact that the library includes functionality to work with <a href='http://code.google.com/appengine/'>Google App Engine</a>, another new technology we are using. There was a small gap in this functionality and that is where I found my opportunity. While everything was setup to work with retrieving information from Facebook in GAE (Google has disabled socket access in the version of Python available through GAE, so you need to use their urlfetch method instead of calls to httplib), the Photos.upload() method was not setup in the same manner. I needed to upload files to Facebook, so I modified the library to work the way I needed.</p>
<p>Once my mods were complete I sent them to the maintainer of the pyFacebook project and, after a few helpful suggestions from him, I had a version that he was willing to commit to the project&#8217;s svn repository: <a href='http://code.google.com/p/pyfacebook/source/detail?r=166'>http://code.google.com/p/pyfacebook/source/detail?r=166</a>. After that I was able to track down and fix an actual bug involving some infinite redirects: <a href='http://code.google.com/p/pyfacebook/source/detail?r=168'>http://code.google.com/p/pyfacebook/source/detail?r=168</a>.</p>
<p>Two very small contributions to a single project, but I am hopeful that this is only the beginning!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2008/11/24/giving-back/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MacHackin&#8217;</title>
		<link>http://www.ifisgeek.com/2008/11/19/machackin/</link>
		<comments>http://www.ifisgeek.com/2008/11/19/machackin/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 02:23:41 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/2008/11/19/machackin/</guid>
		<description><![CDATA[Well, I have been working and living with a MacBook Pro for a few weeks now and I have to say I&#8217;m liking it a lot more than I had thought I would. I am starting to get the hang of how everything works and I am very happy about just how similar things are [...]]]></description>
			<content:encoded><![CDATA[<p>Well, I have been working and living with a MacBook Pro for a few weeks now and I have to say I&#8217;m liking it a lot more than I had thought I would. I am starting to get the hang of how everything works and I am very happy about just how similar things are to LINUX when you open up the command line. I had heard that, despite being built on BSD, much of that functionality was crippled in some way in OSX. Thankfully, that is not the case at all.</p>
<p>I finally got a chance this week to take a crack at customizing things a little bit. I have been listening to <a href='http://www.977music.com/'>Internet Radio .977</a> lately,  a set of &#8220;radio&#8221; channels I found in my ShoutCast playlist in XBMC. One thing that is very cool about working on a Mac is that so many of the applications play really well together. For instance, if you are listening to music in iTunes, with a couple of clicks you can have the current song showing up in your status in iChat or Adium. Unfortunately for me, the .977 stream does not play in iTunes. I listen to it in VLC, which does not fit together with the chat apps the way iTunes does.</p>
<p>I did a little Googling and wasn&#8217;t able to find much on the subject. There are a few ways to get current media information out of VLC, however, most of that is geared towards playing mp3s and using these techniques I was only able to extract the name of the radio station I was listening to, not the track name that was appearing in the VLC window. Additionally, I was able to find a site that detailed writing some Applescript and BASH scripts to set iChat/Adium status to dynamically indicate your location, based on IP address. After a little tinkering I was able to put something together.</p>
<p>I won&#8217;t bother with all of the details here (anyone who wants to know how it was done, drop me a line). Basically my solution was this: setup VLC to write its log out to a file and set the verbosity of the logging to max. When the track playing changes a line is written to the log including &#8220;New Title=XXX&#8221; where XXX is the track listing as it appears in the main VLC window. This information was utilized with two BASH scripts (one to pull the last song entry from the log and parse the song from that line and another to control this whole process) and one Applescript to push the status into the chat apps. A little cron magic and it works like a charm!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2008/11/19/machackin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Copy and Paste Does Not a Programmer Make</title>
		<link>http://www.ifisgeek.com/2008/10/28/copy-and-paste-does-not-a-programmer-make/</link>
		<comments>http://www.ifisgeek.com/2008/10/28/copy-and-paste-does-not-a-programmer-make/#comments</comments>
		<pubDate>Tue, 28 Oct 2008 14:33:06 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/2008/10/28/copy-and-paste-does-not-a-programmer-make/</guid>
		<description><![CDATA[As any experienced programmer knows, using existing, well proven code for new applications can greatly reduce development time. It can also remove some of the uncertainty in a project by reusing code that is a known quantity. In addition to reusing code you or a teammate has used already in a current or past project, [...]]]></description>
			<content:encoded><![CDATA[<p>As any experienced programmer knows, using existing, well proven code for new applications can greatly reduce development time. It can also remove some of the uncertainty in a project by reusing code that is a known quantity. In addition to reusing code you or a teammate has used already in a current or past project, using code from various resources on the web can provide a speedy way to get a new technology into your project. The one requirement for doing this successfully is that you have to know what you are doing. This requirement was something that became very apparent to me during my final few months at Cover-All.</p>
<p>At the end of my time at Cover-All I was in charge of three other programmers. I&#8217;ll refer to them as <em>the good</em>, <em>the bad</em> and <em>the kid</em>. <em>The kid</em> was the newest member of the team and the youngest. <em>The good</em> was one of the best programmers I have ever worked with. Finally, <em>the bad</em> was, in reality, not a programmer. He was trained as a CAD guy and evolved into a role as a programmer, but despite that he never really became a programmer. He just didn&#8217;t care about getting better at programming and didn&#8217;t want to actually learn the tech he was using. As you have probably guessed, the rest of this post is about <em>the bad</em>. The non-programmer.</p>
<p>It really is amazing how far someone can get with a very minimal skillset and a good library of code to draw from. <em>The bad</em> would typically follow the same methodology for each project he worked on. Step one would be to find a piece or pieces of code (either from elsewhere in our projects or from somewhere on the web) which had the same or similar functionality to that which he wanted to implement. Step two would would be to copy it into the project he was working on and make the modifications he thought were required to make meet his needs. That last bit is key and it is what separates <em>the good</em> from <em>the bad.</em></p>
<p>A good programmer takes the time to understand the code that he is using &#8211; whether it is code he has written beforehand, code another dev wrote in the same or another project or code that he has found on the web. It is this understanding which makes everything come together. <em>The bad</em> usually did not understand the code he was trying to use and would end up with completely non-functional code. Code he would invariably send to <em>the good</em> with the subject line &#8220;what&#8217;s wrong with this?&#8221;. After a few weeks of <em>the good</em> doing all of the difficult parts of his work, I told <em>the good</em> it was okay for him to tell <em>the bad</em> to do his own work.</p>
<p>The full extent of just how bad <em>the bad</em> was only became apparent to me during my last week at Cover-All. He was working on adding some functionality to an aspx page that <em>the good</em> had created to display a listing of parts which had been added to an order. <em>The good</em> had done a very good job of creating the page &#8211; he had placed a datagrid on the form and was populating it dynamically using a datasource in the code-behind, and updated via AJAX. <em>The bad</em>, when faced with this page was completely unable to understand what was being done there and therefore could not add the functionality he needed. So, after being told to do his own work yet again, he did some googling and came up with something. A few hours later he was again asking <em>the good</em> why no text was showing up on his page at all &#8211; he had even broken that which had been working. <em>The good</em> took a look at his work and asked, &#8220;Where did all of <em>my</em> code go?&#8221;. The response was a chilling, &#8220;I found a better way.&#8221;. That better way was to remove the datagrid and remove the code-behind and fill the aspx page with a tonne of inline asp. It turns out that <em>the bad</em> doesn&#8217;t know that there is a difference between asp and asp.net.</p>
<p>The moral of this little story is twofold. First, if you are a programmer and you have an honest desire to become better at what you do, using code written by other developers can be a great resource for learning new techniques and new technologies. Just make sure that you take the necessary time to understand the code you are using. Secondly, if you are working with someone who seems to be asking for a lot of help with code that he didn&#8217;t write himself, you might want to think twice about solving his problems for him. He might be a little inexperienced and trying to use code a little beyond his abilities (in that case, you&#8217;ll want to encourage him to spend more time on understanding the code he uses) or he may be your own version of <em>the bad</em> and he might be using your help and other people&#8217;s code as a crutch for his lack of real skill.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2008/10/28/copy-and-paste-does-not-a-programmer-make/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
