Thread: [java-gnome-hackers] Mixing generated and hand-written classes
Brought to you by:
afcowie
From: Colin W. <wa...@ve...> - 2008-03-21 05:52:36
|
Hi, I just today tried to use java-gnome for the first time, and ran into the issue of the TextBuffer/TextView not being bound. What I didn't understand at first was why that blocked me from instantiating a TextView at all - if we're generating code as I'd heard java-gnome 4.x is, then certainly I'd have access at least to the constructor? Now, I just read through http://java-gnome.sourceforge.net/4.0/doc/design/5a-Architecture.html and I understand what's going on. I think the design has a lot of good ideas, but the crucial bit that strikes me as wrong is this: "2. inheritance hierarchies — who is extending what? Given that any native G entity has two parts on the Java side (the hand written part with the API that we expose, and the machinery that we generate..." If you look at PyGTK, their approach is to have *one* class, with hand-written "overrides". The huge advantage of this approach is it means that you automatically get access to *almost* everything - it may not be as *nice* as you'd like, but it's there. The current java-gnome approach seems to me it is still much like writing manual bindings, just the generated layer is nicer than JNI. Going back to the "Great Owen Thread" from 2005, he said this: "Well, I wouldn't characterize that as my core objection ... my core objection is really the lack of a consistent and predictable mapping between the GObject signature of an object and the Java signature." The way I think of this is that completeness and correctness are more important than being the slickest Java API. The problem is that as soon as you deviate at all from autogeneration, it is an ongoing maintenance and documentation burden. This is another point about PyGTK - they automatically generate their documentation from the existing gtk-doc. Here is a concrete goal - when someone adds a method to the GTK platform, say in the new GIO work, there is 0 work required in java-gnome to expose that method, including the gtk-doc documentation from it. What this means is that I think we need an architecture, like what PyGTK has, for generating a *single* class from two sources: 1) Autogenerated code from .defs file, possibly filtered 2) Hand-written overrides There's a number of ways to do this. Let's take a quick look at a sample PyGTK override: override gtk_text_view_buffer_to_window_coords kwargs static PyObject * _wrap_gtk_text_view_buffer_to_window_coords(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "win", "buffer_x", "buffer_y", NULL }; GtkTextWindowType win; gint buffer_x, buffer_y, window_x = 0, window_y = 0; PyObject *py_win; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oii:GtkTextView.buffer_to_window_coords", kwlist, &py_win, &buffer_x, &buffer_y)) return NULL; if (pyg_enum_get_value(GTK_TYPE_TEXT_WINDOW_TYPE, py_win, (gint *)&win)) return NULL; gtk_text_view_buffer_to_window_coords(GTK_TEXT_VIEW(self->obj), win, buffer_x, buffer_y, &window_x, &window_y); return Py_BuildValue("(ii)", window_x, window_y); } Imagine that we defined an overrides file like this: public class GtkTextView { public int[] bufferToWindowCoords(int x, int y) { int[] retval = new int[2]; int[] windowX; int[] windowY; gtk_text_view_buffer_to_window_coords(pointerOf(self), numOf(win), bufferX, bufferY, windowX, windowY); retval[0] = windowX[0]; retval[1] = windowY[1]; return retval; } } What would happen at the build process is that we'd parse that Java file, detect a method named bufferToWindowCoords which maps to gtk_text_view_buffer_to_window_coords, and remove the autogenerated method. Instead of parsing Java code, we could have a magic comment like // generator override gtk_text_view_buffer_to_window_coords I don't think something like this would be too hard to achieve with the current code generator - if we tweak the class name to match the formerly hand coded version, remove the explicit "self" passing (I don't understand why that's there?), then we could start to merge in the existing hand-coded classes with generated ones, and keep what parts of the hand-coded things that are nicer. Taking a concrete example here - the hand-coded GtkAboutDialog.java API is basically identical to the generated GtkAboutDialog, except for the static method transformation. The javadoc appears to be handcoded to be nicer, but again I think the approach of generating from gtk-doc is the right thing to do, except for explicit overrides. What do you think? |
From: Andrew C. <an...@op...> - 2008-03-21 14:52:32
|
On Fri, 2008-03-21 at 01:52 -0400, Colin Walters wrote: > What would happen at the build process is that we'd parse that Java > file, Trying to inject hand written code into generated code is the defining nightmare that the Enterprise Java world saddled itself with, to their sorrow. We've spent two years steering clear of it; indeed the entire architecture was designed with avoiding that anti-pattern in mind. In any event, the outer edge hand written bindings layer has turned out to be useful in all sorts of ways. Not the least of which is keeping control of the public API being presented. But most of all, that the translation, native, and JNI layers are generated is simply automating the output of the cumbersome machinery necessary to get from Java to C. The poor bastards who wrote the 2.x version of java-gnome did *all* that by hand; we've simply taken the drudgery part where cut and paste errors are made and streamlined it. The API presented to humans by java-gnome 4.0 is lovingly crafted by other humans, which is as it should be. http://www.operationaldynamics.com/reference/talks/PastPresentFuture/img75.html > The javadoc appears to be handcoded > to be nicer, but again I think the approach of generating from gtk-doc > is the right thing to do, No. The structure of java-gnome is not a consequence of nice to haves, it is a consequence of the objectives and design constraints. Human written JavaDoc is not an option; it is the *entire* point. The C API documentation discusses C memory management issues which are meaningless to a Java developer using our library. They refer to deprecated and obsolete functions and methods, mentions which would be impossible to strip out in a systematic. But worst of all, that documentation is reference style, and notorious for being extremely difficult to learn from. We have adopted the tutorial style for our documentation, and that's not a 1:1 transform. See http://java-gnome.sourceforge.net/4.0/doc/design/2b-DesignConstraints.html ++ If you missed them, you might have a reread of http://java-gnome.sourceforge.net/4.0/objectives.php Perhaps also look at http://www.operationaldynamics.com/reference/talks/PastPresentFuture/img65.html if you weren't at my talk at GUADEC. I suppose I should apologize that I haven't updated any of the doc/design/ material in a long while now; it was all written before we initiated the rewrite and in the early days as I had a working prototype in place. Looking back over two years' work, though, I'm pretty pleased that we're still holding closely to our aims, and I'm happy with where things stand now. Ultimately, my mission here is to open up GNOME to an entirely new group of contributors who have not previously been participants in the Open Source movement. That's a different optimization than doing things the way the existing GTK C developers might have done it. That said, it was pretty nice to get so much support last summer at GUADEC and at Boston Summit, and last week from the GTK hackers in Berlin. I make a point of highlighting behaviours that might have been unexpected, and their support has generally been overwhelming. One of the great things about the GNOME community over the last three years has been people's willingness to tolerate our work and to go through our designs and give us feedback. So I appreciate your notes. AfC Toronto -- Andrew Frederick Cowie Operational Dynamics is an operations and engineering consultancy focusing on IT strategy, organizational architecture, systems review, and effective procedures for change management. We actively carry out research and development in these areas on behalf of our clients, and enable successful use of open source in their mission critical enterprises, worldwide. http://www.operationaldynamics.com/ Sydney New York Toronto London |
From: Colin W. <wa...@ve...> - 2008-03-21 15:45:20
|
On Fri, Mar 21, 2008 at 10:52 AM, Andrew Cowie <an...@op...> wrote: > On Fri, 2008-03-21 at 01:52 -0400, Colin Walters wrote: > > What would happen at the build process is that we'd parse that Java > > file, > > Trying to inject hand written code into generated code is the defining > nightmare that the Enterprise Java world saddled itself with, to their > sorrow. We've spent two years steering clear of it; indeed the entire > architecture was designed with avoiding that anti-pattern in mind. What are the concrete issues you see? The slide link doesn't say. And I don't see how this approach is related to "Enterprise Java". What are you talking about? EJB2? > Human written JavaDoc is not an option; it is the *entire* point. Simply put, I think it is more important to have as much coverage as possible, with a completely consistent and predictable mapping. After that base is achieved, then you can go back and add custom documentation at any time. Now admittedly, I come from the C GTK+ world originally, and I've been hacking on the platform for probably 7 years now. So my perspective is biased towards that world; though in the last 2-3 years I've been immersed in the Java world. What is bad about the hand-coding approach for me is that it's *impossible* for me to write a nontrivial application in Java/GNOME as is. For targeting people who are coming entirely from the Java world and are new to the platform, nice JavaDoc is certainly going to help. But look at it this way, the current approach of hand-coding bindings is still broken for them, because although they get a nicer subset of the API, they're still going to run up against coverage and consistency issues. I'm really worried that this project is going back into completely hand-coded, custom mode. Here's an example I found from the archives: http://article.gmane.org/gmane.comp.gnome.bindings.java.devel/1018 There is no metadata in the .defs file telling you that that's a method which emits a signal. So how would you do something like that? In the current architecture, you'd hand-code it into the class. But then what happens a year from now, when someone adds a new method in GIO like that, and some Java-GNOME contributor forgets about this rule and binds it without the "fire" prefix or whatever? The system becomes inconsistent and confusing to both "platform hackers" and "Java people" alike. > The C API documentation discusses C memory management issues which are meaningless to a Java developer using our library. Most of the methods that discuss memory management are of the form foo_free or the like, which we aren't going to be binding at all. I'm taking a closer look at the PyGTK system now to figure out how their documentation system works. |
From: Vreixo F. L. <met...@ya...> - 2008-03-21 15:58:38
|
--- Colin Walters <wa...@ve...> escreveu: > I don't think something like this would be too hard to achieve with > the current code generator In fact, it is quite easy! Having a direct mapping from Gtk+ to Java is very easy with current code generator, but that way what we would be doing is using in Java an API designed for C!! Do we really want that? Or we prefer a quality API carefully designed for the Java language? With the first option we would have in less than a week bindings for all Gtk+ functions. But would they be a good bindings? I doubt. Only humans, by carefully testing and exploring each of the Gtk+ functions can provide quality Java bindings, both powerful but easy-to-use and easy-to-learn, where things are done in the way a Java developer expects them, and with a good documentation. Seriously, I doubt the Gtk+ documentation is good for Java bindings. (well, in fact I do not doubt, I'm sure it isn't!). Of course, having to hand-coded all our API is much more work, but that is the price we pay for having good bindings. Each hour we waste handcoding good API and docs, is time hundreds of developers won't need to waste learning an ugly, bad documented API. We are not developing an end-user app, but a library many developers will use for writing their apps. Let's do it ok. You may ask, then: why to worry about a code generator? Because this way the ugly and tedious part (the direct mapping, JNI layer, etc) is done automatically!! So we expend our time studying Gtk+ functions and the way they should be mapping in Java, and not writing JNI code!! In fact, thanks to the code generator, I waste less than 1% of my java-gnome work writing code. That is good. I understand that for apps developers it is a pain to wait for the coverage they need. But I really prefer good bindings tomorrow than bad bindings today. And if you really need coverage for a given widget, just request us to implement it!! And contribute, of course! If you use a widget sure you will have good ideas about how it should be implmented in Java! Cheers, Vreixo Abra sua conta no Yahoo! Mail, o único sem limite de espaço para armazenamento! http://br.mail.yahoo.com/ |
From: Andrew C. <an...@op...> - 2008-03-21 16:39:45
|
On Fri, 2008-03-21 at 12:58 -0300, Vreixo Formoso Lopes wrote: > But I really prefer > good bindings tomorrow than bad bindings today. /me cheers! :) AfC Toronto |
From: Colin W. <wa...@ve...> - 2008-03-21 17:43:39
|
On Fri, Mar 21, 2008 at 11:58 AM, Vreixo Formoso Lopes <met...@ya...> wrote: > [...] where things are done > in the way a Java developer expects them, This goal doesn't help me, a "platform hacker". and with a > good documentation. Again, certainly nice but I can do OK since the C API is documented, and as long as you have a decent algorithmic mapping, it's pretty easy to understand what the API will be like to use from Java. > Seriously, I doubt the Gtk+ > documentation is good for Java bindings. (well, in > fact I do not doubt, I'm sure it isn't!). Using the GTK+ docs has worked out quite well for PyGTK+. > I understand that for apps developers it is a pain to > wait for the coverage they need. But I really prefer > good bindings tomorrow than bad bindings today. And if > you really need coverage for a given widget, just > request us to implement it!! Ok, I am in the process of writing a script to prove that the current system is not sustainable. I'll post it soon. |
From: Colin W. <wa...@ve...> - 2008-03-21 21:48:17
|
One other note - I just looked at the gtk-sharp code base, and like PyGTK they use the approach of merging generated and hand-written code as well. Here's an example: http://anonsvn.mono-project.com/source/trunk/gtk-sharp/gtk/TextView.custom Both PyGTK and Gtk# are very successful bindings, and I would argue that this success derives very much from *completeness*. There's no reason the java-gnome bindings can't do just as well. We have most of the pieces. |