Thursday, March 01, 2007

Now Computerworld Jumps In On The Rails Lovefest

According to Computerworld today, Ruby on Rails is the number one of the "five most important technologies that you need to know about in 2007." Oh yeah! As I wrote a couple of days ago, now even the oldest of the old school enterprise publications are showing the love for Ruby and for Rails.

That in itself is quite exciting. Another interesting point to note, is learned by looking over the list of the other four hot technologies. Three are hardware related, and and the fourth is grid computing. So Rails is the ONLY important new application development technology right now, according to Computerworld? So it would seem...

I cannot say I disagree, but I am still amazed!

Monday, February 26, 2007

Even eWeek Is Falling For Ruby

Even that stanch old "enterprisey" publication eWeek has been giving some love to Ruby and Ruby on Rails. Today's most recent article is entitled "Ruby, Ruby, When Will You Be Mine?". Was this supposed to run on Valentine's Day? I'm definitely feeling the love in the title.

Anyhow, the author is all over the JRuby project. Messrs. Nutter et. al. have been building up the energy at the same time as the code base. Microsoft is notably receiving less coverage, no doubt due to providing no visibility as to what they are up to. I almost hate to give Sun props over Microsoft, after spending so many years arguing the opposite, but Sun is allowing the JRuby team to keep up the enthusiasm in the community. MS is giving the appearance of stagnation, even if they are just as active with development of Ruby.NET/RubyCLR/etc. For example, the Ruby.NET team is saying "This is a preliminary beta release. It is knowingly incomplete and contains many bugs. We therefore ask that you do not submit bug reports at this stage." Talk about the Wow...not. Meanwhile the JRuby team is involving the community in the entire dev process just like a real open source project does.

Based on the initial performance numbers from Antonio Cangiano, I'm probably not really looking at either one of those options for a production application any time soon. Can you say YARV?

Saturday, February 24, 2007

RailsConf 2007 Is Sold Out

My dear friends, if you don't have your ticket for RailsConf 2007, you have missed the boat. All 1200 passes have now been sold out!

I suspect that most conferences have a short peak of sales right when the passes first go on sale, then sell the bulk of their registrations in the last few days before the start of the conference, if conferences are anything like concerts. Since most conference don't have the draw of a big musical headliner, conferences sell discounted registrations for a short period of time, to encourage early registrations and guarantee that the conference sells the minimum number of attendees to break-even. If this is true, and given that RailsConf 2007 is still 3 months away, this is pretty amazing. They never even got to the end of the discounted registration period before they sold out.

If you have your position secured, then see you at RailsConf on Beer. Otherwise, well, guess I won't see you unless you somehow get thru the waiting list.

This is going to be fun...

Friday, February 23, 2007

The Wigglebot Cometh

I saw this very interesting robot today. Not only can it crawl, shimmy, roll, and walk, but it does so by combining a small group of autonomous, modular, self-reconfiguring bots that operate together as a unit. Very cool!

Transformers, indeed. Have I mentioned that I want a set of Lego Mindstorms NXT for my birthday? I would love to mess around with ruby-nxt or the Microsoft Robotics Studio.

Gazing Into The ORM

Jeremy Miller has an interesting post today regarding Object Relation Mapping (ORM). Droves of developers are now flocking to ORMs via Ruby on Rails, Castle, or one of the other many projects in this space, so it is good to have people like Jeremy exploring from a real implementation perspective.

Anyhow, his post really is concerned with applications that use an existing database, have a large amount of logical processing. Simply applying an ORM without considering the logical implications of the data, not only fails to take advantage of the power of ORMs, but falls into a bit of a quagmire, with potentially a very non-DRY result.

Some of the specific examples he cites are:


  • Big tables don't map to a single object.  I don't think it's possible that a class with a 100 different properties can possibly be cohesive.  We'd be much better off in terms of writing business logic if that 100 column table is modelled in the middle tier by a half dozen classes, each with a cohesive responsibility.  It may make perfect sense to have only one table for the entire object hierarchy, but big classes are almost always a bad thing.
  • Data Clump and Primitive Obsession code smells.  A database row is naturally flat.  I want to do a bigger post on this later, but think about a database table(s) with lot's of something_currency/something_amount combinations.  There's a separate object for Money wanting to come out.  If you make your business objects pure representations of the database you could easily end up with a large amount of duplicate logic around currency and quantity conversions.
  • Natural cases for polymorphism in your object model.  I think the roughest part of O/R mapping is handling polymorphism inside the database.  Check out Fowler's patterns on database mappings for inheritance.



He then goes on to make an important point regarding the role of the database in the software architecture of your application. Basically there are only two perspectives that make any sense:

  • The database is paramount, and the system is expressed and understood in terms of the tables and rows in the database.  The application code and even user interface is just a conduit to get information back and forth into the database.  You design the database first and then build the business and data layers to match the database.  In the .Net world we might just consume raw DataSet's in the application, effectively just working with the database tables offline.
  • The behavior of the system, primarily in the middle tier and user interface, is paramount, and the database is "just" a means to persist the state of the system.  The database is either built to match the business classes or designed somewhat independently.



So in the case of an application that has significant business logic, it would seem to me that the second case is quite preferable. However, in the case where a legacy database is involved, how can we really avoid the first? I have seen many applications get stuck in that quagmire myself, and one real problem is that the business logic becomes a lot harder to represent cleanly when having to preserve the existing database schema's problems. Especially when trying to achieve a very DSL like approach for business service layers. The less that the domain experts have to understand the database, and can just speak in terms of domain concepts, the better!

Monday, February 19, 2007

Format Ruby Code On Your Blog Postings Like The Cool Kids

I had noticed that almost all of the cool people post nicely formatted, color coded, beautiful looking Ruby code whenever they post.

Well, some of the cool people use a style of formatting that defies description...but I digress.

Anyhow, I looked at my poor pitiful postings, and felt like a second, or even third class citizen. Everybody's code is looking better than mine! What can be done?! Extreme makeover, Ruby CSS edition.

Mac developers who are using TextMate already have a built-in way to get back nicely formatted HTML. Does this mean they have built-in coolness? Yes it does. But for others who are using a different OS, or maybe an IDE like RadRails, there is also a solution.

On the Ruby Advent calendar site from last year, is a cool posting from Peter Cooper that allows you to submit some Ruby code thru a web page, and get back formatted HTML. Add a little bit of CSS to your page, and you too can be one of the cool people.

I had to modify the suggested CSS for my ultra-retro TTL terminal look that I usually set my editors up with. So my Ruby code went from this:


class Animal < DSLThing
attr_accessor :name

def initialize(name=nil)
@name = name
end
end


To this:
class Animal < DSLThing
attr_accessor :name

def initialize(name=nil)
@name = name
end
end


With my new CSS, I can now hopefully masquerade as one of the cool kids, and maybe even sneak into the club.

Wednesday, February 14, 2007

Ruby Blocks, Closures, and Continuations

Recently, while blogging about the Ruby.NET project, it was pointed out to me that I was incorrect about Ruby.NET not supporting closures. Brendan noted that in fact continuations are what is not yet supported. I quickly realized that I was not entirely clear about the differences between a closure and a continuation, except that they both used code blocks. I decided that it must be time that I figured it out.

When in doubt about any aspect of Ruby, it is best to go back to Matz. I found an interview with Matz conducted back in 2003 by Bill Venners. First, let us get Matz's definition of a block:


Yukihiro Matsumoto: Blocks are basically nameless functions...Basically, you can pass a nameless function to another function, and then that function can invoke the passed-in nameless function. For example, a function could perform iteration by passing one item at a time to the nameless function. This is a common style, called higher order function style, among languages that can handle functions as first class objects...In Ruby, the difference is mainly a different kind of syntax for higher order functions. In other languages, you have to specify explicitly that a function can accept another function as an argument. But in Ruby, any method can be called with a block as an implicit argument. Inside the method, you can call the block using the yield keyword with a value.


OK, so far so good. Any beginning Rubyist has seen the fun with blocks:

class Array
def find
for i in 0...size
value = self[i]
return value if yield(value)
end
return nil
end
end

puts [1, 3, 5, 7, 9].find {|v| v*v > 30 }

The block in the above example is used to pass a function used to tell the the "find" method how to determine when the search is complete.

SO what is a closure? Matz, enlighten us:


Yukihiro Matsumoto: ...we can create a closure out of a block. You can pass around a nameless function object, the closure, to another method to customize the behavior of the method. As another example, if you have a sort method to sort an array or list, you can pass a block to define how to compare the elements. This is not iteration. This is not a loop. But it is using blocks...

Bill Venners: What makes a block a closure?

Yukihiro Matsumoto: A closure object has code to run, the executable, and state around the code, the scope. So you capture the environment, namely the local variables, in the closure. As a result, you can refer to the local variables inside a closure. Even after the function has returned, and its local scope has been destroyed, the local variables remain in existence as part of the closure object.


Alright, so that sounds like a pretty good definition of a closure. The Wikipedia page for Ruby has a nice, simple closure example:

# In an object instance variable (denoted with '@'), remember a block.
def remember(&a_block)
@block = a_block
end

# Invoke the above method, giving it a block that takes a name.
remember {|name| puts "Hello, #{name}!"}

# When the time is right (for the object) -- call the closure!
@block.call("John")
# => "Hello, John!"

So storing a block of code into a variable makes it a closure. It can then be called later on using the "call" method.

So what is a continuation, then? A short perusal of the comp.lang.ruby group led me to this video from RubyConf 2005 where Chad Fowler and Jim Weirich explain continuations.

According to them, "A continuation is whatever happens after a block is done executing". In other words, a continuation is an object that can restore the entire context of a program back to where it was when the continuation was saved. Sounds simple enough, but the ramifications can be a little brain boggling.

To summarize a little from Jim Weirich’s blog on Ruby:


Ruby provides continuation functionality in the form of the callcc method. The continuation is passed to a block, and within the block we can do anything we want to with the continuation. Calling it will immediately cause the callcc call that created the continuation to return the value given to the continuation.


Jim provides a nice simple code example, too:


def level3(cont)
cont.call("RETURN THIS")
end

def level2(cont)
level3(cont)
return "NEVER RETURNED"
end

def top_level_function
callcc { |cc|
level2(cc)
}
end

answer = top_level_function
puts answer # => "RETURN THIS"


The block passed into the "callcc" method has a parameter which is also a block. This parameter block is a bit of code that returns control back to the original calling code, immediately after the "callcc" method was called, along with restoring the entire context from when the original call was made.

For example, in the code example above, when the level3 method hits the line with cont.call("RETURN THIS"), the code returns to the top_level_function to immediately after where the callcc method was called in the first place. The parameter passed into the call method within the level3 method is returned by the callcc function, then returned by top_level_function. This is why "RETURN THIS" is displayed by the above code snippet.

Continuation are very cool and powerful, but I can see why most people don't get them. A little search of Krugle shows very few matches for either "callcc" or "Continuation" within the Ruby projects indexed there. It would appear very few people are using them. No wonder they might be dropping them from Ruby 2.0.

Ruby.NET and REXML: Not Yet

I finally had a chance to play around with the latest download of the Gardens Point Ruby.NET compiler. At first, I was excited, as my little DSL test application was able to run perfectly. Blocks, instance_eval, singleton classes all worked fine for me. Very cool!

Then I decided to experiment with the REXML ruby parser. I did so despite the fact that the compiler authors have stated in their project goals that "We do not however plan to implement the other Ruby libraries that commonly ship with the Ruby distribution, such as CGI and DBM (except for those implemented 100% in Ruby)". Since REXML is however completely implemented in Ruby, I thought I would give it a try. Unfortunately, I discovered that the Ruby.NET authors did not lie when they said that "Implementation is not yet complete but we have now implemented the vast majority of Ruby's builtin classes and modules. We have fixed large numbers of existing bugs, but many still remain."

I tried to run the simplest possible REXML sample:


require "rexml/document"
doc = REXML::Document.new File.new("mydoc.xml")


But here was my result:


loading rexml/document
loading rexml/element
loading rexml/parent
loading rexml/child
loading rexml/node
loading rexml/parseexception
finished loading rexml/parseexception
finished loading rexml/node
finished loading rexml/child
finished loading rexml/parent
loading rexml/namespace
loading rexml/xmltokens
finished loading rexml/xmltokens
finished loading rexml/namespace
loading rexml/attribute
loading rexml/text
loading rexml/entity
loading rexml/source
loading rexml/encoding
finished loading rexml/encoding
finished loading rexml/source
finished loading rexml/entity
loading rexml/doctype
loading rexml/attlistdecl
finished loading rexml/attlistdecl
finished loading rexml/doctype
finished loading rexml/text
finished loading rexml/attribute
loading rexml/cdata
finished loading rexml/cdata
loading rexml/xpath
loading rexml/functions
finished loading rexml/functions
loading rexml/xpath_parser
loading rexml/syncenumerator
finished loading rexml/syncenumerator
loading rexml/parsers/xpathparser
finished loading rexml/parsers/xpathparser
finished loading rexml/xpath_parser
finished loading rexml/xpath
finished loading rexml/element
loading rexml/xmldecl
finished loading rexml/xmldecl
loading rexml/comment
finished loading rexml/comment
loading rexml/instruction
finished loading rexml/instruction
loading rexml/rexml
finished loading rexml/rexml
loading rexml/output
finished loading rexml/output
loading rexml/parsers/baseparser
finished loading rexml/parsers/baseparser
loading rexml/parsers/streamparser
finished loading rexml/parsers/streamparser
loading rexml/parsers/treeparser
loading rexml/validation/validationexception
finished loading rexml/validation/validationexception
finished loading rexml/parsers/treeparser

Unhandled Exception: System.MissingMethodException: Method not found: 'System.Ob
ject Ruby.Eval.ivar_defined(System.String)'.
at Ruby.Compiler.AST.PROGRAM.ExecuteMain(PEFile Assembly, String[] args)
at Ruby.Compiler.RubyMain.Main(String[] args)


Oh well! Maybe next month's release will be ready for REXML...

Monday, February 12, 2007

Just Say No To Vista?

Security expert Bruce Schneier says not to use Windows Vista, due to the flaws of the Digital Rights Management (DRM) incorporated into the OS. No, really. One of, if not THE, top security expert says not to use Microsoft's newest OS.

To quote Mr. Schneier:


Windows Vista includes an array of "features" that you don't want. These features will make your computer less reliable and less secure. They'll make your computer less stable and run slower. They will cause technical support problems. They may even require you to upgrade some of your peripheral hardware and existing software. And these features won't do anything useful. In fact, they're working against you. They're digital rights management (DRM) features built into Vista at the behest of the entertainment industry.

And you don't get to refuse them.

The details are pretty geeky, but basically Microsoft has reworked a lot of the core operating system to add copy protection technology for new media formats like HD-DVD and Blu-ray disks. Certain high-quality output paths--audio and video--are reserved for protected peripheral devices. Sometimes output quality is artificially degraded; sometimes output is prevented entirely. And Vista continuously spends CPU time monitoring itself, trying to figure out if you're doing something that it thinks you shouldn't. If it does, it limits functionality and in extreme cases restarts just the video subsystem. We still don't know the exact details of all this, and how far-reaching it is, but it doesn't look good.

Microsoft put all those functionality-crippling features into Vista because it wants to own the entertainment industry. This isn't how Microsoft spins it, of course. It maintains that it has no choice, that it's Hollywood that is demanding DRM in Windows in order to allow "premium content"--meaning, new movies that are still earning revenue--onto your computer. If Microsoft didn't play along, it'd be relegated to second-class status as Hollywood pulled its support for the platform.


Schneier then goes on to explain why story is even worse then just controlling what music or movies you can play:


Microsoft is reaching for a much bigger prize than Apple: not just Hollywood, but also peripheral hardware vendors. Vista's DRM will require driver developers to comply with all kinds of rules and be certified; otherwise, they won't work. And Microsoft talks about expanding this to independent software vendors as well. It's another war for control of the computer market.

Unfortunately, we users are caught in the crossfire. We are not only stuck with DRM systems that interfere with our legitimate fair-use rights for the content we buy, we're stuck with DRM systems that interfere with all of our computer use--even the uses that have nothing to do with copyright.


And then finally the big kicker:


In the meantime, the only advice I can offer you is to not upgrade to Vista. It will be hard. Microsoft's bundling deals with computer manufacturers mean that it will be increasingly hard not to get the new operating system with new computers. And Microsoft has some pretty deep pockets and can wait us all out if it wants to. Yes, some people will shift to Macintosh and some fewer number to Linux, but most of us are stuck on Windows. Still, if enough customers say no to Vista, the company might actually listen.


That is a pretty dark picture you paint, Bruce...

Friday, February 09, 2007

Ruby.NET Lives!

It has been radio silence for quite a while from the Ruby.NET project. Well, the eagle had landed. There is a new beta release.

Here is what they have to say for themselves:


We are pleased to announce the release of a new Beta (version 0.6) of the Gardens Point Ruby.NET compiler. Implementation is not yet complete but we have now implemented the vast majority of Ruby's builtin classes and modules. We have fixed large numbers of existing bugs, but many still remain. We have not yet implemented continuations or Ruby threads but support most other language features.

In addition to passing all 871 tests in the samples/test.rb installation test suite of Ruby 1.8.2, we are now able to support the standard Ruby test unit library and pass most of the 1864 assertions in the test/ruby test directory.

We have just started work on getting Ruby on Rails to run on Ruby.NET and have started work on adding interoperability features to allow .NET programs written in other languages to conveniently use Ruby components and vice versa. We hope to include some of these features in the next public release.

Our plan now is to perform public releases more frequently, approximately once a month. Once we have stabilized the major design choices (including those required for interop) we will move to a more traditional open source type model where others can contribute directly to the code base. We expect this to happen in the second half of this year.


They do not have closures yet, so how will they run Rails? It would appear that the JRuby team is still much further ahead, but will the .NET people catch up? I look forward to playing around with the new Ruby.NET regardless, but it doesn't sound like it will be useful to me...yet.

Thursday, February 08, 2007

Switching Back To The Mac Side Of The Force

Once upon a time, I did really cool things at Apple Computer...

It was during the reign of Jobs the First, and all was well with the world. Except for the installed base of Macs, and trying to sell businesses on buying Macs. Shareholder were incensed, board members impatient.

Even after the coup, and various poorly executed attempts to rectify the situation by the imposters Scully and Gassee could not change, and the kingdom was greatly endangered. Many of us who bled in five colors left the kingdom for greener pastures where we could make our livings under the Pax Microsoft. I feared that someday from my new vantage, I would see the final end of the great dream.

But Jobs was brought back from exile, and in due course has returned the kingdom, not only to its former glory, but stong enough to challenge the Microsoft empire.

Diehard Windows users have seen the Vista, and rejected it for the Mac Way.

Look at the slow pace of innovation in the important areas of developer tools (how many years between releases?), and software rollouts in general. Combine this with the pointless MS-centricness. Why did Visual Studio 2005 have to reinvent well respected open source tools like NUnit and NAnt, with just different for difference's sake tools MSTest and MSBuild?

With so many troubles within the diehard loyalists, mercs, and vassals, the Microsoft Empire in clearly in decline. I have seen the future, and MS is really in grave trouble. Call me opportunist, but I for one, am switching back to Mac the first chance I get! I will run Windows XP SP2 under Parallels, and have the best of both worlds.

Iteration At Jet Speed

Jeff Atwood's blog has some excellent points about agile software development, based on a cool article by Roger Sessions from MSDN.

Sessions notes the concept of the iconoclastic Col. John Boyd that speed of iteration beats quality of iteration.

Boyd decided that the primary determinant to winning dogfights was not observing, orienting, planning, or acting better. The primary determinant to winning dogfights was observing, orienting, planning, and acting faster. In other words, how quickly one could iterate. Speed of iteration, Boyd suggested, beats quality of iteration.


Jeff Atwood riffs further on this idea:

You'll find this same theme echoed throughout every discipline of modern software engineering:


  • Unit tests should be small and fast, so you can run them with every build.

  • Usability tests work best if you make small changes every two weeks and quickly discard what isn't working.

  • Most agile approaches recommend iterations no longer than 4 weeks.

  • Software testing is about failing early and often.

  • Functional specifications are best when they're concise and evolving.


When in doubt, iterate faster.

Wednesday, February 07, 2007

Time For A Little Story

Brian Marick has a great example of how to break a software feature up into user stories.

Note how looking at smaller units of granularity make it so much easier to understand, then just trying to identify an entire feature all at once.

Also note how much value even the simplest pictures add to the stories. However, a picture is not enough. I personally love to see video of the whiteboard conversations for documenting the user stories.

Tuesday, February 06, 2007

RailsConf 2007 Will Have Good Beer

Portland has good beer. There, now I've said it. One of the key benefits of holding the RailsConf 2007 conference in Portland has to be easily obtaining really good beer.

The McMenamins on Broadway is the closest place to the convention center to go where "Classics such as raspberry-tinged Ruby, medium-bodied Hammerhead and dark, strong Terminator Stout are always available."

In between the fun of learning all about Rails 2.0, Capistrano 2.0, scalability, more scalability, still more scalability, let us not forget to take the time to drink a really good beer together! Or more than one, perhaps...

Update: It's official...here is the link for RailsConf on Beer

Friday, February 02, 2007

I Will Be At RailsConf 2007

I just checked my email, and saw that registration has just opened for RailsConf 2007. I went to last year's conference, and it was the most interesting and exciting event in the software industry I had been to in years!

If you are interested in going, I suggest that you register immediately. Last year's event sold out in a couple days. When they added 100 additional spots last year, those sold out in hours!

This year's is looking to be even more amazing...be there, or spend all your time reading blogs to figure out what happened!

Thursday, February 01, 2007

Telecommuting as energy saver

The Christian Science Monitor has an opinion piece called Telecommuting as energy saver which is nicely done.

Here are a few juicy excerpts:


This new work freedom, properly handled, has the power to transform business, government, and home life. Telecommuters – those who work at home or on the road with no office at all – now number between 28 million and 32 million, according to some estimates...

Cutting out that round-trip commute to the office – which averages about 23 miles – can save nearly $1,000 a year in gasoline and avoid putting more than 6,000 pounds of carbon dioxide into the atmosphere...

Recent hearings in Congress focused on telecommuting as a way to deal with traffic, terrorism, oil dependency, and global warming. Some participants noted that remote employees make it possible for offices to operate during a serious storm, terrorist attack, or other emergency.


That last point is especially interesting. Setting up a teleworkforce plan before disaster strikes is just good business. And once you have it setup, why not just execute on the plan NOW? Look at thoses stats on CO2 emmissions reduction!

Wednesday, January 31, 2007

People are communicating beings

I ran into this older article from Alistair Cockburn the other day called Characterizing people as non-linear, first-order components in software development.

What Dr. Cockburn is talking about, is that very agile of ideas that people are the central focus for any software development effort. Developing software is not just a sausage factory of requirement documents, source code documents, and unit test plan documents. The people are what is important, not the documents.

Deep within it is a fantastic section called "People are communicating beings". In it, Dr. Cockburn says that "The most significant single factor is 'communication'", and presents an informal chart of the efficiency of communication that he uses to "inform my methodological considerations":

This chart shows that real-time, face to face communications is the most efficient. Conversely, written documents are the least efficient format.

The article goes on to say:

If this model is useful, it should inform us as to how better to work. Indeed it does, and we find the busiest projects making use of those suggestions.

'Put all the people into one room.' 'Don't give me more than 4 people, that's all I can get into one room and talking together.' These are standard recommendations of successful project leaders. They plan on using the highest communication mode, people face-to-face...'Make sure there are whiteboards and coffee corners all over the building.' Hewlett-Packard and IBM were early to observe the effectiveness of informal meeting places, and by now it has become a standard idiom in our industry that an effective design environment actively encourage and permit ad hoc meetings of small groups. Weinberg documented specific instances where casual conversations had significant effect on the overall group output [Wei]. Much progress comes when people 'just talk together.'.

A colleague of mine argued on behalf of written documents, and in his case, he took a very conventional view and insisted that the documents were the most important thing to "provide a record of what happened". Dr. Cockburn does not dismiss the need, and addresses this in an excellent manner:

The above model also allows us to make a recommendation for archival documentation:

Have the designer give a short (5-20 minute) description of the design to one or two colleagues who are not familiar with the work. They will act as ombudsmen for the viewers of the videotape. Let the people simply have a discussion of the design, with the colleagues asking questions as they need. Video the discussion. At the end, produce drawings of the examples used in the discussion, or the design drawings used, to act as mnemonic anchors of the discussion.

I was pleased to hear from Lizette Velasquez of Lucent Technologies that not only had she profitably already used that technique, but that I had forgotten to mention something important. She said it is also important to mark and index places where 'something interesting happened'. While much of the discussion proceeds at a relatively slow pace, occasionally a question triggers a flurry of significant discussion, and the viewers will want to refer back to those sections.

These days, it is possible to put the talk online with hyperlinked media.

For those who still think a book is best, consider the excellent but difficult book Design Patterns. Imagine that instead of trying to extract the meaning of the 'Decorator' pattern from the paper, you could click on the page and see one of the authors explaining the pattern in a video clip. They would, of course, rely on tonal inflections, gestures, and timing to get the idea across.

The lesson of this human characteristic is that we should try to move team communications up the curve as far as possible, given the situation at hand.


As I said, Dr. Cockburn does not dismiss the need for archival documentation, he just puts it in its place. Thank you, Doctor! I'm just glad I have some of your wisdom on video.

Programming Language Family Tree

My colleague Michael Hocter just sent me a great link to a diagram showing the history of the evolutions of the major programming languages. I just love this kind of visual representation of information!

Note how C# has taken ideas from Java...then Java goes and draws inspiration from C#. Also note how C# 2.0 takes its inspiration from Ruby. The two programming languages that drew from the most other languages (five) were Oak, which turned into Java, and Ruby.

Tuesday, January 30, 2007

What To Do When The Flu Comes For You

My dear friend and former colleague Dan Rasmus has some really important points to make regarding IT operations and emergency preparedness in his blog entry Work Interrupted - Rapid Response in a Crisis.

Thank about how many warnings we have already had about potential pandemics. If it hits, it will be too late to make emergency plans...we will need to be carrying out those plans, not talking about what they should be!

I have a supply of masks, gloves, bottled water and canned food at my home. Do you? I hope I never need them...but I have them.

Beating a Dead Horse

Last week, there was a very funny post from the extreme programming mailing list, published here.

This is quite emblematic of what dead programmers see every day, as we are often ordered to ride dead horses...

We need to add a couple to the list:

- Offshore the dead horse so we can ride it 24 hours a day
- Mandate all riding be done on site, so we can keep an eye on our dead horse

Monday, January 29, 2007

The Folly of Accountabalism

The Harvard Business Review has published their list of 20 breakthrough ideas for 2007. There are several ideas on this list with particular appeal to me. One that stands out is David Weinberger's "Folly of Accountabalism" which insists that "Accountability has gone horribly wrong. It has become 'accountabalism,' the practice of eating sacrificial victims in an attempt to magically ward off evil."

Dr. Weinberger is referring to the emphasis on corporate management and compliance that has come to dominate modern American business. Software development within corporate IT departments are just as bound by this kind of thinking as marketing or sales is. Weinberger argues that this manifests itself as several common practices.

"Deciding that the problem can be solved at the next level of detail - looking at complex systems that have gone wrong for complex reasons and writing another set of work procedures, and printing up more forms." A common approach with software development organizations is to try to become too abstract, creating a solution to every possible problem in advance.

"Assuming perfection - if anything goes wrong, it’s a sign that the system is broken." This does not allow for the "good enough" solutions that allows for the mismatches between what we can do, and what we can do now.

"Being blind to human nature - by overly formalizing processes, accountabalism refuses to acknowledge that people work and think differently. It eliminates the human variations that move institutions forward and provide a check on the monoculture that accounts for most disastrous decisions. It also makes work no fun." Need I say more!

"Bureaucratizing and atomizing responsibility - While claiming to increase individual responsibility, it drives out human judgment. When a sign-off is required for every step in the work flow, those closest to a process lack the leeway to optimize or rectify it." I was just following orders...we know where that road leads.

No wonder so many organizations try to force all of their software development processes into a waterfall! It just fits perfectly within the practices that have already fallen into due to this overemphasis on idealized management, however wrong minded it may be.

Thursday, January 25, 2007

Fabbers Gone Wild

Why stop at fabbing a chocolate bar when you can just fab your own whole factory?
According to Behrokh Khoshnevis, a USC Engineering researcher, "The goal is to be able to completely construct a one-story, 2000-square foot home on site, in one day and without using human hands."
Seems like a scene from Manna to me, doesn't it?

One Man Army

The continued rise of the individual as a viable economic unit is being covered by several bloggers, starting with Paul Kedrosky and continuing with Tim O'Reily.
The trend in human societies has been toward increasing decentralization. We see this in terms of computers (70's = mainframes, 80's = PCs, 90's = Internet, 2000's = Wireless Internet), as well as in terms of business (70's = corporate HQ, 80's = independent business units, 90's = spin-off independent companies, 2000's = supply chain integration). The numbers show that the economic impact of this has become HUGE, at 70% of US businesses.
The difference now is that individuals can impact beyond just their local geographic area. No longer just being limited to the corner store, individuals can reach beyond their neighborhood or city, to play within the broader global market.

Tuesday, January 23, 2007

Speaking The Same Language

The art of successful software development is matching the delivered software to the needs of the users. Achieving this requires that the developers and the users speak the same language regarding the problem to be solved. James Shore has a new chapter called Ubiquitous Language in his upcoming agile development book that summarizes this idea nicely.
Martin Fowler's seminal article on Language Workbenches also has really influenced my thinking. I guess the difference to me is that where Ubiquitous Language is about getting the developers to understand what the users are talking about, Language Workbenches are about building software systems using tools to translate the domain specific language into runnable code.
The foundations of these ideas have to do with human communication as much or more than they have to do with technology. For decades, good consultants have been taught "learn to speak the customer's language". The movement behind domain specific languages is just a formalization of something that has been going on for a long time. I'm pretty sure that Peter Drucker was doing something like this back in 1954 or so...just not using computers.

Sunday, January 21, 2007

The Anti-Team


Jeremy Miller and Ayende have each captured some hysterical and yet poignant slices of life from the depths of the seventh pit of hell...or your typical IT project team, as most of us more commonly know it.
If you are guilty, you know who you are. If you are innocent, then you haven't been working very long in this game...

Friday, January 19, 2007

When We Were Fab

A fabber is a machine that can make three-dimensional objects just like a printer can print in two-dimensions on a a piece of paper. Only recently had this technology escaped the realm of science fiction into the still unreal world of government and large-budget research labs...which is ironic given that the purpose of fabbers is to produce highly specialized items at very low cost.
Well, thanks to an open-source hardware/software project called Fab@Home, the technology is reaching out to the home enthusiast. You can now make anything you want, as long as it is constructed of silicone, or perhaps chocolate.

Thursday, January 18, 2007

Optimus Mini Three is Prime

Time again for another incredibly cool looking device... the Optimus Mini Three Keyboard. The description on their site says "Optimus mini is an auxiliary keyboard with three keys, each complete with an OLED screen displaying the current function."
They call it a keyboard, but I think that is quite the understatement. It is really like an external display surface that you can press. Drivers for Win32, MacOS and Linux are available. The software allows you to configure each of the three mini-screens to display the results of a "plug-in". Plug-ins display whatever they want, and there are already plug-ins that grab data from commonly used applications like iTunes to display summary info on the tiny screens.
Imagine your continuous integration system, server farm health, or stats on your plans for world domination displayed on three tiny screens. If the indicator shows something interesting, the display is actually a button that can launch your desired application. How cool is that!

Friday, January 12, 2007

Ruby Domain Specific Languages - The Basics (Part 4)

In the previous three entries in this series of postings, I have been exploring the basics of creating domain specific languages using Ruby. Since I cannot disclose details of my big financial service client's DSL, I am using this made up example to illustrate the techniques that are useful when building your own Ruby DSL. So far we have created a "PetShop" domain that allows us to interact with the Pets. Defining the behavior of new Pets is the purpose of this DSL.

For example, let's say we now want each Pet to be able to do some trick, when called on to do so. When you are defining behaviors, it is very useful to define a recipe-like syntax in a DSL.

Here is an example:

pet "Toto" do
when_performing_tricks do
sit
speak
end
end


This is just a description or recipe of what the animal is supposed to do when asked to perform it's trick. When we really want our Pet to perform, we simply say:

pet.perform


This produces the following output:

Toto will now perform...
Toto is sitting...
Toto says 'Woof!'
Let's hear some applause for Toto!
Slugworth will now perform...
Slugworth is sitting...
Let's hear some applause for Slugworth!
Tweety will now perform...
Tweety is sitting...
Tweety says 'I thought I saw a putty tat!
Tweety is flying...
Let's hear some applause for Tweety!


The Pet will do whatever tricks it knows, using this little simple bit of Ruby magic:

def self.when_performing_tricks(&routine)
@routine = routine
end

def perform
puts "#{name} will now perform..."
@routine.call
puts "Let's hear some applause for #{name}!"
end


The "when_performing_tricks" method simply stores the block, and executes it only when the time comes to "perform".

So how does the Pet know what is entailed in each trick? I have put the "sit" trick into the base Pet class (every Pet knows how to sit):

def self.sit
puts "#{name} is sitting..."
end


We can also more importantly define custom tricks per type of Pet. A simple bit of Ruby metaprogramming goodness helps us out:

def self.define_trick(name, &trick_definition)
singleton_class.class_eval do
define_method name, &trick_definition
end
end



The "class_eval" methos lets us evaluate the inside expression in the context of the class object, not just a particular instance of the object. Another bit worth noting is the helper method that I have added to the DSLThing base class called "singleton_class" that looks like this:

def self.singleton_class
class << self; self; end
end

This is just a short cut to get to the class instance object, known better to Rubyists as the "singleton_class".

Lastly, the "define_method" method then lets us define a new method for the trick. When we want to define a new trick for a particular Pet, we can simply define it like this:

define_trick "speak" do
puts "Toto says 'Woof!'"
end


Putting it all together, here are our new definitions of the tricks our Pets can do:

pet "Toto" do
when_performing_tricks do
sit
speak
end

define_trick "speak" do
puts "Toto says 'Woof!'"
end
end

pet "Tweety" do
when_performing_tricks do
sit
speak
fly
end

define_trick "speak" do
puts "Tweety says 'I thought I saw a putty tat!"
end

define_trick "fly" do
puts "Tweety is flying..."
end
end

pet "Slugworth" do
when_performing_tricks do
sit
end
end


One other interesting technique of note is that we are actually defining a new type of Pet by dynamically declaring a new class based on the Pet class. Otherwise, our custom tricks for one type of Pet might interfer with the custom tricks of another. The solution to this is using the "Object.const_set" and "Object.const_get". Here is the code I used:

def self.pet(name, &blk)
@pets ||= Hash.new
klass = Class.new(Pet)
Object.const_set(name, klass) if not Object.const_defined?(name)
p = Object.const_get(name).new
p.name = name
p.class.class_eval(&blk) if block_given?
p.copyvars
@pets[name] = p
end


In this posting I have used the DSL recipe technique, and created dynamic methods and classes. Combining these techniques can allow for a very powerful and yet concise syntax when creating your own Ruby domain specific languages.

Here is the complete listing of the code from this post:

class DSLThing
def copyvars
self.class.instance_variables.each do |var|
instance_variable_set(var, self.class.instance_variable_get(var))
end
end

def self.singleton_class
class << self; self; end
end
end

class PetShop < DSLThing
attr_accessor :pets, :people

def self.create(&block)
f = PetShop.new
f.class.instance_eval(&block) if block_given?
f.copyvars
return f
end

def self.pet(name, &blk)
@pets ||= Hash.new
klass = Class.new(Pet)
Object.const_set(name, klass) if not Object.const_defined?(name)
p = Object.const_get(name).new
p.name = name
p.class.class_eval(&blk) if block_given?
p.copyvars
@pets[name] = p
end
end

class Animal < DSLThing
attr_accessor :name

def initialize(name=nil)
@name = name
end
end

class Pet < Animal
def initialize(name=nil)
@name = name
super
end

def self.when_performing_tricks(&routine)
@routine = routine
end

def self.define_trick(name, &trick_definition)
singleton_class.class_eval do
define_method name, &trick_definition
end
end

def perform
puts "#{name} will now perform..."
@routine.call
puts "Let's hear some applause for #{name}!"
end

def self.sit
puts "#{name} is sitting..."
end
end

shop = PetShop.create do
pet "Toto" do
when_performing_tricks do
sit
speak
end

define_trick "speak" do
puts "Toto says 'Woof!'"
end
end

pet "Tweety" do
when_performing_tricks do
sit
speak
fly
end

define_trick "speak" do
puts "Tweety says 'I thought I saw a putty tat!"
end

define_trick "fly" do
puts "Tweety is flying..."
end
end

pet "Slugworth" do
when_performing_tricks do
sit
end
end
end

shop.pets.each_value do |pet|
pet.perform
end

Thursday, January 11, 2007

Rewrite Of No Return

I am really into Kevin Barnes' article "To Rewrite Or Not To Rewrite". He is on the right track about the challenges and tactics for a rewrite of any complexity. Chad Fowler is also exploring the big rewrite, and has fun things to say in a whole series of postings.
Rewriting a system too soon can be a waste of resources. One of the points of SOA is to allows services to be rewritten as needed, not just because a cool new technology can come out, but because there is value to be gained from doing so. For example, one of the best reasons to rewrite a system in a new language is if that the cost of extending the rewritten system will be less than the cost of maintaining the old one.
However, another factor is that near the end of the lifecycle of any system, a time comes when a rewrite may no longer be possible, without impacting the current operations of the existing system. Once you have reached a "development box canyon", your options are limited, and all of them painful. What do you mean, "we", kimosabe?

Tuesday, December 19, 2006

The Man Who Sold The World

Was Thomas Edison the world's first patent troll, or at least the most famous? Fortune's Business Innovation Insider displays a list of the "nine things Edison never actually invented." In case you were wondering, yes, Edison did sue rivals to enforce his patents.
Just for fun, compare the lives of Edison and his great rival Nikola Tesla. Edison was everything that Tesla was not. In particular, financially successful. However Tesla really was a great inventor. Without Tesla's polyphase alternating current power distribution technology, the world would not have developed the widespread use of electric power.
Which is not to say that Edison did not contribute anything...but his contributions were more developmental than inventive in nature.

Patently Absurd

Paul Kedrosky comments on the latest travesty in the abusive system that we use here in the US for "protecting" intellectual property related to computer software.
As someone who gets paid by creating IP, I am supposed to support the US patent system, right? But I cannot help but think, what if the attitude of the early innovators in software had been like that of the current industry? How would have kids like me grown up hacking the Apple ][ using the published source code of its ROM? How would the Mac or Windows been created without mimicking the various OSes that went before it? How would innovation have occurred at all, let alone at the pace at which we have grown?
I look at my career, and it only exists thanks to standing on the shoulders of the giants. Where will we tell the next generation of dead programmers to stand? If we do not cultivate the minds and collective knowledge of our industry, the future programmers may be standing in an unemployment line.
Patents are intended to protect the public good, not merely to enrich individuals. If we do not reform the patent system for software, and quickly, we run the risk of massive consolidation in intellectual capital. Without the entrepreneurism and sharing of ideas that have made the software industry an engine of economic growth, the future of the US will be much poorer as a result.

Thursday, December 14, 2006

Merb Is The Word

I have been playing around with Merb, which is a very cool project from Ezra Zygmuntowicz. Merb combines the Mongrel web server with a lightweight Ruby web framework. It has way less stuff in it than Rails, but is somewhat more than Camping.
Where this all started, was that I was looking for some way to use Mongrel to create a new REST web service for a client. This service has no UI, and basically just needs to front end a Ruby DSL that I have been working on. Another need was that I had to have something that can easily handle multithreading. Rails will block on a single thread, and also I do not need all of the Rails AJAXy goodness. So Rails seemed like a bit too much, and Camping not quite enough.
It was at this point that I discovered Merb. Merb handles threading very simply, by dispatching each new request to a new controller created on a new thread. It also has a very clean and simple support for rendering of HTML, JavaScript, and XML views. In my case, I only really cared about returning XML, so Merb seemed ideal for my needs on this project.
Starting a new Merb project requires some hand copying of files. There is a sample application included, which helps see some of what Merb can do, as well as showing how to setup your own project. At this point, Merb is very early in its lifecycle, so if you want to use it, prepare for a hands-on experience. The Merb code is very simple and clear, however, so it is not hard to see what is going on under the hood.
One of the main problems that Merb was designed to solve is better handling of long running server processes. One example of this is uploading files to your web server. Rails will block on each file upload until the upload is completed, which is a recipe for poor performance (read server unresponsive) if you will have a lot of requests to upload big files. The Merb sample app shows how to use Merb to deal with file uploads. And since Merb supports ActiveRecord, you could easily integrate a Rails app with a small Merb app or two to handle some performance bottlenecks.
Merb is much newer than Rails or Camping, but despite it not being even quite half-baked yet, the parts that are finished are delicious! Looks like it will be a really nice option for an alternative/adjunct to Rails. Now someone just needs to create a generator that lets you start a new Merb project...and some documentation/tutorials.

Monday, December 11, 2006

Resistance To Change

Obie Fernandez comments on Seth Godin's observation that he would be a lousy pilot. Maybe this explains why I do not have a pilot's license...
Obie notes that "innovators catch the most grief from management". But why would this be the case, when management is so eager to capitalize on said innovations? Perhaps a look at anthropology can help. A few years ago I watched a fantastic program on the Discovery Channel called "Walking With Cavemen." As one review of the DVD on Amazon states, "Using real actors and actresses, amazing make-up and special effects, Professor Winston takes us through the lives and times of our remote caveman ancestors." The part that impressed me the most was a example of why Neanderthal was eventually replaced by Homo sapiens, although the two lived side by side for thousands of years.
Homo sapiens was able to learn from experience, and change behavior based on new observations. The example used in the show was that by seeing a group of scavenger birds flying in a circle in the distance, and then noting that a dead animal was in the same location where the birds had been flying, a group of homo sapiens was able to find food the next time they saw birds flying in a circle. A group of Neaderthal was unble to make the connection, and starved to death.
Consequently, homo sapiens was able to survive climate changes that caused Neanderthal to become extinct. Simply enough, our capacity to change and adapt, which is our greatest survival trait as a species, is what most people actually resist the most.

Friday, December 08, 2006

That Ruby Is So Hot Right Now...

I was just reading the latest stats from the TIOBE Programming Community Index. What is this index? They say themselves that it "gives an indication of the popularity of programming languages." Yes, I know what Mark Twain had to say about stats, but I still love reading them! Anyhow, the latest and greatest December 2006 stats are fascinating as usual.
Ruby is still surging in popularity, in fact it has had the biggest rise in popularity over the last year of any language in the top 20. I know that Python/Django enthusiasts have been dissing Ruby heavily of late, but I refuse to get drawn in to any such nonsense. Any language that people actually use has good things going for it at something, or no one would use it at all. Especially any language that is reasonably popular.
Besides, dead programmers are eager to learn new languages. I myself am fluent in 7 of the top 20 languages, and able to fake my way thru a few others. And I'm sure that there are others out there who know more of the languages in this list than I do.
But my love affair with Ruby continues, and it sure looks like I am not the only one!

Friday, December 01, 2006

RubySSPI Gets Thru The Firewall

One of the biggest problem that Guerilla Rubyists have had getting our favorite language into the big companies that pay our bills, has been the corporate firewall. Using corporate Windows machines, behind corporate firewalls that use NTLM authentication to the corporate domain, has meant "no Ruby programmatic access to resources on the other side of the firewall." In other words, no RubyGems! Having to try to download every Gem (and every Gem that the Gem you want to install depends on) for a local install it at the very least a big pain in the behind. I have been feeling this pain for a couple of years now!

Recently Justin Bailey released a Gem called RubySSPI that patches the Net::HTTP class to support NTLM authentication. I was excited! I manually downloaded and installed it...but it did not work for me. Others had successfully used it, however, so I did not give up so easily.

I have been working with Justin Bailey to help him figure out why it was not working in our typical huge corporate environment, and we have achieved success! I was just able to download a Gem in the "normal" way. I'm sure he will uploading an updated version of the Gem soon...Thank you, Justin!

Saturday, November 25, 2006

New Hebruby Release

I have just released a new update of Hebruby, the Ruby hebrew date conversion library. It is now available as a proper Ruby gem, and has much improved documentation. If your Rails application needs to convert from julian date to a hebrew date, or from a hebrew date to a julian date, or display a date in hebrew (either in hebrew or transliterated into english) this gem is for you.
To install it, just:

gem install hebruby

Thank you to everyone who has helped with Hebruby, especially Joshua Harvey, and enjoy!

Sunday, November 19, 2006

Ruby Domain Specific Languages - The Basics (Part 3)

This is another installment in a series about creating domain specific languages with Ruby. In part 1 and part 2 of this series, I created a simple Ruby DSL to describe the relationship between Pets and Persons. Now I will extend the DSL, and use some cool Ruby metaprogramming tricks to demonstrate the power and benefits of using Ruby to create an internal DSL.
First, I want to simplify the syntax for declaring things in our DSL. Getting rid of the class definition stuff can make it a lot easier for domain experts to read. A simple, cool declarative style like Rake is what we want to end up with, something like this:

person "Dorothy" do
temperament :nice
food :sunflower_seeds, :carrot_juice
end

Furthermore, I want to extend our DSL to put all of the descriptions of Pets and Persons together into a PetShop. Here is our PetShop DSL:

shop = PetShop.create do
pet "Toto" do
friend_test do |person|
true unless person.temperament == :mean
end
end

pet "Tweety" do
friend_test do |person|
person.has_food?(:sunflower_seeds)
end
end

pet "Slugworth" do
friend_test do |person|
true # I like anyone
end
end

person "Dorothy" do
temperament :nice
food :sunflower_seeds, :carrot_juice
end

person "Witch" do
temperament :mean
food :cheetos, :soda
end
end

One interesting technique used is declaring the "pet" within the "do-end" block for the "petshop" object:

shop = PetShop.create do
pet "Toto" do
friend_test do |person|
true unless person.temperament == :mean
end
end

...
end

The little bit of DSL niceness is achieved using the class_eval method. The block of code within the "do" block is called in the context of the newly created object. Here is the Ruby code that achieves this for a new Pet:

def self.pet(name, &blk)
@pets = Hash.new
p = Pet.new(name)
p.class.class_eval(&blk) if block_given?
@pets[name] = p
p.copyvars
end


Now that we have declared all of the Pets and Persons in to the context of a PetShop, we can test the relationships between Pets and Persons is a more general purpose way then in my previous post. The older, more fragile code was this:

dog = Toto.new
bird = Tweety.new
snail = Slugworth.new

person = Dorothy.new
puts "#{dog.class.name} is a friend of #{person.class.name}: #{dog.is_friend?(person)}"
puts "#{bird.class.name} is a friend of #{person.class.name}: #{bird.is_friend?(person)}"
puts "#{snail.class.name} is a friend of #{person.class.name}: #{snail.is_friend?(person)}"
puts

person = Witch.new
puts "#{dog.class.name} is a friend of #{person.class.name}: #{dog.is_friend?(person)}"
puts "#{bird.class.name} is a friend of #{person.class.name}: #{bird.is_friend?(person)}"
puts

The new, cleaner code is like this:

shop.people.each_value do person
shop.pets.each_value do pet
puts "Is #{pet.name} a friend of #{person.name}? #{pet.is_friend?(person)}"
end
end

And here is the output when we run the program:

Is Toto a friend of Witch? false
Is Slugworth a friend of Witch? true
Is Tweety a friend of Witch? false
Is Toto a friend of Dorothy? true
Is Slugworth a friend of Dorothy? true
Is Tweety a friend of Dorothy? true

We have simplified the syntax of our domain specific language, and added some additional functionality. We have also been able to reduce the amount of Ruby code required at the same time.

Here is the final version of the code:

class DSLThing
def copyvars
self.class.instance_variables.each do |var|
instance_variable_set(var, self.class.instance_variable_get(var))
end
end
end

class PetShop < DSLThing
attr_accessor :pets, :people

def self.create(&block)
f = PetShop.new
f.class.class_eval(&block) if block_given?
f.copyvars
return f
end

def self.pet(name, &blk)
@pets ||= Hash.new
p = Pet.new(name)
p.class.class_eval(&blk) if block_given?
@pets[name] = p
p.copyvars
end

def self.person(name, &blk)
@people ||= Hash.new
p = Person.new(name)
p.class.class_eval(&blk)
@people[name] = p
p.copyvars
end
end

class Animal < DSLThing
attr_accessor :name

def initialize(name=nil)
@name = name
end
end

class Person < Animal
attr_accessor :temperament

def initialize(name=nil)
super
end

def self.temperament(type)
@temperament = type
end

def self.food(*types_of_food)
@food = []
types_of_food.each do |food|
@food << food
end
end

def has_food?(type_of_food)
@food.include?(type_of_food)
end
end

class Pet < Animal
def initialize(name=nil)
super
end

def self.friend_test(&test)
@friend_test = test
end

def is_friend?(person)
@friend_test.call(person) == true
end
end

shop = PetShop.create do
pet "Toto" do
friend_test do |person|
true unless person.temperament == :mean
end
end

pet "Tweety" do
friend_test do |person|
person.has_food?(:sunflower_seeds)
end
end

pet "Slugworth" do
friend_test do |person|
true # I like anyone
end
end

person "Dorothy" do
temperament :nice
food :sunflower_seeds, :carrot_juice
end

person "Witch" do
temperament :mean
food :cheetos, :soda
end
end

shop.people.each_value do |person|
shop.pets.each_value do |pet|
puts "Is #{pet.name} a friend of #{person.name}? #{pet.is_friend?(person)}"
end
end

Monday, November 13, 2006

The Dark Side Of Metrics

I have usually been in favor of measurement of any possible aspect of the software development process. Proper techniques of gathering and analyzing metrics have been espoused since Capers Jones created the study of software measurement. I was first introduced to many of these concepts in the writings of Steve McConnell, particularly when his book Rapid Development first came out. If a thing cannot be measured, it cannot be easily studied or improved.
But any tool, no matter how well intentioned its purpose, can be used for ill. Any system that relies entirely on user entered information can by lied to. Such systems can be gamed, for various purposes. In a very political environment, a rogue group can manipulate their own metrics to gain power over other groups, gain budget, or simply steer the company in the direction of their own egos. Sometimes metrics can be used to hide something important. "But look at our metrics," protests the manager in charge of a spectacular failure.
Even worse, once this starts to happen, the "everybody's doing it" syndrome strikes, and it can spread like a disease. Pity the poor foolish team that actually tries to tell the truth within such a system once this dynamic sets in. They will be punished, sometimes severely, for "not measuring up to the standards of the company".
The best sorts of metrics are collected automatically. All sorts of interesting information can be learned from analysis of the source code repository. Other information can be assessed from other dynamic sources such as number of unit tests passed, or Fitnesse tests, or measuring Running Tested Features. The important thing is that it is a lot more reliable to use metrics that are not so easily fooled by people with various agendas.

Wednesday, November 08, 2006

Ruby Domain Specific Languages - The Basics (Part 2)

Previously, I was exploring the basics of DSL creation using Ruby. This post continues sharing my lessons learned while developing a prototype of a domain specific language in the mortgage industry. Since I cannot share the actual code itself belonging to my client, I will continue to extract the useful concepts into these simple examples.

Last time we created a simple Animal DSL class. The important part of that class is this bit that makes sure our DSL like syntax works for the declarative methods:

class Animal
attr_accessor :number_of_legs

def self.number_of_legs(number_of_legs)
@number_of_legs = number_of_legs
end

def initialize
self.class.instance_variables.each do |var|
instance_variable_set(var, self.class.instance_variable_get(var))
end
end
end

Now we will create a Person class that can interact with the Animals. Each Person will have a temperament (either mean or nice), and will be carrying some kind of food in their pocket to feed their pet. We will define people using our DSL as follows:


class Dorothy < Person
temperament :nice
food :sunflower_seeds, :carrot_juice
end

class Witch < Person
temperament :mean
food :cheetos, :soda
end


The implementation is very similar to the basic Animal class

class Person < Animal
attr_accessor :temperament

def self.temperament(type)
@temperament = type
end

def self.food(*types_of_food)
@food ||= []
types_of_food.each do |food|
@food << food
end
end

def has_food?(type_of_food)
@food.include?(type_of_food)
end
end


Since we are working with an array, the self.food method has a variable number of parameters, represented using the asterisk in front of the parameters list. The cool little idiom @food ||= [] returns with the current @food variable, or if it is nil, returns an empty array. There is also a has_food? method to tell us if a person is carrying a certain type of food.

Now let us introduce the Pet. We will use the power of Ruby blocks to tell each pet the rules about when it likes a person, or not. Here is the DSL we want to use for the Pets:

class Toto < Pet
friend_test do |person|
true unless person.temperament == :mean # I like anyone who is not mean
end

end

class Tweety < Pet
friend_test do |person|
true if person.has_food?(:sunflower_seeds) # I like anyone who has sunflower seeds
end
end

class Slugworth < Pet
friend_test do |person|
true # I like anyone
end
end


And now the implementation of the Pet class:

class Pet < Animal
def self.friend_test(&test)
@friend_test = test
end

def is_friend?(person)
@friend_test.call(person) == true
end
end


The friend_test method stores a block containing the test for that Pet, and the is_friend? method tests to see if a Pet will be friendly toward a particular Person.
Last, we put it all together with some simple code to display the interactions between the People and the Pets:

dog = Toto.new
bird = Tweety.new
snail = Slugworth.new

person = Dorothy.new
puts "#{dog.class.name} is a friend of #{person.class.name}: #{dog.is_friend?(person)}"
puts "#{bird.class.name} is a friend of #{person.class.name}: #{bird.is_friend?(person)}"
puts "#{snail.class.name} is a friend of #{person.class.name}: #{snail.is_friend?(person)}"
puts

person = Witch.new
puts "#{dog.class.name} is a friend of #{person.class.name}: #{dog.is_friend?(person)}"
puts "#{bird.class.name} is a friend of #{person.class.name}: #{bird.is_friend?(person)}"
puts "#{snail.class.name} is a friend of #{person.class.name}: #{snail.is_friend?(person)}"


The result of running this code is:

Toto is a friend of Dorothy: true
Tweety is a friend of Dorothy: true
Slugworth is a friend of Dorothy: true

Toto is a friend of Witch: false
Tweety is a friend of Witch: false
Slugworth is a friend of Witch: true

Using this simple Ruby DSL approach, it is very easy to add a new Person or Pet, just by entering the rules that define its behavior. As the objects in a system become more complex, one of the best ways to manage that complexity is to create an abstraction that hides the ugly bits.

Here is the full code for this example:

class Animal
attr_accessor :number_of_legs

def self.number_of_legs(number_of_legs)
@number_of_legs = number_of_legs
end

def initialize
self.class.instance_variables.each do |var|
instance_variable_set(var, self.class.instance_variable_get(var))
end
end
end

class Person < Animal
attr_accessor :temperament

def self.temperament(type)
@temperament = type
end

def self.food(*types_of_food)
@food ||= []
types_of_food.each do |food|
@food << food
end
end

def has_food?(type_of_food)
@food.include?(type_of_food)
end
end

class Pet < Animal
def self.friend_test(&test)
@friend_test = test
end

def is_friend?(person)
@friend_test.call(person) == true
end
end


class Toto < Pet
friend_test do |person|
true unless person.temperament == :mean
end

end

class Tweety < Pet
friend_test do |person|
person.has_food?(:sunflower_seeds)
end
end

class Slugworth < Pet
friend_test do |person|
true
end
end

class Dorothy < Person
temperament :nice
food :sunflower_seeds, :carrot_juice
end

class Witch < Person
temperament :mean
food :cheetos, :soda
end


dog = Toto.new
bird = Tweety.new
snail = Slugworth.new

person = Dorothy.new
puts "#{dog.class.name} is a friend of #{person.class.name}: #{dog.is_friend?(person)}"
puts "#{bird.class.name} is a friend of #{person.class.name}: #{bird.is_friend?(person)}"
puts "#{snail.class.name} is a friend of #{person.class.name}: #{snail.is_friend?(person)}"
puts

person = Witch.new
puts "#{dog.class.name} is a friend of #{person.class.name}: #{dog.is_friend?(person)}"
puts "#{bird.class.name} is a friend of #{person.class.name}: #{bird.is_friend?(person)}"
puts "#{snail.class.name} is a friend of #{person.class.name}: #{snail.is_friend?(person)}"

The Planning Game Vs. The Crying Game

James Shore just posted a very cool chapterette from his upcoming book on agile development called "The Planning Game". The concept simply enough is that customers and developers work together to plan what features are going to be implemented, and in what order. Customers know what features have the most value to the business, so they get to choose the order in which features are developed. Developers know about the costs, so they get to say how long something is going to take.
In the Planning Game, the play is not quite so simple as the description above might suggest. As each team discusses a feature from their perspective (cost vs. value), the requirements for that feature can come into clearer focus, or be negotiated to reduce their cost.
More often, what I have experienced is the "Crying Game": whoever cries the loudest gets their way. The outcome of the Crying Game is not a good one. Either arbitrary and unrealistic deadlines are set by customers, or the wrong solution is provided by the developers. The crying doesn't end there; everyone is crying later as the recriminations fly back and forth. The moral of the story is that internal cooperation yields a lot more business value than internal competition.

Saturday, November 04, 2006

Ruby Domain Specific Languages - The Basics (Part 1)


I have been working on a prototype of a Ruby domain specific language for one of my clients, a very large financial services company. I have learned a whole bunch of really interesting lessons, which I will share over a short series of posts as I make more progress.

The first thing I tried to do was create a basic bit of DSL tastiness like this:


class Dog < Animal
number_of_legs 4
end

class Bird < Animal
number_of_legs 2
end

class Snail < Animal
number_of_legs 0
end



My first implementation of the Animal class looked like this:


class Animal
attr_accessor :number_of_legs

def self.number_of_legs(number_of_legs)
@number_of_legs = number_of_legs
end
end




Just looking at this bit of code, it seems like it should work. However, when trying this, it doesn't work as expected.


pet = Dog.new
p pet.number_of_legs # prints nil




In Ruby EVERYTHING is an object. This includes the class objects themselves, not just the instances of class objects! This means that when the number_of_legs method is called, it is actually being called before the actual instance object itself has been created. We need to get to our instance variable, and one way is to copy the class-level instance variable to the instance itself when the actual instance is being initialized like this:


class Animal
attr_accessor :number_of_legs

def self.number_of_legs(number_of_legs)
@number_of_legs = number_of_legs
end

def initialize
instance_variable_set("@number_of_legs", self.class.instance_variable_get("@number_of_legs"))
end
end


Now the class works as expected:


pet = Dog.new
p pet.number_of_legs # prints 4




As you add new things to your DSL, having to copy each variable manually is boring. The final change is to copy every class instance variable automatically at initialization, as follows:


class Animal
attr_accessor :number_of_legs

def self.number_of_legs(number_of_legs)
@number_of_legs = number_of_legs
end

def initialize
self.class.instance_variables.each do var
instance_variable_set(var, self.class.instance_variable_get(var))
end
end
end


This is a lot cleaner, and is much more maintainable code.

Thursday, November 02, 2006

Gmail For Mobile Rocks


I just installed the brand new Gmail for Mobile on my Motorola RAZR. In just a matter of a couple moments, I was looking at my Gmail inbox! Gmail for Mobile is a Java-applet that runs on your Java enabled phone. Keeping the network traffic down this way is a lot better option that a WAP-based email solution, which is what I had tried and abandoned previously.


Not having a QWERTY keyboard is a big limitation for smartphones especially where something heavily textual like email is concerned. Gmail for Mobile deals with this thru a clever mapping of hotkeys to the most commonly used functions (delete, in my case).

Between Google Reader, and now this Gmail for Mobile, another bit of my online existence has been sucked into the Googlesphere...and I like it!