More Thoughts About FXRuby API Changes
Per the last few posts, I’m thinking a lot about potential API changes for the upcoming release of “FXRuby”:http://www.fxruby.org/ 1.6.
When Jeroen began developing “FOX”:http://www.fox-toolkit.com/ way back when, most of the available C++ compilers didn’t have great support for C++ namespaces. As a result, FOX classes ended up with an “FX” prefix to avoid name clashes. That is of course of little concern to Rubyists, as the @Module@ construct provides (among other things) a way of maintaining separate namespaces for different code libraries. Despite this, the FXRuby classes followed the standard FOX naming conventions, and so we end up with the visually jarring situation that the fully-qualified name for FOX’s button class is @Fox::FXButton@.
So one of the major changes that I’m considering for FXRuby 1.6 is renaming the classes by removing the “FX” prefix from the existing class names and method names. @Fox::FXButton@ becomes @Fox::Button@, @Fox::FXLabel@ becomes @Fox::Label@, and so on. There’s no technical reason to make such a change, but it would be more aesthetically pleasing. One disadvantage of this change would be that the FOX and FXRuby class names would no longer quite match up (although it wouldn’t be much of a brain twister to convert between the two). A more significant disadvantage is that it would break a lot of existing code. This problem could probably be alleviated by using @const_missing@, e.g.
module Fox
def self.constmissing(classid)
name = "FX" + classid.tos
if constdefined? name
constget(name)
else
super
end
end
end
Another change that I’m considering is switching from CamelCase method names to method names with underscores, so that @beginWaitCursor@ becomes @beginwaitcursor@. As with the proposed change for the class name, the potential for code breakage could be alleviated by the careful use of @method_missing@, with something along the lines of:
class FXObject
def methodmissing(methodid, args)
camelcase = methodid.tos
while camelcase =~ /([^_])(.)(.*)/
camelcase = $1 + $2.upcase + $3
end
if respondto? camelcase
self.send(camelcase.tosym, *args)
else
super
end
end
end
Note that this idea was “inspired” by Richard Dale’s work on Ruby/Qt.
I vote to leave the ‘FX’ in there. I’d probably feel differently if Fox had gotten rid of theirs. But, that combined with all the code it would break. I don’t think it’s worth it.
As far as CamelCase methods, I don’t know. I really, really, really wish Ruby had a standard for this. But there seems to be variety of styles out there right now.
Personally, I’d keep CamelCase.
Thanks for all your hard work on FxRuby. Keep it up!
Jacob
February 15th, 2006 at 4:41 pmJacob, the point of using the @const_missing()@ and @method_missing()@ tricks described in the article is so that old code *won’t* break. And as for the CamelCase versus underscores debate, I think the argument’s been settled as far as the Ruby core and standard library are concerned (and the “underscores” crowd won). You’re right that the debate still seems to be going on in third-party libraries, though.
February 15th, 2006 at 5:20 pmEven though these changes might be a little painful in the transition period, I think they are worth the consideration. Personally, I find it hard the “camelCaseStyle” of the methods as they are very unusual in Ruby and it makes the “context switching” of writing with_underlines and withoutUnderlines very bothersome in my opinion. I remember when I first converted from Java to Ruby and how my code had many Java conventions rather than Ruby conventions. Nowadays I prefer the Ruby conventions all the way. Between FXButton and Button it does not affect me as much, but I’m afraid that some “include Fox” could cause some kind of confusion between a custom class Button and the default Fox::Button one.
Anyway, I think it’s a bold move, and it’s worth the problems. The only notable difference will be to know how to search for the right method or class in Google if you want to search the Fox documentation rather than the FXRuby one.
I think you have many variables and I hope people will help to decide on this.
Cheers.
February 15th, 2006 at 10:08 pmLyle, when I introduced namespaces in FOX, I went to similar considerations as you are now proposing. I decided to leave things the way they were, because it would require a lot of extra documentation work [keep in mind that that I while of course I *can* change my own documentation, I don't know how to propagate such a change across the world where people have done translations and additional wiki pages and so on]. In the case of C , elimination the prefix would introduce possible name-collisions in existing programs and it is not always clear that these will be detectable.
In fact, my new project, Lumos, does not rely on any any prefixing, and while this gives somewhat more reasonable code, I’ve already found quite a number of cases where the namespace must be explicitly used to disambiguate symbols.
Even though that’s exactly what namespaces are for, of course, it still looks a bit inelegant compared to the alternative, and it makes it less transparent to determine which library a symbol comes from in larger software projects using several libraries.
I’m not sure to what extent the arguments above apply to [FX]Ruby, but I’m sure at least some of them do.
Jeroen
February 15th, 2006 at 10:42 pmJacob, there _is_ a standard for method naming in Ruby: the convention the ruby core and most of it’s standard libraries are following.
lyle, i am glad you decided to make fxruby more a ruby-style library as opposed to a authentic copy of the c API with all it’s flaws. i fully respect and support this decision!
there is annother thing which i want to suggest: please add default arguments for all constructor parameters with index > 0.
i mean: a default text for Button, default settings for Mainwin, etc. this would make the API even more easy to use:
include Fox
app=App.new
MainWin(app){|mw|
Button.new(mw){|button|
button.text = “Click Me”
…
}
}
the motivation for this is: i often get confused with the different sets of parameters in widget constructors. Some have a message target in the constructor, some don’t. to quickly code a gui it is most annoying to look up the parameterlist for every constructor in the docs. the problem is not their quantity (there are 1-4 parameters that don’t have default values in every widget constructor) – it is the inconsistency that makes it hard to remember.
apart from that it makes automatic code generation hard. for foxguib i decided to subclass every foxwidget to provide uniform constructors and to resolve some other inconsistencies in the API. since then i have allways used the simplified API (the fx library that is required by all foxguib-generated code) when i wrote gui-code by hand, because it was faster. would be great if fxruby provided uniform constructors.
annother thing that i often miss: a visible=(bool) method for Fox::Window. it is inconvenient to map a boolean variable to show / hide.
there are much more suggestions which i currently fail to recall. i will tell you later if you are interested.
– henon
February 16th, 2006 at 2:00 amAnother possibility is to put the new API in a different require file, and then have the current require files do something like this:
require ‘fox/newapi/whatever’
module Fox
FXButton = Button
end
Method aliasing could do the same for the camelcase issue. The advantage is that you don’t need const/method_missing (which can be fragile is not done carefully). The downside is a lot of explict renaming and aliasing that would need to be maintained (but remember, automation is your friend).
Just some thoughts.
February 16th, 2006 at 8:11 am*Henon*, thanks for the encouragement and the suggestions. Please use the “Bugs”:http://rubyforge.org/tracker/?atid=1223&group_id=300&func=browse and “Feature Requests”:http://rubyforge.org/tracker/?atid=1226&group_id=300&func=browse trackers at the RubyForge project page to record those suggestions so that they don’t get lost in the shuffle!
*Jim*, I had wondered if the proposed approach was an “abuse” of @method_missing@ and @const_missing@, or if there were other complications that I hadn’t considered. I will also consider just coding-up an add-on library that provides aliases and renames for the class and method names, per your suggestion.
February 16th, 2006 at 10:14 amLyle,
Thanks again for FXRuby. It’s a great help for my main Ruby project.
FWIW, I think underscores instead of camel case is a great idea. The camel case bothers me more than it probably should.
I also like your namespace proposal. Since we have to live with a Fox-Ruby “bridge” no matter what, we may as well take advantage of it and make the names clearer. I don’t think it will make it any harder to use the API docs.
February 16th, 2006 at 10:53 amLyle,
Having used a lot of FXruby code in FreeRIDE, I’d say that I can live with the FX prefix. If you include Fox you don;t have to specify Fox:: anyway and I would even argue that, on the contrary, having the FX prefix and even the camel case makes it easy to distinguish method names that deal with UI stuff from others like standard libraries.
February 16th, 2006 at 3:06 pmLyle,
ok, i will submit the suggestions as feature requests.
a completely new API in a different module would not only be more robust than the method_missing hack (which slows down old camelcased code with an extra indirection for each method call) – it also brings the chance to do a more sophisticated redesign. i.e. resolve the “create issue” and much more.
if you finally deside to code up a new API module i would like to volunteer to join the project
as you might know i have quite some experience because i actually did the same thing for foxguib. well, back then i was more of a hacker than a software engineer so i would like to do it again and well this time. also i would like to work together with a even much more experienced guy like you. and finally, i have a lot of ideas for improvements and simplifications based on usage experience of fxruby.
– henon
February 16th, 2006 at 3:59 pmComing to this thread late … I really like all the suggestions here … no FX prefixes, underscores instead of camelcase in method names, and more default arguments.
April 3rd, 2006 at 9:45 am[...] When I say that I’ve finished the first wave of development, what I mean is that I’ve made all of the necessary updates to make FXRuby compatible with FOX 1.6. I have not yet begun work on any of the new features that I’d like to introduce in the FXRuby 1.6 line, but some of those features include: As previously discussed, there are some global API changes that I’d like to make to the naming of classes and methods in FXRuby. [...]
April 27th, 2006 at 12:32 pm