<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2730416853424583572</id><updated>2011-07-29T00:00:37.564+02:00</updated><category term='Personal'/><category term='Lean'/><category term='TDD'/><category term='Rants'/><category term='Agile'/><category term='Programming'/><category term='skepticism'/><category term='mentalism'/><title type='text'>Tormod</title><subtitle type='html'>Welcome to my blog. 

My place for banter and wrecking thought trains. Even the occasional take-away value to be had for the occasional poor lost soul who ventures in here.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>33</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-73581112126962865</id><published>2011-05-04T09:14:00.001+02:00</published><updated>2011-05-04T09:14:26.050+02:00</updated><title type='text'>Technical debt</title><content type='html'>&lt;p&gt;In our profession we sometimes find that it is hard to find an layman analogy that properly describes tendencies and properties that characterize our craft.&lt;/p&gt;  &lt;p&gt;A codebase can be purposely characterized as being “rigid” or “brittle”. We may laugh at how appropriately it describes specific components. But aside from a good laugh, this is something that we should be more familiar with as it helps to communicate to other professions than programmers.&lt;/p&gt;  &lt;p&gt;Sometimes an analogy is so powerful that it becomes an industry standard.&lt;/p&gt;  &lt;p&gt;One such term was coined by &lt;b&gt;Ward Cunningham&lt;/b&gt; who worked with clients in a financial institution and was bogged down by codebase riddled with issues. The end functionality was satisfactory and the clients were initially unwilling to invest 2-3 months of work without an increase in added business value just to “improve the quality of the code”.&lt;/p&gt;  &lt;p&gt;The qualities of the codebase, aside from functionality, were invisible to the clients. They &lt;i&gt;did&lt;/i&gt; notice, however, that:&lt;/p&gt;  &lt;p&gt;· Estimates more frequently went into weeks.&lt;/p&gt;  &lt;p&gt;· Small changes broke unrelated stuff.&lt;/p&gt;  &lt;p&gt;· Programmers are reluctant to visit certain parts of the system. &lt;/p&gt;  &lt;p&gt;Cunningham introduced the term “Technical debt”. And with this simple context switch, suddenly its financial aspects were apparent to the client.&lt;/p&gt;  &lt;p&gt;It simply means that you have borrowed something, most commonly &lt;i&gt;time&lt;/i&gt;, from somewhere. As with any debt, you will have to keep paying your mortgage until you have paid it back. If you decide to not pay, interest will accumulate. &lt;/p&gt;  &lt;p&gt;It doesn’t have to be time, it may be &lt;i&gt;understanding the component or technology&lt;/i&gt;. You have found a nice little place where you can insert a discrete “if-then” sidetrack to patch up or filter away some data that passes through some random snippet. You are both confident that you haven’t broken anything and you count yourself lucky that you didn’t have to understand the complete context of the snippet.&lt;/p&gt;  &lt;p&gt;The problem is that the code &lt;i&gt;rots&lt;/i&gt;. If you never decide to give pay the borrowed time &lt;i&gt;back&lt;/i&gt;, you end up with most functions not doing what they claim to be doing. The code is not coherent at any one level. You need to constantly deep dive to figure out how it “really” works. Soon, “if-then” is all that you dare do. &lt;/p&gt;  &lt;p&gt;Technical debt will accumulate exponentially, especially since management will frown upon a decrease in productivity. So, the developer “steals” more time from the pool of technical debt.&lt;/p&gt;  &lt;p&gt;Technical debt is, like ordinary debt, something that is &lt;u&gt;not &lt;i&gt;inherently&lt;/i&gt; &lt;i&gt;bad&lt;/i&gt;&lt;/u&gt;, but it should be &lt;i&gt;&lt;u&gt;responsibly managed&lt;/u&gt;&lt;/i&gt;. It is a tool. If a business never went into any kind of debt, it would lose all agility and could not respond to its market, but would be at the complete mercy of its technical underpinnings.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-73581112126962865?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/73581112126962865/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2011/05/technical-debt.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/73581112126962865'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/73581112126962865'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2011/05/technical-debt.html' title='Technical debt'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-2910559391044382424</id><published>2010-10-25T10:46:00.001+02:00</published><updated>2010-11-25T10:21:06.373+01:00</updated><title type='text'>Working at granularity of functions instead of Unit-Of-Work</title><content type='html'>&lt;h1&gt;The Problem&lt;/h1&gt;  &lt;p&gt;When I develop tools for internal use, my users are process engineers. Tech savvy people, but not coders. The problem domain is of a technical nature which should be the perfect place to create tooling for automating the project production. We spend thousands of hours every year, as do every competitor, on checking numbers, transposing tables and datasets using ordinary office software. We are delivering at quality and cost, but still inefficient.&lt;/p&gt;  &lt;p&gt;We’ve all experienced the users with a “vision”. We’ve had it ourselves. The big framework in the sky. The game changing application that does everything and knows everything. Attempts at making this application become bloated, costly, maintenance heavy and often fail to materialize. &lt;/p&gt;  &lt;p&gt;Consider the typical setup of such Engineers. There is a big project about to be delivered. The project can be broken down into sub systems. And then the principal engineer distributes the work load between the available resources:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_ll3fiWXgCdo/TMVDy2-HQMI/AAAAAAAAACA/PIGe8VejsaI/s1600-h/image%5B68%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh4.ggpht.com/_ll3fiWXgCdo/TMVDzUip2xI/AAAAAAAAACE/XJgnZjYFDxE/image_thumb%5B50%5D.png?imgmax=800" width="145" height="240" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;All engineers do basically the same work, but on different parts of the system. The complexity of the end product decides the required skill level of the engineer. A complex subsystem will be handled by a senior engineer.&lt;/p&gt;  &lt;p&gt;In reality, this is a false premise. The complexity of the end product is irrelevant. What matters is the complexity of the work to produce it.&lt;/p&gt;  &lt;p&gt;When re-examining the work flow in order to automate it, it is more interesting to let the workflow be influenced by the emergent properties of the new problem domain, which is the project &lt;em&gt;execution&lt;/em&gt;, not the end product.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_ll3fiWXgCdo/TMVDzg_CS2I/AAAAAAAAACI/3jlTaMhJmSk/s1600-h/image%5B67%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh6.ggpht.com/_ll3fiWXgCdo/TMVDz8xZd4I/AAAAAAAAACM/HukPt93v-g8/image_thumb%5B49%5D.png?imgmax=800" width="95" height="164" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;When working in a tight loop with this person we compose sovereign functions that various (disconnected) parts of his workload.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_ll3fiWXgCdo/TMVD0A7nCbI/AAAAAAAAACQ/qwEuuhVxTYo/s1600-h/image%5B66%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh5.ggpht.com/_ll3fiWXgCdo/TMVD0bHGrqI/AAAAAAAAACU/chF6xxyD-N8/image_thumb%5B48%5D.png?imgmax=800" width="95" height="164" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Basically, I have created one empowered user. One user who can field test the functions. Note that I haven’t created any application yet, only functions. There is an &lt;em&gt;execution engine.&lt;/em&gt; But at this point the functions are tailor made to the individual user.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_ll3fiWXgCdo/TMVD02A-pPI/AAAAAAAAACY/VqZnlG2iVq4/s1600-h/image%5B65%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh6.ggpht.com/_ll3fiWXgCdo/TMVD1fSjJ9I/AAAAAAAAACc/MvxTJxbBt1c/image_thumb%5B47%5D.png?imgmax=800" width="95" height="164" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;If you were to cram all these functions in the same app, you would incur a significant maintenance debt. The functions behave differently and change for different reasons. The volatility of the end app is the sum of all volatility in its parts. Immature functions will immediately clutter the design, both architecturally and the GUI.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;When field testing the functions, it is common to group these functions chronologically or by subsystem. However, there is another, often overlooked, aspect to consider. Namely, the complexity of &lt;em&gt;applying/executing&lt;/em&gt; the function to/against the workload.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_ll3fiWXgCdo/TMVD1jt3E4I/AAAAAAAAACg/tvEhi6kZKRE/s1600-h/image%5B73%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh6.ggpht.com/_ll3fiWXgCdo/TMVD2JN4KtI/AAAAAAAAACk/hyYSZ_QLVuQ/image_thumb%5B53%5D.png?imgmax=800" width="235" height="219" /&gt;&lt;/a&gt; ‘&lt;/p&gt;  &lt;p&gt;When field testing the functions, new classifications emerge.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Some functions (green) can be run straight out-of-the-box. A button would do. &lt;/li&gt;    &lt;li&gt;Some functions (yellow) demand tweaking in a few places. They can be executed, but with options. &lt;/li&gt;    &lt;li&gt;Some functions(orange), however, demand unpredictable tweaking and its parameterization is hard to identify. &lt;/li&gt;    &lt;li&gt;And finally you have the functions (red) that seemingly demand the same complexity as the computer code itself. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;To cram all such responsibilities into a single application, is IMO a heavy contributor to application bloating, code rot and the ol’ saying “software is never done, it is abandoned”. The problem is that application developers will fail to properly absorb user requirements in the red and orange category. In an organization where the developer should not be assumed to know the complexity of the problem domain, this is very costly indeed. Especially if your toolchain has an expensive and slow release process.&lt;/p&gt;  &lt;h1&gt;The solution &lt;/h1&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;You examine options for implementing a GUI for the orange/red category. Instead, you let the principal engineers earn their pay. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_ll3fiWXgCdo/TMVD2f7MYgI/AAAAAAAAACo/Hgc9utOf7fw/s1600-h/image%5B79%5D.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_ll3fiWXgCdo/TMVD2-co6EI/AAAAAAAAACs/kAM0s1W7dzg/image_thumb%5B57%5D.png?imgmax=800" width="199" height="318" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Also, as we keep running the functions, we learn more about them, and we are able to “push” them towards the &amp;quot;green” category. And, as we are discovering new aspects of our work flow, functions can be spawned in the yellow/orange category and through field testing end up in the green/yellow category. &lt;/p&gt;  &lt;p&gt;So, NOW, we create GUI.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_ll3fiWXgCdo/TMVD3WoMRmI/AAAAAAAAACw/If94PsZt64U/s1600-h/image%5B91%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh5.ggpht.com/_ll3fiWXgCdo/TMVD3kq1ALI/AAAAAAAAAC0/60guT-1dX9k/image_thumb%5B65%5D.png?imgmax=800" width="230" height="348" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Yes, I’m serious. The principal engineer is actually handling computer code (C#) &lt;em&gt;in production&lt;/em&gt;. This model has some additional key benefits that may not be obvious. &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The whole workforce is now a living design process. &lt;/li&gt;    &lt;li&gt;As they mature, functions gravitate towards the green. &lt;/li&gt;    &lt;li&gt;App1 is very simple with functions and work flow that is well tested before its first version was released. It handles the bulk of the work. Changes are easy, safe and inexpensive. &lt;/li&gt;    &lt;li&gt;Apps of type “App2” may be more complex, but its complexity is warranted and it is towards a more focused problem domain as well as a dedicated audience. Typically specialized roles/contexts. Stuff you don’t want to clutter up the common case with. &lt;/li&gt;    &lt;li&gt;Functions of a complex nature, one-shots or that people have trouble defining can be put into production in orange and red category, and let it mature for a while. &lt;/li&gt;    &lt;li&gt;There is a natural progression and common ground between the developer and the principal engineers. &lt;/li&gt;    &lt;li&gt;The process is no longer constrained by the GUI and is never blocked. Whenever the App1 does not cover something because of some rare case, chances are that the principal engineer can run the underlying function. We do not need to put a GUI harness around every single conceivable usage. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;And, it friggin’ works.&lt;/strong&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-2910559391044382424?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/2910559391044382424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2010/10/axis-and-freedom-of-unit-of-work.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/2910559391044382424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/2910559391044382424'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2010/10/axis-and-freedom-of-unit-of-work.html' title='Working at granularity of functions instead of Unit-Of-Work'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_ll3fiWXgCdo/TMVDzUip2xI/AAAAAAAAACE/XJgnZjYFDxE/s72-c/image_thumb%5B50%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-7076568537390305653</id><published>2010-10-23T12:36:00.001+02:00</published><updated>2010-10-23T12:36:31.398+02:00</updated><title type='text'>To revolutionize the unknown at App version 1.0</title><content type='html'>&lt;p&gt;How do you create a seasoned application already on version 1.0? One that completely revolutionize a field/discipline that you as a Software Craftsman know little about? &lt;/p&gt;  &lt;p&gt;Can it be done? How is it possible to create something that neither you nor your customer can’t be assumed know up front. Nor should either of you be expected to know. Sure, sometimes people have bright ideas, but the model is potluck and doesn’t scale.&lt;/p&gt;  &lt;p&gt;In traditional waterfall, the user is expected to outline his requirements even though his expertise is the current (obsolete) work&amp;#160; model that you shouldn’t be constrained by. Also, his experience with the work model is the &lt;em&gt;execution&lt;/em&gt; of the work model,&amp;#160; not the work model itself.&lt;/p&gt;  &lt;p&gt;In our world of outsourcing, the distance between the supplier of the tools and the place where the work is executed becomes considerable. Even in our little organization of a few thousand employees.&lt;/p&gt;  &lt;p&gt;So how do you do it?&lt;/p&gt;  &lt;p&gt;The old model is to enter the process by connecting a few dots from his existing work flow from a fresh perspective. You can give the work flow a face lift by reducing the amount of clicks and giving more sensible GUI. You can represent something in a rich grid. You can do a parent-child separation to remove a couple of small popup dialogs. But the result is in danger of being like a horse carriage with mechanical horses instead of inventing the automobile.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;How do you go about &lt;em&gt;&lt;strong&gt;revolutionizing&lt;/strong&gt;&lt;/em&gt; a labor intensive work flow that neither you or the customer should be expected to have broken down up front.&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;You do it by pair programming with a non-programmer. You perform the work alongside the person. You watch him work over his shoulder, you ask, you nag, you challenge and you reward. You switch back and forth between annoying the hell out of them and blowing their minds.&lt;/p&gt;  &lt;p&gt;In my current work model, LinqPAD is a key component in this. The other person is able to field-test a function just seconds after I have written it. At the end of a cycle, I have created an empowered person equipped with functions that he can bring to the field. Never losing productivity during the process.&lt;/p&gt;  &lt;p&gt;And when we have the complete set of functions that are both complete, validated and field tested…. then we are ready to create App version 1.0 based on wealth of experience from seasoned functions all in a revolutionized work model…. without it sounding contradictive anymore.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-7076568537390305653?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/7076568537390305653/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2010/10/to-revolutionize-unknown-at-app-version.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/7076568537390305653'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/7076568537390305653'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2010/10/to-revolutionize-unknown-at-app-version.html' title='To revolutionize the unknown at App version 1.0'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-3951132474866783736</id><published>2010-08-11T12:42:00.001+02:00</published><updated>2010-08-11T12:42:56.388+02:00</updated><title type='text'>Empowering the alpha geeks using LinqPAD</title><content type='html'>&lt;p&gt;Sometimes, you find that the users are destined to be constrained by their GUI. That the developers of the tool chain simply cannot satisfy all consumers of said tools. The complex domain of their business model dictates a complexity that will in turn impede release cycle time and you will never be able to bridge the gap. Ironically, the sum of the user experience is more complex than the underlying reality that it is designed to simplify. &lt;/p&gt;  &lt;p&gt;“If you can’t beat the enemy, join them”. I like the reverse even more: if they can’t beat you, they should join you.&lt;/p&gt;  &lt;p&gt;So, I’ve decided that a particular subset of my users should learn programming. The C# language is expressive and rich. Combined with a rich object model, I may have sugar coated the pill sufficiently to make them take the leap. Suddenly I am not constrained by having to change the GUI anymore, because there is no GUI. &lt;/p&gt;  &lt;p&gt;I have found the perfect bed partner for this endeavor. It is combined development and execution engine for C# snippets that operate against a hidden object model as well as a snippet repository. I am working full throttle to ready an object model to be available for the next launch. &lt;/p&gt;  &lt;p&gt;Bjarne Stroustrup said &amp;quot;I wouldn't like to build a tool that could only do what I had been able to imagine for it.&amp;quot;&lt;/p&gt;  &lt;p&gt;My hope is that the new breed of users will be able to push the envelope to reach new heights of productivity and quality (through automated and assisted audit functionality) and that desired functionality will come in the form of enrichment of the object model as opposed to dabbling in intricacies of how they plan to consume them.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-3951132474866783736?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/3951132474866783736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2010/08/empowering-alpha-geeks-using-linqpad.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/3951132474866783736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/3951132474866783736'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2010/08/empowering-alpha-geeks-using-linqpad.html' title='Empowering the alpha geeks using LinqPAD'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-5083706140410743495</id><published>2010-08-10T12:49:00.001+02:00</published><updated>2010-08-10T12:54:03.423+02:00</updated><title type='text'>Making a maintainable new library of legacy snippets</title><content type='html'>&lt;p&gt;I recently went through a typical exercise of integrating an existing implementation from a legacy component into a new component with a cleaner API and higher level of functionality. The legacy component interfaced a OPC library and used a lot of magic numbers, memory offsets, type conversions etc.&amp;#160; The existing component did not have functions for systematic reconnect, subscribe group status, book keeping for multiple groups etc. The existing code does everything necessary, but the code is not organized to have a clean higher level API. The code is also pretty fragile. If you make changes and then suddenly find that something has stopped working, you have hours of tedious debugging ahead of you. &lt;/p&gt;  &lt;p&gt;A typical scenario where you normally would copy/paste from the older code base and end up with snippets here and there in your code which would have dependencies to arbitrary components. And, if you were to create unit tests, they would only mirror the production code and basically be redundant.&lt;/p&gt;  &lt;p&gt;I decided to do it differently and I am happy with the result. The process may seem like over engineering, but it didn’t feel like it while doing it nor do I feel that the components are difficult to change.&lt;/p&gt;  &lt;p&gt;The first challenge was to identify snippets. I do not plan to put those snippets under tests. It’s black magic. But I do plan on testing them.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;So I extract the snippets&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_ll3fiWXgCdo/TGEuxP6yjLI/AAAAAAAAABo/-BwbmXBXOtg/s1600-h/image%5B10%5D.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://lh5.ggpht.com/_ll3fiWXgCdo/TGEuxQDihkI/AAAAAAAAABs/_hyM_vk4CL8/image_thumb%5B4%5D.png?imgmax=800" width="396" height="349" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;EDIT! The arrow should be pointing from legacy snippets towards the adapter, obviously&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Now I run Online tester, which operates on the live system. I have functions such as:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Add member&lt;/li&gt;    &lt;li&gt;Create Group&lt;/li&gt;    &lt;li&gt;Change Group status&lt;/li&gt;    &lt;li&gt;Remove Member&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;If I try to add members without taking the group offline first, the app will crash. The point of this exercise is to discover the “rules” of the Adapter. These are rules at the correct level of abstractions and they have a natural place in unit tests. How the legacy snippets actually go about &lt;em&gt;taking&lt;/em&gt; the group offline, is not my concern and can only be meaningfully tested against the live system anyhow. There is automated testing done through this app, but they are integration tests and must be set up and kicked off manually.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_ll3fiWXgCdo/TGEux4bD1rI/AAAAAAAAABw/ghQdG0kO6qM/s1600-h/image%5B15%5D.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://lh4.ggpht.com/_ll3fiWXgCdo/TGEuyAjq4SI/AAAAAAAAAB0/alR37MD-yUI/image_thumb%5B7%5D.png?imgmax=800" width="511" height="601" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;EDIT! The arrow should be pointing from legacy snippets towards the adapter, obviously&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This is the result. I have now five projects instead of one (not counting any client) but I feel that I have harnessed the legacy snippets to serve any new component that comes along. Whenever a new version of the live system is released, I need to retest the legacy code, but I do not have to permutate&amp;#160; through various compositions of those snippets to confirm validity of utility functions, as that is covered in the unit tests. I rarely do any change to the Ugly Legacy Code (ULC, pronounced &lt;strong&gt;&lt;em&gt;ulcer&lt;/em&gt;&lt;/strong&gt;, he he).&lt;/p&gt;  &lt;p&gt;The Helper function library is growing quite substantially and with clean unit tests. I have successfully harnessed, and extended upon, a complete mess of a code. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-5083706140410743495?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/5083706140410743495/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2010/08/making-maintainable-new-library-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/5083706140410743495'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/5083706140410743495'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2010/08/making-maintainable-new-library-of.html' title='Making a maintainable new library of legacy snippets'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_ll3fiWXgCdo/TGEuxQDihkI/AAAAAAAAABs/_hyM_vk4CL8/s72-c/image_thumb%5B4%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-10323581471047130</id><published>2010-05-21T10:34:00.001+02:00</published><updated>2010-05-21T10:34:08.046+02:00</updated><title type='text'>Adopting the blind spots.</title><content type='html'>&lt;p&gt;A clear distinction between the master and the apprentice is the mental model that they operate from. If a relevant concept is clearly &lt;strong&gt;absent&lt;/strong&gt; from your thought process altogether, it can be described as a disability.&lt;/p&gt;  &lt;p&gt;I am currently visiting legacy code written by novice programmers. This code base clearly demonstrate a lack of separating microsecond, millisecond and second domains. Disk access, sql server access and web service in the middle of loops. Although there was an elaborate architecture to separate the service level from the data level, comprehension of the penalties involved by ping-ponging between them in the control flow timeline appears to have been void.&lt;/p&gt;  &lt;p&gt;The code made absolutely no sense until I started adopting the thought process behind it. And suddenly I was able to leverage the blind spot, foreseeing likely sore spots. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Socrates said that the hallmarks of an educated mind is to be able to entertain a notion without adopting it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-10323581471047130?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/10323581471047130/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2010/05/adopting-blind-spots.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/10323581471047130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/10323581471047130'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2010/05/adopting-blind-spots.html' title='Adopting the blind spots.'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-6975301807348040395</id><published>2010-05-03T21:41:00.001+02:00</published><updated>2010-05-03T21:41:15.816+02:00</updated><title type='text'>Software Craftsman Yule Calendar: 22nd of December</title><content type='html'>&lt;h5&gt;Todays word is “Pair programming”&lt;/h5&gt;  &lt;p&gt;Two persons, one keyboard, preferably with two duplicated screens. &lt;/p&gt;  &lt;p&gt;The keyboard passed back and forth.&lt;/p&gt;  &lt;p&gt;The pair does not have to have equal time on the keyboard. Just multiple people present and productive software engineering being performed, then it is pair programming.&lt;/p&gt;  &lt;p&gt;Passing the keyboard gives you the off-beat repertoire of focus change, picking up long term concerns. The brain gets its timeout without you grabbing a coffee, visiting the cubicle next to you, checking the mail or opening the web browser.&lt;/p&gt;  &lt;p&gt;Between them:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Blind zones and derailing are reduced to the least common denominator.&lt;/li&gt;    &lt;li&gt;Experience and resources is more than the sum of the two.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;em&gt;“Benefits of pair programming” &lt;/em&gt;is obvious to anyone who have given it a serious go. Rather, I’d rather be discussing &lt;em&gt;“the risks of solo programming”&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;Having to sell every story, you learn to communicate intent, to avoid tangents, to break out of your mentality in order to try the other perspective on for size.&lt;/p&gt;  &lt;p&gt;And it’s social. Software is more and more about people, processes, communication and interaction.&lt;/p&gt;  &lt;p&gt;Something that I think this post’s co-author, Anne, agrees with.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-6975301807348040395?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/6975301807348040395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2010/05/software-craftsman-yule-calendar-22nd.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/6975301807348040395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/6975301807348040395'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2010/05/software-craftsman-yule-calendar-22nd.html' title='Software Craftsman Yule Calendar: 22nd of December'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-2444363970880579567</id><published>2010-05-03T21:26:00.001+02:00</published><updated>2010-05-03T21:26:03.000+02:00</updated><title type='text'>Software Craftsman Yule Calender: 21st of December</title><content type='html'>&lt;h4&gt;Todays topic: “The Jury is in on TDD, there are no more excuses”&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;Test driven development is superior&lt;/li&gt;    &lt;li&gt;Test driven design is superior&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Patient and meticulous grinding at the base level. Driven by the precise execution of core disciplines, reverberating chants of&amp;#160; Red-Green-Refactor down along the aisles of craftsmen. &lt;/p&gt;  &lt;p&gt;TDD forces you to taste your own API. The customer comes first. No work is done until the desired task is purposely expressed in jargon meaningful to the client. &lt;/p&gt;  &lt;p&gt;You suddenly start to work with a flexible base material. You keep it and yourself flexible by you continuously flexing it.&lt;/p&gt;  &lt;p&gt;It is a coding learning experience where the feedback is immediate. Instead of a feedback cycle of hours to weeks, the slap on the wrist is immediate with the guilty misconceptions and the accomplicing mind set still at the scene of the crime. &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Of course it’s a new discipline.&lt;/li&gt;    &lt;li&gt;Of course you will be worse before you get better.&lt;/li&gt;    &lt;li&gt;Of course it takes a different mind set to be the bringer of change rather than hoping to not be awakening the beast.&lt;/li&gt;    &lt;li&gt;Of course you wont find the flow from the get-go.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;BUT:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;When you have the assurance of the green light and due confidence in its significance.&lt;/li&gt;    &lt;li&gt;When you play for keeps, knowing that people will have to get by your tests to break it.&lt;/li&gt;    &lt;li&gt;When you don’t have that uneasy feeling of having to go back to recheck something.&lt;/li&gt;    &lt;li&gt;When you know that you check in better code than you checked out.&lt;/li&gt;    &lt;li&gt;And you know it works.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;…. then it will start to feel unnatural, and unprofessional, to do anything else.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-2444363970880579567?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/2444363970880579567/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2010/05/software-craftsman-yule-calender-21st.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/2444363970880579567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/2444363970880579567'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2010/05/software-craftsman-yule-calender-21st.html' title='Software Craftsman Yule Calender: 21st of December'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-2826008700377611692</id><published>2010-05-02T11:14:00.000+02:00</published><updated>2010-05-02T11:14:17.435+02:00</updated><title type='text'>Software Craftsman Yule Calender: 18th of December</title><content type='html'>Todays topic "The only way to go fast is to go well."&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;(Before starting this little series on the software craftsmanship yule calender, I approached uncle Bob to see if he would pitch in. This was one of his contributions. He has several talks of this, much of which is used in this blog post.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The Paradox:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;How many of us have been considerably delayed by bad code?&lt;/li&gt;&lt;li&gt;How many of us have written bad code to save time?&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Consider a new project.&lt;/span&gt; &lt;br /&gt;Everybody is motivated. No legacy code to slow us down. We have the newest toys available. Productivity will be unprecedented blowing everybody away. &lt;br /&gt;And everything blasts off exactly as we thought. Magic sparkles between our fingertips and keyboard. The rest of the team is mesmerized. The project manager becomes bold. His faith in the programmers is restored. They have his back. He's got theirs.&lt;br /&gt;&lt;br /&gt;Then, gradually something changes. Estimated starts creeping from days to weeks. Certain things are constantly facing small setbacks both in terms of feasibility and estimates. Developers start checking in code that they hope have seen their last revision for a while. The components starts getting&amp;nbsp;personal with who is fit to be working on them without breaking stuff. Productivity suffers. Arbitrary flexible deadlines are postponed. Inflexible deadlines starts forcing stuff. &lt;br /&gt;&lt;br /&gt;The mistrust starts accummulating. The external behaviour of the developers starts to reminisce lazyness and sloppyness. After all, why else would the tasks that was complete in days now take weeks to be half done? If parts of the team has been replaced in the meantime, one might also assume that one is&amp;nbsp;left with a worse group of programmers. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;The problem is that the team has created a mess since day one.&lt;/span&gt;&lt;br /&gt;The deluded initial productivity was&amp;nbsp;a result of stealing from one of the most unappreciated and&amp;nbsp;obscruely measured&amp;nbsp;liabilities of code ownership: &lt;strong&gt;design debt&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Mess accumulates. Mess begets more mess.&lt;br /&gt;&lt;br /&gt;How do you deal with mess? You clean it up and you don't make it in the first place.&lt;br /&gt;Don't cheat. &lt;br /&gt;Don't assume you will come back later and clean it up.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;em&gt;When it comes to software, it never pays to rush.&lt;/em&gt;&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-2826008700377611692?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/2826008700377611692/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2010/05/software-craftsman-yule-calender-18th.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/2826008700377611692'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/2826008700377611692'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2010/05/software-craftsman-yule-calender-18th.html' title='Software Craftsman Yule Calender: 18th of December'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-3383379789252756933</id><published>2010-05-02T10:29:00.000+02:00</published><updated>2010-05-05T14:26:21.819+02:00</updated><title type='text'>Software Craftsman Yule Calender: 17th of December</title><content type='html'>&lt;span style="font-size: large"&gt;Todays word: &amp;quot;Waterfall&amp;quot;&lt;/span&gt;  &lt;br /&gt;  &lt;br /&gt;As stated before, it is important to not only recognize the faults of past paradigms, but also the fortés which gave rise to them in the first place.  &lt;br /&gt;  &lt;br /&gt;Such a beast is waterfall. It was originally contemplated because software is difficult to change. That is its premise. Code commiting design. You need good upfront design before committing to code. And you need good requirement specs before committing to the design preceding the code.  &lt;br /&gt;  &lt;br /&gt;All this changes when code no longer commits design. When software, when properly groomed, is painless to change. One of the primary motivations for waterfall does a 180 degree turn overnight.  &lt;br /&gt;  &lt;br /&gt;But still, waterfall may still be &lt;strong&gt;suitable&lt;/strong&gt; and sometimes even &lt;strong&gt;necessary.&lt;/strong&gt;  &lt;br /&gt;  &lt;br /&gt;&lt;strong&gt;Suitable:&lt;/strong&gt;  &lt;br /&gt;* Irreduceable designs. Some designs are based on a design vision that would be hard pressed to be achieved incrementally.  &lt;br /&gt;* When specs will not change. When there is no reason to assume that there will be any learning curve underway from start to finish. Neither with the developer or the stakeholder. If I can get all specs up front, I will gladly receive them. I just don't think this will be true more than once or twice in a life time.  &lt;br /&gt;  &lt;br /&gt;&lt;strong&gt;Necessary:&lt;/strong&gt;  &lt;br /&gt;* Even though well crafted code now responds well to change, there are still elements to solutions which do not. Such as business contracts, hardware and third party stuff.    &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-3383379789252756933?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/3383379789252756933/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2010/05/software-craftsman-yule-calender-17th.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/3383379789252756933'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/3383379789252756933'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2010/05/software-craftsman-yule-calender-17th.html' title='Software Craftsman Yule Calender: 17th of December'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-3496212247644689362</id><published>2010-05-02T09:59:00.002+02:00</published><updated>2010-05-02T11:15:34.535+02:00</updated><title type='text'>Software Craftsman Yule Calender: 16th of December:</title><content type='html'>&lt;span style="font-size: large;"&gt;Todays topic is "The gaffa tape programmer&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I strive to hone&amp;nbsp;my coding craft at any opportunity.&lt;br /&gt;I don't see them to be at odds with any other priorities in the coding domain. &lt;br /&gt;&lt;br /&gt;However, I do mash&amp;nbsp;stuff together sometimes, what is otherwise known as "Gaffa tape programming".&lt;br /&gt;&lt;br /&gt;I don't always strive for&amp;nbsp;complete 100% coverage. I strive to identify &lt;strong&gt;pockets/domains within my code&lt;/strong&gt; that warrant TDD. The more I can fit into those pockets, the better. The more I can compartmentalize the material, the better. &lt;br /&gt;&lt;br /&gt;But when the building blocks are in place so that I from the offset can&amp;nbsp;purposely&amp;nbsp;express a end task in&amp;nbsp;the suitable pseudo language that rise from&amp;nbsp;existing components, I "mash" them together.&lt;br /&gt;&lt;br /&gt;Yesterday, I noticed that the old comic book series "elf quest" was published on the net. &lt;a href="http://www.elfquest.com/"&gt;(www.elfquest.com&lt;/a&gt;) as it no longer was going to be printed. You could browse the comic book online by clicking "next", "next" etc. &lt;br /&gt;&lt;br /&gt;I made a web crawler to scrape it onto my hard drive. Three loops: one "do-while" and two "for-each". No tests.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-3496212247644689362?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/3496212247644689362/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2010/05/software-craftsmanship-yule-calender.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/3496212247644689362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/3496212247644689362'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2010/05/software-craftsmanship-yule-calender.html' title='Software Craftsman Yule Calender: 16th of December:'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-6485397945253207905</id><published>2010-04-16T08:18:00.003+02:00</published><updated>2010-04-16T08:24:10.895+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lean'/><title type='text'>Software Craftsman Yule Calender: 15th of December</title><content type='html'>&lt;span style="font-size:85%;"&gt; &lt;p&gt;&lt;span style="font-size:180%;"&gt;Todays word is "Lean"&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;We're paid to produce and maintain &lt;em&gt;code&lt;/em&gt;, right? So, by producing &lt;em&gt;code&lt;/em&gt; we are &lt;strong&gt;productive&lt;/strong&gt;. And by &lt;em&gt;maintaining the same code&lt;/em&gt;, we are &lt;strong&gt;even more productive&lt;/strong&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;Well, not really. Without manifesting any business value, this is at best a zero sum game.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;Code has cost of ownership.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;Code made on assumptions is a business risk. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;Code of poor quality is a liability.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;Code or poor quality that must be maintained is a design debt.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;Ill conceived concepts confuse, distract and disrupt within an organization.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;As coders, we need for our managers to understand the nature of the beast that is code so that they can make informed decision. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;Developers often complain about management, but have you ever considered that they may just be on the wrong page of their finance text book? That such-and-such wasn't really an assett aquisition scenario, but rather a risk management scenario.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;Lean is about identifying business value to facilitate focused effort. Lean is about amplifying learning, defer decisions, delivering early value and respond with minimal overhead.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;　&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Define and identify values.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Define, indentify and innovate value streams.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Promote value flow.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;All activity should have an active stakeholder downstream. Pull based.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Refine the process. &lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-6485397945253207905?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/6485397945253207905/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2010/04/software-craftsman-yule-calender-15th.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/6485397945253207905'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/6485397945253207905'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2010/04/software-craftsman-yule-calender-15th.html' title='Software Craftsman Yule Calender: 15th of December'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-5707886832269068291</id><published>2010-02-26T09:24:00.002+01:00</published><updated>2010-02-26T10:13:48.561+01:00</updated><title type='text'>Software Craftsman Yule Calender: 11th of December</title><content type='html'>Todays word is &lt;strong&gt;"Agile"&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;Let's start by saying that if you have a &lt;strong&gt;cross&lt;/strong&gt; and &lt;strong&gt;rigid&lt;/strong&gt; definition about &lt;em&gt;how to be agile&lt;/em&gt;, then that is a red flag already there. Some corner stones exist, though.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Iterative&lt;/strong&gt;&lt;br /&gt;Short cycles. Complete cycles. Reflecting the entirety of your business. From concept to deliverable. From "not done" to "done" or "not done and here's why..." . Not "half done" or "done, but...".&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Incremental&lt;/strong&gt;&lt;br /&gt;The business assets shall have a net increase. Liabilities shall not exceed the investment of the ongoing cycle.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Cross functional teams&lt;/strong&gt;&lt;br /&gt;The team shall have the competence, ability and means to produce. The need for predicted external involvement shall not be of a nature or quantity than what can be assigned the SCRUM master. This is mostly to remove impediments, not engage externals with detailist assignments.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Self managing teams&lt;/strong&gt;&lt;br /&gt;Specialized assets within the team should naturally gravitate towards the appropriate tasks that requires them, but not at the expense of the team members assuming a collective ownership to the entirety of the end product.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-5707886832269068291?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/5707886832269068291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2010/02/software-craftsman-yule-calender-11th.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/5707886832269068291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/5707886832269068291'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2010/02/software-craftsman-yule-calender-11th.html' title='Software Craftsman Yule Calender: 11th of December'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-928789406755347537</id><published>2009-12-11T08:03:00.002+01:00</published><updated>2009-12-11T08:04:47.041+01:00</updated><title type='text'>Software Craftsman Yule Calender: 10th of December</title><content type='html'>&lt;span style="font-size:130%;"&gt;"Perfection is achieved, not when there is &lt;strong&gt;nothing left to add&lt;/strong&gt;, but when there is &lt;strong&gt;nothing left to remove&lt;/strong&gt;"&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-928789406755347537?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/928789406755347537/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-10th.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/928789406755347537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/928789406755347537'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-10th.html' title='Software Craftsman Yule Calender: 10th of December'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-1296506499849738448</id><published>2009-12-10T11:24:00.002+01:00</published><updated>2009-12-10T12:01:38.751+01:00</updated><title type='text'>Software Craftsman Yule Calender: 9th of December</title><content type='html'>&lt;span style="font-size:180%;"&gt;"Enhance, do not replace"&lt;/span&gt;&lt;br /&gt;part 4&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Previously&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;"Following a plan".&lt;br /&gt;&lt;/span&gt;"Not only following a plan, but responding to change"&lt;br /&gt;&lt;span style="font-size:130%;"&gt;"Not only responding to change, but &lt;em&gt;steadily adding value&lt;/em&gt;".&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;"Contract negotiations"&lt;br /&gt;&lt;/span&gt;"Not only contract negotiations, but customer collaboration"&lt;br /&gt;&lt;span style="font-size:130%;"&gt;"Not only customer collaboration, but &lt;em&gt;productive partnership&lt;/em&gt;"&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;"Processes and tools"&lt;/span&gt;&lt;br /&gt;"Not only processes and tools, but individuals and interactions"&lt;br /&gt;&lt;span style="font-size:130%;"&gt;"Not only individuals and interactions, but a &lt;em&gt;community of professionals&lt;/em&gt;" &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Today&lt;/strong&gt;&lt;br /&gt;Being a bit code centric today. During our pursuit of the upper, we find the lower to be indispensible.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;"Comprehensive Documentation"&lt;br /&gt;&lt;/span&gt;"&lt;em&gt;Working software&lt;/em&gt; over comprehensive documentation"&lt;br /&gt;&lt;span style="font-size:130%;"&gt;"&lt;em&gt;Well crafted software&lt;/em&gt; over working software"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Would you have bought something expensive if nothing told you what it was or what it did?&lt;br /&gt;Would you have bought a car that the salesman had trouble starting? And would it then be of any help that you have a thorough understanding of what the car [i]should[/i] have done?&lt;br /&gt;Would you have bought the car if you opened the hood and was looking at a complete mess (also in the eye of a mechanic). The fact that the car actually [i]starts[/i] will again seem insufficient.&lt;br /&gt;&lt;br /&gt;Our profession is first and foremost to produce actively used software that creates value for our business by creating value for its customers. In and of itself, code is not worth anything.&lt;br /&gt;But existing codebase is also an assett to meet future solutions and challenges. For that, we need maintainable and clean code. Code is read more often than it is written.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-1296506499849738448?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/1296506499849738448/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-9th-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/1296506499849738448'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/1296506499849738448'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-9th-of.html' title='Software Craftsman Yule Calender: 9th of December'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-8358481251565186295</id><published>2009-12-08T11:58:00.004+01:00</published><updated>2009-12-08T12:17:06.365+01:00</updated><title type='text'>Software Craftsman Yule Calender: 8th of December</title><content type='html'>&lt;span style="font-size:180%;"&gt;"Enhance, do not replace"&lt;/span&gt;&lt;br /&gt;part 3&lt;br /&gt;&lt;br /&gt;Building on the existing theme, another gem ensues from the Agile and Craftsman manifesto&lt;br /&gt;While still recognizing the former, we value the latter more.&lt;br /&gt;&lt;br /&gt;Thus far:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;"Following a plan".&lt;/span&gt;&lt;br /&gt;"Not only following a plan, but &lt;em&gt;responding to change&lt;/em&gt;"&lt;br /&gt;&lt;span style="font-size:130%;"&gt;"Not only responding to change, but &lt;em&gt;steadily adding value&lt;/em&gt;".&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;"Contract negotiations"&lt;br /&gt;&lt;/span&gt;"Not only contract negotiations, but &lt;em&gt;customer collaboration&lt;/em&gt;"&lt;br /&gt;&lt;span style="font-size:130%;"&gt;"Not only customer collaboration, but &lt;em&gt;productive partnerships&lt;/em&gt;"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Today:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;strong&gt;"Processes and tools"&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;Processes are important. They provide map and compass in a undefined terrain. You can contribute to a piece of the puzzle without an elaborate concern to every other part. You can interface others in a formal process and know both what is expected from you and what is expected by others.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;"Not only processes and tools, but &lt;em&gt;individuals and interactions&lt;/em&gt;"&lt;/strong&gt;&lt;br /&gt;Processes are means to an end.&lt;br /&gt;Initially, a process surrounding a discipline is based on the experience of Yesterdays efforts and challenges. When you start taking ownership of the problem domain, you'll be able to relate to the customer base more directly and able to elicit knowledge and leverage opportunities that might not be available through the process. You'll become approachable from the customer POV.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;"Not only individuals and interactions, but a &lt;em&gt;community of professionals&lt;/em&gt;"&lt;/strong&gt; &lt;/span&gt;&lt;br /&gt;Eventually, you'll see that process and interaction are not opposites. You will need to define the process alongside the product as an integral part of it. It needs to evolve with the product. The optimum process support a community where actual knowledge, insight and competence within the community are naturally appropriately applied. A community that takes a solidary ownership to the totality of the end product.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-8358481251565186295?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/8358481251565186295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-8th-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/8358481251565186295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/8358481251565186295'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-8th-of.html' title='Software Craftsman Yule Calender: 8th of December'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-2075730611714392999</id><published>2009-12-07T09:07:00.002+01:00</published><updated>2010-11-16T08:55:26.058+01:00</updated><title type='text'>Software Craftsman Yule Calender: 7th of December</title><content type='html'>&lt;p&gt;&lt;span style="font-size: 180%"&gt;&amp;quot;The decision making triangle&amp;quot;&lt;/span&gt;    &lt;br /&gt;This one is from Extreme Programming (XP).    &lt;br /&gt;    &lt;br /&gt;How is a technical decision made? What forces are we trying to unify in all our procedures, phase reports, business analysis, product reviews? How is a feature request spawned and what, when presented, argues for it/against it?    &lt;br /&gt;    &lt;br /&gt;The decision making triangle has three components.    &lt;br /&gt;    &lt;br /&gt;&lt;strong&gt;The technician&lt;/strong&gt;, who provides estimates, cost, risk and quality impact.    &lt;br /&gt;&lt;strong&gt;The customer&lt;/strong&gt;, who translates a fluid and chaotic business domain into a concrete set of durable features.    &lt;br /&gt;&lt;strong&gt;The economist&lt;/strong&gt;, who manages the entire backlog relating cost effective activities to return of investement, company strategy and resources.    &lt;br /&gt;    &lt;br /&gt;This does not always have to be three separate individuals, and could possibly more accurately be referred to as roles/hats/influences.    &lt;br /&gt;If there is a crucial support issue, there is obviously no need for an explicit &amp;quot;customer&amp;quot; and &amp;quot;economist&amp;quot; role in order to respond to the matter.    &lt;br /&gt;Also, pair programming has a tendency to encourage being explicit and a more elaborate discourse.    &lt;br /&gt;Alas, these concerns should often be explicitly adressed. Not only for the quarterly review, but as an integral part of the iterative and incremental process.    &lt;br /&gt;    &lt;br /&gt;As I imagine most of my imaginary readers to be technicians, we may insist that all those estimates are unreasonable. Often this may be the case, but to bring the best estimate or even the knowledge of uncertainty into the mix, is the responsibility of the technician.    &lt;br /&gt;    &lt;br /&gt;This triangle is the &lt;em&gt;core&lt;/em&gt; of the decision process, &lt;em&gt;not the entirety&lt;/em&gt; of the team. All of the three roles may have a team of individuals behind them to carry out the respective responsibilities.    &lt;br /&gt;    &lt;br /&gt;The thing I want to focus on in this post is the value of a good customer. In this context, it is not the customer with the most money or willingness to spend. I am not necessarily talking about a person outside your own company. &lt;/p&gt;  &lt;p&gt;Above all, the customer is &lt;strong&gt;not&lt;/strong&gt; a developer who has received a four inch thick requirements document in his lap.&lt;/p&gt;  &lt;p&gt;The customer is whoever who possess the underestimated, yet invaluable, quality of translating a business problem into addressable concerns. A customer is the one who identifies the underlying durable aspects that will form a sustainable business asset.&lt;/p&gt;  &lt;p&gt;The good customer is he whose backlog is based on, and traceable back to, true business concerns.   &lt;br /&gt;An organization with good customers have a good knowledge of their value flow. They can allow their model to be pull based. There are less assumptions and less liability in their efforts.&lt;/p&gt;  &lt;p&gt;The ideal customer is he who will need the least amount of code to make the most amount of money. The ideal customer is he who lives and breathes the problem with a passion, but has a minimum of preconceptions on how it is to be solved. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-2075730611714392999?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/2075730611714392999/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-7th-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/2075730611714392999'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/2075730611714392999'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-7th-of.html' title='Software Craftsman Yule Calender: 7th of December'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-8889218573984688028</id><published>2009-12-04T13:19:00.003+01:00</published><updated>2009-12-04T13:46:36.266+01:00</updated><title type='text'>Software Craftsman Yule Calender: 4th of December</title><content type='html'>&lt;span style="font-size:180%;"&gt;"Enhance, do not replace"&lt;/span&gt;&lt;br /&gt;part 2.&lt;br /&gt;&lt;br /&gt;Another concrete theme on which one gradually develop to challenge established mentality, procedures and practices. And also challenge your own position.&lt;br /&gt;&lt;br /&gt;While still recognizing the former, we value the latter more.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Excerpt from Yesterdays calender&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;"Following a plan".&lt;/span&gt;&lt;br /&gt;"Not only following a plan, but responding to change"&lt;br /&gt;&lt;span style="font-size:130%;"&gt;"Not only responding to change, but steadily adding value".&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;And for today&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;"Contract negotiations"&lt;br /&gt;&lt;/span&gt;"Not only contract negotiations, but customer collaboration"&lt;br /&gt;&lt;span style="font-size:130%;"&gt;"Not only customer collaboration, but productive partnership"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;More on the value of a good customer tomorrow, which will be "The decision triangle".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-8889218573984688028?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/8889218573984688028/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-4th-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/8889218573984688028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/8889218573984688028'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-4th-of.html' title='Software Craftsman Yule Calender: 4th of December'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-7951224739282089358</id><published>2009-12-03T12:17:00.003+01:00</published><updated>2009-12-04T10:45:36.820+01:00</updated><title type='text'>Software Craftsman Yule Calender: 3rd of December</title><content type='html'>&lt;span style="font-size:180%;"&gt;"Enhance, do not replace"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;&lt;/span&gt;&lt;br /&gt;In these agile times, there are a lot of concepts that is beneficial to absorb.&lt;br /&gt;But it is not necessary to do so at the expense of past knowledge.&lt;br /&gt;Concepts may appear contradictive at face value, but this only means that they can only be successfully combined within a seasoned decision maker.&lt;br /&gt;&lt;br /&gt;It is important to not only know why something in the past was &lt;em&gt;bad&lt;/em&gt;, but also why it was &lt;em&gt;good&lt;/em&gt;.&lt;br /&gt;Not only knowing a rule, but knowing when to challenge the rule.&lt;br /&gt;To identify our craft is an ongoing process with driving forces in context of existing paradigms. Don't just see the bottom line without its context.&lt;br /&gt;See the train of thought, learn from history and aim to enhance on the collective knowledge that is the craft that you are a part of.&lt;br /&gt;Don't just swap one doctrine with the next.&lt;br /&gt;&lt;br /&gt;Identify with each of the following, and allow the natural progression to the next.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;"Following a plan"&lt;/strong&gt;&lt;/em&gt;&lt;br /&gt;What can we do if we can't follow a plan? How can then others rely on us?&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;"Not only following a plan, but also &lt;em&gt;responding to change&lt;/em&gt;"&lt;/strong&gt;&lt;br /&gt;We relate to a dynamic world. Specifications are sometimes truth and sometimes assumptions.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;"Not only responding to change, but also &lt;em&gt;steadily adding value&lt;/em&gt;".&lt;/strong&gt;&lt;br /&gt;Why assume that your present knowledge wont change in the future or that it hasn't overlooked or de-emhpasized something in the past?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-7951224739282089358?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/7951224739282089358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-3rd-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/7951224739282089358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/7951224739282089358'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-3rd-of.html' title='Software Craftsman Yule Calender: 3rd of December'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-7102592986251519099</id><published>2009-12-02T12:43:00.002+01:00</published><updated>2009-12-02T12:50:34.458+01:00</updated><title type='text'>Software Craftsman Yule Calender: 2nd of December</title><content type='html'>&lt;span style="font-size:180%;"&gt;"Do no harm"&lt;/span&gt;&lt;br /&gt;(The hypocratic oath revisited)&lt;br /&gt;&lt;br /&gt;The Boy Scout rule is to leave the camp site better than you found it. This goes for coding as well as camping.&lt;br /&gt;&lt;br /&gt;Simply check in better code than you checked out. Not much, necessarily, just a little.&lt;br /&gt;Don't create a mess.&lt;br /&gt;Never buy into the self delusion that you can come back and clean it up at a later time.&lt;br /&gt;Don't let the code rot.&lt;br /&gt;&lt;br /&gt;All other things in our posession:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The Architecture document.&lt;/li&gt;&lt;li&gt;The Design Document.&lt;/li&gt;&lt;li&gt;The Requirement specification.&lt;/li&gt;&lt;li&gt;The Test description.&lt;/li&gt;&lt;li&gt;The user guide.&lt;/li&gt;&lt;/ul&gt;All these things are mere derivatives of our true core; the code.&lt;br /&gt;&lt;br /&gt;Where the code is a mess, everything is a mess.&lt;br /&gt;Where the code is rotten, everything is rotten.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-7102592986251519099?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/7102592986251519099/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-2nd-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/7102592986251519099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/7102592986251519099'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-2nd-of.html' title='Software Craftsman Yule Calender: 2nd of December'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-3441342154548506157</id><published>2009-12-02T11:09:00.002+01:00</published><updated>2009-12-02T12:43:15.575+01:00</updated><title type='text'>Software Craftsman Yule Calender: 1st of December</title><content type='html'>&lt;span style="font-size:180%;"&gt;"Do not be blocked".&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is so fundamental that I considered a "thou shalt not...."&lt;br /&gt;&lt;br /&gt;Don't wait for specifications.&lt;br /&gt;Don't wait for clarifications.&lt;br /&gt;Go with what you have. Influence the decision with what you know and what you can do.&lt;br /&gt;Make functional samples, sketches, proto types. Duct tape is allowed.&lt;br /&gt;Seize ownership. Become integral.&lt;br /&gt;Learn the problem by spending time in the problem domain.&lt;br /&gt;It is allowed to throw away software. Even newly connected neurons is a benefit.&lt;br /&gt;Something tangible and concrete produces tangible and concrete feedback.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-3441342154548506157?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/3441342154548506157/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-1st-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/3441342154548506157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/3441342154548506157'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/12/software-craftsman-yule-calender-1st-of.html' title='Software Craftsman Yule Calender: 1st of December'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-4172855690404118567</id><published>2009-12-02T11:03:00.004+01:00</published><updated>2009-12-02T11:09:07.552+01:00</updated><title type='text'>Introducing: The Software Craftsman Yule Calender</title><content type='html'>In this series, one for each workday up till Christmas, I'll explore an isolated piece of what I consider to be important factors of the professional software developer.&lt;br /&gt;&lt;br /&gt;There may be repeptitions from earlier posts, but this time its succinct form will hopefully enhance its take-away value.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-4172855690404118567?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/4172855690404118567/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/12/introducing-software-craftsman-yule.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/4172855690404118567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/4172855690404118567'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/12/introducing-software-craftsman-yule.html' title='Introducing: The Software Craftsman Yule Calender'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-172521398762955903</id><published>2009-10-20T08:23:00.004+02:00</published><updated>2009-10-21T12:30:30.715+02:00</updated><title type='text'>The duct tape programmer and the patterns geek.</title><content type='html'>Is there a middle road.&lt;br /&gt;&lt;br /&gt;I just finished the book "Design Patterns In Action" and I am starting the "Refactoring to Patterns".&lt;br /&gt;&lt;br /&gt;Then I find the following post by Joel Spoolsky:&lt;br /&gt;&lt;a href="http://www.joelonsoftware.com/items/2009/09/23.html"&gt;http://www.joelonsoftware.com/items/2009/09/23.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A danger of our undefined industry is addicting yourself to bits and pieces underway. You get pet peeves that are secondary to the actual business that your profession is a part of.&lt;br /&gt;&lt;br /&gt;I am completely sold on TDD, but there certainly is a ladder for its business value with distinct stages.&lt;br /&gt;&lt;br /&gt;If you don't have coverage or reliability on your tests, you can't refactor with a vengeance.&lt;br /&gt;If you don't do tests first, you have significantly less chance of producing decoupled code.&lt;br /&gt;If you can't refactor, you will still produce a mess.&lt;br /&gt;If you can't refactor into patterns, you wont see the tests driving the design.&lt;br /&gt;&lt;br /&gt;But, at the end of all this and you leverage TDD to its fullest, have you become overacademic along the way?&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Does TDD, in all its glory, scale &lt;em&gt;downwards&lt;/em&gt;?&lt;/strong&gt;&lt;br /&gt;Both with respect to project size as well as timeframe.&lt;br /&gt;&lt;br /&gt;Are there scenarios where your excellent TDD skills scale so bad that they become an obstacle to getting things done and shipping it?&lt;br /&gt;&lt;br /&gt;Robert Martin says "Do not go fast, go well".&lt;br /&gt;&lt;br /&gt;My perspective is that IDEs that promote a test first discipline and powerful add-ons like Resharper or Coderush makes this discipline go faster and sturdier. Also, future architectures seem to promote logic and presentation in a more clear cut manner.&lt;br /&gt;&lt;br /&gt;As I've stated in an earlier blog post, the jury is out and TDD won, but I appreciate the duct tape programmer perspective. Although I suspect he is a dying breed within the mainstream where people have to maintain code bases and incurred technical debt carry interests.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-172521398762955903?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/172521398762955903/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/10/duct-tape-programmer-and-patterns-geek.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/172521398762955903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/172521398762955903'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/10/duct-tape-programmer-and-patterns-geek.html' title='The duct tape programmer and the patterns geek.'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-6972395225801408712</id><published>2009-10-08T11:45:00.002+02:00</published><updated>2009-10-08T12:08:48.210+02:00</updated><title type='text'>When do you accept a Requirement spec.</title><content type='html'>A prime directive whenever you decide to leap to a new technology/methodology/discipline is to make sure that you have added value to your repertoire. You should GROW, not CHANGE. You should trash what does not work, but you should not trash apples for oranges.&lt;br /&gt;&lt;br /&gt;Like Robert Martin says: "You should not only absorb why waterfall is bad, you should also know why it was good (at times)".&lt;br /&gt;&lt;br /&gt;I have started to appreciate certain indicators when it comes to whenever a requirement spec is justified.&lt;br /&gt;&lt;em&gt;Notice the phrasing above; I put the onus of waterfall applicability on the person wishing to present me with a requirement spec. The burden of proof is on the person professing waterfall, but it defaults to Agile.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In his book "Clean code", Uncle Bob quotes several nestors within our field as to what their opinion is on clean code. Ward Cunningham comes with one of his characteristically apparently annoyingly redundant comments:"When the code is pretty much what you expect".&lt;br /&gt;At first glance this is seems like a cop-out of answering the real question, but upon closer reflection, there are subtle brilliances within this very simple answer. Reading clean code should not make you pause, there should be little "flavours", nothing should feel forced, there should be no need to mentally context switch within a single class, the name of the class and class members should give you a reasonably good opinion as to what lies behind it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;For all my thoughts on the little nuggets of factors that combine into a good requirement specification, it basically boil down to the same:&lt;br /&gt;&lt;strong&gt;When writing and reading it is all but a formality, then it is a justified specification.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The fabled animal "irreducably complex infrastructure" may still really exist, but you should still have a go at it with real tools before calling in the medium.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-6972395225801408712?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/6972395225801408712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/10/when-do-you-accept-requirement-spec.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/6972395225801408712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/6972395225801408712'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/10/when-do-you-accept-requirement-spec.html' title='When do you accept a Requirement spec.'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-583829308028693689</id><published>2009-09-16T12:02:00.006+02:00</published><updated>2009-09-20T21:27:04.903+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lean'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>The decision making triangle</title><content type='html'>As an avid agilist, I maintain that the manager should do little more than putting the following three powers together.&lt;br /&gt;* The techie.&lt;br /&gt;* The funding.&lt;br /&gt;* The customer.&lt;br /&gt;&lt;br /&gt;These are the three roles to any "go"/"no-go" decision making on wether or not a particular technical endeavour is worthwhile.&lt;br /&gt;&lt;br /&gt;The "funding" is simply someone who is able to decide cost against benefit. The financial backbone for a particular push within your portfolio is often quite obfuscated in a large organization. When you no longer produce bang for the buck, you stop.&lt;br /&gt;&lt;br /&gt;The "customer" is simply the someone who can make a decision on a satsifactory solution to any given marketable feature. The customer represents the totality of the demands. In some cases, being an internal customer that is able to map external requirements to internal technical achievable backlog items is a true assett.&lt;br /&gt;A good customer is hard to come by.&lt;br /&gt;&lt;br /&gt;Together, the two can decide on where the efforts can give the most value.&lt;br /&gt;&lt;br /&gt;The techie translates solution proposals into estimates.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The main discipline between these three is to identify the MMF's (minimum marketable features) that will individually add to the value of the product. It is sometimes hard for a customer to see that his problem is not an irreduceable all-or-nothing deal.&lt;br /&gt;Again, consider the value of a good customer.&lt;br /&gt;&lt;br /&gt;The customer is rarely an external person. When deciding on these issues, there should be as little vested interests (and politics) as possible. An external customer is likely to play up his requirements, is unlikely to be willing to vouch satisfaction at the drawing board and various scopes are subject to contract negotiations.&lt;br /&gt;&lt;br /&gt;On small projects, one person can have all these hats.&lt;br /&gt;On large projects, the "customer" can have a full time team of three people behind him doing nothing but mapping classification requirements to the proposed features.&lt;br /&gt;&lt;br /&gt;Since the development departments are mostly techies, the two other roles are likely to suffer. Especially the customer part. We have many products where it is unclear who demanded what, and in what manner we fulfill certain requirements.&lt;br /&gt;&lt;br /&gt;Every agilist should appreciate a customer who can think on his/her feet.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-583829308028693689?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/583829308028693689/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/09/decision-making-triangle.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/583829308028693689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/583829308028693689'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/09/decision-making-triangle.html' title='The decision making triangle'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-3707074384328199800</id><published>2009-09-04T12:28:00.009+02:00</published><updated>2009-09-04T21:33:05.965+02:00</updated><title type='text'>TDD nails it</title><content type='html'>&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Imagine yourself TDD'ing a thermostat controlling a heater. Your first unit test is to set the temperatures in the fake thermometer as well as the Thermostat object, which is the unit under test, and to verify that it actually starts the heater.&lt;br /&gt;&lt;br /&gt;Now, in the production code, a TDD beginner will find it tempting to check the temperature and then start the heater. However, the correct thing is to not check the thermometer, but just start the heater regardless of input. This is because this is all that is required to pass the first test. You don't need to check the thermometer before you have a test that would fail if you didn't check the thermometer.&lt;br /&gt;&lt;br /&gt;If the TDD beginner followed through with his gut feeling and implemented the check right away and then proceeded to the next feature he would be able to remove the thermometer check, introducing a bug in his software, &lt;em&gt;without any tests failing&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Thus removing the premise to safely refactor and changing without breaking.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;TDD nails it.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Now, if you were using hammer and nails to fix a piece of wood (say, a board) in place, a novice could be equally "tempted" to hold the board in place and then just hit a nail in its center before moving on.&lt;br /&gt;&lt;br /&gt;This would look all well and good until the forces started acting upon it, in which case the board would quite likely shift out of place.&lt;br /&gt;&lt;br /&gt;Now, let us pretend that a piece of functionality is a board and that unit tests are nails.&lt;br /&gt;&lt;br /&gt;By using just a single nail, both the &lt;u&gt;piece of functionality&lt;/u&gt; and the &lt;u&gt;board&lt;/u&gt; would seemingly be held in place by nails, but in reality the real upkeeper for both is &lt;em&gt;friction&lt;/em&gt;. Friction on wood surface and friction in the code base. Without neither being be nailed in place.&lt;br /&gt;&lt;br /&gt;When I implement a piece of functionality &lt;strong&gt;I certainly hope to having &lt;em&gt;"nailed it"!&lt;/em&gt;&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-3707074384328199800?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/3707074384328199800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/09/tdd-nails-it.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/3707074384328199800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/3707074384328199800'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/09/tdd-nails-it.html' title='TDD nails it'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-3644280177350232186</id><published>2009-09-03T07:33:00.008+02:00</published><updated>2009-10-16T11:19:18.464+02:00</updated><title type='text'>"As simply as possible"</title><content type='html'>Yesterday, I held an internal TDD Introduction workshop for about 10 developers.&lt;br /&gt;&lt;br /&gt;I had no slides, just winging it using VS2008 on a projector. And using the whiteboard.&lt;br /&gt;&lt;br /&gt;The workshop was in two parts.&lt;br /&gt;&lt;strong&gt;1. The common calculator&lt;/strong&gt; that eventually become string based requiring a tokenizer. This is to push the Red-Green-Refactor envelope. I know : pretty boring, but you want to put the emphasis on the tight cycle of TDD.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;2. A case with external dependencies.&lt;br /&gt;&lt;/strong&gt;The specific use case was a HVAC controller. It starts off as a simple thermostat to control a cooling fan, but evolves to a full fledged HVAC controller.&lt;br /&gt;People discover that the API of a thermostat is principally different than the HVAC controller. For example, "Desired temperature" can be a single number in a thermostat, whereas the HVAC controller needs a desired temperature with an upper and lower limit. The pattern geeks may argue that the HVAC controller is actually two thermostats working in opposites (one for "cold", one for "heat"), which certainly makes for some interesting programming.&lt;br /&gt;&lt;br /&gt;The three immediate takeaway benefits are:&lt;br /&gt;* TDD forces you to think about your interface. And working in pairs produces some fruitful debate at a very early stage. Paradoxically, people suddenly find themselves unable to express their use cases against their own API (and then they start blaming &lt;em&gt;me&lt;/em&gt;).&lt;br /&gt;&lt;br /&gt;* They discover that there is a "secret" dependency on time. One dependency driving requirement is that the airfan should run for two minutes after the furnace has been switched off. Hopefully they'll muck around with DateTime static helpers before realizing that time must be controlled from the tests.&lt;br /&gt;&lt;br /&gt;* The manual mocks versus isolation frameworks (Moq). The initial test cases make for slim manual fakes, but the Moq syntax is usually heartly received.&lt;br /&gt;&lt;br /&gt;We only had half a day, which went by in the blink of an eye, but I think that we ran into many of the typical subjects.&lt;br /&gt;There certainly is stuff that is hard to get even in the simple world of TDD. We met some speed bumps when we crossed the following:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Problem 1: Lambda expressions.&lt;/strong&gt;&lt;br /&gt;I have opted for our group to go for Moq as the isolation framework of choice. This is because of the crisp syntax and a lot of sense and intellisense. The most noted objection against Moq is that it makes heavy use of Lambda expressions and therefore is only available in the .NET 3.5. However, that is no concern for us.&lt;br /&gt;We had some MFC programmers in the workshop. Even seasoned and capable programmers are visibly in pain when they try to wrap their heads around Lambda expressions. I wanted to showcase the evolution of bamed method -&gt; Anonymous method -&gt; Lambda, but I messed up the syntax for anonymous method and we were too pressed for time to google it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Problem 2: "As simply as possible".&lt;/strong&gt;&lt;br /&gt;However simple as it may sound, this rule is all but simple if you start going down the road creating &lt;em&gt;the wrong kind of simplicity&lt;/em&gt;. The TDD dogmatic anecdote is that you shall make a test pass in a manner that is as simple as possible.&lt;br /&gt;This is to make sure that the unit tests enforce the functionality of the production code and that the tests truly drive the development process.&lt;br /&gt;&lt;br /&gt;Just a week ago, I was attending TDD Masters class by Roy Osherove. I think that I grocked the concept of simplicity on the second day.&lt;br /&gt;&lt;br /&gt;In my dependency use case, the first MMF is to make the controller start the FAN if the THERMOMETER shows a higher temperature than the desired temperature which you have set against the API of the HVAC controller instance.&lt;br /&gt;Now, what exactly does simplicity mean? What should be the first test?&lt;br /&gt;&lt;br /&gt;Does it mean to not interact with the mocked FAN?&lt;br /&gt;Does it mean to not interact with the mocked THERMOMETER?&lt;br /&gt;Why would it have dependencies at all? Can't you just put a temperature in and the ask it if wants to start the fan?&lt;br /&gt;&lt;br /&gt;This started to take the form of a dug-in debate in the class, which I had to cut off.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;I think that there is an important distinction to be made here.&lt;/strong&gt; &lt;em&gt;You do not program unit tests that you do not intend to make obsolete at a later time. Although the unit tests only run a concrete scenario testing a narrow case, they should still execute and pass against the final product three months from now. You still need to express the complete scenario against what you, at the time of writing, expect to become the final library API for that use case.&lt;/em&gt;&lt;br /&gt;&lt;em&gt;If you program against getters and setters and the getters only return true, you are not producing value as you plan to both throw away both the unit test and the production code that made it pass. You are also bestowing a legacy API on a brand new component. &lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;I solve the problem as follows in my very first unit test: I create a mock fan and a mock thermometer (with a temperature), pass them both to the controller as constructor arguments and expect the fan to have been attempted to turned on.&lt;br /&gt;This may seem like an advanced use case, but I think it is as simple as it can be.&lt;br /&gt;&lt;br /&gt;People in the TDD domain also argue that you should start with constructor checks. At this point, I am not actually sure if it makes sense to be able to new up an controller without arguments, so I am actually forgoing that for the moment. If a later use case starts by newing up an empty controller, I will create a specific "IsNotNull" test.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Now, here is the &lt;strong&gt;correct&lt;/strong&gt; meaning of "as simple as possible":&lt;/u&gt; When I confirm that the test fails, and I go into &lt;em&gt;production code,&lt;/em&gt; I totally disregard the thermometer and I merely switch the fan on. I do not even store the thermometer reference which was passed in the constructor. This leaves people speechless. The thermometer is available, why not check it? You &lt;strong&gt;know&lt;/strong&gt; that you will have to check the thermometer before starting the fan in the final product.....?&lt;br /&gt;The key here is to recognize the fact that I would then be able to remove the check without breaking any tests. I would be able to introduce a bug in my code without causing any tests to fail. And if that happens, what good are they? How can I safely refactor the code if the green light does not mean anything?&lt;br /&gt;Everybody agrees that I need at least two test cases to "nail" the functionality in place. And I need the if. And when people realize that, they also realize that I am not doing any extra work, I am just doing it in a different order. And the order has additional benefits because I do not have the overhead of writing unit tests after having the complete functionality in the production code.&lt;br /&gt;&lt;br /&gt;If you write unit tests after the fact, you need to change the production code in order to see them fail. It is important that you know that the unit tests you write actually &lt;em&gt;can&lt;/em&gt; and &lt;em&gt;will&lt;/em&gt; fail.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;To sum it up: "As simply as possible" does not mean "as stupidly as possible". You still play for keeps. The production code is &lt;strong&gt;"work in progress"&lt;/strong&gt;, but the unit test is supposed to be &lt;strong&gt;done&lt;/strong&gt;, you don't plan on revisiting it. After all, it would be tedious process with a growing amount of unit tests if you planned on rewriting the API they all consume so that they no longer describe a valid scenario.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-3644280177350232186?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/3644280177350232186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/09/as-simply-as-possible.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/3644280177350232186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/3644280177350232186'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/09/as-simply-as-possible.html' title='&quot;As simply as possible&quot;'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-4079507129719849886</id><published>2009-09-02T10:22:00.002+02:00</published><updated>2009-09-02T10:45:11.817+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rants'/><title type='text'>Aftenpostens artikkel om nordmennene i Kongo</title><content type='html'>(This entry is in Norwegian as it comments on an ongoing debate in Norway.)&lt;br /&gt;&lt;br /&gt;Jeg ble overrasket over dagens oppslag i Aftenposten om Tjostolv Moland og Joshua French.&lt;br /&gt;&lt;br /&gt;Her tar en velrenommert norsk avis og supplerer "anonyme kilder" til ett åpenbart korrupt lokalt aktorat under pågående rettergang med henrettelse som mulig utfall.&lt;br /&gt;&lt;br /&gt;Dette blir da kilder som blir benyttet i rettsprosessen som de tiltaltes forsvarer ikke har noen anledning til utfordre eller kryssutspørre.&lt;br /&gt;&lt;br /&gt;Aftenposten forer en korrupt prosess med beleilig ikke-etterprøvbare data. Og således tar en aktiv sentral del i en prosess som ikke er Norge verdig.&lt;br /&gt;&lt;br /&gt;For meg later dette til å være toppen av journalistisk og redaksjonell uansvarlighet. Med mulig dødelig utfall uten reell rettergang.&lt;br /&gt;&lt;br /&gt;Navnene på journalistene, Thomas Hubert og Sveinung Berg Berntzrød, har iallfall brent seg inn på min netthinne. Håper de er såpass sikre på sine kilder at de er beredt til å inntre som aktor, jury og bøddel.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Jeg så også tendenser til dette under narkosaken i Bolivia hvor pressen ikke har vett til å beskytte folk mot seg selv. Selv om de tiltalte i Bolivia-saken var "skyldige som bare f...", så var det ett tidspunkt hvor så godt som alle aviser sluttet å skrive om saken og nye "versjoner" fra opprørte og ivrige pårørende opphørte.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-4079507129719849886?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/4079507129719849886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/09/aftenpostens-artikkel-om-nordmennene-i.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/4079507129719849886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/4079507129719849886'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/09/aftenpostens-artikkel-om-nordmennene-i.html' title='Aftenpostens artikkel om nordmennene i Kongo'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-6495499858295591073</id><published>2009-08-30T12:33:00.002+02:00</published><updated>2009-08-30T12:50:24.028+02:00</updated><title type='text'>My development Tools</title><content type='html'>In an average work week I use:&lt;br /&gt;&lt;br /&gt;Visual Studio 2008 Team Edition: The IDE of non-choice.&lt;br /&gt;&lt;br /&gt;Reflector: There is no excuse for not having this if you work with anything that you haven't made yourself. And even then....&lt;br /&gt;&lt;br /&gt;Resharper: Can't live without it. If you develop in VS2005/VS2008, professional version or higher, you should waste no time in getting this. This is a plugin which makes Visual Studio what it should have been in the first place. Microsoft is usually very slow to establish accommodation for sound development practices. And even Resharper is a wee slow for being the testrunner of choice.&lt;br /&gt;&lt;br /&gt;NDepend: I love this tool. Have you ever wondered how to manage a large code base without actually having to read every single line of code? Then this is it. Also pretty straightforward to integrate into your build to enforce architectural constraints.&lt;br /&gt;&lt;br /&gt;Redgate SQL toolbelt: We have a lot of stuff going around SQL Server. Even though I have database edition of Visual Studio, redgate are the ones that seem to actually have experience in the problems of managing such servers.&lt;br /&gt;&lt;br /&gt;ANTS Profiler: Wanting to get to those hard-to-find and hard-to-reproduce performance issues? With very little overhead you can have it running. And, if you are able to reproduce it, you have it. Too many performance tools require you to predict exactly when you are going to see the problem. ANTS Profiler allows you to capture all, and then zoom in on it on the timeline.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Other stuff:&lt;br /&gt;* Mindmanager. (when you just want to get those thoughts down)&lt;br /&gt;* Expresso. (regex helper)&lt;br /&gt;* Editpad. (notepad on steroids)&lt;br /&gt;* SPX from Moodysoft: (screen grabber with redlining and visual effects)&lt;br /&gt;* Zoomit. Every presenter need this when sharing desktop with a projector.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-6495499858295591073?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/6495499858295591073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/08/my-development-tools.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/6495499858295591073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/6495499858295591073'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/08/my-development-tools.html' title='My development Tools'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-1427104231770479268</id><published>2009-08-30T11:28:00.004+02:00</published><updated>2009-09-04T13:52:42.619+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>The debate is over, TDD won.</title><content type='html'>I find that I have very little to add to the words of Robert Martin (Uncle Bob).&lt;br /&gt;&lt;br /&gt;I highly recommend people to look at the available videos of him and his talks about professionalism.&lt;br /&gt;&lt;br /&gt;Our profession as programmers is very much immature. We have hard to accommodate accountability and transparency. We have little regard of what constitutes a true "Deliverable". And, to paraphrase Ken Schwaber, we have a very odd understand of what it means to be "done".&lt;br /&gt;&lt;a href="http://www.hanselman.com/blog/HanselminutesPodcast119WhatIsDoneWithScrumCoCreatorKenSchwaber.aspx"&gt;http://www.hanselman.com/blog/HanselminutesPodcast119WhatIsDoneWithScrumCoCreatorKenSchwaber.aspx&lt;/a&gt;&lt;br /&gt;Basically, we like to do the algorithm, but we do not like to bridge the algorithm to the world.&lt;br /&gt;A nice analogy is the difference between a hobby mechanic and a professional service business.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;We put juniors in our office space and we expect them to produce.&lt;br /&gt;Even a person operating the fryer at McDonalds gets some sort of &lt;em&gt;apprenticeship&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;We resist change. We resist being scrutinized. We resist being managed. We seldom recognize business value. We resist comparison.&lt;br /&gt;We do not have objective standards or engineering principles. The only professional criticism from programmer to programmer is "that's not how I would do it".&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.hanselman.com/blog/HanselminutesPodcast171TheReturnOfUncleBob.aspx"&gt;http://www.hanselman.com/blog/HanselminutesPodcast171TheReturnOfUncleBob.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;But there are standards to be had. Engineering principles exist. But I sincerely do not know if you will actually appreciate them if you have no experience in the industry. I have yet to see this successfully condensed into a learning experience that mentor can bestow on apprentice. Or in the class room.&lt;br /&gt;&lt;br /&gt;Uncle Bob has the comparison of when doctors learnt to wash their hands when walking from an autopsy to the maternity ward. It took a generation change to implement it. And the problem domain was unknown to anybody fresh out of the contemporary version of "med school". One may even argue wether or not it still was the same profession before and after knowing about germs.&lt;br /&gt;&lt;br /&gt;Even though I don't think a serious argument still exist against Test Driven Development as a whole. It is still an immature practice which a significant part of the developer community still resist.&lt;br /&gt;&lt;br /&gt;Without a frame of reference, it is hard to separate the community from the practices. It has become a part of the expected norm that software has bugs and that software development is an inherent financial liability.&lt;br /&gt;&lt;br /&gt;I believe and hope that this will change.&lt;br /&gt;&lt;br /&gt;Just fifteen years ago (being careful to pick a timeframe that excludes me), programmers were stereotyped to be socially awkward, cave dwelling magic workers with questionable antics and hygiene. Approachable only by the specially trained project manager who knew better than to hint at a questionable decision or belated milestone.&lt;br /&gt;Today, most project managers are quite capable of programming in MS Excel and the sacred art of programming "magic" has unraveled.&lt;br /&gt;Even though I presented a caricature strawman, something has certainly changed.&lt;br /&gt;&lt;br /&gt;I hope that they will keep changing. That technical debt, development liability, Test Code coverage, Continuous Integration and automated deployment will be common case real life business metrics KPI's (Key Performance Indicators) for the future.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The debate is over, TDD won. Will the community inertia demand another 15 years before the change is de facto?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-1427104231770479268?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/1427104231770479268/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/08/debate-is-over-tdd-won.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/1427104231770479268'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/1427104231770479268'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/08/debate-is-over-tdd-won.html' title='The debate is over, TDD won.'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-5995233718246610737</id><published>2009-08-30T11:07:00.002+02:00</published><updated>2009-08-30T13:03:27.004+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mentalism'/><category scheme='http://www.blogger.com/atom/ns#' term='skepticism'/><title type='text'>Skepticism and mentalism.</title><content type='html'>To me, skepticism is about observing the world and then build your knowledge.&lt;br /&gt;&lt;br /&gt;I love the fact that outspoken atheists like Richard Dawkins have started to connect with the likes of Derren Brown. I believe James Randi has a big part of that credit. I think that this was an important pragmatic step for skepticism.&lt;br /&gt;&lt;br /&gt;I do, however, find that fellow skeptics are less comfortable with that. For example, to me, the "placebo effect" is something wonderful that we should celebrate and try to isolate and purify.&lt;br /&gt;However, my peers usually find the placebo effect (is there any other human intellectual endeavour where you decide to name an effect after the one thing that you know to be &lt;strong&gt;&lt;em&gt;irrellevant&lt;/em&gt;&lt;/strong&gt;?) to be a reason for dismissal. I strongly disagree. I dismiss pretty quick the explanations given (aura, holisticism, spiritualism, deities), but I recognize skills and recipes and I am fascinated by the mere fact that the body can heal itself (or at least: stop behaving symptomatically). If I could invoke the "placebo effect" at will (without mumbo-jumbo) I would prefer that to taking a pill against normal headache.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-5995233718246610737?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/5995233718246610737/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/08/skepticism-and-mentalism.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/5995233718246610737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/5995233718246610737'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/08/skepticism-and-mentalism.html' title='Skepticism and mentalism.'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-3162361778665382729</id><published>2009-08-30T10:39:00.002+02:00</published><updated>2009-09-03T20:46:42.200+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Personal'/><title type='text'>My own blog</title><content type='html'>Somewhere along the way, I realized that I victimize my coworkers by the water cooler by bestowing my idea of "interesting conceptual problems" on them. Usually this means that the problems have no real-world application or even &lt;em&gt;relevance&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;The blog allows my banter to be victimless. And, since I don't yet have readers, I suppose the subjects will be all over the place.&lt;br /&gt;&lt;br /&gt;Maybe even somewhere along the line, I find that someone is willing to give me feedback other than "huh?"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now about me....&lt;br /&gt;&lt;br /&gt;I am an outspoken freethinker and atheist. I pull few punches when it comes to discussing subjects. Sometime in the future, I hope to learn to listen as well... When I find time for it, that is....&lt;br /&gt;&lt;br /&gt;I am an active athlete in underwater rugby (coach and team captain) and an avid amateur on combatives. I have done some instructing on professional application of force as well as self defence and I am pretty good.&lt;br /&gt;&lt;br /&gt;I have a best friend who is a hypnotherapy phenom. I love discussing mentalism, hypnosis, NLP and mind states.&lt;br /&gt;&lt;br /&gt;I am a programmer in C#.NET. That's me for the moment. Not that I don't recognize Java, functional programming or dynamically typed languages. But I find that they expand on a tangent that I'm not "into" right now. Hopefully that will change when I get good with my current programming domain.&lt;br /&gt;&lt;br /&gt;I am well into popular sciences.&lt;br /&gt;&lt;br /&gt;Come to think of it, I sure hope this blog engine support tags so that I wont lose .NET readers due to my banter on hypnosis. Most blogs that I follow usually are all on the same theme.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-3162361778665382729?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/3162361778665382729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/08/my-own-blog.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/3162361778665382729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/3162361778665382729'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/08/my-own-blog.html' title='My own blog'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2730416853424583572.post-1700788469344869471</id><published>2009-08-30T10:36:00.001+02:00</published><updated>2009-08-30T11:21:21.320+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>The reverese dependency problem. TDD</title><content type='html'>When building the word chain app, http://codekata.pragprog.com/2007/01/kata_nineteen_w.html , I quickly identify that there are multiple problem domains involved. One is the generic question of finding the shorter path in a mesh of connected nodes.&lt;br /&gt;&lt;br /&gt;Then the question is: do you build this functionality with its own set of unit tests or not?&lt;br /&gt;&lt;br /&gt;I would like to say "not". I don't want to take "time out" from my real business problem to build a different class library in some BDUF venture. I want to refactor into this design.&lt;br /&gt;&lt;br /&gt;However, let us say that I proceeded with this, and elegantly refactored a utility class library that was generic and succinct.&lt;br /&gt;&lt;br /&gt;And then this class library is so generic that I have more client apps that should be consuming it. And new clients warrant more functionality.&lt;br /&gt;I may not be able to express new client requirements from my wordchain problem, and therefore I need to TDD from the unit tests of the new client apps.&lt;br /&gt;&lt;br /&gt;However, then the class library, slowly becomes "dependent" of a growing number of its clients, because that is where its unit tests are. It wont get coverage unless you run the unit tests of its clients.&lt;br /&gt;&lt;br /&gt;I realize that at some point you must recognize that the new class library is a new "deliverable" and thus you need extract its own tests. This will however result in duplication and longer release cycle for the word chain app, because it is a separate release item. New word chain app requirements will have longer development time because new requirements to the class library must be TDD'ed through unit tests of the class library, parallel to the unit tests of the word chain app.&lt;br /&gt;&lt;br /&gt;Theoretically, you should have 200% percent coverage in the class library. One "100" through the sum of its clients unit tests, and one "100" through its own unit tests.&lt;br /&gt;&lt;br /&gt;Interesting problem. It becomes sort of a reverse dependency problem. Stabile components become dependant of unit tests of less stabile components.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Do you find that you get test duplication because you don't want some internal class libraries to be "depending" on the unit tests of its consumers?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2730416853424583572-1700788469344869471?l=tormodjs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tormodjs.blogspot.com/feeds/1700788469344869471/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tormodjs.blogspot.com/2009/08/reverese-dependency-problem-tdd.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/1700788469344869471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2730416853424583572/posts/default/1700788469344869471'/><link rel='alternate' type='text/html' href='http://tormodjs.blogspot.com/2009/08/reverese-dependency-problem-tdd.html' title='The reverese dependency problem. TDD'/><author><name>Tormod</name><uri>http://www.blogger.com/profile/07202721529766661974</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_ll3fiWXgCdo/Sp_FhCydkTI/AAAAAAAAAAM/SYrkMzZadAw/S220/Tormod.jpg'/></author><thr:total>0</thr:total></entry></feed>
