<?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>Architester &#8211; Chris Edwards</title>
	<atom:link href="http://architester.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://architester.com/blog</link>
	<description>Design, Testing &#38; Architecture</description>
	<lastBuildDate>Wed, 01 Jun 2016 12:58:00 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>My DevOps Presentation from Keep Austin Agile 2016</title>
		<link>http://architester.com/blog/2016/05/27/my-devops-presentation-from-keep-austin-agile-2016/</link>
					<comments>http://architester.com/blog/2016/05/27/my-devops-presentation-from-keep-austin-agile-2016/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Sat, 28 May 2016 03:13:37 +0000</pubDate>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Presentations]]></category>
		<guid isPermaLink="false">http://architester.com/blog/?p=522</guid>

					<description><![CDATA[<p>Here is the video from the DevOps presentation I gave this week at the Keep Austin Agile conference. DevOps &#8211; Applying Lean &#38; Agile Principles to Operations &#38; More from Chris Edwards on Vimeo. You can get the slides here. Abstract: By now you have likely heard about DevOps. It&#8217;s quickly gaining adoption. But what [&#8230;]</p>
The post <a href="http://architester.com/blog/2016/05/27/my-devops-presentation-from-keep-austin-agile-2016/">My DevOps Presentation from Keep Austin Agile 2016</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>Here is the video from the DevOps presentation I gave this week at the Keep Austin Agile conference. </p>
<p><iframe src="https://player.vimeo.com/video/168284464" width="500" height="281" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></p>
<p><a href="https://vimeo.com/168284464">DevOps &#8211; Applying Lean &amp; Agile Principles to Operations &amp; More</a> from <a href="https://vimeo.com/chrisedwards">Chris Edwards</a> on <a href="https://vimeo.com">Vimeo</a>.</p>
<p>You can get the slides <a href='http://www.slideshare.net/ChrisEdwards357/devops-applying-lean-agile-principles-to-operations-more'>here</a>.</p>
<h3>Abstract:</h3>
<p>By now you have likely heard about DevOps. It&#8217;s quickly gaining adoption. But what is it? And why should you care? DevOps is all about creating a culture of high collaboration between development and operations with a goal of optimizing the entire software delivery pipelineâ€”from code commit to features running in production. This enables organizations to deliver value into production faster and at a lower costâ€”even enabling multiple production deployments per day. Imagine the competitive advantage gained by delivering new features in hours or days rather than weeks, months or quarters.</p>
<p>This talk will show how DevOps improves agility by optimizing the delivery pipeline. Weâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />ll look at common patterns and anti-patterns. Weâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />ll see the kind of tools needed to automate and manage the ever increasing number of servers and applications modern organizations need. Weâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />ll also discuss the benefits and costs of adopting a DevOps culture.</p>
<p>Here is a taste of some of the things we will discuss:</p>
<ul>
<li>Get ops involved up front rather than at the end, so deployment and monitoring issues are found early and rework is reduced.</li>
<li>Treat infrastructure as code so it is automated, repeatable, and under version control.</li>
<li>Ensure your development and test environments are identical to production (or as close as possible). This helps catch issues sooner rather than in production.</li>
<li>Deploy more frequently so you are dealing with a smaller batch of changes. This is easier to manage, and less likely to fail.</li>
</ul>
<p>If you struggle with deployments, or your ops team is constantly fighting fires and drowning in unplanned work, this talk is for you. Come see how DevOps can improve the agility of your organization.</p>The post <a href="http://architester.com/blog/2016/05/27/my-devops-presentation-from-keep-austin-agile-2016/">My DevOps Presentation from Keep Austin Agile 2016</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2016/05/27/my-devops-presentation-from-keep-austin-agile-2016/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Microservices Presentation from Keep Austin Agile 2015 Conference</title>
		<link>http://architester.com/blog/2015/05/11/microservices-presentation-from-keep-austin-agile-2015-conference/</link>
					<comments>http://architester.com/blog/2015/05/11/microservices-presentation-from-keep-austin-agile-2015-conference/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Mon, 11 May 2015 17:52:19 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://architester.com/blog/?p=511</guid>

					<description><![CDATA[<p>On Friday I gave this presentation on Microservices at the Keep Austin Agile 2015 conference in Austin, TX. Below you will find the video and slides as well. I presented Microservices as a solution that solves some very difficult problems, but it does so by swapping those problems of some other problems that are easier [&#8230;]</p>
The post <a href="http://architester.com/blog/2015/05/11/microservices-presentation-from-keep-austin-agile-2015-conference/">Microservices Presentation from Keep Austin Agile 2015 Conference</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>On Friday I gave this presentation on Microservices at the Keep Austin Agile 2015 conference in Austin, TX. Below you will find the video and slides as well. </p>
<p>I presented <a href="http://martinfowler.com/articles/microservices.html" target="_blank">Microservices</a> as a solution that solves some very difficult problems, but it does so by swapping those problems of some other problems that are easier to solve. To use Microservices, your organization <a href="http://martinfowler.com/bliki/MicroservicePrerequisites.html" target="_blank">has to be mature enough</a> to solve the problems Microservices introduce. <a href="http://highscalability.com/blog/2014/4/8/microservices-not-a-free-lunch.html" target="_blank">It&#8217;s not a &#8220;free lunch&#8221;</a> as Benjamin Wootten would say.  I cover several patterns and practices that help in solving these problems, as well as common anti-patterns and pitfalls that I have fallen into.</p>
<p><iframe src="https://player.vimeo.com/video/127506703" width="500" height="281" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe> </p>
<p><a href="https://vimeo.com/127506703">Microservices &#8211; Practices, Patterns &amp; Pitfalls</a> from <a href="https://vimeo.com/chrisedwards">Chris Edwards</a> on <a href="https://vimeo.com">Vimeo</a>.</p>
<ul>
<li>The full HD <a href="https://vimeo.com/chrisedwards/microservices" title="Video on Vimeo" target="_blank">video</a> is hosted on Vimeo</li>
<li><a href="http://architester.com/media/Microservices%20Slides%20-%20Chris%20Edwards.pdf" title="Slides as a PDF" target="_blank">Slides as a PDF</a> (20MB)</li>
</ul>
<p>The audio quality is pretty bad. For some reason, my laptop wasn&#8217;t set to record audio, so I had to use the audio from my back-up recorder&#8230;but it&#8217;s not that great. My apologies.</p>
<p>Here are some useful resources (that were in the presentation) to learn more on Microservices:</p>
<ul>
<li><a href="http://martinfowler.com/articles/microservices.html" target="_blank">The Microservices Article</a> By James Lewis &#038; Martin Fowler</li>
<li><a href="http://shop.oreilly.com/product/0636920033158.do" target="_blank">Building Microservices: Designing Fine Grained Systems</a> by Sam Newman &#8211; This is the most comprehensive book on the topic.</li>
<li><a href="http://12factor.net/" target="_blank">The Twelve-Factor App</a> &#8211; A set of design principles on microservice-style architecture from Heroku</li>
<li><a href="http://highscalability.com/blog/2014/4/8/microservices-not-a-free-lunch.html" target="_blank">Microservices: Not a Free Lunch</a> &#8211; Article by Benjamin Wootten about the costs of using Microservices</li>
<li><a href="https://pragprog.com/book/mnee/release-it" target="_blank">Release It!</a> by Michael T. Nygard &#8211; Great book on stability patterns to keep software running in the face of failure.</li>
</ul>The post <a href="http://architester.com/blog/2015/05/11/microservices-presentation-from-keep-austin-agile-2015-conference/">Microservices Presentation from Keep Austin Agile 2015 Conference</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2015/05/11/microservices-presentation-from-keep-austin-agile-2015-conference/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Push Your Tests Down: Part 1 &#8211; Testing Levels</title>
		<link>http://architester.com/blog/2014/04/16/push-your-tests-down-part-1-testing-levels/</link>
					<comments>http://architester.com/blog/2014/04/16/push-your-tests-down-part-1-testing-levels/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Wed, 16 Apr 2014 12:54:04 +0000</pubDate>
				<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">http://architester.com/blog/?p=504</guid>

					<description><![CDATA[<p>I this series, I want to touch on one of the biggest traps people fall into with test automation: writing too many high-level tests. I have made this painful mistake and struggled with constant test failures and spent many hours troubleshooting things that weren&#8217;t even problems in production. They were just bad (flaky) tests. I [&#8230;]</p>
The post <a href="http://architester.com/blog/2014/04/16/push-your-tests-down-part-1-testing-levels/">Push Your Tests Down: Part 1 – Testing Levels</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>I this series, I want to touch on one of the biggest traps people fall into with test automation: <em>writing too many high-level tests.</em> I have made this painful mistake and struggled with constant test failures and spent many hours troubleshooting things that weren&#8217;t even problems in production. They were just bad (flaky) tests. I finally found my way out of that mess, and hopefully I can help you do the same.</p>
<p>For the beginners here, I&#8217;ll start with what levels you can write tests at and why lower level tests are more valuable. I&#8217;ll show you why testing through the UI layer is so painful, and how to push higher level tests down.</p>
<p>I&#8217;ll try to keep each post short and to the point. Without further ado, here is part 1.</p>
<h2>Levels of Testing</h2>
<p>There many different ways to test your code, but they can all be boiled down into three main categories or levels.</p>
<p><em>FYI: The names of the levels may differ based on who you are talking to, but the underlying concepts are the same. Seems no one can agree on what the best names are for these things.</em></p>
<h3>Unit Tests</h3>
<p>Unit tests are the lowest level tests. These tests are very focused and usually only test a few lines of code. They run completely in-memory and never access external resources like disk or network so they are very fast. Because of this, you can run them often and get very fast feedback on errors. I run mine every few minutes. When they fail, I can usually just hit CTRL-Z to undo my last few changes and they are passing again. No need to debug!</p>
<p>Even when they fail later (when I can&#8217;t just hit CTRL-Z), the problem is usually obvious. There&#8217;s only a few lines of code it tests, so I don&#8217;t have to look far for the problem. For the same reason, there&#8217;s only a few things that could actually cause the test to fail, so they don&#8217;t fail that often.</p>
<p>Unit Tests are very low cost. Easy to write. Easy to maintain.</p>
<h3>Integration Tests</h3>
<p>Integration tests validate the interactions of multiple classes with each other, and the environment (like the disk, network, databases, etc.). These tests are inherently slower than unit tests, so you can&#8217;t run them as often. This means it may take longer before you realize you introduced an error.</p>
<p>Plus, since they cover much more code, there are more reasons these tests can fail, so they tend to fail more often than unit tests. And when they do, sifting through more code means it takes longer to figure out where the problem is.</p>
<p>Integration tests take more effort to build and maintain than unit tests. They are harder to debug, and take longer to identify issues.</p>
<h3>UI or End-to-End Tests</h3>
<p>These tests are sometimes called &#8220;functional&#8221; tests as well. They test the fully deployed system as a black box, just like a user would use it. These usually interact directly with the UI.</p>
<p>These tests exercise all the code in the system, from the UI down to the database. It also exercises all the third party resources or external systems as well. So if anything in this chain breaks, the test will fail. And when they fail, because so many things can cause it to fail, it&#8217;s often very hard to determine what caused the failure. I often find myself sifting through log files and logging in to remote servers to figure out what the heck broke. Not fun.</p>
<p>These tests are also the slowest to run, so they aren&#8217;t run very often at all. So when you introduce an error, it may be a long time before you realize it. By then you have moved on to something else so it takes additional effort to get your head back around the problem so you can debug it.</p>
<p>These tests are brittle, and very difficult to maintain. They have the highest cost of all the types of tests you can write. They do have value, but it comes with a cost.</p>
<h2>The Obvious Conclusion</h2>
<p>So, given what you just read, where is the most valuable place to focus your testing efforts? Yeah, I don&#8217;t even need to give you the answer. It&#8217;s pretty self-evident:</p>
<p><strong>Always test at the lowest level possible.</strong></p>
<p>When you have tests at a high level, it&#8217;s best to &#8220;push them down&#8221; as far as you can. That&#8217;s what this series is all about.</p>
<p>So, take a look at your tests. Where have you focused all your efforts? Are you fighting to keep the tests running? Is there any correlation between the two? If so, stay tuned, we&#8217;ll look at ways to fix this.</p>The post <a href="http://architester.com/blog/2014/04/16/push-your-tests-down-part-1-testing-levels/">Push Your Tests Down: Part 1 – Testing Levels</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2014/04/16/push-your-tests-down-part-1-testing-levels/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Effective Test Automation Presentation &#8211; Keep Austin Agile 2014</title>
		<link>http://architester.com/blog/2014/03/25/effective-test-automation-presentation-keep-austin-agile-2014/</link>
					<comments>http://architester.com/blog/2014/03/25/effective-test-automation-presentation-keep-austin-agile-2014/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Tue, 25 Mar 2014 13:52:18 +0000</pubDate>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Mocking]]></category>
		<category><![CDATA[Presentations]]></category>
		<category><![CDATA[Principles]]></category>
		<category><![CDATA[Test-Driven Development]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://chrisedwards.dreamhosters.com/blog/?p=497</guid>

					<description><![CDATA[<p>This weekend I gave a presentation at the Keep Austin Agile conference called &#8220;Effective Test Automation&#8221;. Effective Test Automation from Chris Edwards on Vimeo. Keynote file Slides as PDF Abstract Itâ€™s easy to write tests, but itâ€™s not so easy to maintain them over time. Tests should not be a drain on your productivity, they [&#8230;]</p>
The post <a href="http://architester.com/blog/2014/03/25/effective-test-automation-presentation-keep-austin-agile-2014/">Effective Test Automation Presentation – Keep Austin Agile 2014</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p><em>This weekend I gave a presentation at the Keep Austin Agile conference called &#8220;Effective Test Automation&#8221;.</em></p>
<p><iframe src="//player.vimeo.com/video/89909189" width="500" height="281" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe> </p>
<p><a href="http://vimeo.com/89909189">Effective Test Automation</a> from <a href="http://vimeo.com/chrisedwards">Chris Edwards</a> on <a href="https://vimeo.com">Vimeo</a>.</p>
<p><a href='https://chrisedwards.dreamhosters.com/media/Effective%20Test%20Automation%20-%20Chris%20Edwards.key'>Keynote file</a><br />
<a href='https://chrisedwards.dreamhosters.com/media/Effective%20Test%20Automation%20-%20Chris%20Edwards.pdf'>Slides as PDF</a></p>
<h3>Abstract</h3>
<p>Itâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s easy to write tests, but itâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s not so easy to maintain them over time. Tests should not be a drain on your productivity, they should enhance it. However, many teams struggle just to keep their tests runningâ€”sacrificing time they could be spending developing valuable new features. How can we avoid these pitfalls? What practices and principles are effective? Which ones lead to productivity drain? This talk seeks to answer those questions and more by separating the effective practices and principles from the ineffective ones.</p>
<p>Topics covered:</p>
<ul>
<li>Where should we focus testing efforts? Unit Tests, Integration Tests or UI Tests?</li>
<li>How can we best use mocks and stubs without creating fragile tests?</li>
<li>How can we instill a culture of testing?</li>
<li>How should I handle test data in our tests? </li>
<li>How can I use Fluent Data Builders and Anonymous Data to simplify testing?</li>
<li>And much more.</li>
</ul>The post <a href="http://architester.com/blog/2014/03/25/effective-test-automation-presentation-keep-austin-agile-2014/">Effective Test Automation Presentation – Keep Austin Agile 2014</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2014/03/25/effective-test-automation-presentation-keep-austin-agile-2014/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Automatically Ignoring Untrusted SSL Certificates in Firefox Using WebDriver and C#</title>
		<link>http://architester.com/blog/2012/12/18/automatically-ignoring-untrusted-ssl-certificates-in-firefox-using-webdriver-and-c/</link>
					<comments>http://architester.com/blog/2012/12/18/automatically-ignoring-untrusted-ssl-certificates-in-firefox-using-webdriver-and-c/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Tue, 18 Dec 2012 21:33:28 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Acceptance Testing]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[WebDriver]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[Selenium]]></category>
		<guid isPermaLink="false">https://chrisedwards.dreamhosters.com/blog/?p=483</guid>

					<description><![CDATA[<p>TL;DR &#8211; You can tell WebDriver to automatically ignore untrusted SSL certificates on Firefox by setting the &#8220;webdriver_assume_untrusted_issuer&#8221; preference to false in the Firefox profile. We recently ran into an issue where our tests were failing because Firefox was showing the &#8220;This Connection is Untrusted&#8221; window. Firefox was complaining that our SSL certificate was not [&#8230;]</p>
The post <a href="http://architester.com/blog/2012/12/18/automatically-ignoring-untrusted-ssl-certificates-in-firefox-using-webdriver-and-c/">Automatically Ignoring Untrusted SSL Certificates in Firefox Using WebDriver and C#</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p><strong>TL;DR &#8211; You can tell WebDriver to automatically ignore untrusted SSL certificates on Firefox by setting the &#8220;webdriver_assume_untrusted_issuer&#8221; preference to false in the Firefox profile.</strong></p>
<p>We recently ran into an issue where our tests were failing because Firefox was showing the &#8220;This Connection is Untrusted&#8221; window. Firefox was complaining that our SSL certificate was not from a trusted source (this happens when you use self-signed certs for development). Here is the screen we were seeing:</p>
<p><img loading="lazy" decoding="async" class="alignright size-medium wp-image-485" title="This Connection Is Untrusted Image" src="https://chrisedwards.dreamhosters.com/blog/wp-content/uploads/2012/12/UntrustedSSLCert-300x167.gif" alt="The &quot;This Connection Is Untrusted&quot; page Firefox was showing" width="300" height="167" srcset="http://architester.com/blog/wp-content/uploads/2012/12/UntrustedSSLCert-300x167.gif 300w, http://architester.com/blog/wp-content/uploads/2012/12/UntrustedSSLCert.gif 684w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<p>Googling the issue brought up a lot of solutions for java, but none that worked for C#. We called it a night, and the next morning, when I got in, my coworkers Jason Bilyeu and Carl Cornett had solved the issue. They found that you can set the &#8220;webdriver_assume_untrusted_issuer&#8221; preference to &#8220;false&#8221; in the Firefox profile and it will ignore the cert.</p>
<p>Here is the code:</p>
<pre style="border: 2px solid #777; padding: 5px; font-size: 10pt; font-family: Tahoma; color: #f1f2f3; background: #232323;"><span style="color:#cc7833;">var</span>&nbsp;<span style="color:#b9b9ff;">profile</span>&nbsp;<span style="color:#cc7833;">=</span>&nbsp;<span style="color:#cc7833;">new</span>&nbsp;<span style="color:#678cb1;">FirefoxProfile</span>();
<span style="color:#b9b9ff;">profile</span><span style="color:#cc7833;">.</span><span style="color:#ffc66d;">SetPreference</span>(<span style="color:#a5c261;">&quot;webdriver_assume_untrusted_issuer&quot;</span>,&nbsp;<span style="color:#cc7833;">false</span>);
<span style="color:#cc7833;">return</span>&nbsp;<span style="color:#cc7833;">new</span>&nbsp;<span style="color:#678cb1;">FirefoxDriver</span>(&nbsp;<span style="color:#b9b9ff;">profile</span>&nbsp;);</pre>
<p>I hope this helps anyone who has had issues with this like we did.</p>The post <a href="http://architester.com/blog/2012/12/18/automatically-ignoring-untrusted-ssl-certificates-in-firefox-using-webdriver-and-c/">Automatically Ignoring Untrusted SSL Certificates in Firefox Using WebDriver and C#</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2012/12/18/automatically-ignoring-untrusted-ssl-certificates-in-firefox-using-webdriver-and-c/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Acceptance Criteria vs. Acceptance Tests: Minimize your documentation</title>
		<link>http://architester.com/blog/2012/12/02/acceptance-criteria-vs-acceptance-tests-minimize-your-documentation/</link>
					<comments>http://architester.com/blog/2012/12/02/acceptance-criteria-vs-acceptance-tests-minimize-your-documentation/#comments</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Sun, 02 Dec 2012 21:56:19 +0000</pubDate>
				<category><![CDATA[Acceptance Testing]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://chrisedwards.dreamhosters.com/blog/?p=478</guid>

					<description><![CDATA[<p>To know that a story is done, we create a set of acceptance tests (story tests) that, when they pass, we know the story is complete and functions as expected. The process we follow for defining our acceptance tests is comprised of two steps. We first come up with high level acceptance criteria. Right before, [&#8230;]</p>
The post <a href="http://architester.com/blog/2012/12/02/acceptance-criteria-vs-acceptance-tests-minimize-your-documentation/">Acceptance Criteria vs. Acceptance Tests: Minimize your documentation</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>To know that a story is done, we create a set of acceptance tests (story tests) that, when they pass, we know the story is complete and functions as expected.</p>
<p>The process we follow for defining our acceptance tests is comprised of two steps.</p>
<ol>
<li>We first come up with high level acceptance criteria.</li>
<li>Right before, or during development, we use the criteria to define the actual acceptance tests.</li>
</ol>
<p>You&#8217;ll notice that we make a distinction between Acceptance Criteria and the Acceptance Tests. Here are the definitions as I see them:</p>
<ul>
<li><strong>Acceptance Criteria</strong> is the minimal documentation that ensures a sufficient implementation of acceptance tests.</li>
<li><strong>Acceptance Tests</strong> are the detailed specification of the system&#8217;s behavior for all meaningful scenarios, used to assert its correctness.</li>
</ul>
<h3>Acceptance Criteria</h3>
<ul>
<li>Ensures the team knows when they are done</li>
<li>Ensures the team does not forget important edge cases and considerations</li>
<li>Produced through collaboration of the developers, testers and product owners (3 amigos)</li>
<li>Created prior to development, during planning phase</li>
<li>Expressed at a high level (conceptual, not detailed)</li>
<li>Expressed in whatever form works best for the teamâ€¦keep it minimal</li>
<li>Considers edge cases and failure scenarios</li>
<li>Keep it concise (minimum documentation needed by team&#8230;may be more for one team, less for another)</li>
</ul>
<p>Acceptance Criteria is the minimal amount of documentation you need to specify the expected behavior of the feature and any edge cases that need to be considered. Agile favors working software over comprehensive documentation. This is an expression of that principle. We don&#8217;t flesh out every possible example, but provide &#8220;just enough&#8221; documentation to ensure the correct tests get written. The amount of documentation necessary may vary from team to team. We use a simple bulleted list to capture edge cases and things we need to consider. If your team is distributed, you may need more documentation. Teams that are co-located with testers and product owners (like us) need less.</p>
<h3>Acceptance Tests</h3>
<ul>
<li>Defines behavior of system</li>
<li>Ensures the feature works as expected</li>
<li>Code implemented by developers and testers</li>
<li>Test definition can include product owners or customers if you are using a DSL that decouples the definition of a test from its implementation code (like with Gherkin or FitNesse)</li>
<li>Test definition can happen before development if using a DSL as mentioned above</li>
<li>Test implementation occurs during development (ideally in a test-first manner)</li>
<li>Tests are usually implemented in code, but if testing manually (hopefully only rarely), the &#8220;implementation&#8221; can be a list of steps/expectations</li>
</ul>
<p>The Acceptance Tests are the fully detailed expression of the tests&#8230;.their implementation. We use SpecFlow (which is the .NET equivalent of Cucumber). It allows us to specify Given-When-Then scenarios in the Gherkin syntax. We work with our product owners to create the actual test definitions in Gherkin, then developers pair with testers to implement them. When a test is not feasible to automate, we still develop the Gherkin and can simply follow it as a list of steps to run the test manually.</p>
</p>
<p>I have found it useful to conceptually separate the documentation of the tests (Acceptance Criteria) from the implementation (the actual Acceptance Tests). It helps me to remember not to over-specify the tests. As long as the documentation is enough to ensure sufficient tests will be implemented, I don&#8217;t need to add more detail.</p>The post <a href="http://architester.com/blog/2012/12/02/acceptance-criteria-vs-acceptance-tests-minimize-your-documentation/">Acceptance Criteria vs. Acceptance Tests: Minimize your documentation</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2012/12/02/acceptance-criteria-vs-acceptance-tests-minimize-your-documentation/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>The Effective Developer &#8211; Passion</title>
		<link>http://architester.com/blog/2012/09/09/the-effective-developer-passion/</link>
					<comments>http://architester.com/blog/2012/09/09/the-effective-developer-passion/#comments</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Sun, 09 Sep 2012 06:15:06 +0000</pubDate>
				<category><![CDATA[The Effective Developer]]></category>
		<guid isPermaLink="false">https://chrisedwards.dreamhosters.com/blog/?p=467</guid>

					<description><![CDATA[<p>This post begins a series of topics I will be posting for a book I am writing entitled &#8220;The Effective Developer&#8221;. The topics come from my Padawan to Jedi presentation I have given at the Austin Code Camp for the last two years. There seemed to be a lot of curiosity and around the topics [&#8230;]</p>
The post <a href="http://architester.com/blog/2012/09/09/the-effective-developer-passion/">The Effective Developer – Passion</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>This post begins a series of topics I will be posting for a book I am writing entitled &#8220;The Effective Developer&#8221;. The topics come from my <a href="https://chrisedwards.dreamhosters.com/blog/2011/09/15/padawan2jedi/" title="Video: Padawan to Jedi â€“ A Developer Jump-Start (my presentation at Austin Code Camp 2011)" target="_blank">Padawan to Jedi</a> presentation I have given at the Austin Code Camp for the last two years. There seemed to be a lot of curiosity and around the topics I presented, so I decided to dump that knowledge down on paper to benefit a wider audience. I hope you all find it useful.</p>
<p>I do ask one thing. If you read this, and have any feedback, please post it in the comments. I welcome any constructive criticism you may have. Is there something else I can add? Should I remove something? Please let me know&#8230; Thanks.</p>
<h3>Passion</h3>
<blockquote>
<p><em>The effective developer is passionate about his work. He loves what he does and is therefore driven to do it well.</em></p>
</blockquote>
<p>If you really want to be great at something, you have to love it. How can you be motivated to excel at something you don&#8217;t enjoy? A healthy passion provides a wellspring of motivation. It drives you to do your best, and constantly improve your best. Just think of the advantage this gives you.</p>
<p>You see, we tend to do the things we enjoy. We think about them, read about them, and practice them&#8211;because we like them; we call them hobbies. A passionate developer&#8217;s hobby is his job. Because he loves it, he is driven to do it well. As you can guess, I am passionate about software development. I love reading a good tech book or blog, writing code or writing this book. These activities sharpen my skills, but they don&#8217;t feel like work. I enjoy them and they come naturally to me. I love what I do and I do what I love. This is the biggest secret to my success.</p>
<blockquote>
<p><strong>Sidebar: A warning about passion!</strong></p>
<p>Please be aware that passion can lead to an unbalanced life. Its easy to spend too much time on something you love doing. Resist that temptation. Don&#8217;t neglect the important areas of your life, like family, friends, church, etc. These are essential for happiness, and they are far more important than work. It&#8217;s tempting to believe that happiness can come from work alone. However, that kind of happiness is fleeting; it&#8217;s a lie; burnout and sadness soon take its place.</p>
<p>I will never forget what a wise friend once told me. He said, &#8220;I work to live, I don&#8217;t live to work&#8221;. This should be true for all of us.</p>
</blockquote>
<p>When I interview developers, one of the most important things I look for is passion. I will hire a passionate developer who is lacking technically. I know their passion more than compensates for their deficiencies. Because passion can have such a profound affect on the ability to learn and grow as a developer, I believe it is one of the strongest assets a developer can have.</p>The post <a href="http://architester.com/blog/2012/09/09/the-effective-developer-passion/">The Effective Developer – Passion</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2012/09/09/the-effective-developer-passion/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Want to work for an awesome company? BancVue is hiring!</title>
		<link>http://architester.com/blog/2012/07/31/want-to-work-for-an-awesome-company-bancvue-is-hiring/</link>
					<comments>http://architester.com/blog/2012/07/31/want-to-work-for-an-awesome-company-bancvue-is-hiring/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Tue, 31 Jul 2012 17:38:24 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://chrisedwards.dreamhosters.com/blog/?p=450</guid>

					<description><![CDATA[<p>We are hiring here at BancVue. We are looking for experienced C# developers and automated testers. Are you passionate about software development? Are you a continuous learner? Are you excited about projects that challenge and stretch your skills? Do you want to work at a place that takes Agile seriously? Do you live, eat and [&#8230;]</p>
The post <a href="http://architester.com/blog/2012/07/31/want-to-work-for-an-awesome-company-bancvue-is-hiring/">Want to work for an awesome company? BancVue is hiring!</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p><a href="http://bancvue.com"><img loading="lazy" decoding="async" src="https://chrisedwards.dreamhosters.com/blog/wp-content/uploads/2012/07/BancVueLogo.gif" alt="BancVue Logo" title="BancVue" width="261" height="80" class="alignleft size-full wp-image-451" /></a></p>
<p>We are hiring here at <a href="http://bancvue.com" title="BancVue Homepage" target="_blank">BancVue</a>. We are looking for experienced C# developers and automated testers.</p>
<p>Are you passionate about software development? Are you a continuous learner? Are you excited about projects that challenge and stretch your skills? Do you want to work at a place that takes Agile seriously? Do you live, eat and breathe TDD, BDD, CI, CD, etc? Then this is the place for you, and we want you here.</p>
<p>We have multiple software engineer positions for both intermediate and senior developers. Some of these positions are for technical team leads. We are also looking for automation engineers to design automated tests and test infrastructure. All positions are technical coding positions.</p>
<p>To get an idea what type of development we are doing, here is a list of some technologies we are using:</p>
<ul>
<li>C#</li>
<li>MongoDB</li>
<li>SQL Server</li>
<li>RabbitMQ</li>
<li>Selenium WebDriver (and Grid)</li>
<li>SpecFlow</li>
<li>TeamCity</li>
<li>Octopus Deploy</li>
</ul>
<p>This is a great place to work, and the culture is the best I have seen anywhere. If you are interested in joining us here at BancVue, or just want to know more about the opportunities, contact me via email at ChrisEdwards357 (at) gmail.com.</p>
<p>You can see a detailed listing of the opening job positions we have available at our <a href="http://www.bancvue.com/about/careers.html" title="BancVue Careers" target="_blank">Careers Page</a>.</p>The post <a href="http://architester.com/blog/2012/07/31/want-to-work-for-an-awesome-company-bancvue-is-hiring/">Want to work for an awesome company? BancVue is hiring!</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2012/07/31/want-to-work-for-an-awesome-company-bancvue-is-hiring/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>My Thoughts After Switching from iPhone to Android</title>
		<link>http://architester.com/blog/2012/01/16/my-thoughts-after-switching-from-iphone-to-android/</link>
					<comments>http://architester.com/blog/2012/01/16/my-thoughts-after-switching-from-iphone-to-android/#comments</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Mon, 16 Jan 2012 06:41:34 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mobile]]></category>
		<guid isPermaLink="false">https://chrisedwards.dreamhosters.com/blog/?p=444</guid>

					<description><![CDATA[<p>Its been a month since I made the switch from iPhone to Android and I thought others might benefit from my experience. What do I miss about my iPhone? What do I love about my Android? How do they compare? First some background I have been a loyal iPhone user for the last three years [&#8230;]</p>
The post <a href="http://architester.com/blog/2012/01/16/my-thoughts-after-switching-from-iphone-to-android/">My Thoughts After Switching from iPhone to Android</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>Its been a month since I made the switch from iPhone to Android and I thought others might benefit from my experience. What do I miss about my iPhone? What do I love about my Android? How do they compare?</p>
<p><strong>First some background</strong><br />
I have been a loyal iPhone user for the last three years (3GS). I also love Apple products and use a MacBook for my personal laptop even though I am primarily a Windows developer. I made the switch to Android because I wanted a bigger screen and wanted to see what an open platform had to offer. I am active in open source software development, so Android seemed to fit my personality. All that being said, I don&#8217;t feel that I am biased toward one platform or the other.</p>
<p>The Android phone I switched to is the Samsung Galaxy Nexus running Ice Cream Sandwich (Android 4.0).</p>
<p><strong>What do I miss about my iPhone?</strong><br />
To be honest, if I had written this article only two weeks in to using my new Android, I would have said I wanted to go back to the iPhone. However, at this point (one month in), I can confidently say I am sold on Android. It took me a while to get comfortable (and overcome my co-dependence on iTunes), but I an over the hump and there&#8217;s no turning back. However there are a few things I do miss about my iPhone.</p>
<p><em>Touch free voice dialing</em><br />
When voice dialing on the iPhone I never needed to look at, or touch the phone screen. Even when I had multiple numbers for the contact I was calling, it simply asked me which one I wanted to call and I could respond with my voice and it would call the correct number. It was all totally hands-free.</p>
<p>The Android is a completely different experience. I have to turn on the screen to find the voice button and push it. Then I can say &#8220;call &lt;name&gt;&#8221;. Then, I have to look at the screen again to confirm it found the right contact and select the number to call. I have to do this even if there is only one number for that contact. It&#8217;s very clumsy, and dangerous when driving. Luckily, I seldom make calls while driving.</p>
<p><em>Stability</em><br />
I have rebooted my Android phone more times in the last month than I did my iPhone in the entire three years I owned it. Granted, I got the Galaxy Nexus phone the day it was released, and it is the first phone to run Ice Cream Sandwich (the latest version of android OS&#8211;a major version release), so it makes sense that stability would be somewhat of an issue. However, even when iOS 5 was first released (also a major version release), I didn&#8217;t experience this level of difficulty. The stability has been getting better lately. Its really not that big of a problem&#8230;more of an annoyance, but I am curious to see what the future holds.</p>
<p><em>App selection</em><br />
Android&#8217;s app selection is quite good. There are just a few apps I had for the iPhone that are missing in the Android market. The iPhone appears to get development priority in the mobile app space. This is odd given that Android has a considerably larger market share. Apparently the cultures are quite different. iPhone users are far more willing to spend money in the app store than Android users. So currently, the iPhone presents a better ROI, so it gets implemented first. Hopefully this will change as the Android platform continues to mature. There has been a dramatic increase in both the quantity and quality of Android apps in the market in the last year&#8211;a trend I expect to continue.</p>
<p><strong>What do I love about Android?</strong><br />
<em>Diversity of hardware options</em><br />
There are only a handful of iPhone models, which limits your options as a consumer. However, this limitation it comes with the added benefit of increased stability. Since there is a very limited set of hardware to support, Apple can guarantee that apps will run smoothly on all the current iPhone models.</p>
<p>Android, on the other hand, is an open platform that runs on a very diverse range of hardware. There are many models made by many manufacturers. This presents a diverse number of options to the consumer, but at the cost of stability. It simply isn&#8217;t feasible to test every app against every known hardware configuration. </p>
<p>But because the platform is open, and any manufacturer may enter the market (unlike Apple, which is the sole designer and manufacturer), there are more designers and manufacturers driving innovation in the hardware. As a consumer, this means you have more options to choose from: large phones, small phones, phones with 3D screens, phones with external memory cards, phones with HDMI outputs, etc. etc.</p>
<p><em>Customizable user experience</em><br />
I really like the ability to customize and tweak my phone to work exactly how I want it to. For example, I am using a custom keyboard called SlideIT. Rather than typing each letter one at a time, I just slide over the letters to form words. It is much faster than conventional typing. I just showed it to my wife and she loved it and asked me to install it on her phone. &#8220;Sorry sweetie, your iPhone doesn&#8217;t allow custom keyboards.&#8221; I had to tell her.</p>
<p>The customizable nature of Android goes far beyond just keyboards. Its baked in to the OS&#8211;part of it&#8217;s very philosophy. Almost anything can be customized or tweaked. And if it can&#8217;t, you can always open the source code and change it yourself.</p>
<p><em>Better app integration</em><br />
Android makes app integration much easier. The iPhone requires the developers of the app to explicitly integrate with one another. For instance, if you want to use files from your DropBox or other third party app on the iPhone, you must find an app where the developer explicitly wrote in support for DropBox. If they didn&#8217;t, the app wont integrate. On Android, any app can access your DropBox because it can just look at its files via the file system. The iPhone does not expose its file system to the user in the name of simplicity.</p>
<p>As another example, if you are want to integrate with your favorite Twitter app you can simply install it and any app that supports sharing will be able to share over your Twitter app natively. Integration on Android is an OS-supported concern, its not left up to the app developers to decide what apps to integrate with. Its based on what apps you have installed and what actions they can support. This allows for much greater flexibility and lets apps integrate with one another easily by decoupling them inherently in the OS.</p>
<p><em>I prefer Java over ObjectiveC</em><br />
Yes, yes, I realize my aversion to ObjectiveC is somewhat subjective. To me, ObjectiveC feels like an antiquated language. It just doesn&#8217;t feel natural. It has a much steeper learning curve for the average developer than Java. I imagine this is a non-issue once you learn the language. But it presents a high cost of entry that many are unwilling to pay. I admit that being a C# developer does give me a certain bias towards Java since they are so similar.</p>
<p><em>Freedom</em><br />
Apple is very restrictive in what apps they allow in the app store. It is commonplace for an app to be pulled from the app store if it allows you to do something Apple thinks you shouldn&#8217;t be able to do. This type of thing never happens in the Android market.</p>
<p>While I consider Apple&#8217;s tight-fisted control over their app store as a disadvantage, I must admit that it does result in higher quality apps on the app store. They have much higher standards for an app to be accepted into the app store, and reject apps that don&#8217;t meet them. </p>
<p><strong>In conclusion</strong><br />
I think it all boils down to the type if user you are. If you are a power user who likes to tweak and hack, then android is right for you. If you value stability and simplicity and don&#8217;t mind being restricted in what you are allowed to do, then you will love the iPhone. To each his own.</p>The post <a href="http://architester.com/blog/2012/01/16/my-thoughts-after-switching-from-iphone-to-android/">My Thoughts After Switching from iPhone to Android</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2012/01/16/my-thoughts-after-switching-from-iphone-to-android/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Error loading .NET 4.0 assembly in TeamCity using MSpec</title>
		<link>http://architester.com/blog/2011/12/07/error-loading-net-4-0-assembly-in-teamcity-using-mspec/</link>
					<comments>http://architester.com/blog/2011/12/07/error-loading-net-4-0-assembly-in-teamcity-using-mspec/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Wed, 07 Dec 2011 19:38:02 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[MSpec]]></category>
		<category><![CDATA[TeamCity]]></category>
		<guid isPermaLink="false">https://chrisedwards.dreamhosters.com/blog/?p=438</guid>

					<description><![CDATA[<p>When we migrated our tests from NUnit to MSpec (Machine.Specifications), we encountered the following error: Could not load file or assembly 'file:///C:\BuildAgent\work\c7e220bd4bfc29dc\bin\dependencies\SomeProject.dll' or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded. After some Googling, I realized that the default MSpec runner (MSpec.exe) [&#8230;]</p>
The post <a href="http://architester.com/blog/2011/12/07/error-loading-net-4-0-assembly-in-teamcity-using-mspec/">Error loading .NET 4.0 assembly in TeamCity using MSpec</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>When we migrated our tests from NUnit to <a href="https://github.com/machine/machine.specifications" title="Machine.Specifications on GitHub" target="_blank">MSpec (Machine.Specifications)</a>, we encountered the following error:</p>
<p><code>Could not load file or assembly 'file:///C:\BuildAgent\work\c7e220bd4bfc29dc\bin\dependencies\SomeProject.dll' or one of its dependencies. <b>This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.</b></code></p>
<p>After some Googling, I realized that the default MSpec runner (<code>MSpec.exe</code>) was not built using .NET 4.0. Because our assembly (SomeProject.dll in the error above) was a .NET 4.0 assembly, we were getting this error.</p>
<p>The fix was to use the <code>mspec-clr4.exe<code> executable as the test runner instead. This exe is shipped with newer versions of MSpec (we're on Machine.Specifications version 0.5). The clr4 version of the runner is built on .NET 4.0 and works perfectly.</p>
<p>To do this in TeamCity, simply add the full path to the exe in the "Path to MSpec.exe" field in TeamCity's MSpec build step. Even though the field label says it is expecting <code>MSpec.exe</code>, if you give it a path to <code>mspec-clr4.exe</code>, it will use it.</p>The post <a href="http://architester.com/blog/2011/12/07/error-loading-net-4-0-assembly-in-teamcity-using-mspec/">Error loading .NET 4.0 assembly in TeamCity using MSpec</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2011/12/07/error-loading-net-4-0-assembly-in-teamcity-using-mspec/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Upgrading Java for Firefox on 64-bit Windows</title>
		<link>http://architester.com/blog/2011/11/07/upgrading-java-for-firefox-on-64-bit-windows/</link>
					<comments>http://architester.com/blog/2011/11/07/upgrading-java-for-firefox-on-64-bit-windows/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Mon, 07 Nov 2011 15:12:33 +0000</pubDate>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[64-bit]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Windows]]></category>
		<guid isPermaLink="false">https://chrisedwards.dreamhosters.com/blog/?p=420</guid>

					<description><![CDATA[<p>If you are on a 64-bit Windows machine and are getting a notification that your Java plugin version is out of date in Firefox even after installing the latest version, you need to install the 32-bit version of Java. Firefox runs as a 32-bit application on Windows, so it uses the 32-bit version of Java. [&#8230;]</p>
The post <a href="http://architester.com/blog/2011/11/07/upgrading-java-for-firefox-on-64-bit-windows/">Upgrading Java for Firefox on 64-bit Windows</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>If you are on a 64-bit Windows machine and are getting a notification that your Java plugin version is out of date in Firefox even after installing the latest version, you need to install the 32-bit version of Java.</p>
<p>Firefox runs as a 32-bit application on Windows, so it uses the 32-bit version of Java. I should have read the fine print on the Java website. It tells you to install both 64 and 32-bit versions if you are on a 64-bit system, but are running a 32-bit browser. I did, and now my Java version is up to date in Firefox.</p>
<p>If you are on  a 64-bit Windows machine and run Firefox, you may want to make sure you are upgraded to the latest version of 32-bit Java. You can find out by going to the Addons Manager in Firefox, clicking the â€œPluginsâ€ tab on the left, then click the â€œCheck to see if your plugins are up to dateâ€ link at the top of the page. If Java is out of date, it will give you a red warning.</p>The post <a href="http://architester.com/blog/2011/11/07/upgrading-java-for-firefox-on-64-bit-windows/">Upgrading Java for Firefox on 64-bit Windows</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2011/11/07/upgrading-java-for-firefox-on-64-bit-windows/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>You ARE protecting your passwords in your config files AREN&#8217;T YOU?</title>
		<link>http://architester.com/blog/2011/11/01/you-are-protecting-your-passwords-in-your-config-files-arent-you/</link>
					<comments>http://architester.com/blog/2011/11/01/you-are-protecting-your-passwords-in-your-config-files-arent-you/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Tue, 01 Nov 2011 16:34:45 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Configuration]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[CSharp]]></category>
		<guid isPermaLink="false">https://chrisedwards.dreamhosters.com/blog/?p=416</guid>

					<description><![CDATA[<p>When we are writing software for our clients, we have a fiduciary responsibility to ensure the security of their site. One way to increase security is to ensure that passwords and other sensitive information are not laying around in our config files unsecured (in plain text). All too many times I have seen something like [&#8230;]</p>
The post <a href="http://architester.com/blog/2011/11/01/you-are-protecting-your-passwords-in-your-config-files-arent-you/">You ARE protecting your passwords in your config files AREN’T YOU?</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>When we are writing software for our clients, we have a <a title="Definition of fiduciary" href="http://www.learnersdictionary.com/search/fiduciary" target="_blank">fiduciary</a> responsibility to ensure the security of their site.</p>
<p>One way to increase security is to ensure that passwords and other sensitive information are not laying around in our config files unsecured (in plain text). All too many times I have seen something like the following in a config file:</p>
<p>Code Sample:</p>
<pre style="border: 2px solid #777; padding: 5px; font-size: 10pt; font-family: Tahoma; color: #f1f2f3; background: #232323;">&lt;?<span 
            style="color:#93c763;">xml</span>&nbsp;<span style="color:#678cb1;">version</span>=<span 
            style="color:#cc7833;">&quot;</span><span style="color:#ec7600;">1.0</span><span 
            style="color:#cc7833;">&quot;</span>&nbsp;<span style="color:#678cb1;">encoding</span>=<span 
            style="color:#cc7833;">&quot;</span><span style="color:#ec7600;">utf-8</span><span 
            style="color:#cc7833;">&quot;</span>&nbsp;?&gt;
&lt;<span style="color:#93c763;">configuration</span>&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;<span style="color:#93c763;">appSettings</span>&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;<span style="color:#93c763;">add</span>&nbsp;<span style="color:#678cb1;">key</span>=<span 
            style="color:#cc7833;">&quot;</span><span style="color:#ec7600;">UserName</span><span 
            style="color:#cc7833;">&quot;</span>&nbsp;<span style="color:#678cb1;">value</span>=<span 
            style="color:#cc7833;">&quot;</span><span style="color:#ec7600;">PresidentSkroob</span><span 
            style="color:#cc7833;">&quot;</span>&nbsp;/&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;<span style="color:#93c763;">add</span>&nbsp;<span style="color:#678cb1;">key</span>=<span 
            style="color:#cc7833;">&quot;</span><span style="color:#ec7600;">Password</span><span 
            style="color:#cc7833;">&quot;</span>&nbsp;<span style="color:#678cb1;">value</span>=<span 
            style="color:#cc7833;">&quot;</span><span style="color:#ec7600;">12345</span><span 
            style="color:#cc7833;">&quot;</span>&nbsp;/&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/<span style="color:#93c763;">appSettings</span>&gt;
&lt;/<span style="color:#93c763;">configuration</span>&gt;</pre>
<p>Fixing this problem is as easy as using Microsoft&#8217;s Data Protection API. Just encrypt the value by calling <code>ProtectedData.Protect()</code>. And to decrypt the value, call <code>ProtectedData.Unprotect()</code>. </p>
<p>Both methods take an entropy value (salt), and a <code>DataProtectionScope</code> value that defines the scope for which the value should be encrypted. The scope may be one of the following: <code>CurrentUser</code> &#8211; Only the current user can decrypt the value, or <code>LocalMachine</code> &#8211; The value can only be decrypted on the local machine. <code>CurrentUser</code> can be a little complicated since it may require you to impersonate users in certain cases, so I just use <code>LocalMachine</code>. This does mean that you can&#8217;t ship the config file with the values pre-encrypted because they will not be decryptable on the machine its installed on (it can only be decrypted by the machine that encrypted it). </p>
<p>The functions return a byte array, so I Base64 encode the values prior to writing them to the config file. To do this, I wrote a few extension methods. Here they are:</p>
<p>Encryption:</p>
<pre style="border: 2px solid #777; padding: 5px; font-size: 10pt; font-family: Tahoma; color: #f1f2f3; background: #232323;"><span 
            style="color: #4f4f4f; background: #272727;">///</span><span 
            style="color: #565f4b; background: #272727;">&nbsp;</span><span 
            style="color: #4f4f4f; background: #272727;">&lt;summary&gt;</span>
<span style="color: #4f4f4f; background: #272727;">///</span><span 
            style="color: #565f4b; background: #272727;">&nbsp;Converts&nbsp;a&nbsp;string&nbsp;to&nbsp;a&nbsp;protected&nbsp;value&nbsp;(encrypted&nbsp;using&nbsp;Data&nbsp;Protection&nbsp;API)</span>
<span style="color: #4f4f4f; background: #272727;">///</span><span 
            style="color: #565f4b; background: #272727;">&nbsp;</span><span 
            style="color: #4f4f4f; background: #272727;">&lt;/summary&gt;</span>
<span style="color: #4f4f4f; background: #272727;">///</span><span 
            style="color: #565f4b; background: #272727;">&nbsp;</span><span 
            style="color: #4f4f4f; background: #272727;">&lt;param&nbsp;name=</span><span 
            style="color: #57604a; background: #272727;">&quot;value&quot;</span><span 
            style="color: #4f4f4f; background: #272727;">&gt;</span><span 
            style="color: #565f4b; background: #272727;">The&nbsp;value.</span><span 
            style="color: #4f4f4f; background: #272727;">&lt;/param&gt;</span>
<span style="color: #4f4f4f; background: #272727;">///</span><span 
            style="color: #565f4b; background: #272727;">&nbsp;</span><span 
            style="color: #4f4f4f; background: #272727;">&lt;param&nbsp;name=</span><span 
            style="color: #57604a; background: #272727;">&quot;entropy&quot;</span><span 
            style="color: #4f4f4f; background: #272727;">&gt;</span><span 
            style="color: #565f4b; background: #272727;">The&nbsp;entropy.</span><span 
            style="color: #4f4f4f; background: #272727;">&lt;/param&gt;</span>
<span style="color: #4f4f4f; background: #272727;">///</span><span 
            style="color: #565f4b; background: #272727;">&nbsp;</span><span 
            style="color: #4f4f4f; background: #272727;">&lt;returns&gt;&lt;/returns&gt;</span>
<span style="color:#cc7833;">public</span>&nbsp;<span style="color:#cc7833;">static</span>&nbsp;<span 
            style="color:#cc7833;">string</span>&nbsp;<span 
            style="color: #ffc66d; background: #141e1e;">ToProtectedValue</span>(&nbsp;<span 
            style="color:#cc7833;">this</span>&nbsp;<span style="color:#cc7833;">string</span>&nbsp;<span 
            style="color:#d6cb8b;">value</span>,&nbsp;<span style="color:#cc7833;">string</span>&nbsp;<span 
            style="color:#d6cb8b;">entropy</span>&nbsp;)
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">var</span>&nbsp;<span style="color:#b9b9ff;">entropyBytes</span>&nbsp;<span 
            style="color:#cc7833;">=</span>&nbsp;Encoding<span style="color:#cc7833;">.</span><span 
            style="color:#da4939;">UTF8</span><span style="color:#cc7833;">.</span><span 
            style="color:#ffc66d;">GetBytes</span>(&nbsp;<span style="color:#d6cb8b;">entropy</span>&nbsp;);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">var</span>&nbsp;<span style="color:#b9b9ff;">valueBytes</span>&nbsp;<span 
            style="color:#cc7833;">=</span>&nbsp;Encoding<span style="color:#cc7833;">.</span><span 
            style="color:#da4939;">UTF8</span><span style="color:#cc7833;">.</span><span 
            style="color:#ffc66d;">GetBytes</span>(&nbsp;<span style="color:#d6cb8b;">value</span>&nbsp;);
 
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">var</span>&nbsp;<span style="color:#b9b9ff;">securedBytes</span>&nbsp;<span 
            style="color:#cc7833;">=</span>&nbsp;<span 
            style="color: #f3f3f3; background: #141e1e;">ProtectedData</span><span 
            style="color:#cc7833;">.</span><span style="color:#ffc66d;">Protect</span>(&nbsp;<span 
            style="color:#b9b9ff;">valueBytes</span>,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#b9b9ff;">entropyBytes</span>,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#4f87cc;">DataProtectionScope</span><span 
            style="color:#cc7833;">.</span><span 
            style="font-weight:bold;color:#6d9cbe;">LocalMachine</span>&nbsp;);
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">return</span>&nbsp;<span style="color:#b9b9ff;">securedBytes</span><span 
            style="color:#cc7833;">.</span><span 
            style="color: #ffc66d; background: #141e1e;">AsBase64</span>();
}</pre>
<p>Decryption:</p>
<pre style="border: 2px solid #777; padding: 5px; font-size: 10pt; font-family: Tahoma; color: #f1f2f3; background: #232323;"><span style="color: #4f4f4f; background: #272727;">///</span><span 
            style="color: #565f4b; background: #272727;">&nbsp;</span><span 
            style="color: #4f4f4f; background: #272727;">&lt;summary&gt;</span>
<span style="color: #4f4f4f; background: #272727;">///</span><span 
            style="color: #565f4b; background: #272727;">&nbsp;Converts&nbsp;a&nbsp;string&nbsp;to&nbsp;a&nbsp;protected&nbsp;value&nbsp;(encrypted&nbsp;using&nbsp;Data&nbsp;Protection&nbsp;API)</span>
<span style="color: #4f4f4f; background: #272727;">///</span><span 
            style="color: #565f4b; background: #272727;">&nbsp;</span><span 
            style="color: #4f4f4f; background: #272727;">&lt;/summary&gt;</span>
<span style="color: #4f4f4f; background: #272727;">///</span><span 
            style="color: #565f4b; background: #272727;">&nbsp;</span><span 
            style="color: #4f4f4f; background: #272727;">&lt;param&nbsp;name=</span><span 
            style="color: #57604a; background: #272727;">&quot;protectedString&quot;</span><span 
            style="color: #4f4f4f; background: #272727;">&gt;&lt;/param&gt;</span>
<span style="color: #4f4f4f; background: #272727;">///</span><span 
            style="color: #565f4b; background: #272727;">&nbsp;</span><span 
            style="color: #4f4f4f; background: #272727;">&lt;param&nbsp;name=</span><span 
            style="color: #57604a; background: #272727;">&quot;entropy&quot;</span><span 
            style="color: #4f4f4f; background: #272727;">&gt;</span><span 
            style="color: #565f4b; background: #272727;">The&nbsp;entropy.</span><span 
            style="color: #4f4f4f; background: #272727;">&lt;/param&gt;</span>
<span style="color: #4f4f4f; background: #272727;">///</span><span 
            style="color: #565f4b; background: #272727;">&nbsp;</span><span 
            style="color: #4f4f4f; background: #272727;">&lt;returns&gt;&lt;/returns&gt;</span>
<span style="color:#cc7833;">public</span>&nbsp;<span style="color:#cc7833;">static</span>&nbsp;<span 
            style="color:#cc7833;">string</span>&nbsp;<span 
            style="color: #ffc66d; background: #141e1e;">ToUnprotectedString</span>(&nbsp;<span 
            style="color:#cc7833;">this</span>&nbsp;<span style="color:#cc7833;">string</span>&nbsp;<span 
            style="color:#d6cb8b;">protectedString</span>,&nbsp;<span style="color:#cc7833;">string</span>&nbsp;<span 
            style="color:#d6cb8b;">entropy</span>&nbsp;)
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">var</span>&nbsp;<span style="color:#b9b9ff;">entropyBytes</span>&nbsp;<span 
            style="color:#cc7833;">=</span>&nbsp;Encoding<span style="color:#cc7833;">.</span><span 
            style="color:#da4939;">UTF8</span><span style="color:#cc7833;">.</span><span 
            style="color:#ffc66d;">GetBytes</span>(&nbsp;<span style="color:#d6cb8b;">entropy</span>&nbsp;);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">var</span>&nbsp;<span style="color:#b9b9ff;">encryptedBytes</span>&nbsp;<span 
            style="color:#cc7833;">=</span>&nbsp;<span 
            style="color: #f3f3f3; background: #141e1e;">Convert</span><span 
            style="color:#cc7833;">.</span><span style="color:#ffc66d;">FromBase64String</span>(&nbsp;<span 
            style="color:#d6cb8b;">protectedString</span>&nbsp;);
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">var</span>&nbsp;<span style="color:#b9b9ff;">decryptedBytes</span>&nbsp;<span 
            style="color:#cc7833;">=</span>&nbsp;<span 
            style="color: #f3f3f3; background: #141e1e;">ProtectedData</span><span 
            style="color:#cc7833;">.</span><span style="color:#ffc66d;">Unprotect</span>(&nbsp;<span 
            style="color:#b9b9ff;">encryptedBytes</span>,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#b9b9ff;">entropyBytes</span>,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#4f87cc;">DataProtectionScope</span><span 
            style="color:#cc7833;">.</span><span 
            style="font-weight:bold;color:#6d9cbe;">LocalMachine</span>&nbsp;);
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">return</span>&nbsp;Encoding<span style="color:#cc7833;">.</span><span 
            style="color:#da4939;">UTF8</span><span style="color:#cc7833;">.</span><span 
            style="color:#ffc66d;">GetString</span>(&nbsp;<span style="color:#b9b9ff;">decryptedBytes</span>&nbsp;);
}</pre>
<p>After encrypting these values appropriately, your config file will look like this:</p>
<pre style="border: 2px solid #777; padding: 5px; font-size: 10pt; font-family: Tahoma; color: #f1f2f3; background: #232323;">&lt;?<span 
            style="color:#93c763;">xml</span>&nbsp;<span style="color:#678cb1;">version</span>=<span 
            style="color:#cc7833;">&quot;</span><span style="color:#ec7600;">1.0</span><span 
            style="color:#cc7833;">&quot;</span>&nbsp;<span style="color:#678cb1;">encoding</span>=<span 
            style="color:#cc7833;">&quot;</span><span style="color:#ec7600;">utf-8</span><span 
            style="color:#cc7833;">&quot;</span>&nbsp;?&gt;
&lt;<span style="color:#93c763;">configuration</span>&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;<span style="color:#93c763;">appSettings</span>&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;<span style="color:#93c763;">add</span>&nbsp;<span style="color:#678cb1;">key</span>=<span 
            style="color:#cc7833;">&quot;</span><span style="color:#ec7600;">UserName</span><span 
            style="color:#cc7833;">&quot;</span>&nbsp;<span style="color:#678cb1;">value</span>=<span 
            style="color:#cc7833;">&quot;</span><span style="color:#ec7600;">ADZgAAwAAAABAAAACLYg+TEHoFh88HcfvNTg0yAAAAAASAAACgAAAAEAAAAMFLpAQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA8BdWygYhjUWaw3teJQo04AQAAAACAAAAAAXFMCeBnOURIBAl2DJoQAAAAN7+sLiIZl+x9vPjC16wcmRQAAADS4d9bdlcLF9CmKrsbgGWPM29zAQ==</span><span 
            style="color:#cc7833;">&quot;</span>&nbsp;/&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;<span style="color:#93c763;">add</span>&nbsp;<span style="color:#678cb1;">key</span>=<span 
            style="color:#cc7833;">&quot;</span><span style="color:#ec7600;">Password</span><span 
            style="color:#cc7833;">&quot;</span>&nbsp;<span style="color:#678cb1;">value</span>=<span 
            style="color:#cc7833;">&quot;</span><span style="color:#ec7600;">AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA8BdWygYhjUWaw3teJQo04AQAAAACAAAAAAADZgAAwAAAABAAAAAhfu4ghotvmXphmGWOHFfbAAAAAASAAACgAAAAEAAAAMBMv0D9/mDwktrFSVNIPcwQAAAAwg2IDL1+MOHwdx2A1cax2RQAAACZLB62COjpupN2+pW4yT8LKR5Udg==</span><span 
            style="color:#cc7833;">&quot;</span>&nbsp;/&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/<span style="color:#93c763;">appSettings</span>&gt;
&lt;/<span style="color:#93c763;">configuration</span>&gt;</pre>
<p>Now you and your clients can sleep a little better at night knowing their sensitive information is just a bit more secure. </p>The post <a href="http://architester.com/blog/2011/11/01/you-are-protecting-your-passwords-in-your-config-files-arent-you/">You ARE protecting your passwords in your config files AREN’T YOU?</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2011/11/01/you-are-protecting-your-passwords-in-your-config-files-arent-you/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Video: Padawan to Jedi &#8211; A Developer Jump-Start (my presentation at Austin Code Camp 2011)</title>
		<link>http://architester.com/blog/2011/09/15/padawan2jedi/</link>
					<comments>http://architester.com/blog/2011/09/15/padawan2jedi/#comments</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Fri, 16 Sep 2011 01:52:59 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[Continuous Learning]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Humility]]></category>
		<category><![CDATA[Leading]]></category>
		<category><![CDATA[Mocking]]></category>
		<category><![CDATA[Patterns]]></category>
		<category><![CDATA[Presentations]]></category>
		<category><![CDATA[Principles]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Simplicity]]></category>
		<category><![CDATA[Soft Skills]]></category>
		<category><![CDATA[Test-Driven Development]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[Utilities]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/?p=404</guid>

					<description><![CDATA[<p>Here is the video of my &#8220;Padawan to Jedi &#8211; A Developer Jump-Start&#8221; presentation I gave last week at the Austin Code Camp 2011. It touches on all the principles, patterns, practices, and such that I have learned in my many years being a developer. I designed the Padawan2Jedi talk to present knowledge in a [&#8230;]</p>
The post <a href="http://architester.com/blog/2011/09/15/padawan2jedi/">Video: Padawan to Jedi – A Developer Jump-Start (my presentation at Austin Code Camp 2011)</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>Here is the video of my &#8220;Padawan to Jedi &#8211; A Developer Jump-Start&#8221; presentation I gave last week at the Austin Code Camp 2011. It touches on all the principles, patterns, practices, and such that I have learned in my many years being a developer. I designed the Padawan2Jedi talk to present knowledge in a two-fold manner:</p>
<ol>
<li>To cover a very wide range of topics so that newcomers to the craft can gain an understanding of the full scope of modern software development practices. As such, there is not time to cover any one topic in very much detail</li>
<li>To provide links to detailed information on each topic so that anyone could dig in deeper to learn about anything presented that they wanted to begin putting into practice</li>
</ol>
<p>This second manner of presenting information required a different medium. If I wanted people to have access to all these links, I knew that I couldn&#8217;t just put links on my slides&#8230;no one would want to write them all down. And after all, we are technologists&#8230;I had to use something suitable to the audience, so I thought Twitter would be a more suitable way to convey the links during my presentation. I did some searching and found a script that would send tweets from the presenter notes as you moved through the slides of an Apple Keynote presentation. The script is called <a href="http://cogdogblog.com/2011/02/01/keynote-tweet/" title="Keynote Tweet 2" target="_blank">Keynote Tweet 2</a>. </p>
<p>So as I went through the slides, the resources were tweet(ed?) out over the #Padawan2Jedi hashtag. I really wanted them to walk away with all the links to the resources, and they did. The talk lasted 2 hours, and my screencast recording software (Camtasia) died halfway through, so if you notice a change in the audio, partway through, that is why. I also had to re-record the last half of the video of the slides, so if they aren&#8217;t perfectly in sync with the talk, that is why. (Its amazing how hard it is to anticipate when to change the slide&#8230;even when you were the one talking&#8230;)</p>
<ul>
<li><a href="https://www.chrisedwards.dreamhosters.com/media/Padawan2Jedi-ChrisEdwards-AustinCodeCamp2011.key" title="Padawan 2 Jedi - Apple Keynote Presentation File (30MB)">Padawan 2 Jedi Slides (Apple Keynote File)</a> <em>(The keynote file is 30MB because of all the Star Wars images.)</em></li>
<li><a href="https://www.chrisedwards.dreamhosters.com/media/Padawan2Jedi-Slides-ChrisEdwards-AustinCodeCamp2011.pdf" title="Padawan 2 Jedi - Slides PDF (24MB)">Padawan 2 Jedi Slides (PDF)</a></li>
</ul>
<p><iframe loading="lazy" src="http://player.vimeo.com/video/29103779?title=0&amp;byline=0&amp;portrait=0" width="400" height="300" frameborder="0" webkitAllowFullScreen allowFullScreen></iframe></p>
<p>Here is the abstract that I submitted for the talk:</p>
<blockquote><p>Are you wanting to become a better developer, but don&#8217;t know where to start? Do the terms TDD, BDD, CI, SOLID, etc. seem foreign to you? This two part presentation will cover many of the modern development practices today that every developer should know. Learn about object oriented design principles, design patterns, testing (mocking, TDD, BDD), source control, continuous integration, agile practices, plus many useful tools and techniques. That&#8217;s a lot to cover, so while some topics will be discussed in-depth, others will be touched on lightly, with resources on where to get more information. The purpose of the presentation is to give a broad overview of how modern developers work and the tools they use to be efficient and productive and provide resources so that any aspiring developer can get on the fast-track to becoming better at their craft.</p></blockquote>The post <a href="http://architester.com/blog/2011/09/15/padawan2jedi/">Video: Padawan to Jedi – A Developer Jump-Start (my presentation at Austin Code Camp 2011)</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2011/09/15/padawan2jedi/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Video: Introduction to MongoDB &#8211; Austin Code Camp 2011</title>
		<link>http://architester.com/blog/2011/09/10/video-introduction-to-mongodb-austin-code-camp-2011/</link>
					<comments>http://architester.com/blog/2011/09/10/video-introduction-to-mongodb-austin-code-camp-2011/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Sat, 10 Sep 2011 06:11:33 +0000</pubDate>
				<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[Presentations]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/?p=394</guid>

					<description><![CDATA[<p>Here is the video from my Introduction to MongoDB talk that I did today at the Austin Code Camp 2011. This is an updated presentation that includes some animations to explain the replication and sharding concepts in MongoDB. In the talk, I also cover indexing and querying of the data. I also have attached the [&#8230;]</p>
The post <a href="http://architester.com/blog/2011/09/10/video-introduction-to-mongodb-austin-code-camp-2011/">Video: Introduction to MongoDB – Austin Code Camp 2011</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>Here is the video from my Introduction to MongoDB talk that I did today at the Austin Code Camp 2011. This is an updated presentation that includes some animations to explain the replication and sharding concepts in MongoDB. In the talk, I also cover indexing and querying of the data. I also have attached the slides in Apple Keynote format if anyone is interested in seeing how I put together the animations.</p>
<p><a href="/media/Introduction%20to%20MongoDB%20-%20Austin%20Code%20Camp%202011.key">Introduction to MongoDB &#8211; Austin Code Camp 2011.key</a> (Keynote presentation file)</p>
<p><iframe loading="lazy" src="http://player.vimeo.com/video/28876748" width="540" height="405" frameborder="0" webkitAllowFullScreen allowFullScreen></iframe></p>
<p><a href="http://vimeo.com/28876748">Introduction to MongoDB (Austin Code Camp 2011)</a> from <a href="http://vimeo.com/chrisedwards">Chris Edwards</a> on <a href="http://vimeo.com">Vimeo</a>.</p>The post <a href="http://architester.com/blog/2011/09/10/video-introduction-to-mongodb-austin-code-camp-2011/">Video: Introduction to MongoDB – Austin Code Camp 2011</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2011/09/10/video-introduction-to-mongodb-austin-code-camp-2011/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>I Will Be Presenting at Austin Code Camp 2011</title>
		<link>http://architester.com/blog/2011/08/24/i-will-be-presenting-at-austin-code-camp-2011/</link>
					<comments>http://architester.com/blog/2011/08/24/i-will-be-presenting-at-austin-code-camp-2011/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Wed, 24 Aug 2011 16:07:17 +0000</pubDate>
				<category><![CDATA[Presentations]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/?p=376</guid>

					<description><![CDATA[<p>I will be giving 3 presentations at the 2011 Austin Code Camp. The first will by my Introduction to MongoDB talk that I have given several times&#8230; Introduction to MongoDB MongoDB is one of the new breed of &#8220;NoSQL&#8221; databases available as alternatives to relational databases. It is a document database that represents its data [&#8230;]</p>
The post <a href="http://architester.com/blog/2011/08/24/i-will-be-presenting-at-austin-code-camp-2011/">I Will Be Presenting at Austin Code Camp 2011</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>I will be giving 3 presentations at the <a href="http://adnug.github.com/code-camp-2011/" title="Austin Code Camp 2011 Site" target="_blank">2011 Austin Code Camp</a>. </p>
<p>The first will by my <a href="https://www.chrisedwards.dreamhosters.com/blog/2011/03/25/intro-to-mongodb-slides-and-audio-from-ctxdnug-march-2011/" title="Intro to MongoDb slides and audio from CTXDNUG, March 2011">Introduction to MongoDB</a> talk that I have given several times&#8230;
</p>
<blockquote>
<h3>Introduction to MongoDB</h3>
<p>MongoDB is one of the new breed of &#8220;NoSQL&#8221; databases available as alternatives to relational databases. It is a document database that represents its data as JSON, and thus requires no schema. It can easily scale across many machines using sharding and replication. Come get an overview this database, its scalability and redundancy features, and how to access it via C#. While MongoDB is not meant to replace all SQL databases, its good to know there is an alternative for the cases where it is the better fit.</p>
</blockquote>
<p>This is the same talk I gave at the code camp last year, however I have updated it to include a lot of new functionality released in MongoDB v1.8 and some upcoming features of v1.9. I also incorporated animations to help explain the movement of data across shards and other internal workings of Mongo. I have found animations to be invaluable to helping explain complex interactions. I feel they will add a lot to the presentation.</p>
<p>Right after my MongoDb talk (in the same room), a colleague of mine, Josh Peterson, will be presenting the open source C# LINQ provider for MongoDB that he wrote here at <a href="http://bancvue.com">BancVue</a>. The provider works with the 10gen-supported C# driver. Its some pretty cool code. If you use MongoDB with C#, it will be worth your time to check it out.</p>
<p>The other two presentations are actually a two-part series. Below is the abstract for them:</p>
<blockquote>
<h3>From Padawan To Jedi &#8212; A Developer Jump-Start</h3>
<p>Are you wanting to become a better developer, but don&#8217;t know where to start? Do the terms TDD, BDD, CI, SOLID, etc. seem foreign to you? This two part series will cover many of the software development principles, patterns &#038; practices that every developer should know. The goal is to give a broad overview of how modern developers work, and to provide resources to help any aspiring developer get on the fast-track to becoming better at their craft.</p>
<h4>Episode 1: The Theoretical Side of the Force</h4>
<p>We all know good design when we see it. But why is one design better than another? How can we consistently create code is worthy of being called great? In this episode, we will look at the theoretical side of software development and see the principles and patterns that form the foundations of good design. We&#8217;ll look at the importance of testing and learn about good test design, TDD, BDD, mocking, AAA, and more.</p>
<p><em>The goal of this talk is to give you a broad overview of design theory and testing techniques, so we will cover a lot of ground quickly.  I&#8217;ll be tweeting links to related resources and articles throughout the talk. Follow <a href="http://twitter.com/cedwards" target="_blank">@cedwards</a> or hashtag <a href="http://twitter.com/#!/search/%23Padawan2Jedi" target="_blank">#Padawan2Jedi</a> during the talk so you can dig in and learn more afterwards.</em></p>
<h4>Episode 2: The Practical Side of the Force</h4>
<p>Being a productive developer is far more than just typing in code, especially when working in a team. In this episode, we look at basics like source control, automated builds and refactoring. We&#8217;ll also touch on more advanced topics like continuous integration, IoC containers, ORMs, and application architecture. We&#8217;ll finish by discussing agile software development practices and how they enhance the software development process.</p>
<p><em>The goal of this talk is to give you a broad overview of modern practices, processes and tools, so we will cover a lot of ground quickly.  I&#8217;ll be tweeting links to related resources and articles throughout the talk. Follow <a href="http://twitter.com/cedwards" target="_blank">@cedwards</a> or hashtag <a href="http://twitter.com/#!/search/%23Padawan2Jedi" target="_blank">#Padawan2Jedi</a> during the talk so you can dig in and learn more afterwards.</em></p>
</blockquote>
<p>In this talk I will be using a new script called <a href="http://cogdogblog.com/2011/02/01/keynote-tweet/" title="Keynote Tweet" target="_blank">Keynote Tweet</a> that will automatically tweet content for each slide in a Keynote presentation. I plan to cover a broad range of topics, and can&#8217;t get into a lot of detail in the allotted time, so I wanted to make the resources available to anyone who wants more information. I think twitter is an excellent way to do this. Anyone interested can follow me , or the hashtag (as mentioned above), but I won&#8217;t be tweeting the links on the <a href="http://twitter.com/#!/search/%23Padawan2Jedi" target="_blank">#AustinCodeCamp</a> hashtag because I don&#8217;t want to flood the channel.</p>
<p>I hope to see you there!</p>
<p>-Chris</p>The post <a href="http://architester.com/blog/2011/08/24/i-will-be-presenting-at-austin-code-camp-2011/">I Will Be Presenting at Austin Code Camp 2011</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2011/08/24/i-will-be-presenting-at-austin-code-camp-2011/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Do you lead by influence or position?</title>
		<link>http://architester.com/blog/2011/06/24/do-you-lead-by-influence-or-position/</link>
					<comments>http://architester.com/blog/2011/06/24/do-you-lead-by-influence-or-position/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Fri, 24 Jun 2011 13:54:45 +0000</pubDate>
				<category><![CDATA[Leading]]></category>
		<category><![CDATA[Soft Skills]]></category>
		<category><![CDATA[Leadership]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/?p=352</guid>

					<description><![CDATA[<p>I was listening to the Manager Tools Podcast and learned there are two leadership styles: leading by influence or leading by position. Leading by Position Leading by position is when others follow you only because you are in a position of authority. &#8220;Do this&#8230;because I am your boss!&#8221; While people should follow those in a [&#8230;]</p>
The post <a href="http://architester.com/blog/2011/06/24/do-you-lead-by-influence-or-position/">Do you lead by influence or position?</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>I was listening to the <a href="http://www.manager-tools.com/">Manager Tools Podcast</a> and learned there are two leadership styles: leading by influence or leading by position.</p>
<h3>Leading by Position</h3>
<p>Leading by position is when others follow you only because you are in a position of authority. &#8220;Do this&#8230;because I am your boss!&#8221; While people should follow those in a position of leadership, if a leader is relying solely on the authority of their position to lead others, it is far from ideal.</p>
<h3>Leading by Influence</h3>
<p>Leading by influence is the ideal form of leadership. This is where others follow because you have earned their trust and you are able to exert influence over them. This form of leadership does not require any authority or position. A person can lead their peers solely by influence. </p>
<p>Have you ever heard the saying, &#8220;He&#8217;s a natural born leader?&#8221;  It is likely because of influential leadership. Those who naturally appear as leaders in a team of peers are those who lead in this way. The team trusts them and they begin to &#8220;naturally&#8221; lead even when they haven&#8217;t been officially given the title of leader.</p>
<h3>An Example</h3>
<p>The Bible gives us a great example of this type of leader in Jesus. He was God, yet the bible says, <em>&#8220;[Jesus], being in very nature God, did not consider equality with God something to be used to his own advantage; rather, he made himself nothing by taking the very nature of a servant,  being made in human likeness.&#8221; (Philippians 2:6-7)</em> Jesus gave up his &#8220;title&#8221; and led by example. He didn&#8217;t say &#8220;Obey me because I am God!&#8221; Instead he said <em>&#8220;If you love me, obey my commandments.&#8221; (John 14:15)</em></p>
<p>So, how do you lead?</p>The post <a href="http://architester.com/blog/2011/06/24/do-you-lead-by-influence-or-position/">Do you lead by influence or position?</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2011/06/24/do-you-lead-by-influence-or-position/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Catching vs. Bubbling Errors</title>
		<link>http://architester.com/blog/2011/06/13/catching-vs-bubbling-errors/</link>
					<comments>http://architester.com/blog/2011/06/13/catching-vs-bubbling-errors/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Mon, 13 Jun 2011 12:06:07 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Error Handling]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/?p=343</guid>

					<description><![CDATA[<p>When should you catch an error? When should you just bubble up an error? I was asked this question a while back and came to a rather simple answer. There are two cases when you should catch an error. In all other cases, bubble it. When the error needs to be displayed or logged, catch [&#8230;]</p>
The post <a href="http://architester.com/blog/2011/06/13/catching-vs-bubbling-errors/">Catching vs. Bubbling Errors</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>When should you catch an error? When should you just bubble up an error? I was asked this question a while back and came to a rather simple answer. There are two cases when you should catch an error. In all other cases, bubble it.</p>
<h3>When the error needs to be displayed or logged, catch it</h3>
<p>When you need to do something with the error, you should catch it. For instance, in the UI, you need to display errors to the user. Bubbling it up would mean that it would become an unhandled error, so it needs to be handled. Catch it here so you can do something graceful rather than crash the app.</p>
<h3>When you can add additional information about the error, catch it</h3>
<p>When a method can add some value to the error message that will help the end user or developer understand what is going on, do so. A good example would be if a sql statement failed, it would be useful to catch the error and add the sql that failed to the error message along with any parameters that may have caused the failure. Then throw a a new error with this message and set its InnerException property to the original error.</p>
<p><h3>Let the error bubble up in other cases</h3>
<p>I can&#8217;t think of any other reason to catch the error, so just let it on through and bubble up in any other instance.</p>
<p>-Chris</p>The post <a href="http://architester.com/blog/2011/06/13/catching-vs-bubbling-errors/">Catching vs. Bubbling Errors</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2011/06/13/catching-vs-bubbling-errors/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Questions To Ask In Retrospectives</title>
		<link>http://architester.com/blog/2011/05/09/questions-to-ask-in-retrospectives/</link>
					<comments>http://architester.com/blog/2011/05/09/questions-to-ask-in-retrospectives/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Mon, 09 May 2011 14:34:08 +0000</pubDate>
				<category><![CDATA[Agile]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/?p=327</guid>

					<description><![CDATA[<p>If you ask poor questions in your retrospectives, you will get equally poor results. To uncover the problem areas that you need to focus on, you need to ask the right questions. Here are a list of questions I have compiled over many years of retrospectives. Most of the questions here are very developer-centric, but [&#8230;]</p>
The post <a href="http://architester.com/blog/2011/05/09/questions-to-ask-in-retrospectives/">Questions To Ask In Retrospectives</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>If you ask poor questions in your retrospectives, you will get equally poor results. To uncover the problem areas that you need to focus on, you need to ask the right questions. Here are a list of questions I have compiled over many years of retrospectives.</p>
<p>Most of the questions here are very developer-centric, but some also apply to the broader picture.</p>
<h3>The Three General Questions</h3>
<p>These three questions cover most of what you want in a retrospective, but are too broad to be useful by themselves.</p>
<ul>
<li>What worked well?</li>
<li>What didn&#8217;t work so well?</li>
<li>How can we do better?</li>
</ul>
<h3>Specific Questions</h3>
<p>Here are some specific questions I have found useful. Pick the ones that are most relevant to your situation.</p>
<h4>General</h4>
<ul>
<li>What is keeping us from delivering more value?</li>
<li>Is the path blocked by unresolved obstacles?</li>
<li>Are we getting to done?</li>
<li>Are we uncovering new things every retrospective?</li>
<li>Are we managing risk effectively? (tackling high risk tasks, or avoiding?)</li>
<li>What were the biggest pain points? What was difficult?</li>
<li>What low-hanging annoyances can we remove?</li>
</ul>
<h4>Team</h4>
<ul>
<li>Are the team members happy? Tired? Grumpy?</li>
<li>Are team members really collaborating? Learning? (in general, and from one another)</li>
<li>Are we effectively utilizing the strengths of the team members?</li>
<li>Are team members taking initiative?</li>
<li>Are we respecting the team norms?</li>
</ul>
<h4>Communication</h4>
<ul>
<li>How effectively are we communicating?</li>
<li>How much time does the Product Owner spend with the team?</li>
</ul>
<h4>Environment</h4>
<ul>
<li>What in our physical space is hampering our effectiveness?</li>
</ul>
<h4>Planning/Execution</h4>
<ul>
<li>Are we faithfully tracking and discussing effort remaining?</li>
<li>Are our tasks clearly defined?</li>
<li>Were our estimates accurate? Why/Why Not? How can we do better next time?</li>
<li>Were our requirements sufficient?</li>
<li>Are the user stories too granular? too nebulous?</li>
<li>Was the workload too much or too little? (Are developers over- or under-worked? Are they energized?)</li>
<li>Are team members able to do focused work or are they pulled in too many directions?</li>
<li>Was there an appropriate amount of slack time for cleanup and improvement?</li>
</ul>
<h4>Processes &#038; Practices</h4>
<ul>
<li>Is our iteration length appropriate?</li>
<li>Should we pair program more? or less?</li>
<li>Do we have sufficient test coverage?</li>
<li>Is the quality of our code sufficient?</li>
<li>Is our code base improving or degrading? Why?</li>
<li>Are we adhering to development principles?</li>
<li>Are we appropriately utilizing automation? (If you do something more than once, try to automate)</li>
<li>Are we handling the unexpected well or reverting to our old ways?</li>
<li>Are we utilizing the tools we have effectively?</li>
<li>Are there any tools that would help us be more effective?</li>
</ul>
<h3>Resources</h3>
<p>Some of the questions and concepts were taken from the following cheatsheets by Berteig Consulting.</p>
<ul>
<li><a href="http://www.berteigconsulting.com/archives/AgileWorkCheatSheetRetrospectives.pdf">AgileWork Retrospective Cheat Sheet</a></li>
<li><a href="http://www.berteigconsulting.com/archives/AgileWorkCheatSheetProcessFacilitators.pdf">AgileWork Process Facilitator Cheat Sheet</a></li>
</ul>The post <a href="http://architester.com/blog/2011/05/09/questions-to-ask-in-retrospectives/">Questions To Ask In Retrospectives</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2011/05/09/questions-to-ask-in-retrospectives/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Paper.li &#8211; Read twitter/facebook like a daily newspaper</title>
		<link>http://architester.com/blog/2011/03/30/paper-li-read-twitterfacebook-like-a-daily-newspaper/</link>
					<comments>http://architester.com/blog/2011/03/30/paper-li-read-twitterfacebook-like-a-daily-newspaper/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Wed, 30 Mar 2011 18:52:54 +0000</pubDate>
				<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[twitter]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/?p=322</guid>

					<description><![CDATA[<p>It takes a long time to catch up when I fall behind on twitter. Not anymore. I started using Paper.li to gather all the urls that are tweeted in a day into one consolidated view that looks like a newspaper. See image. I simply navigated to http://paper.li to sign up, and entered my twitter id [&#8230;]</p>
The post <a href="http://architester.com/blog/2011/03/30/paper-li-read-twitterfacebook-like-a-daily-newspaper/">Paper.li – Read twitter/facebook like a daily newspaper</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" decoding="async" class="size-full wp-image-323 alignright" title="Paper.li_example" src="/media/Paper.li_example.gif" alt="Paper.li example image" width="400" height="483" />It takes a long time to catch up when I fall behind on twitter. Not anymore.</p>
<p>I started using <a href="http://paper.li/" target="_blank">Paper.li</a> to gather all the urls that are tweeted in a day into one consolidated view that looks like a newspaper. See image.</p>
<p>I simply navigated to <a href="http://paper.li" target="_blank">http://paper.li</a> to sign up, and entered my twitter id (no password needed) and it generated a daily summary for me! Very nice. Plus, it emails me a link to the summary for each day.</p>
<p>It has really saved me a lot of time trying to catch up on the latest links posted on my twitter feed. I highly recommend it.</p>
<p>-Chris</p>The post <a href="http://architester.com/blog/2011/03/30/paper-li-read-twitterfacebook-like-a-daily-newspaper/">Paper.li – Read twitter/facebook like a daily newspaper</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2011/03/30/paper-li-read-twitterfacebook-like-a-daily-newspaper/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Intro to MongoDb slides and audio from CTXDNUG, March 2011</title>
		<link>http://architester.com/blog/2011/03/25/intro-to-mongodb-slides-and-audio-from-ctxdnug-march-2011/</link>
					<comments>http://architester.com/blog/2011/03/25/intro-to-mongodb-slides-and-audio-from-ctxdnug-march-2011/#comments</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Fri, 25 Mar 2011 21:52:47 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[CSharp]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/?p=317</guid>

					<description><![CDATA[<p>I presented an updated version of my Introduction to MongoDb talk at the Central Texas .NET User Group back in March. I incorporated a lot of what I leaned from the MongoAustin conference. The target audience is technical people (developers) who have experience with relational databases, but have never looked at MongoDb before. It covers [&#8230;]</p>
The post <a href="http://architester.com/blog/2011/03/25/intro-to-mongodb-slides-and-audio-from-ctxdnug-march-2011/">Intro to MongoDb slides and audio from CTXDNUG, March 2011</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>I presented an updated version of my Introduction to <a href="http://mongodb.org">MongoDb</a> talk at the Central Texas .NET User Group back in March. I incorporated a lot of what I leaned from the MongoAustin conference.</p>
<p>The target audience is technical people (developers) who have experience with relational databases, but have never looked at MongoDb before. It covers all the basics but also several advanced topics like sharding and replication. I didn&#8217;t modify my slides much from the last presentation, but I did cover a lot of material not on the slides. </p>
<p>The talk lasted 2 hours. There are times in the audio where I am walking through the demo of the mongo shell, or the c# code that it may not be too easy to follow with only the audio. I apologize for that. </p>
<p>The most interesting part of the talk (in my opinion) was the replication and sharding, which is at the end (starting at about the 1h 20m mark), so if you are interested in that, you can fast forward there.</p>
<p><a href="/media/Intro to MongoDb (Chris Edwards) 2011-03-10 at CTXDNUG.mp3">MP3 Audio File</a><br />
<a href="/media/Introduction to MongoDB (2011-03-10) CTXDNUG.key">Keynote Presentation File</a></p>
<div style="width:425px" id="__ss_7453827"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/ChrisEdwards357/updated-introduction-to-mongodb" title="Updated Introduction to MongoDB">Updated Introduction to MongoDB</a></strong><object id="__sse7453827" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introductiontomongodb2011-03-10ctxdnug-110330171931-phpapp02&#038;stripped_title=updated-introduction-to-mongodb&#038;userName=ChrisEdwards357" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse7453827" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introductiontomongodb2011-03-10ctxdnug-110330171931-phpapp02&#038;stripped_title=updated-introduction-to-mongodb&#038;userName=ChrisEdwards357" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></p>
<div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/ChrisEdwards357">Chris Edwards</a>.</div>
</div>
<p>Enjoy.</p>
<p>-Chris</p>The post <a href="http://architester.com/blog/2011/03/25/intro-to-mongodb-slides-and-audio-from-ctxdnug-march-2011/">Intro to MongoDb slides and audio from CTXDNUG, March 2011</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2011/03/25/intro-to-mongodb-slides-and-audio-from-ctxdnug-march-2011/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Extension: ToPrintableString() dynamically print an object and its properties</title>
		<link>http://architester.com/blog/2011/03/21/extension-toprintablestring-dynamically-print-an-object-and-its-properties/</link>
					<comments>http://architester.com/blog/2011/03/21/extension-toprintablestring-dynamically-print-an-object-and-its-properties/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Mon, 21 Mar 2011 21:41:12 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[CSharp]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/?p=291</guid>

					<description><![CDATA[<p>Have you ever wanted to print out an object and all its property values to a log file or an error message? Have you overridden the ToString() method on all your objects to do this? If you have, you know how tedious it can be, and you will really appreciate this method. What does it [&#8230;]</p>
The post <a href="http://architester.com/blog/2011/03/21/extension-toprintablestring-dynamically-print-an-object-and-its-properties/">Extension: ToPrintableString() dynamically print an object and its properties</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>Have you ever wanted to print out an object and all its property values to a log file or an error message? Have you overridden the <code>ToString()</code> method on all your objects to do this? If you have, you know how tedious it can be, and you will really appreciate this method.</p>
<h3>What does it do?</h3>
<p>Given:</p>
<pre style="border:2px solid #777; padding: 5px; font-size: 10pt; font-family: Tahoma; color: #f1f2f3; background: #232323;"><span 
    style="color:#da4939;">obj</span>&nbsp;<span style="color:#cc7833;">=</span>&nbsp;<span 
    style="color:#cc7833;">new</span>&nbsp;TestClass();
<span style="color:#da4939;">obj</span><span style="color:#cc7833;">.</span><span 
    style="color:#da4939;">Value1</span>&nbsp;<span style="color:#cc7833;">=</span>&nbsp;<span 
    style="color:#a5c261;">&quot;abc&quot;</span>;
<span style="color:#da4939;">obj</span><span style="color:#cc7833;">.</span><span 
    style="color:#da4939;">Value2</span>&nbsp;<span style="color:#cc7833;">=</span>&nbsp;<span 
    style="color:#a5c261;">&quot;123&quot;</span>;</pre>
<p>Callling:</p>
<pre style="border:2px solid #777; padding: 5px; font-size: 10pt; font-family: Tahoma; color: #f1f2f3; background: #232323;"><span 
    style="color:#da4939;">obj</span><span style="color:#cc7833;">.</span><span 
    style="color: #ffc66d; background: #141e1e;">ToPrintableString</span>();</pre>
<p>Yeilds a string containing:</p>
<pre style="border:2px solid #777; padding: 5px; font-size: 10pt; font-family: Tahoma; color: #f1f2f3; background: #232323;"><span 
    style="color:#a5c261;">{{&nbsp;TestClass&nbsp;{&nbsp;Value1&nbsp;=&nbsp;[&nbsp;abc&nbsp;];&nbsp;Value2&nbsp;=&nbsp;[&nbsp;123&nbsp;];&nbsp;}&nbsp;}}</span></pre>
<p>This is all generated dynamically with reflection. It will print out any properties with public getters. </p>
<h3>The Code</h3>
<p>The <code>ToPrintableString()</code> method does most of the work.</p>
<pre style="border:2px solid #777; padding: 5px; font-size: 10pt; font-family: Tahoma; color: #f1f2f3; background: #232323;"><span 
    style="color:#cc7833;">public</span>&nbsp;<span style="color:#cc7833;">static</span>&nbsp;<span 
    style="color:#cc7833;">class</span>&nbsp;<span 
    style="color: #f3f3f3; background: #141e1e;">ObjectExtensions</span>
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">public</span>&nbsp;<span style="color:#cc7833;">static</span>&nbsp;<span 
    style="color:#cc7833;">string</span>&nbsp;<span 
    style="color: #ffc66d; background: #141e1e;">ToPrintableString</span><span 
    style="color:#cc7833;">&lt;</span>&nbsp;<span style="color:#b9acee;">T</span>&nbsp;<span 
    style="color:#cc7833;">&gt;</span>(&nbsp;<span style="color:#cc7833;">this</span>&nbsp;<span 
    style="color:#b9acee;">T</span>&nbsp;<span style="color:#d6cb8b;">objectToPrint</span>&nbsp;)&nbsp;<span 
    style="color:#cc7833;">where</span>&nbsp;<span style="color:#b9acee;">T</span>&nbsp;:&nbsp;<span 
    style="color:#cc7833;">class</span>
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type&nbsp;<span style="color:#b9b9ff;">type</span>&nbsp;<span 
    style="color:#cc7833;">=</span>&nbsp;<span style="color:#cc7833;">typeof</span>&nbsp;(&nbsp;<span 
    style="color:#b9acee;">T</span>&nbsp;);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">var</span>&nbsp;<span 
    style="color:#b9b9ff;">sb</span>&nbsp;<span style="color:#cc7833;">=</span>&nbsp;<span 
    style="color:#cc7833;">new</span>&nbsp;StringBuilder();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#b9b9ff;">sb</span><span style="color:#cc7833;">.</span><span 
    style="color:#ffc66d;">AppendFormat</span>(&nbsp;<span style="color:#a5c261;">&quot;{{{{&nbsp;{0}&nbsp;{{&nbsp;&quot;</span>,&nbsp;<span 
    style="color:#b9b9ff;">type</span><span style="color:#cc7833;">.</span><span 
    style="color:#da4939;">Name</span>&nbsp;);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">foreach</span>&nbsp;(&nbsp;PropertyInfo&nbsp;<span 
    style="font-weight:bold;color:#b9b9ff;">property</span>&nbsp;<span 
    style="color:#cc7833;">in</span>&nbsp;<span style="color:#b9b9ff;">type</span><span 
    style="color:#cc7833;">.</span><span 
    style="color: #ffc66d; background: #141e1e;">GetPublicGetProperties</span>()&nbsp;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#b9b9ff;">sb</span><span 
    style="color:#cc7833;">.</span><span style="color:#ffc66d;">AppendFormat</span>(&nbsp;<span 
    style="color:#a5c261;">&quot;{0}&nbsp;=&nbsp;[&nbsp;{1}&nbsp;];&nbsp;&quot;</span>,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#b9b9ff;">property</span><span 
    style="color:#cc7833;">.</span><span style="color:#da4939;">Name</span>,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#b9b9ff;">property</span><span 
    style="color:#cc7833;">.</span><span style="color:#ffc66d;">GetValue</span>(&nbsp;<span 
    style="color:#d6cb8b;">objectToPrint</span>,&nbsp;<span style="color:#cc7833;">null</span>&nbsp;)&nbsp;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#b9b9ff;">sb</span><span style="color:#cc7833;">.</span><span 
    style="color:#ffc66d;">Append</span>(&nbsp;<span style="color:#a5c261;">&quot;}&nbsp;}}&quot;</span>&nbsp;);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">return</span>&nbsp;<span 
    style="color:#b9b9ff;">sb</span><span style="color:#cc7833;">.</span><span 
    style="color:#ffc66d;">ToString</span>();
&nbsp;&nbsp;&nbsp;&nbsp;}
}</pre>
<p>The <code>GetPublicGetProperties()</code> gets the properties with public getters. This method is part of my ReflectionExtensions class. I include it here for completeness.</p>
<pre style="border: 2px solid #777; padding: 5px; font-size: 10pt; font-family: Tahoma; color: #f1f2f3; background: #232323;"><span 
    style="color:#cc7833;">public</span>&nbsp;<span style="color:#cc7833;">static</span>&nbsp;<span 
    style="color:#cc7833;">class</span>&nbsp;<span 
    style="color: #f3f3f3; background: #141e1e;">ReflectionExtensions</span>
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">public</span>&nbsp;<span style="color:#cc7833;">static</span>&nbsp;PropertyInfo[]&nbsp;<span 
    style="color: #ffc66d; background: #141e1e;">GetPublicGetProperties</span>(&nbsp;<span 
    style="color:#cc7833;">this</span>&nbsp;Type&nbsp;<span style="color:#d6cb8b;">type</span>&nbsp;)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">return</span>&nbsp;<span 
    style="color:#d6cb8b;">type</span><span style="color:#cc7833;">.</span><span 
    style="color:#ffc66d;">FindMembers</span>(&nbsp;<span style="color:#4f87cc;">MemberTypes</span><span 
    style="color:#cc7833;">.</span><span style="color:#6d9cbe;">Property</span>,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#4f87cc;">BindingFlags</span><span 
    style="color:#cc7833;">.</span><span style="color:#6d9cbe;">Public</span>&nbsp;<span 
    style="color:#cc7833;">|</span>&nbsp;<span style="color:#4f87cc;">BindingFlags</span><span 
    style="color:#cc7833;">.</span><span style="color:#6d9cbe;">Instance</span>,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&nbsp;<span style="color:#d6cb8b;">m</span>,&nbsp;<span 
    style="color:#d6cb8b;">f</span>&nbsp;)&nbsp;<span style="color:#cc7833;">=&gt;</span>&nbsp;(&nbsp;(PropertyInfo)<span 
    style="color:#d6cb8b;">m</span>&nbsp;)<span style="color:#cc7833;">.</span><span 
    style="color:#da4939;">CanRead</span>,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">null</span>&nbsp;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">.</span><span 
    style="color: #ffc66d; background: #141e1e;">Cast</span><span 
    style="color:#cc7833;">&lt;</span>&nbsp;PropertyInfo&nbsp;<span style="color:#cc7833;">&gt;</span>()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#cc7833;">.</span><span 
    style="color: #ffc66d; background: #141e1e;">ToArray</span>();
&nbsp;&nbsp;&nbsp;&nbsp;}
}</pre>
<p>This code can be found in my <a href="https://github.com/ChrisEdwards/Shiloh.Testing">Shiloh.Testing github repository</a>.</p>
<p>Enjoy!</p>
<p>-Chris</p>The post <a href="http://architester.com/blog/2011/03/21/extension-toprintablestring-dynamically-print-an-object-and-its-properties/">Extension: ToPrintableString() dynamically print an object and its properties</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2011/03/21/extension-toprintablestring-dynamically-print-an-object-and-its-properties/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>A Dynamic Equality Assertion Method in C#</title>
		<link>http://architester.com/blog/2011/01/30/a-dynamic-equality-assertion-method-in-csharp/</link>
					<comments>http://architester.com/blog/2011/01/30/a-dynamic-equality-assertion-method-in-csharp/#comments</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Mon, 31 Jan 2011 05:56:26 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[CSharp]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/?p=254</guid>

					<description><![CDATA[<p>Ever wanted to assert two objects were equal without having to manually compare their public properties one at a time? Now you can. This method asserts the equality of any two objects by comparing the values of all public, readable properties that have matching names and types. It will compare them even if the objects are different types. This may very well be the last object assertion method you will ever need!</p>
The post <a href="http://architester.com/blog/2011/01/30/a-dynamic-equality-assertion-method-in-csharp/">A Dynamic Equality Assertion Method in C#</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>Ever wanted to assert two objects were equal without having to manually compare their public properties one at a time? Now you can. This method asserts the equality of any two objects by comparing the values of all public, readable properties that have matching names and types. It will compare them even if the objects are different types. This may very well be the last object assertion method you will ever need!</p>
<h3>Usage</h3>
<p>First let&#8217;s look at how we would use the method by looking at the tests. The method is called <code>should_be_equal_to()</code>.</p>
<pre class="codeblock" style="font-size:7pt;"><span style="color: blue;">public</span>Â <span style="color: blue;">class</span>Â <span style="color: darkblue;">TestClass1</span>
{
	<span style="color: blue;">public</span>Â <span style="color: blue;">int</span>Â <span style="color: purple;">Value1</span> { <span style="color: maroon;">get</span>; <span style="color: maroon;">set</span>; }
	<span style="color: blue;">internal</span>Â <span style="color: blue;">int</span>Â <span style="color: purple;">Value2</span> { <span style="color: maroon;">get</span>; <span style="color: maroon;">set</span>; }
}

<span style="color: blue;">public</span>Â <span style="color: blue;">class</span>Â <span style="color: darkblue;">TestClass2</span>
{
	<span style="color: blue;">public</span>Â <span style="color: blue;">int</span>Â <span style="color: purple;">Value1</span> { <span style="color: maroon;">get</span>; <span style="color: maroon;">set</span>; }
}

[ <span style="color: darkblue;">TestFixture</span> ]
<span style="color: blue;">public</span>Â <span style="color: blue;">class</span>Â <span style="color: darkblue;">GlobalEqualityAssertionTests</span>
{
	[ <span style="color: darkblue;">Test</span> ]
	<span style="color: blue;">public</span>Â <span style="color: blue;">void</span>Â <span style="color: maroon;">comparing_two_identical_instances_of_the_same_class_should_pass</span>()
	{
		<span style="color: blue;">var</span> obj1 = <span style="color: blue;">new</span>Â <span style="color: darkblue;">TestClass1</span> {<span style="color: purple;">Value1</span> = 1};
		<span style="color: blue;">var</span> obj2 = <span style="color: blue;">new</span>Â <span style="color: darkblue;">TestClass1</span> {<span style="color: purple;">Value1</span> = 1};
		obj1.<span style="background: #deefef; color: darkcyan;">should_be_equal_to</span>( obj2 );
	}

	[ <span style="color: darkblue;">Test</span> ]
	<span style="color: blue;">public</span>Â <span style="color: blue;">void</span>Â <span style="color: maroon;">comparing_two_instances_of_different_classes_that_have_the_same_public_property_where_both_instances_have_the_same_value_for_that_property</span>()
	{
		<span style="color: blue;">var</span> obj1 = <span style="color: blue;">new</span>Â <span style="color: darkblue;">TestClass1</span> {<span style="color: purple;">Value1</span> = 1};
		<span style="color: blue;">var</span> obj2 = <span style="color: blue;">new</span>Â <span style="color: darkblue;">TestClass2</span> {<span style="color: purple;">Value1</span> = 1};
		obj1.<span style="background: #deefef; color: darkcyan;">should_be_equal_to</span>( obj2 );
	}

	[ <span style="color: darkblue;">Test</span> ]
	<span style="color: blue;">public</span>Â <span style="color: blue;">void</span>Â <span style="color: maroon;">comparing_two_instances_of_different_classes_that_have_the_same_public_property_where_the_values_for_that_property_differ</span>()
	{
		<span style="color: blue;">var</span> obj1 = <span style="color: blue;">new</span>Â <span style="color: darkblue;">TestClass1</span> {<span style="color: purple;">Value1</span> = 1};
		<span style="color: blue;">var</span> obj2 = <span style="color: blue;">new</span>Â <span style="color: darkblue;">TestClass2</span> {<span style="color: purple;">Value1</span> = 2};
		<span style="color: darkblue;">Assert</span>.<span style="color: maroon;">Throws</span>&lt; <span style="color: darkblue;">AssertionException</span> &gt;( () =&gt; obj1.<span style="background: #deefef; color: darkcyan;">should_be_equal_to</span>( obj2 ) );
	}

	[ <span style="color: darkblue;">Test</span> ]
	<span style="color: blue;">public</span>Â <span style="color: blue;">void</span>Â <span style="color: maroon;">comparing_two_instances_of_the_same_class_where_an_internal_property_differs_should_pass</span>()
	{
		<span style="color: blue;">var</span> obj1 = <span style="color: blue;">new</span>Â <span style="color: darkblue;">TestClass1</span> {<span style="color: purple;">Value1</span> = 1, <span style="color: purple;">Value2</span> = 1};
		<span style="color: blue;">var</span> obj2 = <span style="color: blue;">new</span>Â <span style="color: darkblue;">TestClass1</span> {<span style="color: purple;">Value1</span> = 1, <span style="color: purple;">Value2</span> = 3};
		obj1.<span style="background: #deefef; color: darkcyan;">should_be_equal_to</span>( obj2 );
	}

	[ <span style="color: darkblue;">Test</span> ]
	<span style="color: blue;">public</span>Â <span style="color: blue;">void</span>Â <span style="color: maroon;">comparing_two_instances_of_the_same_class_with_different_values_should_fail</span>()
	{
		<span style="color: blue;">var</span> obj1 = <span style="color: blue;">new</span>Â <span style="color: darkblue;">TestClass1</span> {<span style="color: purple;">Value1</span> = 1};
		<span style="color: blue;">var</span> obj2 = <span style="color: blue;">new</span>Â <span style="color: darkblue;">TestClass1</span> {<span style="color: purple;">Value1</span> = 2};
		<span style="color: darkblue;">Assert</span>.<span style="color: maroon;">Throws</span>&lt; <span style="color: darkblue;">AssertionException</span> &gt;( () =&gt; obj1.<span style="background: #deefef; color: darkcyan;">should_be_equal_to</span>( obj2 ) );
	}
}</pre>
<h3>The Code</h3>
<p>Here is the main part of the method&#8230;</p>
<pre class="codeblock" style="font-size:7pt;"><span style="color: blue;">public</span>Â <span style="color: blue;">static</span>Â <span style="color: blue;">void</span>Â <span style="background: #deefef; color: darkcyan;">should_be_equal_to</span>&lt; <span style="color: darkblue;">TActual</span>, <span style="color: darkblue;">TExpected</span> &gt;( <span style="color: blue;">this</span>Â <span style="color: darkblue;">TActual</span>Â <span style="color: teal;">actual</span>, <span style="color: darkblue;">TExpected</span>Â <span style="color: teal;">expected</span> )
{
	<span style="color: blue;">foreach</span> ( <span style="color: darkblue;">PropertyPair</span>Â <span style="font-weight: bold;">propertyPair</span>Â <span style="color: blue;">in</span>Â <span style="color: maroon;">GetPropertiesToCompare</span>( <span style="color: teal;">actual</span>, <span style="color: teal;">expected</span> ) )
	{
		<span style="color: blue;">object</span> actualValue = <span style="font-weight: bold;">propertyPair</span>.<span style="color: purple;">Actual</span>.<span style="color: maroon;">GetValue</span>( <span style="color: teal;">actual</span>, <span style="color: blue;">null</span> );
		<span style="color: blue;">object</span> expectedValue = <span style="font-weight: bold;">propertyPair</span>.<span style="color: purple;">Expected</span>.<span style="color: maroon;">GetValue</span>( <span style="color: teal;">expected</span>, <span style="color: blue;">null</span> );

		<span style="color: darkblue;">Assert</span>.<span style="color: maroon;">That</span>( actualValue, <span style="color: darkblue;">Is</span>.<span style="color: maroon;">EqualTo</span>( expectedValue ),
			<span style="color: blue;">string</span>.<span style="color: maroon;">Format</span>( <span style="color: olive;">"Expected {0} to match, but did not."</span>, <span style="font-weight: bold;">propertyPair</span>.<span style="color: purple;">Expected</span>.<span style="color: purple;">Name</span> ) );
	}
}</pre>
<p>This code loops over all the <code>PropertyPair</code>s we want to compare and compares them. If any value does not match it will fail the assertion with a meaningful error message.</p>
<p>The <code>PropertyPair</code> class is implemented as a private inner class within the assertion class.</p>
<pre class="codeblock" style="font-size:7pt;"><span style="color: blue;">private</span>Â <span style="color: blue;">class</span>Â <span style="color: darkblue;">PropertyPair</span>
{
	<span style="color: blue;">public</span>Â <span style="color: darkblue;">PropertyInfo</span>Â <span style="color: purple;">Expected</span> { <span style="color: maroon;">get</span>; <span style="color: maroon;">set</span>; }
	<span style="color: blue;">public</span>Â <span style="color: darkblue;">PropertyInfo</span>Â <span style="color: purple;">Actual</span> { <span style="color: maroon;">get</span>; <span style="color: maroon;">set</span>; }
}</pre>
<p>Lets look at the code that creates these pairs.</p>
<pre class="codeblock" style="font-size:7pt;"><span style="color: blue;">private</span>Â <span style="color: blue;">static</span>Â <span style="color: darkblue;">IEnumerable</span>&lt; <span style="color: darkblue;">PropertyPair</span> &gt; <span style="color: maroon;">GetPropertiesToCompare</span>&lt; <span style="color: darkblue;">TActual</span>, <span style="color: darkblue;">TExpected</span> &gt;( <span style="color: darkblue;">TActual</span>Â <span style="color: teal;">actual</span>, <span style="color: darkblue;">TExpected</span>Â <span style="color: teal;">expected</span> )
{
	<span style="color: blue;">return</span>
		<span style="color: blue;">from</span> exp <span style="color: blue;">in</span>Â <span style="color: maroon;">GetComparableProperties</span>( <span style="color: teal;">expected</span> )
		<span style="color: blue;">join</span> act <span style="color: blue;">in</span>Â <span style="color: maroon;">GetComparableProperties</span>( <span style="color: teal;">actual</span> )
				<span style="color: blue;">on</span>Â <span style="color: blue;">new</span> {<span style="color: teal;">exp</span>.<span style="color: purple;">Name</span>, <span style="color: teal;">exp</span>.<span style="color: purple;">PropertyType</span>}
				<span style="color: blue;">equals</span>Â <span style="color: blue;">new</span> {<span style="color: teal;">act</span>.<span style="color: purple;">Name</span>, <span style="color: teal;">act</span>.<span style="color: purple;">PropertyType</span>}
		<span style="color: blue;">select</span>Â <span style="color: blue;">new</span>Â <span style="color: darkblue;">PropertyPair</span> {<span style="color: purple;">Actual</span> = <span style="color: teal;">act</span>, <span style="color: purple;">Expected</span> = <span style="color: teal;">exp</span>};
}

<span style="color: blue;">private</span>Â <span style="color: blue;">static</span>Â <span style="color: darkblue;">IEnumerable</span>&lt; <span style="color: darkblue;">PropertyInfo</span> &gt; <span style="color: maroon;">GetComparableProperties</span>&lt; <span style="color: darkblue;">T</span> &gt;( <span style="color: darkblue;">T</span>Â <span style="color: teal;">actual</span> )
{
	<span style="color: blue;">return</span> <span style="color: maroon;">GetPublicGetProperties</span>( <span style="color: teal;">actual</span> )
					.<span style="background: #deefef; color: darkcyan;">Where</span>( <span style="color: teal;">property</span> =&gt;
							!<span style="color: teal;">property</span>.<span style="color: purple;">PropertyType</span>.<span style="color: purple;">IsClass</span> &amp;&amp;
							!<span style="color: teal;">property</span>.<span style="color: purple;">PropertyType</span>.<span style="color: purple;">IsInterface</span>
					);
}

<span style="color: blue;">private</span>Â <span style="color: blue;">static</span>Â <span style="color: darkblue;">IEnumerable</span>&lt; <span style="color: darkblue;">PropertyInfo</span> &gt; <span style="color: maroon;">GetPublicGetProperties</span>&lt; <span style="color: darkblue;">T</span> &gt;( <span style="color: darkblue;">T</span>Â <span style="color: teal;">obj</span> )
{
	<span style="color: darkblue;">Type</span> type = <span style="color: teal;">obj</span>.<span style="color: maroon;">GetType</span>();

	<span style="color: blue;">return</span> type.<span style="color: maroon;">FindMembers</span>( <span style="color: darkblue;">MemberTypes</span>.<span style="color: purple; font-weight: bold;">Property</span>,
					 <span style="color: darkblue;">BindingFlags</span>.<span style="color: purple; font-weight: bold;">Public</span> | <span style="color: darkblue;">BindingFlags</span>.<span style="color: purple; font-weight: bold;">Instance</span>,
					 ( <span style="color: teal;">m</span>, <span style="color: teal;">f</span> ) =&gt; ( (<span style="color: darkblue;">PropertyInfo</span>)<span style="color: teal;">m</span> ).<span style="color: purple;">CanRead</span>,
					 <span style="color: blue;">null</span> )
					.<span style="background: #deefef; color: darkcyan;">Cast</span>&lt; <span style="color: darkblue;">PropertyInfo</span> &gt;();
}</pre>
<p><code>GetPropertiesToCompare()</code> simply gets the comparable properties for each object type and joins them on name and type. Any properties that don&#8217;t match on name and type are ignored. Those that do match are put into a <code>PropertyPair</code> object to be returned.</p>
<p><code>GetComparableProperties()</code> calls <code>GetPublicGetProperties()</code> to get a list of public readable properties. It then throws out any reference type properties so that only value properties are left. These are the properties that get compared.</p>
<h4>Caveats</h4>
<p>Note that reference properties (properties that refer to other objects) are not compared, so even if they differ, the objects will show as equal. I have deferred this task since I still need consider how to handle references we don&#8217;t want to compare (and there are many).</p>
<h3>Where Can I Get It?</h3>
<p>This code can be found on my <a href="https://github.com/ChrisEdwards/Shiloh.Testing/tree/v0.1">Shiloh.Testing github repository</a>. The link goes to the v0.1 tag, which only has this class and its supporting classes and tests. It includes several other features that I stripped out to make this blog post simpler, like the ability to clean up values before comparing them, and an attribute you can place on properties you want to ignore when asserting equality.</p>
<p>I hope this simplifies your testing&#8230;it has definitely simplified mine.</p>
<p>-Chris</p>The post <a href="http://architester.com/blog/2011/01/30/a-dynamic-equality-assertion-method-in-csharp/">A Dynamic Equality Assertion Method in C#</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2011/01/30/a-dynamic-equality-assertion-method-in-csharp/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Slides and Audio for my Introduction to MongoDB presentation</title>
		<link>http://architester.com/blog/2010/11/10/slides-and-audio-for-my-introduction-to-mongodb-presentation/</link>
					<comments>http://architester.com/blog/2010/11/10/slides-and-audio-for-my-introduction-to-mongodb-presentation/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Wed, 10 Nov 2010 14:59:02 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[Presentations]]></category>
		<category><![CDATA[CSharp]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/?p=243</guid>

					<description><![CDATA[<p>I presented at the Austin .NET User Group this week. The topic was an &#8220;Introduction to MongoDB&#8221;. Below are the slides and the audio from the presentation. The talk covers MongoDB from the perspective of a newcomer to the technology. I relate the concepts in MongoDB to their corresponding SQL idioms&#8211;pointing out their differences and [&#8230;]</p>
The post <a href="http://architester.com/blog/2010/11/10/slides-and-audio-for-my-introduction-to-mongodb-presentation/">Slides and Audio for my Introduction to MongoDB presentation</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>I presented at the Austin .NET User Group this week. The topic was an &#8220;Introduction to MongoDB&#8221;. Below are the slides and the audio from the presentation.</p>
<p>The talk covers MongoDB from the perspective of a newcomer to the technology. I relate the concepts in MongoDB to their corresponding SQL idioms&#8211;pointing out their differences and likenesses. The talk covers much of the functionality and capabilities of MongoDB, from the simple to the complex (queries, indexes, sharding, replication, installation, etc.). A lot of questions that are asked push deeper into the internals, many of which I answer, but several I defer with a simple &#8220;I don&#8217;t know&#8221;.</p>
<p>The talk went much longer than I expected&#8211;over 2 hours. I was told it was the longest meeting they ever had. I was pleased at how engaged everyone was. There were so many questions, and many people seemed genuinely interested. I thoroughly enjoyed giving the talk. Can&#8217;t wait to do it again!<br />
<strong><br />
Resources:</strong></p>
<ul>
<li><a href="https://chrisedwards.dreamhosters.com/media/Intro to MongoDb (Chris Edwards).mp3">Download the audio (29.8 MB)</a></li>
<li><a href="http://github.com/ChrisEdwards/IntroducingMongoDB">Source code from the talk on github</a></li>
</ul>
<div style="width:425px" id="__ss_5726172"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/ChrisEdwards357/introduction-to-mongo-db" title="Introduction to mongo db">Introduction to mongo db</a></strong><object id="__sse5726172" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introductiontomongodb-101110080044-phpapp01&#038;rel=0&#038;stripped_title=introduction-to-mongo-db&#038;userName=ChrisEdwards357" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse5726172" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introductiontomongodb-101110080044-phpapp01&#038;rel=0&#038;stripped_title=introduction-to-mongo-db&#038;userName=ChrisEdwards357" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></p>
<div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/ChrisEdwards357">Chris Edwards</a>.</div>
</div>The post <a href="http://architester.com/blog/2010/11/10/slides-and-audio-for-my-introduction-to-mongodb-presentation/">Slides and Audio for my Introduction to MongoDB presentation</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2010/11/10/slides-and-audio-for-my-introduction-to-mongodb-presentation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>I will be presenting on MongoDB at the Austin .NET Users Group Monday</title>
		<link>http://architester.com/blog/2010/11/03/i-will-be-presenting-on-mongodb-at-the-austin-net-users-group-monday/</link>
					<comments>http://architester.com/blog/2010/11/03/i-will-be-presenting-on-mongodb-at-the-austin-net-users-group-monday/#comments</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Wed, 03 Nov 2010 20:17:52 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[Presentations]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/?p=236</guid>

					<description><![CDATA[<p>Here is the info that will be going out in the ADNUG notice. Topic: Introduction to MongoDB The relational database has been around for a very long time. It is used in almost every kind of application imaginable. Most all developers have experience using an RDBMS and use it on almost every project by default. [&#8230;]</p>
The post <a href="http://architester.com/blog/2010/11/03/i-will-be-presenting-on-mongodb-at-the-austin-net-users-group-monday/">I will be presenting on MongoDB at the Austin .NET Users Group Monday</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>Here is the info that will be going out in the <a href="http://www.adnug.org">ADNUG </a>notice.</p>
<p><strong>Topic: Introduction to MongoDB</strong><br />
The  relational database has been around for a very long time. It is used in  almost every kind of application imaginable. Most all developers have  experience using an RDBMS and use it on almost every project by default.  When was the last time you considered using an alternative? You  haven&#8217;t? Let me invite you to take a step outside the box for a moment.</p>
<p>MongoDB  is one of the new breed of &#8220;NoSQL&#8221; databases available as alternatives  to relational databases. It is a document database that represents its  data as JSON, and thus requires no schema. It can easily scale across  many computers using auto-sharding and supports redundancy for each  shard. Come get an overview this database, its scalability and  redundancy features, and how to access it via C#. While MongoDB is not  meant to replace all SQL databases, its good to know there is an  alternative for the cases where it is the better fit.</p>
<p><strong>Speaker: Chris Edwards</strong><br />
Chris  Edwards is a senior software developer with BancVue, Ltd. based in  Austin, TX. He has over 15 years of professional software development  experience in a diverse set of environments and technologies, but has  mostly focused on the Microsoft stack. Chris decided at a young age to  pursue software development after seeing the movie WarGames, and has  never looked back since. Now 26+ years later he is still writing code  with the same passion. Chris has presented as several of the Austin Code  Camps, and actively promotes and contributes to open source software.  When not coding, he can be found spending time with his family or  serving at Hill Country Bible Church, Hutto. He blogs atÂ <a href="http://r20.rs6.net/tn.jsp?llr=khdttecab&amp;et=1103866642845&amp;s=546&amp;e=001LU4Ugq5C0WFqZiby6g7FzTiRN9UMKtKTIrMuExtyZBzONb9_GYB3TipbOvPgSiGOlbzPZXSrg800BMShVLsjCK4CRfEY0-tkQs0ez04BdzMaeyDZ-7tBguaKxkk1M4T0" target="_blank">https://chrisedwards.dreamhosters.com/</a> and you can find some of his work onÂ <a href="http://r20.rs6.net/tn.jsp?llr=khdttecab&amp;et=1103866642845&amp;s=546&amp;e=001LU4Ugq5C0WHhL-lQoTc2Y0IAntEHFeWMERnq8x3m5_sA-xqLofsy6fRfgI_Zq-Xq1OEQ7lpPtE7IY3Qoofr_0q-J_1ILUhjmWE4YSI-jkhYS4uDTUXC69EA2B_PyuhaZ" target="_blank">http://github.com/chrisedwards/ </a></p>
<p><strong>Monday November 8th 5:30-8:00pm</strong></p>
<p><strong>***New Location***</strong><br />
Microsoft Technology Center: Austin<br />
Quarry Oaks II<br />
10900 Stonelake Blvd., Suite 225<br />
Austin, TX 78759<br />
(512) 795-5300</p>The post <a href="http://architester.com/blog/2010/11/03/i-will-be-presenting-on-mongodb-at-the-austin-net-users-group-monday/">I will be presenting on MongoDB at the Austin .NET Users Group Monday</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2010/11/03/i-will-be-presenting-on-mongodb-at-the-austin-net-users-group-monday/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Creating a new gemspec for the Nubular Project (Nu) is easier than you might think</title>
		<link>http://architester.com/blog/2010/09/11/creating-a-new-gemspec-for-the-nubular-project-nu-is-easier-than-you-might-think/</link>
					<comments>http://architester.com/blog/2010/09/11/creating-a-new-gemspec-for-the-nubular-project-nu-is-easier-than-you-might-think/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Sun, 12 Sep 2010 04:34:37 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[CSharp]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/2010/09/11/creating-a-new-gemspec-for-the-nubular-project-nu-is-easier-than-you-might-think/</guid>

					<description><![CDATA[<p>I just started using Nu to manage the dependencies in my Fluency project. I had used package managers for ruby and php in the past, and loved them, so I couldnâ€™t pass up the opportunity to try out Nu. I am glad I did. What the heck is Nu? Nu is a package manager for [&#8230;]</p>
The post <a href="http://architester.com/blog/2010/09/11/creating-a-new-gemspec-for-the-nubular-project-nu-is-easier-than-you-might-think/">Creating a new gemspec for the Nubular Project (Nu) is easier than you might think</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>I just started using <a title="The Nubular Project Wiki" href="http://nu.wikispot.org/" target="_blank">Nu</a> to manage the dependencies in my <a title="Fluency project on GitHub" href="http://github.com/ChrisEdwards/Fluency" target="_blank">Fluency</a> project. I had used package managers for ruby and php in the past, and loved them, so I couldnâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t pass up the opportunity to try out Nu. I am glad I did.</p>
<h2>What the heck is Nu?</h2>
<p>Nu is a package manager for .NET (finally!). It allows you to install code libraries and all their dependencies automatically, and keep them updated. If you have ever heard of <a title="RubyGems.org your community gem host." href="http://rubygems.org/" target="_blank">RubyGems</a>, this is the same thing. In fact, its built on top of ruby gems! </p>
<h2>Installing Nu</h2>
<p>To use Nu, you first need to install ruby. You can get it <a title="Ruby installer for windows." href="http://rubyforge.org/frs/download.php/71078/rubyinstaller-1.9.1-p378.exe" target="_blank">here</a>. Then upgrade RubyGems by dropping to a command prompt and typing</p>
<p><code>gem update --system</code> </p>
<p>Then to install Nu you type</p>
<p><code>gem install nu</code> </p>
<p>And thatâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s itâ€¦Nu is installed and ready to go.</p>
<h2>Using Nu</h2>
<p>Using Nu is dirt simple. Wanna install NUnit?</p>
<p> <code>C:\project&gt;<b>nu install nunit</b>     <br />Gem nunit is not installed locally - I am now going to try and install it     <br />Successfully installed nunit-2.5.7.10213.20100801     <br />Installed package nunit.</code>   </p>
<p>Done! How about NHibernate?</p>
<p> <code>C:\project&gt;<b>nu install nhibernate</b>    <br />Gem nhibernate is not installed locally - I am now going to try and install it    <br />Successfully installed nhibernate-2.1.2.4000    <br />Loading dependency: castle.core = 1.1.0.0    <br />Loading dependency: castle.dynamicproxy2 = 2.1.0.0    <br />Loading dependency: castle.core = 1.1.0.0    <br />Loading dependency: log4net = 1.2.10.0    <br />Installed package nhibernate.</code>   </p>
<p>Sure beats the pants off navigating out to the website to download the latest version, doesnâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t it? And it even installed all the dependencies.</p>
<p><a href="https://www.chrisedwards.dreamhosters.com/blog/wp-content/uploads/2010/09/image.png"><img loading="lazy" decoding="async" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="https://www.chrisedwards.dreamhosters.com/blog/wp-content/uploads/2010/09/image_thumb.png" width="209" height="123" /></a> </p>
<h2>Creating a gem to be installed using Nu</h2>
<p>So what does it take to make a project installable using Nu? Not much. I was surprised at how easy it was. </p>
<p>When I converted Fluency to install all its dependencies using Nu, I found one library that that wasnâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t yet packaged as a gem and installable through Nu. This was the <a title="SharpTestsEx on CodePlex" href="http://sharptestex.codeplex.com/" target="_blank">SharpTestsEx</a> library. So I did what any self-respecting supporter of open-source software would do, I decided to add it myself so anyone else could use it.</p>
<h3>1. Prepare the gemspec</h3>
<p>To do this, I created a gems folder and in it, a <a title="Gemspec::reference" href="http://docs.rubygems.org/read/chapter/20" target="_blank">gemspec</a> file â€œsharptestsex.gemspecâ€ with the following contents</p>
<pre class="ruby" name="code">version = File.read(File.expand_path(&quot;../VERSION&quot;,__FILE__)).strip

Gem::Specification.new do |spec|
  spec.platform    = Gem::Platform::RUBY
  spec.name        = 'sharptestsex'
  spec.version     = version
  spec.files = Dir['lib/**/*']
  
  spec.summary     = 'Sharp Tests Ex - .NET Fluent Assertions for Your Tests'
  spec.description = '#TestsEx (Sharp Tests Extensions) is a set of extensible extensions. The main target is write short assertions where the Visual Studio IDE intellisense is your guide. #TestsEx can be used with NUnit, MsTests, xUnit, MbUnit.'
  
  spec.authors           = ['Fabio Maulo','JDiamond']
  spec.email             = ''
  spec.homepage          = 'http://sharptestex.codeplex.com/'
  spec.rubyforge_project = 'sharptestsex'
end</pre>
<p>and a â€œVERSIONâ€ file that simply contained the version number</p>
<pre class="ruby" name="code">1.0.0.0</pre>
<p>I then created a gems/lib/ folder and placed the binaries in it. The spec.files attribute indicates that I want to include all the files in this folder in the gem.</p>
<h3>2. Build and test the gem locally.</h3>
<p>Then I built the gem at the command prompt with</p>
<p><code>gem build sharptestsex.gemspec</code> </p>
<p>This will product the gem file names sharptestsex-1.0.0.0.gem. I tested it with nu locally by installing the gem directly (without going to the rubygems server) by specifying the filename of the gem.</p>
<p><code>gem install sharptestsex-1.0.0.0.gem</code> </p>
<p>This installed it from my local drive into the gem cache. The gem cache is where nu gets the libraries. If nu does not find the requested library in the gemcache, it asks rubygems to get it from the server. Installing it like I did above ensured its in the cache so nu could find it. Then I tested that nu could install it.</p>
<p><code>nu install sharptestsex</code> </p>
<p>Once I saw it all worked, I uninstalled the gem so that I would be able to test that it pulls from the server. Uninstalling the gem deletes it from the local gemcache. I had to do this because if it existed in the cache, it wouldnâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t even try to download if from the server the next time I test it. I uninstalled it withâ€¦</p>
<p><code>gem uninstall sharptestsex</code></p>
<h3>3. Push the gem to RubyGems.org</h3>
<p>Now I was ready to push the gem out to <a href="http://rubygems.org" target="_blank">RubyGems.org</a>. To do that, I needed to sign up for a free account, which was quick and painless. The I pushed the gem up.</p>
<p><code>gem push sharptestsex-1.0.0.0.gem</code></p>
<p>I was prompted for my RubyGems.org login and password, and then the gem was uploaded.&#160; </p>
<h3>4. The final test</h3>
<p>Then my new gem is ready to install with nu! I tested it withâ€¦</p>
<p><code>nu install sharptestsex</code></p>
<p>I checked, and sure enough, I saw a lib folder that contains a sharptestsex folder with all the binaries. It was way easier than I thought.</p>
<h3>Resources</h3>
<p>I drew heavily from the following resources while getting this to work.</p>
<ul>
<li><a href="http://devlicio.us/blogs/rob_reynolds/archive/2010/07/16/how-to-gems-and-net.aspx" target="_blank">How To: Gems and .NET</a> â€“ <em>Rob Reynolds, â€œThe Fervent Coderâ€</em> </li>
<li><a href="http://weblogs.asp.net/bsimser/archive/2010/07/30/creating-a-quot-new-quot-gem-for-quot-nu-quot-from-0-to-100-in-24-hours.aspx" target="_blank">Creating a &quot;New&quot; Gem for &quot;Nu&quot; &#8211; From 0 to 100 in 24 Hours</a> â€“ <em>Bill Simser</em> </li>
</ul>The post <a href="http://architester.com/blog/2010/09/11/creating-a-new-gemspec-for-the-nubular-project-nu-is-easier-than-you-might-think/">Creating a new gemspec for the Nubular Project (Nu) is easier than you might think</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2010/09/11/creating-a-new-gemspec-for-the-nubular-project-nu-is-easier-than-you-might-think/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Improving the Developer Culture at Your Workplace</title>
		<link>http://architester.com/blog/2010/07/27/improving-the-developer-culture-at-your-workplace/</link>
					<comments>http://architester.com/blog/2010/07/27/improving-the-developer-culture-at-your-workplace/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Tue, 27 Jul 2010 13:28:40 +0000</pubDate>
				<category><![CDATA[Continuous Learning]]></category>
		<category><![CDATA[Leading]]></category>
		<category><![CDATA[Mentoring]]></category>
		<category><![CDATA[Developer Culture]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/2010/07/27/improving-the-developer-culture-at-your-workplace/</guid>

					<description><![CDATA[<p>Here are some of the things we do here at BancVue to help keep our developer culture healthy and strong. They are things you can do to improve the developer culture at your work. Many of these things can be started by anyone at the company, though a few may require management approval or financial [&#8230;]</p>
The post <a href="http://architester.com/blog/2010/07/27/improving-the-developer-culture-at-your-workplace/">Improving the Developer Culture at Your Workplace</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>Here are some of the things we do here at <a href="http://www.bancvue.com/" target="_blank">BancVue</a> to help keep our developer culture healthy and strong. They are things you can do to improve the developer culture at your work. Many of these things can be started by anyone at the company, though a few may require management approval or financial support. However someone needs to lead the charge. If you want to change the culture, it has to start with you.</p>
<p><strong>Start a Developer Book Club</strong> â€“ Here at BancVue, we have a developerâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s book club that meets each Wednesday over lunch. The group decides what book they want to read, and then takes it a chapter (or sometimes a section) or so each week. We discuss what we have read and learn from one another to help keep our skills sharp.</p>
<p><strong>Hold Weekly Dev-Shares (Knowledge Shares)</strong> â€“ Each week we have a different developer share something they have learned, something they have worked on, or some other presentation that would benefit the other developers. Its a great way to spread knowledge or promote new technologies. We identify topics the developers as a whole need to know and ensure those topics are discussed. However, most of the time it is whatever the presenting developers choose to present. Its a great forum to show ways other developers have found to make your work easier. Its been used to discuss company tools or how to overcome common problems in the codebase or toolset. It helps increase the collective knowledge of the teams.</p>
<p><strong>Get Safari Subscriptions</strong> â€“ BancVue provides several subscriptions to <a title="Safari Books Online - Home" href="http://www.safaribooksonline.com/" target="_blank">Safari Books Online</a> that the developers have access to. This is a great resource for the developers to learn from. Several members of the book club use it to read the books. I have used it on many occasions to learn more about technologies relevant to whatever project I am working on.</p>
<p><strong>Start a Developer Library</strong> â€“ I personally bring up several of my development books and have them at my desk for any developer who wants to read them. I have seen places that sponsor a company library that is stocked with current books to help developers learn.</p>
<p><strong>Practice Pair Programming </strong>â€“ If you arenâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t doing pair programming, you are really missing out on a learning opportunity. Pairing is a great way to transfer knowledge. Each developer has their own bag of tips and tricks they have learned over the years. Paring allows the whole team to leverage this knowledge.Â  This is also true of domain knowledge. A great way to grow a junior developer is to pair them with a senior. Even the senior devs will benefit. I have learned A LOT through pairing, even from devs that are many years my junior.</p>
<p><strong>Start Mentoring</strong> â€“ Another way to really help developers grow is to assign them a mentor. Ideally each developer is both being mentored, and mentoring others. Senior devs mentor mid-level devs, who mentor junior devs. Senior devs can be mentored by other senior devs who have more experience, etc. Regardless of whether this is done formally or not, encourage the developers to take on an attitude of mentorship.Â  Everyone should be continuously learning from each other.</p>
<p><strong>Ask for a Training Budget</strong> â€“ Ask management to encourage outside training by providing funding for it. BancVue has a budget for training that can be used for conferences, online training or other courses. Some good examples would be attending JP Boodhooâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s <a title="Jean-Paul S. Boodhoo - Develop With Passion" href="http://www.jpboodhoo.com/training.oo" target="_blank">Nothin but .NET</a> course, or Udi Dahanâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s <a title="Udi Dahan - The Software Simplist - Training" href="http://www.udidahan.com/training" target="_blank">SOA course</a>, etc.</p>
<p><strong>Use Screencasting</strong> â€“ At BancVue, we screencast our dev shares. This way anyone who missed can still see it, plus, as we bring new employees on, they can benefit from them as well. We also have used them for training on company tools and walkthroughs of common tasks. A good example would be a screencast on how to set up a developerâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s box.</p>
<p><strong>Get Training Videos</strong> â€“ There are many video training resources available. Some are free, and some are for purchase. There are many great free videos out there. The purchased ones, however, often cover the topic in much more detail, but this is not always the case. Get videos that cover the technologies you are using, or the techniques the team needs to learn. Make them available to all the developers on a drive share or wiki. Make sure you watch the videos (or a sample of them) before making them available. You want to make sure they arenâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t a waste everyoneâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s time. Some good sources for videos are:</p>
<ul>
<li>Free
<ul>
<li><a title="Dime Casts.Net -- Inform and Educate in ~10 Minutes or Less" href="http://www.dimecasts.net/" target="_blank">DimeCasts.net</a> â€“ A great site with short 10-minute videos on all types of development topics. The length is perfect for the ADD-impaired (like myself).</li>
<li><a title="Virtual ALT.NET" href="http://www.virtualaltnet.com/" target="_blank">Virtual Alt.Net</a> â€“ This site holds a collection of virtual meetings/screencasts on various topics. Check out the â€œRecordingsâ€ tab.</li>
<li><a title="InfoQ: Tracking change and innovation in the enterprise software development community" href="http://www.infoq.com" target="_blank">InfoQ</a> â€“ This is far more than videos. It constantly has great new content. I suggest subscribing to their newsletter, which is just a concise set of links to all their new content.</li>
</ul>
</li>
<li>Paid
<ul>
<li><a title="TekPub - High-quality screencasts for programmers." href="http://tekpub.com/" target="_blank">TekPub</a> â€“ High quality training screencasts on several development topics.</li>
<li><a title="The Pragmatic Bookshelf - Screencasts" href="http://pragprog.com/screencasts" target="_blank">The Pragmatic Bookshelf Screencasts</a> â€“ I got Kent Beckâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s TDD videos off here and they were great.</li>
</ul>
</li>
</ul>
<p><strong>Broadcast Useful Resources</strong> â€“ When you learn of upcoming user group meetings or training opportunities, let all the developers know. I do this often. When the Austin Code Camp comes around each year, I personally invite every developer to come. When I find a great link that I know others would be interested in, forward it to them. I am always trying to make resources available to those who could use them.</p>
<p><strong>Start a Blog</strong> â€“ Starting a blog is not only a good way to learn technology yourself, its a great way to teach others what you are learning. If you want to lead others in your company how to use a particular method or tool, what better way than to write up a blog post and refer them to it. You will not only help the developers you work with, but you will be contributing to the developer community at large. I canâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t count how many times I have directed others to my blog for something they have questions about.</p>
<p><strong>Give a Presentation at a Local User Group</strong> â€“ Find a topic you are passionate about, and give a talk on it. Itâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s a great way to get people to come to the user group who may not otherwise come. They may come just because its you. It also encourages other developers to start doing the same. They see that you donâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t have to be a genius to do these things. It ups their confidence. Not only that, but in doing so, you will learn a lot. The saying is true, â€œIf you want to learn something really well, teach it.â€</p>
<p><strong>Keep up with Twitter</strong> â€“ To get a lot of resources and stay current, follow leading developers on twitter. The resources you can get from there are great. I find myself relying more on twitter and less on my RSS feeds for current information these days.</p>
<p><strong>Read Books</strong> â€“ This will help you stay current and keep your skills sharp. Aside from the obvious benefits to yourself, this also lets you determine what books you may want to suggest to others, or to the book club.</p>
<p>Well, thatâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s a lot of tips. The bottom line is, the change starts with you. I encourage you to implement some (or all) of these tips. Not only will you grow to be a better developer, but so will everyone around you. You will be a blessing to your company and your team, and create a better place to work in the process. Go for it!</p>
<p>-Chris</p>The post <a href="http://architester.com/blog/2010/07/27/improving-the-developer-culture-at-your-workplace/">Improving the Developer Culture at Your Workplace</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2010/07/27/improving-the-developer-culture-at-your-workplace/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Be a Mentor, Not a Critic</title>
		<link>http://architester.com/blog/2010/07/11/be-a-mentor-not-a-critic/</link>
					<comments>http://architester.com/blog/2010/07/11/be-a-mentor-not-a-critic/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Mon, 12 Jul 2010 03:36:48 +0000</pubDate>
				<category><![CDATA[Leading]]></category>
		<category><![CDATA[Mentoring]]></category>
		<category><![CDATA[Soft Skills]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/2010/07/11/be-a-mentor-not-a-critic/</guid>

					<description><![CDATA[<p>This quote was posted on twitter last week and really stuck with me, &#34;Be a mentor, not a critic.&#34; I don&#8217;t remember who posted it, but it really made me think about my attitude at work. I like to think of myself as a mentor. I try to help others become better developers. I make [&#8230;]</p>
The post <a href="http://architester.com/blog/2010/07/11/be-a-mentor-not-a-critic/">Be a Mentor, Not a Critic</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>This quote was posted on twitter last week and really stuck with me, <em>&quot;Be a mentor, not a critic.&quot;</em> I don&#8217;t remember who posted it, but it really made me think about my attitude at work. </p>
<p>I like to think of myself as a mentor. I try to help others become better developers. I make it my mission at work to teach and instruct every chance I can. When I do so, however, I can often be critical. I can easily resort to tearing people down by criticizing their code rather than building them up by encouraging them and teaching them. There is a huge difference between the two, and I need to constantly remind myself of this. </p>
<p>It makes me think of how Jesus could hang out with prostitutes and sinners, yet still be a mentor and guide for them. He demonstrated what was right by his life, and told them what was right in his speech, but he never pointed the finger at them. These people wanted to be with him, even though his life and teaching showed them that their lives were wrong. He was a positive influence on them, without being directly critical of them. He told them the truth when necessary, but did so with love.</p>
<p>So I have to ask myself, am I building people up, or tearing them down? And I ask you the same question. I challenge you to make it a priority to join with me and set the criticism aside. Be a positive influence on those around you. Teach others what you know, and learn from others what you do not. </p>
<p>Be a mentor, not a critic. </p>
<p>-Chris</p>The post <a href="http://architester.com/blog/2010/07/11/be-a-mentor-not-a-critic/">Be a Mentor, Not a Critic</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2010/07/11/be-a-mentor-not-a-critic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Antipattern: The Bloated Configuration File</title>
		<link>http://architester.com/blog/2010/07/07/antipattern-the-bloated-configuration-file/</link>
					<comments>http://architester.com/blog/2010/07/07/antipattern-the-bloated-configuration-file/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Wed, 07 Jul 2010 15:42:29 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Configuration]]></category>
		<category><![CDATA[Principles]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/?p=219</guid>

					<description><![CDATA[<p>Configuration files should contain only the values the end users will need to configure. Everything else should be in code. One problem with WCF is the size of the configuration files. They contain so much data they are unreadable. Its such a problem that Microsoft provides the WCF Configuration Editor to ease developers pain when [&#8230;]</p>
The post <a href="http://architester.com/blog/2010/07/07/antipattern-the-bloated-configuration-file/">Antipattern: The Bloated Configuration File</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p><em>Configuration files should contain only the values the end users will need to configure. Everything else should be in code.</em></p>
<p>One problem with WCF is the size of the configuration files. They contain so much data they are unreadable. Its such a problem that Microsoft provides the <a title="Link to external blog post on the WCF Configuration Editor tool" href="http://jeffbarnes.net/blog/post/2007/02/28/WCF-Configuration-Editor.aspx" target="_blank">WCF Configuration Editor</a> to ease <em>developers </em>pain when editing them.</p>
<p>This is even more of an issue when <em>users </em>need to edit them. I have user-editable configuration settings in my app.config, but since theÂ  WCF settings also reside in that file there is a risk that users will accidentally change them and cause failure. Not good.</p>
<p>WCF is a good example of a bloated config file, but the problem is not isolated to WCF. Anytime a config file contains non-configurable concerns, it is bloated.</p>
<p>You see, a bloated config file contains 2 types of data:</p>
<ol>
<li>User-editable configuration settings</li>
<li>Static application configuration (should never change&#8230;in my case, this is WCF binding configuration).</li>
</ol>
<p><strong>This violates SRP.</strong> Yes, I know, the Single Responsibility Principle applies to objects/classes, but it often applies beyond that scope as well.Â  In this case it applies at the file-level. A config file should have one and only one responsibility: user-configurable settings. Anything beyond that introduces confusion and increases risk when editing the file. If the users should never edit the WCF bindings, keep them out of the config file.</p>
<p><strong>So how do we fix it?</strong> Configure the WCF bindings in code rather than the config file. Expose only the WCF settings the users should modify as settings in the config file (endpoint addresses, timeouts, etc). Express everything else in code or in another file, safely out of reach. The result is clean config files that users can understand and edit without the fear of changing something they shouldn&#8217;t.</p>
<p>-Chris</p>The post <a href="http://architester.com/blog/2010/07/07/antipattern-the-bloated-configuration-file/">Antipattern: The Bloated Configuration File</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2010/07/07/antipattern-the-bloated-configuration-file/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Entities, Services &#038; Resources&#8212;Three Categories of Objects</title>
		<link>http://architester.com/blog/2010/06/27/entities-services-resourcesthree-categories-of-objects/</link>
					<comments>http://architester.com/blog/2010/06/27/entities-services-resourcesthree-categories-of-objects/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Mon, 28 Jun 2010 04:46:40 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Mocking]]></category>
		<category><![CDATA[Patterns]]></category>
		<category><![CDATA[Principles]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/2010/06/27/entities-services-resourcesthree-categories-of-objects/</guid>

					<description><![CDATA[<p>After working with domains for several years I find that there are three major categories of objects I work with: Entities, Services, and Resources. There are clear distinctions between these categories in their purpose, content, dependencies and roles. Understanding these categories clarifies what dependencies I should allow, what purpose the objects serve, and how I [&#8230;]</p>
The post <a href="http://architester.com/blog/2010/06/27/entities-services-resourcesthree-categories-of-objects/">Entities, Services & Resources—Three Categories of Objects</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p>After working with domains for several years I find that there are three major categories of objects I work with: Entities, Services, and Resources. There are clear distinctions between these categories in their purpose, content, dependencies and roles. Understanding these categories clarifies what dependencies I should allow, what purpose the objects serve, and how I should test them.</p>
<h3>Purpose / Content</h3>
<p><em>Entities</em> are the domain objects. They model the data that gets persisted to the database. These objects are mostly data, and have little behavior.</p>
<p><em>Services</em> are the workhorses of the application. They perform the majority of the business logic. These objects have little to no state, and are almost pure behavior.</p>
<p><em>Resources</em> are the objects that interface with outside dependencies like the file system, database, etc. These objects only have the business logic necessary to interface with these outside dependencies. They are used to decouple the application from the dependency itself. A good example of a resource is a repositoryâ€”which serves as the source for entities.</p>
<h3>Dependencies</h3>
<p><em>Entities</em> only have dependencies on other entities through relationships, such as, an order having line items. An entity should never depend on services or resources.</p>
<p><em>Services</em> can depend on anything. Services require dependencies on other services or resources to perform complex tasksâ€”per the Single Responsibility Principle.</p>
<p><em>Resources</em> generally only depend on the underlying subsystems they are encapsulating. Resources donâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t depend upon other services, but may depend upon other resources.</p>
<h3>Testing</h3>
<p><em>Entities</em> require the least amount of testing. They are mostly data and have simple behaviorâ€”there is little to test. But entities are used heavily in testing other objects. The serve as input and expected values when testing services and resources. Because there is so little behavior, it is easiest to use entities directly in the tests rather than mock them. (<em>This is where frameworks like </em><a href="http://github.com/chrisedwards/fluentobjectbuilder/" target="_blank"><em>Fluency</em></a><em> come into play to help create these objects in a state containing valid anonymous data. What mocking is to Services and Resources, Fluency is to Entities.)</em></p>
<p><em>Services</em> require a great deal of testing since they are mostly behavior. Unit testing them requires mocking any other services or resource they depend on. Any entities needed to test them are created and used directly. </p>
<p><em>Resources</em> cannot be covered in unit tests. Because they interact with underlying systems (disk, database, network, etc), any test against them is, by nature, an integration test. Resources are always mocked when unit testing other objects since they represent dependencies that we want to decouple our tests from.</p>
<h3></h3>
<h3>Architecture</h3>
<p><em>Entities</em> are the core of the Domain Model. They represent the business domain directly.</p>
<p><em>Services</em> can be part of the domain model or a part of the infrastructure model depending on the behavior they are supporting. For instance, a notification service would be an infrastructure concern while a loan calculation service would be a business domain concern.</p>
<p><em>Resources</em> are always part of the infrastructure for obvious reasons.</p>
<h3>Other</h3>
<p>Are there any other observations you can make about these three types of objects that can help us in our thinking? If so, please add your comments. I would love to hear them.</p>
<p>-Chris</p>The post <a href="http://architester.com/blog/2010/06/27/entities-services-resourcesthree-categories-of-objects/">Entities, Services & Resources—Three Categories of Objects</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2010/06/27/entities-services-resourcesthree-categories-of-objects/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Fighting Perfectionism&#8212;What Is Good Enough?</title>
		<link>http://architester.com/blog/2010/06/24/fighting-perfectionismwhat-is-good-enough/</link>
					<comments>http://architester.com/blog/2010/06/24/fighting-perfectionismwhat-is-good-enough/#respond</comments>
		
		<dc:creator><![CDATA[ChrisEdwards]]></dc:creator>
		<pubDate>Fri, 25 Jun 2010 05:39:35 +0000</pubDate>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Perfectionism]]></category>
		<category><![CDATA[Soft Skills]]></category>
		<guid isPermaLink="false">https://www.chrisedwards.dreamhosters.com/blog/2010/06/24/fighting-perfectionismwhat-is-good-enough/</guid>

					<description><![CDATA[<p>Perfectionism is a disability deceptively disguised as technical proficiency. It is adds risk to a project while deceiving the developer to believe they are doing the right thing. Where do you draw the line and stop refactoring knowing the code is good enough? Perfectionism is something I have struggled with for a long time. I [&#8230;]</p>
The post <a href="http://architester.com/blog/2010/06/24/fighting-perfectionismwhat-is-good-enough/">Fighting Perfectionism—What Is Good Enough?</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></description>
										<content:encoded><![CDATA[<p><em>Perfectionism is a disability deceptively disguised as technical proficiency. It is adds risk to a project while deceiving the developer to believe they are doing the right thing. Where do you draw the line and stop refactoring knowing the code is good enough?</em> </p>
<p>Perfectionism is something I have struggled with for a long time. I often feel dissatisfied with my code because the code is not â€œjust rightâ€. Time and time again I have found myself up against deadlines trying to clean up code that I should have left alone. It is something I have resolved to overcome, and if you suffer from this handicap, I urge you to do the same.</p>
<p>So what is good enough?&#160; How do I know when to stop?</p>
<p>This is a hard question to answer. To get started, we need to know what good software is. I would propose that good software is software that works,&#160; is understandable, maintainable and usable. Given this, the question can be rephrased as four smaller questions:</p>
<ul>
<li>Does it work well enough?</li>
<li>Is it understandable enough?</li>
<li>Is it maintainable enough?</li>
<li>Is it usable enough?</li>
</ul>
<p>Answering these questions should give us a good understanding of what is good enough, and perhaps help us overcome our perfection fetish.</p>
<h2>Does it work well enough?</h2>
<p>This is a question of requirements. Does the software meet the requirements? Is it stable? Does it meet the defined SLAs? If the answer is to any of these questions is no, then the software is not good enough. If the answer is yes, then we can move on.</p>
<h2>Is it understandable enough?</h2>
<p>Is the code clear? Can other developers read and make sense of it? Could they pick up development on it if you were hit by a truck?</p>
<h2>Is it maintainable enough?</h2>
<p>This is where I always get trapped. Can you reasonably modify the code to handle unforseen requirements changes? Is it flexible where the business rules are flexible? If not, can it easily be refactored to be flexible? I have trouble deciding what refactorings to do now, and which to save for later if we need them. </p>
<p>I am often afraid of painting myself into a cornerâ€”its a fear of being unable to change when necessary. I recently realized that following good agile practices (TDD, etcâ€¦) makes it much harder to paint yourself into a corner. Test coverage and good design allow you to easily refactor yourself out of any pinch. </p>
<p>Remembering to embrace change rather than fear it helps me to put off till tomorrow those things that are not necessary for today.</p>
<p><h2>Is it usable enough?</h2>
</p>
<p>Can the user accomplish the tasks they need to with the software? Can they do so efficiently and without complaint? An application that is not usable is useless. An app that is overdesigned, however, is wasteful and expensive.</p>
<p><h2>A word of caution</h2>
</p>
<p><p>I am not advocating that we develop mediocre software with mediocre design. Please realize that this is written to those developers who have a perfectionist bent, who see great software and great design as something that <strike>could be</strike> must be improved. Their â€œgood enoughâ€ is everyone elseâ€<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s â€œgreatâ€.</p>
<p>In the competitive world of software development and its pressures to deliver, we must strike a balance between quality and cost. The higher the quality of our code, the longer it will take to develop. In this world, the perfectionist will be forever unhappy with their results given the short time they are allotted. They will never be satisfied, that is, until they can overcome their perfectionism.</p>
<p>Fight Perfectionism! Know when to say when. Then move on.</p>
<p>-Chris</p></p>The post <a href="http://architester.com/blog/2010/06/24/fighting-perfectionismwhat-is-good-enough/">Fighting Perfectionism—What Is Good Enough?</a> first appeared on <a href="http://architester.com/blog">Architester - Chris Edwards</a>.]]></content:encoded>
					
					<wfw:commentRss>http://architester.com/blog/2010/06/24/fighting-perfectionismwhat-is-good-enough/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
