<?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-167738975296784101</id><updated>2011-12-02T08:04:55.058-08:00</updated><category term='linux'/><category term='AOP'/><category term='dependency injection'/><category term='open source software'/><category term='enlightenment'/><category term='Computer Science'/><category term='MSpec'/><category term='Unit Test'/><category term='mock'/><category term='Context/Specification'/><category term='Aspect Oriented Programming'/><category term='Java'/><category term='modular code'/><category term='OSS'/><category term='Refactor'/><category term='mvc'/><category term='C#'/><category term='MongoDB'/><category term='xUnit'/><category term='outside-in development'/><category term='Hot Features'/><category term='TDD'/><category term='NOSQL'/><category term='Agile'/><category term='Ruby'/><category term='BDD'/><category term='design'/><category term='asp.net'/><category term='Behavior Driven Development'/><category term='Acceptance Test Driven Development'/><category term='Ubuntu'/><category term='Ruby on Rails'/><category term='Agile Development'/><category term='user story'/><category term='decorator pattern.'/><category term='build automation'/><category term='Dynamic Typing'/><category term='.NET'/><title type='text'>Simplicity Follows Complexity</title><subtitle type='html'>The infrequently chronicled travels of an agile software developer.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>30</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-8583963577082296088</id><published>2011-09-13T18:56:00.000-07:00</published><updated>2011-09-13T18:56:35.330-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agile Development'/><title type='text'>Stop thinking Agile, and start thinking agile</title><content type='html'>There's been plenty of sentiment about Agile (capital A as my buddy &lt;a href="http://www.blogger.com/profile/02256674537851424241"&gt;Ed&lt;/a&gt; pointed out to me) being dead or that it's a failure or that it's in some state of decay. &amp;nbsp;In a sense, I completely understand why people would think that. &amp;nbsp;It may also be some of what is holding back the free thinking in the process of software development. &amp;nbsp;There are few big, new ideas (outside of &lt;a href="http://en.wikipedia.org/wiki/Lean_software_development"&gt;lean &lt;/a&gt;but then that's not new) that are really providing direction for the software development process.&lt;br /&gt;&lt;br /&gt;From my point of view, this wound is self inflicted. &amp;nbsp;Agile has become the hammer to nail all process problems. &amp;nbsp;It was championed and supported by some really smart guys in the software dev space. &amp;nbsp;Popularity grew, Agile become all the rage and, as all fads in the space, it became a personal point of pride to declare that you or your company "went Agile". &amp;nbsp;There were books written about it that contained all the activities and routines you must partake in in order to be considered Agile. &amp;nbsp;Training classes and certifications inevitably popped up that claimed that with 3 days of training you too could be a scrum master and Agile wizard. &amp;nbsp;Before anyone knew it, Agile was a defined creature with a strict set of rules&amp;nbsp;(standup meetings in the AM, planning poker, TDD, pair programming, retrospectives, etc.). &amp;nbsp;It was no longer the organic process that it was supposed to be.&lt;br /&gt;&lt;br /&gt;I certainly wasn't there in the early days of Agile but my company did "go Agile" almost 3 years ago. &amp;nbsp;With it, I've found some fantastic practices that are now part of my software development &lt;a href="http://www.youtube.com/watch?v=pBK8hBG0ozA"&gt;six-demon bag&lt;/a&gt; and I've chronicled many of them on this blog. &amp;nbsp;It's truly been a great addition to my craft and I would certainly advocate others to try it as well. &amp;nbsp;GO AGILE! &amp;nbsp;You may thank me later.&lt;br /&gt;&lt;br /&gt;So what's the problem here? &amp;nbsp;I just said Agile prevents free thinking but then I advocate that you try it. &amp;nbsp;The problem isn't the Agile movement, it's how it is adopted. &amp;nbsp;People want to add it to their process without appreciating where it came from and why your company should care to use it. &amp;nbsp;It's the same behavior I allude to in my "&lt;a href="http://complextosimple.blogspot.com/2011/06/goal.html"&gt;The Goal&lt;/a&gt;" entry. &amp;nbsp;Blind adoption of the Agile process isn't going to be to your benefit.&lt;br /&gt;&lt;br /&gt;When I talk to people about a good software development practice, I no longer think in terms of the canonical Agile. &amp;nbsp;Every company, every product, every team have their own unique environment and set of problems. &amp;nbsp;It would be a mistake to not take those things into account before you start throwing the Agile bible at everyone. &amp;nbsp;&amp;nbsp;My goal is to streamline the process and use the best tools I can to reach the coveted hyper productivity. &amp;nbsp;&amp;nbsp;Agile is comprised of many different practices and procedures. &amp;nbsp;Take what you need from it and recognize what works best for you.&lt;br /&gt;&lt;br /&gt;Remember, Agile wasn't created from thin air. &amp;nbsp;It was coined by a bunch of guys that saw waste, friction and deficiencies in the process. &amp;nbsp;This is not uncommon to any of us. &amp;nbsp;These are things we all see in our days, isn't it? "Wow, that meeting was useless." &amp;nbsp;"The number of regressions grows on each release!" &amp;nbsp;"We build what they ask for but then they never like it!" &amp;nbsp;"These manual deployments take hours and they're error prone!"&lt;br /&gt;&lt;br /&gt;LISTEN to those thoughts and react to them. &amp;nbsp;As a developer I know how easy it is to identify what is going wrong and grouse about it. &amp;nbsp;It feels great to vent. &amp;nbsp;If I asked you what pissed you off, you'd ramble about it for hours, eventually repeating yourself but then you'd dive back into it anyways because you're that passionate about it. &amp;nbsp;Take that energy and think of &lt;i&gt;how&lt;/i&gt;&amp;nbsp;you would fix things. &amp;nbsp;If that meeting was useless, how would you make it better? &amp;nbsp;Should you even have been there? &amp;nbsp;Were there too many people talking at once? &amp;nbsp;Was there one loudmouth that dominated the whole discussion? &lt;br /&gt;&lt;br /&gt;Don't accept this reality. &amp;nbsp;Change it. &amp;nbsp;Make it better. &amp;nbsp;Be organic in your process. &amp;nbsp;Evolve. &amp;nbsp;Mature. &amp;nbsp;You don't need a certification to understand where things are going wrong for you. &amp;nbsp;Fix it. &amp;nbsp;You have manual builds today. &amp;nbsp;Automate them tomorrow. &amp;nbsp;You have 6 month projects with unhappy customers. &amp;nbsp;Decompose them into 1 month deliverables to get quicker feedback. &amp;nbsp;You have too many bugs. &amp;nbsp;Increase test coverage and improve your QA. &amp;nbsp;You have a schizophrenic product organization that pulls you in 8 directions? &amp;nbsp;Stop the assembly line and demand consensus and priority.&lt;br /&gt;&lt;br /&gt;That's all Agile ever was.&lt;br /&gt;&lt;br /&gt;...but before you go, buy a book, ask questions on forums and learn about all the wonderful practices that fall under the Agile umbrella because we've learned a lot in the last decade about good processes.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-8583963577082296088?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/8583963577082296088/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=8583963577082296088' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/8583963577082296088'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/8583963577082296088'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2011/09/stop-thinking-agile-and-start-thinking.html' title='Stop thinking Agile, and start thinking agile'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-6074753463736738499</id><published>2011-07-31T18:28:00.000-07:00</published><updated>2011-07-31T19:52:39.700-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='modular code'/><title type='text'>From a Java/C# world to Ruby's: Writing modular code</title><content type='html'>For the past handful of months I've been dabbling in&amp;nbsp;&lt;a href="http://rubyonrails.org/"&gt;Rails&lt;/a&gt; in my free time to play with some projects. &amp;nbsp;It's a fun platform for creating applications and I (as has been mentioned) dig Ruby. &amp;nbsp;I'm starting to actually build up enough code to warrant a little more discipline than what I've had so far. &amp;nbsp;For the most part, I've been plowing through just trying to experience all the tools and tricks the platform has to offer. &amp;nbsp;I couldn't really be effective otherwise if I hadn't given myself any time to play in the sandbox.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One thing I'm trying to learn is how to modularize code in Ruby. &amp;nbsp;How and where do you draw lines of responsibilities? &amp;nbsp;Where should code live? &amp;nbsp;Should I use a module or should I use a class? &amp;nbsp;There hasn't been a straight forward answer. &amp;nbsp;Ruby being dynamic, open classes and being able to intercept/modify just about any behavior in the system...it feels like my first year away at college (well, not really but you catch my drift). &amp;nbsp;While it's a lot of fun, you have to make sure you don't run wild with your freedoms. &amp;nbsp;There's a limit and you have to govern yourself.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Again, where are the lines drawn? &amp;nbsp;What are the right things to do? &amp;nbsp;It's not apparent. &amp;nbsp;Look at &lt;a href="http://guides.rubyonrails.org/"&gt;models&lt;/a&gt; as they're known in Rails. &amp;nbsp;Models use the &lt;a href="http://en.wikipedia.org/wiki/Active_record_pattern"&gt;Active Record pattern&lt;/a&gt; where each instance constitutes a record in a persistent store. &amp;nbsp;So what is the typical Rails model responsible for? &amp;nbsp;Reading and writing itself from a persistent store at the least (along with any of its child models). &amp;nbsp;This alone will make members of the &lt;a href="http://abdullin.com/cqrs/"&gt;CQRS&amp;nbsp;Illuminati&lt;/a&gt;&amp;nbsp;grow faint. &amp;nbsp;But it doesn't stop there. &amp;nbsp;Also, you need to perform your validation there which makes sense for any stateful, data-driven creature to do. &amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;At first, I let everything pile into my models. &amp;nbsp;If I had 3 ways I wanted to query things from the DB? &amp;nbsp;Oh, hey, I need to query my associations too, what should I do with all that logic? &amp;nbsp;Put it in the model. &amp;nbsp;If I had extended validations dependent on certain conditions? &amp;nbsp;It undoubtedly went in the model. &amp;nbsp;If I add an authentication framework that needed to decorate the client classes? &amp;nbsp;Hey, I'll just add it to the model!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It &lt;i&gt;&lt;u&gt;never&lt;/u&gt;&lt;/i&gt;&amp;nbsp;felt right and as I piled more functionality on, things became especially itchy. &amp;nbsp;Instead of trying to foresee how this would all pan out and try to apply some half-brained pattern of my own, I just went for it and made things a sloppy mess. &amp;nbsp;I really wanted to see what the wrong way to do things was so then the answer would be more apparent. &amp;nbsp;Just like my early days when I realized how tests benefited my code, I could learn from it. &amp;nbsp;Why? &amp;nbsp;Because Ruby isn't Java or C# and I'm a Ruby part-timer. &amp;nbsp;I've seen and &lt;a href="http://fabiokung.com/2010/05/06/ruby-and-dependency-injection-in-a-dynamic-world/"&gt;read about&lt;/a&gt; trying to apply patterns from either of those languages that is inappropriate. &amp;nbsp;I decided to let mother nature dictate how I should proceed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the case of the rogue models, I found what makes me most comfortable. &amp;nbsp;First, anything related to the data and validation of a model stays in its class definition. &amp;nbsp;Second, any associations defined stay in the model's class definition. &amp;nbsp;Third, anything that demonstrates how that model behaves in its domain should stick around (if possible). &amp;nbsp;I want to be able to see and quickly digest what the model is and what it's related to. &amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Last, everything else, provided that its a significant amount of code, is placed into modules. &amp;nbsp;Modules allow me to create meaningful, cohesive groups of methods and constants. &amp;nbsp;For example, the code to query the DB (in any number of ways) is pulled out and placed in some sort of data access module. &amp;nbsp;Modules, while not being the same as classes, act very much like a class in most senses. &amp;nbsp;What I don't have a feel for is how many &lt;a href="http://www.ruby-doc.org/core/classes/Module.html#M000440"&gt;includes&lt;/a&gt; is too many includes. &amp;nbsp;The models get this very facade-like feeling. &amp;nbsp;They do a lot. &amp;nbsp;It's still something I haven't quite gotten used to yet. &amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, the short of the long, modules are nifty and I can draw parallels with how I used interfaces (and ultimately their implementations) in Java/C#. &amp;nbsp;It's the same song, just a different dance. &amp;nbsp;Use them to decompose the larger objects and group logically related functionality. &amp;nbsp;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-6074753463736738499?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/6074753463736738499/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=6074753463736738499' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/6074753463736738499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/6074753463736738499'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2011/07/from-javac-world-to-rubys-writing.html' title='From a Java/C# world to Ruby&apos;s: Writing modular code'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-6349630756293951574</id><published>2011-07-26T18:23:00.000-07:00</published><updated>2011-09-13T18:57:02.531-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MongoDB'/><title type='text'>MongoDB repair on bad shutdown</title><content type='html'>I've been working on a little side project and I've been using MongoDB. &amp;nbsp;One insanely annoying thing I've run into a couple times is if Mongo doesn't shutdown cleanly then you have to repair it. The next time you try to start it up you get errors. &amp;nbsp;You'd hope that these things would happen automagically but oh well...I'm just starting to learn it so I may be missing out on the larger reason. &lt;br /&gt;&lt;br /&gt;You may end up seeing something in the console like this when you try to connect to your local server,&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;:~$ mongo&lt;br /&gt;MongoDB shell version: 1.8.2&lt;br /&gt;connecting to: test&lt;br /&gt;Tue Jul 26 20:45:17 Error: couldn't connect to server 127.0.0.1 shell/mongo.js:79&lt;br /&gt;exception: connect failed&lt;/blockquote&gt;&lt;div&gt;or this (this one was just me putzing around trying to get it going),&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;:~$ sudo mongod&lt;br /&gt;mongod --help for help and startup options&lt;br /&gt;Tue Jul 26 20:47:35 [initandlisten] MongoDB starting : pid=3358 port=27017 dbpath=/data/db/ 32-bit&lt;br /&gt;** NOTE: when using MongoDB 32 bit, you are limited to about 2 gigabytes of data&lt;br /&gt;** &amp;nbsp; &amp;nbsp; &amp;nbsp; see http://blog.mongodb.org/post/137788967/32-bit-limitations&lt;br /&gt;** &amp;nbsp; &amp;nbsp; &amp;nbsp; with --dur, the limit is lower&lt;br /&gt;Tue Jul 26 20:47:35 [initandlisten] db version v1.8.2, pdfile version 4.5&lt;br /&gt;Tue Jul 26 20:47:35 [initandlisten] git version: 433bbaa14aaba6860da15bd4de8edf600f56501b&lt;br /&gt;Tue Jul 26 20:47:35 [initandlisten] build sys info: Linux bs-linux32.10gen.cc 2.6.21.7-2.fc8xen #1 SMP Fri Feb 15 12:39:36 EST 2008 i686 BOOST_LIB_VERSION=1_37&lt;br /&gt;Tue Jul 26 20:47:35 [initandlisten] exception in initAndListen std::exception: dbpath (/data/db/) does not exist, terminating&lt;br /&gt;Tue Jul 26 20:47:35 dbexit:&lt;br /&gt;Tue Jul 26 20:47:35 [initandlisten] shutdown: going to close listening sockets...&lt;br /&gt;Tue Jul 26 20:47:35 [initandlisten] shutdown: going to flush diaglog...&lt;br /&gt;Tue Jul 26 20:47:35 [initandlisten] shutdown: going to close sockets...&lt;br /&gt;Tue Jul 26 20:47:35 [initandlisten] shutdown: waiting for fs preallocator...&lt;br /&gt;Tue Jul 26 20:47:35 [initandlisten] shutdown: closing all files...&lt;br /&gt;Tue Jul 26 20:47:35 closeAllFiles() finished&lt;br /&gt;Tue Jul 26 20:47:35 dbexit: really exiting now&lt;/blockquote&gt;I found the answer in the comments of&amp;nbsp;&lt;a href="http://www.synchrosinteractive.com/blog/1-software/47-mongodb-repair-on-ubuntu"&gt;this blog&lt;/a&gt;. &amp;nbsp;Run the following commands and all will be well,&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;sudo rm /var/lib/mongodb/mongod.lock&lt;br /&gt;sudo chown -R mongodb:mongodb /var/lib/mongodb/&lt;br /&gt;sudo -u mongodb mongod -f /etc/mongodb.conf --repair&lt;br /&gt;sudo service mongodb start&lt;/blockquote&gt;&amp;nbsp;HUZZAH!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-6349630756293951574?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/6349630756293951574/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=6349630756293951574' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/6349630756293951574'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/6349630756293951574'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2011/07/mongodb-repair-on-bad-shutdown.html' title='MongoDB repair on bad shutdown'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-9067729329345219550</id><published>2011-06-20T21:15:00.000-07:00</published><updated>2011-10-07T06:04:33.465-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NOSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile Development'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><category scheme='http://www.blogger.com/atom/ns#' term='enlightenment'/><title type='text'>The Goal</title><content type='html'>The only right way to write code is to use TDD!&lt;br /&gt;&lt;br /&gt;Scrum should only take 5 minutes!!&lt;br /&gt;&lt;br /&gt;You should ALWAYS use DDD to develop your model!!!&lt;br /&gt;&lt;br /&gt;NOSQL is the only way! &amp;nbsp;Down with SQL!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;That's the sentiment you can find in a lot of arguments between developers. &amp;nbsp;It's too black and white, too absolute. &amp;nbsp;The issue is that the focus leaves the goal. &amp;nbsp;It artificially limits the solutions you can come up with.&lt;br /&gt;&lt;br /&gt;In the case of TDD, you can most certainly write code before tests. &amp;nbsp;What do &lt;b&gt;all&lt;/b&gt; software development practices boil down to? &amp;nbsp;Building easily maintained software. &amp;nbsp;It isn't about creating beautiful code, it isn't about designing a family of classes, it isn't about creating a model that sounds like a spoken language. &amp;nbsp;Building easily maintained software can be done in any number of ways. &amp;nbsp;Something like TDD helps to reinforce proven practices for maintainable software but &lt;b&gt;it's not the only solution&lt;/b&gt;. &amp;nbsp;I'm a TDD practitioner but you know what? &amp;nbsp;I've got no beef with writing code first. &amp;nbsp;You don't always need to TDD.&lt;br /&gt;&lt;br /&gt;In the case of agile development, for anyone adopting agile, there's a LOT of focus on the religious practices that come with it. &amp;nbsp;You will, for a long time, follow these practices blindly, even when they don't improve your process and become a nuisance. &amp;nbsp;The answer is that not all practices may make sense. &amp;nbsp;Take a step back and look at what they are intending to achieve. &amp;nbsp;A 5 minute scrum doesn't mean you're doing a good scrum. &amp;nbsp;You may find that, for your group, have something like 8-10 minutes is more comfortable. &amp;nbsp;Don't hate yourself because you're not following it to a T. &amp;nbsp;You've done exactly what these practices were intended to do; maximize your productivity. &amp;nbsp;That's the &lt;b&gt;goal&lt;/b&gt;&amp;nbsp;of this whole thing.&lt;br /&gt;&lt;br /&gt;In the case of NOSQL, it's a poor musician to blame his instrument. &amp;nbsp;People finally realized that they were using SQL as the hammer to nail everyone's persistence problems. &amp;nbsp;With the host of new applications we build, SQL isn't always the answer. &amp;nbsp;Maybe it's a document database. &amp;nbsp;Maybe it's a key-value store. &amp;nbsp;Maybe you need something that natively supports object graphs. &amp;nbsp;Instead of recognizing the fact that applications and their persistence mechanisms come in all shapes and sizes, the sentiment has become that SQL is the scourge of software development. &amp;nbsp;We have ourselves to blame on that one, trying to force an object model into a system that poorly represented it. &amp;nbsp;Somehow this is SQLs fault? &amp;nbsp;We stopped questioning why we did the things we did. &amp;nbsp;Take a step back, ask yourself what you're really trying to do and then it becomes a no-brainer. &amp;nbsp;That's what gave birth to all these new forms of persistence.&lt;br /&gt;&lt;br /&gt;For some, it may take a while to see it but you'll get there. &amp;nbsp;Don't fall into the trap of blindly doing things without re-evaluating constantly. &amp;nbsp;There's more than one way to do something and you shouldn't let software purity or zealotry prevent you from considering it. &amp;nbsp;It leads to the innovations that improve our lives as developers and the people who use our software.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-9067729329345219550?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/9067729329345219550/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=9067729329345219550' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/9067729329345219550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/9067729329345219550'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2011/06/goal.html' title='The Goal'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-5560060738085134919</id><published>2011-03-08T07:44:00.000-08:00</published><updated>2011-03-08T07:44:25.135-08:00</updated><title type='text'>Thoughts on the Test Pyramid</title><content type='html'>About a half year ago, one of my coworkers sparked a discussion on the test pyramid. &amp;nbsp;Specifically, he referenced a link and asked our thoughts on it. &amp;nbsp;Since I like to geek out, I had to respond. &amp;nbsp;I actually spent some time creating what I thought was a reasonable analogy so I figured I'd share it. &amp;nbsp;I'm also offering this now as I have another post I really want to discuss in regards to the boundaries in testing between a QA group and developers. &amp;nbsp;Is there one? &amp;nbsp;Should there be one? &amp;nbsp;How do we deal with test overlap? &amp;nbsp;It's something I've been mulling around and I need to think out loud.&lt;br /&gt;&lt;br /&gt;So, here's how the original thread went,&lt;br /&gt;&lt;br /&gt;&lt;b&gt;S:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;blockquote&gt;Some interesting posts on testing pyramids and automation. I'm a proponent of using this pyramid metaphor for organizing our test strategy. Thoughts?&lt;br /&gt;&lt;a href="http://benhutchison.wordpress.com/2008/03/20/automated-testing-2-the-test-pyramid/"&gt;http://benhutchison.wordpress.com/2008/03/20/automated-testing-2-the-test-pyramid/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blog.mountaingoatsoftware.com/the-forgotten-layer-of-the-test-automation-pyramid"&gt;http://blog.mountaingoatsoftware.com/the-forgotten-layer-of-the-test-automation-pyramid&lt;/a&gt;&lt;/blockquote&gt;&lt;b&gt;Me:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;It's an effective way to describe a proven testing strategy. The simple law here is that tests are all about feedback and how valuable that feedback is. The value is tied directly to their maintenance cost. If you look at it this way, you stop thinking in terms of layers. For example, brittle unit tests are high cost and thus less valuable than verifiable, repeatable, solid unit tests. This is the mindset all test implementers need to have in order to build the best test suite.&amp;nbsp;&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote&gt;In terms of the test pyramid, we can certainly assume that there are responsibly written tests. What's illustrated there is how the test maintenance cost rises in parallel to the growing level of component interaction and complexity. The more complex the interactions in the test then the more likely it is to break. Broken tests need to be maintained. Tests of complex interactions take longer to repair.&amp;nbsp;&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote&gt;At each level of the pyramid, we have a set budget on how much we can spend on maintenance. Unit tests are cheap therefore we buy lots. Integration tests are a little more expensive so we can't afford as much. Functional tests carry the heaviest price tag so we just buy a handful.&amp;nbsp;&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote&gt;Tests at all layers are valuable and provide a distinctly different type of feedback. That's why it isn't a good idea to simply forego testing a layer at all. Having a codebase with only unit tests doesn't prove that the system actually runs.&amp;nbsp;&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote&gt;There are a few more factors in what defines the value of a test but I'm glossing over that by calling them "responsible" tests. If you had two integration tests that exercised the same grouping of components then you should probably entertain getting rid of one. We want clean, clear feedback and having multiple test breaks for a single issue will obscure the root of the problem. Given that we're trying to be as frugal as possible we'd probably identify tests like that early on.&amp;nbsp;&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote&gt;The one caveat/tangent I might mention is that the pyramid metaphor (and how I commonly see it described) doesn't account for things like capacity testing; the throughput of the application, the transactions/second they can service, their memory footprint and resource consumption and other issues that can potentially derail a release.&amp;nbsp;&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote&gt;Application deployment is an implicit test to make sure that you can actually install and run the application. There would never be an NUnit test for that but their is value in knowing that the application can be reliably deployed. We should try doing that earlier to get that feedback when the information is more fresh in our minds.&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote&gt;...&lt;/blockquote&gt;And that was about it. &amp;nbsp;I had a few more words but they dealt with the internals of our specific situation. &amp;nbsp;Not worth repeating for obvious reasons.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-5560060738085134919?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/5560060738085134919/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=5560060738085134919' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/5560060738085134919'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/5560060738085134919'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2011/03/thoughts-on-test-pyramid.html' title='Thoughts on the Test Pyramid'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-1021040848665619575</id><published>2011-02-27T14:26:00.000-08:00</published><updated>2011-02-27T14:38:19.961-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='OSS'/><category scheme='http://www.blogger.com/atom/ns#' term='build automation'/><category scheme='http://www.blogger.com/atom/ns#' term='open source software'/><title type='text'>On the fence about Java, open source is the shiznit and .NET build automation sucks</title><content type='html'>I moved to a new team more than half a year ago and at first things were rough. &amp;nbsp;The team itself was fine but I was giving up my precious C# for Java and I was entering a whole universe of new software. &amp;nbsp;My technology stack changed from Microsoft branded IDEs to that of the open source crowd. &amp;nbsp;I was out of my element but I thought, "Hey, time to try something new!".&lt;br /&gt;&lt;br /&gt;Let's just get this out of the way; as a language, Java is not aging well. &amp;nbsp;Certainly not in comparison to C# which is getting updated more frequently with a lot better language niceties. &amp;nbsp;When .NET rev'ed itself up to v3 it brought along lambdas and extension methods which makes for some really nice, clean code. &amp;nbsp;This is noticeably absent from Java. &amp;nbsp;Even the simple act of passing around functions is no where to be seen in Java. &amp;nbsp;I have to create a full-blown class that implements one method. &amp;nbsp;It feels like Java is more worried about being pulled from the holy scripture of &lt;a href="http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612"&gt;Design Patterns &lt;/a&gt;than it is about making a language that is enjoyable. &amp;nbsp;Ah, you can pass an anonymous class but it's still waaaay too verbose.&lt;br /&gt;&lt;br /&gt;But that's the thing with Java. &amp;nbsp;It seems like it tries to be as horrifically verbose as possible. &amp;nbsp;One of the common Java practices is to mark everything final. &amp;nbsp;You see final everywhere. &amp;nbsp;Final member variables, final arguments, final variable declaration, final classes, final final final. &amp;nbsp;You'd wish that they marked things NON-final because there are far fewer instances of that. &amp;nbsp;Better yet, choose a language where variables are&amp;nbsp;immutable&amp;nbsp;by default. &amp;nbsp;You end up with a lot of chatty code, which is unfortunate since it's already a static language...you don't want to be known for pushing the envelope on verbosity. &amp;nbsp;Here's my favorite quote about it,&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: Helvetica, Verdana, Arial, 'Liberation Sans', FreeSans, sans-serif; font-size: 13px; line-height: 20px;"&gt;&lt;em&gt;Whenever I write code in Java I feel like I'm filling out endless forms in triplicate.&lt;/em&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: Helvetica, Verdana, Arial, 'Liberation Sans', FreeSans, sans-serif; font-size: 13px; line-height: 20px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: Helvetica, Verdana, Arial, 'Liberation Sans', FreeSans, sans-serif; font-size: 13px; line-height: 20px;"&gt;-- Joe Marshall&lt;/span&gt;&lt;/blockquote&gt;I can forgive these sins because I've finally been exposed to open source software. &amp;nbsp;Software built by the community. &amp;nbsp;For us, by us. &amp;nbsp;Open source software has a distinctly different flavor to Microsoft software. &amp;nbsp;Tools load faster. &amp;nbsp;There's less fluff. &amp;nbsp;It's more of what you need and less of what you don't need. &amp;nbsp;If something has a bug, it's fixed quickly and you can get the patch as soon as someone posts it. &amp;nbsp;You don't have to live with the same crap for years because it just doesn't show up as a priority on Microsoft's radar. &amp;nbsp;You know, like the "&lt;a href="http://weblogs.asp.net/scottgu/archive/2009/10/29/add-reference-dialog-improvements-vs-2010-and-net-4-0-series.aspx"&gt;add reference dialog&lt;/a&gt;" that has been the bane of our existence since early 2000 that they only recently addressed (sort of).&lt;br /&gt;&lt;br /&gt;I was introduced to &lt;a href="http://maven.apache.org/"&gt;Maven &lt;/a&gt;which is build and dependency management for Java. &amp;nbsp;For anyone who cares about build automation (and that had better be ALL of you), Maven beats the ever living snot out of anything you can find in .NET. &amp;nbsp;.NET's build automation story is absolutely abysmal in comparison. &amp;nbsp;I know some people think Maven is kinda crappy but it's still light years beyond what the .NET crowd has going on. &amp;nbsp;The only thing that seems to be standardized in .NET is using &lt;a href="http://nant.sourceforge.net/"&gt;NAnt &lt;/a&gt;(and possibly but incredibly doubtfully, &lt;a href="http://albacorebuild.net/"&gt;Albacore/Rake&lt;/a&gt;). &amp;nbsp;Here's a simple scenario that is more difficult to do in .NET,&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Gather dependencies&lt;/li&gt;&lt;li&gt;Compile code&lt;/li&gt;&lt;li&gt;Run Unit tests&lt;/li&gt;&lt;li&gt;Run Integration tests&lt;/li&gt;&lt;li&gt;Deploy the application&lt;/li&gt;&lt;li&gt;Run smoke tests&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Step 1 was always something that was custom to whatever shop you worked at. &amp;nbsp;This is where someone had to copy third party libraries somewhere your build process could access them (probably a lame network share). &amp;nbsp;This is a problem that has been solved for years with things like the Maven repository in Java and &lt;a href="http://rubygems.org/"&gt;Gems repository in Ruby&lt;/a&gt;. &amp;nbsp;Maven just does this out of the box. &amp;nbsp;When you run a build, it will retrieve your dependencies prior to compilation. &amp;nbsp;There's a project &lt;a href="http://nuget.codeplex.com/"&gt;NuGet&lt;/a&gt;&amp;nbsp;for .NET that is supposed to alleviate this problem and I admit I haven't tried using it. &amp;nbsp;I can only hope it gets integrated into another project like Maven for the .NET community.&lt;br /&gt;&lt;br /&gt;Steps 2-3 are straight forward (and usually) don't introduce too much pain. &amp;nbsp;Step 4 usually requires partially constructing the environment of your application which includes databases, web applications and other such "heavy" dependencies. &amp;nbsp;This is where the open source community trounces .NET. &amp;nbsp;When I tried automating testing of web applications it required that IIS be installed, that I had the correct users/authentication, that I figure out the mystery of the &lt;a href="http://www.iis.net/download/webdeploy"&gt;Web Deploy tools&lt;/a&gt;&amp;nbsp;that are anything but intuitive and extremely prejudiced to IIS 6, blah blah blah. &amp;nbsp;It was a process that required massive manual intervention and implementation. &amp;nbsp;It's brittle and no company wants to pay for the time it would take to implement that.&lt;br /&gt;&lt;br /&gt;With Maven, I just reference the Tomcat web server plugin, tell it to start a web application on the fly, install it, and run it. &amp;nbsp;It's disgustingly simple to do and it's actually running a very good analog of my production environment. &amp;nbsp;You don't get Tomcat Home Edition or Tomcat Developer Edition or some other lame&amp;nbsp;neutered version of the web server product (I'm looking at you &lt;a href="http://ultidev.com/products/cassini/"&gt;Cassini web server&lt;/a&gt;). &amp;nbsp;You get the real deal and you get it with only a handful of XML declarations.&lt;br /&gt;&lt;br /&gt;Step 5 in .NET has no real public support or method. &amp;nbsp;It sucks. &amp;nbsp;Using the same Maven Tomcat plugin I mentioned above, deploying your web application is a breeze. &lt;br /&gt;&lt;br /&gt;I don't think I care to carry on describing how immature the state of build automation is in .NET. &amp;nbsp;Suffice it to say, we .NET devs should stop waiting for Microsoft to make it for us. &amp;nbsp;It's a glacial development. &amp;nbsp;There's too much to be learned from the open source software projects. &amp;nbsp;First lesson, not all .NET projects need to be &lt;a href="http://ravendb.net/"&gt;monetized&lt;/a&gt;. &amp;nbsp;Yes, you can be compensated for your hard work but there are tons of opportunities to do that outside of selling a product. &amp;nbsp;Embrace your community, have them push the feature list. &amp;nbsp;We can go from there.&lt;br /&gt;&lt;br /&gt;So while I get a lot better developer tools in open source software, it doesn't come without a price. &amp;nbsp;I'm not impressed with documentation and it's difficult to find the answers you need. &amp;nbsp;Unless you subscribe to their IRC channel or mailing list, you aren't going to find help from available online content. Sure, it can get you going but once the rubber meets the road you will inevitably hit an issue that doesn't seem to be covered in anything you can find with conventional Google searches. &amp;nbsp;I've come to loathe all the websites that index mailing lists, jira and java documentation only to provide you with advertisement-laden dead ends. &amp;nbsp;You'll have to subscribe to a mailing list, post your question and pray that somebody wants to respond to a question they've probably seen a dozen times before.&lt;br /&gt;&lt;br /&gt;The open source world isn't perfect but I love the tooling and the low barrier for entry. &amp;nbsp;If you've been living in the .NET bubble for some time, take a break and try something new. &amp;nbsp;The worst case is that you recognize ways to make your life easier.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-1021040848665619575?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/1021040848665619575/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=1021040848665619575' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/1021040848665619575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/1021040848665619575'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2011/02/on-fence-about-java-open-source-is.html' title='On the fence about Java, open source is the shiznit and .NET build automation sucks'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-998606226777941367</id><published>2010-10-03T07:50:00.000-07:00</published><updated>2010-10-03T07:50:14.657-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='BDD'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Acceptance Test Driven Development'/><title type='text'>It was a busy summer</title><content type='html'>This last summer I spent time getting embedded in a new group at work. &amp;nbsp;It's been a blast because the group is really enthusiastic about agile development and adopting new and efficient practices. &amp;nbsp;I've had a chance to practice a lot of the things I've been doing and studying in my free time including acceptance test driven development, NHibernate, ASP.NET MVC 2 and lots more BDD.&lt;br /&gt;&lt;br /&gt;There's nothing sweeter than having a greenfield project and I was able to get my hands on one. &amp;nbsp;I was tasked with building an internal dashboard for some of our back end (Windows) services. &amp;nbsp;I'm still in .NET land and we're primarily a Microsoft shop so I used a pretty small but flexible stack,&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;ASP.NET MVC 2&lt;/li&gt;&lt;li&gt;&lt;a href="http://fluentnhibernate.org/"&gt;Fluent NHibernate&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://structuremap.net/structuremap/index.html"&gt;StructureMap&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;For testing, I tried out doing acceptance test driven development with &lt;a href="http://specflow.org/"&gt;SpecFlow &lt;/a&gt;which is the .NET analog to Ruby's &lt;a href="http://cukes.info/"&gt;Cucumber&lt;/a&gt;. &amp;nbsp;My unit/integration testing framework of choice is still &lt;a href="http://github.com/machine/machine.specifications"&gt;MSpec&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I took this experience and made a presentation to the company about BDD. &amp;nbsp;For anyone that's looked around the web at BDD presentations&amp;nbsp;you won't be incredibly surprised by the content. &amp;nbsp;Lots of the same points are made and I even borrowed the excellent high gear/low gear analogy of ATDD I found in someone else's presentation (I can't remember who :-(...sorry, uncredited person, whomever you are). &amp;nbsp;You can download it from my dropbox &lt;a href="http://dl.dropbox.com/u/1789099/BDD%20Presentation.ppt"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I know I promised an example of doing ATDD and I'd really like to do it. &amp;nbsp;Now that work is semi-calm I can try to whip something up. &amp;nbsp;There are tons of other things I want to talk about like the Java codebase I'm working in now, when NOT to unit test, the current .NET craze around&amp;nbsp;&lt;a href="http://codebetter.com/blogs/gregyoung/archive/2010/02/16/cqrs-task-based-uis-event-sourcing-agh.aspx"&gt;CQRS&lt;/a&gt;, and other interesting topics swimming around in my head. &amp;nbsp;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-998606226777941367?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/998606226777941367/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=998606226777941367' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/998606226777941367'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/998606226777941367'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2010/10/it-was-busy-summer.html' title='It was a busy summer'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-3018346064587504895</id><published>2010-06-27T13:37:00.000-07:00</published><updated>2010-06-27T19:21:55.200-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Behavior Driven Development'/><category scheme='http://www.blogger.com/atom/ns#' term='outside-in development'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><category scheme='http://www.blogger.com/atom/ns#' term='user story'/><title type='text'>BDD: Just tell me what the eff it is!</title><content type='html'>Here's my big problem with BDD...on first blush the only thing you can see of it are the tools used in it for testing and a bunch of acronyms and buzzwords.&amp;nbsp; You get all these testing frameworks to try to write natural language tests geared to output something your stakeholder can both read and understand.&amp;nbsp; For a long time, the question still stood for me; what &lt;i&gt;is&lt;/i&gt; BDD?&amp;nbsp; How do you &lt;i&gt;do&lt;/i&gt; BDD?&amp;nbsp; Sure, my tests were now human readable but it still hadn't added up.&lt;br /&gt;&lt;br /&gt;For those that don't understand what BDD is and even those that do, I want to walk you through what I've learned over the last year.&amp;nbsp; I want to give you an alternative narrative to the stuffy version on &lt;a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development"&gt;wikipedia&lt;/a&gt; and the dated &lt;a href="http://www.google.com/search?q=behavior+driven+development"&gt;top ranked Google results&lt;/a&gt; which offer breadcrumbs to understanding but didn't give me the clarity I was looking for.&lt;br /&gt;&lt;br /&gt;Let's look at the two line summary Dan North &lt;a href="http://skillsmatter.com/podcast/java-jee/how-to-sell-bdd-to-the-business"&gt;gave last year&lt;/a&gt;,&lt;br /&gt;&lt;blockquote&gt;BDD is a second-generation, outside-in, pull- based,  multiple-stakeholder, multiple-scale, high-automation, agile  methodology. It describes a cycle of interactions with well- defined  outputs, resulting in the delivery of working, tested software that  matters.&lt;/blockquote&gt;Get it?&amp;nbsp; Neither did I when I first read it.&amp;nbsp; After doing a lot of research, investigation and experimentation I finally get it.&amp;nbsp; Now that I do, that two line definition is an excellent summary.&amp;nbsp; There's a lot of information packed into those sentences.&amp;nbsp; We won't try to drill into all of that here.&amp;nbsp; Let's start with the simple building blocks of the BDD process.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;It starts with a story&lt;/h3&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;BDD is firmly rooted in the agile universe.&amp;nbsp; It relies on a lot of the mechanisms and practices you find in agile processes.&amp;nbsp; The first and most important is the practice of capturing user requirements as &lt;a href="http://www.agilemodeling.com/artifacts/userStory.htm"&gt;stories&lt;/a&gt;.&amp;nbsp; I'm not going to spend time in this post defining what a story is but let's just use an example we can refer to.&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: small;"&gt;In order to build readership of the blog&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;As a blog reader&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;I want to leave comments&lt;/span&gt;&lt;/blockquote&gt;This is the first step in BDD, the first tangible piece of the process.&amp;nbsp; Your stakeholder(s) and your agile group develop stories.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Create examples/scenarios&lt;/h3&gt;&lt;br /&gt;You have your story.&amp;nbsp; Take that story and imagine (realistic) scenarios of it in practice.&amp;nbsp; Who it is that generates the scenarios may be &lt;a href="http://blog.dannorth.net/whats-in-a-story/"&gt;multiple people&lt;/a&gt;.&amp;nbsp; Your scenarios are your acceptance criteria.&amp;nbsp; They tell you when the story is done.&lt;br /&gt;&lt;br /&gt;Here are some samples of scenarios based on the above story.&amp;nbsp; (Remember, for this story, we're in the context of a reader of the blog and their desire to leave comments.)&amp;nbsp; The scenarios are written using the &lt;a href="http://blog.objectmentor.com/articles/2008/11/27/the-truth-about-bdd"&gt;Given-When-Then format&lt;/a&gt; for describing scenarios.&lt;br /&gt;&lt;blockquote&gt;Given a blog entry&lt;br /&gt;When I write a comment&lt;br /&gt;And I submit the comment&lt;br /&gt;Then I should see my comment under the blog post&lt;br /&gt;&lt;br /&gt;Given a blog entry&lt;br /&gt;And the blog entry is no longer accepting comments&lt;br /&gt;When I view the blog entry&lt;br /&gt;Then I should not be allowed to write a comment&lt;/blockquote&gt;You can see how there would be numerous scenarios and contexts of users of your application.&amp;nbsp; When generating your scenarios, you must take them all into account.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;You're just about to write code but...AUTOMATION!&lt;/h3&gt;&lt;br /&gt;Any good development environment should be as automated as (in)humanly as possible.&amp;nbsp; With a few quick commands/scripts you should be able to build your app, build your DB (if you have one),  execute tests, deploy the app, and run it.&amp;nbsp; The more you have to do manually the harder this whole thing is.&lt;br /&gt;&lt;br /&gt;Also, you should be able to run this in isolation on your workstation, if possible.&amp;nbsp; If your app is sharing a DB with 5 other workstations in your department, chances are you're going to have collisions.&amp;nbsp; You won't be able to make predictable tests and you'll be stepping on each others' toes.&lt;br /&gt;&lt;br /&gt;When you write your code you want to be continuously running tests.&amp;nbsp; This should be a push-button activity that does not derail you for several minutes.&amp;nbsp; If it is then analyze what it is that you're doing and see if you can find ways to streamline it.&amp;nbsp; Either through tooling or through eliminating deficiencies in your testing strategy.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Outside-in: It's time to TDD&lt;/h3&gt;&lt;br /&gt;In BDD, we do things outside-in.&amp;nbsp; Meaning, you start at the level of the user's interaction with your application and then you build downwards.&amp;nbsp; It's a huge shift for a lot of people.&amp;nbsp; I haven't been doing it for very long but it's not a huge departure if you were already doing TDD.&amp;nbsp; Most of my difficulty was just learning how to automate UI interactions.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Here&lt;/i&gt; is where the rubber (finally) meets the road.&amp;nbsp; You have a story, you have some scenarios of your story that crystallize your acceptance criteria, and you have an automated development environment that allows you to build and test your app rapidly.&lt;br /&gt;&lt;br /&gt;Using the story and scenarios from this blog post, we can write our first lines of code.&amp;nbsp; But...I'm not going to do that here.&amp;nbsp; I have a separate blog post (it certainly deserves its own) coming that will walk through the TDD process under the BDD umbrella.&amp;nbsp; I'll update this post to refer to it once it's done.&lt;br /&gt;&lt;h3&gt;In summary&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;Write user stories&lt;/li&gt;&lt;li&gt;Create scenarios based on the stories&lt;/li&gt;&lt;li&gt;TDD those stories starting at the top level of your application  (typically a UI) and keep developing downwards until it's functionally  complete &lt;/li&gt;&lt;/ol&gt;Yes, that's seriously it.&amp;nbsp; There are methodologies, practices and  tools that go inside of it but, at its simplest, that's all you're  really doing.&amp;nbsp; If you're reading about BDD then I have no doubt that you're already aware of most of these topics anyways.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;The mystical cloak of BDD has now been removed!&lt;br /&gt;&lt;br /&gt;DISCLAIMER:&amp;nbsp; This was meant to be a high level, entry level explanation of BDD because I have rarely seen it simplified.&amp;nbsp; Most information I've found online, the explanation seems to be a deep dive into how to write stories, stakeholder interaction, how DDD dictates the ubiquitous language, how it's the natural evolution of TDD (without ever showing you how!), and a variety of other entirely relevant information.&amp;nbsp; The problem is that there's a lot of cognitive overload.&lt;br /&gt;&lt;br /&gt;In other words, for BDD enthusiasts, or developers in general because we like to be intellectual, don't dog me out and poke holes in my examples.&amp;nbsp; It's horribly contrived, I readily admit I am still learning these concepts and I don't believe anything I've written is incredibly misleading.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-3018346064587504895?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/3018346064587504895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=3018346064587504895' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/3018346064587504895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/3018346064587504895'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2010/06/bdd-just-tell-me-what-eff-it-is.html' title='BDD: Just tell me what the eff it is!'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-8060709713434177739</id><published>2010-06-24T22:13:00.000-07:00</published><updated>2010-06-24T22:31:38.607-07:00</updated><title type='text'>wtf, with a side order of bbq</title><content type='html'>Just a blurb; been trying out new technologies and shiny toys.  Here's my naive/ignorant take on things:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Been years since Linq hit .NET.  Why is the NHibernate criteria API so incredibly non-intuitive and not making a huge move to linq?  It's still clinging to the uber-verbose criteria API that, even fluently, makes hardly any sense.  Yeah, I tried using Linq2NHibernate too but it was buggy for anything outside of simple selects and joins.  I had an inner join that would magically make itself an outer join when I added an orderby clause.  Hot tip for NHibernate; ditch the criteria API and just use Linq like all the other cool kids.  It's ok to abandon the bizarre RDBMS abstraction that's been created.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've been spoiled by Ruby.  I can't tell you how many times in my day I think, "goddam, why can't I have mixins!?"  It would make a lot of things a lot easier/sexier.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Finally, how can there not be a fully automated solution for deploying .NET web apps?  I want something that builds the DB, deploys an MVC app and creates one in IIS if it doesn't exist yet.  I haven't found anything like that.  Granted I haven't looked too much but I didn't find anything with a handful of google searches.  This is another area where the other open source community blows .NET out of the water.  If I cared, I'd try to make something like this but I don't have the friggin' time.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Finally, finally I am again reminded of how small the open source community is in .NET.  Still can't figure out why.  &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-8060709713434177739?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/8060709713434177739/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=8060709713434177739' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/8060709713434177739'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/8060709713434177739'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2010/06/wtf-with-side-order-of-bbq.html' title='wtf, with a side order of bbq'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-5641169408507270072</id><published>2010-05-09T21:08:00.001-07:00</published><updated>2010-05-14T18:43:59.534-07:00</updated><title type='text'>Here we go again; where is my mind?</title><content type='html'>&lt;div&gt;Something is itching at my mind and I haven't given it a name or a face yet.  Whether I use Ruby, Java, C#, Scala or Javascript, it doesn't matter.   They're details.   When you go to Facebook do you think "Wow, this really feels like PHP." or when you hit Twitter do you sense the presence of Ruby and Erlang?  Not so much.  Then what counts here?   What is it that matters?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Software is just a means to an end.   I'm not in the business of writing code, I'm in the business of creating tools.  Software just happens to be the vehicle in which I deliver them.   You need a tool that will remind you to call your mother on her birthday?   I'll write software that generates email reminders for important dates.  Alternatively, I could have created a phone service that would call your home or cell phone as a reminder.   Maybe I could create a network of carrier pigeons that did the same.   Unfortunate for the pigeon trade and call centers, writing software is a lot cheaper and maintainable.  Do you see what I'm getting at though?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's more about what I'm delivering than it is how I deliver it.  And, for me, the "how" is no longer so narrow.  I'm not just a .NET developer and I'm more than comfortable stepping outside of the MS world.  I've learned a fair number of engineering practices and principles that are language agnostic like DRY, YAGNI and some of SOLID.  I can pick things up quickly no matter which language I choose to use.  It's satisfying to know that within 2 weeks of reading and practicing, I have a fairly good idea of how I'd do modular development in Ruby and I even grok some of the deeper concepts like Ruby's compositional nature and metaprogramming.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One benefit of this line of thinking is that I'm no longer narrowing my vision to how I build what the customer wants.  I have a much broader perspective of the business I'm in.  Ultimately, I'm sure 98% of what I make will be a software product but someday there's going to be something that I think of that can be better serviced with a non-software solution.  If I'm lucky, nobody else will be doing it and I can make my fortune from it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What drove me to this whole post is that I'm trying to figure out what I'd like to create with my new found Ruby skillz.   It dawned on me that, while Ruby is a blast to use, it's just the details.  The hard work is figuring out what the hell I want to bring to the world.  What's my product?   What's my vision?  What do people want?  That's the new mental hurdle for me now.&lt;/div&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/167738975296784101-5641169408507270072?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/5641169408507270072/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=5641169408507270072' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/5641169408507270072'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/5641169408507270072'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2010/05/here-we-go-again-where-is-my-mind.html' title='Here we go again; where is my mind?'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-3116949069727004180</id><published>2010-05-02T18:51:00.000-07:00</published><updated>2010-05-09T21:10:42.632-07:00</updated><title type='text'>Ruby is cool, Time for Rails</title><content type='html'>I've spent the last couple weeks reading about the fine details of Ruby.  My first impressions are good.  I dig the language.  I haven't put it to good use yet though.  Mostly just dicking around in IRB and putting some small classes and modules together.  I've been using RubyMine and NetBeans but I haven't had any clear winner on a Ruby IDE.  Again, I think once I get into actually writing an application I'll have something more to substantial to share in that regard.  Or maybe I'll shed my dependencies to a GUI and go all command line...well, let's not go overboard here.  One thing at a time.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now the next thing to check out is Rails.  On first blush, I can see where ASP.NET MVC gets its influence.  They share a similar DSL and even class/method names are echoed between the two.  But, once again, I'm starved for details.  I don't have any books on Rails so I may have to shop for one.  I'm mostly just putzing around with what I know from ASP.NET MVC.  Did I mention that they're close relatives?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-3116949069727004180?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/3116949069727004180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=3116949069727004180' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/3116949069727004180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/3116949069727004180'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2010/05/ruby-is-cool-time-for-rails.html' title='Ruby is cool, Time for Rails'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-36435423353701399</id><published>2010-04-21T18:52:00.000-07:00</published><updated>2010-04-21T19:40:51.171-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><title type='text'>Playing with Ruby</title><content type='html'>With the 1.0 release of  &lt;a href="http://ironruby.net/"&gt;IronRuby&lt;/a&gt; I decided to take a brief detour from my prior game plan of outside-in development .  Part of that decision was because I'd wanted to check out Ruby for a while as a dynamic language (I've lived in a stuffy, static world for too long) with a lot of hype around it.  Part of it was because most of the cutting edge BDD work is happening in the Ruby space.  And the last part is that Ruby is in the .NET space now (at least up to 1.8.6) so the barrier for entry couldn't possibly get any lower.  Yeah, I know the IronRuby project has been going on for years and prior to that it was dirt simple to get Ruby running on Windows but whatever.  I'm here now.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Last year I did manage to pick up the book &lt;a href="http://www.amazon.com/Beginning-Ruby-Novice-Professional/dp/1590597664"&gt;Beginning Ruby&lt;/a&gt; which I, unfortunately, didn't take a shine to.  The first handful of chapters were light on the details of Ruby and deferred it for later chapters that I never got to.  But that's also my fault because I'm a reference book kind of guy.  I just picked up &lt;a href="http://oreilly.com/catalog/9780596516178"&gt;The Ruby Programming Language&lt;/a&gt; the other day which totally itches that scratch.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've been playing around with the &lt;a href="http://en.wikipedia.org/wiki/Interactive_Ruby_Shell"&gt;interactive Ruby shell&lt;/a&gt; which has been fun.  It gives me a chance to take a spin before I do anything serious.  Now I'm looking to pick up an IDE.  I downloaded &lt;a href="http://netbeans.org/"&gt;NetBeans &lt;/a&gt;and &lt;a href="http://www.jetbrains.com/ruby/"&gt;RubyMine&lt;/a&gt;.  I'll post back with impressions on both the language and the tools.&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/167738975296784101-36435423353701399?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/36435423353701399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=36435423353701399' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/36435423353701399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/36435423353701399'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2010/04/playing-with-ruby.html' title='Playing with Ruby'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-7958129291764250842</id><published>2010-04-13T19:40:00.000-07:00</published><updated>2010-04-17T12:11:21.720-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Behavior Driven Development'/><category scheme='http://www.blogger.com/atom/ns#' term='outside-in development'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile Development'/><title type='text'>Analysis and Investigation on Outside-In Development</title><content type='html'>BDD has a variety of testing tools surrounding it in a number of languages.  Since I'm primarily in the .NET world (looking to expand that soon), I've dabbled with MSpec and had a lot of fun/success in creating descriptive tests that spoke the language of the business and communicated value.  That was my first experiment in the world of domain drive design in an agile process.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The one thing these tools have in common is that they promote outside-in development.  In BDD that literally means starting at the touch point with the consumer/customer/stakeholder.  For most applications, that's a GUI of some sort but for others it may be a web service or something similar.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've seen outside-in development go by a couple names like story driven development or acceptance test driven development.  Unless I'm mistaken, they're both trying to achieve the same goal.  What outside-in development is trying to do is make the software customer-oriented not unlike the agile processes that fit with this thinking.  You start building the software from the customer's point of view based on their specification of it (usually as a story).  Coupled with agile, you're doing something along the lines of rapid prototyping (with a bit more discipline).  It's also keeping you focused on what the customer wants.  It discourages gold plating and extra work that are typically waste.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;lt;tangent&amp;gt; &lt;/b&gt;&lt;/div&gt;&lt;div&gt;I don't like to say gold plating because I know there are those developers that think that discouraging gold plating is like discouraging free thought and creativity.  I would disagree.  The hard pill for us to swallow is that what we perceive to be a "better way to do things" is not from the perspective of the actual consumers of the application.  They may have no use for the bells and whistles that we believe to be productivity boosters.  What it may be doing instead is creating excess inventory that costs money but has no ROI.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, if you're in an agile process (or even if you're not), don't despair!  Agile, by its very nature, relies on high-bandwidth communication.  Reach out to the customer and communicate your creative thoughts and ideas.  They will rely on your expertise in this arena and most times accept your recommendations.  But, just remember, if they don't find use for your widget/tool/interface then don't do it (at least on company time :-P)!&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;lt;/tangent&amp;gt; &lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sooooo this is what I've understood so far.  I am by no means an expert on outside-in development and I'm still trying to understand the practice.  In the past, I've worked from the application logic and worked my way downwards.  I haven't done it from the UI down which is certainly an interesting experiment.  I'm also coming to find that I haven't done nearly enough acceptance/functional testing in my travels.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I plan on following up this post with my first attempt at doing outside-in development.  I need to find a good book on it.  I'm pretty sure the &lt;a href="http://www.pragprog.com/titles/achbd/the-rspec-book"&gt;RSpec Book&lt;/a&gt; is probably what I'm looking for but any recommendations are appreciated.  In the meantime, I've just been reading blogs, articles and comments.  One such blog I ran into has a tremendous amount of insight into testing and offers good information to get you started on writing acceptance tests using ASP.NET MVC and some other tools and frameworks.  &lt;a href="http://blog.stevensanderson.com/"&gt;Check out Steve Sanderson's blog&lt;/a&gt; to get some really great information.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-7958129291764250842?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/7958129291764250842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=7958129291764250842' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/7958129291764250842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/7958129291764250842'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2010/04/analysis-and-investigation-on-outside.html' title='Analysis and Investigation on Outside-In Development'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-3299346019523994796</id><published>2010-03-10T05:40:00.000-08:00</published><updated>2010-03-14T21:36:27.272-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='dependency injection'/><category scheme='http://www.blogger.com/atom/ns#' term='Unit Test'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>TDD Tidbits: Your unit tests suck (and so does your design)!</title><content type='html'>&lt;div&gt;&lt;div&gt;TDD is a design process but there are skills required outside of its discipline that you need to master as well.  One such skill is writing proper unit tests.  Prior to TDD I thought I was unit testing.  I really wasn't for a number of reasons.  The simple answer is that my design wasn't permitting unit testing and what I was calling "unit" tests were actually integration tests.  Classes were tightly coupled, methods were more procedural than OO, I didn't do a good job of separating responsibilities/concerns, etc.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A unit test has some simple requirements you need to fulfill.  I'll rattle off a list of them off the top of my head.&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;The test must be fast&lt;/li&gt;&lt;li&gt;The test must be repeatable&lt;/li&gt;&lt;li&gt;The test must be predictable&lt;/li&gt;&lt;li&gt;Only one assertion per test&lt;/li&gt;&lt;li&gt;The test must isolate the behavior under observation&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;Easy, right?  You'd think so.  I'd heard these in some shape or form before I began to do TDD but it never really hit home.  I've seen a couple blog posts with lists like this one so I'll try to describe my thoughts on each of the items above.  I'm sure I could go on for hours about them and more so I'll try to keep it brief.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;DISCLAIMER: The following code examples are extremely naive and serve only to demonstrate.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;u&gt;The test must be fast&lt;/u&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Unit tests are meant to be run frequently.  You have them local to your development workstation and they (should) run as part of your continuous integration.  Unit tests are regression tests and your first line of defense.  They report to you when something is no longer behaving the way it's supposed to.  You need that feedback immediately and there's absolutely no reason for them to be slow.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For any system of significant complexity you don't want to wait 30 or even 10 minutes to find out that a bug was introduced.  Unit tests should execute in milliseconds and running a whole suite of them should execute within seconds.  For example, a project I had at work had around 300 tests that would execute in 4 to 5 seconds.  That's the type of speed you should be aiming for.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Having tests that run in the timespan of minutes immediately introduces context switching.  What happens when you kick off a full system build for a project that may take a minute or two or more to complete?  You open up your browser and see what's going on  in the Twitterverse, Facebook, StackOverflow, etc.  You don't want that to happen for your testing.  It's good to keep focused on the task and to plug along without too much interruption.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;u&gt;&lt;b&gt;The test must be repeatable&lt;/b&gt;&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/div&gt;&lt;div&gt;This one is simple.  I can run a unit test as many times as I want and it will not fail.  Take the following for example of what would not be a repeatable test.  This is a domain of rabbits.  You have some rabbits, you add them to a collection of rabbits.  It's a cruel domain and no two rabbits may have the same name.  When you run this test a second time it will fail since it's picking up state from the last run.  "Thumper" will already be in the database so adding him again will cause an error.&lt;/div&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;[TestFixture]&lt;br /&gt;public class RabbitFixture&lt;br /&gt;{&lt;br /&gt;    [Test]&lt;br /&gt;    public void Should_create_rabbit()&lt;br /&gt;    {&lt;br /&gt;        var rabbitRepo = new RabbitRepository();&lt;br /&gt;&lt;br /&gt;        rabbitRepo.Add(new Rabbit("Thumper"));&lt;br /&gt;&lt;br /&gt;        var thumper = rabbitRepo.GetByName("Thumper");&lt;br /&gt;&lt;br /&gt;        Assert.IsNotNull(thumper);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Rabbit&lt;br /&gt;{&lt;br /&gt;    public Rabbit(string name)&lt;br /&gt;    {&lt;br /&gt;        Name = name;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public string Name { get; private set; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class RabbitRepository&lt;br /&gt;{&lt;br /&gt;    private readonly ISessionFactory _sessionFactory;&lt;br /&gt;&lt;br /&gt;    public void Add(Rabbit rabbit)&lt;br /&gt;    {&lt;br /&gt;        using (var session = _sessionFactory.OpenSession())&lt;br /&gt;        {&lt;br /&gt;            if(Exists(rabbit))&lt;br /&gt;            {&lt;br /&gt;                throw new Exception("Rabbit of the same name already exists!");&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            session.Save(rabbit);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private bool Exists(Rabbit rabbit)&lt;br /&gt;    {&lt;br /&gt;        return GetByName(rabbit.Name) != null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Rabbit GetByName(string name)&lt;br /&gt;    {&lt;br /&gt;        using (var session = _sessionFactory.OpenSession())&lt;br /&gt;        {&lt;br /&gt;            return session.Linq&amp;lt;Rabbit&amp;gt;()&lt;br /&gt;                .FirstOrDefault(r =&amp;gt; r.Name == name);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;There are various tricks to make this test repeatable but not without violating some of the other guidelines like test isolation and speed.  Unit tests shouldn't rely on external state and likewise they should not be creating any state that will last beyond the life of the test itself.  It will be hard to keep the test repeatable and is brittle.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;b&gt;&lt;u&gt;The test must be predictable&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1 + 1 will always equal 2, right? Conceptually, your test should do the same.  The inputs will always yield an expected output.  I don't think this needs much more explanation.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;u&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Only one assertion per test&lt;/span&gt;&lt;/u&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;This is one of the more misunderstood practices of unit testing.  Don't mistake mapping the word "assertion" to the Assert function that is called within a unit test.  In this instance, they are not the same.  You may call the Assert function multiple times to assert a single behavior.  Take the following example.&lt;/div&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;[TestFixture]&lt;br /&gt;public class RectangleFixture&lt;br /&gt;{&lt;br /&gt;    [Test]&lt;br /&gt;    public void Should_resize_rectangle()&lt;br /&gt;    {&lt;br /&gt;        Rectangle rectangle = new Rectangle(40, 20);&lt;br /&gt;&lt;br /&gt;        rectangle.ReduceSizeByPercent(50);&lt;br /&gt;&lt;br /&gt;        Assert.AreEqual(20, rectangle.Length);&lt;br /&gt;        Assert.AreEqual(10, rectangle.Width);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Rectangle&lt;br /&gt;{&lt;br /&gt;    public Rectangle(int length, int width)&lt;br /&gt;    {&lt;br /&gt;        Width = width;&lt;br /&gt;        Length = length;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public double Length { get; private set; }&lt;br /&gt;&lt;br /&gt;    public double Width { get; private set; }&lt;br /&gt;&lt;br /&gt;    public void ReduceSizeByPercent(int percent)&lt;br /&gt;    {&lt;br /&gt;        Length *= (percent * .01);&lt;br /&gt;        Width *= (percent * .01);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;There're two calls to Assert to verify that the rectangle's size was reduced by 50%.  That's what we're talking about when we say a test makes only one assertion.  It's asserting the one behavior.  Don't hate yourself if you call Assert more than once and don't feel the need to create another test.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;u&gt;The test must isolate the behavior under observation&lt;/u&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Now that we're warmed up let's look at the one guideline to rule them all.  This is the one that will have the greatest impact on the design of your code.  You have to isolate the behavior you wish to test.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can read this another way.&lt;i&gt;&lt;b&gt;  The unit test cannot fail for any reason other than the implementation of the behavior being tested is incorrect&lt;/b&gt;&lt;/i&gt;.  I have read blogs that mandate that a unit test cannot touch the file system, a database, a network, etc.  That's not just because of how slow that may be.  It's because now your unit test may fail for any reason related to an external dependency that has absolutely nothing to do with what you're unit testing.  When you get the red light that a unit test fails it shouldn't be because you didn't install a database, it shouldn't be because you neglected to include a configuration file, it shouldn't be because your network cable isn't plugged in.  Those have nothing to do with the unit test at hand.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Following this guideline will teach you how to detach your class from its external dependencies.  The external dependencies aren't just things like databases and LAN access.  They can be other classes that have rules of their own that need to be satisfied.  You do not want your test to fail if some rule in a class that you consume isn't satisfied.  That's outside of the scope of the behavior you're testing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is where people start to introduce language like "mocking" or "faking" your external dependencies.  These are ways of allowing you to truly isolate the behavior you're trying to test.  You're replacing pieces of your class that would cause the test to fail for reasons outside of the class's cares or awareness.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When you first start to really isolate the code you're trying to unit test the first thought that may pop into your mind is that "I'm just writing it this way so that I can test it!" Yes, you are but there is a truth you do not yet realize (and may take some time to settle in).  Well designed code is easily testable and easily testable code is well designed.  Writing proper unit tests can expose major (or minor) issues in the your design.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For me, this is where I learned the most lessons and what made me truly appreciate things like the SOLID principles.  It leads you there and, in my opinion, you would have to go way out of your way to succeed in isolating your tests but avoid good design.  It puts bumpers on your bowling lane so to speak.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;u&gt;Summary&lt;/u&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Unit testing in and of itself is huge to the design process.  Without even engaging in TDD, it is going to highlight deficiencies in your design.  There is a lot of talk that TDD isn't about testing, it's about design.  Unit testing is also about design so it's a perfect marriage.&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/167738975296784101-3299346019523994796?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/3299346019523994796/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=3299346019523994796' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/3299346019523994796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/3299346019523994796'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2010/03/tdd-tidbits-your-unit-tests-suck-and-so.html' title='TDD Tidbits: Your unit tests suck (and so does your design)!'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-2813103191275848491</id><published>2010-03-09T05:38:00.001-08:00</published><updated>2010-03-09T20:13:14.815-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Refactor'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>TDD Tidbits: Red, Green, REFACTOR!!!</title><content type='html'>&lt;div&gt;So I was a TDD noob at one point.  I had to start somewhere so I picked up some recommended reading, Kent Beck's &lt;a href="http://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530"&gt;Test Driven Design: By Example&lt;/a&gt;.  I'll be honest; I didn't like it. I actually returned the book. Was I stupid? No! It just didn't seem to add up.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To Mr. Beck's benefit, I wasn't rejecting his book but rather the notion that I should put myself on a leash when I code and do "stupid" stuff like return static data to satisfy a test. I was feeling the discomfort a lot of developers feel when they first dive into this stuff. It's a whole different way of writing code. I would never fault anyone for having reactions like my own.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The idea of returning junk data to satisfy a test was probably the hardest thing for me to overcome. I spent many frustrating sessions trying to figure out when to stop returning dummy data or why I was even doing it. It was frustrating to know how to code things but having to hold myself back and continue with the TDD process. It won't let you wander off and start implementing all sorts of code.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Why the hell would I return dummy values in my production code? Why would I fake out my code at all? I could write code all day that would return dummy data. Hey look, my code returns zero! On the next unit test I can have it just return one and fake that out as well! What the hell is this proving? I'm not writing any meaningful code! I KNOW what the answer is. Why do I have to go about it this way? What a waste of time!  &lt;b&gt;*head explodes*&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To speak to my frustrations I didn't fully understand the process and I didn't (immediately) see the benefits.  I was missing the important step of refactoring my code after the test passes.  Sure, you may write a test that returns a static value of zero.  Then you write another test that expects the code to behave a new way and return another value.  At this point, feel free to refactor your guts out.  You don't need permission to write code.  Don't let the dogma of "only write code when you have a failing test" fool you.  It comes in two stages.  You write code to get the test to pass and then you write code again to refactor!  Your test passes but that doesn't mean all hands have to come off the keyboard!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For example,  here's a bucket.  You put apples in the bucket and then you want to know how many apples you have.  The first test and implentaton may look like this.&lt;/div&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public class BucketFixture&lt;br /&gt;{&lt;br /&gt;   [Test]&lt;br /&gt;   public void Should_have_five_apples_in_bucket()&lt;br /&gt;   {&lt;br /&gt;       Bucket bucket = new Bucket();&lt;br /&gt;       bucket.AddApples(5);&lt;br /&gt;&lt;br /&gt;       bucket.TotalAppleCount.ShouldEqual(5);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Bucket&lt;br /&gt;{&lt;br /&gt;   public void AddApples(int appleCount)&lt;br /&gt;   {&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public int TotalAppleCount&lt;br /&gt;   {&lt;br /&gt;       get&lt;br /&gt;       {&lt;br /&gt;           return 5;&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Then you want another test to hammer out more of the behavior of this awesome bucket.&lt;/div&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public class BucketFixture&lt;br /&gt;{&lt;br /&gt;   [Test]&lt;br /&gt;   public void Should_have_five_apples_in_bucket()&lt;br /&gt;   {&lt;br /&gt;       Bucket bucket = new Bucket();&lt;br /&gt;       bucket.AddApples(5);&lt;br /&gt;&lt;br /&gt;       bucket.TotalAppleCount.ShouldEqual(5);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   [Test]&lt;br /&gt;   public void Should_have_no_apples_in_bucket()&lt;br /&gt;   {&lt;br /&gt;       Bucket bucket = new Bucket();&lt;br /&gt;&lt;br /&gt;       bucket.TotalAppleCount.ShouldEqual(0);&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;The new test breaks as expected but now you can't pass back dummy data.  What code can you write to satisfy both tests?&lt;/div&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public class Bucket&lt;br /&gt;{&lt;br /&gt;   int _totalAppleCount;&lt;br /&gt;&lt;br /&gt;   public void AddApples(int appleCount)&lt;br /&gt;   {&lt;br /&gt;       _totalAppleCount += appleCount;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public int TotalAppleCount&lt;br /&gt;   {&lt;br /&gt;       get&lt;br /&gt;       {&lt;br /&gt;           return _totalAppleCount;&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Huzzah!  But I don't necessarily have to stop there.  I can still refactor if my heart so desired.  I don't need a failing test.  What if I wanted to be super cool and use auto properties?  Don't bother to write a new test for it.  Just do it.&lt;/div&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public class Bucket&lt;br /&gt;{&lt;br /&gt;   public void AddApples(int appleCount)&lt;br /&gt;   {&lt;br /&gt;       TotalAppleCount += appleCount;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public int TotalAppleCount&lt;br /&gt;   {&lt;br /&gt;       get; private set;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;No failing test required!  But bear in mind this is refactoring; we aren't changing behavior, only structure.  The code must continue to behave the same.  The tests will verify that.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Another thing to point out is that if the only behavior the bucket exhibited was that it had 5 apples then the test and implementation stops immediately.  This is when it's called out that you're trying to do the simplest thing to satisfy the requirements.  Even when new behavior is added, you're taking the shortest route to functional without being a complete chimp about it.  Add patterns where applicable and such.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Last point I'll make is that now I view my first test as probably the most important to my API.  The first test is figuring out the names of my classes, interfaces, properties, methods and arguments.  It's the first stab at the design of the class that you're making.  This is where I'm extra sensitive to the needs of the client code (typically called dog fooding).  It's a big deal to me that my code demonstrates its intent and usage without the need for lengthy comments.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;So there you go kids.  Take advantage of the refactoring step!  Do all the stuff that you want to do when you think that the TDD process has put you on a leash.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-2813103191275848491?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/2813103191275848491/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=2813103191275848491' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/2813103191275848491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/2813103191275848491'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2010/03/tdd-tidbits-red-green-refactor.html' title='TDD Tidbits: Red, Green, REFACTOR!!!'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-3249768144860131651</id><published>2010-03-09T05:36:00.000-08:00</published><updated>2010-03-09T05:38:15.485-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>TDD Tidbits</title><content type='html'>&lt;div&gt;I've been practicing TDD for two years and when I take a step back and look at what it's done for me I see I've learned a lot.  I'm a far better coder because of it.  Had I not picked it up, I doubt I'd be as well off.  I began writing a post about it but it became monolothic.  There's too much to be said.  I decided to break it down into individual posts to make them easier to digest.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Just doing superficial searches on TDD in google, I don't see much in the way of individual experiences on TDD practices.  I'm sure it's sprinkled about in blogs but most of what I find are the howto's, tutorials and videos surrounding it.  I think what I plan to write is a mixture of tips, insight and experiences in TDD.  I'm hoping it has value for the novice, the intermediate and the seasoned veteran.  It's probably going to be in C# but I'll see if I can't do examples in other languages (feel free to comment/request one for all 3-4 of my possible readers).&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-3249768144860131651?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/3249768144860131651/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=3249768144860131651' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/3249768144860131651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/3249768144860131651'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2010/03/tdd-tidbits.html' title='TDD Tidbits'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-6567379561289544114</id><published>2009-09-27T08:26:00.000-07:00</published><updated>2009-09-27T08:39:06.889-07:00</updated><title type='text'>Kickstart your BDD training</title><content type='html'>&lt;a href="http://blog.wekeroad.com/blog/"&gt;Rob Conery&lt;/a&gt; posted an excellent &lt;a href="http://blog.wekeroad.com/blog/make-bdd-your-bff-2/"&gt;quick-start&lt;/a&gt; for getting up and running using MSpec titled "Make BDD your BFF".  For those who still haven't taken the plunge, MSpec is framework for writing tests using the BDD style of development.  Overall, the literature on MSpec on the internet is lacking so take advantage of this and help get the word out!&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Also, just so I'm not repeating too much, &lt;a href="http://apobekiaris.blogspot.com/"&gt;Apostolis Bekiaris&lt;/a&gt; just &lt;a href="http://apobekiaris.blogspot.com/2009/09/bdd-in-few-hours.html"&gt;posted an entry&lt;/a&gt; similar to my own except with more links to resources.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-6567379561289544114?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/6567379561289544114/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=6567379561289544114' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/6567379561289544114'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/6567379561289544114'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2009/09/kickstart-your-bdd-training.html' title='Kickstart your BDD training'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-4585359252649998154</id><published>2009-09-25T19:52:00.001-07:00</published><updated>2009-09-27T07:33:07.139-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='BDD'/><category scheme='http://www.blogger.com/atom/ns#' term='Unit Test'/><category scheme='http://www.blogger.com/atom/ns#' term='MSpec'/><category scheme='http://www.blogger.com/atom/ns#' term='Context/Specification'/><title type='text'>I don't mock much anymore</title><content type='html'>I still use Rhino Mocks.  Never tried any other libraries.  I probably should just so I can be more worldly but it's fit my needs and I have a laundry list a mile long of ToDos.&lt;br /&gt;&lt;br /&gt;That being said, I've done a lot of unmentored exploration into the whole unit test and TDD countryside.  At the beginning of my journey I did a metric ton of mock creation.  I'm speaking to the different types of test doubles.  Go check out Fowler's ever-expanding documentation &lt;a href="http://www.martinfowler.com/bliki/TestDouble.html"&gt;on the topic&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;What I found was the obvious (but not at the time); mocks are part of the test assertions.  Its giving me intimate details about how an object is doing its work.  As such, they should only be used to verify the test at hand.  If they are not truly verifying the expected behavior then it's not a mock.  It's a stub, it's a fake, it's something that's allowing the process to emulate its behavior in some integrated environment.&lt;br /&gt;&lt;br /&gt;The tests get brittle when you mock things that have no business being mocked.  What I started doing was creating everything as a stub and then used the Rhino Mocks AssertWas/WasNotCalled() extension methods.  Things end up being much cleaner and far less prone to unexpected test failures.&lt;br /&gt;&lt;br /&gt;But I ramble.  We're coders.  Let's look at some code.  Here's an example of a test I wrote using Context/Specification  (a style of testing supporting &lt;a href="http://dannorth.net/introducing-bdd"&gt;BDD&lt;/a&gt;) and the &lt;a href="http://codebetter.com/blogs/aaron.jensen/archive/2008/09/02/mspec-v0-2.aspx"&gt;MSpec library&lt;/a&gt;.  Everything is a stub and I use the AssertWas/WasNotCalled() to assert that certain collaborations occurred the way I had expected them to.&lt;br /&gt;&lt;br /&gt;Forgive the user_registration_scenario class as I use it as the base class for a number of scenarios not shown here.  It's the collection of inputs/collaborators used for the test and, per &lt;a href="http://blog.scottbellware.com/2008/07/sustaining-capacity-in-maturing-agile_14.html"&gt;Context/Specification&lt;/a&gt;, the Act of Arrange/Act/Assert is at a class level, not at a method level.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;[Concern(typeof(UserAccountCreationService))]&lt;br /&gt;public class When_a_user_registers_successfully : user_registraton_scenario&lt;br /&gt;{&lt;br /&gt;    Establish context = () =&amp;gt;&lt;br /&gt;    {&lt;br /&gt;        var no_errors = new List&amp;lt;ErrorInfo&amp;gt;();&lt;br /&gt;&lt;br /&gt;        _modelValidator&lt;br /&gt;            .Expect(v =&amp;gt; v.Validate(_account))&lt;br /&gt;            .Return(no_errors);&lt;br /&gt;&lt;br /&gt;        _userRepository&lt;br /&gt;            .Expect(r =&amp;gt; r.UsernameExists(_account.Username))&lt;br /&gt;            .Return(false);&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    Because of = () =&amp;gt; _service.Create(_account);&lt;br /&gt;&lt;br /&gt;    It should_send_confirmation_email =()=&amp;gt;&lt;br /&gt;        _emailService.AssertWasCalled(es =&amp;gt; es.SendConfirmationEmail(_account));&lt;br /&gt;&lt;br /&gt;    It should_save_user_to_persistent_store =()=&amp;gt;&lt;br /&gt;        _userRepository.AssertWasCalled(r =&amp;gt; r.CreateUserAccount(_account));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class user_registraton_scenario&lt;br /&gt;{&lt;br /&gt;    protected static IEmailService _emailService;&lt;br /&gt;    protected static IUserRepository _userRepository;&lt;br /&gt;    protected static IModelValidator _modelValidator;&lt;br /&gt;    protected static UserAccountCreationService _service;&lt;br /&gt;    protected static UserAccount _account;&lt;br /&gt;&lt;br /&gt;    Establish context = () =&amp;gt;&lt;br /&gt;    {&lt;br /&gt;        _account = new UserAccount { Username = "kdog" };&lt;br /&gt;        _modelValidator = MockRepository.GenerateStub&amp;lt;IModelValidator&amp;gt;();&lt;br /&gt;        _emailService = MockRepository.GenerateStub&amp;lt;IEmailService&amp;gt;();&lt;br /&gt;        _userRepository = MockRepository.GenerateStub&amp;lt;IUserRepository&amp;gt;();&lt;br /&gt;        _service = new UserAccountCreationService(_userRepository, _emailService, _modelValidator);&lt;br /&gt;    };&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I might remark that I'm quite enamored with Context/Specification.  I never liked the look of my tests so much.  At work, it's agonizing because we're still at a very basic level of unit testing.  I'm thinking of giving a presentation on BDD using MSpec...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-4585359252649998154?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/4585359252649998154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=4585359252649998154' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/4585359252649998154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/4585359252649998154'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2009/09/i-dont-mock-much-anymore.html' title='I don&apos;t mock much anymore'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-1523107465882643772</id><published>2009-04-12T20:00:00.000-07:00</published><updated>2009-04-12T20:36:30.191-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dependency injection'/><title type='text'>Constructor injection FTW</title><content type='html'>I prefer using constructor injection with &lt;a href="http://en.wikipedia.org/wiki/Dependency_injection"&gt;DI&lt;/a&gt; for a few simple reasons.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;It's self-documenting code.  It's explicitly telling clients or maintainers of the component how it's put together.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It keeps my components honest.  In most cases, excessive constructor arguments is a code smell.&lt;/li&gt;&lt;/ol&gt;I also don't like setter injection for a few simple reasons.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;It adds noise to component's API.  I wouldn't want to see public properties hanging off a component that serves's me no use as a client.&lt;/li&gt;&lt;li&gt;It feels like it breaks encapsulation.  How the component does its work internally shouldn't be part of its public API.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It obfuscates how the component is put together.&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/167738975296784101-1523107465882643772?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/1523107465882643772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=1523107465882643772' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/1523107465882643772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/1523107465882643772'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2009/04/constructor-injection-ftw.html' title='Constructor injection FTW'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-5997150833238310082</id><published>2009-04-09T21:51:00.000-07:00</published><updated>2009-04-10T10:37:06.689-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Finally; ubuntu installs...no problems!</title><content type='html'>This has been a WIP since years and years now.  I install the latest version of Ubuntu two or three times a year mostly because I'm curious and partially because I'm a masochist.  I generally want to get into using an open source OS and just be aware of how things work on the other side of the fence (being a Windows user and .NET developer).  That's also why I chose Ubuntu; it's the entry-level linux distro.&lt;br /&gt;&lt;br /&gt;Things usually work out this way;  I install Ubuntu and there are issues.  Wireless has never worked out-of-the-box.  The graphics are 50-50.  Sometimes they work and other times they don't.  I've done the whole ndiswrapper thing and iwconfig and messed around on the command line more than any Windows user should ever have to feel comfortable with.  Things never end up pretty and are generally unstable.&lt;br /&gt;&lt;br /&gt;For instance, my last installation was Ubuntu 8.04.  Wireless didn't work.  Graphics were fine.  I sacrificed the customary chicken and goat and eventually got the wireless to work.  But then after I did a restart it stopped working again.  Then it intermittently worked until finally it stopped working altogether.  Completely random.&lt;br /&gt;&lt;br /&gt;I tethered my laptop to the wired network and decided to updgrade Ubuntu to 8.10.  After I did, the bootup had the funniest behavior.  It would stop booting unless I pressed keys.  Nothing in particular.  Just pressing keys would make it advance.  Once I booted into the desktop it said there were new drivers for the nVidia graphics card.  I let the update take place (the drivers were recommended by Ubuntu).  When I restarted, I couldn't get to the desktop anymore.  One of the startup steps would fail and it would die.  I'm not a linux ninja so it was as good as dead.&lt;br /&gt;&lt;br /&gt;I burned down the now defunct Ubuntu 8.10 install.  I downloaded and installed Kubuntu 8.10 out of sheer desperation.  It too demonstrated the "press some goddam keys to boot" behavior so this wasn't an isolated incidence.  Once I got to the desktop it didn't recognize I had wireless card at all and the graphics chip wasn't detected either.  I was worse off than when I was just in Ubuntu 8.10.  Fail.&lt;br /&gt;&lt;br /&gt;That was last night.  Today, I see that there's ubuntu 9.04 experimental.  I installed it, it detected my wireless and it only took a minor spiritual channeling to get the graphics to work.  Needless to say, I am happy that things just worked out-of-the-box.  This blog post has come from my linux desktop.  Joyous day!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-5997150833238310082?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/5997150833238310082/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=5997150833238310082' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/5997150833238310082'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/5997150833238310082'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2009/04/finally-ubuntu-installsno-problems.html' title='Finally; ubuntu installs...no problems!'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-4478479354738162477</id><published>2009-04-06T20:22:00.001-07:00</published><updated>2009-04-10T20:32:05.548-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mvc'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='Hot Features'/><title type='text'>Hot feature storm and digging into ASP.NET MVC</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Hot feature&lt;/span&gt; - A feature that is released as a hotfix usually due to an overly complex or bloated release process that makes normal releases a burden on the entire organization.  Those wishing to circumvent the release process will hide features in hotfixes and have them pushed out without any of the normal safety nets used for an official release.&lt;br /&gt;&lt;br /&gt;Hi and welcome to my life for the last month.  Hot features suck.  As a developer, I've never felt so dirty or violated.  The things I do for money...&lt;br /&gt;&lt;br /&gt;The story; we built a releasable product but never got an official release for it due to lack of QA resources and the overall brutal release process we have now (4 days for the automated QA tests to run! Bullshit!).  The solution that was worked out was that I had to tear apart the product and release each feature as a hotfix (henceforth, hot feature).  Decomposing a product for its features in a non-chronological order was a nightmare in and of itself given how code evolves.  This was only compounded by the fact that there was perfect storm of daily issues that would block or bump these hot features.  There was one day where I had to tear apart the product 3 times, each time adding or removing a feature until ultimately, we didn't release anything at all.  I will never partake in such a thing ever again.&lt;br /&gt;&lt;br /&gt;Tomorrow we push out the last of the hot features and I'll officially be switching teams.  My new role is much like my existing role.  I'm generally involved with modeling the solution domain and implementing the application layer.  One of the first things my team lead has indicated to me is that I'll be working on some new web pages and the platform of choice is going to be ASP.NET MVC.  This is thrilling news for me as I've never cut my teeth on any MVC platform.  I've been reading about it, I bought a Ruby book that just arrived today so that I could try out rails and I'm hearing stuff all the time from &lt;a href="http://blog.elliottohara.com/"&gt;Mr. O'Hara&lt;/a&gt; about his MVP framework.&lt;br /&gt;&lt;br /&gt;As the .NET web dev world knows, &lt;a href="http://www.asp.net/mvc/"&gt;ASP.NET MVC 1.0&lt;/a&gt; was RTM'ed a few weeks back.  I've kept it on my radar but hadn't invested any time into it.  Not because I don't care but that I've been involved with a brutal release schedule at work (as outlined above) and a newborn child.  This last weekend I finally had a chance to download it and take it for a spin.&lt;br /&gt;&lt;br /&gt;I've been developing with web forms since time out of mind and I haven't really known anything else.  They've never felt quite right and given my gravitation towards TDD, it's become apparent, more than ever, that it's just not the right solution for me.  I can't test the way I want to and I have to struggle against web forms to create logic that fits the web forms domain, not my product's domain.  I've got the page lifecycle down pat and it was a great introductory solution for me to get acquainted with web app development but it just creates tightly coupled code by default.&lt;br /&gt;&lt;br /&gt;My first impression of MVC; I'm smitten.  It just flows the way my mental model of the application layer should be behaving.  As far as ASP.NET MVC I'm glad I hopped on at 1.0 since they've improved it considerably since the betas.  What it allows me to do is nearly forget the fact that I'm working on the web (outside of rendering the views).  Controllers create the workflow of the app and they create truly meaningful names and actions that speaks directly to what you're modeling.  It's liberating from my years of web forms oppression.&lt;br /&gt;&lt;br /&gt;I really want to articulate for all 3 readers in my audience how this has liberated me and one example ran through my mind that captured it perfectly.  Let's take the example of some portion of a simple banking application where we want to save a deposit.  Use your imagination as to how it should behave.&lt;br /&gt;&lt;br /&gt;In web forms, I load an account on Page_Load and I tie into the button click event of a web control to submit a deposit from a user.&lt;br /&gt;&lt;pre class="brush: csharp"&gt;public partial class AccountPage : System.Web.UI.Page&lt;br /&gt;{&lt;br /&gt;    protected void Page_Load(object sender, EventArgs e)&lt;br /&gt;    {&lt;br /&gt;        //Load the account&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected void btnSaveDeposit_Click(object sender, EventArgs e)&lt;br /&gt;    {&lt;br /&gt;        //Save the deposit&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;In MVC, I speak to the AccountController and I tell it to load an account or save a deposit.&lt;br /&gt;&lt;pre class="brush: csharp"&gt;public class AccountController : Controller&lt;br /&gt;{&lt;br /&gt;    public ActionResult LoadAccount(int accountId)&lt;br /&gt;    {&lt;br /&gt;        //Load an account and show it to the user.&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public ActionResult Save(Deposit deposit)&lt;br /&gt;    {&lt;br /&gt;        //Save the deposit&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Do you see the difference in the way you think about this code?  Web forms have the unintentional side effect of obfuscating the workflow of your application.  It's noise that doesn't speak to anything.  What the hell is Page_Load and why do I care about intercepting events to a button?  Why do I need event arguments that I'm not going to use?  What does this all have to do with a bank account or saving a deposit?  &lt;br /&gt;&lt;br /&gt;Absolutely nothing.  You get mired in the details of the page lifecycle and all the black magic you have to employ to do what should normally be simple activities.  I can never forget lessons like "Don't forget to load dynamic controls at page init or else their viewstate is lost!" or "Always load your data on prerender as events are fired after page load and you may end up displaying stale data!".  I just have a hard time caring for web forms, the page request life cycle, and all the bloat that comes with their attempt at creating a stateful application on a stateless medium.&lt;br /&gt;&lt;br /&gt;With MVC, it makes perfect sense.  My workflow is clearly illustrated, my purpose is outlined with meaningfully named actions and we can get strongly typed arguments.  There is no ambiguity, this is no unexpected behavior and despite it's learning curve, I can show this to anyone and they will get an idea of how the application flows.&lt;br /&gt;&lt;br /&gt;So, this is my first impression and what I've witnessed.  As a 1.0 product it's no doubt rough around the edges and it seems like there's a lot of work to be done to ease the pain of creating the views as the web controls built for web forms can't (for the most part) be dropped into an MVC view.  The tutorials on the main website are also light on details.  They aren't tutorials so much as they are quickstarts.  I had to munge around to find out how some things worked.  Other than that, it looks to be a fun platform and I'll report back when I have more dirty details about my travels in ASP.NET MVC land.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-4478479354738162477?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/4478479354738162477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=4478479354738162477' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/4478479354738162477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/4478479354738162477'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2009/04/hot-feature-storm-and-digging-into.html' title='Hot feature storm and digging into ASP.NET MVC'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-3129162587488191168</id><published>2009-03-26T21:53:00.000-07:00</published><updated>2009-03-26T23:03:48.839-07:00</updated><title type='text'>Holy smokes, do I have a lot to learn</title><content type='html'>It's been a loooooooooong time since I really invested in my technical expertise as a developer.  Sure, I've grown a ton over the last year and I've really "come into my own" but as far as the latest and greatest talks, toys and technology platforms, my head is still somewhere in late 2007.  Luckily, podcasts and prolific blog writers are making my education far easier than I could have imagined.  At the same time I'm absorbing massive quantities of information that I hope I can retain at least 50% of.  Here's a shortlist of the craziness swimming in my mind.&lt;br /&gt;&lt;br /&gt;I made a small quest into truly learning what Javascript is all about and I'm happy to report that it really is an awesome tool.  It's been getting a bad rap for a number of years but it's really turned out to be a simple but effective language.  I've been getting interested in dynamic languages overall and I used Javascript as an opportunity to check out something I've already meddled with AND I can program with nothing more than Notepad and a browser (how effing sweet is that?).  Seriously, I'm sick of compilation.  I waste an hour of my day every day compiling projects.  But that's beside the point.  Javascript is great.  Go check it out, understand closure, understand that everything is a module (function, whatevs) and dynamic languages are not as scary as you've been programmed to believe.&lt;br /&gt;&lt;br /&gt;I've begun to study domain driven design simply so I can see what all the hoopla is about.  At first, you'll be patting yourself on the back since it's talking about things that any seasoned programmer is familiar with.  You have your solution domain where you model your customers or orders or whatever it is that your software is trying to solve.  But it's more than that.  It's creating discipline and drawing lines and boundaries where you may not have considered them before.  It's trying to promote &lt;span style="font-style:italic;"&gt;clarity&lt;/span&gt; not &lt;span style="font-style:italic;"&gt;purity&lt;/span&gt;.  &lt;br /&gt;&lt;br /&gt;Case in point, I was involved with a recent code review where I came across some code that had a distinct smell.  Upon discussing the issue with the developer submitting the review it was revealed that the code existed due to a hack from an external system.  Basically, the external system didn't have a way to model some financial transaction so it used another financial transaction to "hack" it into the system.  For example, it's like recording a negative deposit to some banking software because the software doesn't have a function to withdraw money.  Some of the DDD literature I've been reading recently points to the simple fact that we're no longer modeling the domain.  We're modeling the hack of another system.  Frankly, you don't need DDD to see this as a problem but it certainly brings it into perspective.  It brings confusion to the codebase, to the domain, to any developers coming on board, the code that evolves from this will be as bent and unsightly as its ancestors and so forth.  I may have not given this as much scrutiny had I not had so much DDD dancing through my mind.&lt;br /&gt;&lt;br /&gt;I read Ken Schwaber and Mike Beedle's &lt;a href="http://www.amazon.com/Agile-Software-Development-Scrum/dp/0130676349"&gt;Agile Software Development with Scrum&lt;/a&gt; since the scrum tsunami is about to crash on my development organization.  I'm drinking the Kool Aid so I'm not so concerned about whether or not it's a good methodology.  The only thing that worries me is if the management cast can stomach it when I actually speak up and collaborate in ways I had never done before.  If what I read is true then I should be telling them when what we're doing is ill advised.  I continuously read that I am now "empowered".  We'll have to see how that ultimately shakes out...&lt;br /&gt;&lt;br /&gt;I started digging into .NET 3.5 and some of the niceties that have come to the framework.  Nothing too serious but I hope to be writing a new web app with it soon.  I'm particularly interested in ASP.NET MVC since that's now in 1.0.  I've downloaded everything, now I just need to do something with it.&lt;br /&gt;&lt;br /&gt;Other stuff that's on my radar but I haven't played with yet is Fluent NHibernate, Structure Map, Ruby, and DSLs.  I think I may have a post or two coming to discuss some thoughts that those topics have generated for me.&lt;br /&gt;&lt;br /&gt;In any case, my brain is running dry and it's 2am.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-3129162587488191168?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/3129162587488191168/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=3129162587488191168' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/3129162587488191168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/3129162587488191168'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2009/03/holy-smokes-do-i-have-lot-to-learn.html' title='Holy smokes, do I have a lot to learn'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-6066188800805908203</id><published>2009-03-25T12:38:00.000-07:00</published><updated>2009-03-25T12:39:27.305-07:00</updated><title type='text'>XML sucks</title><content type='html'>Friggin' namespaces.  Such a pain in my ass.  JUST PARSE THE GODDAM VALUE!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-6066188800805908203?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/6066188800805908203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=6066188800805908203' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/6066188800805908203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/6066188800805908203'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2009/03/xml-sucks.html' title='XML sucks'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-2178222778360574713</id><published>2009-03-17T17:36:00.000-07:00</published><updated>2009-04-09T21:50:59.992-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamic Typing'/><category scheme='http://www.blogger.com/atom/ns#' term='Unit Test'/><title type='text'>Of C# Interfaces and dynamic typing</title><content type='html'>Adopting the design kung fu of TDD was one of the better practices I've picked up as a developer in the short time that I've been one.  I build out the behavior of my system with stable, solid code and maximum reward.  Due to its method of design (unit testing) I've also learned other important skills in creating loosely coupled code.&lt;br /&gt;&lt;br /&gt;The one style of programming that goes nearly hand-in-hand with TDD is programming against interfaces.  This is a decades old approach.  What I find to be the most enjoyable behavior of interfaces is the fact that it's breaking the client code from the implementing code.  You're trying to loosen up your coupling.  I used to think it was insulting to create an interface with any less than one implementing class.  I was missing the point.  I forget where I read it but I saw someone who summarized it wonderfully, “Creating interfaces is not to the benefit of the implementing code but rather to the client.”  Points to anyone who can help me find the original source.&lt;br /&gt;&lt;br /&gt;TDD becomes a natural litmus test for discovering when I should introduce an interface.  You get what's commonly called “test friction”.  Friction is simply noise in your tests that has nothing to do with the component you're testing.  It causes them to easily crash or be brittle, and makes it hard to test overall.  Anything that turns your tests into massive scripts or breaks often can be considered test friction.  Abstracting out the friction into interfaces is key to keeping the tests focused and your classes loosely coupled.&lt;br /&gt;&lt;br /&gt;At first you'll be surprised at how many interfaces you end up creating but then it eventually feels right.  The interfaces were always there between your objects, you're just formalizing it.  What's wrong with that?&lt;br /&gt;&lt;br /&gt;Well, actually, maybe a couple of things.  I do get annoyed with the ceremony of interfaces.  First I need to make the compiler happy.  I may have a class that perfectly conforms to the expected method signatures of an interface but I can't use that in place of that interface; it's not the right type.&lt;br /&gt;&lt;br /&gt;So then I need to create the interface every time I need to abstract something(which is often enough).  Being an obsessive, compulsive coder, I create a new file for it (although, from time to time, I may embed them with their default implementation).  I'm introducing noise into the project by having more files and more types to wade through in the auto-complete.  Not ideal.&lt;br /&gt;&lt;br /&gt;Recently I've looked at dynamically typed languages and felt a secret jealousy.  They don't have interfaces.  It's just good old fashioned &lt;a href="http://en.wikipedia.org/wiki/Duck_typing"&gt;duck typing&lt;/a&gt;.  It's just messages being passed between objects.  Why can't I do that?  I don't need an interface to pass messages between objects.  The object either accepts those messages or it doesn't.  No need to paint myself into a corner.  Testing becomes easier.  I create objects on the fly, mock/stub/fake them up with hardly the effort it takes in C#.  No extra interfaces necessary.&lt;br /&gt;&lt;br /&gt;I guess the root of this may be that I'm finding the world of statically typed languages to be confining.  It's been a feeling I've had for at least the last half of year or so.  I've had a hard time articulating what it is that bothers me but I'm seeing it at as these things that I'm being forced into obeying by the compiler.  Statically typed languages will certainly help you to avoid simple issues in your types but it can't guarantee you won't run into runtime issues anyways.  Who can say they've never encountered a InvalidCastException?  NullReferenceException?  Statically typed languages are still exposed to the same problems that dynamically typed languages are.  Compilation is providing compile-time debugging of your types.  But if you're already writing unit tests, which undoubtedly test the interfaces of your objects, does that negate the advantage of compile-time debugging?&lt;br /&gt;&lt;br /&gt;Most accounts that I've read of developers sharing a sentiment like my own usually end up embracing dynamically typed languages.  Some even switch specialization and jump ship.  I don't know what to do yet.  I guess I have to go and find out for myself.  &lt;br /&gt;&lt;br /&gt;There' an awesome alt.net podcast that really speaks to where my head is at.  It's an interview with Scott Bellware so if you dig his contributions to the community then you'll certainly enjoy this.  I strongly recommend you give it a listen.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://altnetpodcast.com/episodes/10-oop-in-ruby/"&gt;OOP in Ruby with Scott Bellware&lt;/a&gt;AOP&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-2178222778360574713?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/2178222778360574713/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=2178222778360574713' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/2178222778360574713'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/2178222778360574713'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2009/03/of-c-interfaces-and-dynamic-typing.html' title='Of C# Interfaces and dynamic typing'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-3922506695469954189</id><published>2009-03-16T07:37:00.000-07:00</published><updated>2009-03-16T07:40:07.034-07:00</updated><title type='text'>javascript unit testing/mocking framework?</title><content type='html'>I've looked around the web and I see a ton.  Can anyone give a recommendation on frameworks they've worked with?  I'm being lazy and avoiding testing every one that I find.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-3922506695469954189?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/3922506695469954189/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=3922506695469954189' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/3922506695469954189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/3922506695469954189'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2009/03/javascript-unit-testingmocking.html' title='javascript unit testing/mocking framework?'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-788489706970682148</id><published>2009-03-10T19:54:00.000-07:00</published><updated>2009-03-15T18:11:31.732-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xUnit'/><category scheme='http://www.blogger.com/atom/ns#' term='Unit Test'/><title type='text'>Why we do it: Unit Testing</title><content type='html'>What started me on this blog on such an elementary concept?  I could list a couple reasons.  There are those that don't unit test.  To them, unit testing is an annoyance.  They're experienced so they know exactly what the design and subsequent code will be.  Unit testing just slows them down.  I might comment that their defect rate is much higher than my own or that their code is far harder to modify or work with.  These things don't matter.  What matters is that when I face this resistance I need to be ready to respond with all the facts that negates any ill-informed opinions.&lt;br /&gt;&lt;br /&gt;The other reason I'm on this is that I've been listening to too many podcasts.  Notably some from Bob Martin (with his &lt;a href="http://www.infoq.com/presentations/craftmanship-ethics"&gt;craftsmanship movement&lt;/a&gt;) and Scott Bellware's &lt;a href="http://altnetpodcast.com/episodes/17-the-state-of-alt-net"&gt;less-than-complimentary view&lt;/a&gt; on recent alt.net activity.  They reasonably argue that developers latch onto the idea of using unit tests or practicing SOLID without ever knowing what benefit it is to them.  They can't quickly tell you why they use it.  In effect they're stagnating an otherwise progressive movement like alt.net by no longer questioning the practices that gave them the awesome methodologies and tools that they're using.&lt;br /&gt;&lt;br /&gt;As a final note, lots of the benefits of unit testing are sometimes attributed to TDD.  Recognize that TDD's primary goal is design and it is the beneficiary of unit testing.  From what I read, BDD was born from this fundamental misunderstanding.  This writing also assumes that we understand what good test writing is.  When you change code it shouldn't make 10% of your tests break.  That's a code smell.  If you find yourself in such a situation then I recommend reading the &lt;a href="http://xunitpatterns.com/"&gt;XUnit Test Patterns&lt;/a&gt; book.&lt;br /&gt;&lt;br /&gt;Without further adieu...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Unit tests are documentation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;They document your API and demonstrate its usage.  Test assertions are telling clients exactly how to specify the inputs to get the desired outputs.  Invalid and erroneous use cases are outlined.  Best practices for your code are emphasized.  For these reasons, you may see developers (like myself) that will forgive violating &lt;a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY&lt;/a&gt; in order to make the test more story-like and readable.  You want anyone to read the script and "get it".&lt;br /&gt;&lt;br /&gt;Unit tests are better than documentation.  Code comments, UML diagrams, design docs, etc. go stale within minutes of the ink drying.  They aren't reliable for anything but the most static systems.  That's not to say that they don't have their place but ,for the sake of development, they're best expressed in white board sessions and reflected in the code.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Unit tests are security&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Good unit tests execute in fractions of a second and running the whole test suite should take a few seconds at most.  If your unit testing suite executes on the order of minutes then they aren't unit tests.  &lt;br /&gt;&lt;br /&gt;They are your safety net for regression.  Introducing change to the system will raise red flags anywhere that has been impacted.  This immediate feedback loop allows us to fix problems before they go out the door as defects.  It also illustrates defects in design.  Making a simple change that implodes half of your test suite indicates that the recipient of the change is a dependency attractor.&lt;br /&gt;&lt;br /&gt;I'll add the obligatory mention of ease of refactoring.  The added security of unit tests allows you to confidently refactor your code with little fear of breaking the system.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Unit tests preclude debugging&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At one point in my life I thought it was the best thing ever to be able to walk through my code, examine values, change them, simulate branching logic and so forth.  No code could be a mystery to me because I could interrogate it in the watch window and make it tell its secrets.  I'd be lying if I said that it didn't save my ass on more than one occasion.&lt;br /&gt;&lt;br /&gt;Flash forward to today.  I hate debugging.  Debugging is a hassle.  Someone has a problem in code then I have to go do a source control update, get the latest dependencies, do a build, work through peripheral issues in getting my integration environment up to snuff, somehow ham-bone data in the DB to recreate the issue BEFORE I can even begin to execute the debugger.  Then, after I run through the debugger once, I have to do a DB restore or some other voodoo magic to restore my integration environment so that I may try again.&lt;br /&gt;&lt;br /&gt;Imagine my shock and surprise when the problem that warranted the debugging session was as pathetic and minor as are most defects I've worked through.  In fact, I can't remember the last time I found a defect that was anything more than an uninitialized value or an unexpected branching.  It's almost heart breaking to make this discovery as you'd hope it would be some mythical code beast that needs slaying so then at least traveling minstrels and bards will sing songs of your valor and courage (Monty Python just sprung to mind).&lt;br /&gt;&lt;br /&gt;Unit testing isolates the units of the system (duh).  Recreating and driving out defects can be done without firing up any debuggers.  Some TDD practitioners will profess that they never have to use a debugger, ever.  The tests themselves provide the debugging.  I can't make such a boast.  The point is that you will be less involved with debugging because you will have appropriately addressed the conditions that create defects and you can easily hop into and test the code that is throwing the error.  Debugging becomes a "break glass in case of emergency" type utility.  You only need it in extreme circumstances.&lt;br /&gt;&lt;br /&gt;One thing that I can boast is that integration or functional tests seem to be a formality now.  I can almost always guarantee that my code works right out of the box before I deploy it to an integrated environment.  It's a very satisfying thing to me and to clients of my code.&lt;br /&gt;&lt;br /&gt;AUTHOR'S NOTE:  I kind of got bored with this post halfway through it so if you're not feeling the love then neither was I.  It's not you, baby, it's me.  I'm just getting this out there since I've spent enough time looking at it in my posting queue.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-788489706970682148?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/788489706970682148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=788489706970682148' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/788489706970682148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/788489706970682148'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2009/03/why-we-do-it-unit-testing.html' title='Why we do it: Unit Testing'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-4918342369231046560</id><published>2009-03-07T22:14:00.001-08:00</published><updated>2009-03-07T22:14:59.082-08:00</updated><title type='text'>Testing code highlighter</title><content type='html'>This should look snazzy.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public interface IComicBookRepository&lt;br /&gt;{&lt;br /&gt;     ComicBookCollection GetComicsByGenre(Genre genre);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-4918342369231046560?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/4918342369231046560/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=4918342369231046560' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/4918342369231046560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/4918342369231046560'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2009/03/testing-code-highlighter.html' title='Testing code highlighter'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-4522972295999772989</id><published>2009-03-07T20:27:00.001-08:00</published><updated>2009-03-12T07:09:52.822-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='decorator pattern.'/><category scheme='http://www.blogger.com/atom/ns#' term='Aspect Oriented Programming'/><title type='text'>Decorator pattern: alternative to using AOP?</title><content type='html'>I've wanted to check out some of the &lt;a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming"&gt;Aspect Oriented Programming&lt;/a&gt; frameworks out there just to get a feel for how they behave in the code.  I understand the paradigm and the vocabulary but I haven't really played around with it.  AOP is one of those things I keep promising myself to check out but I always put it off.  Now I'm finally sitting down to check out what's around and how it would fit in with my day-to-day.&lt;br /&gt;&lt;br /&gt;If you're an AOP framework you're generally implemented in one of two ways; either you're compile-time and the code is "weaved" into the class of choice or you're runtime and a proxy is generated for the class in question.  Basically, you're looking to attach some behavior to a class that will happen before a method call, after a method call or when an exception is thrown.&lt;br /&gt;&lt;br /&gt;AOP being a tool in my six-demon bag, I have to see how it can improve any of my current projects.  Right now, I only have the ubiquitous logging issue that is commonly mentioned in the same breath as AOP.  The usual problem is thus; you have some component who's main concern is not logging wonderfully verbose diagnostic information but rather that it builds a list of accounting records for export to a general ledger or it's approximating how late an MBTA train can be before the commuting populace riots.  To keep the gods of Truth and Beauty satisfied you must separate these concerns.&lt;br /&gt;&lt;br /&gt;My only problem is that I may have already.  I hadn't seen it done this way before but I was using the &lt;a href="http://en.wikipedia.org/wiki/Decorator_pattern"&gt;decorator pattern&lt;/a&gt; to effectively perform the same work that an AOP framework would.  I had fallen into using decorator pattern recently to eliminate inappropriate inheritance (just about any inheritance is inappropriate to me but that's a topic for another post).  Think of it this way; the AOP framework is providing a mechanism to intercept method calls and do some magic before or after the a method is executed.  The decorator pattern is doing just that.  I'll break down the pros and cons for using an AOP framework or using the decorator pattern in a moment but here's a code snippet to demonstrate the thought.&lt;br /&gt;&lt;br /&gt;NOTE: For the sake of brevity I'm hoping you can make logical leaps about the types and classes I'm using.  They're purely fictional and they're not what's important.&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public interface IComicBookRepostitory&lt;br /&gt;{&lt;br /&gt;    ComicBookCollection GetComicsBy(SearchParameters searchParams);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;An IComicBookRepository is simply a repo for comic books.  In this case it has a method for retrieving comic books by a set of parameters.  The concrete class for the repo looks like the following.&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public class ComicBookRepository : IComicBookRepostitory&lt;br /&gt;{&lt;br /&gt;    public ComicBookCollection GetComicsBy(SearchParameters searchParams)&lt;br /&gt;    {&lt;br /&gt;        return new ComicBookCollection();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This class obviously does nothing of import but that's ok.  We can fill this in with whatever we please when we know what that implementation will look like.&lt;br /&gt;&lt;br /&gt;I can create a class that will "decorate" any instance of IComicBookRepostitory with error logging.  Hence the LoggedComicBookRepository.&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public class LoggedComicBookRepository : IComicBookRepostitory&lt;br /&gt;{&lt;br /&gt;    private ILog _log;&lt;br /&gt;    private IComicBookRepostitory _wrappedRepo;&lt;br /&gt;&lt;br /&gt;    public LoggedComicBookRepository(ILog log, IComicBookRepostitory wrappedRepo)&lt;br /&gt;    {&lt;br /&gt;        _log = log;&lt;br /&gt;        _wrappedRepo = wrappedRepo;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public ComicBookCollection GetComicsBy(SearchParameters searchParams)&lt;br /&gt;    {&lt;br /&gt;        try&lt;br /&gt;        {&lt;br /&gt;            _wrappedRepo.GetComicsBy(searchParams);&lt;br /&gt;        }&lt;br /&gt;        catch (ArgumentException ex)&lt;br /&gt;        {&lt;br /&gt;            _log.Error(&lt;br /&gt;                string.Format("Parameters: Genre {0}, Year {1}", searchParams.Genre, searchParams.Year), ex);&lt;br /&gt;            throw;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Notice that it contains an instance of an IComicBookRepostitory.  The LoggedComicBookRepository has a constructor that is configured with an ILog and an IComicBookRepostitory.  The ILog will capture logged messages and the IComicBookRepostitory is what is being wrapped (decorated per the pattern).  Whenever the wrapped instance of the IComicBookRepostitory throws an error it will be captured and the appropriate error logging will occur.  Calling GetComicsBy(searchParams) is now completely logged and our concrete ComicBookRepository is none the wiser.  Likewise, if we wanted to do more work before or after the method is called for any other reason then we may do so and capture the essence of AOP.  &lt;br /&gt;&lt;br /&gt;Here's some setup code that will perform comic book retrieval that will be logged.&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public class SomeClass&lt;br /&gt;{&lt;br /&gt;    public void DoSomething()&lt;br /&gt;    {&lt;br /&gt;        IComicBookRepostitory repo =&lt;br /&gt;            new LoggedComicBookRepository(&lt;br /&gt;                log4net.LogManager.GetLogger(GetType(LoggedComicBookRepository)),&lt;br /&gt;                new ComicBookRepository());&lt;br /&gt;&lt;br /&gt;        SearchParameters searchParams = new SearchParameters(Genre.Action, 1995);&lt;br /&gt;        ComicBookCollection collection = repo.GetComicsBy(searchParams);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That setup/configuration code can easily be hidden behind a DI container or something similar but I'm just illustrating how it would generally work.  &lt;br /&gt;&lt;br /&gt;The advantage to this is that I don't need to bring in a new library with XML configuration, code setup and an API that may not be familiar to other developers.  It's also swatting a fly with a bazooka.  In the scenario presented above we really don't need to involve a professional AOP solution.&lt;br /&gt;&lt;br /&gt;Where AOP makes sense is for a more generic scenario.  With the code I've been working with, I want to emit important information about specific method calls and their inputs.  If I didn't care for that then an AOP framework would be a far better choice.  For example, if I wanted to include code that profiled method execution then I could have a stopwatch that started on method entry and stopped on method exit using an AOP framework.  The only thing it may capture about the method is its name.  If I tried to hack an AOP framework into my previous example I would have to generate additional code that would provide mapping between method names, their overloads and the class that was responsible with logging each.&lt;br /&gt;&lt;br /&gt;So, once again, I've avoided digging into an AOP framework.  I know what I need to know and when I find the square hole I'll put the square block of AOP into it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-4522972295999772989?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/4522972295999772989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=4522972295999772989' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/4522972295999772989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/4522972295999772989'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2009/03/decorator-pattern-alternative-to-using.html' title='Decorator pattern: alternative to using AOP?'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-8487064314927257170</id><published>2009-03-06T21:15:00.000-08:00</published><updated>2009-03-06T22:56:54.783-08:00</updated><title type='text'>I've made up my mind</title><content type='html'>I want to write my own developer blog.  I really do.  I have two major enemies at the moment.  A lack of casual time and rabid curiosity.  The lack of time is self explanatory.  I have a 4 year old, a 2 month old baby and a demanding job.&lt;br /&gt;&lt;br /&gt;The "rabid curiosity" part is my laundry list of methodologies, technologies, practices and tools and I want to preview them all at the same time.  For example, I want to check out what the premier dependency injection framework is so I'll go read some blogs and documentation.  Someone will make a reference to BDD so I have to see what that is.  It's behavior driven design which is apparently the logical evolution of TDD.  So then I'll fire up another tab and start looking at that.  Someone mentions something about TypeMock so now I have to go see what that's all about.  Then I'll start reading the blog war around TypeMock and how it supposedly promotes writing untestable code.&lt;br /&gt;&lt;br /&gt;You can see where this is going.  At the end of this I can't say I have a demonstrable understanding in what it was I had initially set out to explore.  I picked up a handful of nuggets and have a general understanding but it's nothing I can make any good use of.&lt;br /&gt;&lt;br /&gt;I've recognized this and I've forced myself to give only a single topic of interest the bandwidth it needs.  This has worked out well.  I've been interested in scrum as it's coming to my company so I read Schwaber and Beedle's book on it.  I wanted to understand the wackiness of javascript so I spent a week and read around and played a bit.  Now I "get it".&lt;br /&gt;&lt;br /&gt;I'm going to continue on this path and start blogging a bit more on the experience.  It's the best way to learn and then demonstrate that I have a grasp on the subject.&lt;br /&gt;&lt;br /&gt;I also need to improve on my writing.  There was a time where I was never at a loss for words or had trouble communicating my thoughts.  I let that skill atrophy so I have to build it up again.  Bear with me in the meantime.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/167738975296784101-8487064314927257170?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/8487064314927257170/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=8487064314927257170' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/8487064314927257170'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/8487064314927257170'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2009/03/ive-made-up-my-mind.html' title='I&apos;ve made up my mind'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-167738975296784101.post-5802617684742451110</id><published>2008-10-15T09:06:00.000-07:00</published><updated>2008-10-16T11:15:28.025-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Aspect Oriented Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile Development'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='Computer Science'/><title type='text'>Too many interests, too little time</title><content type='html'>I have too many goddam things I want to check out in the world of software development and not nearly enough time to entertain them in any significant fashion.  There are a few tricklets missing or otherwise unpolished from my programming bag of demons that would prove to be valuable to my ability to dispense truth and beauty to the world of code.  Here's the latest group of stuff that I want to dig into:&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Ruby &lt;/span&gt;- Believe it or not I'm beginning to feel constrained in statically typed languages (it's a mostly love and partially hate relationship).  Ruby seems to be all the rage so I want to poke around in it.&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;AOP &lt;/span&gt;- I would love nothing more than to break logging out of the components I write.  I know I can abstract them out in one of a billion ways but I'd rather just have it be completely invisible to classes whose responsibilities should be focused on their task and not making sure log4net gets the message.&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Being a computer scientist &lt;/span&gt;- I got so wrapped into the abstraction of software that I stopped thinking about the science of it.  &lt;a href="http://steve-yegge.blogspot.com/2008/03/get-that-job-at-google.html"&gt;Steve Yegge&lt;/a&gt; reminded me just how much rust I've accumulated since graduating.&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Agile Development &lt;/span&gt;- I've read the manifestos and some online documentation but I haven't committed to reading more details or purchasing any publications.  The only reason I'm partially reluctant to start now is that it's a major uphill battle with my current team.  They aren't dumb and they read about this stuff but there's no interest there.  I'm not much on lobbying and I can't train them all (including the role of our manager).&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Right now I'm mixed between finding out what AOP offerings there are for .NET and playing in Ruby development.  I want to play with toys instead of read books.&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/167738975296784101-5802617684742451110?l=complextosimple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://complextosimple.blogspot.com/feeds/5802617684742451110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=167738975296784101&amp;postID=5802617684742451110' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/5802617684742451110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/167738975296784101/posts/default/5802617684742451110'/><link rel='alternate' type='text/html' href='http://complextosimple.blogspot.com/2008/10/too-many-interests-too-little-time.html' title='Too many interests, too little time'/><author><name>Nick Swarr</name><uri>http://www.blogger.com/profile/09030258577145290834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
