开发者

Why use a nested Ruby module for version information?

I've been looking at the source code of a few ge开发者_如何转开发ms lately. One idiom that I keep seeing is the use of a nested module containing version constants that are joined into a version string i.e. variations around this sort of thing:

module ChunkyBacon
  module Version
    MAJOR = 0
    MINOR = 6
    TINY  = 2
  end

  VERSION = [Version::MAJOR, Version::MINOR, Version::TINY].compact * '.'
end

What's the advantage (if any) of storing the library version information in this way? Why not just do:

module ChunkyBacon
  VERSION = '0.6.2'.freeze
end


Having version information in a string is generally a bad idea.

For example, there can never be a Ruby 1.10, because too many applications which test for compatibility using if RUBY_VERSION > '1.6' would break. (Because lexicographically, 1.10 < 1.6) That's why there is this complicated scheme where what would normally have been Ruby 1.9.x was instead Ruby 1.9.0-x and what would have been Ruby 1.10.x is now Ruby 1.9.x+1. So, the upcoming version of Ruby, which is Ruby 1.9.2, and which looks like it were an unstable development version, is really Ruby 1.10.1, which is a production version.

This leads to a lot of confusion. For example, even many seasoned Ruby community leaders, are still spreading the misinformation that Ruby 1.9 is a development version, despite the fact that the change in versioning policy has been widely communicated.

The Opera web browser is another example. When Opera 10.0 was released, it originally reported its version number as, well, 10.0. However, during the betatest it became clear that many websites, among them very big and well-respected ones, completely broke, because Opera was the first-ever mainstream browser to hit 10.0, and those websites were doing simple string compare and thus thought they were dealing with Opera 1.0, which doesn't support JavaScript or CSS. The only workable solution was that the final release of Opera 10.0 prints 9.80 as the version number.

Mark Russinovich also had a great rant about comparing version numbers during his presentation about the Windows 7 kernel at Microsoft PDC. He was explaining to the audience why the version number of Windows 7, which used to be 7 in the early builds, was 6.1 in the release. The reason is that a lot of applications either degraded or failed to work at all. Some would simply check for if major == 6 then enhanced_vista_mode else crappy_xp_mode which means they would run degraded in Windows 7. Others were even more aggressive and had something like if major == 6 then enhanced_vista_mode elsif major == 5 then crappy_xp_mode else unsupported_windows_version and they would refuse to work at all. (Which is of course stupid since Windows 7 is completely backwards compatible with Vista.)

So, Microsoft changed the version number to 6.1, and Russinovich said, half joking, half sad and serious, that this obviously means that the version number for Windows 8 would have to be 6.1.1. and so on.

So, to make a long story short: programmers are too stupid to parse version numbers themselves, you must do it for them.


For programmatic compatibility checks, it's easier to have an explicitly separated version number.

e.g.:

require 'chunkybacon'
if ChunkyBacon::VERSION::MAJOR > 0
  # barf
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜