<?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>Random Sparks</title>
	<atom:link href="http://bobcravens.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://bobcravens.com</link>
	<description>A digital playground.</description>
	<lastBuildDate>Fri, 06 May 2016 17:38:33 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<!--Theme by MyThemeShop.com-->
	<item>
		<title>VirtualBox Not Starting On Windows</title>
		<link>http://bobcravens.com/2016/05/virtualbox-not-starting-on-windows/</link>
		<comments>http://bobcravens.com/2016/05/virtualbox-not-starting-on-windows/#respond</comments>
		<pubDate>Fri, 06 May 2016 17:38:33 +0000</pubDate>
		<dc:creator><![CDATA[rcravens]]></dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://bobcravens.com/?p=1341</guid>
		<description><![CDATA[Symptoms Install a new instance of VirtualBox on a Windows 7/8/Server 2012 R2. After the install, attempting to start VirtualBox does not show the expected UI. Looking into the Task Manager, shows two VirtualBox processes running. Solution A thorough search results in a number of help desk discussions around USB support. After unplugging the keyboard [&#8230;]]]></description>
				<content:encoded><![CDATA[<h3>Symptoms</h3>
<p>Install a new instance of VirtualBox on a Windows 7/8/Server 2012 R2. After the install, attempting to start VirtualBox does not show the expected UI. Looking into the Task Manager, shows two VirtualBox processes running.</p>
<h3>Solution</h3>
<p>A thorough search results in a number of help desk discussions around USB support. After unplugging the keyboard and mouse (running the machine &#8220;headless&#8221; with VNC access) allowed VirtualBox to work. Plugging in a different keyboard and same mouse also worked. So there was something about the original USB keyboard that VirtualBox did not like.</p>
<p>I&#8217;ll leave this here and hopefully this can save someone else some time.</p>
]]></content:encoded>
			<wfw:commentRss>http://bobcravens.com/2016/05/virtualbox-not-starting-on-windows/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RabbitMq Installation on Ubuntu 12.04</title>
		<link>http://bobcravens.com/2014/02/rabbitmq-install-unbuntu/</link>
		<comments>http://bobcravens.com/2014/02/rabbitmq-install-unbuntu/#comments</comments>
		<pubDate>Thu, 27 Feb 2014 17:09:21 +0000</pubDate>
		<dc:creator><![CDATA[rcravens]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://bobcravens.com/?p=1332</guid>
		<description><![CDATA[Seems like there are a lot of sources with pieces of this. This worked for me on Ubuntu 12.04. sudo apt-get remove rabbitmq-server sudo apt-get install python-software-properties sudo add-apt-repository "deb http://www.rabbitmq.com/debian/ testing main" wget http://www.rabbitmq.com/rabbitmq-signing-key-public.asc sudo apt-key add rabbitmq-signing-key-public.asc sudo apt-get update sudo apt-get install rabbitmq-server -y sudo service rabbitmq-server start sudo rabbitmq-plugins enable rabbitmq_management [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Seems like there are a lot of sources with pieces of this. This worked for me on Ubuntu 12.04.</p>
<pre class="brush: php;">
sudo apt-get remove rabbitmq-server
sudo apt-get install python-software-properties
sudo add-apt-repository "deb http://www.rabbitmq.com/debian/ testing main"
wget http://www.rabbitmq.com/rabbitmq-signing-key-public.asc
sudo apt-key add rabbitmq-signing-key-public.asc
sudo apt-get update
sudo apt-get install rabbitmq-server -y
sudo service rabbitmq-server start
sudo rabbitmq-plugins enable rabbitmq_management
sudo service rabbitmq-server restart
sudo apt-get install php5-dev
cd /tmp/
wget https://github.com/alanxz/rabbitmq-c/releases/download/v0.5.0/rabbitmq-c-0.5.0.tar.gz    (URL from: https://github.com/alanxz/rabbitmq-c)
tar -zxvf rabbitmq-c-0.5.0.tar.gz
cd rabbitmq-c-0.5.0/
./configure
sudo apt-get install make
make
sudo make install
cd ..
wget http://pecl.php.net/get/amqp-1.2.0.tgz    (URL: http://pecl.php.net/package/amqp)
tar -zxvf amqp-1.2.0.tgz 
cd amqp-1.2.0/
phpize && ./configure --with-amqp && make && sudo make install
sudo nano /etc/php5/cli/php.ini 

inside nano
ctrl-w , .so, enter
extension = amqp.so
ctrl-x, Y, enter

cd /vagrant/public/
sudo service php5-fpm restart
sudo service nginx restart
</pre>
<p>Hope that helps!</p>
]]></content:encoded>
			<wfw:commentRss>http://bobcravens.com/2014/02/rabbitmq-install-unbuntu/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Automate Your Database Backups</title>
		<link>http://bobcravens.com/2011/10/automate-your-database-backups/</link>
		<comments>http://bobcravens.com/2011/10/automate-your-database-backups/#comments</comments>
		<pubDate>Fri, 14 Oct 2011 17:44:31 +0000</pubDate>
		<dc:creator><![CDATA[rcravens]]></dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.bobcravens.com/?p=633</guid>
		<description><![CDATA[I have a few blogs and other applications that leverage MySQL as a database. I wanted to automate the backup of the associated database data. My specific requirements are: Needs to work on Windows Server (my hosting machine). My database is MySQL. It needed to be automatic. In other words, no human interaction. I wanted [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I have a few blogs and other applications that leverage MySQL as a database. I wanted to automate the backup of the associated database data. My specific requirements are:</p>
<ul>
<li>Needs to work on Windows Server (my hosting machine).</li>
<li>My database is MySQL.</li>
<li>It needed to be automatic. In other words, no human interaction.</li>
<li>I wanted it to happen twice per day. This minimized the risk of loss to 12 hours</li>
<li>The backup couldn&#8217;t reside on the same machine. It had to be more durable.</li>
<li>I wanted an alert that the backup occurred.</p>
</ul>
<p>After some searching I found the following PHP script that would export the database to a file.</p>
<pre class="brush: php;">
$fileName = 'dbName'.date("Y-m-d").'.sql';
$folder = 'c:\temp\';
$fullName = $folder.$fileName;

$cmd = 'mysqldump --user='.DB_USER.' --password='.DB_PASS.' --host='.DB_HOST.' --port='.DB_PORT.' dbName > '.$fullName;

system($cmd);
</pre>
<p>This bit of script executes the <a href="http://dev.mysql.com/doc/refman/5.5/en/mysqldump.html">MySql command to backup a database</a>. This could probably be done other ways (e.g. batch file), but this was convenient for testing. I could manually navigate to the PHP file with this script in a browser.</p>
<p>This got exported the SQL data to a file on the local disk (temp folder in the above case). Now I needed to get it off of this system. Each of the database files are fairly small, so I chose to simply email them to my gmail account. If I got into a situation where these were bigger or I would probably offload them either to my DropBox or AWS S3 storage. For now they are small and the email serves as an alert that the backup occurred. Here is a bit of code that emailed the backup file:</p>
<pre class="brush: php;">
$mail = new PHPMailer(true);

$mail->IsSMTP();
$mail->Host = "mail.diglabs.com";
$mail->SMTPAuth = true;
$mail->SMTPSecure = "ssl";
$mail->Host = "smtp.gmail.com";
$mail->Port = 465;
$mail->Username = "&#117;s&#x65;r&#x6e;a&#x6d;e&#x40;d&#x69;g&#x6c;a&#x62;s&#x2e;c&#x6f;&#109;";
$mail->Password = "password-for-username";
$mail->AddReplyTo('&#117;&#x73;e&#x72;n&#x61;m&#101;&#x40;&#100;&#x69;g&#x6c;a&#x62;s&#46;&#x63;o&#x6d;');
$mail->SetFrom('&#117;&#x73;e&#x72;&#x6e;&#97;&#x6d;e&#x40;&#x64;&#105;&#x67;l&#x61;&#x62;&#115;&#x2e;c&#x6f;&#x6d;');
$mail->Subject = 'Database Backup';
$mail->AltBody = 'To view the message, please us an HTML compatible email viewer!';
$mail->MsgHTML('Database backup is attached.');
$mail->AddAttachment($fullName, $fileName);
$mail->Send();

// Delete the unzipped file from your server
//	Note: unlink command did not work here.
system("del $fullName");

echo 'Backup completed, email sent';
</pre>
<p>In the above code I am using <a href="http://phpmailer.worxware.com/">PhpM@iler</a> as an email transport class. In this particular example, I am sending an email to &#8216;&#x75;&#115;er&#x6e;&#x61;me&#x40;&#x64;ig&#x6c;&#x61;&#98;s&#x2e;&#x63;&#111;m&#8217; with the database back up file attached. The domain &#8216;diglabs.com&#8217; is my domain and I use Google Apps for email. The above code sends email via Google Apps (smtp.gmail.com, port 465, ssl). Finally, I remove the backup file from the local disk.</p>
<p>Hope you find this useful. If you have suggestions or improvements, please leave them in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://bobcravens.com/2011/10/automate-your-database-backups/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Python Script to Build, Test and Pack .NET Projects</title>
		<link>http://bobcravens.com/2011/07/python-script-to-build-test-and-pack-net-projects/</link>
		<comments>http://bobcravens.com/2011/07/python-script-to-build-test-and-pack-net-projects/#respond</comments>
		<pubDate>Fri, 29 Jul 2011 22:06:46 +0000</pubDate>
		<dc:creator><![CDATA[rcravens]]></dc:creator>
				<category><![CDATA[Build System]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[ci]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://blog.bobcravens.com/2011/07/python-script-to-build-test-and-pack-net-projects/</guid>
		<description><![CDATA[At work we use Jenkins as our continuous integration server. Our implementation at work has to integrate with ClearCase and does a few tasks before actually doing the build. This is pretty typical. Our setup then calls an external script to build. We are not using some of the features that can be configured for [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>At work we use <a href="http://jenkins-ci.org/">Jenkins</a> as our continuous integration server. Our implementation at work has to integrate with ClearCase and does a few tasks before actually doing the build. This is pretty typical. Our setup then calls an external script to build. We are not using some of the features that can be configured for Hudson. This may not be as stream-lined as it can be but it has some benefits and I have to work within these constraints.</p>
<p>Since our build machine already has Python installed, I thought I would see if I can put together a reusable build script. I played around a bit and landed upon the following to call build (MSBuild), execute tests (MSTest) and create Nuget packages. I thought I would share this with you.</p>
<pre class="brush: py;"># Generic build script that builds, tests, and creates nuget packages.
#
# INSTRUCTIONS:
#    Update the following project paths:
#        proj        Path to the project file (.csproj)
#        test        Path to the test project (.csproj)
#        nuspec        Path to the package definition for NuGet.
#
#        delete any of the lines if not applicable
#
#
#    Update the paths to the build tools:
#        msbuild        Path to msbuild
#        test        Path to mstest.exe (requires Visual Studio) (optional – set to None)
#        nuget        Path to nuget.exe (requires NuGet command line tool) (optional - set to None)
#        trx2html    Path to trx2html.exe (http://trx2html.codeplex.com/) (optional - set to None)
#
#
# USAGE:
#
#     proj = r'path to project (.csproj)'
#     test = r'path to project containing test (.csproj)'
#     nuspec = r'path to nuspec definition (.nuspec)'
#
#
#     msbuild = r'C:WindowsMicrosoft.NETFrameworkv4.0.30319MSBuild.exe'
#     mstest = r'C:Program Files (x86)Microsoft Visual Studio 10.0Common7IDEMSTest.exe'
#     nuget = r'C:BuildToolsnuget2199eada12cenuget.exe'
#     trx2html = r'C:BuildToolstrx2html.6trx2html.exe'
#
#     bld = MsBuilder(msbuild, mstest, nuget, trx2html)
#     bld.run(proj, test, nuspec)
#

import os, shlex, subprocess, re, datetime

class MsBuilder:
    def __init__(self, msbuild=None, mstest=None, nuget=None, trx2html=None):
        # The following dictionary holds the location of the various
        #    msbuild.exe paths for the .net framework versions
        if msbuild==None:
            self.msbuild = r'C:WindowsMicrosoft.NETFrameworkv4.0.30319MSBuild.exe'
        else:
            self.msbuild = msbuild

        # Path to mstest (this requires vs2010 to be installed
        if mstest==None:
            self.mstest = r'C:Program Files (x86)Microsoft Visual Studio 10.0Common7IDEMSTest.exe'
        else:
            self.mstest = mstest

        # Path to nuget packager
        if nuget==None:
            self.nuget = r'C:BuildToolsnuget2199eada12cenuget.exe'
        else:
            self.nuget = nuget

        # Path to trx2html transformation tool
        if trx2html==None:
            self.trx2html = r'C:BuildToolstrx2html.6trx2html.exe'
        else:
            self.trx2html = trx2html

    def build(self, projPath):
        # Ensure msbuild exists
        if not os.path.isfile(self.msbuild):
            raise Exception('MsBuild.exe not found. path=' + self.msbuild)

        arg1 = '/t:Rebuild'
        arg2 = '/p:Configuration=Release'
        p = subprocess.call([self.msbuild, projPath, arg1, arg2])
        if p==1: return False    # exit early

        return True

    def test(self, testProject):
        if not os.path.isfile(self.msbuild):
            raise Exception('MsBuild.exe not found. path=' + self.msbuild)
        if not os.path.isfile(self.mstest):
            raise Exception('MsTest.exe not found. path=' + self.mstest)

        # build the test project
        arg1 = '/t:Rebuild'
        arg2 = '/p:Configuration=Release'
        p = subprocess.call([self.msbuild, testProject, arg1, arg2])

        # find the test dll
        f = open(testProject)
        xml = f.read()
        f.close()
        match = re.search(r'&lt;AssemblyName&gt;(.*)&lt;/AssemblyName&gt;', xml)
        if not match:
            print 'Could not find "AssemblyName" in test project file.'
            return False

        outputFolder = os.path.dirname(testProject) + '\bin\Release\'
        dll =  outputFolder + match.groups()[0] + '.dll'
        resultFile = outputFolder + 'testResults.trx'
        if os.path.isfile(resultFile):
            os.remove(resultFile)

        # execute the tests in the container
        arg1 = '/testcontainer:' + dll
        arg2 = '/resultsfile:' + resultFile
        p = subprocess.call([self.mstest, arg1, arg2])

        # convert the results file
        if os.path.isfile(self.trx2html):
            subprocess.call([self.trx2html, resultFile])
        else:
            print 'TRX to HTML converter not found. path=' + self.trx2html

        if p==1: return False # exit early

        return True

    def pack(self, packageSpec, version = '0.0.0.0'):
        if not os.path.isfile(self.nuget):
            raise Exception('Nuget.exe not found. path=' + self.nuget)

        outputFolder = os.path.dirname(packageSpec) + '\artifacts\'
        if not os.path.exists(outputFolder):
            os.makedirs(outputFolder)

        p = subprocess.call([self.nuget, 'pack', packageSpec, '-Version', version, '-Symbols', '-o', outputFolder])

        if p==1: return False #exit early

        return True


    def validate(self, projectPath):
        packFile = os.path.dirname(projectPath) + '\packages.config'
        if os.path.isfile(packFile):
            f = open(packFile)
            xml = f.read()
            f.close()
            print xml
            match = re.search(r'version="0.0.0.0"', xml)
            if match:
                # Found a non-versioned package being used by this project
                return False
        else:
            print 'No "packages.config" file was found. path=' + packFile

        return True

    def run(self, proj=None, test=None, nuspec=None):
        summary = '';

        # File header
        start = datetime.datetime.now()
        print 'n'*5
        summary += self.log('STARTED BUILD - ' + start.strftime("%Y-%m-%d %H:%M:%S"))

        # Build the project
        if proj is not None:
            buildOk = self.build(proj)
            if not buildOk:
                self.log('BUILD: FAILED', start)
                sys.exit(100)
            summary += self.log('BUILD: SUCCEEDED', start)
        else:
            summary += self.log('BUILD: NOT SPECIFIED')

        # Build the tests and run them
        if test is not None:
            testOk = self.test(test)
            if not testOk:
                print self.log('TESTS: FAILED', start)
                sys.exit(100)
            summary += self.log('TESTS: PASSED', start)
        else:
            summary += self.log('TESTS: NOT SPECIFIED')

        # Package up the artifacts
        if nuspec is not None:
            packOk = self.pack(nuspec, '0.0.0.0')
            if not packOk:
                print self.log('NUGET PACK: FAILED', start)
                sys.exit(100)
            summary += self.log('NUGET PACK: SUCCEEDED', start)
        else:
            summary += self.log('NUGET PACK: NOT SPECIFIED')

        # Validate dependencies
        if not self.validate(proj):
            print self.log('DEPENDENCIES: NOT VALIDATED - DETECTED UNVERSIONED DEPENDENCY', start)
            sys.exit(100)
        summary += self.log('DEPENDENCIES: VALIDATED', start)

        # Build footer
        stop = datetime.datetime.now()
        diff = stop - start
        summary += self.log('FINISHED BUILD', start)

        # Build summary
        print 'nn' + '-'*80
        print summary
        print '-'*80

    def log(self, message, start=None):
        timestamp = ''
        numsecs = ''
        if start is not None:
            split = datetime.datetime.now()
            diff = split - start
            timestamp = split.strftime("%Y-%m-%d %H:%M:%S") + 't'
            numsecs = ' (' + str(diff.seconds) + ' seconds)'
        msg = timestamp + message + numsecs + 'nn'
        print '='*10 + '&gt; ' + msg
        return msg
</pre>
<p>You can also find this <a href="https://gist.github.com/1093434">script on github</a>. I am not a Python guru, so if you see opportunities for improvement provide comments on the github page.</p>
]]></content:encoded>
			<wfw:commentRss>http://bobcravens.com/2011/07/python-script-to-build-test-and-pack-net-projects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>4 Principles To Estimation Applied To Software Development</title>
		<link>http://bobcravens.com/2011/05/4-principles-to-estimation-applied-to-software-development/</link>
		<comments>http://bobcravens.com/2011/05/4-principles-to-estimation-applied-to-software-development/#comments</comments>
		<pubDate>Sun, 22 May 2011 22:31:22 +0000</pubDate>
		<dc:creator><![CDATA[rcravens]]></dc:creator>
				<category><![CDATA[Project Management]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[estimation]]></category>

		<guid isPermaLink="false">http://blog.bobcravens.com/2011/05/4-principles-to-estimation-applied-to-software-development/</guid>
		<description><![CDATA[Estimating when a new software feature will be done is a tricky but important task. “When will you be done?” Typically on the other end of this question is the person writing your check. Maybe not directly, but follow the request up the chain and you will certainly end up eye to eye with the [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Estimating when a new software feature will be done is a tricky but important task. “When will you be done?” Typically on the other end of this question is the person writing your check. Maybe not directly, but follow the request up the chain and you will certainly end up eye to eye with the check writer. Another important business fundamental is predictability of the development pipeline. Voice of the customer goes in one end, software features come out the other end. The ability to estimate how long the pipeline will be tied up on a feature is important for scheduling resources and planning. Thankfully, applying some fundamentals will provide faster more accurate measurements.</p>
<h3>Fundamentals of Estimation</h3>
<p>First let’s look at a few examples from every day life. Here is the first estimation problem:</p>
<blockquote><p>An object traveling exactly 100 miles per hour is traveling a distance of exactly 100 miles.</p>
</blockquote>
<p>Estimate how long it will take for the object to travel the distance. A bit of simple math (remember high school physics?)</p>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/05/image.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/05/image_thumb.png" width="336" height="43"></a> Solving for time we get</p>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/05/image1.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/05/image_thumb1.png" width="343" height="44"></a> In this case we plug-in 100 miles for the distance and 100 miles per hour for the velocity and we calculate 1.0 hours as the time for the object to travel the distance. What is the certainty we have in our estimate? In the above problem, both the distance and the velocity were exactly known so the accuracy of our estimate is 100%. The error is zero. </p>
<p>This is really not an estimate, but more of a calculation. Estimate generally involve some approximations. However, from this simple problem we can already see some fundamentals of estimation that we will use. The relation ship between time, velocity and distance will be useful.</p>
<p>In the case of software development ‘distance’ is usually a measure of total size (or effort) of the features to be estimated. A common measure of size is ‘story points’. Mike Cohn has a <a href="http://blog.mountaingoatsoftware.com/its-effort-not-complexity">great blog post on ‘story points’</a>. Software development teams can also measure their ‘velocity’ in terms of ‘story points per unit of time’. For example in scrum the velocity might be measure as 40 story points per sprint. Sprint are always time-boxed. So if the sprint time is 2 weeks, this team has a velocity of 20 story points per week. Before discussing estimation in software development further, lets discuss uncertainty.</p>
<h3>Uncertainty Affects Accuracy</h3>
<p>Let’s add a bit of uncertainty to our first example.</p>
<blockquote><p>You walk from your current position to the nearest door.</p>
</blockquote>
<p>Estimate how long it will take you to accomplish this task? Unless you have a satellite phone and are in the desert, your estimate is probably in units of minutes or seconds. What is the uncertainty with your estimate? Most likely your uncertainty is probably in the units of seconds.</p>
<p>Let’s try another estimate.</p>
<blockquote><p>You walk from <a href="http://maps.google.com/maps?f=d&amp;source=s_d&amp;saddr=Seattle,+WA&amp;daddr=Washington+D.C.,+DC&amp;hl=en&amp;geocode=FcJp1gIdWVy1-ClVM-iTLBCQVDGa1URpRmUlEA%3BFQh-UQIdsoRo-ylb5PZa3sa3iTEqXYjUIkVSwg&amp;mra=ls&amp;sll=37.0625,-95.677068&amp;sspn=55.192325,40.341797&amp;ie=UTF8&amp;t=h&amp;z=3">Seattle, Washington to Washington D.C.</a></p>
</blockquote>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/05/image2.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/05/image_thumb2.png" width="756" height="420"></a> </p>
<p>Estimate how long will this journey take? Go ahead and really do this. I’ll wait. </p>
<p>What thought process did you go through. It was probably a bit different than the previous estimate. In this case, you probably needed to find out the distance (unless you are a geography wizard). Most people don’t possess the domain knowledge required to make this estimate without a bit of homework. No problem, a quick Google search tells it is about 2700 miles. Then you probably estimated your velocity. An average person’s walk is around 3 miles per hour. So that is about 900 hours of walking. Let’s say we walk 8 hours of the day. That puts us in Washington D.C. in about 113 days. What is the uncertainty in your estimate? Is it in units of hours? or days? Because of the size of this task, the initial uncertainty is probably in days (and maybe even weeks).</p>
<p>The estimate to the nearest door, it was too simple and you were probably were able to provide an estimate without the formal process of a distance and velocity approximation. In the second example, the size (or effort) of the problem (in terms of distance) was much larger. There was a lot more uncertainty in our distance and velocity approximations. The uncertainty in our estimate in the second case was much larger.</p>
<p>Now lets do one more estimation task. Imagine you are 100 days into your journey to Washington. Traveling 100 days has certainly provided a lot of experience. You probably have a much more accurate approximation to your velocity. You also have gained some confidence and understanding of your abilities. What has happened to your estimates? When will you arrive? What is the uncertainty?</p>
<p>What happens to your estimation and accuracy the closer you get? When the city limit sign for Washington D.C. becomes visible you could certainly provide an estimate with an accuracy in the minutes. There is a relationship between the accuracy and the amount of time remaining in the trip. Within steps of the finish line your uncertainty is in measured in seconds. While at the start of the trip it was probably in weeks.</p>
<p>From our thought experiments we can deduce the following ‘principles’:</p>
<ol>
<li>
<h2>Estimates require domain knowledge. </h2>
<li>
<h2>Tasks with a large size (or effort) are harder to estimate than smaller tasks. </h2>
<li>
<h2>Uncertainty decreases as we gain confidence and understand our abilities. </h2>
<li>
<h2>Uncertainty continually decreases as we get closer to&nbsp; the finish.</h2>
</li>
</ol>
<p>So let’s apply this knowledge to estimation in our software projects.</p>
<h3>Size The Work</h3>
<p>First let’s spend some time discussing how we determine the size of the features we must estimate. We must learn from the past and not fall into the trap of the waterfall development process. Most development teams are moving towards a more agile or lean development methodology. We have to be careful in the process of sizing our features that we do not fully analyze, break down into tasks, and plan the development for all the features up front.</p>
<p>On the surface this can appear to be desirable. The problem is that a lot of energy (resources and time) go into the analysis, breakdown and planning. But the tasks we plan are subject to more uncertainty the farther in the future they will occur (principle #4). This uncertainty generally manifests itself in the form of change. Change to requirements, design, development, testing…etc. The can result in rework and in terms of lean development represents waste. One of the be<br />
st discussions of ‘what went wrong’ with waterfall and why agile methodologies are better was in a <a href="http://vimeo.com/groups/87639/videos/16287115" class="broken_link">video by Glenn Vanderburg at JRubyConf 2010</a>.</p>
<p>Sizing of a task requires that the people with the domain knowledge be involved (principle #1). Be certain to include a cross-functional (requirements, designers, developers, testers) representatives. Minimize the sizing team for efficiency, but try to include a representative from all the domains on the team. If a story includes a specialized domain that is normally not present then size the story with the current team. Outside the sizing meeting query the domain expert to determine if they concur with the estimate. If the original estimate is not congruent with the expert’s, then cycle this story back through the sizing team.</p>
<p>Typically sizing is done using relative units and not hours. Sizing the work in terms of hours is more difficult and requires the higher level story to be broken down into tasks. Answering which is bigger (relative measurement) a Chihuahua or a German Sheppard is easier than answering how tall is a Chihuahua or German Sheppard in inches (absolute measurement). A common relative sizing scale that is used is the Fibonacci series (1, 2, 3, 5, 8, 13, 21, 34, etc.) or a derivative there of (1, 2, 3, 5, 8, 13, 20, 40, 100). Other sizing teams apply t-shirt sizes. The challenge with the t-shirt sizes is they are not numerical (you could always map them to numbers) and are more difficult to perform computations (velocity, burn down…etc).</p>
<p>Features should be broken down into smaller units of work. If the size of the unit of work is too large (e.g. greater than 50), an epic for example, then it introduces more uncertainty in the estimate (principle #2). To minimize the uncertainty, break these large unit of works into user stories with sizes less than 20 (rule of thumb). Once you are in that range, only break it down further if there is a logical reason for doing so.</p>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/05/image3.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/05/image_thumb3.png" width="615" height="409"></a> </p>
<p>A popular scrum activity for sizing is called planning poker. Essentially the team is issue cards (shown above). Individually, each team member estimates the story. The average of every team member’s size can be used as the final size. If there are outliers (everyone votes around 8 except one team member who votes 50) they should be discussed. This will generally result in an equal amount of over and under estimates.</p>
<p>The goal of the sizing team is to quickly move through the stories (thus the timer in the above image). If the story is too large or not clear, do not spend too much time on it. Make a note and handle it off-line. When all the stories have been sized, total up the numbers to determine the size of the release.</p>
<p>The key to sizing and our ability to measure velocity is to consistently size stories. In other words, a story sized today and the same story sized six months from now should result in the same numerical value. This consistency will result in less uncertainty in the final estimate.</p>
<h3>Measure Your Velocity</h3>
<p>Recall in our trip to Washington at the 100 day mark. We had a much better estimate of our velocity, more confidence in our ability and could better estimate our arrival time. This is true for our development teams also. The teams should be allowed to work through the stages of group development (<a href="http://en.wikipedia.org/wiki/Tuckman's_stages_of_group_development">forming – storming – norming – performing</a>). This allows the team to gain confidence and understanding of its abilities (principle #3). </p>
<p>If we want to have a good approximation to our team’s velocity we also need to have metrics. If you don’t measure the velocity, then you will not be able to provide the average value or understand the uncertainty. All of the agile methodologies already have a baked in velocity concept. </p>
<p>In scrum the team iterates on time-boxed intervals called sprints. </p>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/05/image4.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/05/image_thumb4.png" width="791" height="362"></a> </p>
<p>During the sprint planning the team selects the highest priority stories from the product backlog. They select enough stories to fill their sprint backlog based upon the current estimate for their velocity (story points per sprint). When the sprint concludes, the team’s velocity is recalculated based upon the sprint just completed.</p>
<p>In pull-based methodologies (e.g. kanban), a <a href="http://leadinganswers.typepad.com/leading_answers/files/creating_and_interpreting_cumulative_flow_diagrams.pdf">cumulative flow diagram</a> (shown below) is generally used to calculate the lead time.</p>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/05/image5.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/05/image_thumb5.png" width="483" height="567"></a> </p>
<p>The lead time is the time it takes a story point to propagate through the production pipeline. This is done by recording when a story enters the pipeline and when it exits. As stories exit, the lead time calculation is adjusted to provide a more accurate velocity for the team.</p>
<p>One very important point is to empower the team to have repeatable performance and thus a predictable velocity. Yes, this is a business and the team should be expected to perform. However, it can be detrimental to predictability to interfere with the team by changing team members, expecting the team to pull all nighters for a week to meet a deadline, or not enforcing work in process limits. These types of activities generally are not sustainable or undermine the performance of the team.</p>
<h3>Dealing With Uncertainty</h3>
<p>Now we have our best approximations to the sizes of the stories. Our team has been working together for awhile and are performing with a consistent velocity. Adding up all the story points and dividing by the velocity provides an estimate for the lead time for these features. This is our very best estimate. Even though we have done our very best, there is still some uncertainty in our estimate. What can we do?</p>
<p>First, realize that nothing is perfect. Striving for perfection can lead to paralysis by analysis. It is better to be professional about your estimates by discussing the uncertainty with the customer. Explain the sizing process, velocity and how estimates are calculated. End with an explanation of the ‘<a href="http://www.codinghorror.com/blog/2006/06/the-mysterious-cone-of-uncertainty.html">cone of uncertainty</a>’ or the concept that uncertainty continually decreases as we near the finish (principle #4).</p>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/05/image6.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/05/image_thumb6.png" width="528" height="302"></a> </p>
<p>The key to dealing with this is communication with the customer. Many of the agile mythologies include structure to encourage this communication. As the software evolves, the customer should get frequent opportunities to inspect the product. Explain your development methodology.<br />
 Describe and relay the importance of their role in the process. Just as the software evolves, so should our estimate. The estimate will become more accurate as we proceed. Customers are not surprised by the product, schedule or costs when professionals are involved. Constant communication is key.</p>
<p>The customer has the responsibility to prioritize the stories to ensure the most important stories get developed first. There may be exceptions with this related to retiring risky stories. Generally, the product should evolve with the customers highest priority requirements first.</p>
<p>There are uncertainties in our estimate, but there are also uncertainties in the customer’s expectations. Many times, during a customer inspection they will begin to speak about new features. Often seeing a prototype in action opens up creativity. This can lead to new user stories. The customer may even prioritize these new stories above the currently scoped work. Because this is common, a frank and professional discussion should happen at the start of the project with respect to scope changes. There may be financial, time, or other constraints that prevent the scope from expanding. To prevent disappointment customers must understand your scope change policy.</p>
<h3>Summary</h3>
<p>Remember estimation is not the same thing as guessing. As estimate is comprised of approximations that introduce uncertainty into our answer. Although we can do our best to minimize the uncertainty in our approximations, we simply cannot make it go away. Apply the ‘4 principles’ and deal with uncertainty in a professional manner. The key to providing good estimates is to collect and leverage metrics on the team. This post avoided the complexity of mathematical statistics. Adding a bit of statistical analysis to the metrics can provide valuable information. Providing good estimates can be hard. Hopefully, this discussion makes it a bit easier.</p>
]]></content:encoded>
			<wfw:commentRss>http://bobcravens.com/2011/05/4-principles-to-estimation-applied-to-software-development/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>A .NET Generic Repository Pattern With Implementations</title>
		<link>http://bobcravens.com/2011/05/a-net-generic-repository-pattern-with-implementations/</link>
		<comments>http://bobcravens.com/2011/05/a-net-generic-repository-pattern-with-implementations/#comments</comments>
		<pubDate>Sun, 15 May 2011 19:24:29 +0000</pubDate>
		<dc:creator><![CDATA[rcravens]]></dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Patterns]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[data access]]></category>
		<category><![CDATA[nhibernate]]></category>
		<category><![CDATA[repository]]></category>

		<guid isPermaLink="false">http://blog.bobcravens.com/2011/05/a-net-generic-repository-pattern-with-implementations/</guid>
		<description><![CDATA[I previously blogged about the repository pattern and .NET implementations. Here are the links to those old posts: The Repository Pattern The Repository Pattern – Part 2 Since that time, I have zeroed in on a fairly robust implementation of the repository pattern. I have used this implementation on a number of projects. The number [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I previously blogged about the repository pattern and .NET implementations. Here are the links to those old posts:</p>
<ul>
<li><a href="http://blog.bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/">The Repository Pattern</a>
<li><a href="http://blog.bobcravens.com/2010/09/the-repository-pattern-part-2/">The Repository Pattern – Part 2</a></li>
</ul>
<p>Since that time, I have zeroed in on a fairly robust implementation of the repository pattern. I have used this implementation on a number of projects. The number of changes to the underlying interfaces and the NHibernate concrete implementation have slowed down. I find this generic repository implementation very useful and hope that you will also. I have <a href="https://github.com/rcravens/GenericRepository">posted the repository code on Github</a>.</p>
<p><a class="download" href="https://github.com/rcravens/GenericRepository">Github</a></p>
<p>For the sake of keeping all the documentation in one place, I will be posting additional info in the Github repository also. The repository pattern implementation abstracts away the details of the persistence and ORM layer. This has advantages and disadvantages. The reason I like the pattern is two fold:</p>
<ul>
<li>Provides a consistent interface to the higher level layers of the application.
<li>Allows the persistence layer to be faked for testing.</li>
</ul>
<h3>Example Usage</h3>
<p>Here is an example usage:</p>
<pre class="brush: csharp;">// Create an instance of the session factory. This is typically done
//  once and cached. DbSessionFactory is a concrete implementation
//  of IDbSessionFactory using a variety of ORMs (e.g. NHibernate,
//  EF...etc).
//
IDbSessionFactory dbSessionFactory = new DbSessionFactory(connectionString)


// Create a session. This represents a database transaction.
//
using( IDbSesseion session = dbSessionFactory.Create())
{
    // Create a repository.
    //
    IKeyedRepository&lt;Guid, Person&gt; repo = session.CreateKeyedRepository&lt;Guid, Person&gt;();

    // Perform actions on the repository
    //
    Person person = new Person {Id = Guid.NewGuid(), FirstName = "Bob", LastName = "Cravens" };
    repo.Add(person);

    // Commit the transaction.
    //
    session.Commit();
}
</pre>
<p>Typically the IDbSessionFactory is created once at the start of the application. The concrete implementation of this interface would most likely use your favorite ORM on top of your favorite database. The Github repository currently provides two concrete implementations: NHibernate and an in-memory fake. You can use the fake for automated testing.</p>
<h3>Conclusion</h3>
<p>Visit the Github source and let me know if you see improvements or if you find this useful. I would like to add a few more implementation for some of the other popular ORMs. If you want to contribute an implementation please let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://bobcravens.com/2011/05/a-net-generic-repository-pattern-with-implementations/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Testing Your CRUD Using Generics</title>
		<link>http://bobcravens.com/2011/04/testing-your-crud-using-generics/</link>
		<comments>http://bobcravens.com/2011/04/testing-your-crud-using-generics/#respond</comments>
		<pubDate>Fri, 22 Apr 2011 16:38:24 +0000</pubDate>
		<dc:creator><![CDATA[rcravens]]></dc:creator>
				<category><![CDATA[Testing]]></category>
		<category><![CDATA[data access]]></category>
		<category><![CDATA[nhibernate]]></category>

		<guid isPermaLink="false">http://blog.bobcravens.com/2011/04/testing-your-crud-using-generics/</guid>
		<description><![CDATA[I often use a generic repository pattern as a wrapper around my data access logic. This wrapper generally serves the purpose of encapsulating specific implementation details. Here are the repository interfaces that I current use: public interface IReadOnlyRepository&#60;TEntity&#62; where TEntity:class { IQueryable&#60;TEntity&#62; All(); } public interface IRepository&#60;TEntity&#62; : IReadOnlyRepository&#60;TEntity&#62; where TEntity:class { bool Add(TEntity entity); [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I often use a generic repository pattern as a wrapper around my data access logic. This wrapper generally serves the purpose of encapsulating specific implementation details. Here are the repository interfaces that I current use:</p>
<pre class="brush: csharp;">public interface IReadOnlyRepository&lt;TEntity&gt; where TEntity:class
{
    IQueryable&lt;TEntity&gt; All();
}
public interface IRepository&lt;TEntity&gt; : IReadOnlyRepository&lt;TEntity&gt; where TEntity:class
{
    bool Add(TEntity entity);
    bool Add(IEnumerable&lt;TEntity&gt; items);
    bool Update(TEntity entity);
    bool Delete(TEntity entity);
    bool Delete(IEnumerable&lt;TEntity&gt; entities);
}
public interface IKeyedRepository&lt;TKey, TEntity&gt; : IRepository&lt;TEntity&gt;
    where TEntity : class, IKeyed&lt;TKey&gt;
{
    TEntity FindBy(TKey id);
}
public interface IKeyed&lt;TKey&gt;
{
    TKey Id { get; }
}
</pre>
<p>&nbsp;</p>
<p>I have a couple of <a href="http://blog.bobcravens.com/2010/09/the-repository-pattern-part-2/">previous posts on the repository pattern</a>. </p>
<p>After creating a specific implementation of the repository, I often want to do some simple tests of the create, read, update and delete (CRUD) functions. This allows a quick test to ensure that my repository is configured correctly (DB configuration, entity mappings…etc). These tests are not meant to be part of my automated test bed. These are simply something that I run locally with a real database to get a quick “go” or “no go” indication. To accomplish these tests usually requires the following steps:</p>
<ol style="padding-bottom: 0px; padding-left: 20px; padding-right: 0px; padding-top: 0px">
<li>Create an instance of the repository for the entity type.
<li>Get a count of the number of entities in the DB before we start.
<li>Instantiate an entity using random data.
<li>Add the entity to the DB.
<li>Read the entity back out of the DB.
<li>Compare and ensure they are equal.
<li>Modify the original entity.
<li>Update the entity in the DB.
<li>Read the modified entity from the DB.
<li>Compare and ensure the entity was modified.
<li>Delete the entity.
<li>Get a count of the number of entities in the DB after.
<li>Compare the count before and after and ensure they are equal.</li>
</ol>
<p>This is not a full battery of tests, but hits the all the CRUD methods. I like to do this for each type of entity. This is very repetitive and provides a good opportunity to use Generics to simplify the process.</p>
<h3>Create and Update Random Entities</h3>
<p>The following bit of code generates an entity with properties that have been initialized with random values.</p>
<pre class="brush: csharp;">public static class Random&lt;T&gt; where T:class, new()
{
    private static readonly Random _random = new Random(DateTime.Now.Millisecond);

    public static T Create()
    {
        return Create(null);
    }

    public static T Create(List&lt;string&gt; protectedPropertyNames)
    {
        T result = new T();
        return Update(result, protectedPropertyNames);
    }

    public static T Update(T obj)
    {
        return Update(obj, null);
    }

    public static T Update(T obj, List&lt;string&gt; protectedPropertyNames)
    {
        Type type = typeof (T);
        foreach (PropertyInfo propertyInfo in type.GetProperties())
        {
            PropertyInfo info = propertyInfo;
            bool isFound = protectedPropertyNames == null ? false : protectedPropertyNames.Any(name =&gt; name.ToLower() == info.Name.ToLower());

            if (propertyInfo.CanWrite &amp;&amp; !isFound)
            {
                if (propertyInfo.PropertyType == typeof(DateTime))
                {
                    propertyInfo.SetValue(obj, DateTime.Now, null);
                }
                else if (propertyInfo.PropertyType == typeof(int))
                {
                    propertyInfo.SetValue(obj, _random.Next(), null);
                }
                else if (propertyInfo.PropertyType == typeof(bool))
                {
                    propertyInfo.SetValue(obj, _random.Next(0, 2) == 0 ? false : true, null);
                }
                else if (propertyInfo.PropertyType == typeof(string))
                {
                    propertyInfo.SetValue(obj, Guid.NewGuid().ToString(), null);
                }
                else if (propertyInfo.PropertyType == typeof(double))
                {
                    propertyInfo.SetValue(obj, _random.NextDouble(), null);
                }
                else if (propertyInfo.PropertyType == typeof(byte))
                {
                    propertyInfo.SetValue(obj, byte.Parse(_random.Next(byte.MinValue, byte.MaxValue).ToString()), null);
                }
                else if(propertyInfo.PropertyType == typeof(Guid))
                {
                    propertyInfo.SetValue(obj, Guid.NewGuid(), null);
                }
            }
        }

        return obj;
    }
}
</pre>
<p>&nbsp;</p>
<p>The code above serves two functions: create a new entity and update an existing entity. The create is really an update on a new entity and falls through to the same update code. The methods take an optional parameter that allows a list of properties to be provided that should not be updated. This allows you to set IDs that refer to existing objects without the reference being broken. The list of “if-else if” statements could be extended to include additional types.</p>
<h3>A Generic CRUD Tester</h3>
<p>Now that we can create and update entities with properties having random values. We need a generic test bench for the CRUD methods.</p>
<pre class="brush: csharp;">public static class CrudTester&lt;T&gt; where T: class, IKeyed&lt;int&gt;, new()
{
    public static void Test(ISessionFactory sessionFactory)
    {
        Test(sessionFactory, null);
    }

    public static void Test(ISessionFactory sessionFactory, List&lt;string&gt; protectedPropertyNames)
    {
        T entity1 = Random&lt;T&gt;.Create(protectedPropertyNames);
        Test(sessionFactory, protectedPropertyNames, entity1);
    }

    public static void Test(ISessionFactory sessionFactory, List&lt;string&gt; protectedPropertyNames, T seed)
    {
        int countBefore;

        using (UnitOfWork unitOfWork = new UnitOfWork(sessionFactory))
        {
            IKeyedRepository&lt;int, T&gt; repo = new Repository&lt;int, T&gt;(unitOfWork.Session);

            countBefore = repo.All().Count();

            // create
            repo.Add(seed);
            Assert.IsTrue(seed.Id &gt; 0);

            unitOfWork.Commit();
        }

        T entity2;
        using (UnitOfWork unitOfWork = new UnitOfWork(sessionFactory))
        {
            IKeyedRepository&lt;int, T&gt; repo = new Repository&lt;int, T&gt;(unitOfWork.Session);

            // read
            entity2 = repo.FindBy(seed.Id);
            Assert.IsTrue(seed.Equals(entity2));

            unitOfWork.Commit();
        }

        using (UnitOfWork unitOfWork = new UnitOfWork(sessionFactory))
        {
            IKeyedRepository&lt;int, T&gt; repo = new Repository&lt;int, T&gt;(unitOfWork.Session);

            // update
            seed = Random&lt;T&gt;.Update(seed, protectedPropertyNames);
            repo.Update(seed);
            T entity3 = repo.FindBy(seed.Id);
            Assert.IsFalse(entity2.Equals(seed));
            Assert.IsTrue(entity3.Equals(seed));

            unitOfWork.Commit();
        }

        using (UnitOfWork unitOfWork = new UnitOfWork(sessionFactory))
        {
            IKeyedRepository&lt;int, T&gt; repo = new Repository&lt;int, T&gt;(unitOfWork.Session);

            // delete
            repo.Delete(seed);
            int countAfter = repo.All().Count();
            Assert.IsTrue(countAfter == countBefore);

            unitOfWork.Commit();
        }
    }
}
</pre>
<p>&nbsp;</p>
<p>This above code provides three entry points with various levels of control over the test. The following parameters are either specified externally or internally generated:</p>
<ul>
<li>ISessionFactory – An NHibernate session factory (creates instances of ISession). This would need to be modified to work with other ORMs.
<li>Protected Property Names – This provides a list of property names that should not be modified.
<li>Seed – This provides a seed entity for testing allowing you to hook up your foreign keys and such. </li>
</ul>
<p>All three entry points fall into the final ‘Test’ method. This method simply runs the CRUD tests that we previously outlined.</p>
<h3>Summary</h3>
<p>The above code provides an easy framework to create tests that look like the following:</p>
<pre class="brush: csharp;">public Crud_Test_User_Entity()
{
    NHibernateHelper helper = new NHibernateHelper(_connectionString);
    CrudTester&lt;User&gt;.Test(helper.SessionFactory);
}

public Crud_Test_Address_Entity()
{
    Address address = Random&lt;Address&gt;.Create();
    address.UserId = 10;  // assume this user exists in DB

    NHibernateHelper helper = new NHibernateHelper(_connectionString);
    CrudTester&lt;Address&gt;.Test(helper.SessionFactory, new List&lt;string&gt;{"UserId"}, address);
}
</pre>
<p>This allows the basic CRUD methods to quickly be tested to ensure the ORM is configured correctly.</p>
]]></content:encoded>
			<wfw:commentRss>http://bobcravens.com/2011/04/testing-your-crud-using-generics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Upload Multiple Files With Progress Using Uploadify</title>
		<link>http://bobcravens.com/2011/03/upload-multiple-files-with-progress-using-uploadify/</link>
		<comments>http://bobcravens.com/2011/03/upload-multiple-files-with-progress-using-uploadify/#comments</comments>
		<pubDate>Sun, 27 Mar 2011 16:10:13 +0000</pubDate>
		<dc:creator><![CDATA[rcravens]]></dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[uploadify]]></category>

		<guid isPermaLink="false">http://blog.bobcravens.com/2011/03/upload-multiple-files-with-progress-using-uploadify/</guid>
		<description><![CDATA[I previously posted on how to use Uploadify to upload files. The previous post covered really well how to upload single files to an ASP.NET MVC controller using Uploadify. This post will expand on that a bit. First we will revisit how to upload multiple files using a single HTML input element. Then the case [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I previously posted on <a href="http://blog.bobcravens.com/2010/02/upload-files-with-progress-using-uploadify/">how to use Uploadify to upload files</a>. The previous post covered really well how to upload single files to an ASP.NET MVC controller using Uploadify. This post will expand on that a bit. First we will revisit how to upload multiple files using a single HTML input element. Then the case of uploading multiple files using multiple HTML input elements. Finally, how to upload multiple files while posting form data.</p>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/03/image.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/03/image_thumb.png" width="857" height="392"></a> </p>
<p>Here are links to the demo pages for the Single and Multiple file uploads.</p>
<p><a class="demo" href="http://bobcravens.com/Uploadify/Test/Multiple" target="_blank">Multiple</a>&nbsp; <a class="demo broken_link" href="http://bobcravens.com/Uploadify/Test/Single" target="_blank">Single</a></p>
<h3>Getting Started</h3>
<p>If you are not familiar with Uploadify here is a description from <a href="http://www.uploadify.com/">their web site</a>:</p>
<blockquote><p>Uploadify is a jQuery plugin that integrates a fully-customizable multiple file upload utility on your website. It uses a mixture of JavaScript, ActionScript, and any server-side language to dynamically create an instance over any DOM element on a page.</p>
</blockquote>
<p>If will first need to download the Uploadify code. I simply unzipped it into my ‘scripts’ folder as shown below:</p>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/03/image1.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/03/image_thumb1.png" width="264" height="353"></a> </p>
<p>Any page that uses Uploadify will need to include the following lines in the ‘head’ section:</p>
<pre class="brush: xml;">&lt;link href="&lt;%= Url.Content("~/Content/Scripts/uploadify/uploadify.css") %&gt;" rel="stylesheet" type="text/css" /&gt;

&lt;script type="text/javascript" src="http://cdn.bobcravens.com/wp-content/uploads/2011/03/jquery-1.4.1.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="&lt;%= Url.Content("~/Content/Scripts/uploadify/swfobject.js") %&gt;"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="&lt;%= Url.Content("~/Content/Scripts/uploadify/jquery.uploadify.v2.1.4.min.js") %&gt;"&gt;&lt;/script&gt;

</pre>
<p>The first line links in the CSS used by Uploadify. The last three lines add the required JavaScript.</p>
<h3>Multiple Files With A Single HTML Input</h3>
<p>Uploadify directly supports uploading multiple files by configuring the Uploadify object. Add the following HTML input elements to your page:</p>
<pre class="brush: xml;">&lt;p&gt;&lt;input type="file" id="multipleFiles" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;button id="btn1"&gt;Upload Files&lt;/button&gt;&lt;/p&gt;

</pre>
<p>The ‘input’ element will be used as the Uploadify object. The ‘button’ element serves as a trigger to start the uploads. Here is the JavaScript that configures this scenario:</p>
<pre class="brush: js;">// Multiple files - single input
$("#multipleFiles").uploadify({
    'uploader': '&lt;%= Url.Content("~/Content/Scripts/uploadify/uploadify.swf") %&gt;',
    'script': '&lt;%= Url.Action("Upload") %&gt;',
    'fileDataName': 'file',
    'buttonText': 'File Input...',
    'multi': true,
    'sizeLimit': 1048576,
    'simUploadLimit': 2,
    'cancelImg': '&lt;%= Url.Content("~/Content/Scripts/uploadify/cancel.png") %&gt;',
    'auto': false,
    'onError': function (a, b, c, d) {
        if (d.status == 404)
            alert("Could not find upload script. Use a path relative to: " + "&lt;?= getcwd() ?&gt;");
        else if (d.type === "HTTP")
            alert("error " + d.type + ": " + d.status);
        else if (d.type === "File Size")
            alert(c.name + " " + d.type + " Limit: " + Math.round(d.info / (1024 * 1024)) + "MB");
        else
            alert("error " + d.type + ": " + d.text);
    },
    'onComplete': function (event, queueId, fileObj, response, data) {
        alert(response);
    }
});
$("#btn1").click(function () {
    $('#multipleFiles').uploadifyUpload();
});

</pre>
<p>The Uploadify object supports a number of properties, events, and methods. <a href="http://www.uploadify.com/">Visit their page for in-depth information</a>. The configuration that allows multiple files to be selected is the ‘multi’ option. Setting this to ‘true’ enables multiple file selection as shown below.</p>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/03/image2.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/03/image_thumb2.png" width="631" height="430"></a></p>
<p>That results in the following:</p>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/03/image3.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/03/image_thumb3.png" width="412" height="199"></a> </p>
<p>The ‘Upload Files’ button is wired up to call the ‘uploadifyUpload’ method on the Uploadify object. This begins the upload process. The file uploads happen asynchronously and not in a guaranteed to arrive in a specified order. All selected files are handled by a single ASP.NET MVC action method:</p>
<pre class="brush: csharp;">public string Upload(HttpPostedFileBase file)
{
    // Process the file here.
    //
    return "Upload processed. filename=" + file.FileName;
}

</pre>
<p>This works great if the same processing can be applied to all files. If you require the files to be dispatched out to different processors based upon their type then this probably will not work. In this case, you will need to use multiple HTML input elements.</p>
<h3>Multiple Files With Multiple HTML Input Elements</h3>
<p>Now we have multiple HTML ‘input’ elements on the page.</p>
<pre class="brush: xml;">&lt;p&gt;&lt;input type="file" id="file1" name="file1" class="uploadify1" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;input type="file" id="file2" name="file2" class="uploadify1" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;input type="file" id="file3" name="file3" class="uploadify1" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;button id="btn2"&gt;Upload Files&lt;/button&gt;&lt;/p&gt;

</pre>
<p>The ‘button’ element is again used to start the upload processing. Each ‘input’ element has a unique ‘name’ attribute. If this were posted back in a normal HTML ‘form’ then this ‘name’ attribute would follow the file to the server where the file processing could be based upon the value of the ‘name’ attribute. Here is the JavaScript that configures this scenario:</p>
<pre class="brush: js;">// Multiple files - multiple inputs
var packageId = 'multiple1' + new Date().getTime() + Math.round(Math.random() * 1000);
$(".uploadify1").each(function () {
    $(this).uploadify({
        'uploader': '&lt;%= Url.Content("~/Content/Scripts/uploadify/uploadify.swf") %&gt;',
        'script': '&lt;%= Url.Action("Upload2") %&gt;',
        'fileDataName': 'file',
        'buttonText': 'File Input...',
        'multi': false,
        'scriptData': { 'packageId': packageId, 'type': $(this).attr('name') },
        'sizeLimit': 1048576,
        'simUploadLimit': 1,
        'cancelImg': '&lt;%= Url.Content("~/Content/Scripts/uploadify/cancel.png") %&gt;',
        'auto': false,
        'onError': function (a, b, c, d) {
            if (d.status == 404)
                alert("Could not find upload script. Use a path relative to: " + "&lt;?= getcwd() ?&gt;");
            else if (d.type === "HTTP")
                alert("error " + d.type + ": " + d.status);
            else if (d.type === "File Size")
                alert(c.name + " " + d.type + " Limit: " + Math.round(d.info / (1024 * 1024)) + "MB");
            else
                alert("error " + d.type + ": " + d.text);
        },
        'onComplete': function (event, queueId, fileObj, response, data) {
            alert(response);
        }
    });
});
$("#btn2").click(function () {
    $(".uploadify1").uploadifyUpload();
});

</pre>
<p>In this case, each input element is configured to only allow a single file to be selected (‘multi’:false). The key configuration in this case is the ‘scriptData’ option. This options allows JSON data to be sent back to the server along with the file. In this case we send a ‘packageId’ (created on the first line) and a ‘type’. The ‘packageId’ is used to associate the files into groups on the server. The ‘type’ variable is the ‘input’ element’s ‘name’ attribute and allows the server side code to differentiate the files. The ASP.NET MVC controller now looks like the following:</p>
<pre class="brush: csharp;">public string Upload2(HttpPostedFileBase file, string packageId, string type)
{
    // Add the file to the package.
    //
    Package package = PackageManager.GetPackage(packageId);
    package.AddFile(file, type);
    return "Upload received.nFilename: " + file.FileName + "nPackage Id: " + packageId + "nType: " + type;
}

</pre>
<p>This method not only receives the file, but also the JSON data sent by Uploadify. The JSON data is then used to add the incoming file to a particular package. The specific implementation of the packaging system is not important (and not shown), but the key is that the server has the information necessary to implement the packaging feature. The above code could just as easily dispatched the file to various processors based upon the ‘type’ parameter.</p>
<p>The above works great for processing files based upon their types. The next challenge is processing files and form data where the form data provides important context for processing.</p>
<h3>Multiple Files With Multiple HTML Input Plus Form Data</h3>
<p>Assume we have an HTML ‘form’ that accepts multiple files and the first/last name of the user. The files must be processed based upon who uploaded the files. Therefore the first/last name data is important and required before processing can occur. Here is the HTML defining the form:</p>
<pre class="brush: xml;">&lt;form id='form1' method='post' action='&lt;%= Url.Action("ProcessForm") %&gt;'&gt;
    &lt;p&gt;&lt;em&gt;Provide your name:&lt;/em&gt;&lt;/p&gt;
    &lt;p&gt;First Name &lt;input type="text" name="firstName" id="fname" /&gt;&lt;/p&gt;
    &lt;p&gt;Last Name &lt;input type="text" name="lastName" id="lname" /&gt;&lt;/p&gt;
    &lt;p&gt;&lt;em&gt;Using the buttons below, navigate and select up to three files (1MB size limit) then click the 'Submit' button:&lt;/em&gt;&lt;/p&gt;
    &lt;p&gt;&lt;input type="file" id="file4" name="file1" class="uploadify2" /&gt;&lt;/p&gt;
    &lt;p&gt;&lt;input type="file" id="file5" name="file2" class="uploadify2" /&gt;&lt;/p&gt;
    &lt;p&gt;&lt;input type="file" id="file6" name="file3" class="uploadify2" /&gt;&lt;/p&gt;
    &lt;p&gt;&lt;input type="submit" id="btn3" /&gt;&lt;/p&gt;
&lt;/form&gt;

</pre>
<p>Traditionally (without Uploadify involved) this form would POST all the data to a single ASP.NET MVC action method and no upload progress would be provided. Hooking up Uploadify provides the desired progress indicators, but now the files are uploaded ‘out of band’. Some special handling is necessary to keep the files and the form data associated. Here is the JavaScript that configures the form:</p>
<pre class="brush: js;">// Multiple files - multiple inputs in a form
var packageId2 = 'multiple2' + new Date().getTime() + Math.round(Math.random() * 1000);
var elem = $("&lt;input type='hidden' name='packageId' value='" + packageId2 + "' /&gt;");
$("#form1").prepend(elem);
$(".uploadify2").each(function () {
    $(this).uploadify({
        'uploader': '&lt;%= Url.Content("~/Content/Scripts/uploadify/uploadify.swf") %&gt;',
        'script': '&lt;%= Url.Action("Upload2") %&gt;',
        'fileDataName': 'file',
        'buttonText': 'File Input...',
        'multi': false,
        'scriptData': { 'packageId': packageId2, 'type': $(this).attr('name') },
        'sizeLimit': 1048576,
        'simUploadLimit': 1,
        'cancelImg': '&lt;%= Url.Content("~/Content/Scripts/uploadify/cancel.png") %&gt;',
        'auto': false,
        'onError': function (a, b, c, d) {
            if (d.status == 404)
                alert("Could not find upload script. Use a path relative to: " + "&lt;?= getcwd() ?&gt;");
            else if (d.type === "HTTP")
                alert("error " + d.type + ": " + d.status);
            else if (d.type === "File Size")
                alert(c.name + " " + d.type + " Limit: " + Math.round(d.info / (1024 * 1024)) + "MB");
            else
                alert("error " + d.type + ": " + d.text);
        },
        'onComplete': function (event, queueId, fileObj, response, data) {
            incrementUploadCount();
        }
    });
});
$("#btn3").click(function (evt) {
    evt.preventDefault();

    submit();
});

</pre>
<p>The Uploadify elements are configured nearly the same as before using the ‘scriptData’ option to send back the ‘packageId’ and the ‘type’ information as JSON. However, in this case the ‘packageId’ is prepended to the form as an HTML hidden ‘input’ element (first three lines). In addition the Uploadify ‘onComplete’ callback now calls the ‘incrementUploadCount’ function (covered below) and the HTML submit button is wired up to call the ‘submit’ function.</p>
<pre class="brush: js;">var numFilesSelected = 0;
var numFilesUploaded = 0;
function submit() {
    // validate the form
    if ($('#fname').val() === '') {
        alert('Provide a first name.');
        return;
    }
    if ($('#lname').val() === '') {
        alert('Provide a last name.');
        return;
    }

    // determine the number of files that need to be
    //  uploaded and reset the uploaded count
    numFilesSelected = $(".uploadifyQueueItem").length;
    numFilesUploaded = 0;
    // upload the files
    $('.uploadify2').uploadifyUpload();
}

function incrementUploadCount() {
    numFilesUploaded++;
    if (numFilesUploaded === numFilesSelected) {
        alert('About to submit the form data.');
        postFormData();
    }
}

function postFormData() {
    $("#form1").submit();
}
</pre>
<p>The above code defines the client side pipeline that eventually upload the files and submit the form. The submit button calls the ‘submit’ function. In the ‘submit’ function, the form is first validated. Then the number of files being uploaded is determined and a counter is set to zero. Finally, the Uploadify elements are triggered.</p>
<p>Each Uploadify element calls the ‘incrementUploadCount’ upon successfully uploading the file to the server. Once all the files have been uploaded, the form is submitted. Here is the ASP.NET MVC action methods that are needed:</p>
<pre class="brush: csharp;">public string Upload2(HttpPostedFileBase file, string packageId, string type)
{
    // Add the file to the package.
    //
    Package package = PackageManager.GetPackage(packageId);
    package.AddFile(file, type);
    return "Upload received.nFilename: " + file.FileName + "nPackage Id: " + packageId + "nType: " + type;
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ProcessForm(string firstName, string lastName, string packageId)
{
    Package package = PackageManager.GetPackage(packageId);
    package.FirstName = firstName;
    package.LastName = lastName;
    PackageManager.RemovePackage(package.Id);
    return View("UploadReceipt", package);
}

</pre>
<p>The ‘Upload2’ action method is the same as before. It collects the uploaded files into a package. The ‘ProcessForm’ action method receives the rest of the form data along with the ‘packageId’. The ‘packageId’ is used to request the ‘Package’ that contains the associated files. The form data is then added to the ‘Package’. Once complete the ‘Package’ can be sent off for processing as a whole. In this case, it is simply sent to a ‘View’ to render a receipt page.</p>
<h3>Summary</h3>
<p>Uploading multiple files with progress using Uploadify is an option. Depending on your requirements there can be additional complexity. In this post, we have covered a way of accomplishing multiple file uploads under various requirements. As always, if you have feedback post a comment.</p>
<h3>[ Update ]</h3>
<p>Here is the package manager that I put together. I did not put a lot of thought or testing into this implementation.</>
<pre class="brush:csharp;">public class UploadedFile
{
    public HttpPostedFileBase Stream { get; set; }
    public string Type { get; set; }
}

public class Package
{
    public string Id { get; private set; }
    public List&lt;UploadedFile&gt; Files { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Package(string id)
    {
        Id = id;
        Files = new List&lt;UploadedFile&gt;();
    }

    public void AddFile(HttpPostedFileBase file, string type)
    {
        UploadedFile fileInfo = new UploadedFile { Stream = file, Type = type };
        Files.Add(fileInfo);
    }
}

public static class PackageManager
{
    private static readonly List&lt;Package&gt; _packages = new List&lt;Package&gt;();

    public static Package GetPackage(string packageId)
    {
        Package package = _packages.Where(p =&gt; p.Id == packageId).SingleOrDefault();
        if (package == null)
        {
            package = new Package(packageId);
            _packages.Add(package);
        }
        return package;
    }

    public static void RemovePackage(string packageId)
    {
        Package package = _packages.Where(p =&gt; p.Id == packageId).SingleOrDefault();
        if (package != null)
        {
            _packages.Remove(package);
        }
    }
}

</pre>
]]></content:encoded>
			<wfw:commentRss>http://bobcravens.com/2011/03/upload-multiple-files-with-progress-using-uploadify/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>A Modal Dialog Plugin for jQuery</title>
		<link>http://bobcravens.com/2011/02/a-modal-dialog-plugin-for-jquery/</link>
		<comments>http://bobcravens.com/2011/02/a-modal-dialog-plugin-for-jquery/#respond</comments>
		<pubDate>Sat, 26 Feb 2011 17:55:02 +0000</pubDate>
		<dc:creator><![CDATA[rcravens]]></dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[plugin]]></category>

		<guid isPermaLink="false">http://blog.bobcravens.com/2011/02/a-modal-dialog-plugin-for-jquery/</guid>
		<description><![CDATA[There are a number of great jQuery modal plug-ins that already exist. So, why am I cluttering the interwebs with yet another one? There are a number of reasons: Feature Bloat – A number of plug-ins offer a lot of features. At times so many features that the plug-in became too complicated to use. I [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>There are a number of great jQuery modal plug-ins that already exist. So, why am I cluttering the interwebs with yet another one? There are a number of reasons:</p>
<ul>
<li><strong><img style="border-right-width: 0px; margin: 0px 10px 0px 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="form[1]" border="0" alt="form[1]" align="left" src="http://cdn.bobcravens.com/wp-content/uploads/2011/02/form1_thumb.png" width="380" height="257">Feature Bloat</strong> – A number of plug-ins offer a lot of features. At times so many features that the plug-in became too complicated to use. I want the plug-in to be simple to integrate into my page.
<li><strong>Styling Issues</strong> – Some modal plug-ins do not separate the CSS for visual styling (e.g. border and background-color) the modal from those styles necessary to create a modal (e.g. positioning and z-index). I want the visual styling to be 100% in my page’s CSS.
<li><strong>Learning Experience</strong> – This is probably the most important reason (at least to me). Writing code, using your creations and sharing them with the community are three ‘bullet-proof’ ways to improve your skills.</li>
</ul>
<p>For more information or to download check out the demo page!</p>
<p><a class="demo" href="http://bobcravens.com/demos/modal/">Demo</a></p>
]]></content:encoded>
			<wfw:commentRss>http://bobcravens.com/2011/02/a-modal-dialog-plugin-for-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Loosely Coupled JavaScript Using PubSub</title>
		<link>http://bobcravens.com/2011/01/loosely-coupled-javascript-using-pubsub/</link>
		<comments>http://bobcravens.com/2011/01/loosely-coupled-javascript-using-pubsub/#comments</comments>
		<pubDate>Sun, 30 Jan 2011 21:04:09 +0000</pubDate>
		<dc:creator><![CDATA[rcravens]]></dc:creator>
				<category><![CDATA[Patterns]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://blog.bobcravens.com/2011/01/loosely-coupled-javascript-using-pubsub/</guid>
		<description><![CDATA[I recently watched a very interesting video by Rebecca Murphy that discussed using the pubsub architecture to create loosely coupled JavaScript. The concept is to develop your JavaScript objects and allow the communication between the objects to occur via events that are managed by a publisher / subscriber (pubsub) service. The diagram below illustrates a [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I recently watched a very interesting <a href="http://net.tutsplus.com/tutorials/javascript-ajax/loose-coupling-with-the-pubsub-plugin/">video by Rebecca Murphy</a> that discussed using the pubsub architecture to create loosely coupled JavaScript. The concept is to develop your JavaScript objects and allow the communication between the objects to occur via events that are managed by a publisher / subscriber (pubsub) service. The diagram below illustrates a pubsub service that exposes three methods: publish, subscribe, and unsubscribe. In this case, two ‘panels’ are subscribing to the service.</p>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/01/image4.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/01/image_thumb3.png" width="405" height="394"></a> A data source in the system then publishes data to the pubsub service. The pubsub service forwards this data to the appropriate subscribers. This is illustrated below.</p>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/01/image5.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/01/image_thumb4.png" width="404" height="395"></a>The pubsub service allows subscriptions to specific ‘events’. Much like you can subscribe to specific channels with your cable TV provider.</p>
<p>Let’s take a look at a specific example. Imagine we have a web page. On that we page is a form that allows the user to enter their name, lucky number, and select a favorite color.</p>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/01/image6.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/01/image_thumb5.png" width="233" height="466"></a>In addition to this form we have a number of other panels that present the data in a specialized way. For example we could have a panel that presents the names of all registered users. Another panel could present data about only the most recent users. While another displays a list of unique lucky numbers. Yet another presents color swatches of all the favorite colors. The development of these panels could be quite complex. Each will probably have its own HTML, CSS, and JavaScript.</p>
<p><a href="http://cdn.bobcravens.com/wp-content/uploads/2011/01/image7.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://cdn.bobcravens.com/wp-content/uploads/2011/01/image_thumb6.png" width="628" height="224"></a> </p>
<p>By using the pubsub service to couple these panels to the data source, each can be developed independently of the others. The development process feels a bit like using an IOC container. Develop each component and then bind them together. Here is a link to a demo page.</p>
<p><a class="demo" href="http://bobcravens.com/demos/pubsub/">Demo</a></p>
<h3>HTML</h3>
<p>The markup for this example is shown below:</p>
<pre class="brush: xml;">&lt;div id="page"&gt;
    &lt;div id="form"&gt;
        &lt;p&gt;
            &lt;label for="first"&gt;First Name&lt;/label&gt;
            &lt;input type="text" id="first" /&gt;
        &lt;/p&gt;
        &lt;p&gt;
            &lt;label for="last"&gt;Last Name&lt;/label&gt;
            &lt;input type="text" id="last" /&gt;
        &lt;/p&gt;
        &lt;p&gt;
            &lt;label for="number"&gt;Lucky Number&lt;/label&gt;
            &lt;input type="text" id="number" /&gt;
        &lt;/p&gt;
        &lt;p&gt;
            &lt;label for="color"&gt;Favorite Color&lt;/label&gt;
            &lt;input type="text" id="color" name="color" value="#006699" /&gt;
            &lt;div id="colorpicker"&gt;&lt;/div&gt;
        &lt;/p&gt;
        &lt;p&gt;
            &lt;button id="add"&gt;Add&lt;/button&gt;
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;div id="panel-wrap"&gt;
        &lt;div id="names" class="panel"&gt;&lt;/div&gt;
        &lt;div id="lastuser" class="panel"&gt;&lt;/div&gt;
        &lt;div id="numbers" class="panel"&gt;&lt;/div&gt;
        &lt;div id="colors" class="panel"&gt;&lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;

</pre>
<p>There are two main sections. The top defines the form (in a literal sense not the html element) that is used as the data source. The bottom creates placeholders for the panels.</p>
<h3>JavaScript</h3>
<p>I am using a slightly modified version of a pubsub plug-in <a href="https://github.com/phiggins42/bloody-jquery-plugins/blob/master/pubsub.js">created by Peter Higgins</a>. The only modification that I did was to add a try catch block around the publish method. Without that modification any one subscriber can prevent later subscribers from receiving the event by having ‘exceptional code’ (in a bad way). For completeness here is the final code (without the comments):</p>
<pre class="brush: js;">;(function(d){
    var cache = {};

    d.publish = function(/* String */topic, /* Array? */args){
        try{
            d.each(cache[topic], function(){
                this.apply(d, args || []);
            });
        } catch (err) {
            // handle this error
            console.log(err);
        }
    };

    d.subscribe = function(/* String */topic, /* Function */callback){
        if(!cache[topic]){
            cache[topic] = [];
        }
        cache[topic].push(callback);
        return [topic, callback]; // Array
    };

    d.unsubscribe = function(/* Array */handle){
        var t = handle[0];
        cache[t] &amp;&amp; d.each(cache[t], function(idx){
            if(this == handle[1]){
                cache[t].splice(idx, 1);
            }
        });
    };

})(jQuery);
</pre>
<p>&nbsp;</p>
<p>The main page uses this service to bind publishers and subscribers to each other. The relevant JavaScript is shown below:</p>
<pre class="brush: js;">// Initialize the panels
//    1st param: the container element
//    2nd param: the event to subscribe
var userPanel = new UserPanel(      $('#names'),    'new/user');
var lastPanel = new LastUser(       $('#lastuser'), 'new/all');
var numberPanel = new LuckyNumbers( $('#numbers'),  'new/number');
var colorPanel = new FavColors(     $('#colors'),   'new/color');


// Bind to the click event
$('#add').click(function(){

    // Get the values from the form
    var first = $('#first').val();
    var last = $('#last').val();
    var color = $('#color').val();
    var number = $('#number').val();
    if(isNaN(number)){
        alert("woah...that's not a number");
        $('#number').focus();
        return;
    }

    // Publish the new data
    $.publish('new/user',   [first,last]);
    $.publish('new/number', [number]);
    $.publish('new/color',  [color]);
    $.publish('new/all',    [first,last,number,color]);
});

</pre>
<p>First this code creates and initializes four panel objects. Each panel takes a container element and an event in the constructor. Each panel then subscribes to the appropriate event and renders itself. The code above binds to the ‘click’ event of the form that we created earlier. At the bottom of that binding are the publish events supported by the form. The data is sliced up and made available via a number of events that expose only that slice.</p>
<p>Each panel is contained in its own JavaScript file. They all follow the same pattern. The following code shows the ‘UserPanel’ object. View source the demo for the other panels.</p>
<pre class="brush: js;">function UserPanel(parent, event){
    var _parent = parent;
    var _html = '';
    var _title = 'Registered Users';
    var _tmpl = '&lt;li&gt;{{name}}&lt;/li&gt;';

    var _renderUserPanel = function(name){
        if(name!=undefined){
            var elem = _tmpl.replace('{{name}}', name);
            _html = _html + elem;
        }

        var result = '&lt;h3&gt;' + _title + '&lt;/h3&gt;';
        if(_html!=''){
            result += '&lt;ul&gt;' + _html + '&lt;/ul&gt;';
        } else {
            result += '&lt;ul&gt;&lt;li&gt;no users&lt;/li&gt;&lt;/ul&gt;';
        }
        _parent.html(result);
    }

    var _subscribe = function(event){
        $.subscribe(event, function(first, last){
            var name = first + ' ' + last;
            _renderUserPanel(name);
        });
    }

    // render the initial markup
    _renderUserPanel();
    if(event!=undefined){
        _subscribe(event);
    }
}

</pre>
<h3>Summary</h3>
<p>There is a definite trade off with this architecture. On one hand there is a bit more code. On the other hand the architecture is more decoupled. I struggled a bit to come up with a meaningful example that tips the balance in favor of decoupled architecture. With simple pubsub examples, the added code appears as too much cost for the added benefit. I hope this example has found the right balance. If you know of a better example, please provide links in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://bobcravens.com/2011/01/loosely-coupled-javascript-using-pubsub/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: https://www.w3-edge.com/products/

Object Caching 1168/1378 objects using disk
Page Caching using disk: enhanced
Content Delivery Network via Amazon Web Services: CloudFront: cdn.bobcravens.com
Minified using disk
Database Caching 10/48 queries in 0.155 seconds using disk

 Served from: blog.bobcravens.com @ 2016-11-27 00:53:59 by W3 Total Cache -->