<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1201901477992407964</id><updated>2012-02-02T22:36:34.113-06:00</updated><category term='SOLID'/><category term='AOP'/><category term='MVC'/><category term='IoC'/><category term='Craftsmanship'/><category term='Kid'/><category term='ActiveRecord'/><category term='Dependency Injection'/><category term='Pylons'/><category term='Hibernate'/><category term='CI'/><category term='Castle'/><category term='Caching'/><category term='Java'/><category term='Google App Engine'/><category term='C#'/><category term='Mako'/><category term='NDepend'/><category term='Context'/><category term='Ivy'/><category term='dynamic languages'/><category term='Spec'/><category term='Sprocs'/><category term='Agile'/><category term='python'/><category term='so long'/><category term='Maven'/><category term='BDD'/><category term='ORM'/><category term='turbogears'/><category term='Nhibernate'/><category term='Automated Deployment'/><category term='Monorail'/><category term='Spring'/><category term='San Antoino Book Club.'/><category term='snake-guice'/><category term='Pinsor'/><category term='Development Ideals'/><category term='Ayende'/><title type='text'>Mind Dump</title><subtitle type='html'>Random daily ramblings of an unfocused developer</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>38</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-808406658049210495</id><published>2011-09-25T11:54:00.000-05:00</published><updated>2011-09-25T11:54:33.912-05:00</updated><title type='text'>Rail 3.1 CI setup with Jenkins, Test Unit &amp; SimpleCov on OS X Lion.</title><content type='html'>I recently had to setup a build server for some rails work I'm doing. Still wanting to support my other projects I setup Jenkins. I ran into several issues.&lt;br /&gt;&lt;h2&gt;Running Jenkins as a hidden user&lt;/h2&gt;First I noticed that jenkins was running as the "daemon" user, this obviously wasn't going to work for github and rvm needs. So I did some googling and had some guides to get Jenkins running as a specific user. I did the following (sourced from http://colonelpanic.net/2011/06/jenkins-on-mac-os-x-git-w-ssh-public-key/ ).&lt;script src="https://gist.github.com/1240763.js?file=gistfile1.sh"&gt;&lt;/script&gt;Note: That's really $PASSWORD up above. This gives you a prompt to enter that password. Next you'll need to stop the Jenkins service and edit the plist and start the service back up.&lt;br/&gt;&lt;script src="https://gist.github.com/1240767.js?file=gistfile1.sh"&gt;&lt;/script&gt;You're plist file should end up like this.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-JckxfVa4CUE/Tn9bFY-ZIpI/AAAAAAAAEfw/2Kfjwl0hl78/s1600/file_to_edit.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-JckxfVa4CUE/Tn9bFY-ZIpI/AAAAAAAAEfw/2Kfjwl0hl78/s1600/file_to_edit.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;h2&gt;RVM issues&lt;/h2&gt;Now my next issue was despite what I'd read elsewhere I was unable to get Jenkins to use the default ruby provided by RVM. So I just pasted the commands that I would run anyway in the "Execute Shell" build step.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-CNWCN4T-AWU/Tn9bMpQzPlI/AAAAAAAAEgA/5BzEJ8fHCNA/s1600/rvm_workaround.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="171" src="http://1.bp.blogspot.com/-CNWCN4T-AWU/Tn9bMpQzPlI/AAAAAAAAEgA/5BzEJ8fHCNA/s640/rvm_workaround.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;h2&gt;Getting Jenkins to see tests&lt;/h2&gt;I've been using Test:Unit/Minitest lately just to keep more consistent with my day to day work. However I haven't found a way to get my tests to show when using the "Execute Shell" task. I found a little gem called ci_reporter that exports to the standard junit format, unfortunately it doesn't work with minitest yet. That's ok I haven't done anything that Test:Unit doesn't support so far so I added the the following to my Gemfile (note the part about unit-test 2.0):&lt;br /&gt;&lt;script src="https://gist.github.com/1240779.js?file=gemfile_with_ci_reporter"&gt;&lt;/script&gt;Running "rake ci:setup:testunit test" should give you a bunch of xml files in tests/reports. Now we need to tell Jenkins where to find those reports so add a post build action to pick them up as junit reports.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-m8riEeliq_c/Tn9bJhqygFI/AAAAAAAAEf4/eWchXXzfCjw/s1600/post_build_actions.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="86" src="http://2.bp.blogspot.com/-m8riEeliq_c/Tn9bJhqygFI/AAAAAAAAEf4/eWchXXzfCjw/s640/post_build_actions.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h2&gt;&lt;br /&gt;&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2&gt;Rcov reports&lt;/h2&gt;This was pretty easy.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Install Jenkins plugin for RCov (it's in the plugin list in the admin section).&lt;/li&gt;&lt;li&gt;add simplecov and semiplecov-rcov to your Gemfile.&lt;/li&gt;&lt;li&gt;configure Jenkins rcov plugin to look in coverage/rcov&lt;/li&gt;&lt;li&gt;add the following 4 lines to the TOP of your tests/test_helper.rb file:&lt;/li&gt;&lt;/ol&gt;&lt;br/&gt;&lt;script src="https://gist.github.com/1240806.js?file=test_helper.rb"&gt;&lt;/script&gt;&lt;br /&gt;&lt;h2&gt;In closing&lt;/h2&gt;This took a fair amount of time, but the end result was quite satisfying. I now have CI with tests, tests coverage, RVM to target different versions of Ruby and bundler to make sure my Gem environment is sane.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-808406658049210495?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/808406658049210495/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=808406658049210495' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/808406658049210495'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/808406658049210495'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2011/09/rail-31-ci-setup-with-jenkins-test-unit.html' title='Rail 3.1 CI setup with Jenkins, Test Unit &amp; SimpleCov on OS X Lion.'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-JckxfVa4CUE/Tn9bFY-ZIpI/AAAAAAAAEfw/2Kfjwl0hl78/s72-c/file_to_edit.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-3496633685542950098</id><published>2011-02-04T16:49:00.000-06:00</published><updated>2011-02-04T16:49:25.357-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>The difficult definition of professional software development</title><content type='html'>Here are some of the contradictory phrases (and a few paraphrases) I've overheard used to define what is "good" and "bad" code. &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Code should always be well commented&lt;/li&gt;&lt;li&gt;Maintainable code has unit tests and well named methods therefore needs little if any comments&lt;/li&gt;&lt;li&gt;Class explosion is to be avoided at all costs&lt;/li&gt;&lt;li&gt;Many small simple well named classes are the key to well organized code&lt;/li&gt;&lt;li&gt;Unit tests really don't test anything useful&lt;/li&gt;&lt;li&gt;Dependency injection leads to an unusable mess&lt;/li&gt;&lt;li&gt;Dependency Injection is a very useful tool for making your code extensible and easily reused"&lt;/li&gt;&lt;li&gt;Inheritance leads to solid code reuse&lt;/li&gt;&lt;li&gt;Inheritance is the strongest coupling of your code you can have&lt;/li&gt;&lt;li&gt;Functional programming simplifies and minimizes the complexity of your code&lt;/li&gt;&lt;li&gt;Functional programing just makes my eyes bleed!&lt;/li&gt;&lt;li&gt;Static global references are 'just programming' and something you have to learn how to manage to make simple easy to understand code&lt;/li&gt;&lt;li&gt;Static global spiderwebs are crippling to maintenance and program lifetime&lt;/li&gt;&lt;/ul&gt;&amp;nbsp; The part that is most difficult about that list for me is while I agree with half of it strongly and respect the people who said those things,  the other half that list I do not agree with, has all come from people I respect and who overall do some pretty impressive things. They've certainly created things by all measures more impressive than anything I've ever produced&lt;br /&gt;&lt;br /&gt;&amp;nbsp; This leads me to question how much do software principles matter when taking them out of the context of yourself but viewing it in a bigger picture?  Thinking about it, 95% of the software that I actually like probably wasn't using any TDD at any point in time and certainly violates a number of things that I would consider required for "professional software".  I keep reinforcing this fact every time I checkout the source of a major software project I've used for years and gasp in horror at the spaghetti code I find.&lt;br /&gt;&lt;br /&gt;&amp;nbsp; Worse still the different schools of thought are not compatible in the slightest, and one side views the other side as wholly unprofessional (granted for different reasons) to the point that I've realized I myself was perceived as the one being "amateur" by those with a different definition of what makes good and bad software. I of course unfortunately often thought the same of them, regardless of how I felt about them personally.&lt;br /&gt;&lt;br /&gt;&amp;nbsp; Anyway, this is all food for thought and I have not yet come to any conclusion what it all means. I know I've tried coding under other schools of thought and while through practice I was able to deliver well enough, I'm far slower and more error prone with no TDD, big mega classes, and avoiding dependency injection.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-3496633685542950098?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/3496633685542950098/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=3496633685542950098' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/3496633685542950098'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/3496633685542950098'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2011/02/difficult-definition-of-professional.html' title='The difficult definition of professional software development'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-6501333237108032444</id><published>2010-09-19T14:01:00.001-05:00</published><updated>2010-09-19T15:12:13.429-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><title type='text'>Java IoC containers and classpath scanning (or what I’ve been looking for from .NET for months)</title><content type='html'>&lt;p&gt;Frustrated with the typical way I saw IoC used in Java where every example I found involved thousands of lines of XML    &lt;br /&gt;and/or Java code to configure Java beans or components.&amp;#160; This is very different than IoC typically used in .NET where most IoC containers allow     &lt;br /&gt;you to &amp;quot;autowire&amp;quot; in their terminology up every class in an assembly with a couple of lines of code.&amp;#160; Having been coding in that fashion     &lt;br /&gt;for several years in .NET I was dismayed when none of my fellow Java coders that I worked with or knew personally had any concept     &lt;br /&gt;of the equivalent functionality, and instead informed me the IDE would be my help in maintaining these massive XML files. &lt;/p&gt;  &lt;p&gt;Not content with their answers I burrowed into Spring, Guice and PicoContainer docs and found &amp;quot;classpath scanning&amp;quot; which is roughly    &lt;br /&gt;equivalent to &amp;quot;autowire&amp;quot; in .NET. Below is an example of this in Spring 3:&lt;/p&gt;  &lt;p&gt;MyStuff.java (my main class note his has 2 dependencies which you can view on my &lt;a href="http://github.com/rssvihla/SpringDemo/tree/master/src/org/foo" target="_blank"&gt;github repo&lt;/a&gt;)&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:b3ddcea4-700b-4575-a466-42262c47dee0" class="wlWriterEditableSmartContent"&gt;&lt;div style="font-family:consolas,lucida console,courier,monospace"&gt;&lt;br /&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&amp;#160;org&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;foo&lt;/span&gt;&lt;span style="color:#666666"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0000FF"&gt;&lt;b&gt;org.springframework.beans.factory.annotation.Autowired&lt;/b&gt;&lt;/span&gt;&lt;span style="color:#666666"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0000FF"&gt;&lt;b&gt;org.springframework.stereotype.Service&lt;/b&gt;&lt;/span&gt;&lt;span style="color:#666666"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:#AA22FF"&gt;@Service&lt;/span&gt;&amp;#160;&lt;span style="color:#408080"&gt;&lt;i&gt;//one&amp;#160;way&amp;#160;of&amp;#160;marking&amp;#160;this&amp;#160;as&amp;#160;a&amp;#160;component&amp;#160;to&amp;#160;register&lt;br/&gt;&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0000FF"&gt;&lt;b&gt;MyStuff&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#666666"&gt;{&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;final&lt;/b&gt;&lt;/span&gt;&amp;#160;DependencyWithNoInterface&amp;#160;first&lt;span style="color:#666666"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;final&lt;/b&gt;&lt;/span&gt;&amp;#160;DependencyInterface&amp;#160;second&lt;span style="color:#666666"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#AA22FF"&gt;@Autowired&lt;/span&gt;&amp;#160;&lt;span style="color:#408080"&gt;&lt;i&gt;//tells&amp;#160;spring&amp;#160;which&amp;#160;constructor&amp;#160;to&amp;#160;use&amp;#160;for&amp;#160;it's&amp;#160;dependencies&lt;br/&gt;&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0000FF"&gt;MyStuff&lt;/span&gt;&lt;span style="color:#666666"&gt;(&lt;/span&gt;DependencyWithNoInterface&amp;#160;first&lt;span style="color:#666666"&gt;,&lt;/span&gt;&amp;#160;DependencyInterface&amp;#160;second&lt;span style="color:#666666"&gt;)&lt;/span&gt;&amp;#160;&lt;span style="color:#666666"&gt;{&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;this&lt;/b&gt;&lt;/span&gt;&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;first&lt;/span&gt;&amp;#160;&lt;span style="color:#666666"&gt;=&lt;/span&gt;&amp;#160;first&lt;span style="color:#666666"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;this&lt;/b&gt;&lt;/span&gt;&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;second&lt;/span&gt;&amp;#160;&lt;span style="color:#666666"&gt;=&lt;/span&gt;&amp;#160;second&lt;span style="color:#666666"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#666666"&gt;}&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#B00040"&gt;void&lt;/span&gt;&amp;#160;&lt;span style="color:#0000FF"&gt;run&lt;/span&gt;&lt;span style="color:#666666"&gt;(){&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;System&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;out&lt;/span&gt;&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;println&lt;/span&gt;&lt;span style="color:#666666"&gt;(&lt;/span&gt;&lt;span style="color:#BA2121"&gt;"foo&amp;#160;me"&lt;/span&gt;&lt;span style="color:#666666"&gt;);&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;first&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;foo&lt;/span&gt;&lt;span style="color:#666666"&gt;();&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;second&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;superFoo&lt;/span&gt;&lt;span style="color:#666666"&gt;();&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#666666"&gt;}&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:#666666"&gt;}&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;  &lt;p&gt;appContext.xml (seems you still need some XML)&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:a4fae1d2-1a1d-449e-b7d5-1d5d84f285e3" class="wlWriterEditableSmartContent"&gt;&lt;div style="font-family:consolas,lucida console,courier,monospace"&gt;&lt;br /&gt;&lt;span style="color:#BC7A00"&gt;&amp;lt;?xml&amp;#160;version="1.0"&amp;#160;encoding="UTF-8"?&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;beans&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#7D9029"&gt;xmlns=&lt;/span&gt;&lt;span style="color:#BA2121"&gt;"http://www.springframework.org/schema/beans"&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#7D9029"&gt;xmlns:xsi=&lt;/span&gt;&lt;span style="color:#BA2121"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#7D9029"&gt;xmlns:context=&lt;/span&gt;&lt;span style="color:#BA2121"&gt;"http://www.springframework.org/schema/context"&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#7D9029"&gt;xsi:schemaLocation=&lt;/span&gt;&lt;span style="color:#BA2121"&gt;"http://www.springframework.org/schema/beans&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;http://www.springframework.org/schema/beans/spring-beans-3.0.xsd&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;http://www.springframework.org/schema/context&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;http://www.springframework.org/schema/context/spring-context-3.0.xsd"&lt;/span&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;context:component-scan&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#7D9029"&gt;base-package=&lt;/span&gt;&lt;span style="color:#BA2121"&gt;"org.foo"&lt;/span&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;/&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;/beans&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;  &lt;p&gt;Application.java (the initialization)&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:eec33a84-1084-4e74-9b65-987aeedd1c57" class="wlWriterEditableSmartContent"&gt;&lt;div style="font-family:consolas,lucida console,courier,monospace"&gt;&lt;br /&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&amp;#160;org&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;foo&lt;/span&gt;&lt;span style="color:#666666"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0000FF"&gt;&lt;b&gt;org.springframework.context.ApplicationContext&lt;/b&gt;&lt;/span&gt;&lt;span style="color:#666666"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0000FF"&gt;&lt;b&gt;org.springframework.context.support.ClassPathXmlApplicationContext&lt;/b&gt;&lt;/span&gt;&lt;span style="color:#666666"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0000FF"&gt;&lt;b&gt;Application&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#666666"&gt;{&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#B00040"&gt;void&lt;/span&gt;&amp;#160;&lt;span style="color:#0000FF"&gt;main&lt;/span&gt;&lt;span style="color:#666666"&gt;(&lt;/span&gt;String&amp;#160;args&lt;span style="color:#666666"&gt;[]){&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;ApplicationContext&amp;#160;ctx&amp;#160;&lt;span style="color:#666666"&gt;=&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;&amp;#160;ClassPathXmlApplicationContext&lt;span style="color:#666666"&gt;(&lt;/span&gt;&lt;span style="color:#BA2121"&gt;"appContext.xml"&lt;/span&gt;&lt;span style="color:#666666"&gt;);&lt;/span&gt;&amp;#160;&lt;span style="color:#408080"&gt;&lt;i&gt;//the&amp;#160;IoC&amp;#160;container&lt;br/&gt;&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;MyStuff&amp;#160;stff&amp;#160;&lt;span style="color:#666666"&gt;=&lt;/span&gt;&amp;#160;ctx&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;getBean&lt;/span&gt;&lt;span style="color:#666666"&gt;(&lt;/span&gt;MyStuff&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;class&lt;/span&gt;&lt;span style="color:#666666"&gt;);&lt;/span&gt;&amp;#160;&lt;span style="color:#408080"&gt;&lt;i&gt;//my&amp;#160;fully&amp;#160;injected&amp;#160;class&lt;br/&gt;&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;stff&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;run&lt;/span&gt;&lt;span style="color:#666666"&gt;();&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#666666"&gt;}&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:#666666"&gt;}&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Now I’m sure for the .NET developers familiar with StructureMap, Windsor, Autofac, etc this is completely unimpressive. I’m also sure there are Java developers that are somewhat unimpressed with this but for reasons that involve holding onto giant configuration artifacts. &lt;strong&gt;Manual IoC component registration falls where hand writing SQL for trivial data access does for me, extra repetitive work that has been solved years ago&lt;/strong&gt;. I worked in factories a decade ago, and therefore now have a low tolerance for similar activity as a professional.&lt;/p&gt;  &lt;p&gt;Edit:&lt;/p&gt;  &lt;p&gt;It appears you can forgo XML as well in your main class use a different Application context and add the refresh and scan lines&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:17470b9c-ed5b-4600-a901-5315af6574ba" class="wlWriterEditableSmartContent"&gt;&lt;div style="font-family:consolas,lucida console,courier,monospace"&gt;&lt;br /&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&amp;#160;org&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;foo&lt;/span&gt;&lt;span style="color:#666666"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0000FF"&gt;&lt;b&gt;org.springframework.context.annotation.AnnotationConfigApplicationContext&lt;/b&gt;&lt;/span&gt;&lt;span style="color:#666666"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0000FF"&gt;&lt;b&gt;Application&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#666666"&gt;{&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#B00040"&gt;void&lt;/span&gt;&amp;#160;&lt;span style="color:#0000FF"&gt;main&lt;/span&gt;&lt;span style="color:#666666"&gt;(&lt;/span&gt;String&amp;#160;args&lt;span style="color:#666666"&gt;[]){&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;AnnotationConfigApplicationContext&amp;#160;ctx&amp;#160;&lt;span style="color:#666666"&gt;=&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;&amp;#160;AnnotationConfigApplicationContext&lt;span style="color:#666666"&gt;();&lt;/span&gt;&amp;#160;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;ctx&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;scan&lt;/span&gt;&lt;span style="color:#666666"&gt;(&lt;/span&gt;&lt;span style="color:#BA2121"&gt;"org.foo"&lt;/span&gt;&lt;span style="color:#666666"&gt;);&lt;/span&gt;&amp;#160;&lt;span style="color:#408080"&gt;&lt;i&gt;//scans&amp;#160;the&amp;#160;org.foo&amp;#160;package&lt;br/&gt;&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;ctx&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;refresh&lt;/span&gt;&lt;span style="color:#666666"&gt;();&lt;/span&gt;&amp;#160;&lt;span style="color:#408080"&gt;&lt;i&gt;//needed&amp;#160;to&amp;#160;load&amp;#160;them&amp;#160;for&amp;#160;some&amp;#160;reason&lt;br/&gt;&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;MyStuff&amp;#160;stff&amp;#160;&lt;span style="color:#666666"&gt;=&lt;/span&gt;&amp;#160;ctx&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;getBean&lt;/span&gt;&lt;span style="color:#666666"&gt;(&lt;/span&gt;MyStuff&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;class&lt;/span&gt;&lt;span style="color:#666666"&gt;);&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;stff&lt;span style="color:#666666"&gt;.&lt;/span&gt;&lt;span style="color:#7D9029"&gt;run&lt;/span&gt;&lt;span style="color:#666666"&gt;();&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#666666"&gt;}&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:#666666"&gt;}&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-6501333237108032444?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/6501333237108032444/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=6501333237108032444' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/6501333237108032444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/6501333237108032444'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2010/09/java-ioc-containers-and-classpath.html' title='Java IoC containers and classpath scanning (or what I’ve been looking for from .NET for months)'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-3783627848396743238</id><published>2010-07-15T07:00:00.001-05:00</published><updated>2010-06-25T22:59:38.362-05:00</updated><title type='text'>Anti-Pattern: Too much of your application is about interacting with external resources</title><content type='html'>Firstly, what am I talking about? Applications that meet some of the following descriptions:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Stored procedures with a fair amount of conditional logic or complicated business rules buried in a sub-query (some would argue sprocs at all).&lt;/li&gt;&lt;li&gt;Web pages with lots of conditional output again encoding business rules in snippets of view logic. if else checks that display the latest price for something if before and certain date or a default price.&lt;/li&gt;&lt;li&gt;The majority of ‘unit tests’ require a database, or web and application server to be up and running.&lt;/li&gt;&lt;li&gt;The majority of code files make reference to language default I/O or database libraries.&lt;/li&gt;&lt;li&gt;Hours are spent trying to determine if differences in version of infrastructure are the cause of certain bugs.&lt;/li&gt;&lt;li&gt;Changing database schema results in hours of refactoring, as hundreds of querys and sprocs are hunted through to see if this index or that index is being properly hit.&lt;/li&gt;&lt;/ol&gt;Why is this an anti-pattern? First before I bore you with endless reasoning behind SOLID principles, proper OO etc if you’re reading this and you’re of a bent that disagrees with me so far entirely..none of that will mean anything to you, and none of it will mean anything to your customers so let me put this in the most practical terms I can. &lt;br /&gt;&lt;em&gt;&lt;strong&gt;It is not testable in the slightest in any practical sense&lt;/strong&gt;&lt;/em&gt;. You will be counter with well that with that sort of application and making everything a front to back test that you KNOW when things are working, &lt;em&gt;&lt;strong&gt;yes but you RARELY if EVER know in a quick sense why things are not working.&lt;/strong&gt;&lt;/em&gt; If i can reliably eliminate any chance that my actual code or business logic is the cause of a problem, if all of my fancy business rules are in something that can be run thousands of times a second, then I can throw all sorts of corner cases at my code base and not increase my verification time. If the majority of my application is business logic and plain old code then I can save my slow manual testing to the areas that are so bullet proof and only have a slice of my application doing front to back testing to yes, make sure things really work.&lt;br /&gt;&lt;b&gt;Note:&lt;/b&gt; Cross posted from &lt;a href="http://rssvihla.lostechies.com/"&gt;Polyglots R Us&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.blogger.com/blogs/rssvihla/archive/2010/07/15/anti-pattern-too-much-of-your-application-is-about-interacting-with-external-resources.aspx"&gt;Permalink&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-3783627848396743238?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/3783627848396743238/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=3783627848396743238' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/3783627848396743238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/3783627848396743238'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2010/06/anti-pattern-too-much-of-your.html' title='Anti-Pattern: Too much of your application is about interacting with external resources'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-6644175136639443268</id><published>2010-07-10T12:50:00.003-05:00</published><updated>2010-07-10T12:55:11.923-05:00</updated><title type='text'>Project Management in Java: A Confused .NET Developer’s Perspective</title><content type='html'>When I was first introduced to workplace Java the amount of ways one could define a project appeared to be restrictive, confusing and a point of frequent friction. While those things may all be true, it’s a great deal better than I would have expected since I was coming from a world where an upgrade to a newer version of Visual Studio requires your whole team to sync up to that same version!&amp;nbsp; So how do cross IDEA teams get any work done in the Java workplace? Do Java OSS projects require everyone uses Eclipse, NetBeans, or IntelliJ?&amp;nbsp; Does every new IDE need to have import/export filters for all of the other existing ones and if it becomes popular do the already present IDE’s have to include this? Which system is the best and what matters?&lt;br /&gt;To answer these questions let break down what makes a project and while doing so compare and contrast the Java perspective with the .NET one.&lt;br /&gt;&lt;h3&gt;Compilation&lt;/h3&gt;Java IDE’s&amp;nbsp;&amp;nbsp;(Intellij/Eclipse/Netbeans)&amp;nbsp;– basically run “make” on the fly and pass everything to javac.&lt;br /&gt;JAVA IDE-agnostic project systems&amp;nbsp;&amp;nbsp;(Maven, Gradle)&amp;nbsp;– adding all the references contained directly to the classpath and then calling javac.&lt;br /&gt;.NET&amp;nbsp;(Visual Studio,MSBuild)&amp;nbsp;&amp;nbsp;– MSBuild feeds all references to csc.&lt;br /&gt;In summary, there is more similar than different here.&lt;br /&gt;&lt;h3&gt;Strong Versioning&lt;/h3&gt;Java IDE’s – at least in the case of IntelliJ I ended up manually writing a MANIFEST.MF file.&lt;br /&gt;Java IDE-agnostic project systems – still manual editing a lot of the time but usually just one line already filled out by your template that you edit.&amp;nbsp; I know NetBeans gives you a GUI to edit this. &lt;br /&gt;.NET – GUI but you can manually edit an assembly.cs file. &lt;br /&gt;In summary,&amp;nbsp; Java IDE’s at least in the case of IntelliJ really are using default Java by hand stuff.&lt;br /&gt;&lt;h3&gt;Dependencies&lt;/h3&gt;Java IDE’s – All use convention! Basically, search for jar files in your source tree, if the IDE finds them it assumes you need them and adds them as references in your project format. Works pretty nice on a whole and allows for manual tweaking in the oddball cases.&lt;br /&gt;Java IDE-agnostic project systems – requires explicit dependency reference by version, however they will download them automatically from remote locations and put them in your file-system in a specific way (defined by them unless overridden by you). Since both of these are also responsible for your compilation you have to basically run everything through them or your IDE has to be aware of them.&lt;br /&gt;.NET – requires explicit reference to DLL’s on the file system.&lt;br /&gt;In summary, .NET and the Java IDE-agnostic systems are VERY similar here in approach, whereas the Java IDE’s take a convention over configuration approach. I’d say there are times I definitely prefer the Java IDE approach and there are times the capabilities of the Java IDE-agnostic systems are worth it.&lt;br /&gt;&lt;h3&gt;&lt;/h3&gt;&lt;h3&gt;Source References&lt;/h3&gt;All Java solutions – do reference by directory structure and wild card matching.&lt;br /&gt;.NET – explicit references to &lt;strong&gt;&lt;u&gt;each class file&lt;/u&gt;&lt;/strong&gt; .&lt;br /&gt;In summary, this is the HUGE difference. Java takes more of a Make based approach where it’s EXPECTED this will not be the only IDE/project system ever used on this source tree, and this is where the Visual Studio/.NET experience starts to fall apart when trying to use cross-ide’s or versions. It has forced everyone to implement and keep up with MSBuild’s format to enable other IDE’s to be used, and don’t talk about actual alternatives to MSBuild. At this point even though things like NAnt and Rake/Albacore are more popular among agile .NET teams than scripting MSBuild almost all of those scripts still call MSBuild to do the compile step! &lt;br /&gt;&lt;h3&gt;Questions Answered&lt;/h3&gt;Q. How do Java OSS projects deal with all the different IDE’s out there and even different project formats?/How do cross IDE teams get work done?&lt;br /&gt;A. They don’t have to worry about it as much as .NET devs. A friend of mine who a lead contributor to the Apache Cassandra project in fact included a Maven file for the “enterprise types” but by and large use Ant’s to do their builds and he himself has used a number of IDE’s on that same codebase. .NET OSS development is still a bit hamstrung by MSBuild and really alternative IDE’s are keeping in sync with that project management format. There are real problems with style and code format guidelines, but there are usually workarounds or ways of solving this if code style guidelines is something you really care about ( which I don’t).&lt;br /&gt;Q. Which system is the best?&lt;br /&gt;A. There is no one size fits all answer here. I now know Apache Maven solves some problems for people and even though I don’t appreciate it’s approach to things, it’s done some valuable good for the community.&amp;nbsp; The IDE-centric approach really works pretty well a lot of the time for projects. Gradle, while being the closest to what I want is very young and has limited IDE support, at least it’s not easy enough for this Java n00b to figure out how to use with IntelliJ without some friction.&lt;br /&gt;&lt;h3&gt;Summary&lt;/h3&gt;I hope that all wasn’t too confusing, it sure was for me to go through while I had all these options , and in a completely different environment to what I was used to. Worse a lot of the folks I talked to saw these IDE-agnostic project systems as solving problems they didn’t have. Maven, Ivy, etc was a world that was buzzword laden (I’m really looking at you Maven and Ivy), involved heavy setup time for relatively simple tasks, incomplete documentation (looking at you Gradle) and was frequently badly misused (those who know me know what I’m referring too here). In the end an IDE-centric approach in the Java world does not seem to tie you to that IDE in any way I can find, and for getting started had little friction, and for people new to Java it seemed to be the best way to get started. Besides in Java at least it’s easy to change your mind later.&lt;br /&gt;&lt;b&gt;Note:&lt;/b&gt; Cross posted from &lt;a href="http://www.lostechies.com/blogs/rssvihla/archive/2010/07/12/project-management-in-java-a-confused-net-developer-s-perspective.aspx"&gt;Polyglots R Us&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.blogger.com/blogs/rssvihla/archive/2010/07/12/project-management-in-java-a-confused-net-developer-s-perspective.aspx"&gt;Permalink&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-6644175136639443268?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/6644175136639443268/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=6644175136639443268' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/6644175136639443268'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/6644175136639443268'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2010/07/project-management-in-java-confused-net.html' title='Project Management in Java: A Confused .NET Developer’s Perspective'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-7656192575134724143</id><published>2010-07-01T07:00:00.000-05:00</published><updated>2010-06-25T23:48:57.656-05:00</updated><title type='text'>MySQL 5 Performance Tuning Toolkit</title><content type='html'>Recently we’d played with table partitioning and because of the limitations of it and some decisions we’d made a very long time ago we ended up spending a couple of days tracking down hotspots. In the process I picked up a few tricks, I’m not even an authority on any of this but I figured it’d help out others in the same spot.&lt;br /&gt;&lt;h3&gt;Logging Toolkit&lt;/h3&gt;If you have a slow loading page or test and have no idea which one of the thirty or so queries going on is the cause how to do you find it.&amp;nbsp; Slow query log and logging queries that are not using indexes. Adding the following to your my.ini, my.cnf or whatever your mysql config file is named on your system and you’ll be able to get a list of offenders to further investigate.&lt;br /&gt;&lt;script src="http://gist.github.com/453770.js?file=logging-my.cnf%20"&gt;&lt;/script&gt;  &lt;br /&gt;&lt;h3&gt;MySQL Console Toolkit&lt;/h3&gt;SHOW INNODB STATUS – gives tons of useful information on what the current state of deadlocks, transactions and all sorts of information.&lt;br /&gt;SHOW FULL PROCESSLIST – shows the current threads and queries running on them. running this over and over again can show you queries that are hanging.&lt;br /&gt;EXPLAIN &amp;lt;QUERY&amp;gt;– Just in place of query type your full query statement, particularly in sub-queries, this is great for pointing out potential problems, in my most recent case I had an uncacheable sub-query, pointing out quickly something that was just not going to work no matter what. &lt;br /&gt;&lt;h3&gt;&lt;/h3&gt;&lt;h3&gt;Final Notes&lt;/h3&gt;Anyway this is only a smidgen of the useful stuff you need in your toolkit and I’m certainly no expert. I want to plug &lt;a href="http://www.amazon.com/gp/product/0596101716/ref=s9_simh_gw_p14_i1?pf_rd_m=ATVPDKIKX0DER&amp;amp;pf_rd_s=center-http://www.amazon.com/High-Performance-MySQL-Optimization-Replication/dp/0596101716/ref=pd_sim_b_1"&gt;High Performance MySQL: Optimization, Backups, Replication, and More&lt;/a&gt; and the &lt;a href="http://www.mysqlperformanceblog.com/"&gt;http://www.mysqlperformanceblog.com/&lt;/a&gt; for it’s help and as a reference for those wanting to go into deeper study.&lt;br /&gt;&lt;b&gt;Note:&lt;/b&gt; Cross posted from &lt;a href="http://rssvihla.lostechies.com/"&gt;Polyglots R Us&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.blogger.com/blogs/rssvihla/archive/2010/07/01/mysql-5-performance-tuning-toolkit.aspx"&gt;Permalink&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-7656192575134724143?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/7656192575134724143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=7656192575134724143' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/7656192575134724143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/7656192575134724143'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2010/06/mysql-5-performance-tuning-toolkit.html' title='MySQL 5 Performance Tuning Toolkit'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-5153740879891307891</id><published>2010-06-26T08:53:00.001-05:00</published><updated>2010-06-26T08:55:12.895-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><title type='text'>Hibernate Connection Pooling: why isn't the default one for production?</title><content type='html'>&lt;div style="font-family: arial; font-size: 12px; background-color: #FFFFFF; "&gt;Hibernate unlike NHibernate comes with a variety of connection pooling options. The three primary ones of which I'm aware are &lt;a href="http://proxool.sourceforge.net/"&gt;Proxool&lt;/a&gt;, &lt;a href="http://commons.apache.org/dbcp/"&gt;Apache DBCP&lt;/a&gt;, and &lt;a href="http://sourceforge.net/projects/c3p0/"&gt;c3p0&lt;/a&gt; . I myself have only so far used c3p0 and it works quite well having saved me from a couple of jams so far where the default one was in use previously. First why not use the default one? Because the official Hibernate documentation says in a big yellow box marked caution the following words:&lt;p&gt;&lt;span class="Apple-style-span" style="font-family: 'Lucida Grande', Geneva, Verdana, Arial, sans-serif; color: #533500; line-height: 18px; "&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote&gt;The built-in Hibernate connection pool is in no way intended for production use. It lacks several features found on any decent connection pool.&lt;/blockquote&gt;&lt;p&gt;Yet on almost every single Java project I've worked on the default is in use. I wouldn't care so much but this has personally wasted a fair amount of time for me and I've had to approach this as an outsider every time getting into the argument "it hasn't cause any issues before". Yet usually within a couple of days of that discussion I or someone else has resolved a "well it just does that sometimes" problem just by switching the connection pool. However, in implementing an alternate connection pool I should share a couple of gotcha's&lt;/p&gt;&lt;p&gt;1) Turn on logging for Hibernate and read the logs and make sure your connection pool of choice is actually activated and not the default one.&lt;/p&gt;&lt;p&gt;2) Older examples of the documentation I found for c3p0 did not include the necessary line for the C3P0Connection provider. If this line is not included in version 3.x version of hibernate regardless of what else is configured hibernate will use the default connection pool.&lt;/p&gt;&lt;p&gt;3) If the class you specified for connection provider line is not found for some reason, also the default connection pool will be used. Depending on your version of hibernate you may have to reference a different jar.&lt;/p&gt;&lt;p&gt;Below is the config borrowed from the hibernate connection tutorial only with c3p0 configured, please borrow it instead of using the default one.&lt;/p&gt;&lt;script src="http://gist.github.com/454055.js?file=c3p0.hibernate.cfg.xml"&gt;&lt;/script&gt;&lt;link rel="stylesheet" href="http://gist.github.com/stylesheets/gist/embed.css"&gt;&lt;div id="gist-454055" class="gist"&gt;                          &lt;div class="gist-file"&gt;        &lt;div class="gist-data gist-syntax"&gt;                                          &lt;div class="gist-highlight"&gt;&lt;pre&gt;&amp;lt;div class="line" id="LC1"&amp;gt;&amp;lt;span class="cp"&amp;gt;&amp;lt;?xml version='1.0' encoding='utf-8'?&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC2"&amp;gt;&amp;lt;span class="cp"&amp;gt;&amp;lt;!DOCTYPE hibernate-configuration PUBLIC&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC3"&amp;gt;&amp;lt;span class="cp"&amp;gt;        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC4"&amp;gt;&amp;lt;span class="cp"&amp;gt;        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC5"&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC6"&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;lt;hibernate-configuration&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC7"&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC8"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;session-factory&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC9"&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC10"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="c"&amp;gt;&amp;lt;!-- Database connection settings --&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC11"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"connection.driver_class"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;org.hsqldb.jdbcDriver&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC12"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"connection.url"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;jdbc:hsqldb:hsql://localhost&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC13"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"connection.username"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;sa&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC14"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"connection.password"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC15"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"connection.provider_class"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;org.hibernate.connection.C3P0ConnectionProvider&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="c"&amp;gt;&amp;lt;!-- NECESSARY TO USE C3P0 --&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC16"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"c3p0.acquire_increment"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;1&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC17"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"c3p0.idle_test_period"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;100&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="c"&amp;gt;&amp;lt;!-- seconds --&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC18"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"c3p0.max_size"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;100&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC19"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"c3p0.max_statements"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;0&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC20"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"c3p0.min_size"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;10&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC21"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"c3p0.timeout"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;100&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="c"&amp;gt;&amp;lt;!-- seconds --&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC22"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="c"&amp;gt;&amp;lt;!-- SQL dialect --&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC23"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"dialect"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;org.hibernate.dialect.HSQLDialect&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC24"&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC25"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="c"&amp;gt;&amp;lt;!-- Enable Hibernate's automatic session context management --&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC26"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"current_session_context_class"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;thread&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC27"&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC28"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="c"&amp;gt;&amp;lt;!-- Disable the second-level cache  --&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC29"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"cache.provider_class"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;org.hibernate.cache.NoCacheProvider&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC30"&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC31"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="c"&amp;gt;&amp;lt;!-- Echo all executed SQL to stdout --&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC32"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"show_sql"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;true&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC33"&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC34"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="c"&amp;gt;&amp;lt;!-- Drop and re-create the database schema on startup --&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC35"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;property&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;name=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"hbm2ddl.auto"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;update&amp;lt;span class="nt"&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC36"&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC37"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;mapping&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;resource=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"org/hibernate/tutorial/domain/Event.hbm.xml"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;/&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC38"&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC39"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span class="nt"&amp;gt;&amp;lt;/session-factory&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC40"&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="line" id="LC41"&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;lt;/hibernate-configuration&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;/pre&gt;&lt;/div&gt;                  &lt;/div&gt;        &lt;div class="gist-meta"&gt;          &lt;a href="http://gist.github.com/raw/454055/dd0f23990ffaf0a88fa832409230991e8b6d2b21/c3p0.hibernate.cfg.xml" style="float:right;"&gt;view raw&lt;/a&gt;          &lt;a href="http://gist.github.com/454055#file_c3p0.hibernate.cfg.xml" style="float:right;margin-right:10px;color:#666"&gt;c3p0.hibernate.cfg.xml&lt;/a&gt;          &lt;a href="http://gist.github.com/454055"&gt;This Gist&lt;/a&gt; brought to you by &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt;.        &lt;/div&gt;      &lt;/div&gt;      &lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-5153740879891307891?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/5153740879891307891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=5153740879891307891' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/5153740879891307891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/5153740879891307891'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2010/06/hibernate-connection-pooling-why-is.html' title='Hibernate Connection Pooling: why isn&amp;#39;t the default one for production?'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-8883063391059111962</id><published>2010-06-06T13:05:00.001-05:00</published><updated>2010-06-06T13:05:13.992-05:00</updated><title type='text'>Dynamic DNS with Amazon EC2 Linux and EveryDNS</title><content type='html'>&lt;p&gt;So I finally sat down and did the math and found out Amazon EC2 was quite a bit cheaper than what I’d been paying for hosting as long as I was willing to prepay for at least a year.&amp;#160; However, with EC2 you are getting a dynamic ip’s so what to do? Well I’ve been using EveryDNS for years for my dns hosting and despite it’s recent acquisition by Dyn, Inc it’s still works the same. The scripts that are described below can be downloaded &lt;a href="http://unstabletransit.com/blogfiles/dyndns.tgz" target="_blank"&gt;here&lt;/a&gt;, what follows is a brief walkthrough.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Download EveryDns update script from &lt;a href="http://www.everydns.com/dynamic.php"&gt;http://www.everydns.com/dynamic.php&lt;/a&gt;&amp;#160; and place it in something like /usr/local/bin. &lt;/li&gt;    &lt;li&gt;Create a convenience script in /usr/local/bin that will get your external ip and have it contain the following lines and call it &lt;strong&gt;external-ip.sh . &lt;/strong&gt;This is using Amazon’s suggested curl command to find out your EC2 instance Ip address.       &lt;ol&gt;       &lt;li&gt;&lt;a href="http://lh4.ggpht.com/_k_9IJqyZcGU/TAvjUnMeeNI/AAAAAAAAAdI/EA_dxBBXDJc/s1600-h/external-ip%5B6%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="external-ip" border="0" alt="external-ip" src="http://lh3.ggpht.com/_k_9IJqyZcGU/TAvjVDvfNEI/AAAAAAAAAdM/apNTywtvoCQ/external-ip_thumb%5B4%5D.png?imgmax=800" width="670" height="168" /&gt;&lt;/a&gt; &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt;    &lt;li&gt;Then create a script for the actual dynamic DNS update in /usr/local/bin/ and call it updatedns-sh. This is using the set command to grab the output of external ip and storing it in the variable $1, and then passing that value to the update command. &lt;strong&gt;NOTE: this will update the dns record of ALL your domains with everydns set to dynamic&lt;/strong&gt;. If you need to use specific domain names there is a –d flag for the eDNS client.&lt;a href="http://lh4.ggpht.com/_k_9IJqyZcGU/TAvjVSxfKoI/AAAAAAAAAdQ/0CTQtEGBOt0/s1600-h/update%5B12%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="update" border="0" alt="update" src="http://lh5.ggpht.com/_k_9IJqyZcGU/TAvjVt7re1I/AAAAAAAAAdU/_NoE-iU5TeY/update_thumb%5B6%5D.png?imgmax=800" width="677" height="169" /&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;create a cron job on your linux distro of choice but the cron job line should look like the following.      &lt;ol&gt;       &lt;li&gt;&lt;a href="http://lh4.ggpht.com/_k_9IJqyZcGU/TAvjV-gN8oI/AAAAAAAAAdY/GAX3LEI3c2o/s1600-h/cron%5B4%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="cron" border="0" alt="cron" src="http://lh5.ggpht.com/_k_9IJqyZcGU/TAvjWbPEDSI/AAAAAAAAAdc/BxfCfYsx3gQ/cron_thumb%5B2%5D.png?imgmax=800" width="754" height="38" /&gt;&lt;/a&gt; &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-8883063391059111962?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/8883063391059111962/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=8883063391059111962' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/8883063391059111962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/8883063391059111962'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2010/06/dynamic-dns-with-amazon-ec2-linux-and.html' title='Dynamic DNS with Amazon EC2 Linux and EveryDNS'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_k_9IJqyZcGU/TAvjVDvfNEI/AAAAAAAAAdM/apNTywtvoCQ/s72-c/external-ip_thumb%5B4%5D.png?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-1034368586928470715</id><published>2010-05-22T21:56:00.001-05:00</published><updated>2010-05-22T21:56:56.271-05:00</updated><title type='text'>Projects in Java with Maven 2</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;For those of you who don’t know Maven is a build tool/dependency manager/project model. Those in the Microsoft space can probably imagine MSBuild + the ability to download all dll’s for you.&lt;/p&gt;  &lt;h3&gt;What I liked&lt;/h3&gt;  &lt;ol&gt;   &lt;li&gt;Dependency Resolution. Automatic downloading of dependencies rocks in concept. Just specify library name and version and when you compile again it’s there.&amp;#160; No need to check in jar’s into your source tree. &lt;/li&gt;    &lt;li&gt;IDE Independence. In practical terms lets you use whatever IDE you want with no import/export.&amp;#160; Intellij, Eclipse and Netbeans all understand maven as a full project format. So your team can all have different IDE’s and not create havoc with one another. &lt;/li&gt;    &lt;li&gt;Good Default Project Structure. Tests are in the same location by default, resources for tests and your prod code are in expected places. &lt;/li&gt; &lt;/ol&gt;  &lt;h3&gt;What I hated&lt;/h3&gt;  &lt;ol&gt;   &lt;li&gt;Inefficient with already downloaded dependencies. It will check remote repositories &lt;em&gt;every time&lt;/em&gt; you build even when you specified version number. Now I can see why they did that but not as a default. I mean sure version 1.12 may have had a bad bug and the project hotfixed in a new one with the same version number, but I’d say that’s really unlikely.&amp;#160; In a larger project with several repositories the difference in time to build between this and an alternate dependency manager Apache Ivy is stark. &lt;/li&gt;    &lt;li&gt;Very opinionated view of the build process. Those of you used to (N)Ant or Rake will miss the lack of control. The AntRun plugin will help mitigate some of the lose of control. &lt;/li&gt;    &lt;li&gt;HOME/.m2/settings.xml . Specific system wide settings do not belong in a build language. The bad heavy friction ideas that it enabled were legion. Just one example was I had to connect to my work VPN even when working on my home OSS projects hosted on github. &lt;/li&gt;    &lt;li&gt;Way too XML for for sometimes simple things. To specify the version of java target language version see the figure below, this specifies Java 1.6. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:1136fb41-f264-41bb-925a-f392a3919c65" class="wlWriterEditableSmartContent"&gt;&lt;div style="font-family:consolas,lucida console,courier,monospace"&gt;&lt;br /&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;build&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;plugins&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;plugin&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;artifactId&amp;gt;&lt;/b&gt;&lt;/span&gt;maven-compiler-plugin&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;/artifactId&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;configuration&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;source&amp;gt;&lt;/b&gt;&lt;/span&gt;1.6&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;/source&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;target&amp;gt;&lt;/b&gt;&lt;/span&gt;1.6&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;/target&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;/configuration&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;/plugin&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br/&gt;&lt;br /&gt;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;/plugins&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:#008000"&gt;&lt;b&gt;&amp;lt;/build&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;  &lt;h3&gt;Summary&lt;/h3&gt;  &lt;p&gt;If you have a cross IDE team or are running an OSS java project I find it very hard to ignore Maven. If you are looking for easier dependency management, less verbose build files, and do not care about IDE independence I suggest any number of alternatives such as Apache Buildr, Apache Ivy, Gradle or many others I’m sure I’m forgetting.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-1034368586928470715?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/1034368586928470715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=1034368586928470715' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/1034368586928470715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/1034368586928470715'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2010/05/projects-in-java-with-maven-2.html' title='Projects in Java with Maven 2'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-5451644952050439212</id><published>2009-06-29T09:00:00.000-05:00</published><updated>2010-06-26T20:13:36.453-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><category scheme='http://www.blogger.com/atom/ns#' term='Ivy'/><title type='text'>Java Dependency Management with Apache Ivy</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;p&gt;Not wanting to ditch your already built well working ant scripts for the plugin-centric view of Maven, especially if your project structure doesn't line up quite right with Maven's point of view? Enter Apache Ivy which like Maven can automatically download and resolve all of your dependencies and their dependencies for you with just a few simple lines of XML (if only I could get rid of the XML Part).&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Pros&lt;/p&gt;&lt;p&gt;Integrates with Ant, but can still be run standalone.&lt;/p&gt;&lt;p&gt;By default dumps all dependencies into your lib folder which makes it super easy to use with most IDE's.&lt;/p&gt;&lt;p&gt;Works with existing Maven 2 repositories, allowing you to leverage work already done by the Maven community.&lt;/p&gt;&lt;p&gt;Cons&lt;/p&gt;&lt;p&gt;Despite lots of documentation, too much focus on theory with little practical example of how to do simple things. Maybe I'm missing something but I did waste a fair amount of time trying to get a custom 3rd party repository working without crippling the defaults for Ivy. Again I may be just dense, but this was harder for me than either Gradle or Maven to do, and I ran into a couple of hiccups from there.&lt;/p&gt;&lt;p&gt;Limited IDE support compared to say Maven at least in the case of Intellij. Part of this is Maven has some pretty snazzy integration with Maven and I know on more than a couple of occasions I've just started projects with Maven because Intelij makes it super simple and gives me lots of nice integration for adding dependencies with the classic alt+enter .&lt;/p&gt;&lt;p&gt;I decided to include the default scripts I start with. This should get you up and running and give you a template for solving some of the hassle I went through. Just place next to each other in your top level project directory, ivy.xml, ivysettings.xml, and build.xml if you plan on using Ant integration. Also for ant integration make sure you have ivy-2.1.0.jar in "$ANT_HOME/lib" and all should be well. Please ask for clarification on anything, I'll do another post if I get enough questions.&lt;/p&gt;&lt;script src="http://gist.github.com/454111.js"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-5451644952050439212?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/5451644952050439212/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=5451644952050439212' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/5451644952050439212'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/5451644952050439212'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/06/java-dependency-management-with-apache.html' title='Java Dependency Management with Apache Ivy'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-4280200406605827597</id><published>2009-05-22T11:05:00.003-05:00</published><updated>2009-05-22T11:08:17.216-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='so long'/><title type='text'>Over at los techies now</title><content type='html'>I got a wonderful opportunity to blog over at  &lt;a href="http://www.lostechies.com/blogs/rssvihla/default.aspx"&gt;Los Techies&lt;/a&gt; . I'm not too worried about losing my independence as I see eye to eye with a lot of that community and its a good place to get my idea's kicked around and adjusted by others experiences.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-4280200406605827597?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/4280200406605827597/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=4280200406605827597' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/4280200406605827597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/4280200406605827597'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/05/over-at-los-techies-now.html' title='Over at los techies now'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-2041466939132051664</id><published>2009-05-21T09:24:00.003-05:00</published><updated>2009-05-21T09:39:31.521-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Spec'/><category scheme='http://www.blogger.com/atom/ns#' term='BDD'/><category scheme='http://www.blogger.com/atom/ns#' term='Context'/><title type='text'>Context/Spec style testing and my approach to BDD</title><content type='html'>I borrow heavily my approach to testing from a combination of Ayende's Rhino Tools tests, and my reading of the Rspec beta book.  But I think I've stumbled onto something I'm happy with and I can generate reports out of.  Let's go over some basic rules first:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Move as much common setup logic to a base class as possible.&lt;/li&gt;&lt;li&gt;Use your class name as the context&lt;/li&gt;&lt;li&gt;methods are rules beginning with "should"&lt;/li&gt;&lt;li&gt;create a new subclass of the base context every time you have a new scenario&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Code ends up looking like so:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public class BaseAddVacationContext&lt;br /&gt;{&lt;br /&gt;    protected AddVacationRequest submission;&lt;br /&gt;    protected IEmailSender _sender;&lt;br /&gt;    protected IUserInformation _information;&lt;br /&gt;    protected ICrudRepo&lt;leaverequest&gt;&amp;lt;LeaveRequest&amp;gt; _leaverepo;&lt;br /&gt;    protected LeaveRequest request;&lt;br /&gt;    [SetUp]&lt;br /&gt;    public virtual void SetUp()&lt;br /&gt;    {&lt;br /&gt;        _sender = MockRepository.GenerateMock&lt;iemailsender&gt;&amp;lt;IEmailSender&amp;gt;();&lt;br /&gt;        _information = MockRepository.GenerateMock&lt;iuserinformation&gt;&amp;lt;IUserInformation&amp;gt;();&lt;br /&gt;        _leaverepo= MockRepository.GenerateMock&lt;icrudrepo&gt;&lt;leaverequest&gt;&amp;lt;ICrudRepo&amp;lt;LeaveRequest&amp;gt;&amp;gt;();&lt;br /&gt;        submission = new AddVacationRequest(_sender, _information, _emprepo);&lt;br /&gt;        request = new LeaveRequest() { UserName = "james" };&lt;br /&gt;  &lt;br /&gt;   &lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;[TestFixture]&lt;br /&gt;public class SpecAddVacationRequestWhenHappyPathOccurs : BaseAddVacationContext&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    [SetUp]&lt;br /&gt;    public override void SetUp()&lt;br /&gt;    {&lt;br /&gt;        base.SetUp();&lt;br /&gt;        _information.Stub(x =&gt; x.GetManagersEmailAddresses("james")).Return(new[]{"jacob@jonbank.com", "johnny@jonbank.com"});&lt;br /&gt;        _information.Stub(x =&gt; x.GetUserEmail("james")).Return("james@jonbank.com");&lt;br /&gt;        submission.Execute(request);&lt;br /&gt;   &lt;br /&gt;    }&lt;br /&gt;    [Test]&lt;br /&gt;    public void should_email_all_managers()&lt;br /&gt;    {&lt;br /&gt;        _sender.AssertWasCalled(x =&gt; x.Send(Arg&lt;message&gt;&lt;/message&gt;&lt;/leaverequest&gt;&lt;/icrudrepo&gt;&lt;/iuserinformation&gt;&lt;/iemailsender&gt;&lt;/leaverequest&gt;&lt;/code&gt;&lt;span style="font-family:monospace;"&gt;&amp;lt;Message&amp;gt;&lt;/span&gt;&lt;code&gt;&lt;leaverequest&gt;&lt;iemailsender&gt;&lt;iuserinformation&gt;&lt;icrudrepo&gt;&lt;leaverequest&gt;&lt;message&gt;.Matches(y =&gt; y.To == "jacob@jonbank.com")));&lt;br /&gt;        _sender.AssertWasCalled(x=&gt;x.Send(Arg&lt;message&gt;&lt;/message&gt;&lt;/message&gt;&lt;/leaverequest&gt;&lt;/icrudrepo&gt;&lt;/iuserinformation&gt;&lt;/iemailsender&gt;&lt;/leaverequest&gt;&lt;/code&gt;&lt;span style="font-family:monospace;"&gt;&amp;lt;Message&amp;gt;&lt;/span&gt;&lt;code&gt;&lt;leaverequest&gt;&lt;iemailsender&gt;&lt;iuserinformation&gt;&lt;icrudrepo&gt;&lt;leaverequest&gt;&lt;message&gt;&lt;message&gt;.Matches(y=&gt;y.To =="johnny@jonbank.com")));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [Test]&lt;br /&gt;    public void should_send_email_to_user()&lt;br /&gt;    {&lt;br /&gt;        _sender.AssertWasCalled(x =&gt; x.Send(Arg&lt;message&gt;&lt;/message&gt;&lt;/message&gt;&lt;/message&gt;&lt;/leaverequest&gt;&lt;/icrudrepo&gt;&lt;/iuserinformation&gt;&lt;/iemailsender&gt;&lt;/leaverequest&gt;&lt;/code&gt;&lt;span style="font-family:monospace;"&gt;&amp;lt;Message&amp;gt;&lt;/span&gt;&lt;code&gt;&lt;leaverequest&gt;&lt;iemailsender&gt;&lt;iuserinformation&gt;&lt;icrudrepo&gt;&lt;leaverequest&gt;&lt;message&gt;&lt;message&gt;&lt;message&gt;.Matches(y =&gt; y.To == "james@jonbank.com")));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [Test]&lt;br /&gt;    public void should_store_leave_request_in_database()&lt;br /&gt;    {&lt;br /&gt;        _emprepo.AssertWasCalled(x=&gt;x.Create(Arg&lt;/message&gt;&lt;/message&gt;&lt;/message&gt;&lt;/leaverequest&gt;&lt;/icrudrepo&gt;&lt;/iuserinformation&gt;&lt;/iemailsender&gt;&lt;/leaverequest&gt;&lt;/code&gt;&lt;span style="font-family:monospace;"&gt;&amp;lt;LeaveRequest&amp;gt;&lt;/span&gt;&lt;code&gt;&lt;leaverequest&gt;&lt;iemailsender&gt;&lt;iuserinformation&gt;&lt;icrudrepo&gt;&lt;leaverequest&gt;&lt;message&gt;&lt;message&gt;&lt;message&gt;&lt;leaverequest&gt;.Matches&lt;/leaverequest&gt;&lt;/message&gt;&lt;/message&gt;&lt;/message&gt;&lt;/leaverequest&gt;&lt;/icrudrepo&gt;&lt;/iuserinformation&gt;&lt;/iemailsender&gt;&lt;/leaverequest&gt;&lt;/code&gt;&lt;code&gt;&lt;leaverequest&gt;&lt;iemailsender&gt;&lt;iuserinformation&gt;&lt;icrudrepo&gt;&lt;leaverequest&gt;&lt;message&gt;&lt;message&gt;&lt;message&gt;&lt;leaverequest&gt;(u=&gt;u == request)));&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/leaverequest&gt;&lt;/message&gt;&lt;/message&gt;&lt;/message&gt;&lt;/leaverequest&gt;&lt;/icrudrepo&gt;&lt;/iuserinformation&gt;&lt;/iemailsender&gt;&lt;/leaverequest&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So here we have:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A setup that you need to override and call to setup context specific behavior&lt;/li&gt;&lt;li&gt;small small tests and asserts.&lt;/li&gt;&lt;li&gt;limited setup on mocks, you can use handrolled mocks or the real classes if you prefer (which I do often).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Use AssertWasCalled instead of .Expect() on my mocks&lt;/li&gt;&lt;/ul&gt;I'll post more examples of this as they come up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-2041466939132051664?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/2041466939132051664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=2041466939132051664' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/2041466939132051664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/2041466939132051664'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/05/contextspec-style-testing-and-my.html' title='Context/Spec style testing and my approach to BDD'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-7108340393125861649</id><published>2009-05-21T04:42:00.006-05:00</published><updated>2009-05-21T05:37:43.449-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ActiveRecord'/><category scheme='http://www.blogger.com/atom/ns#' term='Monorail'/><category scheme='http://www.blogger.com/atom/ns#' term='Caching'/><title type='text'>Monorail ActiveRecord and NHibernate</title><content type='html'>Ran into this at work yesterday and wanted to save others some aggravation:&lt;br /&gt;&lt;br /&gt;Scenario: Need To query a value on a page repeatedly. Another 3rd party program is modifying the data you are querying. (in my case to generate new account numbers, could be anything)&lt;br /&gt;&lt;br /&gt;Bad Result: 3rd Party Program changes data in background your page does not update the new value.&lt;br /&gt;&lt;br /&gt;So my ActiveRecord query before looked something like so:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;ActiveRecordMediator&lt;dpacct&gt;.FindAll(Restrictions//you don't really care do you)&lt;br /&gt;&lt;/dpacct&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;now instead grab the underlying session object:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;ISession session =ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(DpAcct))&lt;br /&gt;var query = session.CreateQuery(//again you dont care)&lt;br /&gt;var list = query.List()&lt;br /&gt;session.Close()&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This may not be the best way and my Nhibernate knowledge is rudimentary once you start getting into Sessions, Scopes and Flushing, but it worked to get an ActiveRecord user by.&lt;br /&gt;&lt;br /&gt;It seems the cache doesn't know when to refresh when a third party application is involved. This is logical as the caching would be more expensive if it did.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-7108340393125861649?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/7108340393125861649/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=7108340393125861649' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/7108340393125861649'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/7108340393125861649'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/05/monorail-activerecord-and-nhibernate.html' title='Monorail ActiveRecord and NHibernate'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-7110094532221821314</id><published>2009-05-21T04:35:00.002-05:00</published><updated>2009-05-21T04:40:38.040-05:00</updated><title type='text'>Typemock Isolater and ASP.net Bundle -FREE</title><content type='html'>Pretty obvious marketing, but this is an awesome deal so I wanted you my readers in on it too. What kind of irresponsible blogger would I be?  So without further ado:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.typemock.com/"&gt;Unit Testing&lt;/a&gt; ASP.NET? &lt;a href="http://www.typemock.com/ASP.NET_unit_testing_page.php"&gt;ASP.NET unit testing&lt;/a&gt; has never been this easy.&lt;br /&gt;&lt;br /&gt;Typemock is launching a new product for ASP.NET developers – the &lt;strong&gt;ASP.NET Bundle&lt;/strong&gt; - and for the launch will be giving out &lt;span style="color: rgb(0, 102, 0);"&gt;&lt;strong&gt;FREE licenses&lt;/strong&gt;&lt;/span&gt; to bloggers and their readers.&lt;br /&gt;&lt;br /&gt;The ASP.NET Bundle is the ultimate ASP.NET unit testing solution, and offers both &lt;a href="http://www.typemock.com/"&gt;Typemock Isolator&lt;/a&gt;, a &lt;a href="http://www.typemock.com/"&gt;unit test&lt;/a&gt; tool and &lt;a href="http://sm-art.biz/Ivonna.aspx"&gt;Ivonna&lt;/a&gt;, the Isolator add-on for &lt;a href="http://sm-art.biz/Ivonna.aspx"&gt;ASP.NET unit testing&lt;/a&gt;, for a bargain price.&lt;br /&gt;&lt;br /&gt;Typemock Isolator is a leading &lt;a href="http://www.typemock.com/"&gt;.NET unit testing&lt;/a&gt; tool (C# and VB.NET) for many ‘hard to test’ technologies such as &lt;a href="http://typemock.com/sharepointpage.php"&gt;SharePoint&lt;/a&gt;, &lt;a href="http://www.typemock.com/ASP.NET_unit_testing_page.php"&gt;ASP.NET&lt;/a&gt;, &lt;a href="http://www.typemock.com/ASP.NET_unit_testing_page.php"&gt;MVC&lt;/a&gt;, &lt;a href="http://www.typemock.com/wcfpage.php"&gt;WCF&lt;/a&gt;, WPF, &lt;a href="http://www.typemock.com/Silverlight_unit_testing_page.php"&gt;Silverlight&lt;/a&gt; and more. Note that for &lt;a href="http://www.typemock.com/Silverlight_unit_testing_page.php"&gt;unit testing Silverlight&lt;/a&gt; there is an open source Isolator add-on called &lt;a href="http://www.typemock.com/Silverlight_unit_testing_page.php"&gt;SilverUnit&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The first 60 bloggers who will blog this text in their blog and &lt;a href="http://blog.typemock.com/2009/05/get-free-typemock-licenses-aspnet.html"&gt;tell us about it&lt;/a&gt;, will get a Free Isolator ASP.NET Bundle license (Typemock Isolator + Ivonna). If you post this in an ASP.NET &lt;strong&gt;dedicated&lt;/strong&gt; blog, you'll get a license automatically (even if more than 60 submit) during the first week of this announcement.&lt;br /&gt;&lt;br /&gt;Also 8 bloggers will get an &lt;strong&gt;additional 2 licenses&lt;/strong&gt; (each) to give away to their readers / friends.&lt;br /&gt;&lt;br /&gt;Go ahead, click the following link for &lt;a href="http://blog.typemock.com/2009/05/get-free-typemock-licenses-aspnet.html"&gt;more information &lt;/a&gt;on how to get your free license.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-7110094532221821314?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/7110094532221821314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=7110094532221821314' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/7110094532221821314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/7110094532221821314'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/05/typemock-isolater-and-aspnet-bundle.html' title='Typemock Isolater and ASP.net Bundle -FREE'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-9076758281062428251</id><published>2009-04-26T13:24:00.015-05:00</published><updated>2009-04-26T14:23:49.264-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CI'/><category scheme='http://www.blogger.com/atom/ns#' term='NDepend'/><title type='text'>Hudson, NDepend and OSS - The Good, The Bad, and The Useful</title><content type='html'>&lt;a href="http://codebetter.com/blogs/patricksmacchia/"&gt;Patrick Smacchia&lt;/a&gt; was kind enough to give me a copy of &lt;a href="http://www.ndepend.com/Default.aspx"&gt;NDepend&lt;/a&gt; so I could give it a good test drive. While we do use NDepend at work, we primarily use it for finding low hanging fruit for refactoring with our legacy software. I decided this would be a wonderful opportunity to see what NDepends story is with OSS and CI.&lt;br /&gt;&lt;br /&gt;To facilitate this demo, I used my fresh new BDD Framework Specmaker and Hudson CI server. Normally for CI at work I'd include a copy of whatever software I need in the actual source tree to make it easy to deploy. Obviously, since NDepend is a commercial product and Specmaker is Apache 2.0 license and hosted on Google Code, this was not a viable approach.&lt;br /&gt;&lt;br /&gt;So I did the following:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Installed Ndepend on my CI Server&lt;/li&gt;&lt;li&gt;Created a directory to store results&lt;/li&gt;&lt;li&gt;Created a VisualNDepend project. To be able to find my dlls I had to edit the NDependProject.xml file by hand to point to the correct locations. I'd like some nant style Fileset matching instead here. Makes it feel very much like MSBuild.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Setup 2 batch command steps in my build process to run AFTER my normal nant build (seen below, click to view closely) that called ndepend.console.exe and then copied the results to my build folder so they could be archived by Hudson.&lt;/li&gt;&lt;li&gt;Setup the archival rules for my build to grab all of the results that I'd copied to "build\NDependOut" so I could easily reference them after a successful build.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lh4.ggpht.com/_k_9IJqyZcGU/SfSvBK7rs2I/AAAAAAAAAK8/5nUUFpwZWrc/workspace-ndepend-ci-small.png"&gt;&lt;img style="cursor: pointer; width: 610px; height: 56px;" src="http://lh4.ggpht.com/_k_9IJqyZcGU/SfSvBK7rs2I/AAAAAAAAAK8/5nUUFpwZWrc/workspace-ndepend-ci-small.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lh6.ggpht.com/_k_9IJqyZcGU/SfSvBAMNGfI/AAAAAAAAAK0/YlPkNQxRroQ/hudson-ndepend.png"&gt;&lt;img style="cursor: pointer; width: 685px; height: 38px;" src="http://lh6.ggpht.com/_k_9IJqyZcGU/SfSvBAMNGfI/AAAAAAAAAK0/YlPkNQxRroQ/hudson-ndepend.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This took quite a bit of fiddling to get working my primary issues were related to Hudson's NAnt plugin (if you reference two nant calls, the first one ends up overwriting your second one so you just do step 1 twice). However once, I got it working my reward was the scolding finger of NDepend. Apparently I have a class teetering on the verge of Cyclomatic Complexity limits (SpecDescription), looks like I have some review to work out some kinks.&lt;br /&gt;&lt;br /&gt;Overall Review&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The Good - Nice UI for Visual NDepend, GOBS of information, CQL is really well thoughtout dsl for finding what you want so far.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The Bad - Hard Referencing dlls in xml is bad, rule matching is badly needed here.  Causes friction when setting up the project for automation. Custom Nant Task it comes with is very limited according to included documents.&lt;/li&gt;&lt;li&gt;The Useful - when combined with CI the comparitive analysis is brilliant. This lets you catch when codebases are declining in quality in an automated fashion. See &lt;a href="http://codebetter.com/blogs/patricksmacchia/archive/2008/01/20/avoid-api-breaking-changes.aspx"&gt;here&lt;/a&gt; for one such example.&lt;/li&gt;&lt;/ul&gt;Final words, I have to be honest here, I had fallen out of love with NDepend largely, finding it mostly useful only when initially touching a codebase, or when I was first learning SOLID principles. This was of course amazingly useful to my growth, and refactoring efforts, but I was finding less and less need for it with new projects.  Looking over Patrick's blog at some of the examples he's come up with using CQL I do not think I've come close to tapping the usefulness possible with this tool.  I'll be working more and more towards bending the tool to keep existing codebases in check, and will definitely be using it at home on my OSS work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-9076758281062428251?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/9076758281062428251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=9076758281062428251' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/9076758281062428251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/9076758281062428251'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/04/hudson-ndepend-and-oss-good-bad-and.html' title='Hudson, NDepend and OSS - The Good, The Bad, and The Useful'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_k_9IJqyZcGU/SfSvBK7rs2I/AAAAAAAAAK8/5nUUFpwZWrc/s72-c/workspace-ndepend-ci-small.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-4429841788445487616</id><published>2009-04-10T06:26:00.003-05:00</published><updated>2009-04-10T06:53:55.738-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CI'/><category scheme='http://www.blogger.com/atom/ns#' term='Automated Deployment'/><title type='text'>Deployment automation and adventures in stupid</title><content type='html'>At work we currently do not have a ton of order to software releases and requests. I've worked hard to try to bring more there but it's just not part of the way things have been done in the past and that type of change in particular takes a lot of work and persuasion.&lt;div&gt;Summary we're better than we were but we're not perfect yet.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;I have a confession to make...I was being a hypocrite yesterday.  I've been preaching since shortly after I got there "you can automate deployment", "manual deployment is error prone and slow", "integrate regularly, release often".  With my background as a sysadmin it didn't take me long to get every at least newer software release auto deployed in some fashion or another. The other push was towards not implementing software in chunks but slowly in front to back layers.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, about a month and a half ago, me and my co-worker were making changes that would require us to change two products at once. I had stupidly gone off on an unecessarily bold refactoring to modularity of one of those products...so I just let things fall behind and stopped pushing frequent releases.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Month and a half goes by and now the trunk has  :&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt; a TON of changes to a variety of processes. Including fixes to things that were major current maintenance time sinks&lt;/li&gt;&lt;li&gt; I had not yet successfully moved all my unit tests around to the different modules so I had managed to eliminate my hard won safety net.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Several database changes that I haven't scripted.&lt;/li&gt;&lt;li&gt;Worst of all code that was behind schedule that had been done for 4 weeks.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;So yesterday I finally have had enough of excuses why I wasn't pushing this build out. I manually do everything I had not yet had time to automate, and without all my tests in the proper location!&lt;br /&gt;&lt;br /&gt;Finding several stupid kinks, multiple bonehead "I forgot" things, and 15 hours later (with only two hours of sleep) with a process that was supposed to take 30 seconds I had both products released.&lt;br /&gt;&lt;br /&gt;I'm quite happy to say now I have an in sync code base, and a big list of fixes to implement which I will release one at a time!&lt;br /&gt;&lt;br /&gt;Release Frequently, do not push off things till later, and do things in small small layers.&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-4429841788445487616?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/4429841788445487616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=4429841788445487616' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/4429841788445487616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/4429841788445487616'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/04/deployment-automation-and-adventures-in.html' title='Deployment automation and adventures in stupid'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-1650471809669918664</id><published>2009-03-23T06:57:00.003-05:00</published><updated>2009-03-23T07:06:35.212-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='San Antoino Book Club.'/><category scheme='http://www.blogger.com/atom/ns#' term='Pinsor'/><category scheme='http://www.blogger.com/atom/ns#' term='Castle'/><category scheme='http://www.blogger.com/atom/ns#' term='Ayende'/><title type='text'>Update</title><content type='html'>It's been awhile since I added anything, but I want to update myself or any future readers on what I've actually been doing with myself the past month.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Got a commiter to Pinsor in Carlos Ble. Very smart fellow and very helpful.&lt;/li&gt;&lt;li&gt;Got plugin support finally worked out for a project at work (but done at home).  Will sanitize the code concepts and post here shortly.&lt;/li&gt;&lt;li&gt;Did a presentation of Castle Windsor and IoC at alamocoders that I think went pretty well (need to work on my material and demos a bit, but the talk went well).&lt;/li&gt;&lt;li&gt;Ayende made my head explode with the following post http://ayende.com/Blog/archive/2009/03/20/nhibernate-avoid-identity-generator-when-possible.aspx. Gonna take me a few days to process that one.&lt;/li&gt;&lt;li&gt;Did San Antonio Book Club meet and greet.  Was a lot of fun and i think we're going to start working lean into the mix.&lt;/li&gt;&lt;/ol&gt;Short update I'll try to get more details out of those into another series of posts.  I'd like to start putting my windsor material on the blog and hopefully suss out some of the weaker areas.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-1650471809669918664?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/1650471809669918664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=1650471809669918664' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/1650471809669918664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/1650471809669918664'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/03/update.html' title='Update'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-3342168728319149359</id><published>2009-02-28T10:18:00.004-06:00</published><updated>2009-02-28T11:01:34.393-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>Bosses and your approach to Agile</title><content type='html'>For me the hardest part of Agile by far is getting bosses to understand what it is, why it matters, why what they're doing now is harder than it needs to be, and why what they're doing now is causing the problems they're seeing.&lt;br /&gt;&lt;br /&gt;There are a few reasons I've observed and you may or may not run into that I think make this difficult.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Developers tend to talk over "normal" people's head&lt;/span&gt;s. I struggle with this and I didn't even own a computer till I was 23, so in theory I should understand the non-technical perspective better.  It's just ultimately VERY hard to take a technical and very detailed issue and bring it down to simpler terms and levels.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Bosses that compartmentalize software they buy and software their employees build as entirely different species&lt;/span&gt;.  If they buy software and it doesn't behave as they expect they'll stop using it, ask for their money back or raise unholy hell.  If they spend 50k in man hours for in house work they can sometimes accept it breaking on &lt;span style="font-style: italic;"&gt;its very basic designed functionality&lt;/span&gt;. I've seen software like that praised because it delivered business value, even if it did so at an excessive unnecessary cost.  This ends up you'd think working in our favor, except inevitably when going Agile we have a TON of software to maintain, and none of it is maintainable.  This stacks the deck against going agile in so many ways that I'll leave it for a dedicated blog post.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Bosses assume that developers are not able to understand business value.&lt;/span&gt; This one has been a huge problem for me.  I go out of my way to deliver business value first and foremost, I was a successful manager before I was a software developer.  However, generally speaking bosses are correct into thinking this about us a developers, which I'll cover later in another blog post.  Needless to say it's blunts our effectiveness at proposing solutions.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Our industry is filled with people that don't deliver what they say.&lt;/span&gt;  Sometimes it's us just overshooting our goal.  Sometimes it's developers who just want to look better than they are and stretch the truth .  Finally, sometimes it's people that just are flat out interested in taking the money and running (subtle distinction to others which one of the three types you are).  Regardless, some bosses have been burned so much they assume everything is a lie and they've made up their mind when they walk in the room.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Some bosses take a lot of pride in having a big hand in implementation details.&lt;/span&gt;  Now while this can easily help you once you have agile working if they are interested in helping you produce software that has lots of feedback. However, if your boss is this way, he's probably a former developer in a time far far away, and absolutely convinced about how a software project should be implemented (and assumes that the way they did it then was perfect despite the problems that all projects inevitably have).&lt;/li&gt;&lt;/ol&gt;There are certainly more, and if anyone wants to share please do.  In future blog posts I'll go through these one by one about what problems they cause and hopefully I can work through how to conquer these challenges in the future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-3342168728319149359?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/3342168728319149359/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=3342168728319149359' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/3342168728319149359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/3342168728319149359'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/02/bosses-and-your-approach-to-agile.html' title='Bosses and your approach to Agile'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-6536363608232814423</id><published>2009-02-18T20:27:00.007-06:00</published><updated>2009-02-18T20:53:25.193-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOLID'/><title type='text'>"Do I Care" and "It Depends"</title><content type='html'>Between my time talking to Agile Joe when my bank hired him and Jimmy Bogard in the last Virtual Alt.net meeting, I now have two new guiding principles to most development tasks.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Do I Care&lt;/span&gt;?&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Should you unit test this code? Do I care about that code?  Do I care if I change things later and this is not tested?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Should I write this Documentation? Do I care about the docs and what they say? Do I care if I can't remember what I did?&lt;/li&gt;&lt;li&gt;Should I delete this code? Do I care about it anymore? Does it do anything for me now?&lt;/li&gt;&lt;li&gt;Should I follow SOLID principles here? Is the work needed worth it for the payoff?&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;All of these questions may or may not be yes or no to "Do I Care?".   So how do you know if you care or not..this dovetails nicely with "&lt;span style="font-weight: bold;"&gt;It Depends&lt;/span&gt;".&lt;br /&gt;&lt;br /&gt;Like it or not one of our primary jobs is too manage tradeoffs. In one case we hamstring ourselves with too much work for little benefit in another we do not do nearly enough "housekeeping work" to make our code manageable.&lt;br /&gt;&lt;br /&gt;Full on SOLID on an application you're building for a day and then going to throw away? I'd hope you say "No I Don't Care About SOLID where it causes me more work", an app that will take 2 months to build...if you don't care, make sure it's only the first couple of days and not when it's too late.&lt;br /&gt;&lt;br /&gt;Bob Martin focuses on the "last responsible moment" i really always liked that and all but I feel like "Do I Care" maybe appeals in a more plain spoken way.  I only follow "good patterns and design" when I start caring, otherwise I fall into the trap of forgetting why i do these things in the first place.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-6536363608232814423?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/6536363608232814423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=6536363608232814423' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/6536363608232814423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/6536363608232814423'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/02/do-i-care-and-it-depends.html' title='&quot;Do I Care&quot; and &quot;It Depends&quot;'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-7942399596201511293</id><published>2009-02-16T04:14:00.002-06:00</published><updated>2009-02-16T04:20:10.438-06:00</updated><title type='text'>What to work on</title><content type='html'>Been quite busy with work for a couple of weeks, but as that is winding down a bit. I think I need another oss project to focus on. Pinsor needs one decent rewrite for clarity, and then some basic feature support and it'll need actual usage to warrant more changes.&lt;br /&gt;&lt;br /&gt;Been thinking about what I should work on next?&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Job scheduler ( some reason always loved these kind of projects, and could use pinsor on it)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Scrum project manager web app (would have to actually get comfy with pylons/tg/django)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;BDD framework in either C#, python or start contribing to spectre in boo.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-7942399596201511293?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/7942399596201511293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=7942399596201511293' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/7942399596201511293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/7942399596201511293'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/02/what-to-work-on.html' title='What to work on'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-2473520846969912526</id><published>2009-01-31T04:10:00.003-06:00</published><updated>2009-01-31T04:12:47.529-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dependency Injection'/><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='SOLID'/><title type='text'>S.O.L.I.D. Principles in Python</title><content type='html'>On the Pinsor google code project  I added my Perspective of SOLID principles in Python and their relevance&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/pinsor/wiki/SOLID?ts=1233396562&amp;amp;updated=SOLID"&gt;http://code.google.com/p/pinsor/wiki/SOLID?ts=1233396562&amp;amp;updated=SOLID&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-2473520846969912526?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/2473520846969912526/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=2473520846969912526' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/2473520846969912526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/2473520846969912526'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/01/solid-principles-in-python.html' title='S.O.L.I.D. Principles in Python'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-6802037184873441344</id><published>2009-01-26T20:47:00.007-06:00</published><updated>2009-01-26T21:21:49.652-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Pinsor Python DI/IoC framework</title><content type='html'>Well we'll see where this goes, but I finally decided to give back to open source a bit (besides being an advocate and willing trainer for those interested).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/pinsor/"&gt;Pinsor Google Code Project&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There doesn't seem to be much demand for IoC in Python (in fact &lt;a href="http://www.traceback.org/2009/01/01/article-help-dependency-injection-in-python/"&gt;anger&lt;/a&gt; see comments), but there wasn't in the DotNet community for a long time.  I believe the trick there was making IoC containers that people wanted to use for their language (read not 4000 lines of xml that you found in Java containers so often back then).&lt;br /&gt;&lt;br /&gt;Hopefully, my aim here is to bring auto-dependency resolution and cut down lines of code in an app, everything else that people typically blab on about with IoC/DI is &lt;span style="font-weight: bold;"&gt;staggeringly less important&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;This is an area where I fundamentally disagree with the most users of IoC frameworks who tend to pound DI DI DI and TESTABILTY.  Dependency Injection in of itself is a concept that's so bloody simple you can get it in 5 minutes of working with any language if you just accept it (which is by far the hardest part), and not the important part.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The most imporant thing pinsor will aim to bring is less lines of code in moderately complex projects or greater&lt;/span&gt;, if it doesn't accomplish that then I'll be the first to delete it and remove it permanently. My focus will therefore be on making sure automatic dependency resolution and convention based configuration are fluid and easy to use.&lt;br /&gt;&lt;br /&gt;As I refine the api and get a pythonic configuration DSL up I'll post examples and add to the docs.  Till then you may use the unit tests (which are done with a bit of  Behavior Driven Development style).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-6802037184873441344?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/6802037184873441344/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=6802037184873441344' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/6802037184873441344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/6802037184873441344'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/01/pinsor-python-diioc-framework.html' title='Pinsor Python DI/IoC framework'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-9003650304256979948</id><published>2009-01-11T12:50:00.005-06:00</published><updated>2009-01-26T21:23:06.621-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Development Ideals'/><title type='text'>Developer Professionalism and Chad Myers</title><content type='html'>Generally speaking I like Chad Myers comments a lot, some of it he has more experience and that leaves me with less material to challenge his ideas, but sometimes he just see's the world the same way I do.&lt;br /&gt;&lt;br /&gt;This &lt;a href="http://www.lostechies.com/blogs/chad_myers/archive/2009/01/11/a-rant-on-professionalism.aspx"&gt;post&lt;/a&gt; is exactly what I've felt for so terribly long, especially the parts about magic, hocus-pocus and charlatans. Its lonnngg past time computing in general move out of the voodoo phase.   So here is my advice for aspiring professional developers, technicians and support techs:&lt;br /&gt;&lt;br /&gt;Firstly, technology is not to be applied with the same logic as sports teams. Just because someone started liking Windows, Linux, c#, python, oracle, mysql, whatever does not mean that is the only technology in the world and one must support it till their dying day.  Things are good/bad on their own merits, and most work in one situation or another, and what was once bad can become good and vice versa.&lt;br /&gt;&lt;br /&gt;Let me state this REALLY clearly. Every time you refuse to dive into a technology because "it must be inferior" and you haven't actually tried to get some work done with it, you are hurting YOURSELF.&lt;br /&gt;&lt;br /&gt;Secondly, things are not what they seem on initial examination.  If you dont know how something works say so!  If you don't like something, give it a deeper look and try to use it, talk to those that actually do use it to get work done on a day to day basis.&lt;br /&gt;&lt;br /&gt;Thirdly,  if something breaks, or acts in a way you didn't expect. Figure out why that is, with analysis and thought.  Use the scientific method, only change one variable at a time, and dive deeply until you are satisfied with your findings.  Even then don't trust what you've found is gospel.&lt;br /&gt;&lt;br /&gt;Finally our job is to serve as tech experts for those that aren't tech experts.  This is a delicate job at times, but honesty and building trust is mandatory. Bullcrap solutions/explanations that may fool the customer for a time have a way of sooner or later exposing the bullcrapper as a useless expert to deal with.  Regardless, those that give good timely honest solutions and explanations with a touch of humility end up being the ones that everyone relies on.&lt;br /&gt;&lt;br /&gt;That's enough soap box for now, but at the end of the day if the industry as a whole acted that way, I'm quite certain we'd have a lot less "awful legacy code", less management interference, and we'd be focusing on delivering business value to customers (and delivering it quickly) instead of geek ego.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-9003650304256979948?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/9003650304256979948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=9003650304256979948' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/9003650304256979948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/9003650304256979948'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/01/developer-professionalism-and-chad.html' title='Developer Professionalism and Chad Myers'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-7860309207411995592</id><published>2009-01-02T00:26:00.005-06:00</published><updated>2009-01-27T09:32:18.671-06:00</updated><title type='text'>Remoting objects (yes I know it's not 2001) without using the MSDN Way</title><content type='html'>Ok very few people use Remoting Services any more but it's good in a pinch for quick and dirty way of doing distributed applications.&lt;br /&gt;&lt;br /&gt;Now when I went to first use Remoting I struggled to make it fully usable as the books I was using (as well as a quick Google and MSDN lookup) had me all using code like so:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;pre&gt;&lt;span&gt;&lt;span style="font-family:Verdana,Arial,Helvetica;"&gt;&lt;span class="codeComment"&gt;// Create an instance of a channel&lt;/span&gt;&lt;br /&gt; TcpChannel channel = new TcpChannel(8080);&lt;br /&gt; ChannelServices.RegisterChannel(channel);&lt;br /&gt;&lt;br /&gt; &lt;span class="codeComment"&gt;// Register as an available service with the name HelloWorld&lt;/span&gt;&lt;br /&gt; RemotingConfiguration.RegisterWellKnownServiceType(&lt;br /&gt;     typeof(SampleObject),&lt;br /&gt;     "HelloWorld",&lt;br /&gt;     WellKnownObjectMode.SingleCall );&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The above code instantiates (calls: new SampleObject() )  an object to be able to accessed remotely..but it cannot take any arguments in the ctor !!&lt;br /&gt;&lt;br /&gt;This ended up causing me no end of grief, because if I wanted to write a remoting test, I was pretty much stuck with whatever "new SampleObject()" initialized.  Now I was forced to open up configuration changes via setters!&lt;br /&gt;&lt;br /&gt;Eventually I scratched the whole thing when I found out Castle Windsor had a remoting facility and just used that to handle my remoting needs and it works quite well.&lt;br /&gt;&lt;br /&gt;Looking through Castle Trunk they use RemotingServices like so:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;internal static void Marshal(object instance, ComponentModel model)&lt;br /&gt;      {&lt;br /&gt;          MarshalByRefObject mbr = (MarshalByRefObject) instance;&lt;br /&gt;       &lt;br /&gt;          if (!Convert.ToBoolean(model.ExtendedProperties["remoting.published"]))&lt;br /&gt;          {&lt;br /&gt;              string uri = (string) model.ExtendedProperties["remoting.uri"];&lt;br /&gt;&lt;br /&gt;             &lt;span style="font-weight: bold;"&gt;// key logic is here&lt;/span&gt;&lt;br /&gt;              RemotingServices.Marshal(mbr, uri, model.Service);&lt;br /&gt;           &lt;br /&gt;              model.ExtendedProperties["remoting.published"] = true;&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So with RemotingService.Marshal(object, uri ) is the key here it takes an already intialized class and makes it "remote" and available as a service to another client somewhere else.  So much more flexible!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-7860309207411995592?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/7860309207411995592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=7860309207411995592' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/7860309207411995592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/7860309207411995592'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2009/01/remoting-objects-yes-i-know-its-not.html' title='Remoting objects (yes I know it&apos;s not 2001) without using the MSDN Way'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-1956258910926182314</id><published>2008-12-29T21:04:00.004-06:00</published><updated>2008-12-29T21:10:48.600-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google App Engine'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Unit testing Google App Engine</title><content type='html'>Was having a massive pain with unit testing with my test development work..well nose plugin and blogging to the &lt;a href="http://www.cuberick.com/2008/11/unit-test-your-google-app-engine-models.html"&gt;rescue&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Will hopefully start making faster progress (code, develop, run test manually, is slower now than tdd).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-1956258910926182314?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/1956258910926182314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=1956258910926182314' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/1956258910926182314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/1956258910926182314'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2008/12/unit-testing-google-app-engine.html' title='Unit testing Google App Engine'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-4883174068105814412</id><published>2008-12-28T21:20:00.004-06:00</published><updated>2008-12-29T21:11:07.507-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google App Engine'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Google App Engine</title><content type='html'>Been playing with this lately. The framework Google provides to access their app engine service is written in python and largely Django from what I can see.&lt;br /&gt;&lt;br /&gt;You can supposedly run whatever you want on top of it that uses WSGI with some modifications.&lt;br /&gt;&lt;br /&gt;I think I may give this pylons a try at the same time with &lt;a href="http://code.google.com/p/appengine-monkey/wiki/Pylons"&gt;appengine-monkey&lt;/a&gt; . I fear that may be enough steps when using a new framework that idea may be doa but we'll see how much time I have over the next couple of days.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-4883174068105814412?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/4883174068105814412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=4883174068105814412' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/4883174068105814412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/4883174068105814412'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2008/12/google-app-engine.html' title='Google App Engine'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-1818426245405869124</id><published>2008-12-26T00:54:00.004-06:00</published><updated>2008-12-26T01:58:58.744-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sprocs'/><category scheme='http://www.blogger.com/atom/ns#' term='ORM'/><title type='text'>The great dead horse of ORM vs Sproc</title><content type='html'>I'm not the first to dive in this at all, but here is my pov.  I'm only mentioning this because I still see it cropping up a lot on various blogs and message boards as if there was an actual valid controversy.&lt;br /&gt;&lt;br /&gt;Let me recap the basic sides of the argument:&lt;br /&gt;&lt;br /&gt;ORM side&lt;br /&gt;&lt;ul&gt;&lt;li&gt;This is the haven of coders&lt;/li&gt;&lt;li&gt;Automatically creates your sql for you so you don't have to worry about handcrafting sql&lt;/li&gt;&lt;li&gt;uses normal source code so you get easy refactoring and source control&lt;/li&gt;&lt;/ul&gt;Sproc side&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Position of pretty much all DBA's, some coders typically from a more traditional development software development model.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Been recommended model for development for a couple of decades (since stored procs came into existence )&lt;/li&gt;&lt;li&gt;Optimal performance&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Now with those points in place if you were a neutral observer (which is a mythical creature on this subject), you would think i'd come out on the side of sprocs with the benefits in performance and it's proven history...and you'd be wrong.&lt;br /&gt;&lt;br /&gt;The above is how I'd say a majority of people I've talked to involved in software see things, but reality is I'd put refactoring and source control as being OVERWHELMINGLY important and performance as being secondary and rarely your limiter.&lt;br /&gt;&lt;br /&gt;Finally,  I think it's intellectually lazy to just go with what's "been done in the past" regardless of existing realities and what changes today brings.&lt;br /&gt;&lt;br /&gt;So lets go blow by blow:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Source Control&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Without source control we're left never making changes unless we absolutely have to.  This has subtle awful effects on software being reused and growing to match what end users want and need to use. &lt;br /&gt;&lt;br /&gt;Source control is one tool that helps software change be safe and thoughtfully done.  Sprocs while you can keep the scripts in source control to make or alter the sprocs, this means the dba or whoever is editing them has to be manually disciplined or a third party utility has to make the process seamless. &lt;br /&gt;&lt;br /&gt;In my experience this does not work without constantly standing on someones head (including your own) that you always check in sproc changes.  In the end, everyone is reluctant to change the application.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Refactoring&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So lets say a customer or end user comes to you and requests a simple name change of a column in the database.  There may be many reasons for this, sometimes it's for a report, sometimes its compliance with a regulation, sometimes it's someone with power who is whim driven.  Regardless you now have several ways of dealing with this. &lt;br /&gt;&lt;br /&gt;With the orm approach, you renamed the property in your orm class and since most IDE's have integrated mass rename where all references are updated in one click, all you're left with is renaming the table column (or just mapping the new column name in your orm class).&lt;br /&gt;&lt;br /&gt;With sprocs you're in a whole different world.  Now there is no auto-renaming tool I'm aware of for sql servers (Redgate may have something expensive) and then I doubt there is one for mysql, mssql, db2, etc.  So not only do you to renamed code that you've got to change and test your udf's now that may depend on that column name.&lt;br /&gt;&lt;br /&gt;In some cases this could be very quick, but in some practical cases I've worked with this just leads to no one being willing to enact such a change or they just cheat the system a bit and only rename the property or column in one place that makes it appear it was changed.&lt;br /&gt;&lt;br /&gt;Things get worse as the issues become more complex however I'll assume  you get the idea, again this leads to being reluctant to change the application.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Performance&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Performance is nice, but if you REALLY need it, sprocs will not be what makes the difference.  I say this with a couple of caveats, depending on your ORM library bulk updates, deletes, and inserts are going to be slow..very slow, but they have to be REALLY bulk.  Otherwise scalability in the truest sense is gotten by application design thought through at a systems point of view using messaging systems and growing horizontally. &lt;br /&gt;&lt;br /&gt;Lets say sprocs were somehow 25% more performant  than hand sql/orm, they're not, but if they were imagine say you had an widget seller app that could process 700 transactions a second.&lt;br /&gt;&lt;br /&gt;The widget seller company comes out with a buy one get one free coupon, now transactions are regularly over 100,000 a second.  If you were using sprocs or not, you're done for.  &lt;br /&gt;&lt;br /&gt;However, if you've written an app that uses a messaging protocol and can be spread out over multiple datasources (or even one datasource that's clustered), with several web servers and several middle ware servers...you maybe actually able to scale to that 100,000 a second transactions regardless of if you use sprocs or not.&lt;br /&gt;&lt;br /&gt;Scaling out and the use of asynchronous transactions are the actual key way to achieve scalability...everything else is a fake wedge issue.&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Most Importantly&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Generally speaking anything that gets in the way of giving the customer what they want is very very bad.  It leads to applications getting scrapped repeatedly because either the customer has replaced you.&lt;br /&gt;&lt;br /&gt;If you're lucky, you've convinced them that yet again they're wrong and did not properly know at the very beginning exactly what they wanted, please deposit another 40k in development to generate the app you desire...this time it'll be perfect we  promise.  &lt;br /&gt;&lt;br /&gt;Heavy use of sprocs are hard to justify when it comes to the maintenance side of things.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Summary&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Ultimately I think this does come down to a real valid pull between what dba's have been taught is there job and what agile developers needs are.  With the proliferation of agile growing daily (and I'm certain the quality of the agile attempts decreasing as it becomes more and more "the thing to do") it's natural and logical to see this red herring happen over and over again.&lt;br /&gt;&lt;br /&gt;Are there other things to consider in this argument? Oh definitely but I've yet to find anything that tops maintainability and adaptability as key reasons to avoid sprocs.  &lt;br /&gt;&lt;br /&gt;This argument I'm certain will continue indefinitely, and I'll in the near future have to call some 2000 line business logic heavy stored proc that takes 10 minutes to read and then setup on a test database to make sure i'm understanding what my changes will do, but I'll go out of my way to document and then see if i can move it all to unit tested, source controlled, good old boring bog standard code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-1818426245405869124?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/1818426245405869124/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=1818426245405869124' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/1818426245405869124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/1818426245405869124'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2008/12/great-dead-horse-of-orm-vs-sproc.html' title='The great dead horse of ORM vs Sproc'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-7130222186648680394</id><published>2008-12-21T13:31:00.004-06:00</published><updated>2008-12-21T15:26:39.577-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snake-guice'/><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Snake Guice</title><content type='html'>So I was looking at making my own IoC container in python using inspiration from &lt;a href="http://ayende.com/Blog/archive/2007/10/20/Building-an-IoC-container-in-15-lines-of-code.aspx"&gt;Ayende's post&lt;/a&gt; on rolling your own IoC in a pinch (though I may run into this again when I start playing with ruby) and I came up what I thought would be an ingenious idea to use decorators on methods and classes to do type resolution.&lt;br /&gt;Something like so:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class Foo(object):&lt;br /&gt;&lt;br /&gt;@ioc(booable = ghost, mooable = cow)&lt;br /&gt;def __init__(self, booable, moooable):&lt;br /&gt;     self.boo  = boo&lt;br /&gt;     self.moo = moo&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I'm sure it wouldn't be popular with your average python dev, but I again really want autowiring of dependencies, and didn't want to make a bunch of factory classes to tie together a bunch of related dependency chains.&lt;br /&gt;&lt;br /&gt;Well someone already went with that idea with &lt;a href="http://code.google.com/p/snake-guice/"&gt;snake-guice&lt;/a&gt; an IoC container inspiried by google guice which is written in java and makes heavy use of annotations the python equivalent of decorators and not concidentally my inspiration for my attempt at an IoC container.&lt;br /&gt;&lt;br /&gt;I'll update with more information later as I get to play with snake-guice if I can grok the concepts and code, perhaps I'll dare venture into OSS and see if I can help contribute.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-7130222186648680394?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/7130222186648680394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=7130222186648680394' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/7130222186648680394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/7130222186648680394'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2008/12/snake-guice.html' title='Snake Guice'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-1151955296867845217</id><published>2008-12-14T17:40:00.004-06:00</published><updated>2008-12-14T18:14:47.212-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='dynamic languages'/><title type='text'>IoC in ruby, python and lack of autowiring</title><content type='html'>In my &lt;a href="http://ryansvihla.blogspot.com/2008/12/ioc-and-dependecy-injection.html"&gt;last post&lt;/a&gt; I waxed joyously about my love of IoC containers which are third party libs that track all my dependencies. &lt;br /&gt;&lt;br /&gt;Now I've been trying to play around with Python and a bit of Ruby lately, and while I just adore the lack of getting decoupling for free (duck-typing gives you this), I enjoy the lack of compiling and I enjoy getting to have a fresh look as a programmer at languages I used to use as an admin for simple scripts.&lt;br /&gt;&lt;br /&gt;However, the love fest and productivity ends when I realize I've lost my beloved auto-wiring of dependency management I get with things like Castle Windsor. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Most of the ruby and python IoC containers I found were no longer in active development and were started back when IoC was taking off in Java back in 2004 or so, namely Needle, Copland and py-container.&lt;br /&gt;&lt;br /&gt;So I've looked at &lt;a href="http://springpython.webfactional.com/"&gt;Spring Python&lt;/a&gt; which is active, looks nice and all, but I have to explicitly map components myself. You do get Aspects, service location, and some framework helpers like security, and transaction managment, but without auto-wiring .....  I have to be honest may not be worth it to me at all in a dynamic language.&lt;br /&gt;&lt;br /&gt;So this leaves me in a bind. I've been convinced that dynamic languages are the future, staticly compiled languages keep moving that way, but now that i've learned all these awful tricks  to make static languages more flexible, and in the meantime found the joy of IoC autowiring....seems like I'm stuck being most productive still in statically compiled languages.&lt;br /&gt;&lt;br /&gt;The only alternative I forsee right now if I keep developing in Ruby or Python is build alot of factory classes to tie together large junks of dependency injected code.&lt;br /&gt;&lt;br /&gt;Hopefully, I can find an autowiring IoC container for one of my dynamic languages of choice but I dont see how easy it'll be.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-1151955296867845217?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/1151955296867845217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=1151955296867845217' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/1151955296867845217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/1151955296867845217'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2008/12/ioc-in-ruby-python-and-lack-of.html' title='IoC in ruby, python and lack of autowiring'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-968053785458803650</id><published>2008-12-14T09:55:00.004-06:00</published><updated>2008-12-21T13:55:16.997-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>IoC and Dependecy Injection</title><content type='html'>IoC (Inversion Of Control) is one of many programming concepts that when I was first approached with it I wondered why on earth anyone would have need of such and thing and now I can't imagine a world without it.&lt;br /&gt;&lt;br /&gt;The 10,000 foot simple view of it goes something like this:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Anything in your code that requires a resource or code from somewhere else is a "dependency". Examples: database access, another class that provides a method call or service,a web service, etc, etc.&lt;/li&gt;&lt;li&gt;Give all your dependencies an interface or an abstract underclass.  have all of your code depend on these instead.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Make all your dependencies  come into your class via the constructor, a method parameter, or a setter property. Your end goal is to never have "new" called on anything unless you're working with a class that only contains data . Also using static methods to get around new is cheating and still hard coding a dependency.&lt;/li&gt;&lt;li&gt;Use a third party solution or wire up your own IoC container, that looks at all your dependencies and plays match maker (oh this class needs widget a,b, and c , let me call new widget a, b,c, and add them to this class when called). This replaces all your "Factory" style classes.&lt;/li&gt;&lt;/ol&gt;Short example of this in code is as follows:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public interface DrawWidget{&lt;br /&gt;&lt;br /&gt;void Draw();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class ColorWidget: DrawWidget&lt;br /&gt;{&lt;br /&gt;  public ColorWidget()&lt;br /&gt;{&lt;br /&gt;  //imagine this connects and initializes connection to printer&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt; public void Draw()&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;  // imagine color widget active code here&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;public interface WidgetData&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;  public string[] GetStrings();&lt;br /&gt;}&lt;br /&gt;public class WidgetDb : WidgetData&lt;br /&gt;{&lt;br /&gt; public WidgetDB()&lt;br /&gt;{&lt;br /&gt;// imagine this sets up connections strings and makes db connection.&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;  public string[] GetStrings()&lt;br /&gt; {&lt;br /&gt;     //imagine db code here&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;traditional approach:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public class WidgetCombiner&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;public CombinedWidget WidgetPayload()&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;WidgetPayLoad payload = new WidgetPayload();&lt;br /&gt;  payload.Draw = new ColorWidget();//connection to printer must be alive&lt;br /&gt;  payload.Data = new WidgetDb(); //connection to db must be alive&lt;br /&gt;&lt;br /&gt;  return payload;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Dependency Injection Approach&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public class WidgetCombiner{&lt;br /&gt;&lt;br /&gt;private DrawWidget draw;&lt;br /&gt;private WidgetData data;&lt;br /&gt;&lt;br /&gt;public WidgetCombiner( DrawWidget draw, WidgetData data)&lt;br /&gt;{&lt;br /&gt; this.draw = draw;&lt;br /&gt; this.data = data;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public CombinedWidget WidgetPayload()&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;  WidgetPayLoad payload = new WidgetPayload();&lt;br /&gt;  payload.Draw = this.draw;&lt;br /&gt;  payload.Data = this.data;&lt;br /&gt;&lt;br /&gt;  return payload;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The key difference is WidgetCombiner in the first "traditional" implementation it depends on the printer being live and the database connection functioning.  The second implementation does not care at all, it's dependency is dynamic and easily changed to another database, another printer, or just a fake test environment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-968053785458803650?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/968053785458803650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=968053785458803650' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/968053785458803650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/968053785458803650'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2008/12/ioc-and-dependecy-injection.html' title='IoC and Dependecy Injection'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-8137970890768412484</id><published>2008-12-04T13:05:00.003-06:00</published><updated>2008-12-04T13:39:28.884-06:00</updated><title type='text'>YAGNI and when</title><content type='html'>I struggle with YAGNI frequently (You Ain't Gonna Need It).  But, recently I had some success with just being draconian about.  Not adding features unless I could justifiably say "this is adding value X for Y need".&lt;br /&gt;&lt;br /&gt;Today, another developer I was working with gave me a bit of a conundrum. We were expecting one of two values from a column in a database (Say "S" and "E"). However, in very very rare cases we could get another couple of different values (Say "X" and "C").  They would likely never come up into our code, and if they did, the rest of the corresponding data would be completely incorrect, and the data would go through the normal paths of incorrect data.&lt;br /&gt;&lt;br /&gt;So in this case, should I adjust the code to handle extreme corner cases, that don't effect the actual outcome of the application, but could give some fidelity into logging if an "X" or a "C" actually showed up?&lt;br /&gt;&lt;br /&gt;I think YAGNI in this case is telling me not to worry about the C and the X, as they don't actually effect the end result and we have no need for that level of logging fidelity at this time(and changing the where block to exclude the bad possibilities should be enough).  But it did give me pause to just leave those corner cases floating out there untouched.  &lt;br /&gt;&lt;br /&gt;It made me think a bit how in reality a YAGNI style approach probably helped contribute to the justification of y2k problems, and to a degree this was the same issue (which was this other developers contention).  &lt;br /&gt;&lt;br /&gt;However, I'm pretty certain with modern languages and patterns one could stick to YAGNI and avoid a y2k style mess.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-8137970890768412484?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/8137970890768412484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=8137970890768412484' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/8137970890768412484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/8137970890768412484'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2008/12/yagni-and-when.html' title='YAGNI and when'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-4941353542232185944</id><published>2008-12-02T23:07:00.003-06:00</published><updated>2008-12-02T23:20:57.926-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mako'/><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='Kid'/><category scheme='http://www.blogger.com/atom/ns#' term='Pylons'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='turbogears'/><title type='text'>Mako Templates</title><content type='html'>Ok so tired of the goofy stuff with Kid even though I did find out a way to debug templates but I was still upset enough that I wanted to go away from an XML based template engine entirely.&lt;br /&gt;&lt;br /&gt;Enter Mako.  Mako is newish but the preferred engine of Pylons and it works on Turbogears as well.  Instead of being xml based it's a run of the mill view engine using python as it's scripting language.  This struck me as the easiest and most straight forward for my skill set(especially since I use the pythonic Brail in Monorail).&lt;br /&gt;&lt;br /&gt;Turbogears and Mako integration take some hunting. I had to resort to just giving it a stab how I wanted it to work, googling my errors, and then bit by bit piecing together the sections of configuration i needed.&lt;br /&gt;&lt;br /&gt;Finally I groked the concept thanks to Wesley Chun the author of Core Python Programming  who'd run into a &lt;a href="http://markmail.org/message/74kyntsn7piaf424"&gt;similar conundrum &lt;/a&gt;(at least it makes me feel less stupid) .&lt;br /&gt;&lt;br /&gt;Key excerpt here:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;2. another problem that people have is that in your controller, your @expose decorator call tends to have more of a "full-path" to the template when porting from Kid, i.e.,&lt;br /&gt;&lt;br /&gt;@expose(template="tghello.templates.hello") def hello(self): :&lt;br /&gt;&lt;br /&gt;when switching to Mako, because of your mako.directories list, you no longer have to give the entire path, meaning that the failures are happening because it's trying to find that full name as a template file name, which isn't going to work.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Finally, played with this briefly feel much more at home with this templating style.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-4941353542232185944?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/4941353542232185944/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=4941353542232185944' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/4941353542232185944'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/4941353542232185944'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2008/12/mako-templates.html' title='Mako Templates'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-7112193148632410817</id><published>2008-12-02T20:29:00.004-06:00</published><updated>2008-12-02T21:28:12.836-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nhibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveRecord'/><category scheme='http://www.blogger.com/atom/ns#' term='Castle'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Castle Active Record and ActiveRecordMediator</title><content type='html'>the ActiveRecord pattern as it's typically implemented works like so.&lt;br /&gt;step 1 - Take a base class with all the persistence methods you need (save, update, delete, find, etc)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public class ActiveRecordBase{&lt;br /&gt;&lt;br /&gt;public static object Find(ICriteria criteria)&lt;br /&gt;{&lt;br /&gt;//return object&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;public void Save()&lt;br /&gt;{&lt;br /&gt;//save object to db here&lt;br /&gt;}&lt;br /&gt;// rest hidden&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;step 2 - take all your db classes and have them inherit from them (optionally passing on column configuration or whatever you'll make available).&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public class Account : ActiveRecordBase&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;public int Id{get;set;}&lt;br /&gt;public string Name{get;set;}&lt;br /&gt;public AcctType Type {get;set;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;client code ends up looking like so&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;public void static Main(string[] args)&lt;br /&gt;{&lt;br /&gt;Account acct = new Account();&lt;br /&gt;acct.Name = "Max Earnings";&lt;br /&gt;acct.AcctType = AcctType.Checking;&lt;br /&gt;acct.Save()&lt;br /&gt;&lt;br /&gt;Account[] acctsfromdb = Account.FindAll();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now alot of people like this pattern. They'll attach behavior or methods to the properties or even add their services to the same class (in the above example maybe adding a method that calculates current interest rate against a lookup table).&lt;br /&gt;&lt;br /&gt;I however have always had issues with unit testing this way. You end up testing against a database directly (which is substantially slower), and your class becomes decorated with all these persistence methods. Plus I've never personally enjoyed mixing data classes and method classes (called services in Domain Driven Design), this confuses the picture for me and muddies things up (what do you do when you have an interaction between multiple classes for example?)&lt;br /&gt;&lt;br /&gt;So how do you get the simplicity of db access with ActiveRecord but not have to worry about having database tied classes?  Well you can use an orm that's persistent ignorant like Nhibernate (or several others), which involves alot of by hand configuration (I say this watching the &lt;a href="http://code.google.com/p/fluent-nhibernate/"&gt;fluent nhibernate project&lt;/a&gt; closely), session, transaction handling, and generally gives you more control than you need for alot of starting projects.  If only you could find a nice middle ground.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Enter Castle ActiveRecord and ActiveRecordMediator class.  ActiveRecordMediator is NHibernate for dummies (or lazys).  So back to our earlier example&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[ActiveRecord]&lt;br /&gt;public class Account&lt;br /&gt;{&lt;br /&gt;[Property]&lt;br /&gt;public int Id{get;set;}&lt;br /&gt;&lt;br /&gt;[Property]&lt;br /&gt;public string Name{get;set;}&lt;br /&gt;&lt;br /&gt;[Property]&lt;br /&gt;public AcctType Type {get;set;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;now client code looks like so&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public static void Main(string[] args){&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Account acct = new Account();&lt;br /&gt;acct.Name = "Max Earnings";&lt;br /&gt;acct.AcctType = AcctType.Checking;&lt;br /&gt;ActiveRecordMediator&amp;lt;account&amp;gt;.Save(acct)&lt;br /&gt;&lt;br /&gt;Account[] acctsfromdb = ActiveRecordMediator&amp;lt;account&amp;gt;.FindAll();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So recap the difference in code is small. Lines of code is about the same..but now I can decouple the use of my objects away from database...but HOW you ask?&lt;br /&gt;&lt;br /&gt;Ahh yes let me carry you that last step.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public interface IRepository&amp;lt;T&amp;gt;{&lt;br /&gt;&lt;br /&gt;public void Save(T t);&lt;br /&gt;public T[] FindAll();&lt;br /&gt;public void Update(T t);&lt;br /&gt;//etc etc&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;public class DbRepsository&amp;lt;T&amp;gt;:IRepository&amp;lt;T&amp;gt;where T : class&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;public void Save(T t){&lt;br /&gt;&lt;br /&gt;ActiveRecordMediator&amp;lt;T&amp;gt;.Save(t);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public T[] FindAll()&lt;br /&gt;{&lt;br /&gt; var records = ActiveRecordMediator&amp;lt;T&amp;gt;.FindAll();&lt;br /&gt; return records;&lt;br /&gt;}&lt;br /&gt;//etc, etc&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;public class Client{&lt;br /&gt;private IRepository&amp;lt;Account&amp;gt; _db;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public Client(IRepository&amp;lt;Account&amp;gt;() db)&lt;br /&gt;{&lt;br /&gt;_db = db&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public void AddAccount(Account acct)&lt;br /&gt;{&lt;br /&gt;_db.Save(acct);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class FakeDb&amp;lt;T&amp;gt;:IRepository&amp;lt;T&amp;gt; where T : class&lt;br /&gt;{&lt;br /&gt;private List&amp;lt;T&amp;gt; records = new List&amp;lt;T&amp;gt;();&lt;br /&gt;&lt;br /&gt;public void Save(T t){&lt;br /&gt; records.Add(t);&lt;br /&gt;}&lt;br /&gt;public T[] FindAll(){&lt;br /&gt;return records.ToArray();&lt;br /&gt;}&lt;br /&gt;//etc etc&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;[TestFixture]&lt;br /&gt;public class TestClientCode{&lt;br /&gt;&lt;br /&gt;[Test]&lt;br /&gt;public void should_save_record_to_repository(){&lt;br /&gt;&lt;br /&gt;var memdb = new FakeDb&amp;lt;Account&amp;gt;();&lt;br /&gt;var client = new Client(memdb);&lt;br /&gt;Account acct = new Account();&lt;br /&gt;acct.Name = "Max Earnings";&lt;br /&gt;acct.AcctType = AcctType.Checking;&lt;br /&gt;&lt;br /&gt;client.Save(acct);&lt;br /&gt;&lt;br /&gt;var fromdb = memdb.FindAll();&lt;br /&gt;Assert.AreEqual(1,fromdb.Length);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Final Recap if you look at the test we can now easily write unit tests (with no db to worry about).  With the simple example provided here there isn't much obvious gain, but start adding your persistence classes to controllers, services and any other usage you can think of and this pays back the initial work we did here 10 fold.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-7112193148632410817?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/7112193148632410817/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=7112193148632410817' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/7112193148632410817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/7112193148632410817'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2008/12/castle-active-record-and.html' title='Castle Active Record and ActiveRecordMediator'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-2495218940815776377</id><published>2008-12-01T21:44:00.004-06:00</published><updated>2008-12-01T22:16:05.520-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='turbogears'/><title type='text'>Issues with Kid templating</title><content type='html'>Was working on my little Turbogears app I'm building and ran into some issues with the Kid template system that's default with turbogears 1.0.&lt;br /&gt;&lt;br /&gt;Now I've wasted several hours just messing around with master and layout files.  I can build my own master file and have it work quite well, but no one wants to see my websites so I grabbed a template off OSWD and it was even in strict xhtml.&lt;br /&gt;&lt;br /&gt;First, I try the master approach.  This is to me a pretty noisy process (have to specify match parameters in html, head, and what i want to be the content area, i learned through trial and error this does not seem to be optional) but at least it looks like a complete xhtml file to a web designer.&lt;br /&gt;&lt;br /&gt;Now the specific pages just need a py:extends="'sitemaster'" attribute in the html tag and boom....it blows up with an odd error (&lt;pre id="traceback"&gt;Template file "'sitemaster.kid'" not found&lt;br /&gt;while processing layout="'sitemaster.kid'"&lt;br /&gt;&lt;/pre&gt;.&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;I dive into the &lt;a href="http://www.kid-templating.org/language.html"&gt;kid language specification&lt;/a&gt; and find the py:layout="'sitemaster'"  option. this looks much better. far less noise and at least somewhat closer to what you'd find in NVelocity or Brail.&lt;br /&gt;However in the end once I've made the same changes, done a test case that works with some hand thrown together html. When trying to load up my 3rd party template it blows up with same odd error.&lt;br /&gt;&lt;br /&gt;Long story short, I narrowed enough down to find there is something in an WC3 xhtml strict compliant doc that throws the kid parser for a loop.  I can delete all the html in the body and it works.&lt;br /&gt;&lt;br /&gt;I believe the way kid ends up approaching things is ultimately to blame here, and I'd have to change the template output to strict xhtml or something to get this all to work..but ultimately I shouldn't have to think about this at all.&lt;br /&gt;&lt;br /&gt;It is my belief that view engines should stay out of the way of the html entirely, they shouldnt barf on it, and if they do they should tell you what element is causing you the problem, or where the parser gives up at the horrible mess you've sent it.&lt;br /&gt;&lt;br /&gt;I get that Kid is trying really hard to make a designer friendly view engine, but in this instance if I were working with a designer and we got this error when he made an html change..and he actually did it 3 days ago, and he did a bunch more changes since...we'd be struggling for hours to figure out what was the offending piece of html he added.&lt;br /&gt;&lt;br /&gt;Now I'm sure experienced users of Kid would chastise me, and that I'm supposed to learn all the ins and outs and then it'll all be worth it (it may very well be, but I'm not convinced yet).&lt;br /&gt;&lt;br /&gt;I had a look at genshi and it looks like the same model but better in some ways (extension is .html..this alone makes it worthwhile for dealing with skiddish designers).  Maybe it'll tell me where this html blows up...regardless I'll say it again..view engines should not care what html I throw it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-2495218940815776377?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/2495218940815776377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=2495218940815776377' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/2495218940815776377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/2495218940815776377'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2008/12/issues-with-kid-templating.html' title='Issues with Kid templating'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-158041137842147421</id><published>2008-11-30T13:46:00.004-06:00</published><updated>2008-11-30T14:03:40.634-06:00</updated><title type='text'>Turbogears, Pylons, and Django</title><content type='html'>Been wanting to do some high productivity oss work at home lately. At first I was gonna write something in rails, but being as I have a  bit more experience in python that Ruby, I decided to give the Python MVC frameworks a look.&lt;br /&gt;&lt;br /&gt;From what I can see so far from my research and a few hours coding in django and turbogears.&lt;br /&gt;&lt;br /&gt;TurboGears&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Middle of changeover in orm technologies preferences.  Version 1.0 prefers SQLObject, but has support for SQLAlchemy. 1.1 Beta has tigher integration with SQLAlchemy.&lt;/li&gt;&lt;li&gt;Horrid name, but seems like more classic MVC framework, has some convention of configuration out of the box.&lt;/li&gt;&lt;/ul&gt;Django&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Has great docs. Can find loads of tutorials for it.&lt;/li&gt;&lt;li&gt;When I used it seemed I had to do a lot of manual url configuration. I found this obnoxious.&lt;/li&gt;&lt;li&gt;Nice out of the box admin pages, that are easy to set up.  Some people find this gimmicky but I had little issue with it.&lt;/li&gt;&lt;/ul&gt;Pylons&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Have not had time to code with this but from the docs appears to be a pythonic rails (claims as such).&lt;/li&gt;&lt;li&gt;It's a bit new and docs struck me as a bit more lacking.&lt;/li&gt;&lt;li&gt;Has conflict with turbogears somehow.  Not enough of a python guru to figure this out.  Other people had same issue, had to run one or other on the install however.&lt;/li&gt;&lt;/ul&gt;Overall my impression of the python MVC trio here was solid.  It still does seem rails has convention over configuration down better, but I haven't used anything yet in any language that was as well thought out for "good defaults".  Turbogears in particular is still better than say Castle Monorail, but that has more to do with the differences between static compliation and dynamic (look at the differences in the Castle's Active Record and Rail's to see what I'm referring too).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-158041137842147421?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/158041137842147421/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=158041137842147421' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/158041137842147421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/158041137842147421'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2008/11/turbogears-pylons-and-django.html' title='Turbogears, Pylons, and Django'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-5376944760502016136</id><published>2008-10-23T20:56:00.008-05:00</published><updated>2009-03-30T07:52:02.251-05:00</updated><title type='text'>Why oh why streamreader</title><content type='html'>While I was going through some playing around with python i was really impressed with the following bit of functional joy.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;inList = open(fileLoc, 'rU').readlines();&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I was so happy to find that little tidbit and sad to not have used such a thing in C# ever.  I always used the awful:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;List&amp;lt;&lt;/span&gt;String&amp;gt; strings = new List&amp;lt;String&amp;gt;();&lt;br /&gt;using(StreamReader reader = new StreamReader(fileloc))&lt;br /&gt;{&lt;br /&gt;while(line = reader.ReadLine()) != null&lt;br /&gt;{&lt;br /&gt;strings.Add(line);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This is the type of code you see in MSDN and in various "Professional C# 2.0"  type books, they'll even show you TextReader to boot.  However for the vast majority of cases the least bug free and easy to use appears to be something I totally missed for the past couple of years:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;string[] readText = File.ReadAllLines(fileloc);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This has been around since .net 2.0, opens the file, reads it and closes it. At this point I'd argue that the shorter option should be shown primarily to newer students and the remaining features left in an appendix somewhere.&lt;br /&gt;&lt;br /&gt;EDIT:  Jon Skeet pointed out his simple class for doing the same above but with better performance.&lt;a href="http://csharpindepth.com/ViewChapterNotes.aspx?Chapter=6"&gt; http://csharpindepth.com/ViewChapterNotes.aspx?Chapter=6&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-5376944760502016136?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/5376944760502016136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=5376944760502016136' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/5376944760502016136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/5376944760502016136'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2008/10/why-oh-why-streamreader.html' title='Why oh why streamreader'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-3513547423005937249</id><published>2008-09-27T08:00:00.011-05:00</published><updated>2008-09-27T09:29:34.410-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><title type='text'>AOP:  what is it and why do I care</title><content type='html'>Aspect Oriented Programming or AOP. This is Yet Another Acronym (or YAA ) but for most people and most cases it's really just another recipe to solve problems in your programmer cookbook.   There are many resources out there on AOP on the web and I won't attempt to cover all details of AOP.&lt;br /&gt;&lt;br /&gt;For those new to the concept, AOP will be most clear to you through the lens of logging concerns.   How many of you have written or seen code like the following?:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;DoSomething action= new DoSomething();&lt;br /&gt;string result = action.Execute();&lt;br /&gt;Logger.Log("Info", result);&lt;br /&gt;&lt;/code&gt;Or even worse:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;DoSomething action = new DoSomething();&lt;br /&gt;Customer result = action.Execute();&lt;br /&gt;LogCustomer.Log(result.FullName, result.Address, result.Phone);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Only you see it every 3 lines and scattered everywhere, throughout the code base.  Do something as simple as changing logging framework, changing what you log or adjusting your static logging class can end up being a nightmare.  AOP attempts to solve this more cleverly by using a combination of rules called "pointcuts" to match what you log, and then executing functions called "advices" .&lt;br /&gt;&lt;br /&gt;The flexibility and implementation of pointcuts vary greatly from one AOP framework to another, so you'll have to consult your framework of choice's docs.  But I can give you an example using IoC container Castle Windsor:&lt;br /&gt;&lt;code&gt;1: WindsorContainer container  = new WindsorContainter();&lt;br /&gt;2: container.Register(AllTypes.Of&lt;icommand&gt;&lt;iloggable&gt;.FromAssembly&lt;br /&gt;(Assembly.GetExecutingAssembly()).Interceptors.Add(new InterceptorReference(typeof(LoggingAdvice))).Last));&lt;br /&gt;&lt;br /&gt;&lt;/iloggable&gt;&lt;/icommand&gt;&lt;/code&gt;Now lets recap what's going on here?  First line initializes the container, second line registers all classes that implement the ICommand interface in the currently running assembly, and then adds the LoggingAdvice.  You can change this to all classes, or only individual classes but that's an exercise I leave up to the reader.   Lets show the code now:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;public interface ICommand{&lt;br /&gt;string Execute(string sendString);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;public class Command: ICommand&lt;br /&gt;public string Execute(string sendString)&lt;br /&gt;{&lt;br /&gt;   string toconsole  = sendString + " this is from the console";&lt;br /&gt;   Console.WriteLine( toconsole);&lt;br /&gt;   string retvalue = sendString + " this is returned by the method";&lt;br /&gt;   return retvale;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;This is a simple enough class.  It writes the sent string to the console with some additional information, then returns the sent string with where it is in the Execute Method.&lt;br /&gt;&lt;br /&gt;And the LoggingAdvice is as follows:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;public class LoggingAdvice:IInterceptor&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;public void Intercept(IInvocation invocation)&lt;br /&gt;&lt;br /&gt;  {&lt;br /&gt;              invocation.Proceed();&lt;br /&gt;              Object argument = invocation.GetArgumentValue();&lt;br /&gt;              Console.WriteLine(argument.ToString() + " from LoggingAdvice" );&lt;br /&gt;              Object returnValue = invocation.ReturnValue;&lt;br /&gt;              Console.WriteLine(returnvalue.ToString() + " from LoggingAdvice" );&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;span codelanguage="CSharp"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;note the invocation.Proceed() method call.  This ends up having the "Advised" or "Intercepted" method execute then and there.  Then the invocation will be able to get the return value. This means you could move the proceed call to just before the ReturnValue call.&lt;br /&gt;&lt;br /&gt;Now client code would look something like so:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;class Program{&lt;br /&gt;&lt;br /&gt;static void Main(string[] args)&lt;br /&gt;&lt;br /&gt; {&lt;br /&gt;   WindsorContainer container = new WindsorContainer();&lt;br /&gt;   //add registration code from above here&lt;br /&gt;  ICommand cmd = container.Resolve&lt;icommand&gt;();&lt;br /&gt;  cmd.Execute(args[0]);&lt;br /&gt;}&lt;br /&gt;&lt;/icommand&gt;&lt;/code&gt;What's going on here?  Windsor retrieves an instance of ICommand which will give you the Command class. The Execute is called on the ICommand instance with the args from the command line passed in.  You'll find a result similiar to so when run from the command prompt:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;1: program.exe "doing stuff"&lt;br /&gt;2: doing stuff this is from console&lt;br /&gt;3: doing stuff from Logging Advice&lt;br /&gt;4: doing stuff this is returned from the method from Logging Advice&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Let's recap, our core code is making no direct calls to a logging class and it is not sprinkled all over our code. While in this trivial example the gains are not realized but anything larger than 300 lines of code we're going to see a benefit from using an AOP framework.&lt;br /&gt;&lt;br /&gt;In upcoming posts I'll cover other frameworks and more common uses of AOP.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-3513547423005937249?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/3513547423005937249/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=3513547423005937249' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/3513547423005937249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/3513547423005937249'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2008/09/aop-what-is-it-and-why-do-i-care.html' title='AOP:  what is it and why do I care'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201901477992407964.post-5541770063907965244</id><published>2008-09-23T22:35:00.005-05:00</published><updated>2008-09-23T23:26:57.841-05:00</updated><title type='text'>Quartz.Net and Castle.Scheduler for scheduled jobs</title><content type='html'>I've had the opportunity to work with both scheduler frameworks in the same project (ended up switching out Quartz.Net for Castle.Scheduler) and here is what I found.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://quartznet.sourceforge.net/"&gt;&lt;span style="font-weight: bold;"&gt;Quartz.Net&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Positives:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;CronTrigger alone is almost worth it. Anyone with a unix background (like me) finds this a big win.&lt;/li&gt;&lt;li&gt;Based on a very mature Java based project so in theory it's design is well tested.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Has support for supplying different Calendars (think holiday calendar, being loaded into a "job" so that it knows not to fire on your organizations particular holidays, this is nice to have in banking for example).&lt;/li&gt;&lt;li&gt;comes with command line client and service.  This wasn't out when I was using it and I had to implement my own versions.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Negatives:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Complete Seperation of Triggers (scheduling objects) and a "JobDetail" (think name, description, etc).  This in my experience lead to alot of confusion with developers and caused alot of inconsistency.  &lt;span style="font-weight: bold;"&gt;Example:&lt;/span&gt; When wanting to reschedule a job, you had to reschedule it by it's trigger name.  Which would cause problems if you had that trigger setup on more than one "JobDetail", and also would require you to find the trigger name of that job anyway.&lt;/li&gt;&lt;li&gt;A lot of string literals.  Just my personal take don't care for this.&lt;/li&gt;&lt;li&gt;Some incomplete implementations.  Example: when using 0.9.1 I had a dev who was stuck on why NextFireTime wasn't showing up on a Trigger.  Some things are just tagged as not implemented yet.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;MegaClasses.  Lots of methods, lots of noise. Again this is a port so it's not like Quartz.Net can vary too terribly much from Quartz.&lt;/li&gt;&lt;li&gt;Only one developer that I can see.  He works hard, pushes out releases frequently, but the Castle team is top notch and has many qualified contributors, it's not a fair comparison.&lt;/li&gt;&lt;li&gt;RamJobStore was solid, ADOJobstore was a bit flakey and didn't work nearly as well.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;a href="http://using.castleproject.org/display/Contrib/Castle.Components.Scheduler"&gt;&lt;span style="font-weight: bold;"&gt;Castle Scheduler&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Positives:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Leverages Castle Windsor.  If you use it already this is huge plus.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Simple small easily understandable classes.&lt;/li&gt;&lt;li&gt;JobSpec easy to understand and transparent to the junior devs.  Includes a trigger property so that there is only a 1 to 1 mapping between triggers and jobs.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;SqlJob store is well supported and works about as well as the InMemoryJobStore.&lt;/li&gt;&lt;li&gt;Out of the box clustering of schedulers using a db backend to track jobs between the schedulers.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Negatives:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;As most castle projects, may not be enough docs for less experienced devs unused to reading source code and unit tests.&lt;/li&gt;&lt;li&gt;Limited out of the box trigger support.  You'll have to implement your own triggers to get something outside of daily and interval executions.&lt;/li&gt;&lt;li&gt;You have to be comfortable builing Castle Trunk. This is a limiter to new users obviously.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Summary&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Both of them do the job if you need a job scheduler&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;.  &lt;/span&gt;&lt;/span&gt;If you already "speak Castle" and are comfortable with that tool chain then Castle.Scheduler is a much lower friction option.  If you don't already use Castle (which I love btw) , or you need complex scheduling then Quartz.Net may be more for you.  However,  fear the AdoJobStore and prepare to use another method to persist you jobs, if you find friction using it for higher performance scenarios.&lt;br /&gt;&lt;br /&gt;I'll try to make time showing the basic use of Castle.Scheduler not already covered in docs later in the week.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201901477992407964-5541770063907965244?l=ryansvihla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ryansvihla.blogspot.com/feeds/5541770063907965244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1201901477992407964&amp;postID=5541770063907965244' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/5541770063907965244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201901477992407964/posts/default/5541770063907965244'/><link rel='alternate' type='text/html' href='http://ryansvihla.blogspot.com/2008/09/quartznet-and-castlescheduler-for.html' title='Quartz.Net and Castle.Scheduler for scheduled jobs'/><author><name>Ryan Svihla</name><uri>http://www.blogger.com/profile/11881339526666128272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-D0_Ih-_6Ptc/Tn9dPTV_B9I/AAAAAAAAEgI/GHIJs01GedE/s1600/0438ccea75300839c59c11cc880ccf16.png'/></author><thr:total>1</thr:total></entry></feed>
