<?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>Pervasive Code &#187; java</title>
	<atom:link href="http://www.pervasivecode.com/blog/category/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.pervasivecode.com/blog</link>
	<description>Jamie Flournoy's Software Development Blog</description>
	<lastBuildDate>Mon, 26 Jul 2010 05:29:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Why mod_rails is great for light-duty Rails apps</title>
		<link>http://www.pervasivecode.com/blog/2008/04/14/why-mod_rails-is-a-really-good-thing-for-light-duty-ruby-on-rails/</link>
		<comments>http://www.pervasivecode.com/blog/2008/04/14/why-mod_rails-is-a-really-good-thing-for-light-duty-ruby-on-rails/#comments</comments>
		<pubDate>Mon, 14 Apr 2008 20:30:25 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[architecture]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[servers]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2008/04/14/why-mod_rails-is-a-really-good-thing-for-light-duty-ruby-on-rails/</guid>
		<description><![CDATA[The Ruby on Rails story is usually presented to the new developer as a wonderful break from tradition that makes a developer&#8217;s life so much better than the frameworks of the past. The clattering of skeletons in the closet you&#8217;re hearing? Well, that&#8217;s because it makes the sysadmin&#8217;s life much worse than PHP or Java. [...]]]></description>
			<content:encoded><![CDATA[<p>The Ruby on Rails story is usually presented to the new developer as a wonderful break from tradition that makes a developer&#8217;s life so much better than the frameworks of the past. The clattering of skeletons in the closet you&#8217;re hearing? Well, that&#8217;s because it makes the sysadmin&#8217;s life much worse than PHP or Java. That just improved on Friday, with the release of mod_rails. If you&#8217;re looking for a way to do shared (or low traffic) hosting of Rails applications, this is for you.<br />
<span id="more-67"></span><br />
With Java there&#8217;s this alien environment of CLASSPATHs and WARs and JARs and heap size limits, but once you get it up and running, developers can include libraries in with their application or the lib/ directory of the J2EE server, and the sysadmin doesn&#8217;t have to care. A Java developer is unlikely to ask you to build and install a pile of custom libraries.</p>
<p>With PHP it&#8217;s just another Apache module, but you might need to build a few extra libraries and maybe custom-compile Apache. Once you get it up and running, though, you don&#8217;t even need to restart the server when you deploy new code. It&#8217;s automatically updated.</p>
<p>With Ruby on Rails, it has been far uglier, especially as you go further back. The standard &#8220;Matz Ruby Interpreter&#8221; (MRI) doesn&#8217;t thread well and is quite remarkably slow, and Ruby + Rails in an MRI process use a lot lot lot of memory. So you don&#8217;t really want RoR running inside each Apache process. Folks used to use FastCGI (which should have died over a decade ago, but lingers on like a bad cold) but now use Mongrel, which is conceptually kind of like FastCGI, except that it actually works. Mongrel presents the application via HTTP, which is much easier to understand and integrate with other parts of your architecture (such as a load balancer) than FastCGI.</p>
<p>Whereas in J2EE you&#8217;d run one big honkin&#8217; JVM that used lots of memory to load up your code and data structures, but then ran many threads inside that one process, with the limitations of the MRI (green threads and many, many trips into non thread safe C code that requires the use of a &#8220;giant lock&#8221; that essentially makes it single-threaded), you run one process per thread. That&#8217;s like Apache+PHP or OpenSSH or many other unix programs that fork, right? Well, sort of. The issue is that your Ruby code is not seen by the kernel as something that all those forked processes can share; it sees the parsed Ruby code as data, and when the MRI&#8217;s garbage collector marks all those objects during garbage collection, it seems this data as being recently changed, differently for each forked process. So not only do you need 30-70MB or more per process, but very little of that is shared between processes. Ouch!</p>
<p>A second problem is that these processes take a while to start up and load the code, so it&#8217;s not reasonable to embed the Ruby interpreter in Apache when using Rails; the overhead is just too high. So the Mongrel solution is to pre-launch a bunch of interpreters, and have them just sit there until requests arrive. That&#8217;s pretty inefficient from a memory standpoint, but the latency when a request comes in is quite low since there is no initialization needed.</p>
<p>There have been a few interesting alternatives under development: JRuby is very promising, because it reuses all of the investment in VM development that Sun made over the last 10+ years for Java. At this point the JVM is pretty darn good at running many threads across multiple CPU cores, and at garbage collecting efficiently, among other things. These are key weaknesses of MRI, so running Rails on JRuby seems like a huge benefit. I haven&#8217;t tried it yet but I suspect that this will become one of the 2 or 3 most common ways to run Rails applications in the near future.</p>
<p>Another interesting alternative was <a href="http://izumi.plan99.net/blog/index.php/2007/07/29/making-ruby%E2%80%99s-garbage-collector-copy-on-write-friendly-part-3/">some experimental hacking to MRI&#8217;s garbage collector by Hongli Lai</a>, to store its working data separately from the objects being examined, so that preloaded Ruby code would remain shared by many forked interpreter processes over long periods of time. In other words, this is a potentially major memory use savings for Mongrel cluster users, which would in turn allow the sysadmin to run more Mongrels to service more simultaneous requests, or to bump up the database cache, or to increase the size of the running memcached instance. So, this would indirectly be a performance booster, and Ruby could really use that.</p>
<p>This experimentation apparently became <a href="http://www.rubyenterpriseedition.com/">Ruby Enterprise Edition</a>, which as of this writing is not available yet. But the other development coming from Hongli Lai&#8217;s new company, <a href="http://www.phusion.nl">Phusion</a>, is Passenger, a.k.a. <a href="http://www.modrails.com/">mod_rails</a>.</p>
<p>What&#8217;s interesting about mod_rails for the beginning Rails developer is that it is intended to make Rails hosting easier, particularly for shared hosting enviroments, which have been <a href="http://blog.dreamhost.com/2008/01/07/how-ruby-on-rails-could-be-much-better/">struggling</a> to offer Rails hosting in a uniform and cost-effective fashion. That means that in a short while (weeks?), shared hosting plans for fiddling around with Rails will become much cheaper and more widely available than they are now.</p>
<p>What&#8217;s interesting about mod_rails for the experienced sysadmin is that it mimics the min/max process pooling behavior of Apache, and addresses startup overhead in a clever way. It also serves static images via Apache automatically, eliminating the need for a separate block of mod_rewrite rules that must be crafted carefully so as to avoid conflicts with mod_proxy.</p>
<p>The <a href="http://www.modrails.com/documentation/Architectural%20overview.html">architectural overview</a> is comprehensive and well written, but here&#8217;s a summary: The Spawn Server makes a tree of child processes that preloads Ruby, Rails, and your application code for you, and then that is fork()ed to satisfy incoming requests. So the first request after startup incurs startup overhead (in my case, 5 seconds to load the Redmine login page) but subsequent requests get much better response time (.6s to reload that login page).</p>
<p>That seems like a lot of overhead in terms of big Ruby processes. Here&#8217;s what I measured just now: 97MB free with just Apache running (no spawn server yet). After the first page view, there was 36MB free, and four new processes: the Spawn Server taking a little over 6MB (rsize), the FrameworkSpawner taking 20MB (rsize), the ApplicationSpawner taking 34MB (rsize), and one Rails process taking 34MB (rsize).</p>
<p>The new &#8220;free&#8221; value is 36MB. The Buffers and used Swap values remained constant, with only 48KB of swap used. So that means that all four processes, which would seem to need 94MB to run (34+34+20+6), are actually overlapping enough that they are using only 61MB (97-36). And the ApplicationSpawner eventually terminates, leaving 36MB still free, which makes sense &#8211; it&#8217;s the process that fork()ed the Rails process, so they should ideally be overlapping nearly 100%. I&#8217;m surprised that this is so high; based on the GC experimentation that Hongli Lai did, I would have expected them not to overlap as much.</p>
<p>The idle Rails process exits eventually also, controlled by the <a href="http://www.modrails.com/documentation/Users%20guide.html#_configuring_passenger">RailsPoolIdleTime</a> setting. That saves memory but re-introduces the startup overhead. That leaves the FrameworkSpawner and the SpawnServer running, taking about 25MB of memory (quite close to the 20+6 shown by their rsize values).</p>
<p>Let&#8217;s compare this memory footprint to a Mongrel cluster. In a Mongrel cluster the processes start up and stay running forever, so the users are unlikely to incur much startup overhead at all, since it&#8217;s done long before they visit the application. Some amount of application-specific internal overhead is still an issue, though; that might include gradually filling an initially empty memcached, template compilation and/or caching, etc. As for memory, each Mongrel would need the same 34MB of memory, but there&#8217;s no SpawnServer, FrameworkServer, or ApplicationServer, so the extra 25MB of overhead would not be present with a Mongrel cluster.</p>
<p>That means that for a shared hosting setup where many low-traffic Rails sites may be used, or a multifunction server where serving one or more low-traffic Rails applications is just part of the job, mod_rails is a benefit. When the Rails app isn&#8217;t being used, it will exit and free up that memory for other processes. The starting and stopping of Rails with mod_rails is automatic and demand-based, so the sysadmin can tune it and forget about it.</p>
<p>On the other hand, a single dedicated server or VPS with a fixed amount of memory serving a single application would be better off with Mongrel, because of the lower memory overhead (25MB less), and the fact that the Mongrel processes start up before users need them and stay running indefinitely. Mongrel clusters could still potentially benefit from the Ruby Enterprise Edition&#8217;s garbage collector tweak if forking were used after preloading all of the code.</p>
<p>A single-purpose dedicated server running mod_rails could attain similar performance to a Mongrel cluster by simply setting the RailsPoolIdleTime value to a very high number. Then the Rails processes would hang around, and although you&#8217;d pay the price of a 25MB memory overhead, the startup overhead would only be paid by the very first visitor. However, you&#8217;d lose the main benefit of mod_rails, which is demand-based pool resizing, particularly if you&#8217;re running more than one application, Rails version, or Ruby interpreter version.</p>
<p>In short, I think mod_rails is very nice, and having actually used it I&#8217;m impressed with how polished it is for a 1.0 product. But if you&#8217;re already running a single application as a Mongrel cluster on a dedicated server, there&#8217;s no point in switching.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2008/04/14/why-mod_rails-is-a-really-good-thing-for-light-duty-ruby-on-rails/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Journalists, Developers Puzzled by Android SDK&#8217;s License</title>
		<link>http://www.pervasivecode.com/blog/2007/11/21/journalists-developers-puzzled-by-android-sdks-license/</link>
		<comments>http://www.pervasivecode.com/blog/2007/11/21/journalists-developers-puzzled-by-android-sdks-license/#comments</comments>
		<pubDate>Wed, 21 Nov 2007 19:55:08 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[strategy]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2007/11/21/journalists-developers-puzzled-by-android-sdks-license/</guid>
		<description><![CDATA[The Android mobile phone software platform from Google has some journalists and developers confused due to its license terms. The terms are open source, but not as free as the GNU Public License. That decision has people wondering what Google&#8217;s up to. I have a theory about why they did this.

Android is a full software [...]]]></description>
			<content:encoded><![CDATA[<p>The Android mobile phone software platform from Google has some journalists and developers confused due to its license terms. The terms are open source, but not as free as the GNU Public License. That decision has people wondering what Google&#8217;s up to. I have a theory about why they did this.</p>
<p><span id="more-51"></span></p>
<p>Android is a full software stack made up of many projects that exist separately from Android. The components of this stack are available under a variety of different terms: Linux is GPL&#8217;d; WebKit is LGPL&#8217;d; SQLite is in the public domain; FreeType is available via GPL or its own license. There are probably a dozen more little libraries and components that Android builds upon, all of which have licenses that need to be considered. It&#8217;s not possible for Google to just put a bow on the whole stack and say it all uses license X.</p>
<p>Google has released the Android SDK, which is the top layer, under the Apache license. According to the <a href="http://www.opensource.org/licenses/alphabetical">OSI list of approved open source licenses</a>, this is an open source license. And yet, <a href="http://www.wired.com/techbiz/it/news/2007/11/android_opensource/">the reaction to Android from open source advocates is negative</a>. Why? Well, the concern is that some implementation of Android will add proprietary code and/or remove standard code, fragmenting the platform. Since Google can&#8217;t rewrite the licenses of the underlying components of the stack, we&#8217;re really talking about fragmentation at the top layer of the stack.</p>
<p>The Apache license allows for parties who download the source code to alter it and then keep the altered source code secret, while distributing a derivative work. Contrast this with the &#8220;viral&#8221; GNU Public License, which obligates all parties who modify the source to either keep the modified software completely to themselves, or to distribute the source if they distribute a derivative work. Ignoring the case where a licensee simply keeps the derivative work to themselves, the GPL forces a web of innovation and collective advancement, whereas the Apache license encourages a central publishing model, where innovations are kept private and used for competitive gain.</p>
<p>Thus, Android applications designed to be compatible with Google&#8217;s platform could be made incompatible with a particular device, by a handset vendor who removes core Android APIs and replaces them with their own closed source alternative. This might seem like a paranoid fantasy of a small clan of open source zealots, but it&#8217;s not. This is the same tactic that Apple has successfully used to keep Mac OS X closed. Mac OS X rests upon a large amount of open-source code (some of which is also part of what Android is built upon), while requiring developers to code to Apple&#8217;s proprietary Cocoa APIs in order to make Mac apps. You can install Linux on a Mac, but then you lose the ability to run Mac OS X apps. You can build generic Unix applications on a Mac, but they look quite different from a standard Mac app, and lose a lot of Mac-specific functionality. Apple chose to make this possible, but compare this with the iPhone, which uses much of the same software underneath, but (as of this writing) cannot run a generic Unix app because Apple doesn&#8217;t want you to do this.</p>
<p>This same sort of situation is possible with Android under this license. Company X grabs the Android sources, dumps a few key APIs (maybe the GUI, network, and process management ones) and suddenly they have their own incompatible platform that can run on the same hardware but can&#8217;t share apps with the mainstream. Dump phones on the market (subsidized by monthly fees, as usual) and fund a few key apps (MP3 player, movie player, email/SMS, web browser) and users are stuck with that vendor&#8217;s offering, just like they are now. And this is just how telcos and media companies, both of whom are desperately trying to keep hardware and software platforms closed, think. The more closed a platform is, the more secure they feel about their profits, and the more willing they are to invest in it.</p>
<p>The only charitable explanation I can think of for why Google chose this license is the Apple explanation.</p>
<p>If Google were really pandering to the existing mobile carrier crowd, they could simply have released nothing, because another closed platform to build phones with and to write apps for is pointless. There are plenty of existing <a href="http://www.scripting.com/davenet/2001/07/06/theMicroChannelArchitectur.html">trunks to be locked in</a> already. We don&#8217;t need somebody else to slap together a Linux distro for phones with a closed GUI on it. You can to go LinuxWorld Expo and probably find two dozen companies doing exactly that, and none of them is particularly successful. Google is too smart to add itself to this list of flops. It makes no strategic sense.</p>
<p>More likely, I think, is that Google intends to be Company X in my above scenario, putting themselves in the role of Apple by making an &#8220;Android Plus&#8221; premium platform that they put on the handsets they&#8217;re pushing. In this scenario, you can write your own apps to the reference platform and they&#8217;ll run on Google&#8217;s favored phone, but Google can still reserve the right to put all sorts of funky stuff on their phones without documenting it or giving developers or users any rights to it, and more importantly, without having to open source their special components so that non-Google devices could use them.</p>
<p>Sure, this is a charitable interpretation. They might just have screwed up royally, buying a company (Android) that wasn&#8217;t anything special and releasing something that no one other than journalists will pay attention to. But given that Google is betting $4.6 billion on the 700MHz spectrum auction in the U.S., I&#8217;m reluctant to simply write Android off as a &#8220;hail mary&#8221; acquisition.</p>
<p>There must be a larger strategy here, and I suspect it&#8217;s Google putting itself in the shoes of mobile carrier, handset OS maker, and service provider. Somebody else manufactures the handsets, of course, but Google owns and operates the whole experience from end to end other than that. You buy a Google device, pay a monthly Google subscription fee, your bits travel over a Google global network of wireless towers and a wired backbone, and you run apps on your Google phone that interact with Google back-end services. It&#8217;s a carbon copy of Apple&#8217;s iPhone/iTunes strategy, without AT&#038;T in the picture, and with third party apps allowed on the phone, as long as they work on the already-published Android SDK. All Google has to do is to make a decent looking device and be less customer-hostile than existing U.S. mobile providers, and they&#8217;ll do well.</p>
<p>In this light, the partnering talks with existing mobile carriers is puzzling. It&#8217;s possible that they&#8217;re pitching a strategy that removes the burden of application development from mobile carriers, allowing them to be the billing companies that they really are, and putting Google in the position of being the provider of content and software. The lukewarm responses from these carriers is predictable; for the carriers to be involved as just bandwidth providers and customer billing service providers, there would have to be a careful negotiation of revenue sharing, or else the carriers will simply continue on their current, very lucrative course.</p>
<p>If they are planning to become a carrier themselves, then nothing can actually begin to happen until January, when the 700MHz spectrum auction actually takes place. There&#8217;s a closer <a href="http://arstechnica.com/news.ars/post/20071116-its-official-google-planning-700mhz-bid.html">December 3rd</a> deadline for Google to reveal their plans. At that point we&#8217;ll know what they&#8217;re up to, assuming they&#8217;re actually able to buy the spectrum that would make it possible. Alternatively, this spectrum purchase could be a bargaining chip on Google&#8217;s part, which they do not intend to directly utilize themselves. Google would provide the spectrum, the handsets, the OS, the apps, and the services, and the carrier partners would provide the towers, the maintenance staff, sales, and billing.</p>
<p>Given all this, it makes little sense for Google to GPL the Android platform. They need to own it so that they can assure a prospective carrier partner that they will be the ones whose phones are being used by customers, in order to share revenues. If they were to open up the handset market entirely, the carriers would block any new entrants and Android based phones would be doomed.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2007/11/21/journalists-developers-puzzled-by-android-sdks-license/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Google Gives J2ME the Finger, but Still Needs a Carrier Partner</title>
		<link>http://www.pervasivecode.com/blog/2007/11/12/google-gives-j2me-the-finger-but-still-needs-a-carrier-partner/</link>
		<comments>http://www.pervasivecode.com/blog/2007/11/12/google-gives-j2me-the-finger-but-still-needs-a-carrier-partner/#comments</comments>
		<pubDate>Tue, 13 Nov 2007 00:53:52 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[strategy]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2007/11/12/google-gives-j2me-the-finger-but-still-needs-a-carrier-partner/</guid>
		<description><![CDATA[It turns out that as The New York Times says, Google is not building a phone. They&#8217;ve built (bought, really) a phone platform called Android. It&#8217;s Java on Linux, and it&#8217;s open source, but notably it is not J2ME based. Reportedly it will run J2ME apps, but the SDK makes the Android API look more [...]]]></description>
			<content:encoded><![CDATA[<p>It turns out that <a href="http://www.nytimes.com/2007/11/06/technology/06google.html?_r=1&#038;oref=slogin">as The New York Times says</a>, Google is not building a phone. They&#8217;ve built (bought, really) <a href="http://code.google.com/android/what-is-android.html">a phone platform called Android</a>. It&#8217;s Java on Linux, and it&#8217;s open source, but notably it is <i>not J2ME based</i>. Reportedly it will run J2ME apps, but the SDK makes the Android API look more like the BlackBerry&#8217;s Java API than J2ME. It&#8217;s a full featured API that isn&#8217;t a <a href="/blog/2007/08/19/j2me-write-once-be-disappointed-everywhere/">least common denominator of all possible mobile devices</a>.<br />
<span id="more-49"></span><br />
By building on top of and bundling Linux, instead of an assortment of phone OS&#8217;s with varying feature sets, developers can be assured that the low-level feature set across handsets will be constant, by which I mean that threads will work and <a href="http://code.google.com/android/intro/lifecycle.html">multitasking will always be available</a>.  Given that some J2ME implementations and some non-J2ME mobile Java runtimes lack threads, and many phones lack multitasking, this will make writing sophisticated apps for Android far easier.</p>
<p>Android is a huge win for developers. The SDK is already available for Windows, Mac-on-Intel, and Linux-on-i386, and it uses technologies that are already mainstream. Based on my <a href="/blog/2007/11/12/evaluating-future-web-application-technologies/">previous post</a> I am curious about whether Rhino, Jython, and JRuby will work on the Dalvik VM, but I have no specific reason to believe they won&#8217;t. This is exactly the sort of thing I was talking about when I said that layering on top of the JVM or .NET DLR would ease portability; the Dalvik JVM means that you can likely write a Hello World in any language that can compile down to Java bytecode and run it immediately.</p>
<p>OK, so it&#8217;s great for developers. So what? Developers don&#8217;t control the mobile market; carriers do. Handset makers would probably love to use Linux instead of paying a per-handset license for a closed phone OS; PalmSource/ACCESS and Palm, Inc. have already said they will move in that direction (though Palm, Inc is <a href="http://en.wikipedia.org/wiki/Palm_OS#Modernization">creating some confusion</a> about whose Linux-based Garnet-compatible runtime will end up on future devices bearing the Palm OS name). But why would carriers want this?</p>
<p>It&#8217;s possible that carriers would like to see their value-added apps run on many different handsets without the cost of developing them separately for each handset they sell. Handset makers and mobile OS vendors clearly are making some money from consulting to carriers on these projects (somebody has to tell Sprint how to write the PictureMail app), so actually in this area handset makers would stand to lose money.</p>
<p>What carriers probably would like less about Android is that it would allow Google to bypass the carriers&#8217; value added services and build their own ecosystem of mobile apps for Android-based handsets, which is exactly the point of Android. Who gets the value added dollars from customers? That&#8217;s what this is all about. Google is battling ISPs regarding Net Neutrality, and it comes back to the same thing. If a customer is going to pay for a service delivered from a server across a network onto an endpoint, there are at least four parties that want to get paid, and who view the division of revenue as a zero-sum game.</p>
<p>The <b>server folks</b> (Google, Yahoo, Microsoft, Apple, etc.) want to charge you for the subscription to their applications or for individual chunks of content. That charge may take the form of just showing you ads. Then they want to pay a flat rate for the bandwidth across the network to get to you, and will minimize that cost using the massive content delivery networks which they already have in place.</p>
<p>The <b>network folks</b> want to put a toll booth on that network that charges either the end-user or server folks (or both) for transferring paid content, or one that penalizes the end-user (bandwidth shaping) for buying a cheap connectivity plan and then trying to use it for transferring large media files from the server guys. The network folks also still think they can force the Internet to look like Cable TV, by putting up barriers to keep their users from using anybody&#8217;s services but their own, so their ISP customers also become their content customers.</p>
<p>The <b>handset OS folks</b> want to be paid to write those apps for the server folks and the network folks who want to also be server folks. They want to encourage developers (ISVs, or server or network big guys) to focus on their platform, thereby making it more attractive to users, thereby making it more valuable so they can charge a larger amount from each phone sold. These folks are directly in competition with Android, whether Google intends to attack them or not.</p>
<p>The <b>handset manufacturers</b> want to minimize the price of their phone (a free OS that supports tons of hardware components that they might use is a good start) and maximize the number of apps that will run on their phone. They should love this, although the most successful high-end handset makers who also use closed OS&#8217;s (basically every major handset maker) will not like it as much as the underdogs who sell tons of cheap phones. LG and Samsung say &#8220;hooray&#8221; while Motorola, RIM, Palm, Sony, and Nokia say &#8220;boo-hoo.&#8221; Their investment in special fancy phones and fancy apps for their chosen OS is undermined by the prospect of commodified hardware with carrier- or user-installable third party apps.</p>
<p>Users should be happy as well. Developers, as I mentioned, should love this platform, so users should benefit both from more apps and cheaper handsets, and probably also from more service offerings that will work with their handset.</p>
<p>The problem with all this is that as I mentioned in <a href="/blog/2007/11/12/technical-architecture-is-a-form-of-investing/">Technical Architecture is a Form of Investing</a>, just because developers like something doesn&#8217;t mean it will win. If Google&#8217;s aim is to open up and commodify the handset market, they will have to fight the folks that are trying to keep the handset market closed and fragmented. That group includes all of the major U.S. mobile vendors, and the companies who make handset OS&#8217;s. The latter group is weak and easily conquered, with the exception of Microsoft; in this space, though, Microsoft is not strong enough to fight Linux and Java. The former group is extremely powerful and will not simply sell handsets that eliminate their chief source of revenue (proprietary value-added services that show up on your mobile phone bill). Nevertheless, these value-added offerings are generally awful and absurdly overpriced, so there is quite a lot of opportunity if someone can break through the carriers&#8217; stranglehold.</p>
<p>The strategy that Google must follow is to convince an underdog mobile carrier to market an Android-based handset to consumers. Google has little strategic advantage to gain from replacing handset OS makers; they are a service and as such need to prevent the network guys from erecting that toll booth in front of Google&#8217;s services. To do that they will need to bypass the network guys, and a phone OS isn&#8217;t going to do that. Even a handset offering won&#8217;t be sufficient; look at Apple&#8217;s iPhone bricking debacle for evidence of that. The mobile carriers control the handset makers in the U.S., and Apple has had to learn that the hard way, screwing over their customers who dared to choose another carrier than Apple&#8217;s partner. You can bet that Apple wasn&#8217;t the driving force behind that decision.</p>
<p>So Google will have to go all the way to partnering with or acquiring a carrier who is currently an underdog and who needs this offering in order to win customers away from the big guys. Alternatively (and less likely, due to the red tape involved) Google will have to become or spin off that underdog carrier themselves as a new carrier.</p>
<p>So, look for the second shoe to drop: not who is going to build a &#8220;GooPhone&#8221;, but who is going to offer you a mobile plan that lets you use one without placing severe restrictions on what you can run on it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2007/11/12/google-gives-j2me-the-finger-but-still-needs-a-carrier-partner/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Evaluating Future Web Application Technologies</title>
		<link>http://www.pervasivecode.com/blog/2007/11/12/evaluating-future-web-application-technologies/</link>
		<comments>http://www.pervasivecode.com/blog/2007/11/12/evaluating-future-web-application-technologies/#comments</comments>
		<pubDate>Mon, 12 Nov 2007 23:22:30 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[outsourcing]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[strategy]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2007/11/12/evaluating-future-web-application-technologies/</guid>
		<description><![CDATA[Technical Architecture is a Form of Investing. I&#8217;m reminded of this sort of thinking because of recent news from RubyConf 2007.

First, IronRuby joins Ruby.NET in providing a Ruby runtime on .NET. They&#8217;re at different stages of completeness, and building on different .NET runtimes (DLR vs. the regular CLR), but the important point is that Microsoft [...]]]></description>
			<content:encoded><![CDATA[<p>Technical Architecture is a Form of Investing. I&#8217;m reminded of this sort of thinking because of recent news from <a href="http://www.rubyconf.org/">RubyConf</a> 2007.<br />
<span id="more-48"></span><br />
First, <a href="http://www.ironruby.net/">IronRuby</a> joins <a href="http://plas.fit.qut.edu.au/Ruby.NET/">Ruby.NET</a> in providing a Ruby runtime on .NET. They&#8217;re at different stages of completeness, and building on different .NET runtimes (<a href="http://blogs.msdn.com/hugunin/archive/2007/04/30/a-dynamic-language-runtime-dlr.aspx">DLR</a> vs. the regular CLR), but the important point is that Microsoft is investing in dynamic languages. Is it ready for production today? Probably not. But keep an eye on Ruby, Python, and JavaScript if you&#8217;re a .NET developer.</p>
<p>Second, <a href="http://docs.codehaus.org/display/JRUBY/2007/11/02/JRuby+1.1b1+Released">JRuby 1.1b1</a> has been released and as expected is considerably faster (see <a href="http://headius.blogspot.com/2007/11/top-five-questions-i-get-asked.html">item #5 in this link</a>) than the standard &#8220;MRI&#8221; runtime. JRuby joins <a href="http://www.jython.org/">Jython</a> and <a href="http://www.mozilla.org/rhino/">Rhino</a> in providing a JVM-based runtime for a dynamic language, with features designed to help developers mix and match the dynamic language code with Java code.</p>
<p>See the trend here? Python, Ruby, and JavaScript are emerging as the dynamic languages of the future for .NET and Java developers.</p>
<p>The hard work done by Sun and Microsoft to make their VMs work well is being leveraged by the next wave of languages. Threads, high performance I/O, memory management, and portability are all features that are quite expensive to get right, and the .NET and Java platforms have pretty much achieved that at this point. (Piggybacking newer, higher-level languages on these mature runtimes means that you get a mature new language runtime faster than if each language&#8217;s runtime were built from scratch and painstakingly debugged in isolation from the others.)</p>
<p>There are still some hurdles (performance, type safety fears, lack of mass market acceptance, ECMAScript 4 standardization and adoption, etc.), but in 2 or 3 years, things are going to change dramatically in the web application development world. The seeds of this change are already sown, and it&#8217;s just a matter of time. Threads, SQL, OOP, and garbage collection are all features of web application architectures that were initially controversial, but have now met with general acceptance. Dynamic languages are clearly the next step.</p>
<p>Obviously, Java and C# are far from dead, and in 10 years people will still be coding in Java and C#, because as with other languages like C and assembly, the newest and highest-level language isn&#8217;t automatically right for every project. But if you&#8217;re building web applications, most of what your code does falls into the categories of string manipulation, collection operations, or file and socket I/O. Image processing, crypto, full text search, and other CPU-heavy, byte-twiddling features may be part of your application, but you&#8217;re not writing the image scaler, RC4 cipher, or inverted index yourself; those are done in a library, probably written in C, and you&#8217;re just calling it. So your needs are likely to be similar to the sweet spot of dynamic languages: maximum expressivity and the fancy features to let you write clever code, making you productive and making the code as clean and elegant as possible. In other words, they put developer productivity first (lower labor cost and shorter development schedules) at the expense of runtime performance. Since hardware gets cheaper over time but <a href="http://www.laputan.org/mud/mud.html#Forces">code gets uglier over time</a>, this is probably the right choice to make for most web application projects.</p>
<p>Another interesting benefit of layering instead of starting over is that the integration between dynamic languages and Java or CLR languages is much nicer than managed vs. unmanaged code in .NET or, even worse, JNI in Java. That is, it won&#8217;t be a bloody mess to mix and match code, from a technical feasibility standpoint. This matters, because <a href="http://chadfowler.com/2006/12/27/the-big-rewrite">The Big Rewrite</a> is among the <a href="http://www.joelonsoftware.com/articles/fog0000000069.html">Things You Should Never Do</a>. But little bitty rewrites are fine, especially if you have a thorough test suite to help you avoid breaking things. (By the way, dynamic languages are <i>great</i> for writing automated tests.)</p>
<p>Which of these three (JavaScript, Python, or Ruby) is going to be dominant 5 years from now? I don&#8217;t think any of them will be. The dynamic language community is fragmented, and the various vendors and big sponsors of these three languages are fairly entrenched already. Microsoft is investing in all three; Google has standardized on Python and JavaScript to the exclusion of Ruby; Sun has hired the JRuby team; Mozilla is heavily invested in JavaScript; Adobe supports JavaScript in AIR but not Ruby or Python, etc. </p>
<p>In fact, if you encapsulated the glue code sufficiently well, you could mix and match JavaScript, Python, and Ruby in your application, and port your hideous hydra between the JVM and .NET. You would be wasting a lot of effort since the three languages are largely similar, but you could do it. Alternatively, you could create a portability layer between the DLR and the JVM a la WxWindows, and write-once-debug-everywhere in a more productive language than Java.</p>
<p>These are all repugnant ideas, but only because as I write this and as you read this, we probably realize that to attempt this today would be a huge task. But what about in 2010? Probably not so gross. What about an application that could be executed on Silverlight, AIR, Firefox, SWT, and Mono, unmodified? How about a mobile app that runs on smartphones regardless of the runtime (.NET vs. J2SE)? Not gross at all, and not unthinkable if your app is written in JavaScript using some kind of portability layer that doesn&#8217;t exist yet.</p>
<p>In the longer term, JavaScript (a.k.a. ECMAScript 4) is likely to become extremely popular. As far as I know it&#8217;s not quite a perfect fit for Steve Yegge&#8217;s <a href="http://steve-yegge.blogspot.com/2007/02/next-big-language.html">The Next Big Language</a>, but it&#8217;s the closest thing there is, and it has two critical advantages over Ruby and Python that will make it successful: C-family syntax (which makes development tools cheaper to build) and effectively unanimous buy-in from vendors and developers.</p>
<p>So, what about the other dynamic languages that people are using in large numbers today? What&#8217;s going to happen to ActionScript, CFScript, PHP, and VB?</p>
<p>ActionScript and CFScript are pretty close to JavaScript by design; I&#8217;ve read that ActionScript 3 is actually compliant with the ECMAScript 4 draft specfication. It&#8217;s pretty clear that Adobe is betting on JavaScript. In the near future (2 or 3 years) I predict that Adobe will rev its products and support ECMAScript 4 across the board.</p>
<p>PHP and VB.NET/VBScript will hang around for a long time because they&#8217;re approachable and already very popular, but they&#8217;ve already peaked, and will steadily decline as developers switch to C# (on the .NET side) and Rails (on the Linux side), and then JavaScript as soon as a serious web app framework and an ISP-friendly runtime exist. Microsoft will keep investing in VB to keep customers happy; Yahoo will keep investing in PHP because it is so heavily invested in PHP already; new developers will find PHP to be an easy starting point for light duty web development, with tons of documentation and free applications that they can download and hack. But PHP will not inherit the kingdom from C# or Java, and the languages which do achieve mainstream success after C# and Java will do everything that PHP does language-wise, and the market momentum around those languages will make them better than PHP at what PHP does. Developers will ask themselves why they would write the client side and server side in two different languages, especially when the server-side language is more expressive and has better portability and libraries. That&#8217;s not true yet, but it will be in a couple of years. In 5 years or so PHP and VBScript will go the way of Perl CGIs: still used, but by a community a tenth of the size it is today.</p>
<p>What about the new Java-based dynamic language, Groovy? Groovy is interesting, but it&#8217;s too late. The Java mainstream of vendors and developers only recently managed to convince the world of &#8220;serious&#8221; C++ developers that automatic garbage collection and JIT compiled bytecodes can actually work in a high traffic context. The next battle, to promote the dynamic language features that Java lacks but which Groovy brings, will take years to fight. Once a developer makes a decision to not use standard Java, Groovy is on a more or less level playing field with the JVM-hosted versions of Python, JavaScript, and Ruby, but each of those languages has far greater adoption than Groovy, and each of them has greater opportunity for leverage on other runtimes than Groovy. For a Java developer, once the door is opened to other languages, the only advantage Groovy has is that its syntax is familiar. Compare this to JavaScript which web developers also need to know how to use; why learn a third language (Groovy) in addition to Java and JavaScript? Over time the simplicity of coding and debugging in JavaScript on client and server, together with dynamic-language productivity, will overcome the momentum of the Java standard, and web developers using server-side Java now will gradually replace it with JavaScript on the JVM. Conservative attitudes in the mainstream Java community (including Fortune 500 companies and the many offshore development firms that write code for them) will make this take quite a while &#8211; probably 5 years before JavaScript becomes a common part of the architectures that currently use J2EE, and 10 years before Java goes the way of COBOL (maintained forever but not used for new projects).</p>
<p>So in conclusion, keeping an eye on the future value of a technology, including who&#8217;s investing in it and who&#8217;s talking about investing in it, is critical to making your own investments today. In five years you&#8217;re not going to be using the same technology stack that you are today, and your project&#8217;s success and your own salary will be tied in large part to how well you invested today.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2007/11/12/evaluating-future-web-application-technologies/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ActiveRecord: the Visual Basic of Object Relational Mappers</title>
		<link>http://www.pervasivecode.com/blog/2007/10/04/activerecord-the-visual-basic-of-object-relational-mappers/</link>
		<comments>http://www.pervasivecode.com/blog/2007/10/04/activerecord-the-visual-basic-of-object-relational-mappers/#comments</comments>
		<pubDate>Fri, 05 Oct 2007 02:07:53 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[architecture]]></category>
		<category><![CDATA[articles]]></category>
		<category><![CDATA[databases]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2007/10/04/activerecord-the-visual-basic-of-object-relational-mappers/</guid>
		<description><![CDATA[I&#8217;ve been working with Ruby on Rails intensively for several months, and I&#8217;ve finally found a place where Rails can&#8217;t readily be extended to do what I want. It&#8217;s ActiveRecord, which is probably the most controversial part of Rails.
I&#8217;m reminded of a James Gosling quote disparaging Microsoft tools, particularly Visual Basic: &#8220;The easy stuff is [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working with Ruby on Rails intensively for several months, and I&#8217;ve finally found a place where Rails can&#8217;t readily be extended to do what I want. It&#8217;s ActiveRecord, which is probably the most controversial part of Rails.</p>
<p>I&#8217;m reminded of a <a href="http://en.wikipedia.org/wiki/James_Gosling">James Gosling</a> quote disparaging Microsoft tools, particularly Visual Basic: &#8220;The easy stuff is easy, but the hard stuff is impossible.&#8221; There&#8217;s a parallel between VB and Rails in this instance, in that <em>if you only let yourself use the high level tools</em>, the hard stuff is impossible, but the designers specifically tell you to do the hard stuff using a lower level toolset. The controversy that surrounds &#8220;X can&#8217;t do everything, therefore it sucks&#8221; should really be focusing on the feasibility of going through that trapdoor to do things &#8220;the hard way&#8221;. This is what <a href="http://en.wikipedia.org/wiki/Borland_Delphi">Delphi</a> did, which is why so many folks chose it over VB; it made the hard stuff easier.</p>
<p><span id="more-46"></span></p>
<p>Here&#8217;s the task I need to accomplish, for which ActiveRecord is not well suited: complex queries involving SQL functions and multiple-table joins. I want to join a few tables together, order by a SQL function, include with each result row the result of a SQL function that operates on each row, and have all that come back as a graph of high-level objects.</p>
<p>Despite my attempts to use plugins, extend and/or fix bugs in those plugins, and to dig through the ActiveRecord source to figure out what the documentation won&#8217;t tell me, I was unable to get it to work. Most of the parts of what I wanted was possible: acts_as_tsearch cleverly weaves SQL functions into a high-level ActiveRecord::Base.find calls; paginating_find provides a very convenient pagination API on top of ActiveRecord::Base.find, and ActiveRecord includes some clever association tricks such as automatic many-to-many relationships (has_and_belongs_to_many), eager loading of associated records using a join (via the :include option to ActiveRecord::Base.find), and a fairly low-level :joins option that lets you add tables to a &#8216;find&#8217; query which can be used in your :conditions. Problem is, they don&#8217;t all work together in a fancy way.</p>
<p>Really, the issue in this case is related to the design choices that went into ActiveRecord.</p>
<p>Some ORMs (object-relational mappers) are designed in a modular fashion: there is a part that helps you describe the relationships between your model objects, a part that helps you construct queries, and a part that does the storage and retrieval. Sometimes there&#8217;s another part that uses your description of object relationships to create an empty database with the appropriate data model, or that looks at an existing database and creates an object model that matches it. Sometimes there&#8217;s an import/export tool for bulk data loading or dumping as well.</p>
<p>ActiveRecord has the first three functions integrated (which has benefits and drawbacks compared to a more modular approach), has a very isolated schema manipulation module, and has a somewhat isolated data loader tool.</p>
<p>The relationships are explicitly declared in source code using associations: has_one, has_many, belongs_to, and has_and_belongs_to_many. These are pretty fancy and provide some convenience features that make the associations appear as object collections, such that changing the collection and saving it turns into insert/delete/update activity in the database.</p>
<p>Query construction is basically tied to the objects themselves, in a way that greatly simplifies star-join queries, but which handles only the simplest joins across multiple tables, and is barely able to handle self-referential joins at all. So, you can easily load an object (or group of similar objects) and associated objects, but OLAP-style queries (&#8221;what are the top 5 states where customers are located who have bought classical CDs within 2 weeks of their release using American Express and had them shipped as gifts via UPS 3-day Select?&#8221;) are impossible. Oddly, views, functions, and stored procedures could bridge the gap between real-world data models and ActiveRecord&#8217;s limited set of association types, but they are not supported either.</p>
<p>The storage and retrieval code is inseparable from the query code, and so it is not possible to examine and modify the final SQL before it is executed, nor is it possible to provide an arbitrary query and have the results be parsed into an object graph based on the associations you have defined. The code that would allow these features appears to exist and be sufficiently well designed to allow this with a fairly small amount of changes to ActiveRecord. However, it is currently (as of Rails 1.2.3, which is the current release) not part of the documented API and is declared private.</p>
<p>There is a limited facility for constructing simple objects from arbitrary SQL, in find_by_sql. This loses essentially all of the high level functionality of the find method; most notably, it isn&#8217;t possible to use find_by_sql results to instantiate an object graph, rather than a flat array of objects (similar to the eager loading feature in the regular find method).</p>
<p>ActiveRecord has fairly good high-level schema creation functionality (&#8221;migrations&#8221;). Though it lacks concepts for all but the basic database objects, support can be added for <a href="http://www.redhillonrails.org/#foreign_key_migrations">foreign key constraints</a> (I kid you not, they aren&#8217;t supported by Rails itself!) and <a href="http://activewarehouse.rubyforge.org/rails_sql_views/">views</a>. There&#8217;s also a simple way to execute arbitrary SQL. Migrations aren&#8217;t technically that amazing, but rather they&#8217;re a helpful organizational approach to what can be a really hairy problem: defining a schema and then applying changes to live databases while keeping track of what changes you&#8217;ve already applied.</p>
<p>Finally, there is a test data loading facility called Fixtures. The common opinion of Fixtures seems to be that they are broken by design and should be avoided. The main issue I&#8217;ve found with them is that the implementation ignores the kind of database design elements that any book on SQL would recommend, such as foreign keys and check constraints. I managed to circumvent this with a combination of a plugin and some customization, described in detail in my previous post, <a href="http://www.pervasivecode.com/blog/2007/08/02/rails-fixtures-the-test-db-and-testunit/">Rails, Fixtures, the Test DB, and Test::Unit</a>. With those changes, all test fixture data is preloaded in the right order (so constraints aren&#8217;t violated) before any tests run, and any data alterations within tests are rolled back automatically by Rails.</p>
<p>A secondary issue with Fixtures is that they go directly from YAML text files to SQL INSERT statements, bypassing the ActiveRecord Model classes. ActiveRecord does pretty much rule out any fancy mapping between database tables and objects, so that&#8217;s not a problem, but this model-skipping fixture loading implementation means that any code in your model object (validations, before_save filters, etc.) <i>will not be executed</i> when loading fixtures. So fixtures do not work well with the otherwise pervasive Rails design rule of &#8220;put all the intelligence in the application&#8221;.</p>
<p>Still, despite the commonly-held disdain for using fixtures at all, I find that they can be tamed. In fact I&#8217;ve even created a base data facility for loading the fundamental data set that needs to be in the live database (e.g. initial admin user info). My approach is basically to alter fixture behavior to treat it as essentially a bulk data loading tool, and to do the extra housekeeping after loading to make up for the fact that the ActiveRecord model code was bypassed.</p>
<p>As far as I know, there is no bulk data dumping functionality in Rails.</p>
<p>So, to summarize, of the five main ORM features, here&#8217;s how ActiveRecord stacks up:</p>
<ol>
<li><b>Describing Relationships</b>: Easy to understand and use, with lots of slick functionality</li>
<li><b>Querying</b>: Easy to understand and use, but limited to simple join structures, and not possible to customize query building or rewrite SQL before execution</li>
<li><b>Storage and Retrieval</b>: Very easy to use, but only within the limits of the query builder&#8217;s features</li>
<li><b>Schema manipulation</b>: Easy to understand and use; limited in functionality but readily extensible; solid third party plugins are available for missing schema objects</li>
<li><b>Bulk Loading and Dumping</b>: Loading is badly designed and implemented, but fixable with some effort; dumping is not offered</li>
</ol>
<p>Okay, so it definitely makes the easy stuff easy. But what about the rest?</p>
<p>As I observed before, ActiveRecord is not designed as a set of modules that you use to assemble a solution that fits your needs. That&#8217;s more of the Java approach to design, and it trades flexibility for convenience. It can be a major pain to assemble a working system out of all of those abstract Java APIs, which are sometimes so comically over-<a href="http://en.wikipedia.org/wiki/Design_Patterns">pattern</a>ized as to draw mockery such as the hilarious &#8220;Are Javalanders Happy?&#8221; code snippet from <a href="http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html">Execution in the Kingdom of Nouns</a>.  Rails makes the opposite trade-off: sacrifice flexibility and gain a very approachable API.</p>
<p>Unfortunately, the Java approach (too abstract to readily use, but extremely flexible) is easily wrapped with a simpler, more convenient, less customizable API. The Rails approach isn&#8217;t internally componentized (have a look at ActiveRecord&#8217;s activerecord/base.rb source file in its 2,165-line glory, almost all of which is one class), so if you want to fiddle with its internal behavior, you can&#8217;t. So with Rails, it&#8217;s all or nothing: high level slickness for simple requirements, or hand-written SQL and hand-coded results mapping for your complex requirements.</p>
<p>As I said at the beginning, though, the key question is not how comprehensive the high level feature set is. More important is the question of how painful things are when you drop down to a lower level for a greater degree of control.</p>
<p>It would be nice if there were a middle level of complexity, between the high-level &#8216;find&#8217; method and &#8216;has_xxx&#8217; associations, and raw SQL. There isn&#8217;t. I think that the reason there isn&#8217;t one is that there is still a persistent belief among many Rails core team members and community members that databases should be stupid: just a persistent hash. Once upon a time I worked that way myself: I didn&#8217;t have access to or skill with a SQL RDBMS, and so I solved all of my persistence problems with DBM files, which (using Perl&#8217;s Tie::Hash class) are conceptually just persistent hashtables. miniSQL was little more than a SQL query parser on top of that sort of storage engine, and MySQL originally was pretty similar. But big databases have all sorts of useful features that address complicated persistence requirements in a fairly elegant way.</p>
<p>Given that Ruby fans like the idea of domain specific languages, which let you work in a super high level language customized to the problem domain, it&#8217;s surprising that Rails groupthink is that SQL is bad. It&#8217;s actually a very high level language, and allows a well written database to do some pretty amazing optimization on the fly because it provides a strong layer of abstraction between what you requested and how the storage engine provides it.</p>
<p>No, it&#8217;s not dynamic, nor is it pure relational perfection, but it&#8217;s pretty darn good. Pre- and post-event validations and arbitrary callbacks to user-specified code, functions providing behavior on top of data&#8230; these are all things that Ruby and Rails fans hold in high regard when provided by Ruby and Rails, but which are considered a bad idea at the database layer. As I discussed at length in <a href="http://www.pervasivecode.com/blog/2007/08/02/rails-and-the-notion-of-stupid-databases-being-a-good-idea/">Rails and the notion of Stupid Databases Being a Good Idea</a>, this is a philosophy rooted in <a href="http://c2.com/cgi/wiki?DontRepeatYourself">DRY</a>, but it has some major flaws.</p>
<p>Mainly, there is the issue that some things <i>must</i> be done in the data tier, and trying to put them in the application tier doesn&#8217;t work. The best example that comes to mind is full text search. Satisfying queries is the database&#8217;s job, period. It&#8217;s just hideously slow to try and do an inner join in the application across a network link to a database. If you find yourself doing this, that&#8217;s a pretty good sign that your architecture is broken. But some queries are too complicated for ActiveRecord, so sometimes you must choose between a series of high level queries whose results are intersected in application code (easy to understand, but extremely inefficient), or hand coded SQL.</p>
<p>Well, SQL is fast and is a high level domain-specific language, so it isn&#8217;t actually a bad tool for the job. The problem is that this approach (the trapdoor to the lower level API) is regarded differently by different people. Some see it as a common and reasonable approach to complex requirements; others see it as a bad evil scary thing that should be avoided at all costs, a <a href="http://gilesbowkett.blogspot.com/2007/05/evan-weavers-railsconf-presentation.html">kludge and a design mistake</a>.</p>
<p>As a result, the low level option in Rails is anemic. It&#8217;s there, but you&#8217;re not supposed to use it. <a href="http://rlucas.net/blog/bugfix/ruby_active_record_makes_raw_sql_a_royal_pain.html">Ruby&#8217;s ActiveRecord Makes Dropping to Raw SQL a Royal Pain (Probably on Purpose)</a> notes that there are no bind variables allowed in ActiveRecord. You may be saying, &#8220;No, wait a minute, I&#8217;ve used them, that can&#8217;t be right.&#8221; That&#8217;s what I thought. Look at the source; the bind variable functionality is actually a high level feature built on top of drivers that don&#8217;t have that feature. Whatever you did at the high level, it&#8217;s going to the driver as a single string. Okay, it&#8217;s nice that they added that feature, especially since it provides a single point of testing and verification for safe escaping. But that functionality (in sanitize_sql) is <i>not part of the public API</i>. Fortunately <a href="http://rlucas.net/blog/bugfix/ruby_active_record_makes_raw_sql_a_royal_pain.html">that same article</a> provides a workaround that makes sanitize_sql accessible, so you can use bind variables in your hand coded SQL code, and pretend that the driver supports them. But that&#8217;s not likely to work forever.</p>
<p>The key problem with ActiveRecord is its least common denominator feature set, based around the least featureful of all popular SQL databases: MySQL. Years ago, MySQL AB (the vendor of the MySQL database) took a strong philosophical stand against pretty much any advanced database features (which their product lacked, and which competing products had), but lately they&#8217;ve softened and added those features that they claimed nobody really needed. In the meantime, Rails has been designed with minimal expectations for database sophistication; therefore, the limited functionality of ActiveRecord is fairly complete, assuming you&#8217;re using a database with similarly limited functionality.</p>
<p>Triggers, stored procedures, functions, data integrity constraints, nested transactions, and views are all examples of unsupported database functionality. Try and use them via ActiveRecord&#8217;s high level API, and you will quickly see how fragile and inflexible ActiveRecord really is. If you shouldn&#8217;t need those features in your database, then you shouldn&#8217;t need anything that ActiveRecord doesn&#8217;t already provide, so it shouldn&#8217;t matter that you can&#8217;t extend ActiveRecord.</p>
<p>Truly, these are features that you need only in a few small cases in your application, so looking at individual queries they&#8217;re needed rarely (which is not the same thing as &#8220;never&#8221;). But looking at whether you need one or more of them in a given <i>application</i>, they&#8217;re needed <i>more often than not</i>. The pain of using hand coded SQL makes this worse: some tricky things could be done either using a view or stored procedure, or using a really slick dynamic SQL statement. Making all of those options painful means that even a clever developer can&#8217;t use anything in their bag of tricks to craft an elegant solution.</p>
<p>Unfortunately, non-trivial web applications need things like full text search, complex associations between persistent objects, non-trival summary information about associated objects, and complex reports, and ActiveRecord fails at all of these. These are not just things that big dumb ancient companies that like using Object COBOL think they need; Amazon and eBay need them too.</p>
<p>The <a href="http://code.google.com/p/acts-as-tsearch/">acts_as_tsearch</a> plugin is a good case study of ActiveRecord&#8217;s design flaws. <a href="http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/">TSearch2</a> is the standard PostgreSQL full text search engine, and it&#8217;s pretty good in my opinion. It&#8217;s also pretty straightforward to use. Unfortunately for developers using Rails, TSearch2 uses SQL functions (mainly <code>to_tsquery</code> and <code>rank_cd</code>). The acts_as_tsearch plugin tries to inject SQL into ActiveRecord&#8217;s queries via the high-level <code>find</code> interface, but ultimately fails as soon as you use the :joins or :include options. The problem is that ActiveRecord has a very simplistic idea of how queries and joins work, and so if you need to inject SQL functions to get the job done (as is necessary in TSearch2 queries), too bad. (See also issues <a href="http://code.google.com/p/acts-as-tsearch/issues/detail?id=7">7</a> and <a href="http://code.google.com/p/acts-as-tsearch/issues/detail?id=8">8</a> in acts_as_tsearch, in which I describe and attempt to clean up the mess that results when you use find_by_tsearch in non-trivial ways.)</p>
<p>A fellow Rails developer asked me in all seriousness why I wasn&#8217;t abandoning the full text search functionality of TSearch2 and just using a completely separate, redundant database product designed exclusively for full text search. Seriously, that is considered the &#8220;easy&#8221; approach: one database for full text search, and another for ACID/OLTP/CRUD. Honestly if I were going to go down that road I would try hard to just abandon the SQL RDMBS and put everything in the other database, since Lucene and its imitators are capable of far more than just find-text-in-document queries. The pain of duplicating everything, using two query languages, two document representations (in addition to the object representation in Ruby) and writing application-tier query correlation makes the double-DB approach seem very unwise.</p>
<p>It makes far more sense to me to use the SQL RDMBS&#8217;s full text search facility, even if there&#8217;s a 2x or 3x read performance penalty, because the conceptual simplicity of having one powerful storage tier (instead of two halves cobbled together) eliminates a ton of ugliness in the application, and the SQL RDBMS is going to get clustered for reads anyway. Nevertheless, even if I&#8217;m wrong about this case (putting search in the SQL RDBMS instead of in a separate server), there are other cases for needing a smart database that gives you exactly the results you need and lets you push data logic into the data tier.</p>
<p>So, what do I suggest? Abandon Rails? Nope. I still like Ruby a lot, and find Rails very useful. I just think that ActiveRecord needs to support the low-level and middle-level abstractions better.</p>
<p>Specifically, supporting bind variables (either by exposing that sanitize_sql function, or better yet by making drivers and connection adapters support bind variables for real) would make the <code>find_by_sql</code>, <code>select_all</code>, and <code>exec</code> approaches to low-level SQL query execution less painful.</p>
<p>More difficult, and substantially more valuable, would be refactoring ActiveRecord::Base to split it up in the way I described above: association descriptions and unmarshalling code separate from query building code separate from SQL execution and result retrieval code. All of this could remain hidden for most users under the same old slick high-level API, but for advanced requirements, the ability to fiddle with the SQL and still use the built in high-level unmarshalling code to create object graphs from flat result sets would be very powerful, and useful. </p>
<p>I looked at one alternative to ActiveRecord, called <a href="http://sequel.rubyforge.org/">Sequel</a>, which overlaps with ActiveRecord only partially. It is a query builder and lazy result proxy, which is actually what I thought ActiveRecord would do when I first started working with Rails. The proxy design means that you can either keep adding constraints or start fetching results, from the same Dataset class. This seems like a pretty good approach, though I haven&#8217;t really looked closely to make sure it would fit what ActiveRecord needs.</p>
<p>What Sequel lacks, though, is the unmarshalling side: turning a 2-dimensional (rows of columns) result set into a complex object graph (customers with orders with order lines with products from suppliers stored in warehouses), with user-controlled eager or lazy loading behavior. Ruby is well-suited to a design that would allow user-specified code (i.e., a block) to decompose each row into the object graph associated with that row, leaving the remaining associations on those objects to be lazily provided via future queries.</p>
<p>So, I think there is hope for ActiveRecord, definitely. I considered the idea of rolling a minimal Hibernate clone, or some other sort of challenger to ActiveRecord, but I don&#8217;t that ActiveRecord is broken beyond repair. I think the shortest path to a badass Ruby ORM is through improvements (refactoring and abstraction) to ActiveRecord.</p>
<p>So, if you&#8217;ve read this far, you probably care about these issues. Here&#8217;s my call to action: Please help me make ActiveRecord less like VB and more like Delphi. Who else is interested in helping me with this effort? Are there alternatives that I&#8217;ve missed, or components that could be integrated into ActiveRecord to make it better?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2007/10/04/activerecord-the-visual-basic-of-object-relational-mappers/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>J2ME: Write Once, Be Disappointed Everywhere</title>
		<link>http://www.pervasivecode.com/blog/2007/08/19/j2me-write-once-be-disappointed-everywhere/</link>
		<comments>http://www.pervasivecode.com/blog/2007/08/19/j2me-write-once-be-disappointed-everywhere/#comments</comments>
		<pubDate>Mon, 20 Aug 2007 05:37:59 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[IA]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[articles]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2007/08/19/j2me-write-once-be-disappointed-everywhere/</guid>
		<description><![CDATA[We developers and other nerdy folk are used to using strange and klunky applications that do something special, and we&#8217;re used to that trade-off.
Eclipse is an IDE so it&#8217;s hard to imagine it not being baroque and difficult to use, requiring weeks of effort to become productive. JBidWatcher has saved me a lot of money [...]]]></description>
			<content:encoded><![CDATA[<p>We developers and other nerdy folk are used to using strange and klunky applications that do something special, and we&#8217;re used to that trade-off.</p>
<p><a href="http://www.eclipse.org/">Eclipse</a> is an IDE so it&#8217;s hard to imagine it <i>not</i> being baroque and difficult to use, requiring weeks of effort to become productive. <a href="http://www.jbidwatcher.com/">JBidWatcher</a> has saved me a lot of money on eBay so I could probably put a dollar value on how much it&#8217;s worth to endure its bizarre UI. <a href="http://azureus.sourceforge.net/">Azureus</a> is fairly fugly also but it does a very good job and has a deep, sophisticated UI that&#8217;s fairly easy to understand, so despite the eyesore, it&#8217;s at least fairly clear. The common thread among all of these is that they are all written in Java, and that they are so valuable that it&#8217;s worthwhile to overlook the ugly UIs.</p>
<p>Now imagine those sorts of trade-offs, but on already difficult to use mobile devices, and aimed at consumers. Are you making a strategically wise choice by sacrificing usability and control over the user interface, and probably access to platform-specific features such as dialing the phone, in order to save money on development? Adam Breindel talks about this in <a href="http://skipmeamadeus.blogspot.com/2007/08/when-building-smartphone-app-resist.html">When Building a Smartphone App, Resist the Siren Song of J2ME</a>.<br />
<span id="more-42"></span></p>
<p>Adam and I worked on a J2ME application and I totally agree with him about the disillusionment of trying to write a single app that would work across phones. Issues include:</p>
<ul>
<li>Complex and difficult application installation procedures for end-users: How do you install the JVM on the phone? How do you get the plain J2ME app packaged up so that the phone will accept it? Does the app require manual user configuration before use? Is there a different launching process from other apps?</li>
<li>Lack of control of the user interface: hardware details such as how many buttons you have, whether there&#8217;s a stylus, etc. differ from phone to phone, and the API to let you code once and let J2ME handle the layout for each device leaves your code very disconnected from what&#8217;s actually happening on the screen.</li>
<li>Not being able to use recent J2ME APIs because even the latest phones only support older, more minimal J2ME APIs</li>
<li>Not being able to do things on a phone that would seem obvious, like dialing the phone, opening a hyperlink in the phone&#8217;s browser, sending an SMS, or making a network connection. Either these are entirely impossible or require phone-specific or JVM-specific tools and procedures to sign your application, or having the runtime nag the user to request permission to do something that they just asked the app to do for them.</li>
</ul>
<p>For all the noise Sun is making about broad J2ME penetration, the developer experience is quite disappointing, and as a result, the user experience is also quite disappointing. You can look up J2ME features and APIs and get excited, but when you actually deploy your app to a handset, it won&#8217;t load, or runs terribly slowly, or looks awful, or simply doesn&#8217;t do the things that the API says will happen when you call it a certain way. Suddenly the strict J2SE and J2EE logo certification programs make sense, because the J2ME approach of making so much functionality specified but optional leaves developers high and dry. The phone supports J2ME version xyz, but write an app coded to that API that works on the emulator and deploy it to a handset and lo and behold, all those optional APIs turn out to be missing even though the handset is capable of that functionality, and <i>some mandatory API functions are not working</i>. <a href="http://en.wikipedia.org/wiki/Here_be_dragons">Here be dragons</a>.</p>
<p>Case in point: can&#8217;t dial the phone on a Treo 650 (at least, not as of a year ago). The J2ME API tells you how to do it. The PalmOS JVM (made by IBM) lets you make the API call, and returns a successful response. Nothing happens. IBM says they&#8217;re aware of this issue. The end. The docs say you can, the code you write says you did, the phone just doesn&#8217;t do it.</p>
<p>Case in point: Every time you start an application and it accesses the network for the first time on a Treo 650, the user is nagged for permission to access the network. Quit the app and start again, nagged again. IBM has a tool that you can use to sign the app, but you have to use their VisualAge Micro Edition IDE which costs hundreds of dollars to do that. Try and find and download the trial version. A year ago, it was not possible. So, making that persistent nag go away probably costs several hundred dollars. (I never verified that it actually works, just that IBM says the way to sign the app so that it&#8217;s trusted is to do that, and that there was no available free way to get that tool.)</p>
<p>These are minor issues, but they certainly interfere with the quick usage pattern of a mobile app, and make it annoying to use your app. Imagine what that would be like if you had a competitor with a native application for that phone, whose application probably cost them more, but their app is better and the user likes it a lot more.</p>
<p>The important distinction here is not cost, it&#8217;s ROI. It costs a lot to develop a similar application for each smartphone platform, using that platform&#8217;s native tools. It would seem to cost a lot less to develop a J2ME app. But that&#8217;s only if you assume that it&#8217;s OK to abandon features and settle for a horrid user experience in the course of development.</p>
<p>It&#8217;s likely that your goal as a development team is to develop an app that has a predefined feature set that you know the device can support, and a predefined UI design that your mobile-savvy UI people are sure will go over well with users accustomed to that particular kind of smartphone. In that case you will almost certainly fail to accomplish that goal using J2ME. You have to scale back your goal so that you&#8217;re satisfied that you got something kinda like what you wanted working on a bunch of phones, and determined users will probably be able to figure out how to install it and make it work.</p>
<p>I call that phenomenon &#8220;write once, be disappointed everywhere.&#8221;</p>
<p>Let&#8217;s continue talking about cost, though. The native apps may require (or suggest) different programming language skills for different devices. It might seem wise to just write everything in C, but I think that&#8217;s a false economy as well. The phone APIs will differ so much that you will really need a native developer for each platform, not a team of generic C developers who will figure out the individual phone stuff and be freely floating resources that you can assign to whatever app version needs their attention. Smartphones may run Linux, may run Windows Mobile, may run PalmOS, may run Symbian&#8230; these are different operating systems with very different ideas of how applications run and coexist. The platform specific knowledge (APIs, appropriate UI feel, device capabilities) is probably an order of magnitude harder to learn and maintain than the ability to get an application working in a given programming language.</p>
<p>How much of a great C programmer&#8217;s skill is really the C language, and how much of it is proficiency with the available libraries on the platform he or she is accustomed to? I think close to 90% of their professional skill set is platform and library familiarity, and 10% syntax and low-level understanding of how the language actually works.</p>
<p>In light of this (just using C doesn&#8217;t mean developers or code are portable across smartphones), consider that there are high level languages available for some smartphones. What if that 90% platform familiarity means they can use a language and/or development environment that makes them 5 or 10 times as productive, after spending just a few days or a couple of weeks learning the language syntax?</p>
<p>After our very disappointing J2ME-on-PalmOS port experience, Adam found <a href="http://www.handheld-basic.com/">Handheld Basic</a> which initially appalled me (oh no, BASIC!) but turned out to be a great choice. It&#8217;s a flavor of BASIC, so learning the language didn&#8217;t take long, and the support happens to be quite good (<i>lots</i> of code samples) so picking up the library portion of that 90% didn&#8217;t take long at all. I imagine that C# on Windows Mobile is similar. As more and more phone start to use Linux as their OS (which will be a particularly huge improvement for PalmOS based phones), you&#8217;ll be able to use Python, Ruby, Mono, J2SE (a whole different animal from J2ME), TCL, or pretty much any other high level language available for Linux. At LinuxWorld 2006 I saw a development device running unmodified GNOME desktop apps running on a PalmOS device alongside PalmOS apps. There are more options appearing all the time, and with the exception of Handheld Basic, most of them are ports of familiar, mature, well understood desktop languages, with class libraries relevant to mobile devices.</p>
<p>So, I recommend that you work in whatever high level language lets you do all the platform specific stuff you want, and if that means a different language per phone, that&#8217;s actually going to be the least expensive way to get to the apps you actually wanted to build. A big chunk of the scary cost of developing native apps goes away, because native doesn&#8217;t necessarily mean abandoning Java for C. (In fact I found Handheld Basic to be a more productive environment for me after a couple of weeks than J2ME was, despite my ~8 years of full time Java experience before starting that project.)</p>
<p>That pretty much means no reuse for you. Sorry, but that&#8217;s the deal right now.</p>
<p>If that unique-app-per-platform cost is too scary, consider a few ways to save money:</p>
<ul>
<li>For networked apps (aren&#8217;t they all?) ask yourself if there&#8217;s some logic that could just as easily be done on the server as on the client. Is there some complicated parsing code on the client that could be simplified by changing the response format from the server to something that&#8217;s easier to parse?</li>
<li>Can you remove or alter certain features from a subset of platforms you intend to support, so that your premium supported platforms get your ideal app, whereas a few less popular phones still get a nice app, but perhaps one that doesn&#8217;t have every feature available on your premium app. You might be reading this and thinking &#8220;but that&#8217;s what you said J2ME would force me to do! Why is this any better?&#8221; The distinction is that you are in control of the decision of what to leave out to save money, whereas with J2ME it&#8217;s the platform vendor who makes that decision for everyone using their platform. If you&#8217;re writing an address book, not being able to dial the phone is lethal; not writing the code to let the user attach a photo to the entries is not.</li>
<li>Can you move some user-facing functionality to the server to make the client simpler? Maybe there are some rarely-used features that could be done via a desktop or mobile web browser, so you can focus on putting the ten-times-a-day features on the handset, and making those features fast and convenient. You probably already made that trade-off in general, but perhaps for some kinds of handset, you&#8217;ll move the dividing line a little further, so that for users of particularly rare phones, some moderately frequent features can&#8217;t be done on the phone. This could also be a good approach for new handset types: design a &#8220;lite&#8221; app and a &#8220;full&#8221; app version, build the &#8220;lite&#8221; app first on each platform, and let user demand tell you whether the full app is worth it. Your developers can tell you much more accurately how much the incremental functionality would cost, since they already have done the lite version. Maybe you&#8217;d provide a VoiceXML interface, or mobile web browser interface, for that feature so that the user can still do whatever the feature requires while they&#8217;re far from a desktop PC.</li>
</ul>
<p>A final consideration: labor. Maybe you have some Java developers, or C developers, and don&#8217;t have developers good at Handheld Basic or C#, so you&#8217;re not inclined to fire them all and hire new developers to do native apps, you&#8217;re thinking maybe C on every handset, or J2ME, is still the right choice. I still say that you should probably use native apps in native high level languages on every smartphone platform. If you&#8217;re committed to a strategy of good apps on a bunch of different phones, I think I&#8217;ve made clear that native apps are the only way to currently get there; J2ME simply doesn&#8217;t let you make good apps. So what&#8217;s left is C code written by C developers vs. high level code written by C developers who have to retrain.</p>
<p>As I said above, I don&#8217;t see much chance that your developers or your code will be portable across different smartphones if you use C. Maybe you&#8217;ll get 5-10% savings that way (some code ported across phones, or some developer hours shuffled between platform teams). But you&#8217;d get a 5-10x cost saving from using something very modern and high-level instead of C, and the overhead of training for the language would be very very small as compared to the large and unavoidable overhead of having to learn what the handsets can do and how the APIs for the handset&#8217;s OS work.</p>
<p>I suppose that means that if you have a bunch of C developers who lack smartphone skills, you&#8217;re in a pickle, but that situation seems kind of unlikely to me (a mobile app company hires a bunch of Unix and Win32 C developers with no mobile phone skills?). More likely is that you&#8217;d find a mobile developer who is proficient with one or more handset OSs and the best tools for each one, and they may be of the opinion that C is the best choice since they can reuse skills and some code across platforms. I would say that in that case you need to convince them to (or more likely encourage them to do what they were already considering, which is to) go ahead and find a highly productive high level programming language/environment for each smartphone platform.</p>
<p>A final possibility if you have a ton of platforms to target and a pile of killer C programmers is to try and port something like Python across most of your target platforms, or to make a very high-level API or domain-specific language that runs inside your own custom C portability layer. You might be able to find an open source option that you can invest some developer hours in, so that the actual application-specific code that you write on each platform is minimized and portable. But I suspect that this would still be expensive and would result in some J2ME-like UI abstractions that ended up being very unsatisfying in the end.</p>
<p>Best of luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2007/08/19/j2me-write-once-be-disappointed-everywhere/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>&#8220;Ruby faster than Python and Perl!&#8221; ORLY?</title>
		<link>http://www.pervasivecode.com/blog/2007/08/16/ruby-faster-than-python-and-perl-orly/</link>
		<comments>http://www.pervasivecode.com/blog/2007/08/16/ruby-faster-than-python-and-perl-orly/#comments</comments>
		<pubDate>Thu, 16 Aug 2007 23:05:46 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[articles]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2007/08/16/ruby-faster-than-python-and-perl-orly/</guid>
		<description><![CDATA[Ruby faster than Python and Perl! cries the headline. This is based on a benchmark that tests &#8220;i = i + 1&#8221; in a loop, so it&#8217;s a particularly useless benchmark, even in a world of benchmarks designed to test unrealistic scenarios that make the benchmark author&#8217;s product look good.

But wait! A commenter accuses the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://smyck.de/2007/08/15/ruby-faster-than-python-and-perl/">Ruby faster than Python and Perl!</a> cries the headline. This is based on a benchmark that tests &#8220;<code>i = i + 1</code>&#8221; in a loop, so it&#8217;s a particularly useless benchmark, even in a world of benchmarks designed to test unrealistic scenarios that make the benchmark author&#8217;s product look good.<br />
<span id="more-41"></span><br />
But wait! A commenter accuses the poster of cheating! (On a benchmark? No!)<br />
<em>&gt;Ummm…. Why did you test Ruby with less data than you tested Python and Perl? You cheated.<br />
</em><br />
As it turns out, the &#8220;microbenchmark&#8221; scripts for different languages have differing loop counts, so the total run time is super extra especially meaningless as a way to compare language performance.</p>
<p>When I was in 5th grade (age 9) learning AppleSoft BASIC on the Apple ][+ in math class, we wrote programs that did this:<br />
<code>10 X = 1<br />
20 PRINT X<br />
30 X = X +1<br />
40 GOTO 20</code><br />
And we would race each other, starting at the same moment and seeing whose column of increasing numbers on the screen scrolled faster. This was of course stupid because all the computers in the lab were chip-for-chip identical to each other, and probably were all made on the same production run on a single day.</p>
<p>We learned that we could cheat by adding a number larger than one in each loop iteration, which was quickly detected and outlawed. Far more cleverly, someone figured out that you could do something like this:<br />
<code>20 PRINT X: X = X + 1: GOTO 20</code><br />
The same algorithm yielded better performance if it was all written on one line of code. I could be misremembering (it has been 25 years and I don't have a ][+ handy to verify this on) but it was something like that. Anyway, we learned that the same language runtime on identical hardware using the same algorithm could be made to run faster or slower using simple formatting changes.</p>
<p>So does it make sense to compare different languages this way, which may mean favoring one language's idiomatic code structure while hitting a weak spot of another? This is a common, and in my opinion valid, critique of apples-vs-oranges benchmarks: how do we know that the performance difference isn't due to naive coding or configuration on one side and expert tuning on the other side? For that matter, do we know that the benchmark design isn't selected specifically to highlight exceptionally high performance in one area of a product, to the exclusion of embarassingly slow areas that the benchmark designer would prefer that you not consider?</p>
<p>Thus I claim that this benchmark is approximately as valuable as my 5th grade silly hacks. X=X+1, change the number of iterations to suit your bias, or perhaps just don't bother making them the same because it's meaningless anyway. (Z=X*Y and a matrix multiplication are other parts of this benchmark, but they too are so trivial in concept and implementation as to be equally pointless.)</p>
<p>I'm going to guess that the author of the blog post didn't notice the different in loop iterations, or was looking at the per-second values rather than the total run time. But if we're looking at average performance over time, then how long does it take for the performance to stabilize? <strong>Stabi-<a href="http://www.penny-arcade.com/comic/2007/03/30">whatchamaha</a></strong>? Ask <a href="http://www.zedshaw.com/rants/programmer_stats.html">Zed Shaw</a>: look at his list of pet peeves, #3.</p>
<p>Do we know that 0.142 seconds is enough to measure &#8220;language performance&#8221; (really, it&#8217;s the performance of a particular runtime environment being measured) including stuff like garbage collection and JIT compilation overhead? If one language&#8217;s runtime waits for N iterations before JIT-compiling the code, whereas another runtime waits for 5N, how many total iterations do you need to minimize the effect of that?</p>
<p>What happens in JRuby, Ruby2C, etc.? The poster says the tests were run on a MacBook Pro &#8211; what architecture (PPC vs. Intel) were these language runtimes compiled for, with what compiler, blah blah. GCC versions, optimized for certain CPU models, etc. This stuff can make a big difference in CPU benchmarks, which is why proper benchmarks include things like this in their configuration information.</p>
<p>Or are you measuring small script execution time, and >1s runtimes are meaningless for your needs, in which case Java seems painfully slow and Bash lightning fast?</p>
<p>What the heck <em>is</em> being measured by this &#8220;microbenchmark&#8221;? Language fanboy gullibility?</p>
<p>For a less awful benchmark, have a look at the <a href="http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&amp;lang=all">Computer Language Benchmarks Game</a>: &#8220;What fun! Can you manipulate the multipliers and weights to make your favourite language the best programming language in the Benchmarks Game?&#8221; At least they realize how not-terribly-useful synthetic CPU benchmarks of language runtimes are.</p>
<p>Anyway, for most applications, if you&#8217;re choosing your language based on runtime performance, you&#8217;re choosing very poorly. If you&#8217;re choosing your language based on a really awful &#8220;microbenchmark&#8221; comparable in accuracy to the first toy hack of a room full of 9-year-olds, well&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2007/08/16/ruby-faster-than-python-and-perl-orly/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Bad, Bad Code</title>
		<link>http://www.pervasivecode.com/blog/2007/08/04/bad-bad-code/</link>
		<comments>http://www.pervasivecode.com/blog/2007/08/04/bad-bad-code/#comments</comments>
		<pubDate>Sat, 04 Aug 2007 22:21:02 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[humor]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[labor]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[offshoring]]></category>
		<category><![CDATA[outsourcing]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2007/08/04/bad-bad-code/</guid>
		<description><![CDATA[I&#8217;ve written before about tips for offshoring. One specific thing I said to watch for is the bait-and-switch of talent: during the sales process you&#8217;re shown rockstars, but the real code you get is written by clueless newbies. When you set up a project such that you&#8217;ve minimized the cost per hour of development, but [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve written before about <a href="http://www.pervasivecode.com/blog/2007/02/20/tips-for-offshoring/">tips for offshoring</a>. One specific thing I said to watch for is the bait-and-switch of talent: during the sales process you&#8217;re shown rockstars, but the real code you get is written by clueless newbies. When you set up a project such that you&#8217;ve minimized the cost per hour of development, but you don&#8217;t have anyone checking the work product (i.e. code reviews) coming from the subcontractor, very bad things happen.<br />
<span id="more-40"></span><br />
Here&#8217;s a doozy: <a href="http://www.discursive.com/blog/2007/07/in-2007-people-are-still-writing-jsp.html">In 2007, people are still writing JSP like this&#8230;</a></p>
<p>Check out the 4th message in the thread, with the big code sample.</p>
<ul>
<li>Table based HTML layout, and no CSS at all? Check. Heck, the table width % values don&#8217;t even add up to 100%.</li>
<li>SQL in the JSP? Check.</li>
<li>Making a new JDBC connection for each page view, instead of using a connection pool? Check.</li>
<li>Unescaped strings in the SQL? Check. (Not strings coming from the browser in this particular JSP page, but you don&#8217;t know where those strings originate. Why wouldn&#8217;t you escape it just in case?)</li>
<li>Failing to use a prepared statement? Check. (That would also solve the escaping problem.)</li>
<li>Using a string literal in a SQL or command line context, so you can&#8217;t log it beforehand? Check. Even better, the code makes a query string first, prints it (commented out), and then <i>uses a different string in the actual query</i>. Nice!</li>
<li>Using the JdbcOdbc driver? Check. (From <a href="http://java.sun.com/docs/books/tutorial/jdbc/basics/connecting.html">Sun&#8217;s JDBC Basics</a>: The JDBC-ODBC Bridge driver provided with JDBC is recommended only for development and testing, or when no other alternative is available.) I&#8217;m guessing that the use of ODBC here is the only reason why the database username and password aren&#8217;t embedded in the code sample and posted for all to see.</li>
<li>Empty exception catch block? Check.</li>
</ul>
<p>I&#8217;d have a hard time coming up with a fake example of bad code that was worse.</p>
<p>But wait, <a href="http://forum.java.sun.com/profile.jspa?userID=908177">what else has this person asked about</a>?</p>
<p>No way. Yes! <a href="http://forum.java.sun.com/thread.jspa?threadID=5156702&#038;messageID=9593464#9593464">Error in Socket and File Writing</a>!<br />
The post includes the router&#8217;s username and password, and its configuration including:</p>
<ul>
<li>Its IP address, and all of the routes it contains, and all of its interfaces and where they go</li>
<li>A couple of other passwords stored in the router</li>
<li>A crypto key that appears to be to a VPN (looks like a pre-shared key, meaning not a public key but one that must be kept secret)!</li>
</ul>
<p>I&#8217;m not gonna say &#8220;you get what you pay for&#8221; since open source software has served me very well, but I will say that you get what you bargain for. If your bargain includes not looking at the work product of the people you hire, which is to say, hiring the cheapest people available and not supervising them, you&#8217;re not going to be happy with what you get.</p>
<p>Of course, this <em>could</em> have been written by a U.S. citizen who works in a cube on-site and makes $200/hour. Point is, hire carefully, and supervise your workers. It seems simple when put that way, but it&#8217;s amazing how often companies are willing to hire software subcontractors carelessly (solely on price?) and then pay little or no attention to the resulting work, when the arrangement involves offshore outsourcing.</p>
<p>By the way, the IP addresses in the original post (with the awful code sample) are listed next to the name &#8220;Areva&#8221;, implying that this code is part of a project for Areva. Who is Areva? <a href="http://www.areva.com/servlet/operations-en.html">They make nuclear power plants</a>. Sweet dreams!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2007/08/04/bad-bad-code/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Rails, Fixtures, the Test DB, and Test::Unit</title>
		<link>http://www.pervasivecode.com/blog/2007/08/02/rails-fixtures-the-test-db-and-testunit/</link>
		<comments>http://www.pervasivecode.com/blog/2007/08/02/rails-fixtures-the-test-db-and-testunit/#comments</comments>
		<pubDate>Fri, 03 Aug 2007 02:37:22 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[architecture]]></category>
		<category><![CDATA[databases]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2007/08/02/rails-fixtures-the-test-db-and-testunit/</guid>
		<description><![CDATA[From what I&#8217;ve seen, Rails&#8217; weakest features lie in the way it prepares the test database and test data, and Ruby&#8217;s Test::Unit isn&#8217;t much better than the awful but ubuiquitous JUnit that Java developers are accustomed to. I set out this week to impose my preferences on Rails in this area, and that took some [...]]]></description>
			<content:encoded><![CDATA[<p>From what I&#8217;ve seen, Rails&#8217; weakest features lie in the way it prepares the test database and test data, and Ruby&#8217;s Test::Unit isn&#8217;t much better than the awful but ubuiquitous <a href="http://www.junit.org/index.htm">JUnit</a> that Java developers are accustomed to. I set out this week to impose my preferences on Rails in this area, and that took some effort. Here&#8217;s what I did.<br />
<span id="more-39"></span></p>
<p>When I&#8217;ve implemented (in Java) what Rails does for database preparation, I did it like this:</p>
<ol>
<li>Create the test database exactly the same way that the developers&#8217; databases are created: by running the exact same code, pointed at a different database.</li>
<li>Load the appropriate sets of data for the test database. &#8220;Sets&#8221; is plural on purpose; most non-trivial databases include code tables, which constitute base data which are essentially part of the database design itself. Then, test code will want a fixed set of known test data to act upon, so that tests can measure whether the code did the right thing given the test data (the right inputs yield the right outputs).</li>
<li>Run the individual tests, providing some way of assuring that changes to the test data are undone before the next test.
</ol>
<p>At first (11 years ago) I used a hand-maintained SQL DDL file to create the databases. Later I split that up into one file per table, and made a list of the proper ordering of tables during creation (reversible for deletion). Later still, with <a href="http://www.hibernate.org/">Hibernate</a>, I ditched the DDL and let a higher-level ORM description of the table do the schema generation (which was painful in Hibernate since it wasn&#8217;t made to do that except from the command line, but it was possible to hack it into a state of relative beauty). The test data was always loaded from a bunch of text files that were easy to hand-edit (as opposed to a bunch of SQL INSERT statements).</p>
<p>Running the test with assurance of pristine test data was more or less horrific in a J2EE+Hibernate 2.x environment. The design of Hibernate and JUnit made it difficult to wrap tests in transactions, and the version of MySQL that we were using had no transactional storage engines available at all (MyISAM? Thanks, Red Hat!), so I ended up falling back on an intrusive but relatively high-performance design that required tests to declare if they were going to alter the test data, so that the test teardown method knew it had to reload the test data. Since we were waiting for Hibernate 3.0, MySQL 5.x, and a few other things to become part of our architecture, I left that solution in place and ended up moving on to a new job before fixing it.</p>
<p>Rails initially seemed to nail this problem: the test database is automatically made based on the development database; the data is loaded from YAML files called Fixtures, which feature a very simple and straightforward API, and tests run inside individual transactions. Nice!</p>
<p>Except not. Fixtures are loaded by specifying the tables for which you need test data loaded, and this is done in each Test::Unit::TestCase class, of which I have several hundred. They are stupidly reloaded each time you say a given TestCase is going to use them. Worse, the tables you&#8217;re using for this TestCase are emptied out using SQL DELETE statements, but if there is test data in other tables that has foreign key dependencies on the data being deleted, fixture loading will fail. (Rails was not designed for FKs to be enabled in the database, so encountering this this bug is a side effect of enabling them via the plugin.) This deletion behavior is pointless in light of transactions wrapping each test, but if you&#8217;re using MySQL MyISAM you can&#8217;t use transactions, so it needs to be there for people using MyISAM, which is to say, crazy people who care not for their data.</p>
<p>Since Test::Unit, like Java&#8217;s JUnit, lacks a hook for the beginning or end of a given TestCase class&#8217;s set of tests, there&#8217;s no way to accumulate a list of fixtures created and then delete them and/or reload them at the end. That would at least allow you to undo the creation of the fixtures so that the tables were all empty before the next set of fixtures were loaded. Sadly, Test::Unit is not that clever.</p>
<p>I initially fixed this problem a couple of months ago, using a hack that simply refuses to delete and re-create (test data) fixtures if they&#8217;re already loaded. That works since the fixture data progressively accumulates and is always clean since changes within tests are rolled back at the end of those tests.</p>
<p>Upon adding a trigger to a Rails migration and then writing a test case that checked to see if it was working, I found the true ugliness. Rails has <a href="http://wiki.rubyonrails.org/rails/pages/UnderstandingMigrations">Migrations</a>, which in my opinion are an excellent feature that works well, and is a more useful generalization of my ordered-list-o-tables and set of table-definition text files. But&#8230; when creating the test database, Rails uses the <a href="http://caboo.se/doc/classes/ActiveRecord/SchemaDumper.html">SchemaDumper</a>&#8217;s schema.rb output to create it, instead of using migrations. Talk about principle of least astonishment&#8230; I was pretty astonished. We have migrations, which is how we create databases! Great! So let&#8217;s use this other thing instead.</p>
<p>Also, SchemaDumper does not in fact dump the schema; it dumps tables and indices only. The RedHillOnRails foreign keys core plugin adds foreign key dumping to this output, but forget about check constraints, triggers, and stored procedures. Those schema objects are ignored, so your test database is not the same as your development (or production) database. Whoops.</p>
<p>I thought of about a dozen ways to deal with this:</p>
<ol>
<li>Abandon triggers and do it all in Rails, make a TODO to fix this later, and get on with feature implementation</li>
<li>Add code to the tests to check for the missing schema objects and add them if missing (eww)</li>
<li>Replace the db:test:prepare Rake task with one that tells PostgreSQL to copy the database as-is</li>
<li>Replace the db:test:prepare Rake task with one that tells PostgreSQL to use <a href="http://www.postgresql.org/docs/8.2/static/app-pgdump.html">pg_dump</a> instead of ActiveRecord::SchemaDumper</li>
<li>Hack the PostgreSQL-specific code that SchemaDumper uses to look at the <a href="http://www.postgresql.org/docs/8.2/static/catalog-pg-proc.html">pg_proc</a> and <a href="http://www.postgresql.org/docs/8.2/static/catalog-pg-trigger.html">pg_trigger</a> system catalogs and use code similar to the RedHillOnRails Core plugin to dump stored procs and triggers into schema.rb also</li>
<li>Just dump using pg_dump into a temp file and parse the output and add that to schema.rb (ewwwwwww)</li>
</ol>
<p>etc. etc.</p>
<p>I finally found the <a href="http://www.elctech.com/2007/7/12/migrate_test_db">Migrate Test DB Rake Plugin</a> which simply uses your Rails Migrations to create the test database. Lovely. Except I now had some new problems.</p>
<ol>
<li>rake db:schema:purge for PostgreSQL does dropdb/createdb on the test database to empty it out. That creates a database with no built in procedural langauges, so stored procs won&#8217;t work. Adding the language to that database is a DB superuser task, so it couldn&#8217;t be done inside of Rake. Fortunately I found that I could solve this via &#8220;createlang plpgsql template1&#8243; which puts plpgsql in the template database used for creating new databases. Easy.</li>
<li>My never-delete-fixtures code got into a fight with my base-data-loader code. They both used Fixtures to load data, and so the base data fixtures made the never-delete-fixtures code think that the test data was already in. So the tests failed due to lacking test data.</li>
</ol>
<p>I fixed this initially by modifying my BaseDataLoader class to not load base data if RAILS_ENV is &#8216;test&#8217;, and added code to the Migrate Test DB Plugin to set RAILS_ENV to &#8216;test&#8217; right before running the migrations on the test database. This is a workaround, really, because it still leaves the base data either missing entirely, or duplicated.</p>
<p>Then I switched to the <a href="http://www.elctech.com/2007/5/31/preloading-fixtures">Preload Fixtures plugin</a> which is nice but still leads to FK related errors. It grab the fixture names from your test/fixtures directory and loads all the files it finds, in the order it found them. That fails since alphabetical order and the required table creation order are different in my case.</p>
<p>Fortunately since I&#8217;m using the Migrate Test DB Plugin I can just observe the order in which tables were created and tell the Preload Fixtures plugin to do its work in the same order. This is in my environment.rb because that&#8217;s where all my project-wide monkeypatching currently lives. (Cleaning that up and maybe plugin-izing it is a TODO for the future.)</p>
<pre>
# Due to FKs, gotta specify ordering of fixture preloading here. Why not let migration create_table statements do it?
# (depends on Migrate Test DB Plugin being present; is here for the benefit of the preload_fixtures plugin)
module ActiveRecord::ConnectionAdapters::SchemaStatements
    alias create_table_orig create_table
    def create_table(table_name, options = {}, &#038;block)
        fixture_filename = "#{table_name}.yml"
        if File.file?(File.join([RAILS_ROOT, 'test', 'fixtures' ,fixture_filename]))
            ENV['FIXTURES'] = [ENV['FIXTURES'], fixture_filename].compact.join(',')
            # puts ENV['FIXTURES']
        end
        create_table_orig(table_name, options, &#038;block)
    end
end
</pre>
<p>Sadly if you run &#8220;rake test&#8221; it runs ruby as a subprocess in order to do &#8220;rake test:units&#8221;, &#8220;rake test:functionals&#8221;, and &#8220;rake test:integration&#8221;. That means that the migrations are run once (before the tests), but that the preloading is done three times. The second and third times through, though, the preloading fails since it&#8217;s trying to delete-then-create each table&#8217;s fixtures in table-creation order. So, a patch to preload_fixtures.rb is needed, to ensure that deletes are done first, in the reverse order of table creation. Here&#8217;s what the new preload! method looks like:</p>
<pre>
  def self.preload!
    puts "PRELOADING FIXTURES..."

    require 'active_record/fixtures'
    ActiveRecord::Base.establish_connection(:test)
    fixture_filenames = (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'test', 'fixtures', '*.{yml,csv}')))

    # delete first, in reverse order
    fixture_filenames.reverse.each do |fixture_file|
        table_name = File.basename(fixture_file, '.*') # hack; might not be correct if class name != camelized table name
        ActiveRecord::Base.connection.delete "DELETE FROM #{table_name}", 'Fixture Delete'
    end

    fixture_filenames.each do |fixture_file|
      Fixtures.create_fixtures(File.join(RAILS_ROOT, 'test', 'fixtures'), File.basename(fixture_file, '.*'))
    end
    puts "DONE. Loaded #{Fixtures.all_loaded_fixtures.keys.length} fixtures."
  end
</pre>
<p>I&#8217;m not sure, but I think there&#8217;s an assumption in there that the table name is the same as the fixture name. My patch also makes that assumption, which is true in the case of my project. But in your project you might not have done that, so further hackery might be needed.</p>
<p>So, it all seems to work correctly now, and I&#8217;m back to working on my trigger code. If this seems like it took a lot of effort, it did, but I think it&#8217;ll be worth it once I start using stored procs and triggers more. That phase begins now.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2007/08/02/rails-fixtures-the-test-db-and-testunit/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>RCOV C0 line coverage more generous than EMMA&#8217;s C1 line coverage</title>
		<link>http://www.pervasivecode.com/blog/2007/07/11/rcov-c0-line-coverage-more-generous-than-emmas-c1-bytecode-coverage/</link>
		<comments>http://www.pervasivecode.com/blog/2007/07/11/rcov-c0-line-coverage-more-generous-than-emmas-c1-bytecode-coverage/#comments</comments>
		<pubDate>Wed, 11 Jul 2007 19:26:01 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[coverage]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2007/07/11/rcov-c0-line-coverage-more-generous-than-emmas-c1-bytecode-coverage/</guid>
		<description><![CDATA[Coverage tests in Ruby (with rcov) are less strict than in Java (with EMMA), so watch out &#8211; 100% coverage is easy to attain but not as meaningful.

For Java code coverage, I like EMMA. Clover looks really nice and all, but seriously, $250 a seat? Yeesh. Talk about poor product pricing &#8211; I will never [...]]]></description>
			<content:encoded><![CDATA[<p>Coverage tests in Ruby (with <a href="http://eigenclass.org/hiki.rb?rcov">rcov</a>) are less strict than in Java (with <a href="http://emma.sourceforge.net/">EMMA</a>), so watch out &#8211; 100% coverage is easy to attain but not as meaningful.<br />
<span id="more-34"></span><br />
For Java code coverage, I like EMMA. <a href="http://www.cenqua.com/clover/">Clover</a> looks really nice and all, but seriously, $250 a seat? Yeesh. Talk about poor product pricing &#8211; I will <i>never</i> buy that product, nor seriously consider buying it, because of the outrageous price. I mean, a single license of <a href="http://www.jetbrains.com/idea/">IntelliJ</a> is $1 cheaper. That&#8217;s like charging $300 for a better Ant. C&#8217;mon.</p>
<p>Anyway, EMMA is very conservative about coverage estimates. Consider this single line of Java code:</p>
<p><code>int x = 1; if (x &gt; 1){throw new RuntimeException();}</code></p>
<p>When you run it, the assignment will execute, as will the comparison, but the block containing <code>throw</code> will never be reached. So, the line is not fully covered. EMMA looks at bytecodes and maps those back to line numbers, and will mark this line as partially covered.</p>
<p>It&#8217;s maddening sometimes, but it&#8217;s correct; it&#8217;s your problem to figure out how to force all those darned IOExceptions that you know can&#8217;t ever happen, or to give up and let some apocalyptic error handling code not be covered. I used to shoot for 85-90% coverage, and just live with some uncovered wacky code when I couldn&#8217;t find a reasonable way to trigger hideous errors.</p>
<p>(There&#8217;s a little voice in my head that says, &#8220;Come on, you slacker, you should make it possible to dynamically break the database configuration and remount the root filesystem as read-only during the test suite so that the error handlers can all be 100% covered!&#8221; But that little voice never ships anything, he just sits around and writes more and more paranoid code &#8212; no <a href="http://archive.eiffel.com/doc/manuals/technology/contract/ariane/page.html">Ariane 5 disaster</a> on my watch! &#8212; and gets asymptotically closer to 100% coverage.)</p>
<p>Okay, now the Ruby version:</p>
<p><code>x = 1; raise RuntimeError if x &gt; 1</code></p>
<p>Same story, prettier code (cuz it&#8217;s Ruby; duh, of course it&#8217;s prettier): assignment gets executed, condition is executed, no exception is raised. Rcov says it&#8217;s 100% covered.</p>
<p>The difference is <a href="http://eigenclass.org/hiki.rb?rcov#l15">C0 coverage</a> (Rcov) vs. <a href="http://emma.sourceforge.net/faq.html#q.fractional">C1 coverage</a> (EMMA). EMMA only counts a line as 100% covered if all of the bytecodes compiled from it were executed. Rcov counts a line as 100% covered if execution visited that line at all.</p>
<p>(EMMA uses &#8220;basic blocks&#8221; instead of bytecodes, so in obscure failure cases the reported line coverage figure is even lower, but that doesn&#8217;t affect the conditions for what 100% line coverage requires.)</p>
<p>I&#8217;m not sure if it&#8217;s feasible to get C1 coverage on the regular Ruby VM, but it would be nice to have. In the meantime, just be aware that 100% C0 coverage is easy to attain with rcov, but doesn&#8217;t mean you&#8217;re done testing everything.</p>
<p>Of course, 100% C1 coverage doesn&#8217;t mean you&#8217;re done testing everything either, but it&#8217;s closer to meaning that than 100% C0 coverage is.</p>
<p>In fact, it&#8217;s good to over-test code that&#8217;s already covered once. On any given project in the real world, there is code that will succeed with some values and fail with others. (<code>print x/y</code>, for example.)  Just testing with one set of values isn&#8217;t enough. I like to create an array of inputs and expected outputs and use Array.each to iterate over them and pass them into a block that calls the code under test and then compares the actual outputs to the expected outputs with assert_equal. It means that I&#8217;m following DRY (rather than cutting and pasting several lines of test code and then editing a teeny bit of each pasted chunk&#8230; eww) but still testing many different ways.</p>
<p>But, even with a C0 coverage tool, at least you know what <em>hasn&#8217;t</em> been touched at all, and you can use your big smart programmer brain to think of a few ways to torture that code. Just remember that you probably should be aiming for an unmeasurable way-over-100% imaginary coverage target, beating the heck out of your fanciest code with many, many different inputs and then moving on to the next chunk of uncovered code only when the last chunk is thoroughly proven to not suck.</p>
<p>Good testing!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2007/07/11/rcov-c0-line-coverage-more-generous-than-emmas-c1-bytecode-coverage/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
