<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Los Techies</title><link>http://www.lostechies.com/blogs/</link><description>LosTechies.com was originally discussed a few years ago, over a couple of adult beverages whose name sounds very similar to l(D)os t(E)quies. Anyway the thought was to create a public forum where technical ideas and thoughts can be shared in the same way we all get together around a good meal and drinks. Ideas and thoughts are cultivated in discussion, and brought to fruition through professional debate and laughter. Sounds good in theory, well read our thoughts and ideas, take part in our debates and rejoice in our laughter.</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 (Build: 30929.2835)</generator><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/LosTechies" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item><title>Take 3: Python, ISP, IoC, and OCP need a fundamental rethink.</title><link>http://feedproxy.google.com/~r/LosTechies/~3/q-_BDCZFVeM/take-3-python-isp-ioc-and-ocp-need-a-fundamental-rethink.aspx</link><pubDate>Fri, 20 Nov 2009 19:23:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:33261</guid><dc:creator>Ryan Svihla</dc:creator><slash:comments>1</slash:comments><description>&lt;p&gt;In response to Julian’s thoughtful &lt;a href="http://www.colourcoding.net/Blog/archive/2009/11/20/dynamic-languages-and-solid-principles.aspx" target="_blank"&gt;Dynamic Languages and SOLID Principles&lt;/a&gt; I’d have to argue he is about 95% there but is missing the last critical links needed to view this in a whole different light. For ISP, Julian says it all:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Ultimately, I don't think ISP is changed by Python, it's just kind of irrelevant, for better or worse.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Exactly!&amp;#160; Why even bother mentioning in the context of dynamic languages. A developer that understands it fully and one that does not will code the same way. Whereas LSP is still taught in dynamic languages, I’ve never seen it called that but I’ve seen many admonishments about subclass consistency, and not making client code aware of the differences, and is something that requires mentioning. With ISP we could ignore it’s entire existence and developers would code the same.&lt;/p&gt;  &lt;p&gt;For OCP:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Well, the open closed principle is a goal, not a design practice, but let's take a look at the danger points: &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; * &lt;strong&gt;You can't have non-virtual methods, so Python wins this hands down.&lt;/strong&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; * &lt;strong&gt;Your variable can't be made too specific, so you're safe there.&lt;/strong&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; * You can still compare against hard-coded values.&amp;#160; It's just as easy to get this wrong in Python as it is in C#.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; * Same holds true for Law of Demeter violations.&amp;#160; If you pass the wrong object around, your code will be just as fragile in Python as in C#. &lt;/p&gt;    &lt;p&gt;&lt;strong&gt;Python certainly reduces the scope for some OC violations&lt;/strong&gt;, but you've still got lots of rope to hang yourself.&amp;#160; Think you still need to bear the goal in mind.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Bolding emphasis is mine. Enough of OCP is stripped and the primary ways its taught and demonstrated do not apply to the language at all. Focus on Law of Demeter, but having something that stands for “Open for extension” whenever everything is open and “Closed for modification” when nothing is closed would fall on completely deaf ears when presenting any of the associated ideas to a Python developer.&lt;/p&gt;  &lt;p&gt;For Dependency Inversion/ IoC:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Let's quote Ryan: &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; Now all calls in this runtime, from any module, that reference the Output class will use XmlOutput or HtmlOutput instead. &lt;/p&gt;    &lt;p&gt;Yes, but what if I wanted only half of them?&amp;#160; Maybe there's Python techniques I don't know about (I'm barely competent in the language) but as I see it, I'm going to need to change the code.&amp;#160; I don't think that dependencies can &amp;quot;always&amp;quot; be injected.&amp;#160; They can only be done when it won't cause damage.&amp;#160; In his case, he's worrying about testability.&amp;#160; That's fine, but we all agree there's more to DI than testability.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Ok firstly, I didn’t just mention testability, in fact that the code you’re referencing there was no unit test for, it was about flexibility.&amp;#160; Secondly, call Output an “Abstract Class”,and then call XmlOutput and HtmlOutput concrete types and then add them to an IoC container like Windsor then let me ask yourself the question you asked me “what if i wanted only half of them”.&amp;#160; There would be a need for custom code to make this resolution work for this custom circumstance.&amp;#160; All I’m advocating is taking that same exact custom code and place it somewhere else in Python (yes you can override per method, per instance, etc, etc).&amp;#160; &lt;/p&gt;  &lt;p&gt;I think there needs to be a principle that addresses the benefits of &lt;strong&gt;explicit&lt;/strong&gt; interfaces and well formed custom composition cases…and in those cases DI makes a lot more sense, but certainly not as a defacto convention and certainly is not required to provide flexibility to existing implementations.&amp;#160; It certainly becomes apparent when you start looking into the actual way IoC works in static languages its &lt;u&gt;all too similar to how a dynamic language runtime works&lt;/u&gt;. That code you’d use in a static language IoC to apply AOP, or custom composition rules, could just as easily be applied in a component in Python, &lt;u&gt;because the primary mechanism for an IoC to work is as a factory, and the benefits and features they bring are all derived from having access to how objects are created and then returned&lt;/u&gt;, when you always have access to how objects are created and returned anyway as in dynamic languages, why should you implement it a second time. 100% DI’d code will be more effort to maintain because it would be in C# too…if not for that fact the language is so “structured” that the flexibility and testability benefits gained &lt;strong&gt;far&lt;/strong&gt; outweigh the slightly increased cost (which is only brought down with the awesomeness of auto registering components).&amp;#160; In a language already with flexibility and testability whether you use DI or not AND without auto registering IoC containers the cost to maintain a full DI code base is I’d argue unacceptable. &lt;/p&gt;  &lt;p&gt;Summary, for SOLID to make any sense whatsoever in a dynamic context it has to amended and modified to fit that world. Maybe make SOLID into SELL for:&lt;/p&gt;  &lt;p&gt;S.RP &lt;/p&gt;  &lt;p&gt;E.xplicit empty class for required overrides&lt;/p&gt;  &lt;p&gt;L.SP&lt;/p&gt;  &lt;p&gt;L.aw of Demeter&lt;/p&gt;  &lt;p&gt;Maybe there is something containing other more valid concepts for the dynamic world that I’m probably not qualified to design or come up with. Anyway, I’ve enjoyed the conversation and I hope it brings about a firmer understanding of SOLID, and whatever we’ve not come up with yet for dynamic languages.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Take+3%3a+Python%2c+ISP%2c+IoC%2c+and+OCP+need+a+fundamental+rethink.&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2frssvihla%2farchive%2f2009%2f11%2f20%2ftake-3-python-isp-ioc-and-ocp-need-a-fundamental-rethink.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2frssvihla%2farchive%2f2009%2f11%2f20%2ftake-3-python-isp-ioc-and-ocp-need-a-fundamental-rethink.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=33261" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/38DA3DC5690712096190415D516ABCFC3BA1E204"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/38DA3DC5690712096190415D516ABCFC3BA1E204"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=q-_BDCZFVeM:w5zPSCSdMFU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=q-_BDCZFVeM:w5zPSCSdMFU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=q-_BDCZFVeM:w5zPSCSdMFU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=q-_BDCZFVeM:w5zPSCSdMFU:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/q-_BDCZFVeM" height="1" width="1"/&gt;</description><category domain="http://www.lostechies.com/blogs/rssvihla/archive/tags/Dynamic+Langs/default.aspx">Dynamic Langs</category><category domain="http://www.lostechies.com/blogs/rssvihla/archive/tags/IoC/default.aspx">IoC</category><feedburner:origLink>http://www.lostechies.com/blogs/rssvihla/archive/2009/11/20/take-3-python-isp-ioc-and-ocp-need-a-fundamental-rethink.aspx</feedburner:origLink></item><item><title>Why Chrome OS Will Succeed (in a limited market)</title><link>http://feedproxy.google.com/~r/LosTechies/~3/8k0j6Agv6r4/why-chrome-os-will-succeed-in-a-limited-market.aspx</link><pubDate>Fri, 20 Nov 2009 13:22:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:33123</guid><dc:creator>Eric Anderson</dc:creator><slash:comments>6</slash:comments><description>&lt;p&gt;Randall Kennedy released an excellent analysis of the Chrome OS that I &lt;a target="_blank" href="http://www.computerworld.com/s/article/9141207/Why_Chrome_OS_will_fail_big_time?taxonomyId=0&amp;amp;pageNumber=2"&gt;invite you to read&lt;/a&gt;.&amp;nbsp; In that analysis, Mr. Kennedy outlines why he believes that the Chome OS is doomed to fail miserably.&amp;nbsp; Though I haven't seen Chrome OS myself, I believe his read on the operating system is solid.&amp;nbsp; This is a stripped down operating system that basically locks the user into web applications with the Chrome browser as the interface.&amp;nbsp; The operating system is at its core a paired down version of linux and does not seem to support running desktop applications.&amp;nbsp; Because this is a this OS that only supports the web browser, Mr. Kennedy's analysis is that no user will want this running on their computer.&amp;nbsp; This is where Kennedy misses the point.&lt;/p&gt;
&lt;p&gt;From reports including Mr. Kennedy's article, Google will be releasing Chrome OS on a limited set of hardware.&amp;nbsp; Instead of having to deal with device drivers for a wide array of display adapters and whatnot, it appears that Google will be shipping Chrome OS on a constrained set of netbooks.&amp;nbsp; Kennedy looks at this limited set of hardware combined with the limited features of Chrome OS and determines that with all these restrictions, nobody will use the operating system.&amp;nbsp; This is where Kennedy has missed the point.&lt;/p&gt;
&lt;p&gt;Personally, I would be happy to have a netbook running Chrome OS on it.&amp;nbsp; With access to Google apps, I will still have simple spreadsheets and word processing inside of the full functional web browser.&amp;nbsp; I would use a Chrome OS netbook like, well, a netbook.&amp;nbsp; I would surf the web and check email.&amp;nbsp; My wife and I would keep it in the kitchen for looking up recipes on our favorite recipe sites.&amp;nbsp; My wife would use it to waste time on Facebook, er... "see what her friends are up to."&amp;nbsp; I would have to find a web Twitter client that I like since I'm guessing I wouldn't be able to run TweetDeck.&amp;nbsp; But, that's not a major loss.&lt;/p&gt;
&lt;p&gt;I don't want to run VisualStudio on my netbook.&amp;nbsp; I probably wouldn't care if I couldn't run Word.&amp;nbsp; As long as the user is looking for a simple web appliance that is better than a mobile phone while being lighter and less expensive than an entry laptop, then I think a Chrome OS netbook could be a suitable device.&amp;nbsp;&amp;nbsp; Yes, this is a narrow market.&amp;nbsp; No, Google won't be making a big dent in Windows (or Mac for that matter) with this device.&amp;nbsp; However, this could get them a decent footing in a tough market to make headway into.&lt;/p&gt;
&lt;p&gt;I, for one, welcome our new robot overlords&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Why+Chrome+OS+Will+Succeed+(in+a+limited+market)&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2feric%2farchive%2f2009%2f11%2f20%2fwhy-chrome-os-will-succeed-in-a-limited-market.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2feric%2farchive%2f2009%2f11%2f20%2fwhy-chrome-os-will-succeed-in-a-limited-market.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=33123" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/4E207C1542834195551C5B8476ADADD87F5BA70C"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/4E207C1542834195551C5B8476ADADD87F5BA70C"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=8k0j6Agv6r4:pKZxwsMfDh0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=8k0j6Agv6r4:pKZxwsMfDh0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=8k0j6Agv6r4:pKZxwsMfDh0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=8k0j6Agv6r4:pKZxwsMfDh0:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/8k0j6Agv6r4" height="1" width="1"/&gt;</description><category domain="http://www.lostechies.com/blogs/eric/archive/tags/Google/default.aspx">Google</category><category domain="http://www.lostechies.com/blogs/eric/archive/tags/Chrome+OS/default.aspx">Chrome OS</category><feedburner:origLink>http://www.lostechies.com/blogs/eric/archive/2009/11/20/why-chrome-os-will-succeed-in-a-limited-market.aspx</feedburner:origLink></item><item><title>A better Model Binder addendum</title><link>http://feedproxy.google.com/~r/LosTechies/~3/bBS8Y_0VOmw/a-better-model-binder-addendum.aspx</link><pubDate>Fri, 20 Nov 2009 02:31:19 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:32917</guid><dc:creator>bogardj</dc:creator><slash:comments>1</slash:comments><description>&lt;p&gt;A while back, I wrote about a &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/03/17/a-better-model-binder.aspx"&gt;ModelBinder enhancement&lt;/a&gt; we use to do arbitrary filtering on types.&amp;#160; The underlying matching algorithm only matches on one type, but we like to use layer supertypes for a lot of our domain objects, so we want to use a single model binder for every Entity or Enumeration type in our system.&lt;/p&gt;  &lt;p&gt;However, I missed an important piece in our model binding story: ModelState.&amp;#160; In the original implementation:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public override object &lt;/span&gt;BindModel(
    &lt;span style="color: #2b91af"&gt;ControllerContext &lt;/span&gt;controllerContext, 
    &lt;span style="color: #2b91af"&gt;ModelBindingContext &lt;/span&gt;bindingContext)
{
    &lt;span style="color: blue"&gt;foreach &lt;/span&gt;(&lt;span style="color: blue"&gt;var &lt;/span&gt;filteredModelBinder &lt;span style="color: blue"&gt;in &lt;/span&gt;_filteredModelBinders)
    {
        &lt;span style="color: blue"&gt;if &lt;/span&gt;(filteredModelBinder.IsMatch(bindingContext.ModelType))
        {
            &lt;span style="color: blue"&gt;return &lt;/span&gt;filteredModelBinder.BindModel(controllerContext, bindingContext);
        }
    }

    &lt;span style="color: blue"&gt;return base&lt;/span&gt;.BindModel(controllerContext, bindingContext);
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;I didn’t address ModelState.&amp;#160; It turns out that this may lead to problems later on when I use the built-in HtmlHelper methods.&amp;#160; These helper methods use ModelState to do things like set error message indicators, fill in values and so on.&amp;#160; But if one of the IFilteredModelBinder implementations binds a value but &lt;em&gt;doesn’t&lt;/em&gt; do the ModelState piece, I start to get some weird behavior in certain scenarios.&lt;/p&gt;

&lt;p&gt;If you start to dig pretty deeply in the DefaultModelBinder code, you’ll find that the base implementation of BindModel will set the ModelState values for certain scenarios.&amp;#160; In our case, we need to allow the IFilteredModelBinders to do something similar.&lt;/p&gt;

&lt;h3&gt;Our slight fix&lt;/h3&gt;

&lt;p&gt;First, we’ll need to fix the IFilteredModelBinder interface to return not just an object, but something that includes the ValueProviderResult object (used by ModelState).&amp;#160; Why not just do object?&amp;#160; Well, we can’t make an assumption on what the underlying model binder implementations need to do with a BindResult, it’s rather custom for each implementation.&amp;#160; So, our IFilteredModelBinder interface becomes:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public interface &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IFilteredModelBinder
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;bool &lt;/span&gt;IsMatch(&lt;span style="color: #2b91af"&gt;ModelBindingContext &lt;/span&gt;bindingContext);
    &lt;span style="color: #2b91af"&gt;BindResult &lt;/span&gt;BindModel(
        &lt;span style="color: #2b91af"&gt;ControllerContext &lt;/span&gt;controllerContext, 
        &lt;span style="color: #2b91af"&gt;ModelBindingContext &lt;/span&gt;bindingContext);
}&lt;/pre&gt;

&lt;p&gt;That BindResult object is not in MVC, it’s something we have to define:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;BindResult
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;public object &lt;/span&gt;Value { &lt;span style="color: blue"&gt;get&lt;/span&gt;; &lt;span style="color: blue"&gt;private set&lt;/span&gt;; }
    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ValueProviderResult &lt;/span&gt;ValueProviderResult { &lt;span style="color: blue"&gt;get&lt;/span&gt;; &lt;span style="color: blue"&gt;private set&lt;/span&gt;; }

    &lt;span style="color: blue"&gt;public &lt;/span&gt;BindResult(&lt;span style="color: blue"&gt;object &lt;/span&gt;value, &lt;span style="color: #2b91af"&gt;ValueProviderResult &lt;/span&gt;valueProviderResult)
    {
        Value = value;
        ValueProviderResult = valueProviderResult ?? 
            &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ValueProviderResult&lt;/span&gt;(&lt;span style="color: blue"&gt;null&lt;/span&gt;, &lt;span style="color: blue"&gt;string&lt;/span&gt;.Empty, &lt;span style="color: #2b91af"&gt;CultureInfo&lt;/span&gt;.CurrentCulture);
    }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;All object adds is the ValueProviderResult, providing a default null-object implementation if the implementing filtered model binder doesn’t support ValueProviderResults.&amp;#160; With this in place, we need to fix our SmartBinder:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;SmartBinder &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;DefaultModelBinder
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;private readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IFilteredModelBinder&lt;/span&gt;[] _filteredModelBinders;

    &lt;span style="color: blue"&gt;public &lt;/span&gt;SmartBinder(&lt;span style="color: #2b91af"&gt;IFilteredModelBinder&lt;/span&gt;[] filteredModelBinders)
    {
        _filteredModelBinders = filteredModelBinders;
    }

    &lt;span style="color: blue"&gt;public override object &lt;/span&gt;BindModel(
        &lt;span style="color: #2b91af"&gt;ControllerContext &lt;/span&gt;controllerContext, 
        &lt;span style="color: #2b91af"&gt;ModelBindingContext &lt;/span&gt;bindingContext)
    {
        &lt;span style="color: blue"&gt;foreach &lt;/span&gt;(&lt;span style="color: blue"&gt;var &lt;/span&gt;filteredModelBinder &lt;span style="color: blue"&gt;in &lt;/span&gt;_filteredModelBinders)
        {
            &lt;span style="color: blue"&gt;if &lt;/span&gt;(filteredModelBinder.IsMatch(bindingContext))
            {
                &lt;span style="color: blue"&gt;var &lt;/span&gt;result = filteredModelBinder.BindModel(controllerContext, bindingContext);

                bindingContext.ModelState.SetModelValue(
                    bindingContext.ModelName, 
                    result.ValueProviderResult);

                &lt;span style="color: blue"&gt;return &lt;/span&gt;result.Value;
            }
        }

        &lt;span style="color: blue"&gt;return base&lt;/span&gt;.BindModel(controllerContext, bindingContext);
    }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;It’s pretty much like the original, except that piece that does the SetModelValue part.&amp;#160; That fills in the necessary pieces for the input HtmlHelper methods to do their thing.&amp;#160; Interestingly, this made another problem go away, around &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/03/26/mvc-beta-to-rtw-upgrade-issue-addmodelerror-and-nullreferenceexceptions.aspx"&gt;ModelState.AddModelError&lt;/a&gt;.&amp;#160; It turns out I just missed a piece in the custom model binding code.&lt;/p&gt;

&lt;p&gt;So just a note to custom model binder implementors – don’t forget to populate the appropriate ModelState values, especially if the results of the binding operation will be used in conjunction with the HtmlHelper extensions.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=A+better+Model+Binder+addendum&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjimmy_bogard%2farchive%2f2009%2f11%2f19%2fa-better-model-binder-addendum.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjimmy_bogard%2farchive%2f2009%2f11%2f19%2fa-better-model-binder-addendum.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=32917" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/2B80D57BD5680235ABFF134511952D0C1900DC87"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/2B80D57BD5680235ABFF134511952D0C1900DC87"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=bBS8Y_0VOmw:kVNAUW2umqk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=bBS8Y_0VOmw:kVNAUW2umqk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=bBS8Y_0VOmw:kVNAUW2umqk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=bBS8Y_0VOmw:kVNAUW2umqk:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/bBS8Y_0VOmw" height="1" width="1"/&gt;</description><category domain="http://www.lostechies.com/blogs/jimmy_bogard/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><feedburner:origLink>http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/11/19/a-better-model-binder-addendum.aspx</feedburner:origLink></item><item><title>Take 2: Why we use SOLID in static languages and how we get the same functionality for cheap in dynamic languages</title><link>http://feedproxy.google.com/~r/LosTechies/~3/zuC9rwFiges/take-2-why-we-use-solid-in-static-languages-and-how-we-get-the-same-functionality-for-cheap-in-dynamic-languages.aspx</link><pubDate>Thu, 19 Nov 2009 22:46:17 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:32828</guid><dc:creator>Ryan Svihla</dc:creator><slash:comments>9</slash:comments><description>&lt;p&gt;One of the things we do pretty well at Los Techies is explaining SOLID principles and why they make our code more maintainable and if you’re not familiar with our work on SOLID,&amp;#160; read &lt;a href="http://www.lostechies.com/blogs/chad_myers/archive/2008/03/07/pablo-s-topic-of-the-month-march-solid-principles.aspx" target="_blank"&gt;Chad Meyer's post&lt;/a&gt; to get an understanding on the Los Techies perspective. Now that you’ve taken a bit of time to read that the following chart takes SOLID’s benefits and then shows how they apply to dynamic languages:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;table border="2" cellspacing="0" cellpadding="2" width="413"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Principle&lt;/td&gt;        &lt;td valign="top" width="121"&gt;Primary Benefit&lt;/td&gt;        &lt;td valign="top"&gt;Secondary Benefit&lt;/td&gt;        &lt;td valign="top" width="86"&gt;What dynamic langs do to replace said principle&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;Single Responsibility Principle (SRP)&lt;/td&gt;        &lt;td valign="top" width="121"&gt;Classes are in understandable units&lt;/td&gt;        &lt;td valign="top"&gt;Testability&lt;/td&gt;        &lt;td valign="top" width="86"&gt;Nothing&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;Open-Closed Principle (OCP)&lt;/td&gt;        &lt;td valign="top" width="121"&gt;Flexibility&lt;/td&gt;        &lt;td valign="top"&gt;Guidance&lt;/td&gt;        &lt;td valign="top" width="86"&gt;can override anything globally (monkey patch)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;Liskov Substitution Principle (LSP)&lt;/td&gt;        &lt;td valign="top" width="121"&gt;Not bleeding subclass specific knowledge everywhere&lt;/td&gt;        &lt;td valign="top"&gt;Least surprise&lt;/td&gt;        &lt;td valign="top" width="86"&gt;Nothing&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;Interface Segregation Principle (ISP)&lt;/td&gt;        &lt;td valign="top" width="121"&gt;Interfaces are in understandable units&lt;/td&gt;        &lt;td valign="top"&gt;Less work for interface implementation&lt;/td&gt;        &lt;td valign="top" width="86"&gt;everything’s an interface (duck typing)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;Dependency Inversion Principle(DIP)&lt;/td&gt;        &lt;td valign="top" width="121"&gt;Flexibility&lt;/td&gt;        &lt;td valign="top"&gt;Testability&lt;/td&gt;        &lt;td valign="top" width="86"&gt;can override anything globally (monkey patch)&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The above is my opinion and I’m sure people will beat me to death because I’m just some dude not many people know about,&amp;#160; but I think I’ve got a grasp of what SOLID means in C# and I’ve grappled with it from a practical perspective.&lt;/p&gt;  &lt;p&gt;You’ll note when it comes to LSP and SRP dynamic languages really give you nothing at all, but OCP, ISP, and DI benefits wise are supplanted by language features in python, ruby, etc.&amp;#160; How does this happen? In the case of ISP and “duck typing” this should be pretty obvious, but in the cases of OCP, DIP&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;DIP/OCP testability achieved through C#:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:e5b017cf-53bf-4595-947f-f0e091cebf2b" class="wlWriterEditableSmartContent"&gt;&lt;div style="font-family:consolas,lucida console,courier,monospace"&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;FooBar&lt;/b&gt;&lt;/span&gt;&lt;span style="color:#008800"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&amp;#160;IFooService&amp;#160;_service;&lt;br/&gt;
&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;FooBar&lt;/b&gt;&lt;/span&gt;(IFooService&amp;#160;service)&lt;span style="color:#008800"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;_service&amp;#160;=&amp;#160;service;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;DoFoo&lt;/b&gt;&lt;/span&gt;()&lt;span style="color:#008800"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;_service.run();&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#888888"&gt;//testcode&lt;br/&gt;
&lt;/span&gt;&lt;span style="color:#336699"&gt;&lt;br/&gt;
[TestFixture]&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;FooBarSpec&lt;/b&gt;&lt;/span&gt;&lt;span style="color:#008800"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:#336699"&gt;&amp;#160;&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;[Test]&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;should_call_fooservice&lt;/b&gt;&lt;/span&gt;()&lt;span style="color:#008800"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;var&amp;#160;mockfoo&amp;#160;=&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;&amp;#160;Mock&amp;lt;IFooService&amp;gt;();&amp;#160;&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;var&amp;#160;foobar&amp;#160;=&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;&amp;#160;FooBar(mockfoo.&lt;span style="color:#888888"&gt;&lt;b&gt;object&lt;/b&gt;&lt;/span&gt;);&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;foobar.DoFoo();&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;mockfoo.Verify(foo=&amp;gt;foo.run())&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;/div&gt;
&lt;/div&gt;  &lt;p&gt;DIP/OCP equivalent testability achieved through Python:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:43448cf0-795f-4ea0-849f-d2a4ea4b9f61" class="wlWriterEditableSmartContent"&gt;&lt;div style="font-family:consolas,lucida console,courier,monospace"&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;FooBar&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;object&lt;/span&gt;):&lt;br/&gt;
&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;DoFoo&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;self&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;service&amp;#160;=&amp;#160;FooService()&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;service.run()&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#888888"&gt;#test&amp;#160;code&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;unittest&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;TestFooBar&lt;/b&gt;&lt;/span&gt;(unittest.TestCase):&lt;br/&gt;
&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;runmock&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;self&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#003388"&gt;self&lt;/span&gt;.fooservice_run_was_called&amp;#160;=&amp;#160;&lt;span style="color:#003388"&gt;True&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;test_do_fooservice_is_called&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;self&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;originalrun&amp;#160;=&amp;#160;FooService.run&amp;#160;&lt;span style="color:#888888"&gt;#storing&amp;#160;the&amp;#160;original&amp;#160;method&amp;#160;in&amp;#160;a&amp;#160;variable&amp;#160;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;FooService.run&amp;#160;=&amp;#160;&lt;span style="color:#003388"&gt;self&lt;/span&gt;.runmock&amp;#160;&amp;#160;&lt;span style="color:#888888"&gt;#&amp;#160;I'm&amp;#160;globally&amp;#160;overriding&amp;#160;the&amp;#160;method&amp;#160;call&amp;#160;FooService.run&amp;#160;AKA&amp;#160;Monkey&amp;#160;Patch&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;FooBar().DoFoo()&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;FooService.run&amp;#160;=&amp;#160;originalrun&amp;#160;&lt;span style="color:#888888"&gt;#globally&amp;#160;put&amp;#160;it&amp;#160;back&amp;#160;to&amp;#160;where&amp;#160;it&amp;#160;was&amp;#160;AKA&amp;#160;Monkey&amp;#160;Patch&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;assert&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#003388"&gt;self&lt;/span&gt;.fooservice_run_was_called&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br/&gt;
&lt;/div&gt;
&lt;/div&gt;  &lt;p&gt;Now rightfully you may say the Python version has a few more lines of code, and it certainly can be considered ugly…but don’t you see that I replaced an &lt;strong&gt;entire mocking library&lt;/strong&gt; in a few lines of code.&amp;#160; There are also mocking libraries and monkey patch libraries for Python that would shorten my line of code count further.&amp;#160; Testability and flexibility dovetail, but the &lt;strong&gt;global accessibility of class definitions &lt;/strong&gt;is understandably hard to grasp for the static mindset (it took me months), so we’ll continue on to flexibility:&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:5e9f357c-5a26-4e5b-a3bb-523f1138579f" class="wlWriterEditableSmartContent"&gt;&lt;div style="font-family:consolas,lucida console,courier,monospace"&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;interface&lt;/b&gt;&lt;/span&gt;&amp;#160;IOutput&lt;span style="color:#008800"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;save&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#888888"&gt;&lt;b&gt;string&lt;/b&gt;&lt;/span&gt;&amp;#160;fileloc,&amp;#160;ResultObjects[]&amp;#160;results);&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;XmlOutput&lt;/b&gt;&lt;/span&gt;:IOutput&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;save&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#888888"&gt;&lt;b&gt;string&lt;/b&gt;&lt;/span&gt;&amp;#160;fileloc,&amp;#160;ResultObjects[]&amp;#160;results)&lt;span style="color:#008800"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#888888"&gt;//&amp;#160;place&amp;#160;xml&amp;#160;specific&amp;#160;code&amp;#160;here&lt;br/&gt;
&lt;/span&gt;&lt;span style="color:#008800"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;HtmlOutput&lt;/b&gt;&lt;/span&gt;:&amp;#160;IOutput&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;save&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#888888"&gt;&lt;b&gt;string&lt;/b&gt;&lt;/span&gt;&amp;#160;fileloc,&amp;#160;ResultObjects[]&amp;#160;results)&lt;span style="color:#008800"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#888888"&gt;//&amp;#160;place&amp;#160;html&amp;#160;specific&amp;#160;code&amp;#160;here&lt;br/&gt;
&lt;/span&gt;&lt;span style="color:#008800"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;TestRunner&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&amp;#160;IOutput&amp;#160;_output;&lt;br/&gt;
&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&amp;#160;ITests&amp;#160;_tests;&lt;br/&gt;
&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;StoreTestResults&lt;/b&gt;&lt;/span&gt;(IOutput&amp;#160;output,&amp;#160;ITests&amp;#160;tests)&lt;span style="color:#008800"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;_output&amp;#160;=&amp;#160;output;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;_tests&amp;#160;=&amp;#160;tests;	&lt;br/&gt;
&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;RunTestsFromDir&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#888888"&gt;&lt;b&gt;string&lt;/b&gt;&lt;/span&gt;&amp;#160;testdirectory,&amp;#160;&lt;span style="color:#888888"&gt;&lt;b&gt;string&lt;/b&gt;&lt;/span&gt;&amp;#160;outfile)&lt;span style="color:#008800"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;var&amp;#160;results&amp;#160;=&amp;#160;_tests.GetResults(testdirectory);&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;_output.save(outputfile,&amp;#160;results)&lt;br/&gt;
&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#888888"&gt;//later&amp;#160;on&amp;#160;we&amp;#160;use&amp;#160;IoC&amp;#160;containers&amp;#160;to&amp;#160;make&amp;#160;this&amp;#160;chain&amp;#160;easy&amp;#160;&lt;br/&gt;
&lt;/span&gt;&lt;br/&gt;
pubilc&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;main&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#888888"&gt;&lt;b&gt;string&lt;/b&gt;&lt;/span&gt;[]&amp;#160;args)&lt;span style="color:#008800"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&amp;#160;&amp;#160;&lt;span style="color:#888888"&gt;//&amp;#160;imagine&amp;#160;contextual&amp;#160;resolution&amp;#160;is&amp;#160;happening&amp;#160;intelligently&amp;#160;&lt;br/&gt;
&lt;/span&gt;&amp;#160;&lt;span style="color:#888888"&gt;//&amp;#160;on&amp;#160;the&amp;#160;resolver&amp;#160;because&amp;#160;someone&amp;#160;did&amp;#160;some&amp;#160;cool&amp;#160;stuff&amp;#160;in&amp;#160;windsor&lt;br/&gt;
&lt;/span&gt;&amp;#160;&amp;#160;var&amp;#160;runner&amp;#160;=&amp;#160;testcontainer.Resolve&amp;lt;TestRunner&amp;gt;();&lt;br/&gt;
&amp;#160;&amp;#160;runner.RunTestsFromDir(args[&lt;span style="color:#0000DD"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;],&amp;#160;args[&lt;span style="color:#0000DD"&gt;&lt;b&gt;1&lt;/b&gt;&lt;/span&gt;]);&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;/div&gt;
&lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In Python with “monkey patching” everything is “Open For Extension” and dependencies can “always” be injected. A code sample based on my last blog post but extended to include some more complete client code follows:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:8bd30a7f-33bf-4693-a44d-5561882617e3" class="wlWriterEditableSmartContent"&gt;&lt;div style="font-family:consolas,lucida console,courier,monospace"&gt;
&lt;span style="color:#888888"&gt;#in&amp;#160;module&amp;#160;outputlib&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;Output&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;object&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;save&lt;/b&gt;&lt;/span&gt;(fileloc,&amp;#160;results):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;pass&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;XmlOutput&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;object&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;save&lt;/b&gt;&lt;/span&gt;(fileloc,results):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#dd2200"&gt;"""xml&amp;#160;specific&amp;#160;logic&amp;#160;here"""&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;pass&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;HtmlOutput&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;object&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;save&lt;/b&gt;&lt;/span&gt;(fileloc,results):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#dd2200"&gt;"""xml&amp;#160;specific&amp;#160;logic&amp;#160;here"""&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;pass&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;TestRunner&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;object&lt;/span&gt;):&lt;br/&gt;
&lt;br/&gt;
&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;run_tests_from_dir&lt;/b&gt;&lt;/span&gt;(testdirectory,&amp;#160;outfile):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;tests&amp;#160;=&amp;#160;Tests()&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;output&amp;#160;=&amp;#160;Output()&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;output.save(&amp;#160;&amp;#160;outfile&amp;#160;&amp;#160;,&amp;#160;tests.get_results(testdirectory)&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#888888"&gt;#rest&amp;#160;of&amp;#160;the&amp;#160;script&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;sys&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;outputlib&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;o&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
testdirectory&amp;#160;=&amp;#160;sys.argv[&lt;span style="color:#0000DD"&gt;&lt;b&gt;1&lt;/b&gt;&lt;/span&gt;]&lt;br/&gt;
outfile&amp;#160;=&amp;#160;sys.argv[&lt;span style="color:#0000DD"&gt;&lt;b&gt;2&lt;/b&gt;&lt;/span&gt;]&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt;&amp;#160;outfile.endswith(&lt;span style="color:#dd2200"&gt;"xml"&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;o.Output&amp;#160;=&amp;#160;o.XmlOutput&amp;#160;&lt;span style="color:#888888"&gt;#globally&amp;#160;override&amp;#160;calls&amp;#160;to&amp;#160;Output&amp;#160;with&amp;#160;XmlOutput.&amp;#160;AKA&amp;#160;Monkey&amp;#160;Patch&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;elif&lt;/b&gt;&lt;/span&gt;&amp;#160;outfile.endswith(&lt;span style="color:#dd2200"&gt;"html"&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;o.Output&amp;#160;=&amp;#160;o.HtmlOutput&amp;#160;&lt;span style="color:#888888"&gt;#globally&amp;#160;override&amp;#160;calls&amp;#160;to&amp;#160;Output&amp;#160;with&amp;#160;HtmlOutput&amp;#160;AKA&amp;#160;Monkey&amp;#160;Patch&lt;/span&gt;&lt;br/&gt;
runner&amp;#160;=&amp;#160;o.TestRunner()&lt;br/&gt;
runner.run_tests_from_dir(testdirectory,&amp;#160;outfile)&lt;br/&gt;
&lt;/div&gt;
&lt;/div&gt;  &lt;p&gt;Again this is longer code than the c# example.. but we’ve replaced an &lt;strong&gt;entire IoC container&lt;/strong&gt; and whatever custom code we would have had to add to create custom dependency resolver for selecting HTML or XML output options has now been replaced by a simple if else if conditional at the beginning of the code base execution. &lt;strong&gt; Now all calls in this runtime, from any module, that reference the Output class will use XmlOutput or HtmlOutput instead&lt;/strong&gt;, all with “monkey patching”.&lt;/p&gt;  &lt;p&gt;Hopefully, from here the rest of the dominos will fall into place once you get the concepts above, and the things we rely on SOLID for are in some cases already there in dynamic languages. Consequentially, my dynamic code looks (now) nothing like my static code because I no longer have to use DI/IoC to achieve my desired flexibility and access to use proper unit tests.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Take+2%3a+Why+we+use+SOLID+in+static+languages+and+how+we+get+the+same+functionality+for+cheap+in+dynamic+languages&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2frssvihla%2farchive%2f2009%2f11%2f19%2ftake-2-why-we-use-solid-in-static-languages-and-how-we-get-the-same-functionality-for-cheap-in-dynamic-languages.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2frssvihla%2farchive%2f2009%2f11%2f19%2ftake-2-why-we-use-solid-in-static-languages-and-how-we-get-the-same-functionality-for-cheap-in-dynamic-languages.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=32828" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/29C3B8602C2700880B6A94D358BF1F2D34606832"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/29C3B8602C2700880B6A94D358BF1F2D34606832"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=zuC9rwFiges:M-soxRqZZPI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=zuC9rwFiges:M-soxRqZZPI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=zuC9rwFiges:M-soxRqZZPI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=zuC9rwFiges:M-soxRqZZPI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/zuC9rwFiges" height="1" width="1"/&gt;</description><category domain="http://www.lostechies.com/blogs/rssvihla/archive/tags/Python/default.aspx">Python</category><category domain="http://www.lostechies.com/blogs/rssvihla/archive/tags/Dynamic+Langs/default.aspx">Dynamic Langs</category><category domain="http://www.lostechies.com/blogs/rssvihla/archive/tags/SOLID/default.aspx">SOLID</category><feedburner:origLink>http://www.lostechies.com/blogs/rssvihla/archive/2009/11/19/take-2-why-we-use-solid-in-static-languages-and-how-we-get-the-same-functionality-for-cheap-in-dynamic-languages.aspx</feedburner:origLink></item><item><title>Pablo’s Fiesta Open Space Conference</title><link>http://feedproxy.google.com/~r/LosTechies/~3/iWvp2UoGgFc/pablo-s-fiesta-open-space-conference.aspx</link><pubDate>Wed, 18 Nov 2009 15:51:22 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:32301</guid><dc:creator>chadmyers</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;In case you didn’t see it on the main Los Techies feed, John Teague and fellow Los Techian &lt;a href="http://www.lostechies.com/blogs/johnteague/archive/2009/11/16/pablo-s-fiesta-open-space-conference-in-austin-tx.aspx"&gt;announced “Pablo’s Fiesta”&lt;/a&gt;, Los Techies’ first Open Space conference.&lt;/p&gt;  &lt;p&gt;The sign-up page is here for more information: &lt;a href="http://fiesta.lostechies.com/"&gt;http://fiesta.lostechies.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;John Teague has taken the lead on this thing and has done an amazing amount of work on this in the past few days (not to mention several other Los Techies who have dedicated many hours of their own time to make this happen).&lt;/p&gt;  &lt;p&gt;We were hoping to make it free, but there’s some cost involved in the venue and probably a bunch of other stuff. At $15, I’m hoping you won’t think it’s too expensive.&lt;/p&gt;  &lt;p&gt;You can read more details on the site, but the gist is that it’s an Open Spaces conference, so YOU determine what the subject matter will be.&amp;#160; Personally, I’m hoping it’ll be focused on hard-core nuts and bolts stuff with real code and patterns and practices around code.&lt;/p&gt;  &lt;p&gt;If you’re reading this blog, you’re the right person to come, so if you can make it to Austin in February, please try to come!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Pablo%e2%80%99s+Fiesta+Open+Space+Conference&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fchad_myers%2farchive%2f2009%2f11%2f18%2fpablo-s-fiesta-open-space-conference.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fchad_myers%2farchive%2f2009%2f11%2f18%2fpablo-s-fiesta-open-space-conference.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=32301" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/B3F724D81C6193DF48054730E14F787CD71A29C7"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/B3F724D81C6193DF48054730E14F787CD71A29C7"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=iWvp2UoGgFc:07jOmaT3hRU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=iWvp2UoGgFc:07jOmaT3hRU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=iWvp2UoGgFc:07jOmaT3hRU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=iWvp2UoGgFc:07jOmaT3hRU:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/iWvp2UoGgFc" height="1" width="1"/&gt;</description><category domain="http://www.lostechies.com/blogs/chad_myers/archive/tags/Fiesta/default.aspx">Fiesta</category><feedburner:origLink>http://www.lostechies.com/blogs/chad_myers/archive/2009/11/18/pablo-s-fiesta-open-space-conference.aspx</feedburner:origLink></item><item><title>How We Do Things - The Team Room</title><link>http://feedproxy.google.com/~r/LosTechies/~3/fRP1XvbhkZQ/how-we-do-things-the-team-room.aspx</link><pubDate>Tue, 17 Nov 2009 14:30:16 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:32007</guid><dc:creator>Scott C Reynolds</dc:creator><slash:comments>5</slash:comments><description>&lt;p&gt;&lt;em&gt;This content comes solely from my experience, study, and a lot of trial and error (mostly error). I make no claims stating that which works for me will work for you. As with all things, your mileage may vary, and you will need to apply all knowledge through the filter of your context in order to strain out the good parts for you. Also, feel free to call BS on anything I say. I write this as much for me to learn as for you.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This is part 8 of the &lt;a href="http://www.lostechies.com/blogs/scottcreynolds/archive/2009/10/04/how-we-do-things-preamble-and-contents.aspx"&gt;How We Do Things&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Everyone should basically know what a team room is by now, so this post is going to just be a look into how we set ours up, how we got the team to buy in to the change from private cubicles, what we've noticed since creating the team room, and my thoughts on privacy and productivity.&lt;/p&gt;
&lt;p&gt;When we first started growing our team, we were scattered about. A few of us had private offices, the rest were in cubicles with high walls. As we increased staff, I began to look at some alternatives to this situation. The space allocated to me was a rectangular room about 54'X18' with an adjacent office that was about 15' square. Not a lot to work with in a traditional cube setup, which is what I was asked to pursue. So I took this as an opportunity to build the team room I had been wanting.&lt;/p&gt;
&lt;p&gt;What we came up with is "pods" of 3 desks each, with about 1' mesh dividers above the desk surface. This gave everyone their own desk, and their own little area, but they were still together, and everyone could see and freely talk to everyone else.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/scottcreynolds/IMG_5F00_0562.JPG" alt="IMG_0562.JPG" border="0" width="400" height="300" /&gt;&lt;/div&gt;
&lt;p&gt;Steve Harman once asked on twitter if private desks were anti-productive, and I answered that I didn't think so when used appropriately. I know a lot of team rooms just do the flat table thing and everyone sits shoulder to shoulder at all times. That's fine, I guess, and great for pairing, but people do need a place of their own. Someplace they can check email and their bank account without everyone looking over their shoulder. Someplace where they can put their knick-knacks. People like desk drawers to store things in. It's psychology 101. People need a little space. At least the people on my team do.&lt;/p&gt;
&lt;p&gt;One of the problems with some of the things we do in agile-type software is that we ignore the human factor, we ignore team dynamics and personalities, and try to make everyone the same. This is probably at least partly why a lot of teams push back on these practices, and why they end up falling down.&lt;/p&gt;
&lt;p&gt;So we compromised, and people got private desks that were put together in such a way as to not hinder the "team" aspect of the team room. And I think it's worked well.&lt;/p&gt;
&lt;p&gt;We outfitted the team room with plenty of whiteboard action:&lt;/p&gt;&lt;div style="text-align:center;"&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/scottcreynolds/IMG_5F00_0563.JPG" alt="IMG_0563.JPG" border="0" width="400" height="300" /&gt;&lt;/div&gt;It's important to have a lot of areas where people can collaborate and try out ideas. In addition to the team room we also have a "conference room" for just us that is separate, has a whiteboard and a nice projector, where people can gather and do design and planning sessions.
&lt;p&gt;Since the desks aren't really conducive to long-term pair programming, we set up a pairing station at the end of the team room, and we turned the extra office into what we call "pairing jail". Pairing jail has two pairing stations and another whiteboard, plus all the equipment we need to test our hardware integrations (microscope, camera, barcode scanners, etc). &lt;/p&gt;&lt;div style="text-align:center;"&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/scottcreynolds/IMG_5F00_0561.JPG" alt="IMG_0561.JPG" border="0" width="400" height="300" /&gt;&lt;/div&gt;Each pairing station has a 24" monitor, extra keyboards and mice, and is a nice flat surface people can work on.
&lt;p&gt;This is the compromise between pair programming and private desks. We pair most features, and most of the developers are pairing about 5-6 hours a day. However, we have an uneven number of developers, and sometimes people are working on something on their own, or spiking something, or just doing whatever else, and having a semi-private space keeps morale up.&lt;/p&gt;
&lt;p&gt;We have 7 developers so 3 pairing stations works. When we add more staff, we add more pairing stations. Pretty simple.&lt;/p&gt;
&lt;p&gt;We also work on a few different projects simultaneously, which makes the separated pairing room nice. That room usually becomes the war room for the two pairs working on the biggest thing, so they can have all their conversations and whiteboard sessions without interfering with the conversations of the third pair who is working on something totally different. It works for us.&lt;/p&gt;
&lt;p&gt;People seem to organize themselves fairly well into various areas, they respect the whiteboards when there's real work on them (people outside the team don't always respect the whiteboard, which can get annoying, but that's another story)&lt;/p&gt;
&lt;p&gt;At first there was resistance to the team room concept, and I'm sure a lot of people come up against this. To overcome the objections I did the simplest thing that could possibly work: I gave up my office and sat in the team room. When the boss gives up his office, people are less likely to complain about sharing space. Then they get used to it. Then, over time, they see the value, and the organic process of gelling a team happens.&lt;/p&gt;
&lt;p&gt;There was also resistance externally to the idea at first (and still some today, a couple of years later). Other managers at my level didn't understand why I left my office for a desk in this room, and I took a lot of not-so-subtle teasing for it. People didn't understand the collaborative nature of a team room, because corporate America is used to peons in cubes, managers in offices, and communication via email and scheduled meetings. This is just something people have to get over or not. I stopped caring. The results spoke for themselves. Don't let the sheep drag you down.&lt;/p&gt;
&lt;p&gt;The team room isn't just for developers. I sat in there until very recently (gave up my space for expansion since I'm moving soon anyway). The business analysts are in the team room. The QA guys are in the team room. Everyone is together, and everyone talks, and everyone is accessible.&lt;/p&gt;
&lt;p&gt;Not everyone has the perfect big room for a team room, I didn't. You have to find a way to work with the space you have, be creative. The most important thing is getting the team together, in the same place, and removing the barriers.&lt;/p&gt;
&lt;p&gt;A team isn't built overnight. It takes time. When people aren't used to a team environment, a collaborative environment, you can't just throw them together at desks and expect magic. It's a process. I will say that since we put the team room in place, after the first month or so, it's been amazing. People communicate. They talk. They whiteboard. They get together at each others' desks for impromptu design sessions. They pair on things they weren't even planning to pair on. They collaborate. Without the team room in place we would not be where we are today with either our process or our practices.&lt;/p&gt;
&lt;!-- Technorati Tags Start --&gt;
&lt;p&gt;Technorati Tags:
&lt;a href="http://technorati.com/tag/how                   2e                  17o                   9t" rel="tag"&gt;how we do it&lt;/a&gt;, &lt;a href="http://technorati.com/tag/improvement" rel="tag"&gt;improvement&lt;/a&gt;, &lt;a href="http://technorati.com/tag/lean" rel="tag"&gt;lean&lt;/a&gt;, &lt;a href="http://technorati.com/tag/management" rel="tag"&gt;management&lt;/a&gt;, &lt;a href="http://technorati.com/tag/quality" rel="tag"&gt;quality&lt;/a&gt;, &lt;a href="http://technorati.com/tag/software" rel="tag"&gt;software&lt;/a&gt;, &lt;a href="http://technorati.com/tag/team" rel="tag"&gt;team&lt;/a&gt;, &lt;a href="http://technorati.com/tag/planning" rel="tag"&gt;planning&lt;/a&gt;
&lt;/p&gt;
&lt;!-- Technorati Tags End --&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=How+We+Do+Things+-+The+Team+Room&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fscottcreynolds%2farchive%2f2009%2f11%2f17%2fhow-we-do-things-the-team-room.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fscottcreynolds%2farchive%2f2009%2f11%2f17%2fhow-we-do-things-the-team-room.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=32007" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/AD7BF465A91201E2DFDE2008A16A8CB8D9FECA4A"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/AD7BF465A91201E2DFDE2008A16A8CB8D9FECA4A"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=fRP1XvbhkZQ:IANUCEyEZ40:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=fRP1XvbhkZQ:IANUCEyEZ40:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=fRP1XvbhkZQ:IANUCEyEZ40:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=fRP1XvbhkZQ:IANUCEyEZ40:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/fRP1XvbhkZQ" height="1" width="1"/&gt;</description><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/management/default.aspx">management</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/software/default.aspx">software</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/improvement/default.aspx">improvement</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/how+we+do+it/default.aspx">how we do it</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/team/default.aspx">team</category><feedburner:origLink>http://www.lostechies.com/blogs/scottcreynolds/archive/2009/11/17/how-we-do-things-the-team-room.aspx</feedburner:origLink></item><item><title>I recant my IoC! IoC containers in dynamic languages are silly.</title><link>http://feedproxy.google.com/~r/LosTechies/~3/CndCd48eJdU/i-recant-my-ioc-ioc-containers-in-dynamic-languages-are-silly.aspx</link><pubDate>Mon, 16 Nov 2009 22:28:33 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:31780</guid><dc:creator>Ryan Svihla</dc:creator><slash:comments>10</slash:comments><description>&lt;p&gt;After a year or so of solid Alt Dot Net infection (as far as infections go its a pretty awesome one to have), I decided to give Python a try again for more than one off sysadmin tasks, and to actually dive into it as a newly minted “Agilista”.&amp;#160; &lt;/p&gt;  &lt;p&gt;However, I had&amp;#160; a problem..there were no non-painful IoC containers in Python (sorry to the other authors of IoC frameworks in Python like Spring Python and Snake Guice, I know you try and I respect the effort).&amp;#160; Ultimately, I could &lt;u&gt;&lt;strong&gt;not&lt;/strong&gt;&lt;/u&gt;&amp;#160; imagine coding anymore without something to handle all my registration for me, that’d dynamically inject in my dependencies, give me hooks for contextual resolution, and give me rich interception support.&lt;/p&gt;  &lt;p&gt;So I built my own, it was painful still, but I had some ideas to move it in an Convention Over Configuration direction, and ultimately get within shooting range of what fancy stuff we’ve come to expect in .Net that Windsor, StructureMap and many others provide.&lt;/p&gt;  &lt;p&gt;Now as I got into the fancier aspects of dynamic languages, open classes and the ability to override &lt;strong&gt;all&lt;/strong&gt; behavior easily I get it…a dynamic languages runtime is like a bit IoC container.&lt;/p&gt;  &lt;p&gt;Now I’ve heard other people say this many times but rarely with explanation or example, or focus on frankly silly things like “Dependency Injection adds too many lines of code” which is a bit melodramatic. Two arguments to a constructor, two fields ,and then avoiding having to call new is not “adding too many lines of code”, especially with templates, IDE’s, scripting, etc to cut down the actual typing load.Today I’m going to actually try to explain how languages like Python, Ruby etc give us the same awesomeness we’ve come to expect in things like Windsor..but at a much cheaper cost of learning and dev time.&lt;/p&gt;  &lt;p&gt;Take a typical resolution scenario where you want to output to a different file format depending on command line switches.&amp;#160; With an IoC container you can either:&lt;/p&gt;  &lt;p&gt;Change the resolution argument to load a different concrete type:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;     &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:3dcbdc1b-494c-457b-9efd-ede9201abe6f" class="wlWriterEditableSmartContent"&gt;&lt;div style="font-family:consolas,lucida console,courier,monospace"&gt;
&lt;span style="color:#0000ff"&gt;if&lt;/span&gt;(arg&amp;#160;==&amp;#160;&lt;span style="color:#a31515"&gt;"XML"&lt;/span&gt;)&lt;br/&gt;
&lt;span style="color:#0000ff"&gt;{&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;container.Register(Component.For&amp;lt;IOutput&amp;gt;().ImpmentedBy&amp;lt;XmlOutput&amp;gt;());&lt;br/&gt;
&lt;span style="color:#0000ff"&gt;}&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:#0000ff"&gt;else&lt;/span&gt;&amp;#160;if(arg&amp;#160;==&amp;#160;&lt;span style="color:#a31515"&gt;"HTML"&lt;/span&gt;)&lt;br/&gt;
&lt;span style="color:#0000ff"&gt;{&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;container.Register(Component.For&amp;lt;IOutput&amp;gt;().ImpmentedBy&amp;lt;HtmlOutput&amp;gt;());&lt;br/&gt;
&lt;span style="color:#0000ff"&gt;}&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:#0000ff"&gt;else&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:#0000ff"&gt;{&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;container.Register(Component.For&amp;lt;IOutput&amp;gt;().ImpmentedBy&amp;lt;NullOutput&amp;gt;());&lt;br/&gt;
&lt;span style="color:#0000ff"&gt;}&lt;/span&gt;&lt;br/&gt;
&lt;/div&gt;
&lt;/div&gt;   &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;or resolve different arguments or keys using a service locator approach in later client code (thereby depending on the container)&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;     &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:0f98bb6c-197e-44c9-884d-326c91be6373" class="wlWriterEditableSmartContent"&gt;&lt;div style="font-family:consolas,lucida console,courier,monospace"&gt;
	&lt;span style="color:#0000ff"&gt;public&lt;/span&gt;&amp;#160;&lt;span style="color:#0000ff"&gt;void&lt;/span&gt;&amp;#160;output(IKernel&amp;#160;container,&amp;#160;&lt;span style="color:#2b91af"&gt;string&lt;/span&gt;&amp;#160;key)&lt;br/&gt;
	&lt;span style="color:#0000ff"&gt;{&lt;/span&gt;&lt;br/&gt;
		var&amp;#160;output&amp;#160;=container.Resolve&amp;lt;IOutput&amp;gt;(key);&lt;br/&gt;
		output.save();&lt;br/&gt;
&lt;br/&gt;
	&lt;span style="color:#0000ff"&gt;}&lt;/span&gt;&lt;br/&gt;
&lt;/div&gt;
&lt;/div&gt;   &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;or implement a custom implementation of the resolver system (which I’ll leave out for the sake of brevity, but it’s not instant code).&amp;#160; Also to do all this you have to depend on interfaces, add all your interchangeable code to the constructor and life is grand.&amp;#160; You do this for many reasons in static languages, its the only way to get easy testability and code that is open to extension.&amp;#160; In dynamic languages its &lt;strong&gt;&lt;u&gt;always open for extension and easy to test&lt;/u&gt;&lt;/strong&gt; . Let me demonstrate:&lt;/p&gt;  &lt;blockquote&gt;   &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:c306549e-c4ed-4b96-9589-57a9b432eba7" class="wlWriterEditableSmartContent"&gt;&lt;div style="font-family:consolas,lucida console,courier,monospace"&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;outputlib&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;o&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;outputselect&lt;/b&gt;&lt;/span&gt;(arg):&lt;br/&gt;
	&lt;span style="color:#008800"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt;&amp;#160;arg&amp;#160;==&amp;#160;&lt;span style="color:#dd2200"&gt;"XML"&lt;/span&gt;:&lt;br/&gt;
		o.Output&amp;#160;=&amp;#160;XmlOutput&lt;br/&gt;
	&lt;span style="color:#008800"&gt;&lt;b&gt;elif&lt;/b&gt;&lt;/span&gt;&amp;#160;arg&amp;#160;==&amp;#160;&lt;span style="color:#dd2200"&gt;"HTML"&lt;/span&gt;:&lt;br/&gt;
		o.Output&amp;#160;=&amp;#160;HtmlOutput&lt;br/&gt;
	&lt;span style="color:#008800"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt;:&lt;br/&gt;
		o.Output&amp;#160;=&amp;#160;NullOutput&lt;br/&gt;
&lt;br/&gt;
&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;saveoutput&lt;/b&gt;&lt;/span&gt;():&lt;br/&gt;
	o.Output().save()&amp;#160;&amp;#160;&lt;span style="color:#888888"&gt;#will&amp;#160;save&amp;#160;whichever&lt;/span&gt;&lt;br/&gt;
&lt;/div&gt;
&lt;/div&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Contextual resolution in a nutshell, and throughout your code if need be.&amp;#160; “Interception” is even easier, take a look at &lt;a title="http://docs.python.org/dev/library/functools.html" href="http://docs.python.org/dev/library/functools.html"&gt;http://docs.python.org/dev/library/functools.html&lt;/a&gt; and then start playing you’ll see you can trivially apply logging and security to methods without explicitly adding it. A short logging example follows:&lt;/p&gt; &lt;/blockquote&gt;  &lt;blockquote&gt;   &lt;p&gt;     &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:2EC9848E-067D-4e79-BAB7-06CA927DB962:21ea489c-0a45-4b0c-8ae4-cd4fbbf78b2e" class="wlWriterEditableSmartContent"&gt;&lt;div style="font-family:consolas,lucida console,courier,monospace"&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;types&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;functools&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#888888"&gt;#applies&amp;#160;a&amp;#160;cepter&amp;#160;to&amp;#160;each&amp;#160;non-underscored&amp;#160;method.&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;wrapcls&lt;/b&gt;&lt;/span&gt;(cls,&amp;#160;cepter):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;publics&amp;#160;&amp;#160;=&amp;#160;[&amp;#160;name&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt;&amp;#160;name&amp;#160;&lt;span style="color:#008800"&gt;in&lt;/span&gt;&amp;#160;&lt;span style="color:#003388"&gt;dir&lt;/span&gt;(cls)&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#008800"&gt;not&lt;/span&gt;&amp;#160;name.startswith(&lt;span style="color:#dd2200"&gt;"_"&lt;/span&gt;)]&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;methods&amp;#160;=&amp;#160;[&lt;span style="color:#003388"&gt;getattr&lt;/span&gt;(cls,method)&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt;&amp;#160;method&amp;#160;&lt;span style="color:#008800"&gt;in&lt;/span&gt;&amp;#160;publics&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#003388"&gt;type&lt;/span&gt;(&lt;span style="color:#003388"&gt;getattr&lt;/span&gt;(cls,method))&amp;#160;==&amp;#160;types.MethodType&amp;#160;]&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt;&amp;#160;method&amp;#160;&lt;span style="color:#008800"&gt;in&lt;/span&gt;&amp;#160;methods:&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;intercepted_method&amp;#160;=&amp;#160;cepter(method)&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#003388"&gt;setattr&lt;/span&gt;(cls,&amp;#160;method.__name__,&amp;#160;intercepted_method)&amp;#160;&lt;span style="color:#888888"&gt;#attaches&amp;#160;intercepted_method&amp;#160;to&amp;#160;the&amp;#160;original&amp;#160;class,&amp;#160;replacing&amp;#160;non-intercepted&amp;#160;one&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#888888"&gt;#the&amp;#160;magic&amp;#160;all&amp;#160;happens&amp;#160;in&amp;#160;the&amp;#160;functools.wraps&amp;#160;decorator&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;loggingcepter&lt;/b&gt;&lt;/span&gt;(func):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#555555"&gt;@functools&lt;/span&gt;.wraps(func)&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;logafter&lt;/b&gt;&lt;/span&gt;(*args,&amp;#160;**kwargs):&amp;#160;&lt;span style="color:#888888"&gt;#for&amp;#160;csharp&amp;#160;devs&amp;#160;view&amp;#160;this&amp;#160;as&amp;#160;an&amp;#160;inline&amp;#160;delegate&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;result&amp;#160;=&amp;#160;func(*args,&amp;#160;**kwargs)&amp;#160;&lt;span style="color:#888888"&gt;#invoking&amp;#160;function&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#dd2200"&gt;"function&amp;#160;name:&amp;#160;"&lt;/span&gt;&amp;#160;+&amp;#160;func.__name__&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#dd2200"&gt;"arguments&amp;#160;were:&amp;#160;"&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt;&amp;#160;a&amp;#160;&lt;span style="color:#008800"&gt;in&lt;/span&gt;&amp;#160;args:&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#003388"&gt;repr&lt;/span&gt;(a)&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#dd2200"&gt;"keyword&amp;#160;args&amp;#160;were:&amp;#160;"&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt;&amp;#160;kword&amp;#160;&lt;span style="color:#008800"&gt;in&lt;/span&gt;&amp;#160;kwargs:&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#003388"&gt;repr&lt;/span&gt;(kword)&amp;#160;+&amp;#160;&lt;span style="color:#dd2200"&gt;"&amp;#160;:&amp;#160;"&lt;/span&gt;&amp;#160;+&amp;#160;&lt;span style="color:#003388"&gt;repr&lt;/span&gt;(kwargs[kword])&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#dd2200"&gt;"return&amp;#160;value&amp;#160;was:&amp;#160;"&lt;/span&gt;&amp;#160;+&amp;#160;&lt;span style="color:#003388"&gt;repr&lt;/span&gt;(result)&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt;&amp;#160;result&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt;&amp;#160;logafter&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br/&gt;
&lt;span style="color:#888888"&gt;#default&amp;#160;boring&amp;#160;repository&amp;#160;class&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;StorageEngine&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;object&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#555555"&gt;@property&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;connections&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;self&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;pass&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;_sessioncall&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;self&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;pass&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;self&lt;/span&gt;,user):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#dd2200"&gt;"running&amp;#160;create&amp;#160;now&amp;#160;from&amp;#160;the&amp;#160;method"&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;delete&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;self&lt;/span&gt;,&amp;#160;&lt;span style="color:#003388"&gt;id&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#dd2200"&gt;"running&amp;#160;delete&amp;#160;now&amp;#160;from&amp;#160;the&amp;#160;method"&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#dd2200"&gt;"deleted&amp;#160;from&amp;#160;the&amp;#160;database"&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;get&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;self&lt;/span&gt;,&amp;#160;&lt;span style="color:#003388"&gt;id&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;pass&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#0066bb"&gt;&lt;b&gt;__init__&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;self&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;pass&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:#888888"&gt;#placeholder&amp;#160;storage&amp;#160;object&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#bb0066"&gt;&lt;b&gt;User&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#003388"&gt;object&lt;/span&gt;):&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008800"&gt;&lt;b&gt;pass&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br/&gt;
wrapcls(StorageEngine&amp;#160;,loggingcepter)&lt;br/&gt;
repo&amp;#160;=&amp;#160;StorageEngine()&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#dd2200"&gt;"calling&amp;#160;count&amp;#160;this&amp;#160;should&amp;#160;not&amp;#160;be&amp;#160;intercepted"&lt;/span&gt;&lt;br/&gt;
cnncount&amp;#160;=&amp;#160;repo.connections&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#dd2200"&gt;"now&amp;#160;get&amp;#160;should&amp;#160;be&amp;#160;intercepted"&lt;/span&gt;&lt;br/&gt;
repo.get(&lt;span style="color:#0000DD"&gt;&lt;b&gt;1&lt;/b&gt;&lt;/span&gt;)&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#dd2200"&gt;"we&amp;#160;should&amp;#160;see&amp;#160;keyword&amp;#160;arguments&amp;#160;here"&lt;/span&gt;&lt;br/&gt;
repo.delete(&lt;span style="color:#003388"&gt;id&lt;/span&gt;=&lt;span style="color:#0000DD"&gt;&lt;b&gt;2&lt;/b&gt;&lt;/span&gt;)&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#dd2200"&gt;"session&amp;#160;call&amp;#160;should&amp;#160;not&amp;#160;be&amp;#160;intercepted"&lt;/span&gt;&lt;br/&gt;
repo._sessioncall()&lt;br/&gt;
&lt;span style="color:#008800"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;&amp;#160;&lt;span style="color:#dd2200"&gt;"create&amp;#160;should&amp;#160;be&amp;#160;intercepted&amp;#160;and&amp;#160;we&amp;#160;should&amp;#160;see&amp;#160;a&amp;#160;User&amp;#160;object"&lt;/span&gt;&lt;br/&gt;
repo.create(User())&lt;br/&gt;
&lt;/div&gt;
&lt;/div&gt;   &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Running the above script should result in the following output&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rssvihla/Screenshot20091116at4.20.56PM_5F00_0C117192.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Screen shot 2009-11-16 at 4.20.56 PM" border="0" alt="Screen shot 2009-11-16 at 4.20.56 PM" src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rssvihla/Screenshot20091116at4.20.56PM_5F00_thumb_5F00_49A1600C.png" width="625" height="530" /&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;So this is all very cool, but what does it mean or why do I care?&amp;#160; For those of us used to using a proper IoC container like Windsor or StructureMap, we’ve gotten used to have capabilities like the above easily available to us when we’ve needed them. It’s nice to find that in Python (or really any dynamic language ) we can easily build our own similar functionality that we’ve come to depend on.&amp;#160; We’re never coupled and we’re always able to test and mock out behavior.&amp;#160; It was a long time coming but I think I finally get it now.&lt;/p&gt;&lt;/blockquote&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=I+recant+my+IoC!+IoC+containers+in+dynamic+languages+are+silly.&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2frssvihla%2farchive%2f2009%2f11%2f16%2fi-recant-my-ioc-ioc-containers-in-dynamic-languages-are-silly.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2frssvihla%2farchive%2f2009%2f11%2f16%2fi-recant-my-ioc-ioc-containers-in-dynamic-languages-are-silly.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=31780" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/BD0FFDF8E0EDC4EF2618282AEFF5147707BCD8DA"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/BD0FFDF8E0EDC4EF2618282AEFF5147707BCD8DA"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=CndCd48eJdU:wLA1njK9vL8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=CndCd48eJdU:wLA1njK9vL8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=CndCd48eJdU:wLA1njK9vL8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=CndCd48eJdU:wLA1njK9vL8:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/CndCd48eJdU" height="1" width="1"/&gt;</description><category domain="http://www.lostechies.com/blogs/rssvihla/archive/tags/Python/default.aspx">Python</category><category domain="http://www.lostechies.com/blogs/rssvihla/archive/tags/Dynamic+Langs/default.aspx">Dynamic Langs</category><category domain="http://www.lostechies.com/blogs/rssvihla/archive/tags/IoC/default.aspx">IoC</category><feedburner:origLink>http://www.lostechies.com/blogs/rssvihla/archive/2009/11/16/i-recant-my-ioc-ioc-containers-in-dynamic-languages-are-silly.aspx</feedburner:origLink></item><item><title>Pablo’s Fiesta: Open Space Conference in Austin TX</title><link>http://feedproxy.google.com/~r/LosTechies/~3/62Lg3nOS07E/pablo-s-fiesta-open-space-conference-in-austin-tx.aspx</link><pubDate>Mon, 16 Nov 2009 21:36:27 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:31767</guid><dc:creator>jcteague</dc:creator><slash:comments>5</slash:comments><description>&lt;h2&gt;Pablo's Fiesta&lt;/h2&gt;  &lt;h4&gt;&lt;strong&gt;Los Techies Open Space Conference on Software Quality &amp;amp; Craftsmanship&lt;/strong&gt; &lt;/h4&gt;  &lt;p&gt;&lt;strong&gt;When: February 26, 27 &amp;amp; 28      &lt;br /&gt;Where: St. Edward's Professional Educational Center, Austin TX&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I am proud to announce the first Los Techies Open Space Conference.&amp;#160; We’ve been working on this for a while we are now finally ready to make the public announcement.&lt;/p&gt;  &lt;p&gt;You can see all of the details and register &lt;a href="http://fiesta.lostechies.com"&gt;here&lt;/a&gt;.&amp;#160; &lt;/p&gt;  &lt;h3&gt;What I want the conference to be.&lt;/h3&gt;  &lt;p&gt;The great thing about Open Space conferences is that the content as well as the tenor of the conference is defined more by those attending than those who organize it.&amp;#160; Here is what I think the conference should be.&amp;#160; &lt;/p&gt;  &lt;p&gt;The topic of the conference will be focused on Software Quality and Craftsmanship.&amp;#160; This is a topic that is very near and dear to the hearts of the Los Techies crew.&amp;#160; Quality is the most important feature of any product, and can be difficult to achieve and&amp;#160; measure in software.&amp;#160; Craftsmanship is a philosophy about how professionals in our field should approach their work and how, as a profession, we should focus on cultivating a community of software developers who&amp;#160; learn, respect and give back to the profession.&lt;/p&gt;  &lt;p&gt;There are several important aspects to being a craftsman that I&amp;#160; to&amp;#160; address:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Sharpening the Saw&lt;/strong&gt;.&amp;#160; It important to learn new techniques and different technologies to continue to grow in this profession. I’m the software developer equivalent of a gear head (or petro head you you UK guys). I have no doubt there will be some technical discussions.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Multi-Platform&lt;/strong&gt;.&amp;#160; I want to talk about more the C#.&amp;#160; Let’s discuss iPhone, Ruby, Python and any other platform that help us become better software developers.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Selling Quality as a feature&lt;/strong&gt;.&amp;#160; How do we convince clients and business executives that quality is a feature of software that has a very big impact on their bottom line.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Come to the conference and influence help shape it to be to what you think it should be.&amp;#160; Please join us in Austin TX, February 26,l 27 &amp;amp; 28. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Pablo%e2%80%99s+Fiesta%3a+Open+Space+Conference+in+Austin+TX&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjohnteague%2farchive%2f2009%2f11%2f16%2fpablo-s-fiesta-open-space-conference-in-austin-tx.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjohnteague%2farchive%2f2009%2f11%2f16%2fpablo-s-fiesta-open-space-conference-in-austin-tx.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=31767" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/C77145684C9C3022D1969EA041F37ECCA9450CE8"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/C77145684C9C3022D1969EA041F37ECCA9450CE8"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=62Lg3nOS07E:4Ot9gqM0-CQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=62Lg3nOS07E:4Ot9gqM0-CQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=62Lg3nOS07E:4Ot9gqM0-CQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=62Lg3nOS07E:4Ot9gqM0-CQ:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/62Lg3nOS07E" height="1" width="1"/&gt;</description><category domain="http://www.lostechies.com/blogs/johnteague/archive/tags/los-techies-fiesta/default.aspx">los-techies-fiesta</category><feedburner:origLink>http://www.lostechies.com/blogs/johnteague/archive/2009/11/16/pablo-s-fiesta-open-space-conference-in-austin-tx.aspx</feedburner:origLink></item><item><title>The Passionate Programmer Book Review</title><link>http://feedproxy.google.com/~r/LosTechies/~3/pWjEs_g7bWI/the-passionate-programmer-review.aspx</link><pubDate>Sun, 15 Nov 2009 22:19:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:31453</guid><dc:creator>Louis Salin</dc:creator><slash:comments>2</slash:comments><description>&lt;p&gt;Earlier this year, I've been given the chance to read any book of my choice from the Pragmatic Programmer bookshelf and write a quick review. Being so focused right now on figuring out where I want to go with my career, I thought I'd give &lt;a href="http://www.pragprog.com/titles/cfcar2/the-passionate-programmer"&gt;The Passionate Programmer&lt;/a&gt; a try. I mean, who doesn't want to be passionate about their job? Loving what you do makes it fun and this is the key to a very successful career! I don't think I can do it justice until I've tried to put into practice most of what the author is preaching in the book, so here is a quick and dirty review of the book. (spoiler: I liked the book!)&lt;/p&gt;
&lt;p&gt;The author, &lt;a href="http://chadfowler.com/"&gt;Chad Fowler&lt;/a&gt;, didn't get his start by getting a degree in computer science. Yet, he has accomplished more in his career than most software developers will ever do in their lifespan. So he must be doing something right, no? Well, the book might not teach you how to be passionate about anything. However, it will give you great pointers to make a great career out of software programming, which might make you passionate about the whole thing, I guess.&lt;/p&gt;
&lt;p&gt;The book is divided into five independent parts, each of which you need to give serious thought to if you're ever going to become great at what you do, and remain great. In each part are multiple, small chapters of about two to three pages long, that will give you some hopefully valuable insight about growing you skills, finding mentors, pleasing your managers, how not to panic in dire situations and being careful about market changes, among many, various others topics. All in all, there are 53 "tips" in the book and I must say that most of them are very useful.&lt;/p&gt;
&lt;p&gt;I would've wished that not all of those tips be written as if it was a recipe for success. Every single one ends with a "Act on it" section with exercises that are bound to put some of us out of our comfort zone. But maybe that's a good thing! Any day, I can open up the book and re-read one of the tips that I know I should be working on. There is no doubt in my mind that I can become a remarkable programmer by working on my weaknesses, and Chad covers most of them in his book.&lt;/p&gt;
&lt;p&gt;This isn't a book that you'll read cover to cover. The optimal way to get through it, in my opinion, is to read it one chapter or two at a time and quickly put into practice what was read before progressing any further. Incidentally, this makes the book a very easy read; you could be spending only 15 minutes every night reading this book. But to make it effective, you'll need to actively put it into practice. I know I will. And I know I'll probably end up re-reading it a couple of times.&lt;/p&gt;
&lt;p&gt;I have read the 7 Habits of Highly Successful People and Who Moved My Cheese and Chad's book reminded me of them. Because of that, I can only recommend this book to all my peers, unless you are already at the top of your game. Then maybe you should write your own book too! Oh wait, that's one of the tips in The Passionate Programmer!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=The+Passionate+Programmer+Book+Review&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f11%2f15%2fthe-passionate-programmer-review.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f11%2f15%2fthe-passionate-programmer-review.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=31453" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/5ADC7F3378C6DA3CEDEE98AC3049B1EBC346F2EA"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/5ADC7F3378C6DA3CEDEE98AC3049B1EBC346F2EA"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=pWjEs_g7bWI:6UjlzFZgaqQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=pWjEs_g7bWI:6UjlzFZgaqQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=pWjEs_g7bWI:6UjlzFZgaqQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=pWjEs_g7bWI:6UjlzFZgaqQ:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/pWjEs_g7bWI" height="1" width="1"/&gt;</description><feedburner:origLink>http://www.lostechies.com/blogs/louissalin/archive/2009/11/15/the-passionate-programmer-review.aspx</feedburner:origLink></item><item><title>How We Do Things - Specification (Using the right tools)</title><link>http://feedproxy.google.com/~r/LosTechies/~3/_T5TOhxgEVI/how-we-do-things-specification-using-the-right-tools.aspx</link><pubDate>Fri, 13 Nov 2009 14:41:52 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:30581</guid><dc:creator>Scott C Reynolds</dc:creator><slash:comments>3</slash:comments><description>&lt;p&gt;&lt;em&gt;This content comes solely from my experience, study, and a lot of trial and error (mostly error). I make no claims stating that which works for me will work for you. As with all things, your mileage may vary, and you will need to apply all knowledge through the filter of your context in order to strain out the good parts for you. Also, feel free to call BS on anything I say. I write this as much for me to learn as for you.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This is part 7 of the &lt;a href="http://www.lostechies.com/blogs/scottcreynolds/archive/2009/10/04/how-we-do-things-preamble-and-contents.aspx"&gt;How We Do Things&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post was co-written with &lt;a href="http://www.catschwamm.com"&gt;Cat Schwamm&lt;/a&gt;, business analyst extraordinaire.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In the last post we talked about how we approach specification philosophically, as an iterative, JIT process. In this post we will take a look at the tools we use to create specifications.&lt;/p&gt;
&lt;h3&gt;User Stories and Text&lt;/h3&gt;
&lt;p&gt;User stories and other text documents are the bread and butter of defining work, and we use them like crazy. Our story practice has evolved over time, and we have come to a place where we feel that, when used appropriately, our stories are very effective. For a deeper look at the guidelines we use to construct stories, I recommend you go check out &lt;a href="http://catschwamm.com/2009/08/09/constructing-effective-user-stories-or-my-user-stories-bring-all-the-boys-to-the-yard/"&gt;Cat’s post&lt;/a&gt; on the subject. Go ahead. I’ll wait.&lt;/p&gt;
&lt;p&gt;Okay, welcome back. Here’s the thing, stories and tasks are only part of the equation. Stories alone aren’t enough to define a system, and trying to define everything in text is a fool’s task. (I’ve been that fool). You need a full arsenal of specification tools to do the best job possible.&lt;/p&gt;
&lt;p&gt;Story Pros: captures textual data well, tells the story&lt;/p&gt;
&lt;p&gt;Story Cons: not everything is meant to be captured in text&lt;/p&gt;
&lt;h3&gt;Mockups&lt;/h3&gt;
&lt;p&gt;Mockups are a very useful tool when specifying details of how things should work. With stories, you really can't add a lot of design and implementation details or the signal to noise ratio becomes too high and shit gets overlooked. A basic rule of thumb we employ on the team is &lt;em&gt;"things that don't get communicated well in text shouldn't be forced into a text medium."&lt;/em&gt; Basically, if you're going to try to describe the way something should look in a story, a) it's probably not going to look the way you actually picture it b) that story is now noisy as crap and people are going to ignore more important parts. With a mockup, you don't have to take forever to do a flashy, literal, perfect screenshot in Fireworks or anything; you can just drag and drop Balsamiq controls around and voila. Ya got an aesthetically pleasing mockup that humans go nuts over. In five minutes I can mock something up in front of a developer, explain how it works, and they are ready to go.&lt;/p&gt;
&lt;p&gt;Another great thing about mockups is that they are extremely useful for getting user feedback on specs without distracting the user that "this is the final product, no more input." You can use a mockup to discuss workflow and layout without getting mired in fine-grained detail. The last time I was at the lab, I went back to my hotel room for a couple of hours and mocked up apps for 4 workspaces, brought them back to the supervisors and was able to get plenty of good feedback and make edits right there in front of them. Gold.&lt;/p&gt;
&lt;p&gt;Mockup Pros: Time-saver, gives the gist of what you want, keeps your stories clean while still conveying what you want, good to show to users.&lt;/p&gt;
&lt;p&gt;Mockup Cons: Can fall into the trap of putting everything on a mockup just like you would put everything into a story and it's inappropriate&lt;/p&gt;
&lt;h3&gt;High Fidelity Design&lt;/h3&gt;
&lt;p&gt;How easy is it to develop from what basically amounts to a screenshot? You know exactly how everything should look, you can strip images out, you don't really have to think about it.&lt;/p&gt;
&lt;p&gt;Wait a minute. There's a red flag.&lt;/p&gt;
&lt;p&gt;You don't have to think about it? That's a paddlin'. A high fidelity screenshot, while beautiful and easy to work from, gives developers a signal that this screen is a specification set in stone. They see what it needs to look like, they build it like that. It's just like BDUF; the high level of detail and granularity means that people won't think about what they're actually building, they'll just duplicate what they are given.&lt;/p&gt;
&lt;p&gt;Screenshot Pros: Hotness, high level of detail, easy to work from&lt;/p&gt;
&lt;p&gt;Screenshot Cons: Removes developer thought, can take a long time to create such a design &lt;/p&gt;
&lt;h3&gt;Conversation and Whiteboarding&lt;/h3&gt;
&lt;p&gt;While each of these mediums has plenty of merit and many benefits, conversation and whiteboarding are my (Cat's..well, OK mine too) favorite method of specifying work. There is nothing like having the team (or pertinent members) together, talking through the workflow of a feature/app, mapping out how everything works, doodling out a rough idea of what things are going to look like and how things will come together. It is so damned valuable to have the working group together, talking through how things are going to work and getting their input. While business analysts and managers can come together to specify the general nature of how things need to work, having different members of the team around will help to eke out edge cases or problems that may not have been thought of in original discussion.&lt;/p&gt;
&lt;p&gt;Conversation is obviously important by itself too; user stories are written to leave plenty of room for conversation. If you lose communication on your team and people just go off to code in the dark, a lot of the intent and original specification is lost.&lt;/p&gt;
&lt;p&gt;Whiteboard Pros: Mapping workflow, multiple sources of input, easy to sketch out an idea/easy to change an idea, whiteboarding is fun as shit, conversation fully fleshes out ideas&lt;/p&gt;
&lt;p&gt;Whiteboard Cons: Easy to get lost if not captured appropriately&lt;/p&gt;
&lt;p&gt;While we’ve clearly chosen a favorite medium, you really can’t use just one.  Each medium has a lot to offer depending on the scenario you are working with, and just like any other thing, you have to use what works naturally for the team in context with what you are doing.&lt;/p&gt;
&lt;!-- Technorati Tags Start --&gt;
&lt;p&gt;Technorati Tags:
&lt;a href="http://technorati.com/tag/how                   4e                  12o                   6t" rel="tag"&gt;how we do it&lt;/a&gt;, &lt;a href="http://technorati.com/tag/improvement" rel="tag"&gt;improvement&lt;/a&gt;, &lt;a href="http://technorati.com/tag/lean" rel="tag"&gt;lean&lt;/a&gt;, &lt;a href="http://technorati.com/tag/management" rel="tag"&gt;management&lt;/a&gt;, &lt;a href="http://technorati.com/tag/quality" rel="tag"&gt;quality&lt;/a&gt;, &lt;a href="http://technorati.com/tag/software" rel="tag"&gt;software&lt;/a&gt;, &lt;a href="http://technorati.com/tag/team" rel="tag"&gt;team&lt;/a&gt;, &lt;a href="http://technorati.com/tag/planning" rel="tag"&gt;planning&lt;/a&gt;
&lt;/p&gt;
&lt;!-- Technorati Tags End --&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=How+We+Do+Things+-+Specification+(Using+the+right+tools)&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fscottcreynolds%2farchive%2f2009%2f11%2f13%2fhow-we-do-things-specification-using-the-right-tools.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fscottcreynolds%2farchive%2f2009%2f11%2f13%2fhow-we-do-things-specification-using-the-right-tools.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=30581" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/A609B3C820EAC29BFABDE69A7EDD84F1B36A3508"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/A609B3C820EAC29BFABDE69A7EDD84F1B36A3508"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=_T5TOhxgEVI:TOvJIGBg_2w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=_T5TOhxgEVI:TOvJIGBg_2w:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=_T5TOhxgEVI:TOvJIGBg_2w:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=_T5TOhxgEVI:TOvJIGBg_2w:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/_T5TOhxgEVI" height="1" width="1"/&gt;</description><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/lean/default.aspx">lean</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/management/default.aspx">management</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/mentoring/default.aspx">mentoring</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/software/default.aspx">software</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/quality/default.aspx">quality</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/improvement/default.aspx">improvement</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/how+we+do+it/default.aspx">how we do it</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/team/default.aspx">team</category><feedburner:origLink>http://www.lostechies.com/blogs/scottcreynolds/archive/2009/11/13/how-we-do-things-specification-using-the-right-tools.aspx</feedburner:origLink></item><item><title>How to annoy your teammates</title><link>http://feedproxy.google.com/~r/LosTechies/~3/kd2E-YLhehI/how-to-annoy-your-teammates.aspx</link><pubDate>Fri, 13 Nov 2009 14:22:55 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:30578</guid><dc:creator>bogardj</dc:creator><slash:comments>9</slash:comments><description>&lt;p&gt;In 3 easy steps:&lt;/p&gt;  &lt;h3&gt;Step 1: Perform a change that affects many, many files&lt;/h3&gt;  &lt;p&gt;My favorite is a namespace rename.&amp;#160; Other choices include deleting a core marker interface, renaming a layer supertype class, or changing the folder structure in a project.&lt;/p&gt;  &lt;p&gt;Typically, VisualStudio will crash when I do this, though I’m not sure if it’s VS choking or ReSharper.&amp;#160; Either way, a large automatic refactoring will cause a crash.&lt;/p&gt;  &lt;h3&gt;Step 2: After the VS crash, re-open the solution and choose to recover all unsaved files&lt;/h3&gt;  &lt;p&gt;ReSharper likely made it quite a ways through your refactoring before VS crashed.&amp;#160; All those unsaved files were likely cached for recovery by VisualStudio, so you can probably get a lot of those changes back.&amp;#160; Instead of choosing to revert your local changes, go ahead and recover all those files.&amp;#160; It’s key for maximum annoyance.&lt;/p&gt;  &lt;h3&gt;Step 3: Merge these recovered files back to trunk&lt;/h3&gt;  &lt;p&gt;Since this was an &lt;em&gt;enormous&lt;/em&gt; refactoring, maybe affecting hundreds of files, you’ll want to merge your changes back to trunk as soon as possible.&amp;#160; After all, you don’t want to be the sucker merging after everyone else has finished their work.&lt;/p&gt;  &lt;p&gt;When you’re done, your co-workers will be greeted with one annoying merge, and another fun dialog that never seems to quite go away:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jimmy_5F00_bogard/image_5F00_74481858.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jimmy_5F00_bogard/image_5F00_thumb_5F00_3AC50861.png" width="451" height="242" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Just when you think you caught the last of the recovered files that had its line endings screwed up, another one pops up.&amp;#160; They’ll hate you once because of the core change that affected so many files, making it quite annoying to merge back to trunk.&amp;#160; But they’ll form that long-lasting, persistent hate because of this dialog box that keeps coming up.&amp;#160; Yes, there is that little checkbox at the bottom, but who reads these things anyway?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=How+to+annoy+your+teammates&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjimmy_bogard%2farchive%2f2009%2f11%2f13%2fhow-to-annoy-your-teammates.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjimmy_bogard%2farchive%2f2009%2f11%2f13%2fhow-to-annoy-your-teammates.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=30578" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/B5112BEF611D3C5DAA20BE439457ED365A5D13C5"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/B5112BEF611D3C5DAA20BE439457ED365A5D13C5"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=kd2E-YLhehI:9uC5y7JVfNE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=kd2E-YLhehI:9uC5y7JVfNE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=kd2E-YLhehI:9uC5y7JVfNE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=kd2E-YLhehI:9uC5y7JVfNE:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/kd2E-YLhehI" height="1" width="1"/&gt;</description><category domain="http://www.lostechies.com/blogs/jimmy_bogard/archive/tags/Misc/default.aspx">Misc</category><feedburner:origLink>http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/11/13/how-to-annoy-your-teammates.aspx</feedburner:origLink></item><item><title>Willed and forced design</title><link>http://feedproxy.google.com/~r/LosTechies/~3/hPccuMKJZC4/willed-and-forced-design.aspx</link><pubDate>Fri, 13 Nov 2009 02:32:19 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:30528</guid><dc:creator>bogardj</dc:creator><slash:comments>10</slash:comments><description>&lt;p&gt;Roy Osherove, as a TypeMock employee, presents quite a dilemma from opinionated TDD blog posts simply because whether he has one or not, there’s always the question of agenda.&amp;#160; Which is quite unfortunate, everyone has some sort of selfish agenda at some level.&amp;#160; One of those posts came up in a commentary on &lt;a href="http://weblogs.asp.net/rosherove/archive/2009/11/12/test-driven-design-willed-vs-forced-designs.aspx"&gt;willed and forced design&lt;/a&gt;, with respect to the usage of mocking frameworks:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;#1 Willed Design&lt;/strong&gt;&lt;/p&gt;    &lt;blockquote&gt;     &lt;p&gt;By writing tests, you can observe the usability of your design from a consumer perspective, and can decide whether or not you like it, and change it accordingly&lt;/p&gt;   &lt;/blockquote&gt;    &lt;p&gt;&lt;strong&gt;#2 Forced Design&lt;/strong&gt;&lt;/p&gt;    &lt;blockquote&gt;     &lt;p&gt;By using a subset of the available isolation frameworks(rhino, moq, nmock) or specific techniques *manual mocks and stubs) you discover cases that are not technically “mockable” or “fakeable” and use that as a sign for design change.&lt;/p&gt;   &lt;/blockquote&gt; &lt;/blockquote&gt;  &lt;p&gt;After about 2 seconds of playing around with dynamic languages such as Ruby and JavaScript, the idea that TypeMock is some how “impure” seemed rather silly.&amp;#160; Yes, it bends the CLR in crazy ways, but in and of itself, I believe it has its place.&lt;/p&gt;  &lt;p&gt;However, I highly disagree with Roy that #2 is bad, that a tool shouldn’t force my hand in a design.&amp;#160; But there’s a bit of a straw man here – it’s not the &lt;em&gt;tool&lt;/em&gt; forcing my design, it’s the &lt;em&gt;test&lt;/em&gt; telling me where I need to change my design.&amp;#160; Quite simply, if I run up against something hard to test, my first choice is to isolate that piece.&amp;#160; Here’s an example:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ActionResult &lt;/span&gt;Index()
{
    &lt;span style="color: blue"&gt;var &lt;/span&gt;user = Session[&lt;span style="color: #a31515"&gt;&amp;quot;CurrentUser&amp;quot;&lt;/span&gt;];

    &lt;span style="color: blue"&gt;return &lt;/span&gt;View(user);
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;This piece is awkward to test, even though HttpSessionBase or whatever is a class with virtual methods, and it makes the test ugly.&amp;#160; Yes, I could mock the crap out of this heavyweight object, but that’s not really helping me out, is it?&amp;#160; Instead, I’ll isolate the ugly:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;private readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IUserSession &lt;/span&gt;_userSession;

&lt;span style="color: blue"&gt;public &lt;/span&gt;HomeController(&lt;span style="color: #2b91af"&gt;IUserSession &lt;/span&gt;userSession)
{
    _userSession = userSession;
}

&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ActionResult &lt;/span&gt;Index()
{
    &lt;span style="color: blue"&gt;var &lt;/span&gt;user = _userSession.GetUser();

    &lt;span style="color: blue"&gt;return &lt;/span&gt;View(user);
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Instead of using a dictionary directly, I’ll hide that business behind a facade service, keeping the dictionary ugliness and duplication in one highly cohesive class.&amp;#160; But it was the _test_ that led me to do this, because I’m tuned in to pieces that are hard to mock.&amp;#160; File I/O?&amp;#160; Facade.&amp;#160; Web service proxies?&amp;#160; Facade.&amp;#160; Registry, HttpContext, etc. etc?&amp;#160; All facade.&amp;#160; I want to isolate my core application from the untestable pieces, not because they’re necessary untestable, but because I don’t want to couple my application directly to these external services.&amp;#160; Putting these behind targeted facades eliminates all that duplication that directly using these APIs tends to encourage.&lt;/p&gt;

&lt;p&gt;There are plenty of APIs that slapping a simple facade over tends to make things worse, not better, such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Workflow Foundation&lt;/li&gt;

  &lt;li&gt;SharePoint&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And any other framework that requires you to tiiiiightly integrate with in order to be successful.&amp;#160; So where does that leave me and TypeMock?&amp;#160; Well, I don’t use any of those frameworks that require tight coupling, and I don’t have any pain with my current tool of choice in .NET (Rhino Mocks), so why switch exactly?&amp;#160; For those rare occasions I might need TypeMock (DateTime.Now), I &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/11/09/systemtime-versus-isystemclock-dependencies-revisited.aspx"&gt;already have a solution&lt;/a&gt; I quite like.&amp;#160; Yes, TypeMock could be free, but the only compelling reason I’d switch would be to another free tool with a better, clearer to write, read and scan API.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Willed+and+forced+design&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjimmy_bogard%2farchive%2f2009%2f11%2f12%2fwilled-and-forced-design.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjimmy_bogard%2farchive%2f2009%2f11%2f12%2fwilled-and-forced-design.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=30528" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/E6CB54A635101C0BBEAFF9241A09CBA6DCE7C038"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/E6CB54A635101C0BBEAFF9241A09CBA6DCE7C038"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=hPccuMKJZC4:zHVs41W1hF4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=hPccuMKJZC4:zHVs41W1hF4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=hPccuMKJZC4:zHVs41W1hF4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=hPccuMKJZC4:zHVs41W1hF4:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/hPccuMKJZC4" height="1" width="1"/&gt;</description><category domain="http://www.lostechies.com/blogs/jimmy_bogard/archive/tags/TDD/default.aspx">TDD</category><feedburner:origLink>http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/11/12/willed-and-forced-design.aspx</feedburner:origLink></item><item><title>How We Do Things - Evolving our Specification Practice</title><link>http://feedproxy.google.com/~r/LosTechies/~3/H0iODGhtM5U/how-we-do-things-evolving-our-specification-practice.aspx</link><pubDate>Thu, 12 Nov 2009 21:59:14 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:30503</guid><dc:creator>Scott C Reynolds</dc:creator><slash:comments>2</slash:comments><description>&lt;p&gt;&lt;em&gt;This content comes solely from my experience, study, and a lot of trial and error (mostly error). I make no claims stating that which works for me will work for you. As with all things, your mileage may vary, and you will need to apply all knowledge through the filter of your context in order to strain out the good parts for you. Also, feel free to call BS on anything I say. I write this as much for me to learn as for you.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This is part 6 of the &lt;a href="http://www.lostechies.com/blogs/scottcreynolds/archive/2009/10/04/how-we-do-things-preamble-and-contents.aspx"&gt;How We Do Things&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post was co-written on Google Wave with my colleague &lt;a href="http://www.catschwamm.com"&gt;Cat Schwamm&lt;/a&gt;, who keeps me sane every day.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this part we will explore how specification practice has evolved in our team, from a very waterfallish BDUF approach to what currently is a very lean approach to specification. In the next part of the series we will talk stories and mockups and other tools we employ to make the magic happen.&lt;/p&gt;
&lt;h3&gt;Where we came from&lt;/h3&gt;
&lt;p&gt;We began our large LIS project in late 2004, starting with about 6 full months of writing specifications and designing the database. We created reams of documentation for each application complete with use cases that we knew we wouldn't even implement until after the first version was released (sidebar: some of those still haven't been done). We defined more than 100 tables of heavily normalized database schema. Before one line of code was written, we had spent six months of project budget.&lt;/p&gt;
&lt;p&gt;As development continued on the project we found ourselves diverging from the specifications that had been created. The documents became little more than a roadmap, with the bold headers on functional groups and the basic usage stories becoming the guidelines that we followed. Much of the detailed specification and database schema went out the window as the system took shape and people began to see and give feedback on what was being produced. Too much specification gave us a false sense of "doing it right" and led us down many wrong paths. Balancingrework with completing planned features became a costly chore.&lt;/p&gt;
&lt;p&gt;By the time the project was complete, it was clear that much of that up-front work had been wasted time and money. Had we top-lined the major milestones of such a large project, detailed a small set of functionality, and started developing iteratively, the system would have taken form much sooner, allowing for a tighter feedback loop and much less overall waste.&lt;/p&gt;
&lt;h3&gt;How we do it now - Overview&lt;/h3&gt;
&lt;p&gt;Lessons learned, we set about improving how we do specification. I already talked a little about this in the posts on planning, so please review those if you haven't seen them yet. &lt;a href="http://www.scottcreynolds.com/archive/2009/10/05/607.aspx"&gt;[part 1]&lt;/a&gt; &lt;a href="http://www.scottcreynolds.com/archive/2009/10/06/609.aspx"&gt;[part 2]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When planning a new project of any size, we take an iterative approach. We start at a very high level, and strive to understand the goals of the project. What need does it serve? Who will be using it? Are we competing with something else for market share? Is there a strategic timeline? What's the corporate vision here? What are the bullet points? We will fill in details later. We only want broad targets to guide us further.&lt;/p&gt;
&lt;p&gt;When we get closer to development, we start to identify smaller chunks of functionality within each of those broad areas. This is still pretty high level, but done by business analysts and management on the IT team. We start to identify MMFs (minimal marketable features) and group them up in order of importance to help determine next steps.&lt;/p&gt;
&lt;p&gt;MMFs in hand, we take the first one and start defining it further. This is where the information from the planning post comes in. We start to write stories (Cat has a &lt;a href="http://catschwamm.com/2009/08/09/constructing-effective-user-stories-or-my-user-stories-bring-all-the-boys-to-the-yard/"&gt;great post&lt;/a&gt; detailing how to build effective stories). The other information gathered to this point sits dormant, with as little specification work done as possible, until such time as we are getting closer to working on it.&lt;/p&gt;
&lt;p&gt;Over time, and only as needed, we put more and more specification on the system, and this is done in parallel with development. In fact, often the most specific information can only surface during development of those features, as they take shape, and as we understand how users will react. Specification should be every bit as iterative as coding.&lt;/p&gt;
&lt;p&gt;Reduced to its essence, we JIT specification at many levels to allow maximum flexibility to change direction with minimal wasted work.&lt;/p&gt;
&lt;h3&gt;Gemba is an essential part of specification&lt;/h3&gt;
&lt;p&gt;
It's often the case that a team relies on "domain experts" to provide them with the specifications they need to build software. This is the BDUF way - gather in committee and have the all-knowing user tell you what to build. Fail.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cat sez:&lt;/em&gt;
&lt;/p&gt;&lt;blockquote&gt;
The dev team works out of the corporate office in Florida, while the actual laboratory is located in upstate New York. As a result, it is often an exercise of the imagination to figure out the best way to create things for them. Before I visited the lab, I relied on information from others, emails back and forth to the lab crews working all weird hours of the night, and my knowledge of the applications currently in existence. I really only ever got half the picture, and it was difficult to ensure that the things I was specifying would fit into the lab users workflow well without actually knowing what was going on up there. When I visited the lab my whole world was changed. Actually seeing how users interacted with the software and seeing ways they would work around what we didn't have (open Excel or Word documents on their desktop, a wall covered in post-it notes). Just from walking around talking to people for 2 days, I probably got 50 requests. And they never would have asked for them; they would have just kept suffering. Being there showed me everything about how they worked and a million ways I could improve their lives. The experience was invaluable to both me and them, and each subsequent trip has just improved my knowledge of the way we work and the way they interact with our software.&lt;/blockquote&gt;
&lt;p&gt;There is no substitute for a certain amount of domain expertise being resident in the team room. Your domain experts are experts only in their domain. They may know the workings of a histology laboratory inside and out, but if you ask them to design a system to support that lab, they'll come back with something that looks an awful lot like excel and post-it notes.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/scottcreynolds/postits.png" alt="postits.png" border="0" width="604" height="453" /&gt;&lt;br /&gt; &lt;em&gt;Yes...this is a workaround someone had for something our system didn't do. It's been fixed ;)&lt;/em&gt;&lt;/div&gt;
&lt;p&gt;Lean has a concept of the &lt;a href="http://en.wikipedia.org/wiki/Gemba"&gt;gemba attitude&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Genchi_Genbutsu"&gt;genchi genbutsu&lt;/a&gt;, essentially, being in the place where the action happens. Developers and business analysts have to work with the domain experts, in the place where the work happens, and observe the true workflows in place before hoping to design a system to support them. You cannot get this information from sit down meetings and emails with domain experts. You must go and see for yourself, or you will miss things.&lt;/p&gt;
&lt;p&gt;
In the next post we will talk specifically about the tools and techniques we use to specify work, and how we combine them to form complete pictures of a system (spoiler alert: it ain't just stories).&lt;/p&gt;&lt;/div&gt;
&lt;!-- Technorati Tags Start --&gt;
&lt;p&gt;Technorati Tags:
&lt;a href="http://technorati.com/tag/how                   4e                  12o                   4t" rel="tag"&gt;how we do it&lt;/a&gt;, &lt;a href="http://technorati.com/tag/improvement" rel="tag"&gt;improvement&lt;/a&gt;, &lt;a href="http://technorati.com/tag/lean" rel="tag"&gt;lean&lt;/a&gt;, &lt;a href="http://technorati.com/tag/management" rel="tag"&gt;management&lt;/a&gt;, &lt;a href="http://technorati.com/tag/quality" rel="tag"&gt;quality&lt;/a&gt;, &lt;a href="http://technorati.com/tag/software" rel="tag"&gt;software&lt;/a&gt;, &lt;a href="http://technorati.com/tag/team" rel="tag"&gt;team&lt;/a&gt;, &lt;a href="http://technorati.com/tag/planning" rel="tag"&gt;planning&lt;/a&gt;
&lt;/p&gt;
&lt;!-- Technorati Tags End --&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=How+We+Do+Things+-+Evolving+our+Specification+Practice&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fscottcreynolds%2farchive%2f2009%2f11%2f12%2fhow-we-do-things-evolving-our-specification-practice.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fscottcreynolds%2farchive%2f2009%2f11%2f12%2fhow-we-do-things-evolving-our-specification-practice.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=30503" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/292D42307DE44656D14125697C667B83D9839F82"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/292D42307DE44656D14125697C667B83D9839F82"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=H0iODGhtM5U:J9nwWDmsfvw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=H0iODGhtM5U:J9nwWDmsfvw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=H0iODGhtM5U:J9nwWDmsfvw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=H0iODGhtM5U:J9nwWDmsfvw:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/H0iODGhtM5U" height="1" width="1"/&gt;</description><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/lean/default.aspx">lean</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/management/default.aspx">management</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/software/default.aspx">software</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/improvement/default.aspx">improvement</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/how+we+do+it/default.aspx">how we do it</category><category domain="http://www.lostechies.com/blogs/scottcreynolds/archive/tags/team/default.aspx">team</category><feedburner:origLink>http://www.lostechies.com/blogs/scottcreynolds/archive/2009/11/12/how-we-do-things-evolving-our-specification-practice.aspx</feedburner:origLink></item><item><title>Going Away Geek Beers</title><link>http://feedproxy.google.com/~r/LosTechies/~3/SAcVVGt-bmg/going-away-geek-beers.aspx</link><pubDate>Thu, 12 Nov 2009 14:47:43 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:30470</guid><dc:creator>Scott C Reynolds</dc:creator><slash:comments>1</slash:comments><description>&lt;p&gt;Most of you have heard by now that I am leaving Florida for the concrete pastures of New York City.&lt;/p&gt;
&lt;p&gt;I'd like to have a get-together of some of the Florida community guys (and gals) Monday, Nov 16, in Ocala at 7pm until we decide to leave.&lt;/p&gt;
&lt;p&gt;It's truly been a pleasure working with this community over the last few years, and I will miss you guys. So..come on out and buy me a beer! ;)&lt;/p&gt;
&lt;p&gt;Location: &lt;a href="http://maps.google.com/maps/place?oe=utf-8&amp;rls=org.mozilla:en-US:official&amp;client=firefox-a&amp;um=1&amp;ie=UTF-8&amp;q=omalley%27s+alley+ocala&amp;fb=1&amp;gl=us&amp;hq=omalley%27s+alley&amp;hnear=ocala&amp;cid=6839249953853431108"&gt;O'Malley's Alley&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My phone is 352.209.0943 drop me a line if you get lost of want to confirm you're coming. So far looks like a real good group will be there, including Cory Foy, Sean Chambers, Scott Densmore, and Will Green, the amazing &lt;a href="http://www.catschwamm.com"&gt;Cat Schwamm&lt;/a&gt; as well as members of my team. Hope to see you Monday!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Going+Away+Geek+Beers&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fscottcreynolds%2farchive%2f2009%2f11%2f12%2fgoing-away-geek-beers.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fscottcreynolds%2farchive%2f2009%2f11%2f12%2fgoing-away-geek-beers.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=30470" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/99129E1C0881059A8898C1D711B219D9E050BBC2"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/99129E1C0881059A8898C1D711B219D9E050BBC2"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=SAcVVGt-bmg:wREZzsHGvnI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=SAcVVGt-bmg:wREZzsHGvnI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=SAcVVGt-bmg:wREZzsHGvnI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=SAcVVGt-bmg:wREZzsHGvnI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/SAcVVGt-bmg" height="1" width="1"/&gt;</description><feedburner:origLink>http://www.lostechies.com/blogs/scottcreynolds/archive/2009/11/12/going-away-geek-beers.aspx</feedburner:origLink></item><item><title>Electronic Kanban Tools and WIP Limits: LeanKitKanban and AgileZen Get It!</title><link>http://feedproxy.google.com/~r/LosTechies/~3/qNAH9TNEWuA/electronic-kanban-tools-and-wip-limits-leankitkanban-gets-it.aspx</link><pubDate>Mon, 09 Nov 2009 17:55:24 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:30192</guid><dc:creator>derick.bailey</dc:creator><slash:comments>10</slash:comments><description>&lt;p&gt;Most of the electronic Kanban boards that exist simply don’t understand what WIP limits are really about. They all seem to go down the path of forcing any step (column) in the process to have a maximum limit that is very hard and fast. They set it up so that you cannot add any more items to the step than the limit allows. But the truth about WIP limits is that they are not supposed to be hard and fast, mechanical limits. Putting in a hard limit like this is a great way to destroy the productivity of a team and usefulness of a tool when the team finds themselves in a crunch, in a situation with additional resources and needs, or any of a number of other circumstances.&lt;/p&gt;  &lt;p&gt;I know I haven’t been vocal about this online, but it’s something I’ve been complaining about to my coworkers and friends for a while. It bugs me and is one of the major reasons that I’ve stayed away from the major (free) players in the electronic Kanban realm, other than trials and basic testing of the systems.&lt;/p&gt;  &lt;p&gt;But then I got an email from Chris Hefley this morning, about some new features in &lt;a href="http://leankitkanban.com/"&gt;LeanKitKanban&lt;/a&gt;. When I logged in to check them out, I was surprised to see this happen when I tried to exceed a column limit:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/derickbailey/image_5F00_0093C96B.png" width="646" height="450" /&gt; &lt;/p&gt;  &lt;p&gt;I can’t tell you how happy I was to see this! Finally, one of the tools vendors in this space is really starting to get it! For this, and a few other reasons that I don’t want to talk about yet, &lt;a href="http://leankitkanban.com/"&gt;LeanKitKanban&lt;/a&gt; is now officially my favorite electronic Kanban / task board around. If you haven’t done so, I highly recommend that you check them out. &lt;/p&gt;  &lt;p&gt;Do any other electronic Kanban boards are heading down this same path and allowing for limit overrides? If your current tool doesn’t support this, it should.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Looks like &lt;a href="http://agilezen.com"&gt;AgileZen&lt;/a&gt; is getting this feature in the next release (see Nate’s comments below). that’s great news! I’ve been impressed by this tool as well. the support for soft WIP limits in multiple tools is starting to show some real competition and innovation in the market space. that’s good news for everyone!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Electronic+Kanban+Tools+and+WIP+Limits%3a+LeanKitKanban+and+AgileZen+Get+It!&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fderickbailey%2farchive%2f2009%2f11%2f09%2felectronic-kanban-tools-and-wip-limits-leankitkanban-gets-it.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fderickbailey%2farchive%2f2009%2f11%2f09%2felectronic-kanban-tools-and-wip-limits-leankitkanban-gets-it.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=30192" width="1" height="1"&gt;&lt;p&gt;&lt;a target="_blank" href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/8F6C0CBB9EBB1B3136EBEF51F6EDCCA9C1B83230"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/8F6C0CBB9EBB1B3136EBEF51F6EDCCA9C1B83230"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=qNAH9TNEWuA:-XhSdSglD2I:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=qNAH9TNEWuA:-XhSdSglD2I:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=qNAH9TNEWuA:-XhSdSglD2I:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=qNAH9TNEWuA:-XhSdSglD2I:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/qNAH9TNEWuA" height="1" width="1"/&gt;</description><category domain="http://www.lostechies.com/blogs/derickbailey/archive/tags/Management/default.aspx">Management</category><category domain="http://www.lostechies.com/blogs/derickbailey/archive/tags/Kanban/default.aspx">Kanban</category><category domain="http://www.lostechies.com/blogs/derickbailey/archive/tags/Metrics/default.aspx">Metrics</category><category domain="http://www.lostechies.com/blogs/derickbailey/archive/tags/Tools+and+Vendors/default.aspx">Tools and Vendors</category><feedburner:origLink>http://www.lostechies.com/blogs/derickbailey/archive/2009/11/09/electronic-kanban-tools-and-wip-limits-leankitkanban-gets-it.aspx</feedburner:origLink></item></channel></rss>
