<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jimako's Blog &#187; Software Development</title>
	<atom:link href="http://www.jimako.com/blog/category/software-development/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jimako.com/blog</link>
	<description>Looking forward, aware of the past...</description>
	<lastBuildDate>Fri, 25 Jan 2008 13:28:21 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>What to develop?</title>
		<link>http://www.jimako.com/blog/2007/05/16/what-to-develop/</link>
		<comments>http://www.jimako.com/blog/2007/05/16/what-to-develop/#comments</comments>
		<pubDate>Wed, 16 May 2007 02:37:03 +0000</pubDate>
		<dc:creator>jimako</dc:creator>
				<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.jimako.com/blog/2007/05/16/what-to-develop/</guid>
		<description><![CDATA[You know, I am getting to the point where I want to do something for myself. After many, many years developing software, I want to develop something where I own the IP.
There are two ways to make money with this sort of thing. One is to try to sell software, for as high a price [...]]]></description>
			<content:encoded><![CDATA[<p>You know, I am getting to the point where I want to do something for myself. After many, many years developing software, I want to develop something where I own the IP.</p>
<p>There are two ways to make money with this sort of thing. One is to try to sell software, for as high a price as you can get away with (and some of the prices paid in the enterprise space are just amazing).  However, I am not keen on this. I have been involved in this type of sales process, and I have yet to remove the sour taste it left in my mouth.</p>
<p>I would rather look at developing an online service, and ask people to subscribe to it. Get just 1000 people world-wide to pay $10/month, and you have a reasonable salary. Make that 10,000 and you are talking serious income. In today&#8217;s global market, neither figure seems absurd.</p>
<p>So, what to develop?  Does anyone have any good ideas? I&#8217;d love to hear from you.</p>
<p>What online service would you be willing to pay $10/month for?  What about $20/year?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jimako.com/blog/2007/05/16/what-to-develop/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Zen of Python</title>
		<link>http://www.jimako.com/blog/2006/12/05/the-zen-of-python/</link>
		<comments>http://www.jimako.com/blog/2006/12/05/the-zen-of-python/#comments</comments>
		<pubDate>Tue, 05 Dec 2006 02:32:41 +0000</pubDate>
		<dc:creator>jimako</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.jimako.com/blog/2006/12/05/the-zen-of-python/</guid>
		<description><![CDATA[I really like Python, but was not aware of this little hidden easter egg.  If you fire up the interactive interpreter, and type &#8220;import this&#8221;, you get this wonderful printout to the console:
&#62;&#62;&#62; import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is [...]]]></description>
			<content:encoded><![CDATA[<p>I really like <a href="http://www.python.org" title="Python web site">Python</a>, but was not aware of this little hidden easter egg.  If you fire up the interactive interpreter, and type &#8220;import this&#8221;, you get this wonderful printout to the console:</p>
<p>&gt;&gt;&gt;<strong> import this</strong><br />
The Zen of Python, by Tim Peters</p>
<p>Beautiful is better than ugly.<br />
Explicit is better than implicit.<br />
Simple is better than complex.<br />
Complex is better than complicated.<br />
Flat is better than nested.<br />
Sparse is better than dense.<br />
Readability counts.<br />
Special cases aren&#8217;t special enough to break the rules.<br />
Although practicality beats purity.<br />
Errors should never pass silently.<br />
Unless explicitly silenced.<br />
In the face of ambiguity, refuse the temptation to guess.<br />
There should be one&#8211; and preferably only one &#8211;obvious way to do it.<br />
Although that way may not be obvious at first unless you&#8217;re Dutch.<br />
Now is better than never.<br />
Although never is often better than *right* now.<br />
If the implementation is hard to explain, it&#8217;s a bad idea.<br />
If the implementation is easy to explain, it may be a good idea.<br />
Namespaces are one honking great idea &#8212; let&#8217;s do more of those!<br />
&gt;&gt;&gt;</p>
<p>Enough said.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jimako.com/blog/2006/12/05/the-zen-of-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What&#8217;s the logical next step in web development?</title>
		<link>http://www.jimako.com/blog/2006/11/24/whats-the-logical-next-step-in-web-development/</link>
		<comments>http://www.jimako.com/blog/2006/11/24/whats-the-logical-next-step-in-web-development/#comments</comments>
		<pubDate>Fri, 24 Nov 2006 12:10:35 +0000</pubDate>
		<dc:creator>jimako</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Rants and Raves]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.jimako.com/blog/2006/11/24/whats-the-logical-next-step-in-web-development/</guid>
		<description><![CDATA[I&#8217;m a big fan of Ruby, the language.
I&#8217;m really impressed with the potential of the Rails framework (although to be honest there seems to be a lot of voodoo going on behind the scenes, which is probably just an indication that I have not yet done enough with this framework to be comfortable with it).
But [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a big fan of <a title="Link to Ruby home page" href="http://www.ruby-lang.org/en/">Ruby</a>, the language.</p>
<p>I&#8217;m really impressed with the potential of the <a title="Ruby on Rails" href="http://www.rubyonrails.org/">Rails</a> framework (although to be honest there seems to be a lot of voodoo going on behind the scenes, which is probably just an indication that I have not yet done enough with this framework to be comfortable with it).</p>
<p>But there is no denying the reality that, for most of us, adopting Ruby and RoR is not a simple decision, because we already have code that has been developed atop a Java web stack.</p>
<p>If we are looking at a new project, and there is some ability to absorb the risk of going with a new technology stack, I would be the first to suggest that RoR be given serious consideration.  On the other hand, if we are involved in the on-going development of a Java web application that has been going on for several years, does it make sense to try to integrate a new stack into the mix?</p>
<p>Let me set some parameters.  You have a successful product that is continually being improved. Using &#8220;<strong>best practices</strong>&#8221; (I&#8217;ll come back to that term in another post), the application has been developed using an <a title="http://java.sun.com/blueprints/patterns/MVC.html" href="http://java.sun.com/blueprints/patterns/MVC.html">MVC</a> framework &#8212; let&#8217;s say <a title="http://struts.apache.org/" href="http://struts.apache.org/">Struts</a>, <a title="http://java.sun.com/products/jsp/" href="http://java.sun.com/products/jsp/">JSP</a> and <a title="http://www.hibernate.org/" href="http://www.hibernate.org/">Hibernate</a> as a concrete and all-too-common example.</p>
<p>Now, we want to make some changes as a result of customer feedback. Typically, these changes are either new features or modules, or else changes to the existing functionality.</p>
<p>Changes to the existing functionality are hard to do in any other technology.  Sure, if the changes are broad enough, it might make sense to redevelop one or more modules from scratch; in that case, of course, we can treat it the same way we would treat the development of a new feature.</p>
<p>So, for a new feature, what alternatives do we have?</p>
<p>We can certainly continue on with our existing technology stack.  In many ways, this is the low-risk option, because we know the technology.  We know the tool-sets, we have knowledge within our development team, and we have historical data about how quickly we can do things using that technology. And let&#8217;s not forget that the stack itself is well-proven, because we (and countless others) have deployed applications on that stack and we know how the stack scales, how it deploys, how it responds to machine and network resource allocations.  There is a lot of value to maturity.</p>
<p>But is it <strong>really</strong> a low-risk option?  What if the development velocity is not fast enough?  Sure, we have good predictability, but if our predictions are that we can&#8217;t do it as quickly as we need to in order to satisfy the customer, or prevent the work being assigned off-shore, then surely persisting with that technology is in reality the <strong>high risk</strong> option.</p>
<p>And here&#8217;s the real issue.  Java web development using the classic development stack is just not fast enough.  I&#8217;ve heard the arguments &#8212; you need to do all the fancy plumbing and documentation / annotation so that the app scales and is flexible and maintainable when it gets hit by millions of users per minute.  The reality, however, is that most applications never need that scalability, especially if they are not finished because application development is too slow.</p>
<p>So what do we do?  Is there some way to incorporate some of the really rapid web application development techniques into an existing Java web application?</p>
<p>I think that we are at a difficult time in Java web development. We have a lot of systems that have been developed over a long time (&#8220;long&#8221; being relative to the rate of change of software development, of course).  While these systems are often still in active enhancement, they are also in a very real sense legacy systems, built using tool sets, frameworks and architectures that, well, seemed like a good idea at the time.  Looking back at what we have done, and also looking at all the shining new toys all the new kids are playing with that show just how much faster web application development can be, we can&#8217;t help but feel frustrated and itchy to do something, well, different.</p>
<p>At the same time, we have some interesting things &#8220;just around the corner&#8221; in the Java space.  But we need something we can use <strong>right now</strong>.</p>
<p>I see <a title="http://jruby.codehaus.org/" href="http://jruby.codehaus.org/">JRuby</a> is coming along in leaps and bounds.  This is an implementation of the Ruby language for the Java Virtual Machine.  It is almost at the point that it can run Rails applications.  However, I don&#8217;t see a clean way to do new-feature development for an existing web application using Rails, even if it is on the JVM.  Another very nice dynamic language, <a title="http://www.python.org/" href="http://www.python.org/">Python</a>, has a JVM implementation in <a title="http://www.jython.org/" href="http://www.jython.org/">Jython</a>, but this is languishing and seems to have been largely orphaned when its initial developer switched focus to <a title="http://www.ironpython.com/" href="http://www.ironpython.com/">IronPython</a>, which is an implementation for the .NET platform.</p>
<p><a title="http://groovy.codehaus.org/" href="http://groovy.codehaus.org/">Groovy</a> is coming along nicely, but slowly.  It is likely to be an &#8220;official&#8221; scripting language as a result of having a <a title="http://www.jcp.org/en/jsr/detail?id=241" href="http://www.jcp.org/en/jsr/detail?id=241">JSR</a>. Also, it has a Java-like syntax, which means that there is a shorter pick-up time required for Java developers.</p>
<p>If I thought that language is the limiting factor, then I would look at Groovy because it has a lot of the syntactical conveniences of the popular scripting languages with full access to existing objects that have been coded in Java (including the Java libraries).</p>
<p>However, while I think Java can be too wordy, requiring lots of boilerplate code in some circumstances, I am not at all convinced that this is the major reason that web development in Java is too slow.</p>
<p>In reality, I think that the real reason web development in Java is too slow is that we are making it too complicated.  The real reason that frameworks like RoR are so incredibly productive, in my opinion, are more related to the use of very simple ORM designs like <a title="http://wiki.rubyonrails.com/rails/pages/ActiveRecord" href="http://wiki.rubyonrails.com/rails/pages/ActiveRecord">ActiveRecord</a>, and the <a title="http://en.wikipedia.org/wiki/Ruby_on_rails" href="http://en.wikipedia.org/wiki/Ruby_on_rails">Convention over Configuration</a> philosophy.</p>
<p>Sure, Hibernate is REALLY powerful.  But it is not ideal for all sorts of database access, at least not when used naively.  Sometimes, a simple SQL query, processed as JBOF (Just a Bunch Of Fields, and yes, I did just make that up) is totally appropriate.</p>
<p>Consider for example presenting a user with a filtered, paged list of widgets.  In the prehistoric era of web development (that is, about 8 years ago, and using VB6 COM behind IIS/ASP) I designed a relatively simple, generic technique.  I created an SQL statement by putting together the WHERE clause dynamically. I then did a SELECT statement, retrieving only the IDs that matched the criteria.  IDs were just 32 bits each, so even a million of the suckers was just 4M &#8212; most lists were a few hundred to a (very) few thousand rows.  I just stuck them in an array and stuffed them into the session.  Then, paging was simple: just calculate the array indexes that correspond to the desired page, create an SQL statement that retrieves only the ID and the columns required for the list display (using an SQL WHERE ID IN &#8230; statement) and displayed the list.  All this is totally generic, it scales REALLY well, and has not let us down after years of very heavy use in the field.</p>
<p>More recently, and in the Java world, we end up retrieving lists of objects. We rely on Hibernate or the <em>ORM de jour</em> to do magic, multi-level caching and lazy object instantiation and hope that it all works.  And then we dump the list into some magic JSP taglib that does sorting in memory.  And when the list gets to a few hundred items, the list takes MINUTES to display, and customers are unhappy, and developers say &#8220;you didn&#8217;t specify performance criteria&#8221;, and analysts say &#8220;but of course it has to handle more than a dozen items in a list&#8221;, and you need to divert resources to do major investigation and refactoring or redevelopment, and you start to think that things are not meant to be this hard.</p>
<p>In business application development, the needs of the application for data access are not complex.  We need to get filtered lists of items, then we need to get complete individual items.  That&#8217;s pretty much it, and that&#8217;s what DATABASE servers do &#8212; we should let them do their job and not try to replicate that in the application. Updating is only a little more complex.</p>
<p>The other lesson that we can learn from RoR is that we seriously need to tame the configuration frenzy that Struts brings.  I need more time to think about this, but I think that a good way to begin simplifying this in an existing product is to add a single Struts action that further parses the request URI and uses some convention to identify the class and method that should handle it.  That class could be written in Java, or any of the new, JVM-hosted scripting languages.  Do it well, and write a suitable class loader, and you could even hot-deploy a URI request handler class or JAR file.</p>
<p>The reason that I am considering this is not because I don&#8217;t want to use an existing framework like Ruby on Rails (or for that matter <a title="http://grails.codehaus.org/" href="http://grails.codehaus.org/">Grails</a>, <a title="http://www.turbogears.org/" href="http://www.turbogears.org/">Turbogears</a> or <a title="http://www.djangoproject.com/" href="http://www.djangoproject.com/">Django</a>). It&#8217;s that I need to be able to integrate whatever framework we use into the application as it exists so far, and everything I see (and my gut instinct) tells me that these frameworks are good for new projects but are likely to be a bitch to configure and integrate with a Java/Struts/JSP stack.</p>
<p>I have not yet clarified my own thinking about all this, but I wanted to post it to get some feedback.  What do others think?  Am I alone in thinking that we are making Java web development harder than it needs to be?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jimako.com/blog/2006/11/24/whats-the-logical-next-step-in-web-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>When the map doesn&#8217;t match the ground&#8230;</title>
		<link>http://www.jimako.com/blog/2006/09/03/when-the-map-doesnt-match-the-ground/</link>
		<comments>http://www.jimako.com/blog/2006/09/03/when-the-map-doesnt-match-the-ground/#comments</comments>
		<pubDate>Sat, 02 Sep 2006 21:10:19 +0000</pubDate>
		<dc:creator>jimako</dc:creator>
				<category><![CDATA[Rants and Raves]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.jimako.com/blog/2006/09/03/when-the-map-doesnt-match-the-ground/</guid>
		<description><![CDATA[&#8230; then it&#8217;s the map that is wrong. 
Last week, my son went for an interview for entry into one of the top academic high schools in this state, and I needed to kill a couple of hours. I therefore went into a local Borders bookshop, grabbed a book almost at random and sat down [...]]]></description>
			<content:encoded><![CDATA[<p>&#8230; then it&#8217;s the map that is wrong. </p>
<p>Last week, my son went for an interview for entry into one of the <a href="http://www.mhs.vic.edu.au/">top academic high schools</a> in this state, and I needed to kill a couple of hours. I therefore went into a local Borders bookshop, grabbed a book almost at random and sat down with it in the embedded Gloria Jean&#8217;s with a cup of coffee. I don&#8217;t even remember the name of the book; it was something like &quot;30 Things You Need To Know Right Now&quot;. What has stuck in my mind is the first of these &quot;things&quot;.</p>
<blockquote><p><strong>If the ground doesn&#8217;t correspond to the map, then it&#8217;s the map that is wrong.</strong></p></blockquote>
<p>Sounds simple, doesn&#8217;t it?</p>
<p>I must admit that I didn&#8217;t read much past that opening chapter heading, because I had one of those &quot;Aha&quot; moments (or more like one of thise &quot;D&#8217;oh&quot; moments, I guess). </p>
<p>Everyone today seems to have a preferred point of view about how the world works. Based on that view, plans are drawn out that attempt to map out what we will do and the outcomes that we expect. I admit to having a particular issue in mind here &#8212; the issue of &quot;professional managers&quot; that I have <a href="/blog/2006/06/16/professional-managers/">blogged about before</a>, and I will use this issue as an example &#8212; but the observations that I am making are more generally applicable. </p>
<p>Let me go through a concrete example here. As I have already documented, I believe that a technical activity like software development cannot be managed by a generalist manager. But my view is not universally subscribed to &#8212; shocking, I know, but not everyone agrees with my every view, at least not yet, although I continue to work on it. </p>
<p>So in a particular workplace that I am familiar with, despite my view, there has been a definite move over the past several months away from using managers with a technical background and towards employing generalist managers, people who are in fact actively TRYING to remain non-technical, and believe that major software development projects should be managed in the abstract using general project management techniques. </p>
<p>For a while, I have been trying to argue against this policy, and several others have voiced concerns as well. But this single statement hit me like a cricket bat over the head. </p>
<p>If the ground doesn&#8217;t correspond to the map, then it&#8217;s the map that is wrong. </p>
<p>I don&#8217;t need to argue the view on a &quot;first principles&quot; or &quot;logical&quot; basis. I simply need to look at what is happening in the real world. </p>
<p>In other words, I need to stop focusing on the map and look at the ground. </p>
<p>You see, there are a few very clear indicators about the health of a software development project, and they can be measured reasonably easily. Those indicators are not universal, as every human endeavour is a trade-off between competing requirements. But for any given project, there is a specific range of settings on the various axes that we are aiming for, and we can usually gauge how we are tracking. </p>
<p>So if we are aiming for high quality, then we can look at defect rates. If speed of delivery is our focus, then we can look at function points delivered per release. If we are looking at long term project sustainability, then developer satisfaction and retention rates (or, inversely, dissatisfaction and staff turnover) can be examined. If we are concerned with customer satisfaction, we can ask the customer for subjective or objective feedback. </p>
<p>If we look at what data we have &quot;before&quot; (that is, with technical managers) and &quot;after&quot; (with generalist managers), we can see which set of conditions moves us closer to our desired outcomes. And if one of them is significantly closer to the way we want to be, then all the arguments and logic about which management strategy is best become irrelevant. It&#8217;s like arguing about which map is more correct without looking at the ground. The correct answer can be determined quite unambiguously by comparing the maps to the ground. </p>
<p>Similarly, if we look at the health of the project, using whatever parameters we want to define health, under the two management styles, we should be able to discern which of the styles is better in this context. </p>
<p>Now, let me be the first to admit that this metric will only look at the relative performance of the particular individuals involved, and on the project under examination, and a single set of observations like this cannot be extrapolated safely to the broader project management landscape. However, I am really interested in just this one particular set of variables, so that&#8217;s perfectly OK. </p>
<p>I would be interested, however, in collating more information from a number of different projects that have tried both management types to see if there is any commonality. With enough separate data points, we might well be able to draw some generally applicable conclusions. </p>
<p>Feel free to leave any anecdotal data in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jimako.com/blog/2006/09/03/when-the-map-doesnt-match-the-ground/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8220;Professional&#8221; Managers</title>
		<link>http://www.jimako.com/blog/2006/06/16/professional-managers/</link>
		<comments>http://www.jimako.com/blog/2006/06/16/professional-managers/#comments</comments>
		<pubDate>Thu, 15 Jun 2006 20:39:21 +0000</pubDate>
		<dc:creator>jimako</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[Rants and Raves]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.jimako.com/blog/2006/06/16/professional-managers/</guid>
		<description><![CDATA[I just read the latest article by Joel Spolsky over on Joel on Software (a site you really should bookmark). Joel reminisces about the time he had his First BillG Interview where he had to present the spec for what was going to be Visual Basic for Applications to Bill Gates. It&#8217;s a good read, [...]]]></description>
			<content:encoded><![CDATA[<p>I just read the latest article by Joel Spolsky over on <a href="http://www.joelonsoftware.com/" title="Joel On Software">Joel on Software</a> (a site you really should bookmark). Joel reminisces about the time he had his <a href="http://www.joelonsoftware.com/items/2006/06/16.html" title="First BillG Interview">First BillG Interview</a> where he had to present the spec for what was going to be Visual Basic for Applications to Bill Gates. It&#8217;s a good read, and Joel&#8217;s writing style is very entertaining. While Joel and I have differing opinions on some things, I certainly respect his experience and knowledge, and I suspect that the things we disagree about are simply related to the fact that he takes some concepts too literally (especially with regards to such Agile concepts and no <a href="http://xp.c2.com/BigDesignUpFront.html" title="BDUF">BDUF</a>, but&#8217;s that&#8217;s for another post). </p>
<p>Towards the end of the post, Joel makes this observation:</p>
<blockquote><p>
Bill Gates was amazingly technical. He understood Variants, and COM objects, and IDispatch and why Automation is different than vtables and why this might lead to dual interfaces. He worried about date functions. He didn&#8217;t meddle in software if he trusted the people who were working on it, but you couldn&#8217;t bullshit him for a minute because he was a programmer. A real, actual, programmer. </p>
<p>Watching non-programmers trying to run software companies is like watching someone who doesn&#8217;t know how to surf trying to surf. </p>
<p>&quot;It&#8217;s ok! I have great advisors standing on the shore telling me what to do!&quot; they say, and then fall off the board, again and again. The standard cry of the MBA who believes that management is a generic function. Is Ballmer going to be another John Sculley, who nearly drove Apple into extinction because the board of directors thought that selling Pepsi was good preparation for running a computer company? The cult of the MBA likes to believe that you can run organizations that do things that you don&#8217;t understand.</p>
</blockquote>
<p><strong>Hear! Hear!</strong> </p>
<p>You know, it&#8217;s not that I don&#8217;t respect management as a discrete set of skills, a seperate discipline if you will. Managing anything successfully requires a particular mindset and approach that is quite specific to the task of management, and the actions that a manager does (and the skill required to carry them out effectively) are specific and distinct from those needed in other endeavours (like, oh, I don&#8217;t know&#8230; developing software, for example). </p>
<p>That does not mean, however, that those skills are all that a manager needs in order to be effective. </p>
<p>I guess it is theoretically a possibility that somewhere there is an activity that can be managed by someone who has no understanding about that activity. (I am not saying that there <strong>is</strong> such an activity, just that there <strong>might</strong> be.) </p>
<p><strong>But developing software is not it.</strong> </p>
<p>It is simply not possible to manage a software development business without a reasonable understanding of software development. I am not going to try to justify that statement here, because quite frankly either you know that this is true, or you can&#8217;t possibly be convinced that it is. What I will say, after 28 years in this game, is that whenever I have had to work with a &quot;manager&quot; that does not understand software development, the end result has invariably been sub-optimal. And by &quot;sub-optimal&quot; I mean a disaster, except where this was avoided by those who <strong>did</strong> understand and who went far beyond what could be expected of them and worked around that manager to get things done. </p>
<p>While it is not necessary (indeed, it may not even be desirable) for a manager in a software business to be the most technically competent developer, it is an absolute requirement that he or she be able to understand if something is easy or hard, if it is high risk or low risk, if it is reasonable or unreasonable, if it is obviously wrong, obviously right, or just plain not known. He or she needs to understand whether an estimate is reasonable, or whether it is too optimistic or too conservative. </p>
<p>If the manager can&#8217;t do these things, then how can he or she manage? Can you imagine this scenario? If I were asked to manage a banana farm (an activity I know absolutely nothing about) then here is a conversation with the farm workers: </p>
<p><strong>Me:</strong> The buyers want bananas that are more uniform in size. How can we do this? </p>
<p><strong>Workers:</strong> You can&#8217;t. Bananas have a certain variation in size. Indeed, the particular species we grow is internationally recognised as the most uniform in size. </p>
<p>OK. Now what? Is this true? What do I do next? </p>
<p>Worse still, the previous day, in the meeting with the buyer, the conversation had gone like this: </p>
<p><strong>Buyer:</strong> Our consumers are complaining about the variation in the size of the bananas. We need them to be far more uniform. </p>
<p><strong>Me:</strong> Oh, I&#8217;m sure that is not going to be a problem. After all, we employ world best practice farming techniques. I am sure we can do something about that. So if we add a clause to that effect into the contract, you will sign an order today? </p>
<p><strong>Buyer:</strong> Yes, but only if you can assure me you can have a smaller variation in the size. </p>
<p><strong>Me:</strong> No problem. Sign here, please. </p>
<p><strong>If this sounds ridiculous to you, welcome to my world&#8230;</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.jimako.com/blog/2006/06/16/professional-managers/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Too many levels of Abstraction</title>
		<link>http://www.jimako.com/blog/2006/05/22/too-many-levels-of-abstraction/</link>
		<comments>http://www.jimako.com/blog/2006/05/22/too-many-levels-of-abstraction/#comments</comments>
		<pubDate>Sun, 21 May 2006 16:03:54 +0000</pubDate>
		<dc:creator>jimako</dc:creator>
				<category><![CDATA[Rants and Raves]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.jimako.com/blog/2006/05/22/too-many-levels-of-abstraction/</guid>
		<description><![CDATA[I have been reading a great book over the past couple of days. It is called The Best Software Writing I and I picked it up at the local Borders when I dropped in to browse as I am wont to do on the odd occasion. Reading it fired up the creative juices, so I [...]]]></description>
			<content:encoded><![CDATA[<p>I have been reading a great book over the past couple of days. It is called <a href="http://www.amazon.com/gp/product/1590595009/104-6856871-7835951?v=glance&amp;n=283155" title="The Best Software Writing I">The Best Software Writing I</a> and I picked it up at the local Borders when I dropped in to browse as I am wont to do on the odd occasion. Reading it fired up the creative juices, so I thought I would put finger to keyboard about something that has been gnawing at me for a while now: the fact that we seem to be making things more complex than they need to be because of some misguided attempt to model the &quot;real world&quot;. </p>
<p>Now, I am the first to admit to being an old-world developer. I learnt how to program in the late 70s, at at time when OOP was simply unheard of out in the wild. I clearly remember the famous hot air balloon cover on the issue of Byte that introduced Smalltalk. Yes, not only was I alive then, I was old enough to buy Byte and read it. </p>
<p>I have worked through the evolution of our craft and the changes in the way we approach the development of software. By virtue of the fact that I learnt to program before there was OOP, intially I had a tough time really understanding how OOP worked, simply because there was a lot of <em>unlearning</em> that I had to do. It took me a while, and there were many times when I told myself that <strong>now</strong> I &#8216;got&#8217; OOP, only to admit a little while later that I really didn&#8217;t get it at all. </p>
<p>If that sounds at all negative about OOP, it isn&#8217;t meant to. I am actually a big proponent of the benefits of OOP and think that the binding of data with the procedures that operate on it is A Good Thing. </p>
<p>What I am finding, however, is that a new generation of programmers who don&#8217;t know anything <strong>except</strong> OOP are losing track of the objective. When you learn OOP, you are inevitably given examples of real-world objects that you try to model. I think that if I ever see another example of an Animal class, with Dog and Cat descendents, I will scream, even though I actually wrote <a href="http://www.jimako.com/Articles/OOPForVBProgrammers" title="a student manual for a VB4 course">a student manual for a VB4 course</a> that used these self same classes. We learn about inheritance and its use to create polymorphic behaviour by having Cat.Speak emit a mieaow while Dog.Speak emits a woof. Or we have traffic lights control their own sequencing by sending messages to each other. All very cool. </p>
<p>Then off we go to do commercial programming. Except, there is a real disconnect at this point. &#8216;EDP&#8217; (to use an outdated but nonetheless expressive term) is not the same as traffic control. In most business data manipulation, the entities we are dealing with are nothing but data points. The only reason the system exists it to maintain a repository of data, furnish a controlled view into that repository and provide a mechanism to allow a predifined set of transformations of that data to take place in a controlled manner. There are no dogs or cats in the wild that we are trying to model. What exactly does an account do when it is not being &quot;modelled&quot; by a piece of code? The answer, of course, is nothing at all &#8212; it just sits quietly in a database somewhere. </p>
<p>I have seen too many systems that model an Account object with all sorts of complex behaviours. From one perspective, this can be useful &#8212; we can encapsulate all the things that we can do to an account as methods of the Account object, thereby binding the data with the code and (at least in theory) hiding the implementation details. I have no problem with this; in fact, this is exactly what makes sense. </p>
<p>The problem arises when we refuse to acknowledge that the account lives in a database with a whole lot of other accounts. Worse still, we refuse to acknowledge that the database exists at all. Instead, we abstract it away with a &quot;factory&quot; the magically produces Account objects. It can give us a particular Account object if we can give it some distinguishing attribute, like an ID. But heaven forbid that we ask for any complex filtering &#8212; why, that&#8217;s almost like SQL, and we wouldn&#8217;t want to pollute our neat, abstract, HashMap in the Sky with any of that old &quot;relational stuff&quot;. </p>
<p>So instead of crafting a simple SQL statement that reflects the set of data we actually need, we write code that does all but the simplest filtering on the client side. You don&#8217;t want all the columns of data?  Who cares? Just don&#8217;t reference those attributes of the objects. You don&#8217;t want all the rows? Well, use one of the simple factory methods to do a first cut at the filtering, then just iterate through the list of objects that are returned and remove the ones you don&#8217;t want. </p>
<p>Does anybody else see a problem here? </p>
<p>Decades ago, we came up with a way to manage operations on tabular data. A whole relational alegbra was developed that provided a clean set of operations that could be requested by a client program, so that only the data it actually wanted would be returned by the database. The SQL language provided a reasonably straightforward way to express those operations, and databases got really, <strong>really</strong> good at processing SQL, so that, at least in most cases, they could quickly and efficiently get just this required data together. That&#8217;s what they are designed to do, and they do it very well. And when they have done this, just that data that is actually required goes over the wire to the program that requested it, which in turn can be simpler because it doesn&#8217;t need to do the whole post-processing dance. </p>
<p>Today, OOP developers think that their code has somehow become impure if it contains an SQL statement, or acknowledges the existence of a database, or a table, or a row or column. Yet these are the actual big-O Objects that are being manipulated. The row in the table (OK, the rows in related tables in the database) <strong>are</strong> the account. That <strong>is</strong> the object we are dealing with. Why do we feel the need to abstract it away? </p>
<p>It&#8217;s not like a cat. It is not practical for a program to deal with an actual Cat object. The Cat interface is not well understood, and the Cat Query Language is still in its infancy. When dealing with cats, it makes sense to create a simpler abstraction of a Cat, that models all the attributes of a real cat that we are interested in, and use that as a surrogate for a real cat in our program. Besides, cat fur really clogs up the fan vent in a computer case. </p>
<p>An account, on the other hand, like a large number of the &quot;objects&quot; we deal with in business software development, is quite easily accessible directly. </p>
<p>We don&#8217;t need no steenking abstractions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jimako.com/blog/2006/05/22/too-many-levels-of-abstraction/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>An Interesting Article on Legacy Code</title>
		<link>http://www.jimako.com/blog/2006/02/08/an-interesting-article-on-legacy-code/</link>
		<comments>http://www.jimako.com/blog/2006/02/08/an-interesting-article-on-legacy-code/#comments</comments>
		<pubDate>Wed, 08 Feb 2006 03:12:24 +0000</pubDate>
		<dc:creator>jimako</dc:creator>
				<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.jimako.com/blog/2006/02/08/an-interesting-article-on-legacy-code/</guid>
		<description><![CDATA[I just read an interesting article over on Java Lobby by Dennis Forbes titled Out of Bounds : Avoiding Career Protection Faults.
The article really rang some bells in my mind. I didn&#8217;t really identify with the concerns about job and career security — I guess that I have been fortunate to work with development groups [...]]]></description>
			<content:encoded><![CDATA[<p>I just read an interesting article over on <a title="JavaLobby" href="http://www.javaloby.org">Java Lobby</a> by Dennis Forbes titled <a title="Out of Bounds : Avoiding Career Protection Faults" href="http://www.javalobby.org/articles/outofbounds/">Out of Bounds : Avoiding Career Protection Faults</a>.</p>
<p>The article really rang some bells in my mind. I didn&#8217;t really identify with the concerns about job and career security — I guess that I have been fortunate to work with development groups that are fairly self-confident, and managed by people who can see past the little bits of political posturing that does take place. No, what caught my attention was more related to the behaviour of the new generation of programmers when it comes to anything but the newest code and techniques.</p>
<p>I guess I need to be a bit more concrete. A very good friend of mine, who will remain nameless to protect the innocent, was involved in a web application (yeah, I know, another one). They were using Hibernate to provide an &#8220;object&#8221; view of the database.</p>
<p>Now, before everyone jumps all over me, let me state quite clearly that I like Hibernate. I like it a lot. This is not a criticism of Hibernate. Are we all clear on that? OK, moving right along&#8230;</p>
<p>Recently, they needed to implement a report. Nothing fancy, just your usual run-of-the-mill business report, pulling a few thousand line items and doing some basic totalling and so on. It came back from the dev team, with a note that it now works, so the story is complete, but probably needs to be optimised.</p>
<p>Boy does it need to be optimised. <strong>It takes over 4 hours to produce the report.</strong></p>
<p>Now, these are not dumb developers — nothing could be further from the truth. They are very bright, and they write first-class code. But they <strong>are</strong> young and idealistic. I&#8217;m going to sound like my father for saying this, but the reality is that they haven&#8217;t had enough real-world production experience to make the right decisions on gut instinct. Therefore, in the absence of that, they always apply the pearls of wisdom gathered from the latest &#8220;best practices&#8221; guru or article without filtering it through some basic sanity and appropriateness checks.</p>
<p>Let&#8217;s get back to the report in question as a case in point. There are two reasons that the report was running <strong>so</strong> slowly. The first is a general reluctance to use the database for what it does so well — querying data. Instead, they use Hibernate to get object graphs. And while Hibernate is pretty good at doing sensible things with lazy loading, there is a limit to how well it can optimise this sort of thing and it seems, more often than not in these sorts of scenarios, that it is pulling more data than it needs to out of the database. Quite frankly, I think that creating reports, or lists of items to display in a list view, is generally better done using a simple SQL query that returns just an ID with a the set of columns actually required for displaying the list or report. Hibernate even has a mechanism for doing essentially exactly this, using report queries and HQL, so I am prepared to accept that as a viable alternative, but I would prefer SQL because, quite frankly, it is better understood.</p>
<p>Hibernate is actually pretty well documented, especially for an open-source project. Indeed, it is pretty well documented, period. Many commercial packages could learn a thing or two from Hibernate&#8217;s documentation. But compared to the huge body of knowledge that exists about SQL, and the decades of real-world experience, frankly, it just doesn&#8217;t cut it. Not unless you happen to have a Hibernate guru on hand.</p>
<p>So, I think that using tools such as Hibernate, and refusing to entertain using raw SQL under any circumstances, is <strong>part</strong> of the problem, but only a very small part. I doubt you could make Hibernate take 4 hours to do the report even if you were trying very hard. No, that is not where I think the problem lies.</p>
<p>We can get closer to the problem by stepping back a little. The reason that they can&#8217;t just run a query to get the report data is that the data is not stored, but calculated on demand. The system stores transactional data, and all balances are calculated as required using a bunch of (often nested) calculators that walk the database. So if I want a balance, I walk all the transactions that affect the balance (and there are many types of transactions in several tables with various dependencies) and do a calculation, often quite complex.</p>
<p>From a coding perspective, it&#8217;s a one-line call to a calculator method to get the data I want, so it looks quite elegant, and the calculators are tested separately and I know that they are correct.</p>
<p>The calculators do some basic filtering of the transactions that they process, but they still need to read a lot of them, and sometimes they end up using some lazy fetching of related data. It&#8217;s just the way the data mapping is done, because there are conflicting requirements for different functions in the system. The end result is that doing a calculation is quite expensive, which is not a problem when you are doing just a single calculation.</p>
<p>But what if I want to get month-end balances for the past year? Simple, just loop though the required dates, pass them to the calculator, and get back the balance on that date. It&#8217;s really easy for the calculator to just stop processing transactions when it gets to a particular date.</p>
<p>And if I need DAILY balances? Do you see where this is going?</p>
<p>Inside what looks to the developer like a simple loop, there is a huge amount of database activity going on, and done in such a way that the database has no opportunity to do anything but act as a dumb file store. <strong>That</strong> is what is bringing the database (and the system) to its knees when this report is run.</p>
<p>Now, at this time, gentle reader, you are probably thinking to yourself: why was the database structured that way in the first place? Well, do you remember in school, when you were told not to store something in the database if it can be calculated? Well, that&#8217;s what blindly following that advice ultimately leads to.</p>
<p>Now, I am not advocating that we forget about things like normalisation and removal of redundancy. But all general rules need a context. Just because something <strong>can</strong> be calculated does not mean that it should never, under any circumstances, be stored.</p>
<p>Take this calculated balance as a case in point. Calculating it is expensive, so storing it should at least be considered, and implemented if the time taken to recalculate it makes it impractical to use recalculation whenever it is needed. Even more importantly, some data items, even if they can be calculated, have a distinct &#8220;point-in-time&#8221; value and therefore <strong>need</strong> to be stored regardless of the time it takes to recalculate them.</p>
<p>Let me explain that, because it is important.</p>
<p>Let&#8217;s say that a calculation involves a set of input values, transactions, exchange rates, interest rates, taxation rates&#8230; you get the idea. It&#8217;s more than just the initial and transactional data. Calculating a value means you need to get, for each transaction, the applicable rates that were in effect when that transaction occurred, so you need to keep historical data for each of them. OK, that much is obvious, and there is a clear requirement to store that history if you are going to recalculate as required.</p>
<p>What most people forget, however, is that there is another component to the calculation that can change over time — the code of the calculation itself. If there is a different way to calculate sales tax, for example, or a new type of tax is introduced, or simply a business rule changes, then the calculation logic itself will change <strong>and it will generate different results for the same input data.</strong></p>
<p>So if you want to recalculate an invoice amount for a past date, you better have a copy of the correct version of the calculator code around too, and you better have an infrastructure in the code to handle identifying and instantiating the correct version of the calculator. And it&#8217;s even more complex than that, because if the output of a given calculation feeds into the next period&#8217;s data, then you need to identify, instantiate and use the <strong>correct version of the calculation logic for each period</strong> as you are looping forward.</p>
<p>You&#8217;d better be able to handle this correctly, because if you don&#8217;t, your client-facing staff will see one figure on the screen while the customer will have a different figure on the invoice. Trust me when I say that this is not what you want.</p>
<p>Whenever a figure has a meaning at a point in time, it is a data point all by itself. In my mind, it is a no-brainer: it needs to be stored. In a product order line item, for example, you don&#8217;t store the extended price, because you can always calculate it as unit price times number of units.</p>
<p>But you <strong>do</strong> store the unit price and description, even if you could always look them up from the products table. Why? <strong>Because they can change</strong>, and the line item is a point-in-time data value. In this case, we are shielding the point-in-time data value from changes in the data inputs. We are not concerned about the extended price, because the point-in-time data value&#8217;s data inputs (ie the unit price and number of units) are captured at that point in time, and we do not foresee (and will not support) any changes to the trivial calculation logic. If the calculation logic were ever to change, then I would see no real alternative but to store the extended price in the line item.</p>
<p>Could someone have pointed this out earlier? Yes. Did anyone do so? Yes. Did anyone listen? Unfortunately, no.</p>
<p>You see, that was &#8220;old world&#8221; thinking. We have a calculator! Why would we want to store the data value when we can always calculate it?</p>
<p>This post is long enough. If anyone ever reads it, I fully expect to be flamed. Just before you hit that comment button, however, please take the time to understand the point I am trying to make. I am not trying to discount modern best practices, or the tools that are currently in vogue. I actually pride myself as being pretty good at picking up new ideas and technology, and leading rather than following in their adoption. I am simply pointing out that, <strong>in my opinion</strong>, we need to apply a real-world filter over all the stuff that we are constantly being bombarded with, and realise that there are no absolutes — <strong>no</strong> rule can be applied blindly without some thought.</p>
<p>And sometimes, just sometimes, we older folks might know a thing or two that can be useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jimako.com/blog/2006/02/08/an-interesting-article-on-legacy-code/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Ruby</title>
		<link>http://www.jimako.com/blog/2005/08/02/ruby/</link>
		<comments>http://www.jimako.com/blog/2005/08/02/ruby/#comments</comments>
		<pubDate>Tue, 02 Aug 2005 11:23:00 +0000</pubDate>
		<dc:creator>jimako</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.jimako.com/blog/2005/08/02/ruby/</guid>
		<description><![CDATA[I&#8217;m going to get off the topic of the Apple for today &#8212; not that nothing has happened, but because in reading over the blog I sound like some Mac fanatic. Today, Chris, a good friend of mine, showed me his new HP laptop. Huge, 17&#8243; monster, very powerful, but battery life of about an [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m going to get off the topic of the Apple for today &#8212; not that nothing has happened, but because in reading over the blog I sound like some Mac fanatic. Today, Chris, a good friend of mine, showed me his new HP laptop. Huge, 17&#8243; monster, very powerful, but battery life of about an hour, and he couldn&#8217;t get it set up to access the network. Sigh!</p>
<p>But I said, no Apple today.</p>
<p>Over the past couple of weeks, I have been working on a particular Java application, and I needed to extract a whole bunch of data into flat files for a particular client requirement. Cutting a long story short, I ended up writing a set of scripts to generate an XML specification of an extract that is going to be used to control the total extract process, and this gave me a chance to try my hand at Ruby.</p>
<p>Now, I have heard a lot of good things about Ruby, but had not really used it before. Everyone I knew, who I respected as a programmer, and who had tried Ruby, raved about it. So, even though I knew Python, I made a point of nutting my way round Ruby.</p>
<p>Obviously, it took me a little while to get moving &#8212; there is always a bit to learn when starting with a new language. But I bought a PDF copy of the <a href="http://www.pragmaticprogrammer.com/titles/ruby/index.html">Pickaxe book</a> and zoomed through the highlights.  I have to say, I like Ruby a LOT.</p>
<p>Ruby is OO to the core. Everything is an object, and it has a remarkably convenient set of built-in functionality. I am not going to put together a tutorial on Ruby, at least not here, but here are a few examples to whet your appetite.</p>
<p>In Java, to define a class with a set of accessor methods, you do something like this:</p>
<p><code>    public class Dog<br />
private String name;<br />
public Dog(String name)<br />
{<br />
super();<br />
this.name = name;<br />
}<br />
public String getName()<br />
{<br />
return name;<br />
}<br />
public void setName(String value)<br />
{<br />
name = value;<br />
}<br />
}<br />
</code>Here&#8217;s the same thing in Ruby:</p>
<p><code>    class Dog<br />
attr_accessor :name<br />
def initialize(name)<br />
@name = name<br />
end<br />
end<br />
</code>Creating an instance in Java:</p>
<pre>Dog dog = new Dog("Rover");</pre>
<p>and in Ruby:</p>
<pre>dog = Dog.new("Rover")</pre>
<p>so the classes a pretty much equivalent, except that the Ruby one is (a) much shorter and (b) eliminates the need to write a whole lot of plumbing, no-brain code. Now I know that any modern IDE generates this boilerplate code for you, but it is still there and needs to be navigated and mentally discounted while you work on the stuff that DOES matter. In Ruby, the only code you write is what you need for the application &#8212; well, most of the time anyway <img src='http://www.jimako.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Here&#8217;s a really cool thing you can do in Ruby. When you call a function, as well as passing a number of arguments to it, you can also, optionally, attach a code block to it. A code block is delimited by either a the keywords do and end, or braces (they&#8217;re the same). Inside the called function, the code can determine whether a code block has been attached to it and, if so, essentially call that block any number of times. Here is an example:</p>
<p><code> def send(message)<br />
if block_given?<br />
yield "connecting"<br />
end<br />
connect(...)<br />
if block_given?<br />
yield "sending"<br />
end<br />
send(message)<br />
if block_given?<br />
yield "sent"<br />
end<br />
disconnect(...)<br />
if block_given?<br />
yield "done"<br />
end<br />
end<br />
</code>This is a dummy, skeletal procedure. We assume that it sends a message somewhere, and there are several steps &#8212; connecting, sending and disconnecting.</p>
<p>If you call it like this:</p>
<p><code>send("Hello world")</code></p>
<p>it just does its thing.  But you can optionally attach a code block like this:</p>
<p><code>send("Hello world") {|stage| puts "... now #{stage}" }</code></p>
<p>Let&#8217;s look at this line. The braces define a code block &#8212; the convention seems to be that short blocks like this use braces, while long, multi-line blocks use do/end. The two vertical bars delineate a parameter list; here, the parameter is called &#8220;stage&#8221;. The single line inside the code block uses puts to display a string. I&#8217;ll get to the string in a moment, but for now just accept that this results in the following printout:</p>
<p><code> ... now connecting<br />
... now sending<br />
... now sent<br />
... now done<br />
</code></p>
<p>The string that is displayed is delimited by double-quote characters, which means that the string is processed by Ruby. One of the effects of this is that the #{x} construct embedded in the string is replaced with the value of the variable x &#8212; this works everywhere, not just in these attached code blocks.</p>
<p>This mechanism is used to implement a really simple, generic and pervasive iterator-like mechanism. For example, to allow arrays to be iterated, the Array built-in class implements a method &#8220;each&#8221; which, you guessed it, takes a code block. So, to iterate over an array, you use this sort of code:</p>
<p><code>my_array.each {|element| puts element }</code></p>
<p>The beauty of this is that any object can exhibit this behaviour &#8212; just implement an &#8220;each&#8221; method that expects a code block, and &#8220;yield&#8221; once for each element your object contains. There is no need to be in any other way related to an array.</p>
<p>Which leads me to the topic of Duck Typing. This is the Ruby philosophy about object typing. While Ruby does implement a single-inheritance object hierarchy model, you can actually use unrelated object polymorphically as long as they implement a common subset of methods. The idea is that if it walks like a duck, and looks like a duck, and quacks like a duck, then it can be treated like a duck. Yes, this is NOT as bullet-proof as a strongly-typed language like Java, but in reality I don&#8217;t actually end up assigning a Debit object instance to an Animal object reference very often, and if I do, I will rely on my tests to pick that up. In return, I save myself a lot of unnecessary casting and fiddling in perfectly good code just to tell the compiler what I already know.</p>
<p>Ruby also has mix-ins, called modules. A module is a bit like an interface and a bit like an abstract class. Like an interface, a module aggregates a set of methods &#8212; these are included by classes that want to, regardless of their position in the object inheritance hierarchy. But unlike interfaces, modules have code in them too &#8212; implemented methods. These methods become part of any class that includes the module, and have access to class methods, exactly as if the code had been copied and pasted into that class. Also like interfaces, a single class can mix in, or include, any number of modules.</p>
<p>Like an abstract class, it implements some code, and through access to non-coded variables and methods, can set up an expectation on the classes that include it, but unlike an abstract class, the class that includes it does NOT need to descend from it (indeed, it can&#8217;t do so, because modules are not classes <em>per se</em>).</p>
<p>Very powerful indeed, and I don&#8217;t claim to fully appreciate all the implications of how these can be used, but just intuitively it seems to be really useful. And just plain cool.</p>
<p>Anyway, that&#8217;s more than enough for one post. Tomorrow is going to be a busy day. Toodles.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jimako.com/blog/2005/08/02/ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
