It’s Ok To Call Software “Enterprise”

February 27th, 2007

“Enterprise” is a dirty word in some circles. It is typically taken to mean:

  • Big and impressive (or, they’d like you to think so).
  • Overengineered, overdesigned, and generally far more complicated than necessary.
  • Weighed down with legacy cruft.

I avoided the word for a long time myself, associating it with the sort of overwrought J2EE apps that require 10 developers to support, and probably could be replaced with a 200 line Perl script.

With a name like Patterns of Enterprise Application Architecture, it’s a wonder I ever bothered to pick up and read Martin Fowler’s book. As it turns out, he gives an enlightened definition of enterprise which showed me that the word is pretty useful when used correctly.

Enterprise doesn’t mean big, but it does mean complicated. It means necessary complexity, because the application is modeling some sort of real-world business process which is, well, actually complicated. LiveJournal is not an enterprise app even though it’s very, very big. It has tons of users but its basic function is simple, and it’s not modeling any sort of complex real world activity. (Though one could probably make a good argument that tracking the current moods of ten million teenage girls is a special kind of complexity all its own.)

On the other hand, you could have an order processing system for a small business which doesn’t handle a lot of volume, but is correctly called an enterprise app because it is encoding a series of detailed business processes.

Perhaps a good example of an enterprise system would be a package tracker for a carrier like FedEx or UPS. Although the front end is simple (type in a tracking number and see where your package is), the internally facing components of the software system are numerous and varied. You’ve got labels being printed through a website and an API, you’ve got scanning the packages as they go in and out of facilities, which has its own specialized hardware setup; you’ve got the handheld devices carried by the door-to-door guys that is also specialized hardware; and you’ve got billing systems on the backend, which almost need to be able to handle claims for failed deliveries. Now think of all the different states a package can be in as it travels. There are a huge variety of exceptions that can happen. This stuff is all in the real world, so you can’t easily say, “Well, we’ll simplify the code by just ignoring this case over here.” A tracking system which can’t track the package’s state and location at all times would be pretty much useless. You’re forced to have a huge amount of complexity, like it or not.

Now for the punchline: a good technical design correctly models all of that external complexity, while being as simple internally as it can possible be. You’re encoding a business process that is really complicated - why make things worse for yourself by having the software add complexity?

Of course no one really intends to add complexity (I hope). It’s just that, well, a streamlined design that covers many cases with a minimal amount of code is really quite difficult. People that can do it well (this trait seems to run in the Fowler family, for instance) can make a lot of money doing it.

The difficulty is further enhanced by the fact that enterprise software tends to have a lot of legacy baggage due to its organic growth and long lifetimes. You thought that migrating your mom from Windows to OS X was difficult? Try moving 100,000 employees spread out across the globe from the historic app to your shiny new one. They depend on this thing to do their job, day in and day out. If it was a consumer app, it wouldn’t be a big deal: they could move across one at a time. For an enterprise app, the only real choice is to run both systems side by side for some period of time. But just think of the package tracker again: when the systems get out of sync (and it will happen), mass confusion ensues. Not good.

Since I’m in the enterprise app business, you might think the purpose of my post is either to scare away potential competitors (”What we do is hard, don’t even try it buddy!”) or attract recruits (”What we do is hard: you’re a developer and you like hard problems, so come work for us.”). Actually it’s neither, although if one of those things happens as a result I’m all for it. My goal is actually to get people using the word “enterprise” properly, because it really is useful for describing certain types of software development, and we need a term for this class of software.

Rails / Ubuntu Edgy Quickstart

February 10th, 2007

If you’ve just installed a fresh copy of Ubuntu 6.10 (Edgy Eft), the following sequence of commands will give you everything you need to run Rails with MySQL or Postgres and Mongrel. (See here for the same instructions for the latest version, Feisty Fawn.) This should be run as root (”sudo su -” will get you a root shell).

First, core packages through apt-get:


echo "deb http://us.archive.ubuntu.com/ubuntu/ edgy universe" >> /etc/apt/sources.list
echo "deb http://us.archive.ubuntu.com/ubuntu/ edgy-backports main restricted universe multiverse" >> /etc/apt/sources.list
apt-get update
apt-get install postgresql-8.1 mysql-server ruby ruby1.8-dev irb rdoc libopenssl-ruby1.8 libpgsql-ruby libc6-dev

Now RubyGems:


wget http://rubyforge.org/frs/download.php/17190/rubygems-0.9.2.tgz
tar xzvf rubygems-0.9.2.tgz
cd rubygems-0.9.2
sudo ruby setup.rb
sudo gem update
sudo gem install -y rails mongrel

If it prompts you for which version of Mongrel or whatever to install, the first one on the list (type “1″ and press enter) is almost always right, unless it reads “win32″, in which case pick the first one that says “ruby”. (This silliness is definitely a major weak point of the gem package manager.)

Now, enable mod_rewrite and mod_proxy in your Apache modules (the latter is only necessary if you plan to proxy mongrel, but might as well have it):


cd /etc/apache2/mods-enabled/
ln -s ../mods-available/rewrite.load
ln -s ../mods-available/proxy.load
/etc/init.d/apache2 restart

For bonus points, you might want to install a few other useful developer tools:


apt-get install php5 php5-cli php5-pgsql php5-mysql vim-gtk vim-ruby subversion openssh-server

Gyre, the Open Source, Web-Based Debugger for Rails

February 2nd, 2007

Ruby people don’t need a debugger, because our language is so incredibly elegant that we nevercreate any bugs, right?

Er, maybe not. It does seem like my code tends to work right the first time I run it a lot more with Rails, but this only causes me to tackle yet more complex problems. The tools offered by a traditional IDE environment, though such things are generally scorned by Rails types (and this is a vim user talking here), can be quite effective in certain situations.

Thus I’ve created Gyre, a visual debugger for Rails that runs in a web browser. It’s still very raw - in fine open source tradition, I’m releasing early, releasing often. But it does work, and I’ve already found it to be of use in tracking down gnarly issues in some of my own apps.

Prototype: Sliced Bread, or Devil’s Spawn?

January 24th, 2007

People like to bitch about prototype.js, usually because it extends Array and Object in ways that are incompatible with a lot of existing code, including other add-on libraries. I fully agree with this criticism, but I have yet to find another alternative. Prototype fills a very important niche in the javascript ecosystem: a small, simple, succinct library that lets you do 95% of the things you’d want to do in a modern Ajax app.

Here are some other javascript toolkits. Mind you, these are not all trying to provide equivalent functionality. But I think it’s fair to include them all on the same list, because they are all trying to provide tools to make Javascript a more powerful language, and one more suitable for creating the types of web apps that most people want to make these days.

Mochikit is the one I’m most familiar with. It’s a great toolkit, and kind do all kinds of cool stuff that Prototype doesn’t. But, most of the time I just want to do a simple ajax call, or really minor DOM manipulation. Mochikit just feels like massive overkill in those cases.

This could be intention - Mochikit is supposed to be a heavy-weight solution, which is what you need sometimes. But being heavy-weight means that it’s got that namespaced, heavy-handed, verbose feel that I associate with Java and Python. For example, look at what you need to do to make an Ajax call in Mochikit:


var deferred_obj = MochiKit.Async.doSimpleXMLHttpRequest('/some/url');
deferred_obj.addCallback(updateDiv);
function updateDiv(result) { $('mydiv').innerHTML = result; }

Compare to Prototype:


Ajax.Updater('mydiv', '/some/url');

Aside: I’m no Mochikit expert, though I’ve used it on a few projects. If someone has a better way to write the example above, please leave a comment.

Aside 2: The technique above could more correctly be called AHAH.

You could go on and on about how Mochikit is more powerful, that its deferred object framework offers all kinds of possibilities for unusual ajax calls and other kinds of javascript magic. All that is true. But then there’s the fact that, 99.9% of the time, all you want to do is fire off an ajax call and update a div, or maybe call a function to process the results.

Easy things should be easy to do. When a “powerful” tool makes the easy case hard, I get suspicious. For code, easy means easy to write (which means, easy to remember: I don’t want to reference the docs every time). But it also means easy to read and understand later, and for that you want to be succinct and explicit. Reading the prototype code I can see that the line has something to do with ajax and something to do with updating. Simple and unmistakeable.

The best tools are ones that make the easy case easy, but still offer the power to do more complex and unusual things if you want to dive in a bit deeper. So I guess you could make a Prototype-style wrapper for Mochikit, with simple helper classes like Ajax.Updater to export a succinct interface to the powerful concepts that Mochikit offers, and that should be the best of both worlds.

As for Prototype, I’m certainly not enamored with it. In fact, I’m really hoping for is some other small library will come along and fill the same niche as Prototype, but do it better. In the meantime, Prototype is the best in that niche, so I’ll keep using it.

“Firefox Is Just a Browser”

January 16th, 2007

In my last post, I said that Firefox is “the best thing that ever happened to the web, maybe even the best thing that’s ever happened to software in general.” This off-the-cuff remark seemed to generate more buzz in the comments and on reddit than my main point.

xkcd nailed the issue with perfect humor. Everyone’s going crazy for Firefox, but come on - it’s just a browser. Right?

Well, yes and no. Yes, Firefox is a browser, and in many ways only an incremental improvement over its immediate ancestors like Netscape, IE, and Opera. But it’s also much more than that. Firefox is the enabling technology in a whole new world of software development.

I doubt I need to expound on the virtues of web applications over locally installed apps to anyone that is reading this. But really though, take a moment and think back to what software was like before web apps took over. Incredibly long development cycles, endless installation headaches, viruses, hardware and operating system incompatibility. Being forced to develop with whatever language(s) and tool(s) are available on your end user’s operating system was once the norm, and it gives me the cold sweats just to think about it now. And CDs, in a box? We were such barbarians.

In short: desktop apps sucked. They sucked to make, they sucked to use, and they sucked to support. I’m giving myself ulcers just reminiscing on those days.

Firefox is just one small piece in the web application software revolution. But because it is such a visible piece, it serves as a rallying point for all of us championing the revolution. It solved not necessarily the hardest piece of the puzzle, but the piece that software geeks were probably least equipped to solve: marketing a thin client to the masses.

It’s the bootstrap piece. With that in place, everything else gets pushed back to the server, and software geeks can focus on what they are extremely well-equipped to solve: everything else, which is all technical and design issues.

The beauty of it is that Firefox itself will become a less critical component as time goes on. It served as an emissary, a flag bearer for the technical and political elements that drive this revolution: standards compliance, markup separated from content, specialized open formats like RSS, PNG, and SVG, and client-side scripting powerful enough to do almost everything one might want an application to do. But having led the way, others will follow. And we don’t need Firefox, specifically; we need a standards-compliant browser. Pretty soon all browsers will be that, because they have to be, or be left behind.

As it turns out, replaceability is one of the guiding principles of this new generation of software. Components that can be swapped out like legos. Nothing in the web application stack is unique or can’t easily be replaced with a comparable product. Apache rules the web server world, sure, but Lighttpd is a perfectly suitable replacement. Red Hat Linux ruled the OS world as far as servers and developer workstations for a while, but then it started to suck because of the RHEL/Fedora split. Faster than you can say “lickety-split”, Red Hat was off the map and Debian’s offspring Ubuntu now dominates. Any other major component you can think of is swappable: databases (MySQL, PostgreSQL), languages (Ruby, Python, PHP), application frameworks (Rails, Django, Nitro, Symfony), shells (bash, zsh, dash) - the list goes on.

This might have been the nastiest bit of sucking from the old style of software development. In that world, you had major components that couldn’t be swapped out. Microsoft was king here of course, but they weren’t the only ones: think of Oracle, Sun, or Adobe. This control was great for the profits of the company in control of the technology, but total suck-land for everyone else in the long run.

Firefox is not just a browser; it’s a software platform. Once upon a time we spoke of developing software for DOS, or Windows, or UNIX. Now we develop for the web; and by all rights, Firefox is the web. Not by virtue of its market share, which remains a small minority; but by virtue of its leadership position within that market.

Or you can say Firefox is just a browser, as long as you also say that Linux is just another unix derivative, Microsoft Office is just another office suite, Google is just another search engine, and Rails is just another application framework.

Revolutions rarely are really something completely new. They’re always “just” an incremental improvement over whatever existing before. But that increment can be enough to launch a whole new paradigm. Firefox is one piece of a larger whole which is going to - nay, already has - change the world.

Go Ahead, Do The Big Rewrite

January 11th, 2007

Many experienced developers caution against the Big Rewrite. Perhaps the most famous of these is Joel’s adamant proclamation that the Mozilla team’s decision to rework Netscape from the ground up was “the single worst mistake” that a software team could make.

Although I agree with Chad’s arguments and to a lesser degree with Joel’s, I can’t help but to notice: what Joel called a huge mistake turned into Firefox, which is the best thing that ever happened to the web, maybe even the best thing that’s ever happened to software in general. Some “mistake.”

Ok, ok. So most of the time the big rewrite is a bad idea. Mozilla got lucky, or tried really hard, or it doesn’t count if you’re an open source project, or something.

Except that I’ve done several big rewrites of commercial applications in my software career, and every time it has gone very smoothly. In all cases the end users have been pleased, and I and the other developers find ourselves saying “We should have done this ages ago!”

In fact, Bitscribe is currently finishing up one of these right now. The application being rewritten is one of those sprawling enterprise apps with countless nooks and crannies of functionality. Written in a blend of PHP, Perl, PL/PGSQL stored procedures, and C++ (GTK 1.0, baby!), it dates back to right around the turn of the milenium. So not utterly ancient, but plenty has changed in the software world since then. The rewritten application is 100% Rails.

Everyone involved with the project just couldn’t be more pleased, from what I’ve seen. It’s been a lot of hard work, sure, but the benefits are massive. Developers are energized and excited to be working with the latest tools, and throwing out years of accumulated developer debt. (The legacy app had been maintained by a variety of different companies over the years, so you can imagine what the code looked like.) The client’s staff is loving the shiny ajaxified interfaces. And the client’s management (you know, the people who sign the checks) are seeing a whole new world of software unfold before them, and seem very aware of the efficiency improvements that will come with it.

There was a benefit that we didn’t anticipate, and it’s turned out to be one of the most useful. In the process of rewriting we’re not just porting code; we’re rethinking the design. The technical design of course, but also application design. It turns out that the wisdom the clients had gained from years of production use of the legacy application pointed to many insights on a streamlined design. We’re able to provide the majority of the functionality of the original app with a fraction of the complexity.

And not just code complexity, but user interface complexity. When all is said and done, the client’s training costs for new staff will be greatly reduced; there’s much less likelihood of entry error; and the application matches their business process more closely. Et cetera.

So I’ve never had a rewrite go badly. But maybe that’s because I’m inherently cautious and skeptical about rewrites. I lean toward waiting a bit too long, rather than doing it a bit too soon. So then by the time we go to do it, it’s really overdue.

Raganwald says “And you’ll need to be 100% sure your team has the horsepower to get the job done and is going to use a process that can handle the load.” Maybe that’s why it’s gone well for us; Bitscribe has massive developer horsepower, and massive focus on process. And even for us, there’s been lots of strain on the team doing the rewrite.

I’ll admit that there’s a unique kind of pressure that you get in this situation. It’s not like the ordinary pressure to meet software deadlines. I think it’s that sense that you can’t turn back. You don’t want to fix bugs or add features to the legacy code, but the client needs those changes so that they can do business. So then you have to press on ahead and try to get the new version workable as quickly as you can. And as Chad points out in his essay, there are seemingly endless little bits of functionality in the original app that need to be provided in the new system. It’s not a kind of pressure I’d be willing to bear most of the time, but it can be worth it when an app is really due for a bottom-up overhaul.

And let’s face it, you’ve gotta rewrite sometime - no software system can run forever, and the cost of running even a marginally outdated app can be tremendous. I guess the trick is just picking the right time to do it - and then having a healthy fear of just how big a job it really is. The moment you think it’s going to be easy, that’s the moment you’re digging your own grave. Be scared of what you’re facing and you may just have a chance.

Why Do We Still Use Relational Databases in an OO Era?

January 9th, 2007

Object-Relational Mappers (ORMs) have been a hot topic for, oh I don’t know, a decade now. Mapping an object-oriented data set onto a flat relational schema is unexpectedly difficult. Inheritence, polymorphism, and even simple deviations in type handling between SQL and your language of choice make ORMs a virtual minefield. Some have even said that ORMs are the Vietnam of computer science.

Really, though, it seems rather silly when you think about it. Why go to so very much trouble to map the data from an OO format and back again? Why not just keep the objects in object format all the time?

It’s been done. But it doesn’t work terribly well, and certainly doesn’t have anywhere near the robustness necessary for large and long-lifetime applications. Why not?

As it turns out, the limitations of a relational database are the very thing that make it so robust over the long term. There’s benefit to be gained by forcing the data to be turned into a simple, transparent, structured format every time you save it. Or indeed, to force an explicit saving step at all, instead of just persisting objects flagged to do so.

ZODB and its ilk are hauntingly similar to a core dump: easy to save and load, but fragile over any significant timespan. There’s no enforced strictness to data cleanliness when you can just dump everything out effortlessly.

Another case of embracing constraints? Maybe. I’d like to think that someday this longstanding dilemma will be resolved. Until then, thinking about ORMs this way will make me feel better about using them.

Databases Are Less Important Now

December 27th, 2006

The database has been a centerpiece of my work in application development for the better part of a decade. But now, Rails and other comparable frameworks are reshaping the way that I and others look at databases. A lot of this is stepping down the importance of the database’s role, which can take some getting used to.

The database’s role is now limited to:

  • Storage
  • Indexing - i.e. fast lookups
  • Concurrency - i.e. multiuser access, locking, transactions

There are many things that I’ve used the database for in the past that are now considered bad form:
Read the rest of this entry »

Rails Change Logger

December 9th, 2006

Audit trails are extraordinarily useful in enterprise applications. When you’ve got dozens or hundreds of users doing CRUD operations on a large database full of data, sooner or later someone is going to come across a record that has been changed, and want to know: who did this, and when? (And maybe: why? - but they can find that out if they know the first two items, namely by going and asking the person who made the change.)

I recently put together a small module for storing change logs for one of our larger Rails apps. Here’s the code:

lib/change_logger.rb


module ChangeLogger
   def self.included(other_mod)
      other_mod.module_eval do
         has_many :change_logs, :as => :record, :order => 'created_at'

         def log_change(verb)
            log = ChangeLog.new
            log.record = self
            log.verb = verb
            log.user = ChangeLogger.user
            log.save!
         end

         after_create :log_create
         def log_create
            log_change('created')
         end

         after_update :log_update
         def log_update
            log_change('updated')
         end
      end
   end

   def ChangeLogger.user=(user)
      $changelog_user = user
   end
   def ChangeLogger.user
      $changelog_user
   end
end


Read the rest of this entry »

The Myth of “Just Works”

December 3rd, 2006

This guy recently switched to OS X for the same reason that many people do: he wants a computer that Just Works.

This is, of course, an absolutely excellent reason to go Apple. The combination of quality hardware and software - all integrated together in a dazzlingly shiny package by a central authority - cannot be beaten in the computer market right now or any time in the recent past. When people ask me for computer advice, my default answer is “Get a Mac.” Without knowing anything about what they might want to use it for, I can feel confident that 98% of the time this is the correct answer.

This particular guy switched from Linux to OS X because he was tired of tinkering. That is also not an unsual story. But I do think he’s making a fundamental mistake, and a fairly common one from what I’ve seen.

When it comes to computers, there is no such thing as “Just Works.”

Let me give you an example. I bought a Macbook early this year, shortly after they came out. I’m delighted with it. To my mind, Apple defines the laptop. When I run across a PC laptop (pretty rare these days), I find myself chuckling. It feels like a Model-T, all big and clunky. In my mind’s eye it spews smoke and makes noises like ka-chunk and clang.

So my Macbook is great, but for what I do - web development - it is VERY far from Just Works. To my mind, Linux (and Ubuntu specifically) Just Works, but the Mac requires all sorts of tinkering.

In fact, using OS X’s UNIX reminds me of Linux five or six years ago. It works, sure, it’s reliable, absolutely, but Ubuntu has this polish and maturity that you can taste.

For example, I spent quite a lot of time and frustration trying to get what I consider to be basic tools - Apache 2, MySQL 5, PostgreSQL, PHP 5.1, Ruby 1.8.4 (OS X comes with 1.8.2, which won’t work with Rails) - working. The lack of any sort of real package manager, consistent location for configuration files, or startup scripts drove me insane. I invested many long days dealing with this stuff. I got a couple of seasoned OS X developers to give me a hand and even they ended up standing around scratching their heads as we dealt with trying to get these basic tools up and running. OS X doesn’t even come with gcc installed by default, for pete’s sake!

After days of downloading, compiling and recompiling, tinkering with Apache module configurations, and so forth I finally got most of the tools working. To this day I still have not been able to get Postgresql to install. And the OS X experts I consulted with assured me that things were way more difficult than this back before DarwinPorts. More difficult?!

Contrast this with the magic of Ubuntu, where all of this software is located in their highly well-maintained network repositories. Most of this software can be installed (or upgraded) by typing something like:

sudo apt-get install apache2 php5 mysql5 postgresql-8.1 ruby rails subversion

Or just finding the packages in the graphical package manager and clicking “Install” for each one.

It’s not just developer software, either. I bought a new printer (just a standard consumer laser printer), and after bringing it home decided to plug it into my Mac figuring that that would be most likely to Just Work. Nope - after some searching, I found the vendor’s download page and discovered that they don’t plan on offering Intel drivers. (Downloading drivers is one of those things that seems really archaic after you’ve been using Linux for a while. Any hardware that is going to work - which is most of it - will work just by plugging it in.) So the printer is now plugged into my Linux workstation.

I had some other rude shocks, too. Having long been in open-source land where playing movies is hit and miss, I looked forward to being able to just click on any movie trailer or some silly Internet video and have it Just Work. It’s better, yes, but not completely. To my surprise there are a number of codecs that don’t work out of the box with Quicktime. The program did not give any useful message about where I could get the codec or how I could play the movie, just aborted with a cryptic error message. A friend clued me in to downloading the DivX codec, and that seems to solve some of it, except that it seems to cause Quicktime to crash or lock up a lot. And then of course there’s Windows Media Player, which brings all the user-friendliness and reliability of Windows (read: none) to the Mac. So what I’ve found is… playing movies is hit and miss, just like it was on Linux. I can play more movies now - I think - but forget about Just Works.

In a head-to-head comparison there’s no doubt that OS X and especially Apple hardware in general wins out in the Just Works category. Nevertheless, it seems to be a widely held conception that Just Works is absolute, which it is not. It depends on what you want to do, and that’s something to keep in mind when deciding on your hardware & software platform.

I suspect most developer types are doing exactly what I do: using some combination of Linux and OS X. Most people may divide it up by using Linux (or other free unix) server-side, while using OS X locally as something between a thin client and a full development environment.

For myself it’s a no-brainer to use a Macbook for my laptop needs, since its close integration with the hardware means that stuff like wireless, battery management, and sleep mode all work beautifully out of the box, no tinkering required - and I still get access to all the really vital unix tools, like ssh. On the other hand, my Linux box is way easier to use for development tools. For example, have you tried setting up ssh-agent on OS X lately? (On Ubuntu, ssh-agent Just Works: it’s running by default for all X sessions.) And despite the impressive CPU power of the Macbook, my Pogo Linux workstation runs processor-intensive tasks like large unit test suites about twice as fast, making me much more productive when doing serious development.