<?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>Rohland de Charmoy</title>
	<atom:link href="http://www.rohland.co.za/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.rohland.co.za</link>
	<description>Pushing buttons...</description>
	<lastBuildDate>Sat, 04 Feb 2012 16:01:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>FogBugz &#8211; Email edge detection</title>
		<link>http://www.rohland.co.za/index.php/2012/02/04/fogbugz-email-edge-detection/</link>
		<comments>http://www.rohland.co.za/index.php/2012/02/04/fogbugz-email-edge-detection/#comments</comments>
		<pubDate>Sat, 04 Feb 2012 15:56:54 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Tips and tricks]]></category>
		<category><![CDATA[FogBugz]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Outlook]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=396</guid>
		<description><![CDATA[A while ago I was involved in a project at Clyral where we developed a web based support ticketing system (similar to Zendesk). One of the things we focused on was dealing with the detection of new content in an email conversation. Typically, emails would bounce back and forth between a customer and an agent [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago I was involved in a project at <a href="http://www.clyral.com" target="_blank">Clyral</a> where we developed a web based support ticketing system (similar to <a href="http://www.zendesk.com/" target="_blank">Zendesk</a>). One of the things we focused on was dealing with the detection of new content in an email conversation. Typically, emails would bounce back and forth between a customer and an agent and we wanted to ensure that our web interface wasn’t cluttered with the full email thread for every reply the customer sent in (the original conversation was always included in outbound emails for convenience).</p>
<p>When we looked at implementing the mechanism which would only extract new content from an inbound email, we found it surprising that there was no official standard for demarcating the beginning and end of an email in an email thread. We took a look at a few mail clients and discovered that Microsoft Outlook is capable of dealing with this problem. If you use one of newer versions of Microsoft Outlook, you’ll notice that the client is capable of detecting the boundaries between emails. Take a look at the screenshot below:</p>
<p><a href="http://www.rohland.co.za/wp-content/uploads/2012/02/image.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://www.rohland.co.za/wp-content/uploads/2012/02/image_thumb.png" alt="image" width="644" height="393" border="0" /></a></p>
<p>Notice how Outlook has detected the boundaries between each email. Each email has a gradient which assists you to navigate the thread, furthermore, if you hover over a specific email, you can jump to the next/previous email in the thread relatively easily.</p>
<p>While there didn’t seem to be a standard way of achieving this, we managed to get a decent solution in place for our ticketing system. Since we were sending out the emails which customers would reply to, we could standardise the email content such that we could easily detect the boundary when a customer responded. This was not a full proof solution, so in the end, we implemented a heuristic algorithm that could deal with most of the common mail clients out there. Implementing this feature made it infinitely easier to manage conversations with customers. Obviously, we always kept keep the original email as customers would sometimes reply with changes to the original email content (such as answering questions inline).</p>
<p>Last year, we started using <a href="http://www.fogcreek.com/fogbugz/" target="_blank">FogBugz</a> as our general case and project management system. What we discovered was that FogBugz isn’t as smart as the system we developed in terms of dealing with email conversations. Outbound emails would not include the full email conversation and if you don’t use the web interface to respond, the boundary between the new content and email thread isn’t detected at all. This usually leads to a very cluttered case view where you need to scroll over copious amounts of duplicate text.</p>
<p>To deal with this problem, I implemented a very simple JavaScript customisation which scans over the content in a case and hides any email text which is superfluous. You always have the capability to toggle the content if you do need to inspect it. I’ve included the code for the customisation below. We use Microsoft Outlook (and most of our clients do as well), so the solution works well for us. The code simply scans email for the ‘From: ..’ and splits the email there. It’s not rocket science.</p>
<pre class="brush: jscript; title: ; notranslate">$(function(){
    $('.emailBody').each(function(index, element){
        var body = $(element);
        var edgeIndex = body.html().indexOf('&lt;br&gt;\nFrom: ');
        if (edgeIndex == -1){
        	return;
        }
        var mainBody = body.html().substring(0, edgeIndex);
        var quotedBody = body.html().substring(edgeIndex);
        body.html(mainBody);
        body.append('&lt;div class=&quot;showQuote&quot; style=&quot;padding-top:5px&quot;&gt;&lt;a href=&quot;javascript:void(0);&quot; class=&quot;dotted&quot; onclick=&quot;$(this).parent().parent().find(\'.emailThreadBody\').toggle();&quot;&gt;- show quoted text -&lt;/a&gt;&lt;/div&gt;');
        body.append('&lt;div class=&quot;emailThreadBody&quot; style=&quot;display:none;&quot;&gt;&lt;/div&gt;');
        body.find('.emailThreadBody').html(quotedBody);
    });
});
</pre>
<p>Hope this helps. Hopefully, this issue is addressed in the next major version of FogBugz.</p>
<p>Cheers,<br />
Rohland</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2012/02/04/fogbugz-email-edge-detection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Outlook plugin to enhance FogBugz email notifications</title>
		<link>http://www.rohland.co.za/index.php/2011/06/07/outlook-plugin-to-enhance-fogbugz-email-notifications/</link>
		<comments>http://www.rohland.co.za/index.php/2011/06/07/outlook-plugin-to-enhance-fogbugz-email-notifications/#comments</comments>
		<pubDate>Tue, 07 Jun 2011 20:17:08 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Tips and tricks]]></category>
		<category><![CDATA[FogBugz]]></category>
		<category><![CDATA[Outlook]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=382</guid>
		<description><![CDATA[We’ve recently started using FogBugz to track the work we do. It’s early days, but we’re hoping FogBugz’s Evidence Based Scheduling (EBS) feature will be able assist us to schedule our sprints better. One thing I found particularly annoying when we first started using the product is that there is no easy way to customise [...]]]></description>
			<content:encoded><![CDATA[<p>We’ve recently started using <a href="http://www.fogcreek.com/fogbugz/" target="_blank">FogBugz</a> to track the work we do. It’s early days, but we’re hoping FogBugz’s <a href="http://www.joelonsoftware.com/items/2007/10/26.html" target="_blank">Evidence Based Scheduling (EBS) feature</a> will be able assist <a href="http://www.clyral.com" target="_blank">us</a> to schedule our sprints better. One thing I found particularly annoying when we first started using the product is that there is no easy way to customise the email notifications you receive. I believe it is possible to update the template when using the self hosted option but that requires fiddling with their code. This is the typical notification one receives if someone edits a case that’s assigned to you (or in the case someone notifies you of a change to a case you are potentially not assigned to):</p>
<p><a href="http://www.rohland.co.za/wp-content/uploads/2011/06/image.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" src="http://www.rohland.co.za/wp-content/uploads/2011/06/image_thumb.png" border="0" alt="image" width="510" height="293" /></a></p>
<p>The notification has all the information you need, however, it’s pretty hard to pick up the message someone may have included. I’m not a fan of plain text emails. When you start receiving a number of these notifications every day, it gets a bit annoying trying to scroll and find the meat of the notification. On Saturday I spent a few hours developing a plugin for Outlook 2010 that could assist with the issue. While this was not my only option (I could have developed a FogBugz <a href="http://www.fogcreek.com/fogbugz/plugins/" target="_blank">plugin</a>), I was intrigued to see if it was indeed possible to update the format of a message in Outlook. As it turns out it’s pretty easy.</p>
<p>This is the result:</p>
<p><a href="http://www.rohland.co.za/wp-content/uploads/2011/06/image1.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" src="http://www.rohland.co.za/wp-content/uploads/2011/06/image_thumb1.png" border="0" alt="image" width="501" height="301" /></a></p>
<p>I’m no designer (and Outlook’s HTML support is <a href="http://www.campaignmonitor.com/blog/post/2393/microsoft-takes-email-design-b/" target="_blank">crap</a>) but I’m relatively happy with what I was able to achieve in a short time frame. The plugin will update the email’s format as you open the email so basically, you never have to deal with the plain text version outlined in the first screenshot. Obviously, the downside to this approach is that notifications received on your phone won’t render in the format above (unless you are using Exchange or similar and have opened the email at least once in Outlook).</p>
<p>Other features I was able to add relatively easily included setting the priority flag on the email depending on the priority of the case. If the case is really urgent (priority 1 or 2), the priority flag is set appropriately.</p>
<p><a href="http://www.rohland.co.za/wp-content/uploads/2011/06/image2.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" src="http://www.rohland.co.za/wp-content/uploads/2011/06/image_thumb2.png" border="0" alt="image" width="225" height="43" /></a></p>
<p>If for some reason the parsing fails, the default email format is kept.</p>
<p>I’ve included the source code as an attachment of this post. Feel free to customise it for your needs. It should be relatively easy to update the template as it is bound to a model which is instantiated as a result of parsing the plain text email.</p>
<p>Hope this is useful.</p>
<p>Rohland</p>
<div id="scid:8eb9d37f-1541-4f29-b6f4-1eea890d4876:c71e17d3-1659-441b-af59-34077a488b20" class="wlWriterEditableSmartContent" style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px">
<div><a href="http://www.rohland.co.za/wp-content/uploads/2011/06/Clyral.Outlook.FogBugzFormatter1.zip" target="_self">Clyral.Outlook.FogBugzFormatter.zip</a></div>
<div><a href="http://www.rohland.co.za/wp-content/uploads/2011/06/Clyral.Outlook.FogBugzFormatter-Setup.zip">Clyral.Outlook.FogBugzFormatter Setup</a></div>
<div></div>
<div></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2011/06/07/outlook-plugin-to-enhance-fogbugz-email-notifications/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Strategy for migrating web applications between hosting providers</title>
		<link>http://www.rohland.co.za/index.php/2010/11/20/strategy-for-migrating-web-applications-between-hosting-providers/</link>
		<comments>http://www.rohland.co.za/index.php/2010/11/20/strategy-for-migrating-web-applications-between-hosting-providers/#comments</comments>
		<pubDate>Sat, 20 Nov 2010 13:59:42 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[haproxy]]></category>
		<category><![CDATA[Nginx]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=342</guid>
		<description><![CDATA[It&#8217;s inevitable. If you are a web developer, at some point in time, you are going to be stuck with the problem of migrating a system between internet service providers. At that point you will discover (if you haven&#8217;t already) that it&#8217;s a bit of a pain in the ass. Not just because you have [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s inevitable. If you are a web developer, at some point in time, you are going to be stuck with the problem of migrating a system between internet service providers. At that point you will discover (if you haven&#8217;t already) that it&#8217;s a bit of a pain in the ass. Not just because you have to move stuff, but because of DNS management and the infamous propagation lag.</p>
<p><a href="http://www.rohland.co.za/wp-content/uploads/2010/11/man-pulling-hair-out-2.jpg"><img src="http://www.rohland.co.za/wp-content/uploads/2010/11/man-pulling-hair-out-2.jpg" alt="(image courtesy of: Michael Witthaus: localrhythms.wordpress.com)" title="(image courtesy of: Michael Witthaus: localrhythms.wordpress.com)" width="200" height="322" class="aligncenter size-full wp-image-366" /></a></p>
<p>I&#8217;ve given this quite a bit of thought lately as we were in the process of migrating many of our systems to a new hosting provider. There are two main areas you need to focus on in minimising downtime for your clients:</p>
<ul>
<li>Time required to take the site down, backup, move and restore everything to the new server/s.</li>
<li>The DNS record update.</li>
</ul>
<p>The second item on this list is the major issue. You have little control over the amount of time your DNS update is going to take to propagate to your clients due to DNS record caching. <a href="http://www.ducea.com/2006/05/21/moving-your-website-to-another-server-tune-your-dns-for-minimum-downtime/" target="_blank">Reducing the TTL</a> is not a full-proof solution since many ISPs won&#8217;t obey unusually low <a href="http://en.wikipedia.org/wiki/Time_to_live" target="_blank">TTL settings</a> that you may configure. People have come up with various strategies for dealing with the issue such as <a href="http://omaralzabir.com/redirect_traffic_from_old_to_new_server_when_you_change_hosting_service/comment-page-1/#comment-9414" target="_blank">implementing a temporary sub-domain</a> while the DNS record update slowly propagates around the globe. Either of the options above may be your best bet in many circumstances, however, if you are making use of a load balancer or proxy (such as <a href="http://nginx.org/en/" target="_blank">Nginx</a>) migrating your site is less of an issue.</p>
<p>Before migrating to our new service provider, we were not making use of a load balancer such as <a href="http://nginx.org/en/" target="_blank">Nginx</a>/<a href="http://haproxy.1wt.eu/" target="_blank">HAProxy</a>, however, we had one setup at our new hosting centre (we went with Nginx) before we began the migration. Whilst the rationale for implementing Nginx was more out of the need to create a resilient hosting infrastructure for our clients, we also gained the ability to have more control over where our content is served from.</p>
<p>For those of you not familiar with the concept of a load balancer in the web context, it simply allows you to proxy requests through one endpoint to a dynamic number of back-end web servers. In the Nginx context, the back-end servers are configured as upstream servers. When an HTTP request is received, Nginx forwards the request to one of the back-end webservers. For each successive request, a round robin balancing algorithm is employed to fairly distribute the load. You can control the weighting of each upstream server to deal with a mismatch in server capabilities (think of 3 webservers where 1 is far more capable than the others due to better hardware). While Nginx sufficiently handles balancing in our case, HAProxy does have far more capabilities in this area.</p>
<p>Back to the DNS update issue (if the solution hasn&#8217;t become apparent yet, it will now). In our new environment, we configured our Nginx load balancer to point to all our existing webservers (i.e. not our new webservers). Once we completed the configuration of Nginx to do this, we updated all of our DNS settings. We then waited a few days. As you can imagine, over the course of time, each site began resolving to our new hosting provider but users experienced no downtime since Nginx was simply proxying the updated requests to the original servers. This meant that clients who had not yet received the updated DNS record were hitting the original servers, while clients that did receive the DNS update we also doing so but through Nginx at our new hosting provider. Once we were comfortable that everyone was hitting the various sites through our new setup we simply turned everything off and performed the real migration (i.e. physically move the databases etc. across).</p>
<p>Given this approach we minimised downtime for our clients. The 2-3 hours for the physical migration of databases and systems was acceptable to our clients, 2-3 days for DNS resolution was not. This solution mitigated days of potential downtime and worked well for us. The only real downsides to the approach was that our sites operated marginally slower (due to added latency between new and old host) and that we had to pay for bandwidth twice during the transition period. Both of these issues were tenable given the alternatives.</p>
<p>That&#8217;s it basically. I have documented the steps below for anyone who&#8217;s interested.</p>
<p>Cheers,<br />
Rohland</p>
<p><strong>Setup</strong></p>
<hr/>
- A. Existing web server (DNS currently points here)<br />
- B. New server (Nginx server. This server proxys requests to C, D, E which are the new web servers).</p>
<p><strong>Migration</strong></p>
<hr/>
Step 1. Update the Nginx configuration (Server B) in our new setup such that the upstream servers were set to A (not the new webservers C,D an E)<br />
Step 2. Update the DNS record to point to B.<br />
Step 3. Wait 2-3 days while DNS resolves to B.<br />
Step 4. Take your app offline and install the relevant systems on C, D and E. (presumably there is also a DB server).<br />
Step 5. Update Nginx configuration such that the upstream servers are set back to C, D, E.<br />
Step 6. Bring application back online</p>
<p><strong>Notes:</strong></p>
<hr/>
1. Parts of Step 4 could be achieved before you even start the process. With the exception of the database, the rest of the application could be deployed and tested in the new environment to minimise downtime (only the database needs to be backed up and restored in the final step).<br />
2. As described earlier, during the two to three days while your DNS update is propagating, all requests to B will be proxied to A which means the latency between server B and A will be added onto every request. This shouldn’t be a big problem depending on what the latency between your hosts are.<br />
3. If you make use of SSL, you need to setup your SSL certificate on the Nginx machine before you switch your DNS settings. I&#8217;ll probably need to cover this procedure in a separate blog post.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2010/11/20/strategy-for-migrating-web-applications-between-hosting-providers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Taking stock of my thoughts on ASP .NET and the alternatives</title>
		<link>http://www.rohland.co.za/index.php/2010/09/11/my-thoughts-on-asp-net-microsoft-and-the-alternatives/</link>
		<comments>http://www.rohland.co.za/index.php/2010/09/11/my-thoughts-on-asp-net-microsoft-and-the-alternatives/#comments</comments>
		<pubDate>Sat, 11 Sep 2010 11:59:37 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[asp dotnet]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=281</guid>
		<description><![CDATA[If you&#8217;re an ASP .NET developer (Webforms or MVC) and haven&#8217;t picked up on the recent undercurrent of negative sentiment towards the Microsoft development platform then I&#8217;m not sure where you&#8217;ve been. In any case, welcome back. To fill you in, there have been a number of developers who have raised various concerns about the [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re an <a href="http://www.asp.net/" target="_blank">ASP .NET</a> developer (Webforms or MVC) and haven&#8217;t picked up on the recent undercurrent of negative sentiment towards the Microsoft development platform then I&#8217;m not sure where you&#8217;ve been. In any case, welcome back. To fill you in, there have been a number of  <a href="http://openmymind.net/2010/8/30/How-I-would-fix-ASP-NET" target="_blank">developers</a> who have raised various concerns about the efficiency of an ASP .NET web developer, and how as a group, they compare to those developing with other languages (such as <a href="http://www.ruby-lang.org/en/" target="_blank">Ruby</a>) and frameworks (such as <a href="http://rubyonrails.org/" target="_blank">Rails</a>). I thought I would add my thoughts to the conversation. </p>
<p>I want to be as objective as possible about my thoughts so as to add value to the discussion, but I guess I need to confess that my development experience is heavily weighted to the .NET platform. Over the years I&#8217;ve developed web, mobile and desktop applications using various languages, platforms and frameworks. That said, by far, I am most proficient in C#. </p>
<p>Firstly, I think it is important to note that it is somewhat difficult to accurately compare development contexts. It&#8217;s easy to confuse platforms, frameworks and languages. I once overlooked a developer typing this into Google:</p>
<div style="padding:20px">
<div id="attachment_298" class="wp-caption aligncenter" style="width: 546px"><a href="http://www.rohland.co.za/wp-content/uploads/2010/09/jQuery_uppcase.PNG"><img src="http://www.rohland.co.za/wp-content/uploads/2010/09/jQuery_uppcase.PNG" alt="Say what?" title="Someone was confused" width="536" height="105" class="size-full wp-image-298" /></a><p class="wp-caption-text">Huh?</p></div>
</div>
<p>What makes <a href="http://rubyonrails.org/" target="_blank">Ruby on Rails</a> so popular? Can we attribute its success to the language (Ruby) or the framework (Rails) or both? Some people may say that what makes developing using Rails so awesome is Ruby itself. Others may say it&#8217;s the framework, in which case the same developers could be as efficient on other similar frameworks such as <a href="http://cakephp.org/" target="_blank">CakePHP</a>. If I had to venture a guess, I think that most experienced developers would go with option 3. It&#8217;s the entire ecosystem that makes Ruby and Rails so popular, as much as it&#8217;s the .NET ecosystem that makes ASP .NET a popular option as well. This makes it difficult to compare aspects of each.</p>
<p>I have never had the opportunity to develop an application using Ruby on Rails but I think I have enough experience on various other web platforms to raise the following point. No single language or framework defines a developer, especially a web developer. Right now, most of the applications I develop are web applications and this means I need to be fairly proficient at a number of languages, not just C# ( HTML/XHTML, CSS, JavaScript and SQL to name a few). When it comes to assessing efficiency of developing on a platform, we need to address all of these aspects. Sure, Rails addresses the SQL aspect (Active Record) right off the bat, but how does a Rails developer approach HTML, CSS and JavaScript development? As web developers, we spend a lot time in our server side language of choice, developing code to dynamically output HTML. That said, a lot of time is also spent on the client side as well &#8211; designing, developing and debugging JavaScript. How does the Rails environment stack up in this department? <a href="http://www.clyral.com" target="_blank">We</a> make use of <a href="" target="_blank">Spark</a> as our view engine on MVC projects, and I guess Rails developers use something as slick (or better?). I&#8217;m not saying Visual Studio offers a better story for developers, I&#8217;m just interested to hear more about the Rails context. From a server side perspective, what is the debugging experience like in Rails? I&#8217;ve used Eclipse and a few other popular IDE&#8217;s and I&#8217;m yet to find one that matches Visual Studio&#8217;s debugging capabilities. Within a minute, a developer can write some code, set a breakpoint and have the breakpoint hit within seconds. No drama. The real point I am trying to make is that there is far more to just the server side language, or the framework that impacts on the efficiency of a developer in the web context. There are a lot of other factors which include the IDE, view engine and development web server.</p>
<p>I mentioned earlier that I haven&#8217;t ever had the opportunity to develop a Ruby on Rails application. That said, I have started learning Ruby and have recently developed an application that routinely synchronises our <a href="http://basecamphq.com/" target="_blank">Basecamp</a> data with a local SQL Server database. I specifically wanted to learn Ruby out of the Rails context first. I was delighted that within a relatively short amount of time I had some functional code. It bodes well for my continued personal investment in Ruby. I took a crack at developing my Ruby application using NetBeans on Windows. While I enjoyed developing the code (and learning more about <a href="http://en.wikipedia.org/wiki/Why's_(poignant)_Guide_to_Ruby" target="_blank">chunky bacon</a>), I really didn&#8217;t enjoy the environment. Debugging was a pain in the ass and I resorted to debugging by logging. I hate this approach. I&#8217;m not sure if my experience is unique, and would really appreciate feedback from seasoned Ruby/Rails developers on this.</p>
<p>One of the topics that constantly repeats itself in these types of conversations is that .NET developers are <a href="http://john-sheehan.com/blog/thoughts-inspired-by-ruby/" target="_blank">stuck</a>. They aren&#8217;t good at venturing out of their comfort zone and learning about new languages on other platforms. While this is a gross generalisation, I fear that the recent converts to Ruby from C# are right (for the most part). I think familiarity plays a key role in this and the problem does not only apply to developers using .NET. In the book <a href="http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X" target="_blank">The Pragmatic Programmer</a>, Hunt and Thomas recommend that a developer should strive to learn a new language every year. I must say that when I read this, I was astounded. Every year? Thats crazy! Then I realised that not only is it possible, but they are right. You see, developing on a single platform using the same language and framework, year in and year out has some advantages, but in general, your solutions to problems tend to take the general form of your environment. My recent foray into Ruby has proved this. Your mind becomes boxed into approaching problems in a single way where there may be another number of better solutions that expose themselves wonderfully when you are forced into a different pattern of programming. All in all, I would say that even though I haven&#8217;t been using Ruby for long, I&#8217;m a better C# developer for it. Note, that I am not suggesting that Ruby itself was the reason, you could replace Ruby with Python in the paragraph above and I believe the same would hold true.</p>
<p>When it comes to comparing .NET (and Microsoft solutions generally) to alternative free and open source solutions, cost and licensing are often cited as reasons to migrate away from the Microsoft platform. This seems to be an important part of the discussion. The argument that always seems to be tossed around is that as a startup, you don&#8217;t want to have sink your limited cash into technologies when the alternatives are free. I think this argument is flawed for a few reasons. If you have no experience using the alternative language, framework and platform then the comparison between cost only makes sense if your time is free. Lets face it, in the startup world, your time is not free. Whether being first to market is important or the fact that you only have a small window of opportunity where you can sustain yourself in the back of your garage, you will want to focus on getting your application deployed as soon as possible. Having to sit and learn something new and foreign when you should be focusing on building your app seems to be a weird approach to me, especially considering the factors described above. Even if you could get up to speed with the new language/framework/platform relatively quickly, once you have your application up and running for the world to see and use, you will have no experience dealing with runtime operational issues that usually crop up as people start using your app. Even when you have experience on certain platform, dealing with edge case operational issues can be tricky. In an ideal world, time wouldn&#8217;t be a factor. You could perform a systematic analysis on all languages, frameworks and platforms and assess the pros and cons of each. Unfortunately, I doubt anyone has the luxury of doing this.</p>
<p>So given that it makes sense to build your app using technologies familiar to you, what are you in for? Microsoft haters will most certainly start quoting licensing costs for SQL Server Enterprise Edition, Windows Server Enterprise Edition and how the costs will sink you in a month (or less). Again, I think one needs to look at licensing objectively. I just deployed an environment with 4 servers.</p>
<ul>
<li>1 x load balancer running Nginx on Ubuntu</li>
<li>2 x web servers running Windows Server 2008 Web Edition</li>
<li>1 x database server running Windows Server 2008 Web Edition and SQL Server 2008 Web Edition</li>
</ul>
<p><a href="http://www.rohland.co.za/wp-content/uploads/2010/09/Load_Balancing.png"><img src="http://www.rohland.co.za/wp-content/uploads/2010/09/Load_Balancing.png" alt="Hosting environment" title="Hosting environment" width="600" height="230" class="aligncenter size-full wp-image-322" /></a></p>
<p>In terms of costing for bandwidth, hardware, offsite backup etc., the licensing costs associated with the Microsoft operating systems and servers accounted for just 6% of the monthly cost. I would hardly call that prohibitive. Sure, if I had to use the Enterprise (or even Standard edition) versions of the software, the costs increase quite dramatically. That said, I don&#8217;t see why a web startup would require these versions. In any event, if you want to compare apples with apples, then one should consider that the enterprise version of MySQL is <a href="http://www.mysql.com/products/enterprise/features.html" target="_blank">not free</a>. At this point, <a href="http://en.wikipedia.org/wiki/NoSQL" target="_blank">NoSQL</a> fans will probably be butting their heads against a wall muttering that neither SQL Server or MySQL are good options. That&#8217;s fine. Use what works. The likes of <a href="http://www.mongodb.org/" target="_blank">MongoDB</a>, <a href="http://couchdb.apache.org/" target="_blank">CouchDB</a> and <a href="http://ravendb.net/" target="_blank">RavenDB</a> are available on the Windows platform (the latter developed in C# exclusively for the platform).</p>
<p>What about Visual Studio? Isn&#8217;t it quite expensive? Well, unfortunately, yes it is. That said, I think the one thing people don&#8217;t mention when discussing the cost of Visual Studio is what you are actually paying for. Have a look <a href="http://www.microsoft.com/visualstudio/en-us/products" target="_blank">here</a>. The Professional Edition with MSDN Essntials ($799) unlocks the following software for you:</p>
<ul>
<li>Visual Studio 2010 Professional</li>
<li>Windows 7 *</li>
<li>Windows Server 2008 *</li>
<li>SQL Server 2008 *</li>
</ul>
<p>* Per-user license allows <strong>unlimited installations</strong> and use for designing, developing, testing, and demonstrating applications.</p>
<p>So for essentially $800, you should be sorted for all the development software you will need to develop, test and demonstrate your application. It&#8217;s not free, but the deal isn&#8217;t too bad either.</p>
<p>This post is getting a bit long so I&#8217;m going to end here by saying this. While I&#8217;m a proficient C# developer, there is no reason why I should not dedicate time to learning about alternative languages, frameworks and platforms. It&#8217;s only going to make me a better developer, whether I stick to the Microsoft platform or not.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2010/09/11/my-thoughts-on-asp-net-microsoft-and-the-alternatives/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ordering pizza online &#8211; baking the code that made it happen</title>
		<link>http://www.rohland.co.za/index.php/2010/08/14/ordering-pizza-online-baking-the-code-that-made-it-happen/</link>
		<comments>http://www.rohland.co.za/index.php/2010/08/14/ordering-pizza-online-baking-the-code-that-made-it-happen/#comments</comments>
		<pubDate>Sat, 14 Aug 2010 14:13:37 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Spark]]></category>
		<category><![CDATA[Workflow 4]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=217</guid>
		<description><![CDATA[For the past 2-3 months <a href="http://www.clyral.com/web/pages/team" target="_blank">we</a> have been working hard to deliver (no pun intended) an online ordering system for Debonairs. Basically, we we were tasked to produce a <a href="http://www.debonairs.co.za" target="_blank">website</a> and <a href="http://debonairs.mobi" target="_blank">mobi site</a> which would enable Debonairs' customers to order a pizza using their favourite internet browser. The sites went live a few weeks ago and  I thought it would be useful to put together a short blog post describing the solution from a technical perspective.]]></description>
			<content:encoded><![CDATA[<p>For the past 2-3 months <a href="http://www.clyral.com/web/pages/team" target="_blank">we</a> have been working hard to deliver (no pun intended) an online ordering system for Debonairs. Basically, we we were tasked to produce a <a href="http://www.debonairs.co.za" target="_blank">website</a> and <a href="http://debonairs.mobi" target="_blank">mobi site</a> which would enable Debonairs&#8217;s customers to order a pizza using their favourite internet browser. The sites went live a few weeks ago and  I thought it would be useful to put together a short blog post describing the solution from a technical perspective.</p>
<p><a href="http://www.rohland.co.za/wp-content/uploads/2010/08/Debonairs.png"><img src="http://www.rohland.co.za/wp-content/uploads/2010/08/Debonairs.png" alt="Debonairs Pizza" title="Debonairs Pizza" width="550" height="94" class="aligncenter size-full wp-image-273" /></a></p>
<p>Both the website and mobi site were developed using Microsoft&#8217;s <a href="http://www.asp.net/mvc" target="_blank">ASP .NET MVC 2.0</a> framework with some slight modifications to the vanilla setup. We chose to use <a href="http://www.sparkviewengine.com/" target="_blank">Spark</a> as our view engine. Spark&#8217;s syntax is declarative and resembles HTML which enables us to integrate code seamlessly (i.e. our views don&#8217;t evolve into <a href="http://en.wikipedia.org/wiki/Spaghetti_code" target="_blank">spaghetti code</a>). This is not the sole advantage of using Spark, I would recommend taking a read through the <a href="http://www.sparkviewengine.com/book" target="_blank">documentation</a> to realise the more important benefits. This is not the first project we&#8217;ve integrated Spark with, and we continue to enjoy working with it. </p>
<p>In terms of client side scripting, we used <a href="http://jquery.com/" target="_blank">jQuery</a> as our JavaScript library. <a href="http://combres.codeplex.com/" target="_blank">Combres</a> (an open source project hosted on Codeplex) was implemented at the backend to ensure that resources such as JavaScript and CSS were minified and compressed before being served to a customer&#8217;s browser. Furthermore, Combres enables us to easily update our JavaScript/CSS references which ensures that the latest version of the relevant resources are always loaded.</p>
<p>For the mobi site, we stuck with MVC but ensured that the markup produced by the server was XHTML-MP compliant. Given the nature of the mobile landscape, we were required to support a large number of internet enabled devices ranging from smart phones (such as the iPhone) to the hugely popular Samsung E250. For <a href="http://www.populi.net/mobileresearcher/" target="_blank">Mobile Researcher</a> we use a library called <a href="http://deviceatlas.com/" target="_blank">Device Atlas</a> which enables us to detect the type of device accessing the site and provide information regarding key capabilities. Given our experience with the product we used the same library on the Debonair&#8217;s mobi site. Images are automatically scaled and cached for devices accessing the site which ensures the site&#8217;s look and feel remains consistent no matter what resolution the relevant device sports. In time, we may begin enchancing the site for specific devices such as iPhones and Blackberrys.</p>
<p>For persistence we chose <a href="http://www.microsoft.com/sqlserver/2008/en/us/web.aspx" target="_blank">SQL Server 2008 R2 Web Edition</a>. We have extensive experience working with both Microsoft SQL Server and MySql, however, we wanted to utilise Windows Workflow 4.0 as part of the solution and we didn&#8217;t have time to look at writing a custom MySql persistence service for the workflow engine. In any event, our selected ORM (<a href="http://www.llblgen.com" target="_blank">LLBLGEN</a>) enables us to target any number of database technologies so theoretically, we could switch over to MySql in the long term without too much work. From a code perspective, we implemented the repository pattern using <a href="http://www.rohland.co.za/index.php/2010/01/23/implementing-the-repository-pattern-with-llblgen/" target="_blank">custom LLBLGEN templates</a>. At the repository level, queries were developed using LLBLGEN&#8217;s LINQ engine.</p>
<p><a href="http://msdn.microsoft.com/en-us/netframework/aa663328.aspx" target="_blank">Windows Workflow 4.0</a> was used to handle longer running processes such as those invoked when placing an order. Once an order is validated, the order is serialised into XML and posted to a third party POS gateway which performs further validation and propagates the order down to the relevant store. There are number of failure points involved in this process hence the use of Windows Workflow. If the order is not successful (whether it reached the third party gateway or not) an SMS is sent to the relevant customer informing them of the failure. As you can imagine, there are a number of issues that could cause this to happen including network connectivity failures to the the third party gateway, connectivity problems between the stores and the gateway etc. We wrote a custom Workflow Application Manager that manages persistence and execution of Workflows which means the system is resilient against system reboots etc. </p>
<p>A Windows Service was developed to host the workflow runtime and provides the host for workflow execution. Besides order processing, the service handles menu synchronisation, store connectivity tracking and communication (email/SMS) services. To facilitate communication between the web and mobi-site, we used <a href="http://nservicebus.com/" target="_blank">NServiceBus</a> which leverages MSMQ. NServiceBus enables us to deliver messages to the Windows Service in a transactional context which is obviously critical.</p>
<p>As far as unit testing goes, we used a number of frameworks and libraries to facilitate the unit testing process. For the core testing framework, we used <a href="http://www.nunit.org/" target="_blank">NUnit</a>. For our mocking library we chose <a href="http://code.google.com/p/moq/" target="_blank">Moq</a>. Moq simplifies the mocking process considerably as it exposes a fluent API. If you haven&#8217;t heard of Moq I seriously recommend checking it out.</p>
<p>Right now both sites are humming away on IIS 7.5. There is a lot more to come with a number of key features still in development/testing, the main being the ability to pay for an order using your credit card. All in all, the<br />
implementation process has has been an exciting experience which has allowed us to leverage a number of new and useful technologies. Without resorting to butchering the idiom &#8216;the proof is in the pudding&#8217;, please think about placing your next order for a Pizza using one of the sites mentioned &#8211; we would really appreciate your feedback. </p>
<p>If you have any questions, comments or suggestions please free to give me a shout.</p>
<p>Cheers,<br />
Rohland</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2010/08/14/ordering-pizza-online-baking-the-code-that-made-it-happen/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Workflow 4.0 &#8211; Custom activities not appearing in the VS2010 toolbox</title>
		<link>http://www.rohland.co.za/index.php/2010/06/08/workflow-4-0-custom-activities-not-appearing-in-the-vs2010-toolbox/</link>
		<comments>http://www.rohland.co.za/index.php/2010/06/08/workflow-4-0-custom-activities-not-appearing-in-the-vs2010-toolbox/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 20:24:56 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[llblgen]]></category>
		<category><![CDATA[vs2010]]></category>
		<category><![CDATA[workflow4]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=207</guid>
		<description><![CDATA[I thought this particular issue warranted a blog post because it took me a good couple of hours to track down the problem. Essentially as the title suggests, my custom Workflow 4.0 activities were not appearing in the Workflow 4.0 toolbox on a few projects I am working on. If I created a new Workflow [...]]]></description>
			<content:encoded><![CDATA[<p>I thought this particular issue warranted a blog post because it took me a good couple of hours to track down the problem. Essentially as the title suggests, my custom Workflow 4.0 activities were not appearing in the Workflow 4.0 toolbox on a few projects I am working on.</p>
<p>If I created a new Workflow 4.0 project in Visual Studio 2010, everything worked as it should. However, if I integrated Workflow 4.0 with an existing project I ran into problems. After numerous Google/Bing searches I found a few examples of <a target="_blank" href="http://social.msdn.microsoft.com/Forums/en/wfprerelease/thread/178a2b83-9dc4-46ed-8275-ea6851979d7f">forum</a>/<a target="_blank" href="http://stackoverflow.com/questions/1626210/windows-workflow-4-0-activities-not-being-added-to-the-toolbox">stackoverflow</a> posts about the problem but usually in the VS2010 Beta context.</p>
<p>It tuned out that the problem in my case is that I had two projects in my solution where the project files (*.csproj) were in the same directory. VS2010 did not like that for some reason. After moving the two projects into separate folders, everything worked! Absolutely bizarre. </p>
<p>If you are interested, the reason I had two project files in a single directory was because it&#8217;s the default configuration when using <a href="http://www.llblgen.com/" target="_blank">LLBLGEN</a> (adapter mode). It generates two projects, one database specific and the other generic. It is possible to get LLBLGEN to generate the projects in separate folders, you can find the instructions <a href="http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=8871&#038;StartAtMessage=0&#49181" target="_blank">here</a>.</p>
<p>Feel free to play the <a href="http://www.sadtrombone.com/" target="_blank">sad trombone</a> if you wasted as much time as I did.</p>
<p>Cheers,<br />
Roh</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2010/06/08/workflow-4-0-custom-activities-not-appearing-in-the-vs2010-toolbox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Backup your Subversion repository offsite (Windows Guide)</title>
		<link>http://www.rohland.co.za/index.php/2010/02/01/backup-your-subversion-repository-offsite-windows-guide/</link>
		<comments>http://www.rohland.co.za/index.php/2010/02/01/backup-your-subversion-repository-offsite-windows-guide/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 17:59:34 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[offsitebackup]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=166</guid>
		<description><![CDATA[If you work in a development environment, theres a good chance you are using Subversion as your code repository of choice. If thats the case, the usual suggestion for backing up is to dump the repositories onto a DVD or external drive to be stored offsite. We have been doing this for a while and [...]]]></description>
			<content:encoded><![CDATA[<p>If you work in a development environment, theres a good chance you are using <a href="http://subversion.tigris.org/" target="_blank">Subversion</a> as your code repository of choice. If thats the case, the usual suggestion for backing up is to dump the repositories onto a DVD or external drive to be stored offsite. <a href="http://www.clyral.com" target="_blank">We</a> have been doing this for a while and have found the process painfull (to say the least!). If you run subversion and don&#8217;t have your data backed up frequently offsite, you might find yourself pushing <a href="http://www.nooooooooooooooo.com/" target="_blank">this button</a> sooner or later! </p>
<p>Near the end of last year I started looking at offsite backup options that didn&#8217;t require user intervention and was very excited to discover the <a href="http://svnbook.red-bean.com/en/1.5/svn.ref.svnsync.html" target="_blank">svnsync</a> command. The benefit of svnsync is that only new revisions are mirrored and not the full repository each time. This is absolutely critical if you have a repository that is quite active. Needless to say, I decided to forge ahead and try my hand at implementing automated scripts to take care of backing up our repositories online utilising the svnsync tool. As a reference I have posted the setup process here.</p>
<p>Its important to note that this guide assumes you are working in a Windows environment and that you have access to a server offsite. I have referenced a few articles and other blog posts I discovered along the way to help you if you are working in a Linux environment.</p>
<div style="padding-left:30px">
<p><strong>Step 1 &#8211; Setup Subversion on your remote server</strong></p>
<p>Create a Windows user account on your remote server which you will use to remotely access the backup repository from your main Subversion server. Take note of the account name and password you use. Once you have created the account, install <a href="http://www.visualsvn.com/server/download/" target="_blank">Visual SVN</a> on the server where you want to host your mirrored repositories. Ensure you select Windows Authentication on the security dialog during the installation process. Once completed, ensure that Subversion is running correctly on the remote machine by opening the VisualSVN manager and clicking on the repository address displayed. Now ensure you can access the repository from your host Subversion server. If your backup server&#8217;s name is not addressable from your host server, use the remote servers IP address or simply add an entry to your DNS server or Windows <a href="http://en.wikipedia.org/wiki/Hosts_file" target="_blank">host file</a>. If you opted for setting up a DNS entry, you should be able to ping your backup server using the server&#8217;s name. Try access the repository again. When prompted for username and password use the credentials setup for the user account you created.</p>
<p><strong>Step 2 &#8211; Configure permissions</strong></p>
<p>Before setting up the repositories etc. we need to define which users have access writes to the backup repository. To configure this, open VisualSVN manager on the remote server and right click on the Repositories folder, choose Properties from the drop down menu. Revoke all access for the BUILTIN\Users role and then add the user account you setup in Step 1. Ensure this user has full Read/Write access.</p>
<p><strong>Step 3 &#8211; Create the destination repository</strong></p>
<p>Now that you have full configured the Subversion server hosted on your remote server we can start the process of setting up the synchronisation process. To do this we need to ensure that we have a destination repository to mirror your existing repository to (if you have more than one you need to create a destination repository for each repository you want to mirror). To keep things simple, I gave the destination repository the same name as the source repository. Take note that any repository you create on the destination server should be empty (i.e. do not tick the &#8220;Create default structure&#8221; checkbox when creating the repository.</p>
<p><strong>Step 4 &#8211; Configure the repository</strong></p>
<p>The next step involves setting the Pre-revision Property Change Hook. This is an important step. Right click on the repository you created on the destination server and select All Tasks > Manage Hooks. Click on the &#8220;Pre-revision property change hook&#8221; entry and click Edit. Enter a few blank lines and click OK and Apply.</p>
<p><strong>Step 5 &#8211; Configure SSL</strong></p>
<p>We need to configure the client server to accept the SSL certificate generated by the VisualSVN installer. If you wish to use a properly signed certificate or already have one, follow this <a href="http://www.visualsvn.com/support/topic/00034/" target="_blank">guide</a> and ignore the rest of this step. If you want to continue using the auto generated certificate, follow Mark Wilson&#8217;s <a href="http://www.markwilson.co.uk/blog/2008/11/trusting-a-self-signed-certificate-in-windows.htm" target="_blank">guide</a> on how to trust the default certificate.</p>
<p><strong>Step 6 &#8211; Initialise your repositories for synchronisation</strong></p>
<p>Before you can synchronise your repository, you need to initialise it. To do this, you need to run the following command on the host server (note that you need to replace the keys in CAPS to the relevant object names):</p>
<p><font color="#377400">svnsync init PATH_TO_REMOTE_REPO PATH_TO_LOCAL_REPO &#8211;sync-username REMOTE_USERNAME  &#8211;sync-password REMOTE_PASSWORD &#8211;source-username HOST_USERNAME &#8211;source-password HOST_PASSWORD</font></p>
<p><strong>Step 7 &#8211; Initialise remote repositories from a previous backup</strong></p>
<p>Only run through this step if you have a relatively large repository and don&#8217;t want to have to mirror it (the sync process is quite slow) from revision 0 all the way to revision xxxx. If you are running through these steps for a brand new repository you want to have mirrored, ignore this step. Also, please take note that if you are using Powershell to execute all these scripts &#8220;>&#8221; is equiv to | Out-File -encoding Unicode (thanks <a href="http://twitter.com/r_keith_hill/status/8347225922" target="_blank">Keith</a>). If you don&#8217;t be careful, you might end up with the <a href="http://brianlyttle.com/2009/01/powershell-and-svnadmin/" target="_blank">Malformed dumpfile header</a> error. To be safe, use the command line interface.</p>
<p>Dump your existing repository on your host machine by running the following script: </p>
<p><font color="#377400">svnadmin dump &#8220;FILE_PATH_TO_REPO&#8221; > &#8220;REPO_NAME.db&#8221;</font></p>
<p>Once the repository dump has completed, upload it to your backup server and then run the following script on the backup/mirros server: </p>
<p><font color="#377400">svnadmin load &#8220;FILE_PATH_TO_BACKUP_REPO&#8221; < "REPO_NAME.db"</font></p>
<p>Now, the next step is critical. You need to update the last-merged-rev property on the remote repository to the existing revision number of the repository (you can get this information by running &#8220;svn info REPO_PATH&#8221;). To do this run the following script: </p>
<p><font color="#377400">svn propset svn:sync-last-merged-rev &#8211;revprop -r0 REV_NUMBER &#8220;PATH_TO_REMOTE_REPO&#8221;.</font></p>
<p><strong>Step 8 &#8211; Synchronise!</strong></p>
<p>Basically you are done, you simply need to run the following script on a frequent basis (best to setup as a scheduled task in Windows):</p>
<p><font color="#377400">svnsync sync PATH_TO_REMOTE_REPO &#8211;sync-username REMOTE_USERNAME  &#8211;sync-REMOTE_PASSWORD &#8211;source-username HOST_USERNAME &#8211;source-password HOST_PASSWORD</font></p>
</div>
<p>Hope you found this useful. I might follow this post up with another blog entry on steps I took to setup an automated script to email me when a repository on the host machine is missing its mirrored counterpart. This is really helpful to detect cases where a repository was setup locally but not configured for synchronisation, furthermore the ability to automatically generate the relevant scripts is quite useful <img src='http://www.rohland.co.za/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Rohland</p>
<p>References:<br />
<a href="http://journal.paul.querna.org/articles/2006/09/14/using-svnsync/" target="_blank">http://journal.paul.querna.org/articles/2006/09/14/using-svnsync/</a><br />
<a href="http://www.rosshawkins.net/archive/2009/04/27/using-svnsync-properwith-visualsvn.aspx" target="_blank">http://www.rosshawkins.net/archive/2009/04/27/using-svnsync-properwith-visualsvn.aspx</a><br />
<a href="http://devlicious.com/blogs/christopher_bennage/archive/2009/03/11/mirroring-subversion-from-windows.aspx" target="_blank">http://devlicious.com/blogs/christopher_bennage/archive/2009/03/11/mirroring-subversion-from-windows.aspx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2010/02/01/backup-your-subversion-repository-offsite-windows-guide/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementing the Repository Pattern with LLBLGEN</title>
		<link>http://www.rohland.co.za/index.php/2010/01/23/implementing-the-repository-pattern-with-llblgen/</link>
		<comments>http://www.rohland.co.za/index.php/2010/01/23/implementing-the-repository-pattern-with-llblgen/#comments</comments>
		<pubDate>Sat, 23 Jan 2010 12:12:23 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[llblgen]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=134</guid>
		<description><![CDATA[This post has been sitting in draft for a while but finally managed to get round to completing it. I started it back in 2009. Apologies for the delay It was the start of 2009, and I was investigating ORM tools for a new project we were working on at Clyral. We had been using [...]]]></description>
			<content:encoded><![CDATA[<p>This post has been sitting in draft for a while but finally managed to get round to completing it. I started it back in 2009. Apologies for the delay <img src='http://www.rohland.co.za/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>It was the start of 2009, and I was investigating ORM tools for a new project we were working on at <a href="http://www.clyral.com">Clyral</a>. We had been using Linq 2 SQL as our core database access layer for some time but felt we had outgrown it and were looking for something a bit more powerful and flexible. It didn&#8217;t take long for us to discover <a href="http://www.llblgen.com">LLBLGEN</a>. Whilst not the most intuitive acronym for an O/R mapping framework, LLBLGEN (Lower Level Business logic Layer Generator) impressed the team from the outset. After downloading the demo version and playing around with it on a test project we committed to purchasing it and since then haven&#8217;t looked back.</p>
<p>We started off using the Self Servicing model of the framework as it was earmarked for beginners, in time though, we began to see that we would get more mileage using the adapter model and began using this model as the defacto standard for projects. It was at this point we began looking at ways to implement the <a href="http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/10/08/the-repository-pattern.aspx">repository pattern</a> which simplifies the testing process and ensures the implementation (which is often technology specific) does not get mangled with the domain model. To achieve this we needed every entity to implement an interface (or contract if you will). The problem with this of course, is that in C# <a href="http://stackoverflow.com/questions/1864080/list-of-interfaces-vs-list-of-derived-type-cannot-convert-expression-type-to-r">generic variance is not supported</a>. This posed a bit of a problem because we still wanted the full representation of a given entity graph to be available using our defined interfaces. To get around this, we needed to update the LLBLGEN templates to allow us to inject our own custom implementation of collections which would match our interface definitions. I have provided a few example snippets to illustrate what I am talking about. Essentially we added properties which took a Todos collection (property of a TodoList entity) such as defined below:</p>
<pre class="brush: csharp; title: ; notranslate">
public virtual EntityCollection&lt;TodoEntity&gt; Todos
{
	get
	{
		if(_todos==null)
		{
			_todos = new EntityCollection&lt;TodoEntity&gt;(EntityFactoryCache2.GetEntityFactory(typeof(TodoEntityFactory)));
			_todos.SetContainingEntityInfo(this, &quot;Todolists&quot;);
		}
		return _todos;
	}
}
</pre>
<p>and added the code below to support out interface definition:</p>
<pre class="brush: csharp; title: ; notranslate">
public EntityList&lt;ITodoEntity, TodoEntity&gt;  TodosCollection
{
	get
	{
		if (_TodosCollection == null)
		{
			_TodosCollection = new EntityList&lt;ITodoEntity, TodoEntity&gt;(this.Todos);
		}
		return _TodosCollection;
	}
}

private EntityList&lt;ITodoEntity, TodoEntity&gt;  _TodosCollection;
</pre>
<p>where &#8220;EntityList&#8221; is a custom wrapper we wrote to get around the generic variance issue (note that EntityList understands that a TodoEntity is an implementation of ITodoEntity). This allowed us to define our entity contracts as such:</p>
<pre class="brush: csharp; title: ; notranslate">

    /// &lt;summary&gt;
    /// Interface for the entity 'TodoList'.
    /// &lt;/summary&gt;
	public partial interface ITodoListEntity
	{
		EntityList&lt;ITodoEntity, TodoEntity&gt;  TodosCollection {get;}		

		System.Int32 Id {get;set;}
		System.String Title {get;set;}
		System.String Description {get;set;}
		System.Int32 ProjectId {get;set;}
		System.Int16 Position {get;set;}
		System.Boolean Billable {get;set;}
		System.DateTime CreatedOn {get;set;}
		System.DateTime ModifiedOn {get;set;}
		System.String CreatedBy {get;set;}
		System.String ModifiedBy {get;set;}
		System.Guid CreatedUserId {get;set;}
		System.Guid ModifiedUserId {get;set;}
	}
</pre>
<p>As you can see, a standard was implemented where the original list&#8217;s name was simply extended with the word &#8220;Collection&#8221;. After modifying the adapter&#8217;s templates and generating our templates to create the entity contracts, everything fell into place and we had our repository pattern implemented. Our repository definitions ensured that only interfaces were passed round (of course implemented using LLBLGEN&#8217;s entities) which in turn ensured that our UI (or business logic) knew nothing about the underlying implementation. One benefit of doing this is that the chaps working on the UI never had to deal with the copious number of properties and methods that hang off an LLBLGEN entity by default. Of course, these properties and methods are useful in some cases and can still be used within the repository itself.</p>
<p>I have attached a zip file to this post with the implementation of the EntityList class as well as the templates that we modified and added to make this all happen. Let me know what you think, any comments or suggestions regarding the implementation are certainly welcome!</p>
<p>Rohland</p>
<p><a href="http://www.rohland.co.za/wp-content/uploads/2010/01/LLBLGEN-Customisations.zip">Templates and supporting files</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2010/01/23/implementing-the-repository-pattern-with-llblgen/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>C# HTML Diff Algorithm</title>
		<link>http://www.rohland.co.za/index.php/2009/10/31/csharp-html-diff-algorithm/</link>
		<comments>http://www.rohland.co.za/index.php/2009/10/31/csharp-html-diff-algorithm/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 08:44:25 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[codeplex]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[html]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=81</guid>
		<description><![CDATA[I have finally launched by my first Codeplex project, very exciting :) I was inspired by <a href="http://writeboard.com">writeboard.com</a> to find some way of implementing an HTML difference viewer in an internal application I was developing. Essentially, I was looking for a way to take two blocks of HTML and compare them in a way that highlights what the differences are. This is extremely useful for CMS type systems where WYSIWYG/Textile/Wiki markup is used to populate content. In most web systems where content is authored dynamically, a history of the content is tracked over time. When collaborating with a few people, this feature is critically important. What makes it extremely useful is the capability to detect what has changed between versions. This post focuses on a project I have launched to do exactly that - track the difference between two versions of HTML markup.]]></description>
			<content:encoded><![CDATA[<p>I have finally launched my first <a href="http://htmldiff.codeplex.com" title="C# Html Diff Algorithm">Codeplex project</a>, very exciting <img src='http://www.rohland.co.za/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  I was inspired by <a href="http://writeboard.com">writeboard.com</a> to find some way of implementing an HTML difference viewer in an internal application I was developing. Essentially, I was looking for a way to take two blocks of HTML and compare them in a way that highlights what the differences are. This is extremely useful for CMS type systems where WYSIWYG/Textile/Wiki markup is used to populate content. In most web systems where content is authored dynamically, a history of the content is tracked over time. When collaborating with a few people, this feature is critically important. What makes it extremely useful is the capability to detect what has changed between versions. This post focuses on a project I have launched to do exactly that &#8211; track the difference between two versions of HTML markup.</p>
<p>The application I was building was developed on ASP .NET MVC (C#) so naturally I was looking for some C# code I could use to implement the difference algorithm. In searching, I could not find any libraries that were worth implementing. I did come across one or two command line utilities but nothing spectacular. I widened my search to other languages and came across a <a href="http://github.com/myobie/htmldiff">neat implementation</a> in <a href="http://www.ruby-lang.org/en/">Ruby</a>. The algorithm was developed by <a href="http://nathanherald.com/">Nathan Herald</a> who generously made the code available to everyone via the common <a href="http://en.wikipedia.org/wiki/MIT_License">MIT license</a>.</p>
<p>So, I had the algorithm I was looking for, but I didn&#8217;t speak Ruby! This was an excellent opportunity to roll up my sleeves and learn some Ruby so I fired up my browser, downloaded the Windows <a href="http://www.ruby-lang.org/en/downloads/">one-click installer</a> and got a simple environment up and running. After toying with code for a bit, scratching my head at one or two alien Ruby constructs I got the gist of how things worked. I fired up Visual Studio, created a new project and began the process of porting the algorithm. I must admit that the process was relatively painless and I got something working in a few hours. It took about another hour or two to iron out some bugs I picked up but essentially, in a relatively short space of time, I had the C# diff library that I was originally looking for! Below is a demo of how it is used, followed by one or two screenshots demonstrating the functionality when rendered to your browser.</p>
<pre class="brush: csharp; title: ; notranslate">
            string oldText = @&quot;&lt;p&gt;This is some sample text to demonstrate the capability of the &lt;strong&gt;HTML diff tool&lt;/strong&gt;.&lt;/p&gt;
                                &lt;p&gt;It is based on the Ruby implementation found &lt;a href='http://github.com/myobie/htmldiff'&gt;here&lt;/a&gt;. Note how the link has no tooltip&lt;/p&gt;
                                &lt;table cellpadding='0' cellspacing='0'&gt;
                                &lt;tr&gt;&lt;td&gt;Some sample text&lt;/td&gt;&lt;td&gt;Some sample value&lt;/td&gt;&lt;/tr&gt;
                                &lt;tr&gt;&lt;td&gt;Data 1 (this row will be removed)&lt;/td&gt;&lt;td&gt;Data 2&lt;/td&gt;&lt;/tr&gt;
                                &lt;/table&gt;&quot;;

            string newText = @&quot;&lt;p&gt;This is some sample text to demonstrate the awesome capabilities of the &lt;strong&gt;HTML diff tool&lt;/strong&gt;.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;Extra spacing here that was not here before.
                                &lt;p&gt;It is based on the Ruby implementation found &lt;a title='Cool tooltip' href='http://github.com/myobie/htmldiff'&gt;here&lt;/a&gt;. Note how the link has a tooltip now and the HTML diff algorithm has preserved formatting.&lt;/p&gt;
                                &lt;table cellpadding='0' cellspacing='0'&gt;
                                &lt;tr&gt;&lt;td&gt;Some sample &lt;strong&gt;bold text&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Some sample value&lt;/td&gt;&lt;/tr&gt;
                                &lt;/table&gt;&quot;;

            HtmlDiff diffHelper = new HtmlDiff(oldText, newText);
            string diffOutput = diffHelper.Build();
</pre>
<p>Using the sample web application provided with the project in Codeplex, the following is rendered based on the code above:</p>
<div id="attachment_119" class="wp-caption aligncenter" style="width: 587px"><a href="http://www.rohland.co.za/wp-content/uploads/2009/10/html_diff_old_text.PNG"><img src="http://www.rohland.co.za/wp-content/uploads/2009/10/html_diff_old_text.PNG" alt="Old HTML" title="html_diff_old_text" width="577" height="212" class="size-full wp-image-119" /></a><p class="wp-caption-text">Old HTML</p></div>
<div id="attachment_122" class="wp-caption aligncenter" style="width: 583px"><a href="http://www.rohland.co.za/wp-content/uploads/2009/10/html_diff_new_text.PNG"><img src="http://www.rohland.co.za/wp-content/uploads/2009/10/html_diff_new_text.PNG" alt="Updated HTML" title="html_diff_new_text" width="573" height="275" class="size-full wp-image-122" /></a><p class="wp-caption-text">Updated HTML</p></div>
<div id="attachment_123" class="wp-caption aligncenter" style="width: 588px"><a href="http://www.rohland.co.za/wp-content/uploads/2009/10/html_diff_output_text.PNG"><img src="http://www.rohland.co.za/wp-content/uploads/2009/10/html_diff_output_text.PNG" alt="HTML diff output" title="html_diff_output_text" width="578" height="320" class="size-full wp-image-123" /></a><p class="wp-caption-text">HTML diff output</p></div>
<p>You can see that the algorithm as originally developed takes care of the nasty HTML parsing to figure out how to highlight the differences. The changes are marked up using &#8220;ins&#8221; and &#8220;del&#8221; tags. You can easily style these tags as I have done. The CSS below is responsible for rendering the differences as per the example.</p>
<pre class="brush: css; title: ; notranslate">
ins {
	background-color: #cfc;
	text-decoration: none;
}

del {
	color: #999;
	background-color:#FEC8C8;
}
</pre>
<p>I hope you find the library useful. I wish I had more time to add tests and more documentation to the Codeplex project, but for now I think the implementation is reasonably solid and easy to follow. If you spot any bugs, let me know and I&#8217;ll try and attend to them. Given that I am not responsible for the original implementation as developed in Ruby, it might be a bit tricky to solve some of the fundamental issues with the algorithm but I will certainly have a crack at it since I have quite a good understanding of how it works after porting it.</p>
<p>Link to C# implementation: <a href="http://htmldiff.codeplex.com">http://htmldiff.codeplex.com</a><br />
Link to Ruby implementation: <a href="http://github.com/myobie/htmldiff">http://github.com/myobie/htmldiff</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2009/10/31/csharp-html-diff-algorithm/feed/</wfw:commentRss>
		<slash:comments>37</slash:comments>
		</item>
		<item>
		<title>Blog Migration</title>
		<link>http://www.rohland.co.za/index.php/2009/10/11/blog-migration/</link>
		<comments>http://www.rohland.co.za/index.php/2009/10/11/blog-migration/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 17:42:04 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=58</guid>
		<description><![CDATA[In search of a bit more flexibility, I have decided to move my existing blog at dotnet.org.za to www.rohland.co.za. For lack of a better name, I ended up with the obvious pretentious default I am very grateful for the service made available via the dotnet.org.za portal. A year ago it allowed me to get up [...]]]></description>
			<content:encoded><![CDATA[<p>In search of a bit more flexibility, I have decided to move my existing blog at <a href="http://dotnet.org.za">dotnet.org.za</a> to <a href=''>www.rohland.co.za</a>. For lack of a better name, I ended up with the obvious pretentious default <img src='http://www.rohland.co.za/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>I am very grateful for the service made available via the <a href="http://dotnet.org.za">dotnet.org.za portal</a>. A year ago it allowed me to get up and running with my blog relatively quickly. To the administrators of the portal &#8211; thank you! </p>
<p>In terms of moving forward, I was not sure what the correct procedure for moving my existing blog away from <a href="http://dotnet.org.za">dotnet.org.za</a> was, so I ended up implementing a simple script to redirect to my new domain. Hopefully, I will be able to organise a mechanism whereby future posts here reflect in the dotnet.org.za main feed. If not, then I guess that is the penalty for moving my blog.</p>
<p>Hopefully you subscribe to the RSS feed available <a href='http://www.rohland.co.za/index.php/feed/'>here</a>, or at the very least, check back periodically for new content. Please let me know if spot any issues.</p>
<p>If you have landed here after clicking a link related to one of my older blog posts, simply use the search feature available in the side bar to locate the content you were originally hoping to review.</p>
<p>Cheers,<br />
Rohland</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2009/10/11/blog-migration/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

